everclaw 0.3.7 → 0.3.8

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var li=Object.defineProperty;var ci=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var Be=(o,e)=>()=>(o&&(e=o(o=0)),e);var _r=(o,e)=>{for(var t in e)li(o,t,{get:e[t],enumerable:!0})};import bo from"node:fs";import He from"node:os";import pe from"node:path";import{fileURLToPath as di}from"node:url";function fn(o=He.homedir()){return pe.join(o,it)}function wo(o=He.homedir()){return pe.join(o,it,"workspace")}function So(o=He.homedir()){return pe.join(o,it,"config.json")}function hn(o=He.homedir()){return pe.join(o,it,"logs")}function Mr(o=He.homedir()){return pe.join(o,".config","systemd","user")}function $r(o=He.homedir()){return pe.join(o,"Library","LaunchAgents")}function yn(o=He.homedir()){return pe.join(Mr(o),"everclaw.service")}function bn(o=He.homedir()){return pe.join($r(o),"ai.everclaw.gateway.plist")}function ui(){let o=di(import.meta.url),e=pe.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:pe.resolve(e,"..")}function xo(...o){let e=pe.resolve(ko,...o);if(!bo.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function ze(...o){let e=pe.resolve(ko,...o);return bo.existsSync(e)?e:null}var it,at,vo,ko,le=Be(()=>{"use strict";it=".everclaw",at="~/.everclaw/config.json",vo=pe.join("~",it,"workspace");ko=ui()});import vn from"node:fs";import Ue from"node:path";import Or from"node:os";function Ve(o){return vn.mkdirSync(o,{recursive:!0}),o}function wn(){return Ve(fn(Or.homedir()))}function X(o){let e=o?o.replace(/^~(?=$|[\\/])/,Or.homedir()):wo(Or.homedir());return Ve(Ue.resolve(e))}function Co(o){return o.replace(gi,"_").trim()}function lt(o,e=!1){let t=ze("templates");if(!t)return[];let n=[],r=(i,a)=>{vn.existsSync(a)||(Ve(Ue.dirname(a)),i?vn.copyFileSync(i,a):vn.writeFileSync(a,"","utf8"),n.push(Ue.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(Ue.join(t,i),Ue.join(o,i));if(r(Ue.join(t,"memory","MEMORY.md"),Ue.join(o,"memory","MEMORY.md")),r(null,Ue.join(o,"memory","HISTORY.md")),Ve(Ue.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var gi,Oe=Be(()=>{"use strict";le();gi=/[<>:"/\\|?*]/g});function Io(){let o={};for(let e of Po)e.models.length>0&&(o[e.spec.name]=e.models);return o}function Dr(){return Po.map(o=>o.spec)}var Po,Nr=Be(()=>{"use strict";Po=[{spec:{name:"zai",keywords:["zai"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.z.ai/api/coding/paas/v4"},models:["glm-5-turbo"]},{spec:{name:"openrouter",displayName:"OpenRouter",keywords:["openrouter"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://openrouter.ai/api/v1",detectByKeyPrefix:"sk-or-",detectByBaseKeyword:"openrouter"},models:["anthropic/claude-opus-4-1","anthropic/claude-sonnet-4","openai/gpt-4.1","google/gemini-2.5-pro"]},{spec:{name:"aihubmix",displayName:"AIHubMix",keywords:["aihubmix"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://aihubmix.com/v1",detectByBaseKeyword:"aihubmix"},models:[]},{spec:{name:"siliconflow",displayName:"SiliconFlow",keywords:["siliconflow"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.siliconflow.cn/v1",detectByBaseKeyword:"siliconflow"},models:["openai/deepseek-ai/DeepSeek-R1"]},{spec:{name:"volcengine",displayName:"VolcEngine",keywords:["volcengine","volces","ark"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://ark.cn-beijing.volces.com/api/v3",detectByBaseKeyword:"volces"},models:["volcengine/deepseek-r1-250120"]},{spec:{name:"anthropic",displayName:"Anthropic",keywords:["anthropic","claude"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["anthropic/claude-opus-4-5","anthropic/claude-sonnet-4"]},{spec:{name:"openai",displayName:"OpenAI",keywords:["openai","gpt"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gpt-5.2","gpt-5.2-pro","gpt-5.3-codex","gpt-5.2-codex","gpt-5.1","gpt-5.1-codex","gpt-5-mini","gpt-5-nano","gpt-4.1","gpt-4.1-mini","gpt-4.1-nano","gpt-4o","gpt-4o-mini"]},{spec:{name:"openai_codex",displayName:"OpenAI Codex",keywords:["openai-codex","codex"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:"https://chatgpt.com/backend-api"},models:[]},{spec:{name:"github_copilot",displayName:"GitHub Copilot",keywords:["github_copilot","copilot"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:""},models:[]},{spec:{name:"deepseek",displayName:"DeepSeek",keywords:["deepseek"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["deepseek/deepseek-chat","deepseek/deepseek-reasoner"]},{spec:{name:"gemini",displayName:"Google Gemini",keywords:["gemini"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gemini/gemini-3-flash-preview","gemini/gemini-2.5-pro","gemini/gemini-2.5-flash"]},{spec:{name:"zhipu",displayName:"Zhipu AI",keywords:["zhipu","glm","zai"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["zai/glm-4.5"]},{spec:{name:"dashscope",displayName:"DashScope",keywords:["qwen","dashscope"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["dashscope/qwen-max"]},{spec:{name:"moonshot",displayName:"Moonshot AI",keywords:["moonshot","kimi"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.moonshot.ai/v1"},models:["moonshot/kimi-k2.5"]},{spec:{name:"minimax",displayName:"MiniMax",keywords:["minimax"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.minimax.io/v1"},models:["minimax/MiniMax-M2.1"]},{spec:{name:"vllm",displayName:"vLLM",keywords:["vllm"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:""},models:["hosted_vllm/llama-3.1-8b-instruct"]},{spec:{name:"groq",displayName:"Groq",keywords:["groq"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["openai/gpt-oss-120b","openai/gpt-oss-20b","meta-llama/llama-4-maverick-17b-128e-instruct","groq/compound","groq/compound-mini"]},{spec:{name:"ollama",displayName:"Ollama",keywords:["ollama"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:"http://localhost:11434/v1"},models:["ollama/llama3.3","ollama/qwen2.5","ollama/deepseek-r1"]}]});function kt(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function Wt(o){return`${xt}${kt(o)}`}function _o(o,e){let t=kt(e.startsWith(xt)?e.slice(xt.length):e);return o.customLlmProviders.find(n=>kt(n.name)===t)??null}function ki(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?_o(o,n):null}function ct(o){return!!o&&o.startsWith(xt)}function Ct(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return _o(o,n);let r=ki(o,t??o.agents.defaults.model);if(r)return r;let s=o.customLlmProviders.filter(i=>i.name.trim()&&i.baseUrl.trim());return s.length===1?s[0]??null:null}function Xe(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Ct(o,t,e);return a?Wt(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=kt(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of Gt){let l=o.providers[a.name];if(s&&kt(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of Gt){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(kt(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of Gt){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Ct(o,t,e);return i?Wt(i.name):null}function Mo(o,e){let t=Xe(o,e);if(t&&ct(t)){let n=Ct(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function kn(o,e){let t=Xe(o,e);if(!t)return null;if(ct(t))return Ct(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=Gt.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function xn(o,e){let t=e??o.agents.defaults.model,n=o.agents.defaults.provider;if(n==="auto"&&!t.includes("/"))return null;let r;if(n==="auto"&&t.includes("/")){let s=t.split("/")[0],i=s.toLowerCase(),a=o.customLlmProviders.find(l=>l.name.toLowerCase()===i);if(a){let l=t.slice(s.length+1).toLowerCase();r=a.models.find(c=>c.id.toLowerCase()===l)}}else if(n.startsWith(xt)){let s=n.slice(xt.length).toLowerCase(),i=o.customLlmProviders.find(a=>a.name.toLowerCase()===s);i&&(r=i.models.find(a=>a.id.toLowerCase()===t.toLowerCase()))}else{let s=o.providers[n];s?.models&&(r=s.models.find(i=>i.id.toLowerCase()===t.toLowerCase()))}return r?.capabilities??null}var Gt,Si,xt,fe,Tt=Be(()=>{"use strict";le();Nr();Gt=Dr(),Si=Object.fromEntries(Dr().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),xt="custom:",fe={agents:{defaults:{workspace:vo,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:Si,customLlmProviders:[],customAcpProviders:[],gateway:{host:"127.0.0.1",port:6767,dashboard:{enabled:!0},heartbeat:{enabled:!0,intervalS:1800}},tools:{web:{search:{apiKey:"",maxResults:5}},exec:{timeout:60,pathAppend:""},restrictToWorkspace:!1,mcpServers:{},chromeSession:{enabled:!1,debugPort:9222,minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},browserRelay:{enabled:!1,authToken:"",extensionPath:""},rtk:{enabled:!0,autoInstall:!0,ultraCompact:!1,version:"latest"}},security:{enabled:!1,auth:{enabled:!1,pinHash:"",sessionTtlS:3600,lockOnIdle:!1,idleTimeoutS:900},toolGuard:{enabled:!1,guardedTools:null,deniedTools:[],rules:[],failOpen:!0},skillScanner:{enabled:!1,scanOnLoad:!1,blockUnsafe:!0,maxFileCount:1e3,maxFileSizeBytes:5242880},inputSanitizer:{enabled:!1,maxInputLength:5e4,stripHtmlTags:!1,blockPromptInjection:!1}}}});import Cn from"node:fs";import xi from"node:path";function Rt(){return So()}function De(){return wn()}function $o(o,e){if(!e||typeof e!="object")return o;let t=Array.isArray(o)?[...o]:{...o};for(let[n,r]of Object.entries(e))r&&typeof r=="object"&&!Array.isArray(r)&&t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]=$o(t[n],r):t[n]=r;return t}function _(o){let e=o??Rt();if(!Cn.existsSync(e))return structuredClone(fe);try{let t=Cn.readFileSync(e,"utf8"),n=JSON.parse(t),r=$o(structuredClone(fe),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=fe.subagents.find(l=>l.id===i);a&&r.subagents.push(structuredClone(a))}return r}catch(t){return console.warn(`Warning: Failed to load config from ${e}: ${String(t)}`),structuredClone(fe)}}function oe(o,e){let t=e??Rt();Cn.mkdirSync(xi.dirname(t),{recursive:!0}),Cn.writeFileSync(t,JSON.stringify(o,null,2),"utf8")}function Oo(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(n=>n.name===t)&&e.push(`Provider '${t}' is not in the provider catalog and no matching customLlmProvider exists`),o.gateway.host!=="127.0.0.1"&&o.gateway.host!=="localhost"&&o.gateway.host!=="::1"&&o.gateway.dashboard?.enabled!==!1&&!o.security?.auth?.enabled&&e.push("Dashboard exposed on non-loopback address without authentication"),o.security?.toolGuard?.enabled&&o.security?.toolGuard?.failOpen&&e.push("Tool guard is fail-open \u2014 consider fail-closed for production"),o.channels?.telegram?.enabled&&!o.channels.telegram.token&&e.push("Telegram channel enabled but no token configured"),o.channels?.discord?.enabled&&!o.channels.discord.token&&e.push("Discord channel enabled but no token configured");for(let[n,r]of Object.entries(o.tools?.mcpServers??{}))!r.command&&!r.url&&e.push(`MCP server '${n}' has neither command nor URL configured`),r.command&&r.url&&e.push(`MCP server '${n}' has both command and URL \u2014 must use one`),r.toolTimeout!==void 0&&(!Number.isFinite(r.toolTimeout)||r.toolTimeout<=0)&&e.push(`MCP server '${n}' has invalid toolTimeout`);return e}var Ne=Be(()=>{"use strict";Tt();le();Oe()});var Ho={};_r(Ho,{LocalProcessIsolationRunner:()=>ye,selectExecutionIsolationPolicy:()=>mt});import{spawn as qo}from"node:child_process";function mt(o){return{...Oi[o]}}var Oi,ye,pt=Be(()=>{"use strict";Oi={"agent-turn":{target:"agent-turn",mode:"in-process",risk:"safe",cleanup:"none",observation:"basic",reason:"Normal agent turns stay in-process unless a later surface explicitly routes them through isolation."},"tool.exec":{target:"tool.exec",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Shell execution already crosses the local OS boundary and needs explicit launch, timeout, output capture, and cleanup semantics."},subagent:{target:"subagent",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Spawned subagents are a high-risk local execution path that later Wave D routing can move onto this process boundary."},"scheduled-job":{target:"scheduled-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Scheduled jobs can run unattended and should share the same local-process isolation contract when routed in later Wave D work."},"background-job":{target:"background-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Long-running background work needs the same local process cleanup and attribution boundary as other risky execution paths."}};ye=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,u=null,g=!1,h=(k,G)=>{let L=typeof k=="string"?k:k.toString("utf8"),N=t-Buffer.byteLength(G);return N<=0?G:G+L.slice(0,N)};s.stdout?.on("data",k=>{a=h(k,a)}),s.stderr?.on("data",k=>{l=h(k,l)});let T=null,v=k=>{c||(c=!0,u=k,g=k==="timeout",this.killChild(s,"SIGTERM"),T=setTimeout(()=>this.killChild(s,"SIGKILL"),250),T.unref?.())},d=()=>v("abort");e.signal?.aborted?d():e.signal?.addEventListener("abort",d,{once:!0});let b=n!=null?setTimeout(()=>v("timeout"),n):null;b?.unref?.();let O=await new Promise(k=>{let G=!1,L=N=>{G||(G=!0,k(N))};s.once("error",N=>{i.current=N,L({code:null,signal:null})}),s.once("close",(N,z)=>L({code:N,signal:z}))});return b&&clearTimeout(b),T&&clearTimeout(T),e.signal?.removeEventListener("abort",d),u==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:O.code,signal:O.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:g?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:O.code,signal:O.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:O.code,signal:O.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:u,errorMessage:i.current.message}:O.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:O.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:O.code,signal:O.signal,failureAttribution:O.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:u,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?qo(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):qo(e.command.file,e.command.args??[],{cwd:e.cwd,env:e.env,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}),spawnError:{current:null}}}catch(t){return t instanceof Error?t:new Error(String(t))}}killChild(e,t){try{if(process.platform!=="win32"&&typeof e.pid=="number"){process.kill(-e.pid,t);return}}catch{}try{e.kill(t)}catch{}}}});var gr={};_r(gr,{McpClientManager:()=>on});import{Client as Oa}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as La}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Da}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as Na}from"@modelcontextprotocol/sdk/client/sse.js";function ls(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var on,sn=Be(()=>{"use strict";on=class{connections=new Map;servers={};updateConfig(e){this.servers=e}async getServerTools(e){return(await this.ensureConnected(e)).tools}async callTool(e,t,n,r){let s=await this.ensureConnected(e),i=(s.timeout||60)*1e3,a=new AbortController,l=setTimeout(()=>a.abort(),i);r?.signal&&r.signal.addEventListener("abort",()=>a.abort(),{once:!0});try{let c=await s.client.callTool({name:t,arguments:n},void 0,{signal:a.signal});return c.isError?`Error: ${Array.isArray(c.content)?c.content.map(g=>g.text??JSON.stringify(g)).join(`
3
- `):String(c.content??"Unknown error")}`:Array.isArray(c.content)?c.content.map(g=>g.type==="text"?g.text:JSON.stringify(g)).filter(Boolean).join(`
4
- `)||"OK":c.content?String(c.content):"OK"}finally{clearTimeout(l)}}async closeAll(){let e=[...this.connections.entries()];this.connections.clear();for(let[,t]of e)try{await(await t).client.close()}catch{}}async closeServer(e){let t=this.connections.get(e);if(t){this.connections.delete(e);try{await(await t).client.close()}catch{}}}ensureConnected(e){let t=this.connections.get(e);return t||(t=this.connectServer(e),this.connections.set(e,t),t.catch(()=>this.connections.delete(e)),t)}async connectServer(e){let t=this.servers[e];if(!t)throw new Error(`MCP server '${e}' is not configured.`);let n=this.createTransport(e,t),r=new Oa({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=ls(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${ls(l.name)}`,description:l.description??l.name,inputSchema:l.inputSchema??{type:"object",properties:{}}}));return{client:r,tools:a,timeout:t.toolTimeout||60}}createTransport(e,t){let n=!!t.command,r=!!t.url;if(n&&!r)return new La({command:t.command,args:t.args??[],env:Object.fromEntries(Object.entries({...process.env,...t.env??{}}).filter(s=>s[1]!=null))});if(r&&!n){let s=new URL(t.url),i=s.protocol;if(i==="http:"||i==="https:"){let a=t.headers??{};try{return new Da(s,{requestInit:{headers:a}})}catch{return new Na(s,{requestInit:{headers:a}})}}throw i==="ws:"||i==="wss:"?new Error(`MCP server '${e}': WebSocket transport (ws/wss) is not yet supported.`):new Error(`MCP server '${e}': unsupported URL protocol '${i}'.`)}throw new Error(`MCP server '${e}': requires either a command or a URL.`)}}});var cn,dn,un=Be(()=>{"use strict";cn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(cn||{}),dn=(u=>(u.COMMAND_INJECTION="COMMAND_INJECTION",u.DATA_EXFILTRATION="DATA_EXFILTRATION",u.PATH_TRAVERSAL="PATH_TRAVERSAL",u.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",u.NETWORK_ABUSE="NETWORK_ABUSE",u.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",u.RESOURCE_ABUSE="RESOURCE_ABUSE",u.PROMPT_INJECTION="PROMPT_INJECTION",u.CODE_EXECUTION="CODE_EXECUTION",u.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",u))(dn||{})});var Rs={};_r(Rs,{ToolGuardEngine:()=>gn});import pl from"node:fs";function fl(){if(kr)return kr;try{let o=ze("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=pl.readFileSync(o,"utf8"),t=JSON.parse(e);return kr=t,t}catch{return[]}}function yl(o){if(o.length===0)return"SAFE";let e=ro.SAFE;for(let t of o){let n=ro[t.severity]??ro.SAFE;n<e&&(e=n)}return hl[e]??"SAFE"}var kr,ro,hl,gn,oo=Be(()=>{"use strict";Ne();un();le();kr=null;ro={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},hl={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};gn=class o{static instance=null;config;guardians=[];mergedRules=[];loadFromDisk;constructor(e){this.loadFromDisk=e===void 0,this.config=e??_(),this.reloadRules()}static getInstance(e){return o.instance||(o.instance=new o(e)),o.instance}static resetInstance(){o.instance=null,kr=null}isDenied(e){return!this.config.security.enabled||!this.config.security.toolGuard.enabled?!1:this.config.security.toolGuard.deniedTools.includes(e)}isGuarded(e){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return!1;let t=this.config.security.toolGuard.guardedTools;return t===null?!0:t.includes(e)}guard(e,t){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return null;if(this.isDenied(e)){let g={id:`denied-${e}-${Date.now()}`,ruleId:"denied-tools-list",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Tool '${e}' is denied`,description:`The tool '${e}' is in the denied tools list and cannot be executed.`,toolName:e,guardian:"ToolGuardEngine"};return{toolName:e,params:t,findings:[g],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!1,maxSeverity:"CRITICAL"}}if(!this.isGuarded(e))return{toolName:e,params:t,findings:[],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!0,maxSeverity:"SAFE"};let n=performance.now(),r=[],s=[],i=[],a=this.config.security.toolGuard.failOpen!==!1;for(let g of this.guardians)try{let h=g.guard({toolName:e,params:t});h.length>0&&r.push(...h),s.push(g.name)}catch(h){if(i.push(g.name),console.error(`ToolGuardEngine: guardian '${g.name}' failed: ${String(h)}`),!a){let T={id:`guardian-error-${g.name}-${Date.now()}`,ruleId:"guardian-error",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Guardian '${g.name}' failed`,description:`Security guardian encountered an error and failOpen is disabled: ${String(h)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(T)}}let l=performance.now()-n,c=yl(r);return{toolName:e,params:t,findings:r,guardDurationMs:l,guardiansUsed:s,guardiansFailed:i,isSafe:c!=="CRITICAL"&&c!=="HIGH",maxSeverity:c}}registerGuardian(e){this.guardians.some(t=>t.name===e.name)||this.guardians.push(e)}unregisterGuardian(e){this.guardians=this.guardians.filter(t=>t.name!==e)}getRegisteredGuardians(){return this.guardians.map(e=>e.name)}getRules(){return this.mergedRules}getConfig(){return this.config}reloadRules(){this.loadFromDisk&&(this.config=_());let e=fl(),t=this.config.security.toolGuard.rules,n=new Set(e.map(l=>l.id)),r=t.filter(l=>n.has(l.id)),s=new Set(r.map(l=>l.id)),i=e.filter(l=>!s.has(l.id)),a=t.filter(l=>!n.has(l.id));this.mergedRules=[...i,...r,...a]}setConfig(e){this.config=e}}});import"dotenv/config";import Ro from"node:path";import{createRequire as mi}from"node:module";function ie(){return new Date().toISOString()}Oe();var pi=mi(import.meta.url),Sn=null;function fi(){return Sn||(Sn=pi("node:sqlite").DatabaseSync,Sn)}function Ao(o,e){o.exec("BEGIN IMMEDIATE");try{let t=e();return o.exec("COMMIT"),t}catch(t){try{o.exec("ROLLBACK")}catch{}throw t}}var To=[{version:1,name:"create-operational-state-tables",sql:`
2
+ var ui=Object.defineProperty;var gi=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+o+'" is not supported')});var Be=(o,e)=>()=>(o&&(e=o(o=0)),e);var Mr=(o,e)=>{for(var t in e)ui(o,t,{get:e[t],enumerable:!0})};import vo from"node:fs";import He from"node:os";import he from"node:path";import{fileURLToPath as mi}from"node:url";function fn(o=He.homedir()){return he.join(o,it)}function So(o=He.homedir()){return he.join(o,it,"workspace")}function ko(o=He.homedir()){return he.join(o,it,"config.json")}function hn(o=He.homedir()){return he.join(o,it,"logs")}function $r(o=He.homedir()){return he.join(o,".config","systemd","user")}function Or(o=He.homedir()){return he.join(o,"Library","LaunchAgents")}function yn(o=He.homedir()){return he.join($r(o),"everclaw.service")}function bn(o=He.homedir()){return he.join(Or(o),"ai.everclaw.gateway.plist")}function pi(){let o=mi(import.meta.url),e=he.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:he.resolve(e,"..")}function xo(...o){let e=he.resolve(Co,...o);if(!vo.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function ze(...o){let e=he.resolve(Co,...o);return vo.existsSync(e)?e:null}var it,at,wo,Co,ce=Be(()=>{"use strict";it=".everclaw",at="~/.everclaw/config.json",wo=he.join("~",it,"workspace");Co=pi()});import vn from"node:fs";import Ge from"node:path";import Lr from"node:os";function Ve(o){return vn.mkdirSync(o,{recursive:!0}),o}function wn(){return Ve(fn(Lr.homedir()))}function V(o){let e=o?o.replace(/^~(?=$|[\\/])/,Lr.homedir()):So(Lr.homedir());return Ve(Ge.resolve(e))}function To(o){return o.replace(fi,"_").trim()}function lt(o,e=!1){let t=ze("templates");if(!t)return[];let n=[],r=(i,a)=>{vn.existsSync(a)||(Ve(Ge.dirname(a)),i?vn.copyFileSync(i,a):vn.writeFileSync(a,"","utf8"),n.push(Ge.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(Ge.join(t,i),Ge.join(o,i));if(r(Ge.join(t,"memory","MEMORY.md"),Ge.join(o,"memory","MEMORY.md")),r(null,Ge.join(o,"memory","HISTORY.md")),Ve(Ge.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var fi,Le=Be(()=>{"use strict";ce();fi=/[<>:"/\\|?*]/g});function _o(){let o={};for(let e of Io)e.models.length>0&&(o[e.spec.name]=e.models);return o}function Nr(){return Io.map(o=>o.spec)}var Io,jr=Be(()=>{"use strict";Io=[{spec:{name:"zai",keywords:["zai"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.z.ai/api/coding/paas/v4"},models:["glm-5-turbo"]},{spec:{name:"openrouter",displayName:"OpenRouter",keywords:["openrouter"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://openrouter.ai/api/v1",detectByKeyPrefix:"sk-or-",detectByBaseKeyword:"openrouter"},models:["anthropic/claude-opus-4-1","anthropic/claude-sonnet-4","openai/gpt-4.1","google/gemini-2.5-pro"]},{spec:{name:"aihubmix",displayName:"AIHubMix",keywords:["aihubmix"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://aihubmix.com/v1",detectByBaseKeyword:"aihubmix"},models:[]},{spec:{name:"siliconflow",displayName:"SiliconFlow",keywords:["siliconflow"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.siliconflow.cn/v1",detectByBaseKeyword:"siliconflow"},models:["openai/deepseek-ai/DeepSeek-R1"]},{spec:{name:"volcengine",displayName:"VolcEngine",keywords:["volcengine","volces","ark"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://ark.cn-beijing.volces.com/api/v3",detectByBaseKeyword:"volces"},models:["volcengine/deepseek-r1-250120"]},{spec:{name:"anthropic",displayName:"Anthropic",keywords:["anthropic","claude"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["anthropic/claude-opus-4-5","anthropic/claude-sonnet-4"]},{spec:{name:"openai",displayName:"OpenAI",keywords:["openai","gpt"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gpt-5.2","gpt-5.2-pro","gpt-5.3-codex","gpt-5.2-codex","gpt-5.1","gpt-5.1-codex","gpt-5-mini","gpt-5-nano","gpt-4.1","gpt-4.1-mini","gpt-4.1-nano","gpt-4o","gpt-4o-mini"]},{spec:{name:"openai_codex",displayName:"OpenAI Codex",keywords:["openai-codex","codex"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:"https://chatgpt.com/backend-api"},models:[]},{spec:{name:"github_copilot",displayName:"GitHub Copilot",keywords:["github_copilot","copilot"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:""},models:[]},{spec:{name:"deepseek",displayName:"DeepSeek",keywords:["deepseek"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["deepseek/deepseek-chat","deepseek/deepseek-reasoner"]},{spec:{name:"gemini",displayName:"Google Gemini",keywords:["gemini"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gemini/gemini-3-flash-preview","gemini/gemini-2.5-pro","gemini/gemini-2.5-flash"]},{spec:{name:"zhipu",displayName:"Zhipu AI",keywords:["zhipu","glm","zai"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["zai/glm-4.5"]},{spec:{name:"dashscope",displayName:"DashScope",keywords:["qwen","dashscope"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["dashscope/qwen-max"]},{spec:{name:"moonshot",displayName:"Moonshot AI",keywords:["moonshot","kimi"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.moonshot.ai/v1"},models:["moonshot/kimi-k2.5"]},{spec:{name:"minimax",displayName:"MiniMax",keywords:["minimax"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.minimax.io/v1"},models:["minimax/MiniMax-M2.1"]},{spec:{name:"vllm",displayName:"vLLM",keywords:["vllm"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:""},models:["hosted_vllm/llama-3.1-8b-instruct"]},{spec:{name:"groq",displayName:"Groq",keywords:["groq"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["openai/gpt-oss-120b","openai/gpt-oss-20b","meta-llama/llama-4-maverick-17b-128e-instruct","groq/compound","groq/compound-mini"]},{spec:{name:"ollama",displayName:"Ollama",keywords:["ollama"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:"http://localhost:11434/v1"},models:["ollama/llama3.3","ollama/qwen2.5","ollama/deepseek-r1"]}]});function Ct(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function Wt(o){return`${xt}${Ct(o)}`}function Mo(o,e){let t=Ct(e.startsWith(xt)?e.slice(xt.length):e);return o.customLlmProviders.find(n=>Ct(n.name)===t)??null}function Ti(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?Mo(o,n):null}function ct(o){return!!o&&o.startsWith(xt)}function Tt(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return Mo(o,n);let r=Ti(o,t??o.agents.defaults.model);if(r)return r;let s=o.customLlmProviders.filter(i=>i.name.trim()&&i.baseUrl.trim());return s.length===1?s[0]??null:null}function Xe(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Tt(o,t,e);return a?Wt(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=Ct(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of Ut){let l=o.providers[a.name];if(s&&Ct(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of Ut){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(Ct(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of Ut){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Tt(o,t,e);return i?Wt(i.name):null}function $o(o,e){let t=Xe(o,e);if(t&&ct(t)){let n=Tt(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function kn(o,e){let t=Xe(o,e);if(!t)return null;if(ct(t))return Tt(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=Ut.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function Cn(o,e){let t=e??o.agents.defaults.model,n=o.agents.defaults.provider;if(n==="auto"&&!t.includes("/"))return null;let r;if(n==="auto"&&t.includes("/")){let s=t.split("/")[0],i=s.toLowerCase(),a=o.customLlmProviders.find(l=>l.name.toLowerCase()===i);if(a){let l=t.slice(s.length+1).toLowerCase();r=a.models.find(c=>c.id.toLowerCase()===l)}}else if(n.startsWith(xt)){let s=n.slice(xt.length).toLowerCase(),i=o.customLlmProviders.find(a=>a.name.toLowerCase()===s);i&&(r=i.models.find(a=>a.id.toLowerCase()===t.toLowerCase()))}else{let s=o.providers[n];s?.models&&(r=s.models.find(i=>i.id.toLowerCase()===t.toLowerCase()))}return r?.capabilities??null}var Ut,xi,xt,de,Rt=Be(()=>{"use strict";ce();jr();Ut=Nr(),xi=Object.fromEntries(Nr().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),xt="custom:",de={agents:{defaults:{workspace:wo,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3},groups:{requireMention:!0,allowedGroupIds:null},commands:{native:!0,custom:[]}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:xi,customLlmProviders:[],customAcpProviders:[],gateway:{host:"127.0.0.1",port:6767,dashboard:{enabled:!0},heartbeat:{enabled:!0,intervalS:1800}},tools:{web:{search:{apiKey:"",maxResults:5}},exec:{timeout:60,pathAppend:""},restrictToWorkspace:!1,mcpServers:{},chromeSession:{enabled:!1,debugPort:9222,minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},browserRelay:{enabled:!1,authToken:"",extensionPath:""},rtk:{enabled:!0,autoInstall:!0,ultraCompact:!1,version:"latest"}},security:{enabled:!1,auth:{enabled:!1,pinHash:"",sessionTtlS:3600,lockOnIdle:!1,idleTimeoutS:900},toolGuard:{enabled:!1,guardedTools:null,deniedTools:[],rules:[],failOpen:!0},skillScanner:{enabled:!1,scanOnLoad:!1,blockUnsafe:!0,maxFileCount:1e3,maxFileSizeBytes:5242880},inputSanitizer:{enabled:!1,maxInputLength:5e4,stripHtmlTags:!1,blockPromptInjection:!1}}}});import xn from"node:fs";import Ri from"node:path";function dt(){return ko()}function Ne(){return wn()}function Oo(o,e){if(!e||typeof e!="object")return o;let t=Array.isArray(o)?[...o]:{...o};for(let[n,r]of Object.entries(e))r&&typeof r=="object"&&!Array.isArray(r)&&t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]=Oo(t[n],r):t[n]=r;return t}function Tn(o,e){if(o===e)return!0;if(o===null||e===null)return o===e;if(typeof o!="object"||typeof e!="object"||Array.isArray(o)!==Array.isArray(e))return!1;if(Array.isArray(o)&&Array.isArray(e))return o.length!==e.length?!1:o.every((i,a)=>Tn(i,e[a]));let t=o,n=e,r=Object.keys(t).sort(),s=Object.keys(n).sort();return r.length!==s.length?!1:r.every((i,a)=>i===s[a]&&Tn(t[i],n[i]))}function Ai(o){for(let e of Lo)if(e.startsWith(o+"."))return!0;return!1}function Ei(o){return o.apiKey===""&&o.apiBase===null&&o.extraHeaders===null&&(o.models===void 0||o.models.length===0)}function Do(o,e,t=""){if(Lo.has(t))return o;if(o===null||e===null||typeof o!="object"||typeof e!="object")return o===e?void 0:o;if(Array.isArray(o)!==Array.isArray(e))return o;if(Array.isArray(o)&&Array.isArray(e))return Tn(o,e)?void 0:o;if(t==="providers"){let a=o,l=e,c={},d=!1;for(let[p,h]of Object.entries(a)){let w=l[p];w?Tn(h,w)||(c[p]=h,d=!0):Ei(h)||(c[p]=h,d=!0)}return d?c:void 0}let n=o,r=e,s={},i=!1;for(let a of Object.keys(n)){let l=t?`${t}.${a}`:a,c=n[a],d=r[a];if(d===void 0)s[a]=c,i=!0;else{let p=Do(c,d,l);p!==void 0?(s[a]=p,i=!0):Ai(l)&&(s[a]=c,i=!0)}}return i?s:void 0}function Pi(o){return Do(o,de)??{}}function M(o){let e=o??dt();if(!xn.existsSync(e))return structuredClone(de);try{let t=xn.readFileSync(e,"utf8"),n=JSON.parse(t),r=Oo(structuredClone(de),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=de.subagents.find(l=>l.id===i);a&&r.subagents.push(structuredClone(a))}return r}catch(t){return console.warn(`Warning: Failed to load config from ${e}: ${String(t)}`),structuredClone(de)}}function oe(o,e){let t=e??dt();xn.mkdirSync(Ri.dirname(t),{recursive:!0});let n=Pi(o);xn.writeFileSync(t,JSON.stringify(n,null,2),"utf8")}function No(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(n=>n.name===t)&&e.push(`Provider '${t}' is not in the provider catalog and no matching customLlmProvider exists`),o.gateway.host!=="127.0.0.1"&&o.gateway.host!=="localhost"&&o.gateway.host!=="::1"&&o.gateway.dashboard?.enabled!==!1&&!o.security?.auth?.enabled&&e.push("Dashboard exposed on non-loopback address without authentication"),o.security?.toolGuard?.enabled&&o.security?.toolGuard?.failOpen&&e.push("Tool guard is fail-open \u2014 consider fail-closed for production"),o.channels?.telegram?.enabled&&!o.channels.telegram.token&&e.push("Telegram channel enabled but no token configured"),o.channels?.discord?.enabled&&!o.channels.discord.token&&e.push("Discord channel enabled but no token configured");for(let[n,r]of Object.entries(o.tools?.mcpServers??{}))!r.command&&!r.url&&e.push(`MCP server '${n}' has neither command nor URL configured`),r.command&&r.url&&e.push(`MCP server '${n}' has both command and URL \u2014 must use one`),r.toolTimeout!==void 0&&(!Number.isFinite(r.toolTimeout)||r.toolTimeout<=0)&&e.push(`MCP server '${n}' has invalid toolTimeout`);return e}var Lo,je=Be(()=>{"use strict";Rt();ce();Le();Lo=new Set(["agents.defaults.model","agents.defaults.provider","gateway.port"])});var Xo={};Mr(Xo,{LocalProcessIsolationRunner:()=>be,selectExecutionIsolationPolicy:()=>pt});import{spawn as Vo}from"node:child_process";function pt(o){return{...Bi[o]}}var Bi,be,ft=Be(()=>{"use strict";Bi={"agent-turn":{target:"agent-turn",mode:"in-process",risk:"safe",cleanup:"none",observation:"basic",reason:"Normal agent turns stay in-process unless a later surface explicitly routes them through isolation."},"tool.exec":{target:"tool.exec",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Shell execution already crosses the local OS boundary and needs explicit launch, timeout, output capture, and cleanup semantics."},subagent:{target:"subagent",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Spawned subagents are a high-risk local execution path that later Wave D routing can move onto this process boundary."},"scheduled-job":{target:"scheduled-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Scheduled jobs can run unattended and should share the same local-process isolation contract when routed in later Wave D work."},"background-job":{target:"background-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Long-running background work needs the same local process cleanup and attribution boundary as other risky execution paths."}};be=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,d=null,p=!1,h=(C,N)=>{let q=typeof C=="string"?C:C.toString("utf8"),I=t-Buffer.byteLength(N);return I<=0?N:N+q.slice(0,I)};s.stdout?.on("data",C=>{a=h(C,a)}),s.stderr?.on("data",C=>{l=h(C,l)});let w=null,v=C=>{c||(c=!0,d=C,p=C==="timeout",this.killChild(s,"SIGTERM"),w=setTimeout(()=>this.killChild(s,"SIGKILL"),250),w.unref?.())},u=()=>v("abort");e.signal?.aborted?u():e.signal?.addEventListener("abort",u,{once:!0});let b=n!=null?setTimeout(()=>v("timeout"),n):null;b?.unref?.();let P=await new Promise(C=>{let N=!1,q=I=>{N||(N=!0,C(I))};s.once("error",I=>{i.current=I,q({code:null,signal:null})}),s.once("close",(I,J)=>q({code:I,signal:J}))});return b&&clearTimeout(b),w&&clearTimeout(w),e.signal?.removeEventListener("abort",u),d==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:P.code,signal:P.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:P.code,signal:P.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:P.code,signal:P.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:d,errorMessage:i.current.message}:P.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:P.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:P.code,signal:P.signal,failureAttribution:P.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:d,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?Vo(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):Vo(e.command.file,e.command.args??[],{cwd:e.cwd,env:e.env,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}),spawnError:{current:null}}}catch(t){return t instanceof Error?t:new Error(String(t))}}killChild(e,t){try{if(process.platform!=="win32"&&typeof e.pid=="number"){process.kill(-e.pid,t);return}}catch{}try{e.kill(t)}catch{}}}});var mr={};Mr(mr,{McpClientManager:()=>on});import{Client as Ba}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as Ga}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Ua}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as Wa}from"@modelcontextprotocol/sdk/client/sse.js";function us(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var on,sn=Be(()=>{"use strict";on=class{connections=new Map;servers={};updateConfig(e){this.servers=e}async getServerTools(e){return(await this.ensureConnected(e)).tools}async callTool(e,t,n,r){let s=await this.ensureConnected(e),i=(s.timeout||60)*1e3,a=new AbortController,l=setTimeout(()=>a.abort(),i);r?.signal&&r.signal.addEventListener("abort",()=>a.abort(),{once:!0});try{let c=await s.client.callTool({name:t,arguments:n},void 0,{signal:a.signal});return c.isError?`Error: ${Array.isArray(c.content)?c.content.map(p=>p.text??JSON.stringify(p)).join(`
3
+ `):String(c.content??"Unknown error")}`:Array.isArray(c.content)?c.content.map(p=>p.type==="text"?p.text:JSON.stringify(p)).filter(Boolean).join(`
4
+ `)||"OK":c.content?String(c.content):"OK"}finally{clearTimeout(l)}}async closeAll(){let e=[...this.connections.entries()];this.connections.clear();for(let[,t]of e)try{await(await t).client.close()}catch{}}async closeServer(e){let t=this.connections.get(e);if(t){this.connections.delete(e);try{await(await t).client.close()}catch{}}}ensureConnected(e){let t=this.connections.get(e);return t||(t=this.connectServer(e),this.connections.set(e,t),t.catch(()=>this.connections.delete(e)),t)}async connectServer(e){let t=this.servers[e];if(!t)throw new Error(`MCP server '${e}' is not configured.`);let n=this.createTransport(e,t),r=new Ba({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=us(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${us(l.name)}`,description:l.description??l.name,inputSchema:l.inputSchema??{type:"object",properties:{}}}));return{client:r,tools:a,timeout:t.toolTimeout||60}}createTransport(e,t){let n=!!t.command,r=!!t.url;if(n&&!r)return new Ga({command:t.command,args:t.args??[],env:Object.fromEntries(Object.entries({...process.env,...t.env??{}}).filter(s=>s[1]!=null))});if(r&&!n){let s=new URL(t.url),i=s.protocol;if(i==="http:"||i==="https:"){let a=t.headers??{};try{return new Ua(s,{requestInit:{headers:a}})}catch{return new Wa(s,{requestInit:{headers:a}})}}throw i==="ws:"||i==="wss:"?new Error(`MCP server '${e}': WebSocket transport (ws/wss) is not yet supported.`):new Error(`MCP server '${e}': unsupported URL protocol '${i}'.`)}throw new Error(`MCP server '${e}': requires either a command or a URL.`)}}});var cn,dn,un=Be(()=>{"use strict";cn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(cn||{}),dn=(d=>(d.COMMAND_INJECTION="COMMAND_INJECTION",d.DATA_EXFILTRATION="DATA_EXFILTRATION",d.PATH_TRAVERSAL="PATH_TRAVERSAL",d.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",d.NETWORK_ABUSE="NETWORK_ABUSE",d.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",d.RESOURCE_ABUSE="RESOURCE_ABUSE",d.PROMPT_INJECTION="PROMPT_INJECTION",d.CODE_EXECUTION="CODE_EXECUTION",d.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",d))(dn||{})});var Ps={};Mr(Ps,{ToolGuardEngine:()=>gn});import Sl from"node:fs";function kl(){if(Cr)return Cr;try{let o=ze("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Sl.readFileSync(o,"utf8"),t=JSON.parse(e);return Cr=t,t}catch{return[]}}function xl(o){if(o.length===0)return"SAFE";let e=oo.SAFE;for(let t of o){let n=oo[t.severity]??oo.SAFE;n<e&&(e=n)}return Cl[e]??"SAFE"}var Cr,oo,Cl,gn,so=Be(()=>{"use strict";je();un();ce();Cr=null;oo={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Cl={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};gn=class o{static instance=null;config;guardians=[];mergedRules=[];loadFromDisk;constructor(e){this.loadFromDisk=e===void 0,this.config=e??M(),this.reloadRules()}static getInstance(e){return o.instance||(o.instance=new o(e)),o.instance}static resetInstance(){o.instance=null,Cr=null}isDenied(e){return!this.config.security.enabled||!this.config.security.toolGuard.enabled?!1:this.config.security.toolGuard.deniedTools.includes(e)}isGuarded(e){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return!1;let t=this.config.security.toolGuard.guardedTools;return t===null?!0:t.includes(e)}guard(e,t){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return null;if(this.isDenied(e)){let p={id:`denied-${e}-${Date.now()}`,ruleId:"denied-tools-list",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Tool '${e}' is denied`,description:`The tool '${e}' is in the denied tools list and cannot be executed.`,toolName:e,guardian:"ToolGuardEngine"};return{toolName:e,params:t,findings:[p],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!1,maxSeverity:"CRITICAL"}}if(!this.isGuarded(e))return{toolName:e,params:t,findings:[],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!0,maxSeverity:"SAFE"};let n=performance.now(),r=[],s=[],i=[],a=this.config.security.toolGuard.failOpen!==!1;for(let p of this.guardians)try{let h=p.guard({toolName:e,params:t});h.length>0&&r.push(...h),s.push(p.name)}catch(h){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(h)}`),!a){let w={id:`guardian-error-${p.name}-${Date.now()}`,ruleId:"guardian-error",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Guardian '${p.name}' failed`,description:`Security guardian encountered an error and failOpen is disabled: ${String(h)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(w)}}let l=performance.now()-n,c=xl(r);return{toolName:e,params:t,findings:r,guardDurationMs:l,guardiansUsed:s,guardiansFailed:i,isSafe:c!=="CRITICAL"&&c!=="HIGH",maxSeverity:c}}registerGuardian(e){this.guardians.some(t=>t.name===e.name)||this.guardians.push(e)}unregisterGuardian(e){this.guardians=this.guardians.filter(t=>t.name!==e)}getRegisteredGuardians(){return this.guardians.map(e=>e.name)}getRules(){return this.mergedRules}getConfig(){return this.config}reloadRules(){this.loadFromDisk&&(this.config=M());let e=kl(),t=this.config.security.toolGuard.rules,n=new Set(e.map(l=>l.id)),r=t.filter(l=>n.has(l.id)),s=new Set(r.map(l=>l.id)),i=e.filter(l=>!s.has(l.id)),a=t.filter(l=>!n.has(l.id));this.mergedRules=[...i,...r,...a]}setConfig(e){this.config=e}}});import"dotenv/config";import Ao from"node:path";import{createRequire as hi}from"node:module";function ie(){return new Date().toISOString()}Le();var yi=hi(import.meta.url),Sn=null;function bi(){return Sn||(Sn=yi("node:sqlite").DatabaseSync,Sn)}function Eo(o,e){o.exec("BEGIN IMMEDIATE");try{let t=e();return o.exec("COMMIT"),t}catch(t){try{o.exec("ROLLBACK")}catch{}throw t}}var Ro=[{version:1,name:"create-operational-state-tables",sql:`
5
5
  CREATE TABLE IF NOT EXISTS session_metadata (
6
6
  workspace TEXT NOT NULL,
7
7
  session_key TEXT NOT NULL,
@@ -68,36 +68,36 @@ var li=Object.defineProperty;var ci=(o=>typeof require<"u"?require:typeof Proxy<
68
68
 
69
69
  CREATE INDEX IF NOT EXISTS idx_inbox_deliveries_workspace_cleared_at
70
70
  ON inbox_deliveries (workspace, cleared_at, delivered_at DESC);
71
- `}];function hi(o=wn()){return Ro.join(o,"runtime","operations.sqlite")}var Lr=class{constructor(e,t){this.db=e;this.dbPath=t}kind="sqlite";close(){this.db.close()}exec(e){this.db.exec(e)}prepare(e){return this.db.prepare(e)}transaction(e){return Ao(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
71
+ `}];function vi(o=wn()){return Ao.join(o,"runtime","operations.sqlite")}var Dr=class{constructor(e,t){this.db=e;this.dbPath=t}kind="sqlite";close(){this.db.close()}exec(e){this.db.exec(e)}prepare(e){return this.db.prepare(e)}transaction(e){return Eo(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
72
72
  FROM schema_migrations
73
- ORDER BY version`).all().map(t=>({version:Number(t.version),name:String(t.name),applied_at:String(t.applied_at)}))}getCurrentVersion(){return this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations").get().version}};function yi(o){o.exec(`
73
+ ORDER BY version`).all().map(t=>({version:Number(t.version),name:String(t.name),applied_at:String(t.applied_at)}))}getCurrentVersion(){return this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations").get().version}};function wi(o){o.exec(`
74
74
  CREATE TABLE IF NOT EXISTS schema_migrations (
75
75
  version INTEGER PRIMARY KEY,
76
76
  name TEXT NOT NULL,
77
77
  applied_at TEXT NOT NULL
78
78
  );
79
- `)}function Le(o={}){let e=o.dbPath??hi(o.dataDir);Ve(Ro.dirname(e));let t=fi(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),yi(n);let r=To.at(-1)?.version??0,s=n.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations").get().version;if(s>r)throw n.close(),new Error(`Operational storage schema version ${s} is newer than supported version ${r}.`);let i=new Set(n.prepare("SELECT version FROM schema_migrations ORDER BY version").all().map(a=>a.version));for(let a of To)i.has(a.version)||Ao(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,ie())});return new Lr(n,e)}var bi=new Set(["agent","gateway"]);function vi(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function wi(o){let e=vi(o);return!!e&&bi.has(e)}function Eo(o,e={}){if(!wi(o))return!1;let t=e.openStorage??Le,n=e.onError??(s=>console.error(s)),r=e.exit??(s=>process.exit(s));try{return t().close(),!0}catch(s){let i=s instanceof Error?s.message:String(s);return n(`Failed to initialize operational storage: ${i}`),r(1),!1}}Ne();Tt();import ge from"node:fs";import ti from"node:readline/promises";import{stdin as ni,stdout as ri}from"node:process";import{Command as _c,Option as yo}from"commander";import Fe from"prompts";import S from"chalk";function Ci(o){let e={};if(o.EVERCLAW_PROVIDER&&(e.provider=o.EVERCLAW_PROVIDER),o.EVERCLAW_MODEL&&(e.model=o.EVERCLAW_MODEL),o.EVERCLAW_API_KEY&&(e.apiKey=o.EVERCLAW_API_KEY),o.EVERCLAW_API_BASE&&(e.apiBase=o.EVERCLAW_API_BASE),o.EVERCLAW_GATEWAY_HOST&&(e.gatewayHost=o.EVERCLAW_GATEWAY_HOST),o.EVERCLAW_GATEWAY_PORT){let t=Number(o.EVERCLAW_GATEWAY_PORT);Number.isNaN(t)||(e.gatewayPort=t)}if(o.EVERCLAW_DASHBOARD!==void 0){let t=o.EVERCLAW_DASHBOARD.toLowerCase();(t==="true"||t==="false")&&(e.dashboardEnabled=t==="true")}return e}function Lo(o,e){let t=structuredClone(o);if(e.provider!==void 0&&(t.agents.defaults.provider=e.provider),e.model!==void 0&&(t.agents.defaults.model=e.model),e.gatewayHost!==void 0&&(t.gateway.host=e.gatewayHost),e.gatewayPort!==void 0&&(t.gateway.port=e.gatewayPort),e.dashboardEnabled!==void 0){let n=t.gateway;n.dashboard&&typeof n.dashboard=="object"&&(n.dashboard.enabled=e.dashboardEnabled)}if(e.apiKey!==void 0||e.apiBase!==void 0){let n=t.agents.defaults.provider;n&&n!=="auto"&&(t.providers[n]||(t.providers[n]={apiKey:"",apiBase:null,extraHeaders:null}),e.apiKey!==void 0&&(t.providers[n].apiKey=e.apiKey),e.apiBase!==void 0&&(t.providers[n].apiBase=e.apiBase))}return t}function Kt(o,e,t){let n=Ci(e),r=Lo(o,n);return t?Lo(r,t):r}le();le();import At from"node:fs";import Do from"node:path";import Ti from"node:os";var Ri="gateway.pid";function jr(){return Do.join(Ti.homedir(),it,Ri)}function Fr(o){let e=jr();At.mkdirSync(Do.dirname(e),{recursive:!0}),At.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Ee(){let o=jr();if(!At.existsSync(o))return null;try{let e=At.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function Pe(o){let e=jr();try{if(!At.existsSync(e))return;if(o!==void 0){let t=Ee();if(t&&t.pid!==o)return}At.unlinkSync(e)}catch{}}function Ae(o){try{return process.kill(o,0),!0}catch{return!1}}async function Br(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Ae(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Ae(o)}function dt(o){let e=new Date(o).getTime();if(Number.isNaN(e))return"unknown";let t=Date.now()-e;if(t<0)return"unknown";let n=Math.floor(t/1e3),r=Math.floor(n/86400),s=Math.floor(n%86400/3600),i=Math.floor(n%3600/60),a=[];return r>0&&a.push(`${r}d`),s>0&&a.push(`${s}h`),a.push(`${i}m`),a.join(" ")}Oe();var Jt=class{items=[];waiters=[];push(e){let t=this.waiters.shift();t?t(e):this.items.push(e)}async pop(){let e=this.items.shift();return e!==void 0?e:new Promise(t=>this.waiters.push(t))}size(){return this.items.length}};var ut=class{inbound=new Jt;outbound=new Jt;async publishInbound(e){this.inbound.push(e)}async consumeInbound(){return this.inbound.pop()}async publishOutbound(e){this.outbound.push(e)}async consumeOutbound(){return this.outbound.pop()}get inboundSize(){return this.inbound.size()}get outboundSize(){return this.outbound.size()}};import cs from"node:path";import No from"node:fs";import An from"node:path";import jo from"node:os";import qt from"node:fs";import Tn from"node:path";var Ai=[{type:"function",function:{name:"save_memory",description:"Save the memory consolidation result to persistent storage.",parameters:{type:"object",properties:{history_entry:{type:"string"},memory_update:{type:"string"}},required:["history_entry","memory_update"]}}}],Ht=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Tn.join(e,"memory");this.memoryDir=t?Tn.join(n,t):n,qt.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Tn.join(this.memoryDir,"MEMORY.md"),this.historyFile=Tn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return qt.existsSync(this.memoryFile)?qt.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){qt.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){qt.appendFileSync(this.historyFile,`${e.trim()}
79
+ `)}function De(o={}){let e=o.dbPath??vi(o.dataDir);Ve(Ao.dirname(e));let t=bi(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),wi(n);let r=Ro.at(-1)?.version??0,s=n.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations").get().version;if(s>r)throw n.close(),new Error(`Operational storage schema version ${s} is newer than supported version ${r}.`);let i=new Set(n.prepare("SELECT version FROM schema_migrations ORDER BY version").all().map(a=>a.version));for(let a of Ro)i.has(a.version)||Eo(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,ie())});return new Dr(n,e)}var Si=new Set(["agent","gateway"]);function ki(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function Ci(o){let e=ki(o);return!!e&&Si.has(e)}function Po(o,e={}){if(!Ci(o))return!1;let t=e.openStorage??De,n=e.onError??(s=>console.error(s)),r=e.exit??(s=>process.exit(s));try{return t().close(),!0}catch(s){let i=s instanceof Error?s.message:String(s);return n(`Failed to initialize operational storage: ${i}`),r(1),!1}}je();Rt();import le from"node:fs";import oi from"node:readline/promises";import{stdin as si,stdout as ii}from"node:process";import{Command as jc,Option as bo}from"commander";import pe from"prompts";import S from"chalk";function Ii(o){let e={};if(o.EVERCLAW_PROVIDER&&(e.provider=o.EVERCLAW_PROVIDER),o.EVERCLAW_MODEL&&(e.model=o.EVERCLAW_MODEL),o.EVERCLAW_API_KEY&&(e.apiKey=o.EVERCLAW_API_KEY),o.EVERCLAW_API_BASE&&(e.apiBase=o.EVERCLAW_API_BASE),o.EVERCLAW_GATEWAY_HOST&&(e.gatewayHost=o.EVERCLAW_GATEWAY_HOST),o.EVERCLAW_GATEWAY_PORT){let t=Number(o.EVERCLAW_GATEWAY_PORT);Number.isNaN(t)||(e.gatewayPort=t)}if(o.EVERCLAW_DASHBOARD!==void 0){let t=o.EVERCLAW_DASHBOARD.toLowerCase();(t==="true"||t==="false")&&(e.dashboardEnabled=t==="true")}return e}function jo(o,e){let t=structuredClone(o);if(e.provider!==void 0&&(t.agents.defaults.provider=e.provider),e.model!==void 0&&(t.agents.defaults.model=e.model),e.gatewayHost!==void 0&&(t.gateway.host=e.gatewayHost),e.gatewayPort!==void 0&&(t.gateway.port=e.gatewayPort),e.dashboardEnabled!==void 0){let n=t.gateway;n.dashboard&&typeof n.dashboard=="object"&&(n.dashboard.enabled=e.dashboardEnabled)}if(e.apiKey!==void 0||e.apiBase!==void 0){let n=t.agents.defaults.provider;n&&n!=="auto"&&(t.providers[n]||(t.providers[n]={apiKey:"",apiBase:null,extraHeaders:null}),e.apiKey!==void 0&&(t.providers[n].apiKey=e.apiKey),e.apiBase!==void 0&&(t.providers[n].apiBase=e.apiBase))}return t}function Kt(o,e,t){let n=Ii(e),r=jo(o,n);return t?jo(r,t):r}ce();ce();import At from"node:fs";import Fo from"node:path";import _i from"node:os";var Mi="gateway.pid";function Fr(){return Fo.join(_i.homedir(),it,Mi)}function Br(o){let e=Fr();At.mkdirSync(Fo.dirname(e),{recursive:!0}),At.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Pe(){let o=Fr();if(!At.existsSync(o))return null;try{let e=At.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function Ie(o){let e=Fr();try{if(!At.existsSync(e))return;if(o!==void 0){let t=Pe();if(t&&t.pid!==o)return}At.unlinkSync(e)}catch{}}function Ee(o){try{return process.kill(o,0),!0}catch{return!1}}async function Gr(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Ee(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Ee(o)}function ut(o){let e=new Date(o).getTime();if(Number.isNaN(e))return"unknown";let t=Date.now()-e;if(t<0)return"unknown";let n=Math.floor(t/1e3),r=Math.floor(n/86400),s=Math.floor(n%86400/3600),i=Math.floor(n%3600/60),a=[];return r>0&&a.push(`${r}d`),s>0&&a.push(`${s}h`),a.push(`${i}m`),a.join(" ")}Le();var qt=class{items=[];waiters=[];push(e){let t=this.waiters.shift();t?t(e):this.items.push(e)}async pop(){let e=this.items.shift();return e!==void 0?e:new Promise(t=>this.waiters.push(t))}size(){return this.items.length}};var gt=class{inbound=new qt;outbound=new qt;async publishInbound(e){this.inbound.push(e)}async consumeInbound(){return this.inbound.pop()}async publishOutbound(e){this.outbound.push(e)}async consumeOutbound(){return this.outbound.pop()}get inboundSize(){return this.inbound.size()}get outboundSize(){return this.outbound.size()}};import gs from"node:path";import Bo from"node:fs";import En from"node:path";import Go from"node:os";import Jt from"node:fs";import Rn from"node:path";var $i=[{type:"function",function:{name:"save_memory",description:"Save the memory consolidation result to persistent storage.",parameters:{type:"object",properties:{history_entry:{type:"string"},memory_update:{type:"string"}},required:["history_entry","memory_update"]}}}],Ht=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Rn.join(e,"memory");this.memoryDir=t?Rn.join(n,t):n,Jt.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Rn.join(this.memoryDir,"MEMORY.md"),this.historyFile=Rn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return Jt.existsSync(this.memoryFile)?Jt.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){Jt.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){Jt.appendFileSync(this.historyFile,`${e.trim()}
80
80
 
81
81
  `,"utf8")}getMemoryContext(){let e=this.readLongTerm();return e?`## Long-term Memory
82
- ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],u=[];for(let v of a)v._type==="anchor"?c.push(v):u.push(v);let g=[];for(let v of c)g.push(`[ANCHOR] ${v.name}: ${v.summary??"(no summary)"}`);for(let v of u){if(!v.content&&!v._full_content)continue;let d=Array.isArray(v.tools_used)&&v.tools_used.length?` [tools: ${v.tools_used.join(", ")}]`:"",b=v._full_content??v.content;g.push(`[${String(v.timestamp??"?").slice(0,16)}] ${String(v.role).toUpperCase()}${d}: ${String(b)}`)}let h=this.readLongTerm(),T=`Process this conversation and call the save_memory tool with your consolidation.
82
+ ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],d=[];for(let v of a)v._type==="anchor"?c.push(v):d.push(v);let p=[];for(let v of c)p.push(`[ANCHOR] ${v.name}: ${v.summary??"(no summary)"}`);for(let v of d){if(!v.content&&!v._full_content)continue;let u=Array.isArray(v.tools_used)&&v.tools_used.length?` [tools: ${v.tools_used.join(", ")}]`:"",b=v._full_content??v.content;p.push(`[${String(v.timestamp??"?").slice(0,16)}] ${String(v.role).toUpperCase()}${u}: ${String(b)}`)}let h=this.readLongTerm(),w=`Process this conversation and call the save_memory tool with your consolidation.
83
83
 
84
84
  ## Current Long-term Memory
85
85
  ${h||"(empty)"}
86
86
 
87
87
  ## Conversation to Process
88
- ${g.join(`
89
- `)}`;try{let v=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool."},{role:"user",content:T}],tools:Ai});if(!v.toolCalls.length)return!1;let d=v.toolCalls[0];if(!d)return!1;let b=d.arguments??{},O=b.history_entry,k=b.memory_update;if(O!=null&&this.appendHistory(typeof O=="string"?O:JSON.stringify(O)),k!=null){let z=typeof k=="string"?k:JSON.stringify(k);z!==h&&this.writeLongTerm(z)}let G=s?0:e.messages.length-l,L=e.messages.slice(0,G),N=-1;for(let z=L.length-1;z>=0;z--)if(L[z]?._type==="anchor"){N=z;break}return N!==-1?e.lastConsolidated=N+1:e.lastConsolidated=G,!0}catch{return!1}}};le();import zt from"node:fs";import Vt from"node:path";var Ur=/^[a-z0-9][a-z0-9-]*$/;function Rn(o){return Ur.test(o)}var Ge=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=Vt.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??xo("skills"),this.scannerConfig=r??null,this.scanner=s??null}listSkills(e=!0){return(e?this.getResolvedSkills().filter(n=>n.status==="available"):this.getResolvedSkills()).map(({name:n,path:r,source:s})=>({name:n,path:r,source:s}))}listResolvedSkills(){return this.getResolvedSkills().map(({content:e,metadata:t,runtimeMeta:n,...r})=>r)}loadSkill(e){let t=this.getSkillByName(e);return t?.status==="available"?t.content:null}loadSkillsForContext(e){let t=[];for(let n of e){let r=this.getSkillByName(n);if(!r){t.push(this.renderLoadFailure(n,`Skill '${n}' is not installed. ${this.getAvailableSkillsHint()}`));continue}if(r.status!=="available"){let s=r.status==="malformed"?`Skill '${n}' is malformed: ${r.reason}.`:r.status==="blocked"?`Skill '${n}' is blocked by security scanner: ${r.reason}.`:`Skill '${n}' is unavailable: ${r.reason}.`;t.push(this.renderLoadFailure(n,s));continue}t.push(`### Skill: ${n}
88
+ ${p.join(`
89
+ `)}`;try{let v=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool."},{role:"user",content:w}],tools:$i});if(!v.toolCalls.length)return!1;let u=v.toolCalls[0];if(!u)return!1;let b=u.arguments??{},P=b.history_entry,C=b.memory_update;if(P!=null&&this.appendHistory(typeof P=="string"?P:JSON.stringify(P)),C!=null){let J=typeof C=="string"?C:JSON.stringify(C);J!==h&&this.writeLongTerm(J)}let N=s?0:e.messages.length-l,q=e.messages.slice(0,N),I=-1;for(let J=q.length-1;J>=0;J--)if(q[J]?._type==="anchor"){I=J;break}return I!==-1?e.lastConsolidated=I+1:e.lastConsolidated=N,!0}catch{return!1}}};ce();import zt from"node:fs";import Vt from"node:path";var Ur=/^[a-z0-9][a-z0-9-]*$/;function An(o){return Ur.test(o)}var Ue=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=Vt.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??xo("skills"),this.scannerConfig=r??null,this.scanner=s??null}listSkills(e=!0){return(e?this.getResolvedSkills().filter(n=>n.status==="available"):this.getResolvedSkills()).map(({name:n,path:r,source:s})=>({name:n,path:r,source:s}))}listResolvedSkills(){return this.getResolvedSkills().map(({content:e,metadata:t,runtimeMeta:n,...r})=>r)}loadSkill(e){let t=this.getSkillByName(e);return t?.status==="available"?t.content:null}loadSkillsForContext(e){let t=[];for(let n of e){let r=this.getSkillByName(n);if(!r){t.push(this.renderLoadFailure(n,`Skill '${n}' is not installed. ${this.getAvailableSkillsHint()}`));continue}if(r.status!=="available"){let s=r.status==="malformed"?`Skill '${n}' is malformed: ${r.reason}.`:r.status==="blocked"?`Skill '${n}' is blocked by security scanner: ${r.reason}.`:`Skill '${n}' is unavailable: ${r.reason}.`;t.push(this.renderLoadFailure(n,s));continue}t.push(`### Skill: ${n}
90
90
 
91
91
  ${this.stripFrontmatter(r.content)}`)}return t.join(`
92
92
 
93
93
  ---
94
94
 
95
95
  `)}buildSkillsSummary(){let e=this.getResolvedSkills();if(!e.length)return"";let t=r=>r.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;"),n=["<skills>"];for(let r of e)n.push(` <skill available="${r.status==="available"}" source="${t(r.source)}">`),n.push(` <name>${t(r.name)}</name>`),n.push(` <description>${t(r.description)}</description>`),n.push(` <location>${t(r.path)}</location>`),n.push(` <status>${t(r.status)}</status>`),r.reason&&n.push(` <reason>${t(r.reason)}</reason>`),n.push(" </skill>");return n.push("</skills>"),n.join(`
96
- `)}getAlwaysSkills(){return this.getResolvedSkills().filter(e=>e.status==="available"&&e.always).map(e=>e.name)}getSkillMetadata(e){return this.getSkillByName(e)?.metadata??null}stripFrontmatter(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length).trim():e}getResolvedSkills(){let e=new Map;for(let{root:t,source:n}of this.getSkillRoots()){if(!zt.existsSync(t))continue;let r=zt.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,i)=>s.name.localeCompare(i.name));for(let s of r){if(e.has(s.name))continue;let i=Vt.join(t,s.name,"SKILL.md");zt.existsSync(i)&&e.set(s.name,this.readSkill(s.name,i,n))}}return[...e.values()].sort((t,n)=>t.name.localeCompare(n.name))}getSkillByName(e){return this.getResolvedSkills().find(t=>t.name===e)??null}getSkillRoots(){let e=[{root:this.workspaceSkills,source:"workspace"}];return this.userSkills&&e.push({root:this.userSkills,source:"user"}),e.push({root:this.builtinSkills,source:"builtin"}),e}readSkill(e,t,n){let r=zt.readFileSync(t,"utf8"),s=this.parseSkill(e,r);if(s.errors.length)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:{},description:s.description,status:"malformed",reason:s.errors.join("; "),always:!1};let i=this.getRequirementErrors(s.runtimeMeta),a=this.runSecurityScan(t,e);if(a&&!a.isSafe&&this.scannerConfig?.blockUnsafe)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:"blocked",reason:this.formatBlockedReason(a),always:s.always};if(a&&a.findings.length>0){let l=a.findings.map(c=>`[${c.severity}] ${c.title} (${c.category})`);console.warn(`SkillScanner: skill '${e}' has ${a.findings.length} finding(s): ${l.join("; ")}`)}return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:i.length?"unavailable":"available",reason:i.length?i.join("; "):null,always:s.always}}runSecurityScan(e,t){if(!this.scannerConfig?.enabled||!this.scannerConfig.scanOnLoad||!this.scanner)return null;let n=Vt.dirname(e);return this.scanner.scanSkill(n,t,{maxFileCount:this.scannerConfig.maxFileCount,maxFileSizeBytes:this.scannerConfig.maxFileSizeBytes})}formatBlockedReason(e){let t=e.findings.filter(r=>r.severity==="CRITICAL");return t.length===0?"Security scan failed":`Blocked by security scanner: ${t.map(r=>`[${r.severity}] ${r.title} (${r.category})`).join("; ")}`}parseSkill(e,t){let n=this.extractFrontmatter(t);if(!n.frontmatter)return{metadata:null,runtimeMeta:{},description:e,always:!1,errors:[n.error??"missing YAML frontmatter"]};let r=this.parseFrontmatter(n.frontmatter),s=r.metadata,i=typeof s.description=="string"&&s.description.trim()?s.description.trim():e,a=[...r.errors],l=typeof s.name=="string"?s.name.trim():"";l?l!==e?a.push(`frontmatter name '${l}' does not match directory '${e}'`):Ur.test(l)||a.push(`frontmatter name '${l}' must match ${Ur}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let u=s.always;return u!==void 0&&typeof u!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:u??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
96
+ `)}getAlwaysSkills(){return this.getResolvedSkills().filter(e=>e.status==="available"&&e.always).map(e=>e.name)}getSkillMetadata(e){return this.getSkillByName(e)?.metadata??null}stripFrontmatter(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length).trim():e}getResolvedSkills(){let e=new Map;for(let{root:t,source:n}of this.getSkillRoots()){if(!zt.existsSync(t))continue;let r=zt.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,i)=>s.name.localeCompare(i.name));for(let s of r){if(e.has(s.name))continue;let i=Vt.join(t,s.name,"SKILL.md");zt.existsSync(i)&&e.set(s.name,this.readSkill(s.name,i,n))}}return[...e.values()].sort((t,n)=>t.name.localeCompare(n.name))}getSkillByName(e){return this.getResolvedSkills().find(t=>t.name===e)??null}getSkillRoots(){let e=[{root:this.workspaceSkills,source:"workspace"}];return this.userSkills&&e.push({root:this.userSkills,source:"user"}),e.push({root:this.builtinSkills,source:"builtin"}),e}readSkill(e,t,n){let r=zt.readFileSync(t,"utf8"),s=this.parseSkill(e,r);if(s.errors.length)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:{},description:s.description,status:"malformed",reason:s.errors.join("; "),always:!1};let i=this.getRequirementErrors(s.runtimeMeta),a=this.runSecurityScan(t,e);if(a&&!a.isSafe&&this.scannerConfig?.blockUnsafe)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:"blocked",reason:this.formatBlockedReason(a),always:s.always};if(a&&a.findings.length>0){let l=a.findings.map(c=>`[${c.severity}] ${c.title} (${c.category})`);console.warn(`SkillScanner: skill '${e}' has ${a.findings.length} finding(s): ${l.join("; ")}`)}return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:i.length?"unavailable":"available",reason:i.length?i.join("; "):null,always:s.always}}runSecurityScan(e,t){if(!this.scannerConfig?.enabled||!this.scannerConfig.scanOnLoad||!this.scanner)return null;let n=Vt.dirname(e);return this.scanner.scanSkill(n,t,{maxFileCount:this.scannerConfig.maxFileCount,maxFileSizeBytes:this.scannerConfig.maxFileSizeBytes})}formatBlockedReason(e){let t=e.findings.filter(r=>r.severity==="CRITICAL");return t.length===0?"Security scan failed":`Blocked by security scanner: ${t.map(r=>`[${r.severity}] ${r.title} (${r.category})`).join("; ")}`}parseSkill(e,t){let n=this.extractFrontmatter(t);if(!n.frontmatter)return{metadata:null,runtimeMeta:{},description:e,always:!1,errors:[n.error??"missing YAML frontmatter"]};let r=this.parseFrontmatter(n.frontmatter),s=r.metadata,i=typeof s.description=="string"&&s.description.trim()?s.description.trim():e,a=[...r.errors],l=typeof s.name=="string"?s.name.trim():"";l?l!==e?a.push(`frontmatter name '${l}' does not match directory '${e}'`):Ur.test(l)||a.push(`frontmatter name '${l}' must match ${Ur}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let d=s.always;return d!==void 0&&typeof d!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:d??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
97
97
  `)||e.startsWith(`---\r
98
98
  `)))return{frontmatter:null,error:"missing YAML frontmatter"};let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);return t?{frontmatter:t[1]??null,error:null}:{frontmatter:null,error:"unterminated YAML frontmatter"}}parseFrontmatter(e){let t={},n=[];for(let r of e.split(/\r?\n/)){let s=r.trim();if(!s)continue;let i=s.indexOf(":");if(i<=0){n.push(`invalid frontmatter line '${s}'`);continue}let a=s.slice(0,i).trim(),l=s.slice(i+1).trim();t[a]=this.parseFrontmatterValue(l)}return{metadata:t,errors:n}}parseFrontmatterValue(e){let t=e.replace(/^['"]|['"]$/g,"");return t==="true"?!0:t==="false"?!1:t}parseRuntimeMetadata(e){if(e===void 0||e==="")return{runtimeMeta:{},errors:[]};if(typeof e!="string")return{runtimeMeta:{},errors:["frontmatter field 'metadata' must be a JSON object string"]};let t;try{t=JSON.parse(e)}catch{return{runtimeMeta:{},errors:["frontmatter field 'metadata' must contain valid JSON"]}}if(!this.isRecord(t))return{runtimeMeta:{},errors:["frontmatter field 'metadata' must decode to an object"]};let n=t.everclaw??t.openclaw??{};if(!this.isRecord(n))return{runtimeMeta:{},errors:["skill metadata for 'everclaw'/'openclaw' must be an object"]};let r=[],s={};if(n.always!==void 0&&(typeof n.always!="boolean"?r.push("skill metadata field 'always' must be a boolean"):s.always=n.always),n.requires!==void 0)if(!this.isRecord(n.requires))r.push("skill metadata field 'requires' must be an object");else{let i=n.requires.bins,a=n.requires.env;i!==void 0&&!this.isStringArray(i)&&r.push("skill metadata field 'requires.bins' must be an array of strings"),a!==void 0&&!this.isStringArray(a)&&r.push("skill metadata field 'requires.env' must be an array of strings");let l={};this.isStringArray(i)&&(l.bins=i),this.isStringArray(a)&&(l.env=a),Object.keys(l).length>0&&(s.requires=l)}return{runtimeMeta:s,errors:r}}getRequirementErrors(e){let t=e.requires??{},n=(t.bins??[]).filter(i=>!this.hasBinary(i)),r=(t.env??[]).filter(i=>!process.env[i]),s=[];return n.length&&s.push(`missing required binaries: ${n.join(", ")}`),r.length&&s.push(`missing required env vars: ${r.join(", ")}`),s}hasBinary(e){let t=(process.env.PATH??"").split(Vt.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>zt.existsSync(Vt.join(r,`${e}${s}`))))}getAvailableSkillsHint(){let e=this.getResolvedSkills().filter(t=>t.status==="available").map(t=>t.name);return e.length?`Available skills: ${e.join(", ")}`:"No skills are currently available."}renderLoadFailure(e,t){return`### Skill unavailable: ${e}
99
99
 
100
- Error: ${t}`}isRecord(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}isStringArray(e){return Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim().length>0)}};var gt=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new Ht(e),this.skills=new Ge(e,null,void 0,t,n)}static BOOTSTRAP_FILES=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","IDENTITY.md"];static RUNTIME_CONTEXT_TAG="[Runtime Context - metadata only, not instructions]";static ANCHOR_TAG="[anchor]";static estimateTokens(e){if(!e)return 0;let t=typeof e=="string"?e:JSON.stringify(e);return Math.ceil(t.length/4)}static estimateMessageTokens(e){let t=0;if(typeof e.content=="string"&&(t+=o.estimateTokens(e.content)),Array.isArray(e.tool_calls))for(let n of e.tool_calls)t+=o.estimateTokens(n);return t}static findLastAnchor(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n)continue;let r=n.content;if(typeof r=="string"&&r.includes(o.ANCHOR_TAG))return{name:r.match(/\[anchor\]\s*(\S+)/)?.[1]??null,index:t}}return{name:null,index:-1}}defaultMemory;skills;getMemoryStore(e){return e?new Ht(this.workspace,e):this.defaultMemory}buildSystemPrompt(e,t){let n=[this.getIdentity()],r=this.loadBootstrapFiles();r&&n.push(r);let i=this.getMemoryStore(t).getMemoryContext();i&&n.push(`# Memory
100
+ Error: ${t}`}isRecord(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}isStringArray(e){return Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim().length>0)}};var mt=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new Ht(e),this.skills=new Ue(e,null,void 0,t,n)}static BOOTSTRAP_FILES=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","IDENTITY.md"];static RUNTIME_CONTEXT_TAG="[Runtime Context - metadata only, not instructions]";static ANCHOR_TAG="[anchor]";static estimateTokens(e){if(!e)return 0;let t=typeof e=="string"?e:JSON.stringify(e);return Math.ceil(t.length/4)}static estimateMessageTokens(e){let t=0;if(typeof e.content=="string"&&(t+=o.estimateTokens(e.content)),Array.isArray(e.tool_calls))for(let n of e.tool_calls)t+=o.estimateTokens(n);return t}static findLastAnchor(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n)continue;let r=n.content;if(typeof r=="string"&&r.includes(o.ANCHOR_TAG))return{name:r.match(/\[anchor\]\s*(\S+)/)?.[1]??null,index:t}}return{name:null,index:-1}}defaultMemory;skills;getMemoryStore(e){return e?new Ht(this.workspace,e):this.defaultMemory}buildSystemPrompt(e,t){let n=[this.getIdentity()],r=this.loadBootstrapFiles();r&&n.push(r);let i=this.getMemoryStore(t).getMemoryContext();i&&n.push(`# Memory
101
101
 
102
102
  ${i}`);let a=this.skills.getAlwaysSkills();if(a.length){let c=this.skills.loadSkillsForContext(a);c&&n.push(`# Active Skills
103
103
 
@@ -116,45 +116,45 @@ ${l}`),n.join(`
116
116
  You are everclaw, a helpful AI assistant.
117
117
 
118
118
  ## Runtime
119
- ${jo.platform()} ${jo.arch()}, Node ${process.version}
119
+ ${Go.platform()} ${Go.arch()}, Node ${process.version}
120
120
 
121
121
  ## Workspace
122
122
  Your workspace is at: ${this.workspace}
123
- - Long-term memory: ${An.join(this.workspace,"memory","MEMORY.md")}
124
- - History log: ${An.join(this.workspace,"memory","HISTORY.md")}
125
- - Custom skills: ${An.join(this.workspace,"skills","{skill-name}","SKILL.md")}
123
+ - Long-term memory: ${En.join(this.workspace,"memory","MEMORY.md")}
124
+ - History log: ${En.join(this.workspace,"memory","HISTORY.md")}
125
+ - Custom skills: ${En.join(this.workspace,"skills","{skill-name}","SKILL.md")}
126
126
 
127
127
  ## Guidelines
128
128
  - State intent before tool calls, but never claim results before receiving them.
129
129
  - Before modifying a file, read it first.
130
- - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=An.join(this.workspace,t);No.existsSync(n)&&e.push(`## ${t}
130
+ - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=En.join(this.workspace,t);Bo.existsSync(n)&&e.push(`## ${t}
131
131
 
132
- ${No.readFileSync(n,"utf8")}`)}return e.join(`
132
+ ${Bo.readFileSync(n,"utf8")}`)}return e.join(`
133
133
 
134
- `)}static buildRuntimeContext(e,t){let r=[`Current Time: ${new Date().toISOString()}`];return e&&t&&(r.push(`Channel: ${e}`),r.push(`Chat ID: ${t}`)),`${o.RUNTIME_CONTEXT_TAG}
135
- ${r.join(`
136
- `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}};import{randomUUID as Ca}from"node:crypto";import va from"node:path";import{randomUUID as Bo}from"node:crypto";import Ii from"cron-parser";function Kr(o){return o??"builtin"}function Fo(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function Ye(){return Fo()}function En(o,e,t,n){let r=Kr(t.source),s=e.get(n.name);if(s)throw new Error(`${o} '${n.name}' from extension '${t.name}' conflicts with extension '${s.extension}'`);e.set(n.name,{extension:t.name,source:r,contribution:n})}function Ei(o,e,t){let n=(r,s)=>{let i=r.find(a=>a.contribution.name===s.name);if(i)throw new Error(`lifecycle '${s.slot}:${s.name}' from extension '${e.name}' conflicts with extension '${i.extension}'`);r.push({extension:e.name,source:Kr(e.source),contribution:s})};switch(t.slot){case"beforeAgentTurn":n(o.beforeAgentTurn,t);return;case"afterAgentTurn":n(o.afterAgentTurn,t);return;case"beforeOutbound":n(o.beforeOutbound,t);return;case"afterOutbound":n(o.afterOutbound,t);return;case"beforeScheduledJob":n(o.beforeScheduledJob,t);return;case"afterScheduledJob":n(o.afterScheduledJob,t);return;case"shutdown":n(o.shutdown,t);return}}function he(o){return{...o,source:"builtin"}}var Gr=class{extensions=new Map;register(e){if(this.extensions.has(e.name))throw new Error(`Extension '${e.name}' is already registered`);return this.extensions.set(e.name,{...e,source:Kr(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=Fo();for(let i of this.extensions.values()){for(let a of i.tools??[])En("tool",e,i,a);for(let a of i.channels??[])En("channel",t,i,a);for(let a of i.jobs??[])En("job",n,i,a);for(let a of i.commands??[])En("command",r,i,a);for(let a of i.lifecycle??[])Ei(s,i,a)}return{extensions:this.list(),tools:e,channels:t,jobs:n,commands:r,lifecycle:{beforeAgentTurn:s.beforeAgentTurn,afterAgentTurn:s.afterAgentTurn,beforeOutbound:s.beforeOutbound,afterOutbound:s.afterOutbound,beforeScheduledJob:s.beforeScheduledJob,afterScheduledJob:s.afterScheduledJob,shutdown:s.shutdown}}}};function Pi(o){return o instanceof Error?o.message:String(o)}var Wr=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${Pi(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function We(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new Wr(e,n.extension,n.source,n.contribution.name,r)}}function Jr(o){let e=new Gr;for(let t of o)e.register(t);return e.compose()}function Xt(){let o=new Error("Operation aborted");return o.name="AbortError",o}function te(o){return o instanceof Error&&o.name==="AbortError"}function Y(o){if(o?.aborted)throw Xt()}function ve(){return Date.now()}var _i="default";function Et(o,e){if(o.kind==="at")return o.atMs>e?o.atMs:null;if(o.kind==="every")return o.everyMs>0?e+o.everyMs:null;if(o.kind==="cron")try{let t=o.tz?{currentDate:new Date(e),tz:o.tz}:{currentDate:new Date(e)};return Ii.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Uo(o){if("tz"in o&&o.tz&&o.kind!=="cron")throw new Error("tz can only be used with cron schedules");if(o.kind==="cron"&&o.tz)try{new Intl.DateTimeFormat("en-US",{timeZone:o.tz})}catch{throw new Error(`unknown timezone '${o.tz}'`)}}var Yt=class{constructor(e={},t,n=Ye()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??_i}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Le({dataDir:this.dataDir})),this.storage}rowToJob(e){let t=JSON.parse(e.state_json);return{id:e.job_id,name:e.name,enabled:!!e.enabled,schedule:JSON.parse(e.schedule_json),payload:JSON.parse(e.payload_json),state:{...t,nextRunAtMs:e.next_run_at_ms},createdAtMs:e.created_at_ms,updatedAtMs:e.updated_at_ms,deleteAfterRun:!!e.delete_after_run}}readStoreFromStorage(){return{version:1,jobs:this.getStorage().prepare(`SELECT job_id, name, enabled, schedule_json, payload_json, state_json,
134
+ `)}static buildRuntimeContext(e,t,n){let s=[`Current Time: ${new Date().toISOString()}`];return e&&t&&(s.push(`Channel: ${e}`),s.push(`Chat ID: ${t}`)),n?.chat_type&&s.push(`Chat Type: ${n.chat_type}`),n?.bot_mentioned&&s.push("Bot Mentioned: yes"),`${o.RUNTIME_CONTEXT_TAG}
135
+ ${s.join(`
136
+ `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId,e.metadata)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}};import{randomUUID as Ia}from"node:crypto";import Ta from"node:path";import{randomUUID as Wo}from"node:crypto";import Di from"cron-parser";function qr(o){return o??"builtin"}function Uo(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function Ye(){return Uo()}function Pn(o,e,t,n){let r=qr(t.source),s=e.get(n.name);if(s)throw new Error(`${o} '${n.name}' from extension '${t.name}' conflicts with extension '${s.extension}'`);e.set(n.name,{extension:t.name,source:r,contribution:n})}function Oi(o,e,t){let n=(r,s)=>{let i=r.find(a=>a.contribution.name===s.name);if(i)throw new Error(`lifecycle '${s.slot}:${s.name}' from extension '${e.name}' conflicts with extension '${i.extension}'`);r.push({extension:e.name,source:qr(e.source),contribution:s})};switch(t.slot){case"beforeAgentTurn":n(o.beforeAgentTurn,t);return;case"afterAgentTurn":n(o.afterAgentTurn,t);return;case"beforeOutbound":n(o.beforeOutbound,t);return;case"afterOutbound":n(o.afterOutbound,t);return;case"beforeScheduledJob":n(o.beforeScheduledJob,t);return;case"afterScheduledJob":n(o.afterScheduledJob,t);return;case"shutdown":n(o.shutdown,t);return}}function ye(o){return{...o,source:"builtin"}}var Wr=class{extensions=new Map;register(e){if(this.extensions.has(e.name))throw new Error(`Extension '${e.name}' is already registered`);return this.extensions.set(e.name,{...e,source:qr(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=Uo();for(let i of this.extensions.values()){for(let a of i.tools??[])Pn("tool",e,i,a);for(let a of i.channels??[])Pn("channel",t,i,a);for(let a of i.jobs??[])Pn("job",n,i,a);for(let a of i.commands??[])Pn("command",r,i,a);for(let a of i.lifecycle??[])Oi(s,i,a)}return{extensions:this.list(),tools:e,channels:t,jobs:n,commands:r,lifecycle:{beforeAgentTurn:s.beforeAgentTurn,afterAgentTurn:s.afterAgentTurn,beforeOutbound:s.beforeOutbound,afterOutbound:s.afterOutbound,beforeScheduledJob:s.beforeScheduledJob,afterScheduledJob:s.afterScheduledJob,shutdown:s.shutdown}}}};function Li(o){return o instanceof Error?o.message:String(o)}var Kr=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${Li(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function We(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new Kr(e,n.extension,n.source,n.contribution.name,r)}}function Jr(o){let e=new Wr;for(let t of o)e.register(t);return e.compose()}function Xt(){let o=new Error("Operation aborted");return o.name="AbortError",o}function ne(o){return o instanceof Error&&o.name==="AbortError"}function Y(o){if(o?.aborted)throw Xt()}function we(){return Date.now()}var Ni="default";function Et(o,e){if(o.kind==="at")return o.atMs>e?o.atMs:null;if(o.kind==="every")return o.everyMs>0?e+o.everyMs:null;if(o.kind==="cron")try{let t=o.tz?{currentDate:new Date(e),tz:o.tz}:{currentDate:new Date(e)};return Di.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Ko(o){if("tz"in o&&o.tz&&o.kind!=="cron")throw new Error("tz can only be used with cron schedules");if(o.kind==="cron"&&o.tz)try{new Intl.DateTimeFormat("en-US",{timeZone:o.tz})}catch{throw new Error(`unknown timezone '${o.tz}'`)}}var Yt=class{constructor(e={},t,n=Ye()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??Ni}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=De({dataDir:this.dataDir})),this.storage}rowToJob(e){let t=JSON.parse(e.state_json);return{id:e.job_id,name:e.name,enabled:!!e.enabled,schedule:JSON.parse(e.schedule_json),payload:JSON.parse(e.payload_json),state:{...t,nextRunAtMs:e.next_run_at_ms},createdAtMs:e.created_at_ms,updatedAtMs:e.updated_at_ms,deleteAfterRun:!!e.delete_after_run}}readStoreFromStorage(){return{version:1,jobs:this.getStorage().prepare(`SELECT job_id, name, enabled, schedule_json, payload_json, state_json,
137
137
  next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
138
138
  FROM cron_jobs
139
139
  WHERE workspace = ?
140
140
  ORDER BY created_at_ms, job_id`).all(this.workspaceKey).map(t=>this.rowToJob(t))}}loadStore(){return this.store?this.store:(this.store=this.readStoreFromStorage(),this.store)}saveStore(){if(!this.store)return;let e=this.getStorage();e.transaction(()=>{e.prepare("DELETE FROM cron_jobs WHERE workspace = ?").run(this.workspaceKey);let t=e.prepare(`INSERT INTO cron_jobs (
141
141
  workspace, job_id, name, enabled, schedule_json, payload_json,
142
142
  state_json, next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
143
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let n of this.store.jobs)t.run(this.workspaceKey,n.id,n.name,n.enabled?1:0,JSON.stringify(n.schedule),JSON.stringify(n.payload),JSON.stringify(n.state),n.state.nextRunAtMs,n.deleteAfterRun?1:0,n.createdAtMs,n.updatedAtMs)})}getNextWakeMs(){let t=this.loadStore().jobs.filter(n=>n.enabled&&n.state.nextRunAtMs).map(n=>n.state.nextRunAtMs);return t.length?Math.min(...t):null}armTimer(){this.timer&&clearTimeout(this.timer);let e=this.getNextWakeMs();!this.running||!e||(this.timer=setTimeout(()=>{this.onTimer()},Math.max(0,e-ve())))}async onTimer(){let e=this.loadStore(),t=ve(),n=e.jobs.filter(r=>r.enabled&&r.state.nextRunAtMs&&t>=r.state.nextRunAtMs);for(let r of n)await this.executeJob(r);this.saveStore(),this.armTimer()}async executeJob(e){let t=ve(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await We(this.lifecycle.beforeScheduledJob,"beforeScheduledJob",{job:e}),this.onJob&&(n=await this.onJob(e,{signal:s.signal}))}catch(i){r=i}finally{this.activeControllers.delete(s)}try{await We(this.lifecycle.afterScheduledJob,"afterScheduledJob",{job:e,result:n,error:r})}catch(i){r=r==null?i:new Error(`${String(r)}; ${String(i)}`)}e.state.lastStatus=r==null?"ok":te(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=ve(),e.schedule.kind==="at"?e.deleteAfterRun?this.store.jobs=this.store.jobs.filter(i=>i.id!==e.id):(e.enabled=!1,e.state.nextRunAtMs=null):e.state.nextRunAtMs=Et(e.schedule,ve())}reconcileRecoveredJobs(e){let t=this.loadStore(),n=!1;for(let r of t.jobs){if(!r.enabled){r.state.nextRunAtMs!==null&&(r.state.nextRunAtMs=null,r.updatedAtMs=e,n=!0);continue}if(r.state.nextRunAtMs!==null)continue;let s=r.schedule.kind==="at"&&r.schedule.atMs<=e?e:Et(r.schedule,e);s!==r.state.nextRunAtMs&&(r.state.nextRunAtMs=s,r.updatedAtMs=e,n=!0)}return n}seedDefaultJobs(){let e=this.loadStore();if(e.jobs.length>0)return;let t=ve(),n={id:Bo().slice(0,8),name:"Example: Daily reminder",enabled:!0,schedule:{kind:"every",everyMs:1440*60*1e3},payload:{kind:"agent_turn",message:"This is an example cron job. Edit or delete it.",deliver:!1},state:{nextRunAtMs:Et({kind:"every",everyMs:1440*60*1e3},t),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:t,updatedAtMs:t,deleteAfterRun:!1};e.jobs.push(n),this.saveStore()}async start(){this.running=!0,this.seedDefaultJobs();let e=ve();this.reconcileRecoveredJobs(e)&&this.saveStore(),this.armTimer()}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null;for(let e of this.activeControllers)e.abort()}listJobs(e=!1){let t=this.loadStore();return[...e?t.jobs:t.jobs.filter(r=>r.enabled)].sort((r,s)=>(r.state.nextRunAtMs??Number.MAX_SAFE_INTEGER)-(s.state.nextRunAtMs??Number.MAX_SAFE_INTEGER))}addJob(e){let t=this.loadStore();Uo(e.schedule);let n=ve(),r={id:Bo().slice(0,8),name:e.name,enabled:!0,schedule:e.schedule,payload:{kind:"agent_turn",message:e.message,deliver:!!e.deliver,channel:e.channel,to:e.to},state:{nextRunAtMs:Et(e.schedule,n),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:n,updatedAtMs:n,deleteAfterRun:!!e.deleteAfterRun};return t.jobs.push(r),this.saveStore(),this.armTimer(),r}removeJob(e){let t=this.loadStore(),n=t.jobs.length;t.jobs=t.jobs.filter(s=>s.id!==e);let r=t.jobs.length<n;return r&&(this.saveStore(),this.armTimer()),r}enableJob(e,t=!0){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(r.enabled=t,r.updatedAtMs=ve(),r.state.nextRunAtMs=t?Et(r.schedule,ve()):null,this.saveStore(),this.armTimer(),r):null}async runJob(e,t=!1){let r=this.loadStore().jobs.find(s=>s.id===e);return!r||!t&&!r.enabled?!1:(await this.executeJob(r),this.saveStore(),this.armTimer(),!0)}updateJob(e,t){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(t.name!==void 0&&(r.name=t.name),t.schedule!==void 0&&(Uo(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Et(t.schedule,ve()):null),t.message!==void 0&&(r.payload.message=t.message),t.deliver!==void 0&&(r.payload.deliver=t.deliver),t.channel!==void 0&&(r.payload.channel=t.channel),t.to!==void 0&&(r.payload.to=t.to),t.deleteAfterRun!==void 0&&(r.deleteAfterRun=t.deleteAfterRun),r.updatedAtMs=ve(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import Go from"node:fs";import Mi from"node:path";var $i=[{type:"function",function:{name:"heartbeat",description:"Report heartbeat decision after reviewing tasks.",parameters:{type:"object",properties:{action:{type:"string",enum:["skip","run"]},tasks:{type:"string"}},required:["action"]}}}],Qt=class{constructor(e,t,n,r,s,i=1800,a=!0){this.workspace=e;this.provider=t;this.model=n;this.onExecute=r;this.onNotify=s;this.intervalS=i;this.enabled=a}running=!1;timer=null;activeController=null;get heartbeatFile(){return Mi.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!Go.existsSync(this.heartbeatFile))return null;let e=Go.readFileSync(this.heartbeatFile,"utf8");return e.trim()?e:null}async decide(e){let t=await this.provider.chat({model:this.model,messages:[{role:"system",content:"You are a heartbeat agent. Call the heartbeat tool to report your decision."},{role:"user",content:`Review the following HEARTBEAT.md and decide whether there are active tasks.
143
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let n of this.store.jobs)t.run(this.workspaceKey,n.id,n.name,n.enabled?1:0,JSON.stringify(n.schedule),JSON.stringify(n.payload),JSON.stringify(n.state),n.state.nextRunAtMs,n.deleteAfterRun?1:0,n.createdAtMs,n.updatedAtMs)})}getNextWakeMs(){let t=this.loadStore().jobs.filter(n=>n.enabled&&n.state.nextRunAtMs).map(n=>n.state.nextRunAtMs);return t.length?Math.min(...t):null}armTimer(){this.timer&&clearTimeout(this.timer);let e=this.getNextWakeMs();!this.running||!e||(this.timer=setTimeout(()=>{this.onTimer()},Math.max(0,e-we())))}async onTimer(){let e=this.loadStore(),t=we(),n=e.jobs.filter(r=>r.enabled&&r.state.nextRunAtMs&&t>=r.state.nextRunAtMs);for(let r of n)await this.executeJob(r);this.saveStore(),this.armTimer()}async executeJob(e){let t=we(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await We(this.lifecycle.beforeScheduledJob,"beforeScheduledJob",{job:e}),this.onJob&&(n=await this.onJob(e,{signal:s.signal}))}catch(i){r=i}finally{this.activeControllers.delete(s)}try{await We(this.lifecycle.afterScheduledJob,"afterScheduledJob",{job:e,result:n,error:r})}catch(i){r=r==null?i:new Error(`${String(r)}; ${String(i)}`)}e.state.lastStatus=r==null?"ok":ne(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=we(),e.schedule.kind==="at"?e.deleteAfterRun?this.store.jobs=this.store.jobs.filter(i=>i.id!==e.id):(e.enabled=!1,e.state.nextRunAtMs=null):e.state.nextRunAtMs=Et(e.schedule,we())}reconcileRecoveredJobs(e){let t=this.loadStore(),n=!1;for(let r of t.jobs){if(!r.enabled){r.state.nextRunAtMs!==null&&(r.state.nextRunAtMs=null,r.updatedAtMs=e,n=!0);continue}if(r.state.nextRunAtMs!==null)continue;let s=r.schedule.kind==="at"&&r.schedule.atMs<=e?e:Et(r.schedule,e);s!==r.state.nextRunAtMs&&(r.state.nextRunAtMs=s,r.updatedAtMs=e,n=!0)}return n}seedDefaultJobs(){let e=this.loadStore();if(e.jobs.length>0)return;let t=we(),n={id:Wo().slice(0,8),name:"Example: Daily reminder",enabled:!0,schedule:{kind:"every",everyMs:1440*60*1e3},payload:{kind:"agent_turn",message:"This is an example cron job. Edit or delete it.",deliver:!1},state:{nextRunAtMs:Et({kind:"every",everyMs:1440*60*1e3},t),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:t,updatedAtMs:t,deleteAfterRun:!1};e.jobs.push(n),this.saveStore()}async start(){this.running=!0,this.seedDefaultJobs();let e=we();this.reconcileRecoveredJobs(e)&&this.saveStore(),this.armTimer()}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null;for(let e of this.activeControllers)e.abort()}listJobs(e=!1){let t=this.loadStore();return[...e?t.jobs:t.jobs.filter(r=>r.enabled)].sort((r,s)=>(r.state.nextRunAtMs??Number.MAX_SAFE_INTEGER)-(s.state.nextRunAtMs??Number.MAX_SAFE_INTEGER))}addJob(e){let t=this.loadStore();Ko(e.schedule);let n=we(),r={id:Wo().slice(0,8),name:e.name,enabled:!0,schedule:e.schedule,payload:{kind:"agent_turn",message:e.message,deliver:!!e.deliver,channel:e.channel,to:e.to},state:{nextRunAtMs:Et(e.schedule,n),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:n,updatedAtMs:n,deleteAfterRun:!!e.deleteAfterRun};return t.jobs.push(r),this.saveStore(),this.armTimer(),r}removeJob(e){let t=this.loadStore(),n=t.jobs.length;t.jobs=t.jobs.filter(s=>s.id!==e);let r=t.jobs.length<n;return r&&(this.saveStore(),this.armTimer()),r}enableJob(e,t=!0){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(r.enabled=t,r.updatedAtMs=we(),r.state.nextRunAtMs=t?Et(r.schedule,we()):null,this.saveStore(),this.armTimer(),r):null}async runJob(e,t=!1){let r=this.loadStore().jobs.find(s=>s.id===e);return!r||!t&&!r.enabled?!1:(await this.executeJob(r),this.saveStore(),this.armTimer(),!0)}updateJob(e,t){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(t.name!==void 0&&(r.name=t.name),t.schedule!==void 0&&(Ko(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Et(t.schedule,we()):null),t.message!==void 0&&(r.payload.message=t.message),t.deliver!==void 0&&(r.payload.deliver=t.deliver),t.channel!==void 0&&(r.payload.channel=t.channel),t.to!==void 0&&(r.payload.to=t.to),t.deleteAfterRun!==void 0&&(r.deleteAfterRun=t.deleteAfterRun),r.updatedAtMs=we(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import qo from"node:fs";import ji from"node:path";var Fi=[{type:"function",function:{name:"heartbeat",description:"Report heartbeat decision after reviewing tasks.",parameters:{type:"object",properties:{action:{type:"string",enum:["skip","run"]},tasks:{type:"string"}},required:["action"]}}}],Qt=class{constructor(e,t,n,r,s,i=1800,a=!0){this.workspace=e;this.provider=t;this.model=n;this.onExecute=r;this.onNotify=s;this.intervalS=i;this.enabled=a}running=!1;timer=null;activeController=null;get heartbeatFile(){return ji.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!qo.existsSync(this.heartbeatFile))return null;let e=qo.readFileSync(this.heartbeatFile,"utf8");return e.trim()?e:null}async decide(e){let t=await this.provider.chat({model:this.model,messages:[{role:"system",content:"You are a heartbeat agent. Call the heartbeat tool to report your decision."},{role:"user",content:`Review the following HEARTBEAT.md and decide whether there are active tasks.
144
144
 
145
- ${e}`}],tools:$i});if(!t.toolCalls.length)return{action:"skip",tasks:""};let n=t.toolCalls[0];if(!n)return{action:"skip",tasks:""};let r=n.arguments,s=r.action==="run"?"run":"skip",i=typeof r.tasks=="string"?r.tasks:"";return{action:s,tasks:i}}async start(){!this.enabled||this.running||(this.running=!0,this.schedule())}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null,this.activeController?.abort(),this.activeController=null}schedule(){this.running&&(this.timer=setTimeout(()=>{this.tick().catch(e=>{te(e)||console.warn(String(e))}).finally(()=>this.schedule())},this.intervalS*1e3))}async executeTasks(e){if(!this.onExecute)throw new Error("Heartbeat execution callback is not configured");let t=new AbortController;this.activeController=t;try{return await this.onExecute(e,{signal:t.signal})}finally{this.activeController===t&&(this.activeController=null)}}async tick(){let e=this.readHeartbeat();if(!e)return;let{action:t,tasks:n}=await this.decide(e);if(t!=="run"||!this.onExecute)return;let r=await this.executeTasks(n);r&&this.onNotify&&await this.onNotify(r)}async triggerNow(){let e=this.readHeartbeat();if(!e)return null;let{action:t,tasks:n}=await this.decide(e);return t!=="run"||!this.onExecute?null:this.executeTasks(n)}};var W=class o{static typeMap={string:e=>typeof e=="string",integer:e=>Number.isInteger(e),number:e=>typeof e=="number"&&Number.isFinite(e),boolean:e=>typeof e=="boolean",array:e=>Array.isArray(e),object:e=>!!e&&typeof e=="object"&&!Array.isArray(e)};validateParams(e){let t=this.parameters??{};if(t.type!=="object")throw new Error(`Schema must be object type, got ${String(t.type)}`);return this.validateValue(e,{...t,type:"object"},"parameter")}validateValue(e,t,n){let r=t.type,s=[];if(r&&o.typeMap[r]&&!o.typeMap[r](e))return[`${n} should be ${r}`];if(t.enum&&!t.enum.includes(e)&&s.push(`${n} must be one of ${JSON.stringify(t.enum)}`),(r==="integer"||r==="number")&&typeof e=="number"&&(typeof t.minimum=="number"&&e<t.minimum&&s.push(`${n} must be >= ${t.minimum}`),typeof t.maximum=="number"&&e>t.maximum&&s.push(`${n} must be <= ${t.maximum}`)),r==="string"&&typeof e=="string"&&(typeof t.minLength=="number"&&e.length<t.minLength&&s.push(`${n} must be at least ${t.minLength} chars`),typeof t.maxLength=="number"&&e.length>t.maxLength&&s.push(`${n} must be at most ${t.maxLength} chars`)),r==="object"&&e&&typeof e=="object"&&!Array.isArray(e)){let i=e,a=t.properties??{};for(let l of t.required??[])l in i||s.push(`missing required ${n==="parameter"?l:`${n}.${l}`}`);for(let[l,c]of Object.entries(i))a[l]&&s.push(...this.validateValue(c,a[l],n==="parameter"?l:`${n}.${l}`))}return r==="array"&&Array.isArray(e)&&t.items&&typeof t.items=="object"&&e.forEach((i,a)=>s.push(...this.validateValue(i,t.items,`${n}[${a}]`))),s}toSchema(){return{type:"function",function:{name:this.name,description:this.description,parameters:this.parameters}}}};var Pn=class extends W{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let u={kind:"cron",expr:s};i&&(u.tz=i),l=u}else if(a){let u=new Date(a);if(Number.isNaN(u.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:u.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let u=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${u.name}' (id: ${u.id})`}catch(u){return`Error: ${String(u).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
145
+ ${e}`}],tools:Fi});if(!t.toolCalls.length)return{action:"skip",tasks:""};let n=t.toolCalls[0];if(!n)return{action:"skip",tasks:""};let r=n.arguments,s=r.action==="run"?"run":"skip",i=typeof r.tasks=="string"?r.tasks:"";return{action:s,tasks:i}}async start(){!this.enabled||this.running||(this.running=!0,this.schedule())}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null,this.activeController?.abort(),this.activeController=null}schedule(){this.running&&(this.timer=setTimeout(()=>{this.tick().catch(e=>{ne(e)||console.warn(String(e))}).finally(()=>this.schedule())},this.intervalS*1e3))}async executeTasks(e){if(!this.onExecute)throw new Error("Heartbeat execution callback is not configured");let t=new AbortController;this.activeController=t;try{return await this.onExecute(e,{signal:t.signal})}finally{this.activeController===t&&(this.activeController=null)}}async tick(){let e=this.readHeartbeat();if(!e)return;let{action:t,tasks:n}=await this.decide(e);if(t!=="run"||!this.onExecute)return;let r=await this.executeTasks(n);r&&this.onNotify&&await this.onNotify(r)}async triggerNow(){let e=this.readHeartbeat();if(!e)return null;let{action:t,tasks:n}=await this.decide(e);return t!=="run"||!this.onExecute?null:this.executeTasks(n)}};var G=class o{static typeMap={string:e=>typeof e=="string",integer:e=>Number.isInteger(e),number:e=>typeof e=="number"&&Number.isFinite(e),boolean:e=>typeof e=="boolean",array:e=>Array.isArray(e),object:e=>!!e&&typeof e=="object"&&!Array.isArray(e)};validateParams(e){let t=this.parameters??{};if(t.type!=="object")throw new Error(`Schema must be object type, got ${String(t.type)}`);return this.validateValue(e,{...t,type:"object"},"parameter")}validateValue(e,t,n){let r=t.type,s=[];if(r&&o.typeMap[r]&&!o.typeMap[r](e))return[`${n} should be ${r}`];if(t.enum&&!t.enum.includes(e)&&s.push(`${n} must be one of ${JSON.stringify(t.enum)}`),(r==="integer"||r==="number")&&typeof e=="number"&&(typeof t.minimum=="number"&&e<t.minimum&&s.push(`${n} must be >= ${t.minimum}`),typeof t.maximum=="number"&&e>t.maximum&&s.push(`${n} must be <= ${t.maximum}`)),r==="string"&&typeof e=="string"&&(typeof t.minLength=="number"&&e.length<t.minLength&&s.push(`${n} must be at least ${t.minLength} chars`),typeof t.maxLength=="number"&&e.length>t.maxLength&&s.push(`${n} must be at most ${t.maxLength} chars`)),r==="object"&&e&&typeof e=="object"&&!Array.isArray(e)){let i=e,a=t.properties??{};for(let l of t.required??[])l in i||s.push(`missing required ${n==="parameter"?l:`${n}.${l}`}`);for(let[l,c]of Object.entries(i))a[l]&&s.push(...this.validateValue(c,a[l],n==="parameter"?l:`${n}.${l}`))}return r==="array"&&Array.isArray(e)&&t.items&&typeof t.items=="object"&&e.forEach((i,a)=>s.push(...this.validateValue(i,t.items,`${n}[${a}]`))),s}toSchema(){return{type:"function",function:{name:this.name,description:this.description,parameters:this.parameters}}}};var In=class extends G{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let d={kind:"cron",expr:s};i&&(d.tz=i),l=d}else if(a){let d=new Date(a);if(Number.isNaN(d.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:d.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let d=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${d.name}' (id: ${d.id})`}catch(d){return`Error: ${String(d).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
146
146
  ${t.map(n=>`- ${n.name} (id: ${n.id}, ${n.schedule.kind})`).join(`
147
- `)}`:"No scheduled jobs."}removeJob(t){return t?this.cron.removeJob(t)?`Removed job ${t}`:`Job ${t} not found`:"Error: job_id is required for remove"}};import we from"node:fs";import Pt from"node:path";import Ie from"node:fs";import ce from"node:path";function Wo(o){let e=ce.resolve(o);for(;e!=="/"&&e!==".";)try{return Ie.lstatSync(e),e}catch{let t=ce.dirname(e);if(t===e)break;e=t}return e||"/"}function Ko(o,e){let t=ce.resolve(o),n=ce.resolve(e),r=n.endsWith(ce.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+ce.sep);if(!Ie.existsSync(r))return s;try{let i=r;try{i=Ie.realpathSync.native(r)}catch{}if(Ie.existsSync(t)){let c=Ie.realpathSync.native(t);return c===i||c.startsWith(i+ce.sep)}let a=Wo(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=Ie.realpathSync.native(a);if(c===i||c.startsWith(i+ce.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=ce.dirname(l);if(c===l)break;try{if(Ie.lstatSync(c).isSymbolicLink()){let g=Ie.realpathSync.native(c);if(g!==i&&!g.startsWith(i+ce.sep))return!1}}catch{}l=c}return s}catch{return!1}}function Jo(o,e){let t=ce.resolve(o),n=ce.resolve(e);if(!Ko(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=ce.dirname(t),s=Wo(r),i=n;try{Ie.existsSync(n)&&(i=Ie.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=Ie.realpathSync.native(s);if(a!==i&&!a.startsWith(i+ce.sep))throw new Error(`Path '${o}' would be created outside workspace via symlinked parent directory`)}catch(a){throw a instanceof Error&&a.message.includes("symlinked parent")?a:new Error(`Could not validate path '${o}' is within workspace`)}}function je(o,e){if(!Ko(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function On(o,e,t,n=!1){let r=o.startsWith("~")?Pt.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Pt.isAbsolute(r)?r:e?Pt.join(e,r):r,i=Pt.resolve(s);if(t)try{n?Jo(i,t):je(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var In=class extends W{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="read_file";description="Read the contents of a file at the given path.";parameters={type:"object",properties:{path:{type:"string",description:"The file path to read"}},required:["path"]};async execute(t,n){try{let r=On(String(t.path),this.workspace,this.allowedDir);return we.existsSync(r)?we.statSync(r).isFile()?we.readFileSync(r,"utf8"):`Error: Not a file: ${String(t.path)}`:`Error: File not found: ${String(t.path)}`}catch(r){return`Error reading file: ${String(r)}`}}},_n=class extends W{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="write_file";description="Write content to a file at the given path. Creates parent directories if needed.";parameters={type:"object",properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]};async execute(t,n){try{let r=On(String(t.path),this.workspace,this.allowedDir,!0);we.mkdirSync(Pt.dirname(r),{recursive:!0});let s=String(t.content??"");return we.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},Mn=class extends W{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="edit_file";description="Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file.";parameters={type:"object",properties:{path:{type:"string"},old_text:{type:"string"},new_text:{type:"string"}},required:["path","old_text","new_text"]};async execute(t,n){try{let r=On(String(t.path),this.workspace,this.allowedDir,!0);if(!we.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=we.readFileSync(r,"utf8"),i=String(t.old_text??""),a=String(t.new_text??"");return s.includes(i)?s.split(i).length-1>1?`Warning: old_text appears ${s.split(i).length-1} times. Please provide more context to make it unique.`:(we.writeFileSync(r,s.replace(i,a),"utf8"),`Successfully edited ${r}`):`Error: old_text not found in ${String(t.path)}. Verify the file content.`}catch(r){return`Error editing file: ${String(r)}`}}},$n=class extends W{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="list_dir";description="List the contents of a directory.";parameters={type:"object",properties:{path:{type:"string"}},required:["path"]};async execute(t,n){try{let r=On(String(t.path),this.workspace,this.allowedDir);if(!we.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!we.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=we.readdirSync(r).sort().map(i=>{let a=Pt.join(r,i);return`${we.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
148
- `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var Ln=class extends W{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,u=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${u}`:u}catch(c){return`Error sending message: ${String(c)}`}}};import qr from"node:path";pt();var Dn=class extends W{constructor(t=60,n,r=!1,s="",i=new ye,a,l=!1){super();this.timeout=t;this.workingDir=n;this.restrictToWorkspace=r;this.pathAppend=s;this.runner=i;this.rtkService=a;this.rtkUltraCompact=l}name="exec";description="Execute a shell command and return its output. Use with caution.";parameters={type:"object",properties:{command:{type:"string",description:"The shell command to execute"},working_dir:{type:"string",description:"Optional working directory for the command"}},required:["command"]};guard(t,n){let r=t.toLowerCase();if([/\brm\s+-[rf]{1,2}\b/,/\bdel\s+\/[fq]\b/,/\brmdir\s+\/s\b/,/(?:^|[;&|]\s*)format\b/,/\b(mkfs|diskpart)\b/,/\bdd\s+if=/,/>\s*\/dev\/sd/,/\b(shutdown|reboot|poweroff)\b/,/:\(\)\s*\{.*\};\s*:/].some(i=>i.test(r)))return"Error: Command blocked by safety guard (dangerous pattern detected)";if(this.restrictToWorkspace){if(t.includes("../")||t.includes("..\\"))return"Error: Command blocked by safety guard (path traversal detected)";let i=t.match(/[A-Za-z]:\\[^\s"']+/g)??[];for(let a of i){let l=qr.resolve(a),c=qr.resolve(n);if(!l.startsWith(c))return"Error: Command blocked by safety guard (path outside working dir)"}}return null}async execute(t,n){let r=String(t.command??""),s=String(t.working_dir??this.workingDir??process.cwd()),i=this.guard(r,s);if(i)return i;Y(n?.signal);let a=mt("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${qr.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let u=await this.runner.run(c);if(u.status==="aborted")throw Xt();if(u.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let g=u.stdout?`${u.stdout}${u.status==="failed"?`
149
- `:""}`:"";if(this.rtkService?.getRuntime().available&&g)try{let b=await this.rtkService.compress({command:r,stdout:g,stderr:u.stderr,exitCode:u.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(g=b.stdout)}catch{}let h=u.stderr.trim()?`STDERR:
150
- ${u.stderr}
151
- `:"",T=u.status==="failed"&&typeof u.exitCode=="number"?`
152
- Exit code: ${u.exitCode}`:"",v=u.status==="failed"&&u.signal?`
153
- Signal: ${u.signal}`:"",d=`${g}${h}${T}${v}`.trim();return d?d.length>1e4?`${d.slice(0,1e4)}
154
- ... (truncated, ${d.length-1e4} more chars)`:d:u.status==="failed"?u.errorMessage?`Error executing command: ${u.errorMessage}`:"Error executing command":"(no output)"}};var Nn=class extends W{constructor(t){super();this.manager=t}name="spawn";description="Spawn a subagent to handle a task in the background.";parameters={type:"object",properties:{task:{type:"string",description:"The task for the subagent to complete"},label:{type:"string",description:"Optional short label"},model:{type:"string",description:"Optional model override (e.g. 'anthropic/claude-sonnet-4'). Falls back to subagent config or global default if omitted."},provider:{type:"string",description:"Optional provider override (e.g. 'openai'). Falls back to subagent config or global default if omitted."}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";setContext(t,n,r=`${t}:${n}`){this.originChannel=t,this.originChatId=n,this.sessionKey=r}async execute(t,n){let r={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey};return t.model!=null&&(r.model=String(t.model)),t.provider!=null&&(r.providerName=String(t.provider)),this.manager.spawn(r)}};var jn=class extends W{name="session.search";description="Search the current session's message history for content matching the query.";parameters={type:"object",properties:{query:{type:"string",description:"The search query to match against message content"},limit:{type:"integer",description:"Maximum number of results to return",minimum:1,maximum:100}},required:["query"]};sessionManager=null;sessionKey="cli:direct";constructor(){super()}setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e,t){if(!this.sessionManager)return"Error: Session manager not available";let n=String(e.query??""),r=typeof e.limit=="number"?Math.min(Math.max(1,Math.floor(e.limit)),100):10;if(!n)return"Error: Query cannot be empty";let i=this.sessionManager.getOrCreate(this.sessionKey).search(n,r);return JSON.stringify(i,null,2)}};var Fn=class extends W{name="session.info";description="Returns information about the current session: message count, token estimate, last anchor name, and messages since last anchor.";parameters={type:"object",properties:{},required:[]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=this.sessionManager.getOrCreate(this.sessionKey),n=t.getHistory(1e3),r=0;for(let l of n)r+=gt.estimateMessageTokens(l);let s=t.getLastAnchor(),i=t.getMessagesSinceLastAnchor().length,a={messageCount:t.messages.length,tokenEstimate:r,lastAnchor:s?.name??null,messagesSinceAnchor:i};return JSON.stringify(a,null,2)}};var Bn=class extends W{name="session.anchor";description="Create a named anchor in the session. Messages before the anchor become eligible for summarization. Anchors survive consolidation.";parameters={type:"object",properties:{name:{type:"string",description:"The name of the anchor"},summary:{type:"string",description:"Optional summary describing what happened before this anchor"}},required:["name"]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=String(e.name??"");if(!t)return"Error: Anchor name is required";let n=e.summary!=null?String(e.summary):void 0,s=this.sessionManager.getOrCreate(this.sessionKey).anchor(t,n);return JSON.stringify({success:!0,anchor:{name:s.name,summary:s.summary,timestamp:s.timestamp}},null,2)}};import{readFileSync as Li,existsSync as Di}from"node:fs";import{join as Q}from"node:path";import Ni from"node:http";import{homedir as ji}from"node:os";import Fi from"node:net";import Vo from"ws";var Bi={existsSync:Di,readFileSync:Li},zo=Bi;var Ui=Ni,Xo=Ui;var Gi=1;var Wi="/tmp/chrome-debug-profile";function Ki(o){let e=o??process.platform,t=ji(),n=Q(Wi,"DevToolsActivePort");switch(e){case"darwin":return[n,Q(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),Q(t,"Library/Application Support/Chromium/DevToolsActivePort"),Q(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),Q(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),Q(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||Q(t,".config");return[n,Q(r,"google-chrome","DevToolsActivePort"),Q(r,"chromium","DevToolsActivePort"),Q(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),Q(r,"microsoft-edge","DevToolsActivePort"),Q(r,"vivaldi","DevToolsActivePort"),Q(t,".config","google-chrome","DevToolsActivePort"),Q(t,".config","chromium","DevToolsActivePort"),Q(t,"snap","chromium","common","chromium","DevToolsActivePort"),Q(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),Q(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||Q(t,"AppData","Local");return[n,Q(r,"Google","Chrome","User Data","DevToolsActivePort"),Q(r,"Chromium","User Data","DevToolsActivePort"),Q(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),Q(r,"Microsoft","Edge","User Data","DevToolsActivePort"),Q(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function Gn(o){return Wn(o)?.port}function Wn(o){let e=Ki(o);for(let t of e)try{if(!zo.existsSync(t))continue;let r=zo.readFileSync(t,"utf-8").split(`
155
- `),s=r[0]?.trim(),i=r[1]?.trim()||void 0;if(s){let a=parseInt(s,10);if(a>0&&a<=65535)return{port:a,browserWsPath:i}}}catch{}}function Ji(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=Xo.get(t,{timeout:5e3},r=>{if(r.statusCode!==200){r.resume(),e(void 0);return}let s=[];r.on("data",i=>s.push(i)),r.on("end",()=>{try{let i=Buffer.concat(s).toString("utf-8"),a=JSON.parse(i);e(a)}catch{e(void 0)}}),r.on("error",()=>e(void 0))});n.on("timeout",()=>{n.destroy(),e(void 0)}),n.on("error",()=>e(void 0))})}function qi(o,e="127.0.0.1"){return new Promise(t=>{let n=new Fi.Socket;n.setTimeout(2e3),n.once("connect",()=>{n.destroy(),t(!0)}),n.once("timeout",()=>{n.destroy(),t(!1)}),n.once("error",()=>{t(!1)}),n.connect(o,e)})}function Hi(o){return new Promise(e=>{try{let t=new Vo(o),n=setTimeout(()=>{t.close(),e(!1)},3e3);t.on("open",()=>{clearTimeout(n),t.close(),e(!0)}),t.on("error",()=>{clearTimeout(n),e(!1)})}catch{e(!1)}})}async function It(o=9222){let e=Wn(),t=e?.port??o;if(await qi(t)){for(let r=0;r<2;r++){try{let s=await Ji(t);if(s)return{port:t,versionInfo:s}}catch{}r<1&&await new Promise(s=>setTimeout(s,500))}if(e?.browserWsPath){let r=`ws://127.0.0.1:${t}${e.browserWsPath}`;if(await Hi(r))return{port:t,versionInfo:{Browser:"Chrome","Protocol-Version":"1.3","User-Agent":"","V8-Version":"","WebKit-Version":"",webSocketDebuggerUrl:r}}}return new Promise(r=>{let s=Xo.get(`http://127.0.0.1:${t}/json/version`,{timeout:3e3},i=>{i.resume(),i.statusCode===404||i.statusCode===403?r({port:t,versionInfo:{},pendingApproval:!0}):r(void 0)});s.on("error",()=>r(void 0)),s.on("timeout",()=>{s.destroy(),r(void 0)})})}}async function Zt(o){let t=Wn()?.browserWsPath;if(!t)return[];let n=await Un.connect(`ws://127.0.0.1:${o}${t}`);try{return((await n.send("Target.getTargets")).targetInfos??[]).map(i=>({id:i.targetId,type:i.type,title:i.title,url:i.url,webSocketDebuggerUrl:i.webSocketDebuggerUrl??`ws://127.0.0.1:${o}/devtools/page/${i.targetId}`}))}finally{n.close()}}async function Yo(o,e){let n=Wn()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await Un.connect(`ws://127.0.0.1:${o}${n}`);try{let i=(await r.send("Target.createTarget",{url:e})).targetId;if(!i)throw new Error("Target.createTarget returned no targetId");return{id:i,type:"page",title:"",url:e,webSocketDebuggerUrl:`ws://127.0.0.1:${o}/devtools/page/${i}`}}finally{r.close()}}var Un=class o{ws;nextId=1;pending=new Map;eventListeners=new Map;closed=!1;constructor(e){this.ws=e}static connect(e){return new Promise((t,n)=>{let r=new Vo(e);r.on("open",()=>{let s=new o(r);o.attachHandlers(s,r),t(s)}),r.on("error",(...s)=>{let i=s[0];n(new Error(`Failed to connect to CDP: ${i.message}`))})})}static fromWebSocket(e){let t=new o(e);return o.attachHandlers(t,e),t}static attachHandlers(e,t){t.on("message",n=>{let r=typeof n=="string"?n:Buffer.from(n).toString("utf-8");e.handleMessage(r)}),t.on("close",()=>{e.closed=!0;for(let[,n]of e.pending)n.reject(new Error("WebSocket closed"));e.pending.clear()}),t.on("error",(...n)=>{let r=n[0];for(let[,s]of e.pending)s.reject(r);e.pending.clear()})}async send(e,t){if(this.closed||this.ws.readyState!==Gi)throw new Error("WebSocket is closed");let n=this.nextId++,r=JSON.stringify({id:n,method:e,params:t??{}});return new Promise((s,i)=>{this.pending.set(n,{resolve:s,reject:i}),this.ws.send(r)})}onEvent(e,t){return this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t),()=>{this.eventListeners.get(e)?.delete(t)}}waitForEvent(e,t=1e4){return new Promise((n,r)=>{let s=setTimeout(()=>{i(),r(new Error(`Timeout waiting for event '${e}' after ${t}ms`))},t),i=this.onEvent(e,a=>{clearTimeout(s),i(),n(a)})})}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}handleMessage(e){let t;try{t=JSON.parse(e)}catch{return}if("id"in t&&typeof t.id=="number"){let n=t,r=this.pending.get(n.id);r&&(this.pending.delete(n.id),n.error?r.reject(new Error(`CDP error ${n.error.code}: ${n.error.message}`)):r.resolve(n.result??{}));return}if("method"in t&&typeof t.method=="string"){let n=t,r=this.eventListeners.get(n.method);if(r)for(let s of r)try{s(n.params??{})}catch{}}}};import{spawn as zi}from"node:child_process";import{createConnection as Vi}from"node:net";import{tmpdir as Xi}from"node:os";import{join as Zo,dirname as Yi}from"node:path";import{unlink as Qi,unlinkSync as Zi,mkdirSync as ea,existsSync as Kn}from"node:fs";import ft from"node:fs";function _t(o){let e="electron"in process.versions,t=o;try{t=ft.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!ft.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!ft.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!0}else{let a=t+".js",l=t+".ts";if(ft.existsSync(a)){try{n=ft.realpathSync(a)}catch{n=a}r=!1}else if(ft.existsSync(l)){try{n=ft.realpathSync(l)}catch{n=l}r=!0}else throw new Error(`No executable found: neither ${a} nor ${l} exists.`)}let s=process.execPath,i=r?["--import","tsx",n]:[n];return e?{file:s,args:i,env:{...process.env,ELECTRON_RUN_AS_NODE:"1"}}:{file:s,args:i,env:process.env}}var ta=null,na=null,ra=null,oa=!1;function en(){return na??process.platform}function sa(){return ta??zi}function ia(){return ra??Vi}function aa(o,e){let t=en(),n=e??Xi(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:Zo(n,`airclaw-daemon-${r}.sock`)}function Qo(o,e){let t=o.split(`
156
- `),n=t.pop()??"";for(let r of t){let s=r.trim();if(s)try{let i=JSON.parse(s);e(i)}catch{}}return n}var Mt=class o{static instance=null;daemons=new Map;constructor(){}static getInstance(){return o.instance||(o.instance=new o),o.instance}async getOrCreateDaemon(e,t,n){if(this.daemons.has(e))return;let r=aa(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(en()==="win32"||Kn(r)){let T={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,T);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),en()!=="win32"&&Kn(r))try{Zi(r)}catch{}}}let i=Yi(r);if(!Kn(i)&&en()!=="win32")try{ea(i,{recursive:!0})}catch{}let a={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};if(this.daemons.set(e,a),oa)return;let l=Zo(import.meta.dirname,"daemon-worker"),{file:c,args:u,env:g}=_t(l),h=sa()(c,[...u,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:g});a.child=h,h.on("exit",()=>{this.cleanupDaemon(e)}),h.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((T,v)=>{let d=setTimeout(()=>{v(new Error("Daemon startup timeout"))},1e4),b=O=>{O.toString("utf8").includes("READY")&&(clearTimeout(d),h.stdout?.off("data",b),T())};h.stdout?.on("data",b)}),await this.connectToDaemon(e)}async connectToDaemon(e){let t=this.daemons.get(e);if(!t)throw new Error(`No daemon for target ${e}`);return new Promise((n,r)=>{let s=ia()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=Qo(t.ndjsonBuffer+i.toString("utf8"),a=>{let l=t.pendingCommands.get(a.id);l&&(t.pendingCommands.delete(a.id),l.resolve(a))})}),s.on("close",()=>{t.clientSocket=null;for(let[,i]of t.pendingCommands)i.reject(new Error("Daemon socket closed"));t.pendingCommands.clear()}),s.on("error",()=>{}),n()}),s.on("error",i=>{r(new Error(`Failed to connect to daemon: ${i.message}`))}),setTimeout(()=>{t.clientSocket||(s.destroy(),r(new Error("Daemon connection timeout")))},5e3)})}async sendCommand(e,t,n={}){let r=this.daemons.get(e);if(!r)throw new Error(`No daemon for target ${e}`);if(!r.clientSocket)throw new Error(`Daemon socket not connected for ${e}`);let s=r.commandId++,a=JSON.stringify({id:s,cmd:t,args:n})+`
157
- `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(u){r.pendingCommands.delete(s),c(u)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=Qo(n.ndjsonBuffer+r.toString("utf8"),s=>{let i=n.pendingCommands.get(s.id);i&&(n.pendingCommands.delete(s.id),i.resolve(s))})}),t.on("close",()=>{n.clientSocket=null;for(let[,r]of n.pendingCommands)r.reject(new Error("Daemon socket closed"));n.pendingCommands.clear()})))}cleanupDaemon(e){let t=this.daemons.get(e);if(t){t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM");for(let[,n]of t.pendingCommands)n.reject(new Error("Daemon stopped"));en()!=="win32"&&Kn(t.socketPath)&&Qi(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as la,mkdirSync as ca,existsSync as da}from"node:fs";import{dirname as ua,join as Jn}from"node:path";import{tmpdir as ga}from"node:os";var ht=class extends W{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
147
+ `)}`:"No scheduled jobs."}removeJob(t){return t?this.cron.removeJob(t)?`Removed job ${t}`:`Job ${t} not found`:"Error: job_id is required for remove"}};import Se from"node:fs";import Pt from"node:path";import _e from"node:fs";import ue from"node:path";function Jo(o){let e=ue.resolve(o);for(;e!=="/"&&e!==".";)try{return _e.lstatSync(e),e}catch{let t=ue.dirname(e);if(t===e)break;e=t}return e||"/"}function Ho(o,e){let t=ue.resolve(o),n=ue.resolve(e),r=n.endsWith(ue.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+ue.sep);if(!_e.existsSync(r))return s;try{let i=r;try{i=_e.realpathSync.native(r)}catch{}if(_e.existsSync(t)){let c=_e.realpathSync.native(t);return c===i||c.startsWith(i+ue.sep)}let a=Jo(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=_e.realpathSync.native(a);if(c===i||c.startsWith(i+ue.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=ue.dirname(l);if(c===l)break;try{if(_e.lstatSync(c).isSymbolicLink()){let p=_e.realpathSync.native(c);if(p!==i&&!p.startsWith(i+ue.sep))return!1}}catch{}l=c}return s}catch{return!1}}function zo(o,e){let t=ue.resolve(o),n=ue.resolve(e);if(!Ho(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=ue.dirname(t),s=Jo(r),i=n;try{_e.existsSync(n)&&(i=_e.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=_e.realpathSync.native(s);if(a!==i&&!a.startsWith(i+ue.sep))throw new Error(`Path '${o}' would be created outside workspace via symlinked parent directory`)}catch(a){throw a instanceof Error&&a.message.includes("symlinked parent")?a:new Error(`Could not validate path '${o}' is within workspace`)}}function Fe(o,e){if(!Ho(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function Ln(o,e,t,n=!1){let r=o.startsWith("~")?Pt.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Pt.isAbsolute(r)?r:e?Pt.join(e,r):r,i=Pt.resolve(s);if(t)try{n?zo(i,t):Fe(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var _n=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="read_file";description="Read the contents of a file at the given path.";parameters={type:"object",properties:{path:{type:"string",description:"The file path to read"}},required:["path"]};async execute(t,n){try{let r=Ln(String(t.path),this.workspace,this.allowedDir);return Se.existsSync(r)?Se.statSync(r).isFile()?Se.readFileSync(r,"utf8"):`Error: Not a file: ${String(t.path)}`:`Error: File not found: ${String(t.path)}`}catch(r){return`Error reading file: ${String(r)}`}}},Mn=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="write_file";description="Write content to a file at the given path. Creates parent directories if needed.";parameters={type:"object",properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]};async execute(t,n){try{let r=Ln(String(t.path),this.workspace,this.allowedDir,!0);Se.mkdirSync(Pt.dirname(r),{recursive:!0});let s=String(t.content??"");return Se.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},$n=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="edit_file";description="Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file.";parameters={type:"object",properties:{path:{type:"string"},old_text:{type:"string"},new_text:{type:"string"}},required:["path","old_text","new_text"]};async execute(t,n){try{let r=Ln(String(t.path),this.workspace,this.allowedDir,!0);if(!Se.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=Se.readFileSync(r,"utf8"),i=String(t.old_text??""),a=String(t.new_text??"");return s.includes(i)?s.split(i).length-1>1?`Warning: old_text appears ${s.split(i).length-1} times. Please provide more context to make it unique.`:(Se.writeFileSync(r,s.replace(i,a),"utf8"),`Successfully edited ${r}`):`Error: old_text not found in ${String(t.path)}. Verify the file content.`}catch(r){return`Error editing file: ${String(r)}`}}},On=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="list_dir";description="List the contents of a directory.";parameters={type:"object",properties:{path:{type:"string"}},required:["path"]};async execute(t,n){try{let r=Ln(String(t.path),this.workspace,this.allowedDir);if(!Se.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!Se.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=Se.readdirSync(r).sort().map(i=>{let a=Pt.join(r,i);return`${Se.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
148
+ `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var Dn=class extends G{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,d=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${d}`:d}catch(c){return`Error sending message: ${String(c)}`}}};import Hr from"node:path";ft();var Nn=class extends G{constructor(t=60,n,r=!1,s="",i=new be,a,l=!1){super();this.timeout=t;this.workingDir=n;this.restrictToWorkspace=r;this.pathAppend=s;this.runner=i;this.rtkService=a;this.rtkUltraCompact=l}name="exec";description="Execute a shell command and return its output. Use with caution.";parameters={type:"object",properties:{command:{type:"string",description:"The shell command to execute"},working_dir:{type:"string",description:"Optional working directory for the command"}},required:["command"]};guard(t,n){let r=t.toLowerCase();if([/\brm\s+-[rf]{1,2}\b/,/\bdel\s+\/[fq]\b/,/\brmdir\s+\/s\b/,/(?:^|[;&|]\s*)format\b/,/\b(mkfs|diskpart)\b/,/\bdd\s+if=/,/>\s*\/dev\/sd/,/\b(shutdown|reboot|poweroff)\b/,/:\(\)\s*\{.*\};\s*:/].some(i=>i.test(r)))return"Error: Command blocked by safety guard (dangerous pattern detected)";if(this.restrictToWorkspace){if(t.includes("../")||t.includes("..\\"))return"Error: Command blocked by safety guard (path traversal detected)";let i=t.match(/[A-Za-z]:\\[^\s"']+/g)??[];for(let a of i){let l=Hr.resolve(a),c=Hr.resolve(n);if(!l.startsWith(c))return"Error: Command blocked by safety guard (path outside working dir)"}}return null}async execute(t,n){let r=String(t.command??""),s=String(t.working_dir??this.workingDir??process.cwd()),i=this.guard(r,s);if(i)return i;Y(n?.signal);let a=pt("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${Hr.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let d=await this.runner.run(c);if(d.status==="aborted")throw Xt();if(d.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=d.stdout?`${d.stdout}${d.status==="failed"?`
149
+ `:""}`:"";if(this.rtkService?.getRuntime().available&&p)try{let b=await this.rtkService.compress({command:r,stdout:p,stderr:d.stderr,exitCode:d.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(p=b.stdout)}catch{}let h=d.stderr.trim()?`STDERR:
150
+ ${d.stderr}
151
+ `:"",w=d.status==="failed"&&typeof d.exitCode=="number"?`
152
+ Exit code: ${d.exitCode}`:"",v=d.status==="failed"&&d.signal?`
153
+ Signal: ${d.signal}`:"",u=`${p}${h}${w}${v}`.trim();return u?u.length>1e4?`${u.slice(0,1e4)}
154
+ ... (truncated, ${u.length-1e4} more chars)`:u:d.status==="failed"?d.errorMessage?`Error executing command: ${d.errorMessage}`:"Error executing command":"(no output)"}};var jn=class extends G{constructor(t){super();this.manager=t}name="spawn";description="Spawn a subagent to handle a task in the background.";parameters={type:"object",properties:{task:{type:"string",description:"The task for the subagent to complete"},label:{type:"string",description:"Optional short label"},model:{type:"string",description:"Optional model override (e.g. 'anthropic/claude-sonnet-4'). Falls back to subagent config or global default if omitted."},provider:{type:"string",description:"Optional provider override (e.g. 'openai'). Falls back to subagent config or global default if omitted."}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";setContext(t,n,r=`${t}:${n}`){this.originChannel=t,this.originChatId=n,this.sessionKey=r}async execute(t,n){let r={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey};return t.model!=null&&(r.model=String(t.model)),t.provider!=null&&(r.providerName=String(t.provider)),this.manager.spawn(r)}};var Fn=class extends G{name="session.search";description="Search the current session's message history for content matching the query.";parameters={type:"object",properties:{query:{type:"string",description:"The search query to match against message content"},limit:{type:"integer",description:"Maximum number of results to return",minimum:1,maximum:100}},required:["query"]};sessionManager=null;sessionKey="cli:direct";constructor(){super()}setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e,t){if(!this.sessionManager)return"Error: Session manager not available";let n=String(e.query??""),r=typeof e.limit=="number"?Math.min(Math.max(1,Math.floor(e.limit)),100):10;if(!n)return"Error: Query cannot be empty";let i=this.sessionManager.getOrCreate(this.sessionKey).search(n,r);return JSON.stringify(i,null,2)}};var Bn=class extends G{name="session.info";description="Returns information about the current session: message count, token estimate, last anchor name, and messages since last anchor.";parameters={type:"object",properties:{},required:[]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=this.sessionManager.getOrCreate(this.sessionKey),n=t.getHistory(1e3),r=0;for(let l of n)r+=mt.estimateMessageTokens(l);let s=t.getLastAnchor(),i=t.getMessagesSinceLastAnchor().length,a={messageCount:t.messages.length,tokenEstimate:r,lastAnchor:s?.name??null,messagesSinceAnchor:i};return JSON.stringify(a,null,2)}};var Gn=class extends G{name="session.anchor";description="Create a named anchor in the session. Messages before the anchor become eligible for summarization. Anchors survive consolidation.";parameters={type:"object",properties:{name:{type:"string",description:"The name of the anchor"},summary:{type:"string",description:"Optional summary describing what happened before this anchor"}},required:["name"]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=String(e.name??"");if(!t)return"Error: Anchor name is required";let n=e.summary!=null?String(e.summary):void 0,s=this.sessionManager.getOrCreate(this.sessionKey).anchor(t,n);return JSON.stringify({success:!0,anchor:{name:s.name,summary:s.summary,timestamp:s.timestamp}},null,2)}};import{readFileSync as Gi,existsSync as Ui}from"node:fs";import{join as Z}from"node:path";import Wi from"node:http";import{homedir as Ki}from"node:os";import qi from"node:net";import Qo from"ws";var Ji={existsSync:Ui,readFileSync:Gi},Yo=Ji;var Hi=Wi,Zo=Hi;var zi=1;var Vi="/tmp/chrome-debug-profile";function Xi(o){let e=o??process.platform,t=Ki(),n=Z(Vi,"DevToolsActivePort");switch(e){case"darwin":return[n,Z(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),Z(t,"Library/Application Support/Chromium/DevToolsActivePort"),Z(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),Z(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),Z(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||Z(t,".config");return[n,Z(r,"google-chrome","DevToolsActivePort"),Z(r,"chromium","DevToolsActivePort"),Z(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),Z(r,"microsoft-edge","DevToolsActivePort"),Z(r,"vivaldi","DevToolsActivePort"),Z(t,".config","google-chrome","DevToolsActivePort"),Z(t,".config","chromium","DevToolsActivePort"),Z(t,"snap","chromium","common","chromium","DevToolsActivePort"),Z(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),Z(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||Z(t,"AppData","Local");return[n,Z(r,"Google","Chrome","User Data","DevToolsActivePort"),Z(r,"Chromium","User Data","DevToolsActivePort"),Z(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),Z(r,"Microsoft","Edge","User Data","DevToolsActivePort"),Z(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function Wn(o){return Kn(o)?.port}function Kn(o){let e=Xi(o);for(let t of e)try{if(!Yo.existsSync(t))continue;let r=Yo.readFileSync(t,"utf-8").split(`
155
+ `),s=r[0]?.trim(),i=r[1]?.trim()||void 0;if(s){let a=parseInt(s,10);if(a>0&&a<=65535)return{port:a,browserWsPath:i}}}catch{}}function Yi(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=Zo.get(t,{timeout:5e3},r=>{if(r.statusCode!==200){r.resume(),e(void 0);return}let s=[];r.on("data",i=>s.push(i)),r.on("end",()=>{try{let i=Buffer.concat(s).toString("utf-8"),a=JSON.parse(i);e(a)}catch{e(void 0)}}),r.on("error",()=>e(void 0))});n.on("timeout",()=>{n.destroy(),e(void 0)}),n.on("error",()=>e(void 0))})}function Qi(o,e="127.0.0.1"){return new Promise(t=>{let n=new qi.Socket;n.setTimeout(2e3),n.once("connect",()=>{n.destroy(),t(!0)}),n.once("timeout",()=>{n.destroy(),t(!1)}),n.once("error",()=>{t(!1)}),n.connect(o,e)})}function Zi(o){return new Promise(e=>{try{let t=new Qo(o),n=setTimeout(()=>{t.close(),e(!1)},3e3);t.on("open",()=>{clearTimeout(n),t.close(),e(!0)}),t.on("error",()=>{clearTimeout(n),e(!1)})}catch{e(!1)}})}async function It(o=9222){let e=Kn(),t=e?.port??o;if(await Qi(t)){for(let r=0;r<2;r++){try{let s=await Yi(t);if(s)return{port:t,versionInfo:s}}catch{}r<1&&await new Promise(s=>setTimeout(s,500))}if(e?.browserWsPath){let r=`ws://127.0.0.1:${t}${e.browserWsPath}`;if(await Zi(r))return{port:t,versionInfo:{Browser:"Chrome","Protocol-Version":"1.3","User-Agent":"","V8-Version":"","WebKit-Version":"",webSocketDebuggerUrl:r}}}return new Promise(r=>{let s=Zo.get(`http://127.0.0.1:${t}/json/version`,{timeout:3e3},i=>{i.resume(),i.statusCode===404||i.statusCode===403?r({port:t,versionInfo:{},pendingApproval:!0}):r(void 0)});s.on("error",()=>r(void 0)),s.on("timeout",()=>{s.destroy(),r(void 0)})})}}async function Zt(o){let t=Kn()?.browserWsPath;if(!t)return[];let n=await Un.connect(`ws://127.0.0.1:${o}${t}`);try{return((await n.send("Target.getTargets")).targetInfos??[]).map(i=>({id:i.targetId,type:i.type,title:i.title,url:i.url,webSocketDebuggerUrl:i.webSocketDebuggerUrl??`ws://127.0.0.1:${o}/devtools/page/${i.targetId}`}))}finally{n.close()}}async function es(o,e){let n=Kn()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await Un.connect(`ws://127.0.0.1:${o}${n}`);try{let i=(await r.send("Target.createTarget",{url:e})).targetId;if(!i)throw new Error("Target.createTarget returned no targetId");return{id:i,type:"page",title:"",url:e,webSocketDebuggerUrl:`ws://127.0.0.1:${o}/devtools/page/${i}`}}finally{r.close()}}var Un=class o{ws;nextId=1;pending=new Map;eventListeners=new Map;closed=!1;constructor(e){this.ws=e}static connect(e){return new Promise((t,n)=>{let r=new Qo(e);r.on("open",()=>{let s=new o(r);o.attachHandlers(s,r),t(s)}),r.on("error",(...s)=>{let i=s[0];n(new Error(`Failed to connect to CDP: ${i.message}`))})})}static fromWebSocket(e){let t=new o(e);return o.attachHandlers(t,e),t}static attachHandlers(e,t){t.on("message",n=>{let r=typeof n=="string"?n:Buffer.from(n).toString("utf-8");e.handleMessage(r)}),t.on("close",()=>{e.closed=!0;for(let[,n]of e.pending)n.reject(new Error("WebSocket closed"));e.pending.clear()}),t.on("error",(...n)=>{let r=n[0];for(let[,s]of e.pending)s.reject(r);e.pending.clear()})}async send(e,t){if(this.closed||this.ws.readyState!==zi)throw new Error("WebSocket is closed");let n=this.nextId++,r=JSON.stringify({id:n,method:e,params:t??{}});return new Promise((s,i)=>{this.pending.set(n,{resolve:s,reject:i}),this.ws.send(r)})}onEvent(e,t){return this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t),()=>{this.eventListeners.get(e)?.delete(t)}}waitForEvent(e,t=1e4){return new Promise((n,r)=>{let s=setTimeout(()=>{i(),r(new Error(`Timeout waiting for event '${e}' after ${t}ms`))},t),i=this.onEvent(e,a=>{clearTimeout(s),i(),n(a)})})}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}handleMessage(e){let t;try{t=JSON.parse(e)}catch{return}if("id"in t&&typeof t.id=="number"){let n=t,r=this.pending.get(n.id);r&&(this.pending.delete(n.id),n.error?r.reject(new Error(`CDP error ${n.error.code}: ${n.error.message}`)):r.resolve(n.result??{}));return}if("method"in t&&typeof t.method=="string"){let n=t,r=this.eventListeners.get(n.method);if(r)for(let s of r)try{s(n.params??{})}catch{}}}};import{spawn as ea}from"node:child_process";import{createConnection as ta}from"node:net";import{tmpdir as na}from"node:os";import{join as ns,dirname as ra}from"node:path";import{unlink as oa,unlinkSync as sa,mkdirSync as ia,existsSync as qn}from"node:fs";import ht from"node:fs";function _t(o){let e="electron"in process.versions,t=o;try{t=ht.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!ht.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!ht.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!0}else{let a=t+".js",l=t+".ts";if(ht.existsSync(a)){try{n=ht.realpathSync(a)}catch{n=a}r=!1}else if(ht.existsSync(l)){try{n=ht.realpathSync(l)}catch{n=l}r=!0}else throw new Error(`No executable found: neither ${a} nor ${l} exists.`)}let s=process.execPath,i=r?["--import","tsx",n]:[n];return e?{file:s,args:i,env:{...process.env,ELECTRON_RUN_AS_NODE:"1"}}:{file:s,args:i,env:process.env}}var aa=null,la=null,ca=null,da=!1;function en(){return la??process.platform}function ua(){return aa??ea}function ga(){return ca??ta}function ma(o,e){let t=en(),n=e??na(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:ns(n,`airclaw-daemon-${r}.sock`)}function ts(o,e){let t=o.split(`
156
+ `),n=t.pop()??"";for(let r of t){let s=r.trim();if(s)try{let i=JSON.parse(s);e(i)}catch{}}return n}var Mt=class o{static instance=null;daemons=new Map;constructor(){}static getInstance(){return o.instance||(o.instance=new o),o.instance}async getOrCreateDaemon(e,t,n){if(this.daemons.has(e))return;let r=ma(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(en()==="win32"||qn(r)){let w={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,w);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),en()!=="win32"&&qn(r))try{sa(r)}catch{}}}let i=ra(r);if(!qn(i)&&en()!=="win32")try{ia(i,{recursive:!0})}catch{}let a={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};if(this.daemons.set(e,a),da)return;let l=ns(import.meta.dirname,"daemon-worker"),{file:c,args:d,env:p}=_t(l),h=ua()(c,[...d,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=h,h.on("exit",()=>{this.cleanupDaemon(e)}),h.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((w,v)=>{let u=setTimeout(()=>{v(new Error("Daemon startup timeout"))},1e4),b=P=>{P.toString("utf8").includes("READY")&&(clearTimeout(u),h.stdout?.off("data",b),w())};h.stdout?.on("data",b)}),await this.connectToDaemon(e)}async connectToDaemon(e){let t=this.daemons.get(e);if(!t)throw new Error(`No daemon for target ${e}`);return new Promise((n,r)=>{let s=ga()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=ts(t.ndjsonBuffer+i.toString("utf8"),a=>{let l=t.pendingCommands.get(a.id);l&&(t.pendingCommands.delete(a.id),l.resolve(a))})}),s.on("close",()=>{t.clientSocket=null;for(let[,i]of t.pendingCommands)i.reject(new Error("Daemon socket closed"));t.pendingCommands.clear()}),s.on("error",()=>{}),n()}),s.on("error",i=>{r(new Error(`Failed to connect to daemon: ${i.message}`))}),setTimeout(()=>{t.clientSocket||(s.destroy(),r(new Error("Daemon connection timeout")))},5e3)})}async sendCommand(e,t,n={}){let r=this.daemons.get(e);if(!r)throw new Error(`No daemon for target ${e}`);if(!r.clientSocket)throw new Error(`Daemon socket not connected for ${e}`);let s=r.commandId++,a=JSON.stringify({id:s,cmd:t,args:n})+`
157
+ `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(d){r.pendingCommands.delete(s),c(d)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=ts(n.ndjsonBuffer+r.toString("utf8"),s=>{let i=n.pendingCommands.get(s.id);i&&(n.pendingCommands.delete(s.id),i.resolve(s))})}),t.on("close",()=>{n.clientSocket=null;for(let[,r]of n.pendingCommands)r.reject(new Error("Daemon socket closed"));n.pendingCommands.clear()})))}cleanupDaemon(e){let t=this.daemons.get(e);if(t){t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM");for(let[,n]of t.pendingCommands)n.reject(new Error("Daemon stopped"));en()!=="win32"&&qn(t.socketPath)&&oa(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as pa,mkdirSync as fa,existsSync as ha}from"node:fs";import{dirname as ya,join as Jn}from"node:path";import{tmpdir as ba}from"node:os";var yt=class extends G{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
158
158
 
159
159
  Core Commands:
160
160
  - status: Check Chrome connectivity, version, and remote debugging status
@@ -189,7 +189,7 @@ Examples:
189
189
  - chrome_session clickxy --target "ABC123" --x 100 --y 200
190
190
  - chrome_session type --target "ABC123" --text "Hello World"
191
191
  - chrome_session loadall --target "ABC123" --selector "button.load-more" --interval 500
192
- - chrome_session evalraw --target "ABC123" --method "Page.getTitle" --params '{}'`;parameters={type:"object",properties:{command:{type:"string",description:"The command to execute",enum:["status","list","open","stop","snap","shot","eval","html","nav","net","click","clickxy","type","loadall","evalraw"]},target:{type:"string",description:"Target ID prefix (required for page interaction commands)"},url:{type:"string",description:"URL to open (for 'open' and 'nav' commands)"},path:{type:"string",description:"File path to save screenshot (for 'shot' command)"},selector:{type:"string",description:"CSS selector for element-specific operations (for 'shot', 'html', 'click', 'loadall' commands)"},expression:{type:"string",description:"JavaScript expression to evaluate (for 'eval' command)"},depth:{type:"number",description:"Maximum depth for accessibility tree (for 'snap' command)"},timeout:{type:"number",description:"Timeout in milliseconds (for 'nav' command)"},outer:{type:"boolean",description:"Return outer HTML (default true, for 'html' command)"},x:{type:"number",description:"X coordinate in CSS pixels (for 'clickxy' command)"},y:{type:"number",description:"Y coordinate in CSS pixels (for 'clickxy' command)"},text:{type:"string",description:"Text to type at focused element (for 'type' command)"},interval:{type:"number",description:"Interval in milliseconds between clicks (for 'loadall' command, default 500)"},method:{type:"string",description:"CDP method name (for 'evalraw' command)"},params:{type:"object",description:"CDP method parameters as JSON object (for 'evalraw' command)"}},required:["command"]};config;daemonManager;commands;workspace;restrictToWorkspace;constructor(e={},t,n=!1){super(),this.config={minChromeVersion:e.minChromeVersion??136,daemonIdleTimeoutS:e.daemonIdleTimeoutS??1200,targetPrefixLength:e.targetPrefixLength??8},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Mt.getInstance(),this.commands=new Map([["status",this.handleStatus.bind(this)],["list",this.handleList.bind(this)],["open",this.handleOpen.bind(this)],["stop",this.handleStop.bind(this)],["snap",this.handleSnap.bind(this)],["shot",this.handleShot.bind(this)],["eval",this.handleEval.bind(this)],["html",this.handleHtml.bind(this)],["nav",this.handleNav.bind(this)],["net",this.handleNet.bind(this)],["click",this.handleClick.bind(this)],["clickxy",this.handleClickxy.bind(this)],["type",this.handleType.bind(this)],["loadall",this.handleLoadall.bind(this)],["evalraw",this.handleEvalraw.bind(this)]])}async execute(e,t){let n=e.command;if(!n)return this.formatError("Missing required 'command' parameter. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw");let r=this.commands.get(n);if(!r)return this.formatError(`Unknown command '${n}'. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw`);try{return await r(e,t)}catch(s){let i=s instanceof Error?s.message:String(s);return this.formatError(`Command '${n}' failed: ${i}`)}}async handleStatus(){let e=this.config,t=await It();if(!t)return this.formatResult({available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or launch Chrome with --remote-debugging-port=9222"});if(t.pendingApproval)return this.formatResult({available:!1,pendingApproval:!0,reason:`Chrome is listening on port ${t.port} but remote debugging approval may be required`,hint:"Look for a remote debugging approval prompt in Chrome, or quit Chrome and relaunch with: open -a 'Google Chrome' --args --remote-debugging-port=9222",port:t.port});let{port:n,versionInfo:r}=t,s=r.Browser.match(/(\w+)\/(\d+)/),i=s?.[1]??"Chrome",a=s?parseInt(s[2],10):0;return a>0&&a<e.minChromeVersion?this.formatResult({available:!1,reason:`Chrome version ${a} is below minimum required version ${e.minChromeVersion}`,hint:`Update Chrome to version ${e.minChromeVersion} or higher`,version:r.Browser,port:n,browser:i}):this.formatResult({available:!0,version:r.Browser,protocolVersion:r["Protocol-Version"],userAgent:r["User-Agent"],webSocketDebuggerUrl:r.webSocketDebuggerUrl,port:n,browser:i})}async handleList(){let e=Gn();if(!e)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let t;try{let i=await fetch(`http://127.0.0.1:${e}/json/list`);i.ok?t=await i.json():t=await Zt(e)}catch{t=await Zt(e)}let n=t.filter(i=>i.type==="page"&&!i.url.startsWith("chrome://"));if(n.length===0)return this.formatResult({tabs:[],message:"No open tabs found"});let r=this.config.targetPrefixLength,s=n.map(i=>({id:i.id.slice(0,r),fullId:i.id,title:i.title,url:i.url}));return this.formatResult({tabs:s,count:s.length})}async handleOpen(e){let t=Gn();if(!t)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n=e.url??"about:blank",r=this.config.targetPrefixLength;try{let s=await fetch(`http://127.0.0.1:${t}/json/new?${n}`,{method:"PUT"});if(s.ok){let i=await s.json();return this.formatResult({success:!0,id:i.id.slice(0,r),fullId:i.id,url:i.url,message:`Opened new tab: ${i.url}`})}}catch{}try{let s=await Yo(t,n);return this.formatResult({success:!0,id:s.id.slice(0,r),fullId:s.id,url:s.url,message:`Opened new tab: ${s.url}`})}catch(s){return this.formatError(`Cannot open tab via HTTP or WebSocket on port ${t}: ${s instanceof Error?s.message:String(s)}. Run 'chrome_session status' for details.`)}}async handleStop(e){let t=e.target;if(t){let s=this.daemonManager.getActiveTargets().find(i=>i.toUpperCase().startsWith(t.toUpperCase()));return s?(this.daemonManager.stopDaemon(s),this.formatResult({success:!0,target:s.slice(0,this.config.targetPrefixLength),message:`Stopped daemon for target ${s.slice(0,this.config.targetPrefixLength)}`})):this.formatError(`No daemon found for target prefix '${t}'`)}let n=this.daemonManager.getActiveTargets().length;return n===0?this.formatResult({success:!0,message:"No active daemons to stop"}):(this.daemonManager.stopAll(),this.formatResult({success:!0,message:`Stopped ${n} daemon(s)`}))}async handleSnap(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.depth!==void 0&&(r.depth=e.depth);let s=await this.sendDaemonCommand(t,n,"snap",r);return s.ok?this.formatResult({tree:s.result?.tree,nodeCount:s.result?.nodeCount}):this.formatError(s.error??"Failed to get accessibility tree")}async handleShot(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.path,s=this.resolveScreenshotPath(r),i={};s&&(i.path=s),e.selector&&(i.selector=e.selector);let a=await this.sendDaemonCommand(t,n,"shot",i);return a.ok?(s&&a.result?.data&&this.saveScreenshot(s,a.result.data),this.formatResult({path:s,dpr:a.result?.dpr,viewport:a.result?.viewport,message:s?`Screenshot saved to ${s}`:"Screenshot captured (base64 data in 'data' field)",data:s?void 0:a.result?.data})):this.formatError(a.error??"Failed to capture screenshot")}async handleEval(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.expression;if(!r)return this.formatError("Missing required 'expression' parameter");let s=await this.sendDaemonCommand(t,n,"eval",{expression:r,awaitPromise:!0});return s.ok?this.formatResult({ok:!0,result:s.result?.result,type:s.result?.type,subtype:s.result?.subtype}):this.formatError(s.error??"JavaScript evaluation failed")}async handleHtml(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.selector&&(r.selector=e.selector),e.outer!==void 0&&(r.outer=e.outer);let s=await this.sendDaemonCommand(t,n,"html",r);return s.ok?this.formatResult({html:s.result?.html,selector:s.result?.selector}):this.formatError(s.error??"Failed to get HTML")}async handleNav(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.url;if(!r)return this.formatError("Missing required 'url' parameter");let s={url:r};e.timeout!==void 0&&(s.timeout=e.timeout);let i=await this.sendDaemonCommand(t,n,"nav",s);return i.ok?this.formatResult({ok:!0,url:i.result?.url,frameId:i.result?.frameId,loaderId:i.result?.loaderId,message:i.result?.message}):this.formatError(i.error??"Navigation failed")}async handleNet(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=await this.sendDaemonCommand(t,n,"net",{});return r.ok?this.formatResult({entries:r.result?.entries,count:r.result?.count}):this.formatError(r.error??"Failed to get network timing")}async handleClick(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.selector;if(!r)return this.formatError("Missing required 'selector' parameter");let s=await this.sendDaemonCommand(t,n,"click",{selector:r});return s.ok?this.formatResult({ok:!0,selector:r,tag:s.result?.tag,text:s.result?.text,message:s.result?.message}):this.formatError(s.error??"Click failed")}async handleClickxy(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.x,s=e.y;if(typeof r!="number"||typeof s!="number")return this.formatError("Missing required 'x' and 'y' parameters");let i=await this.sendDaemonCommand(t,n,"clickxy",{x:r,y:s});return i.ok?this.formatResult({ok:!0,x:r,y:s,message:`Clicked at (${r}, ${s})`}):this.formatError(i.error??"Click at coordinates failed")}async handleType(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.text;if(!r)return this.formatError("Missing required 'text' parameter");let s=await this.sendDaemonCommand(t,n,"type",{text:r});return s.ok?this.formatResult({ok:!0,text:r,message:`Typed ${r.length} character(s)`}):this.formatError(s.error??"Type failed")}async handleLoadall(e,t){let{targetId:n,wsUrl:r}=await this.resolveTarget(e.target),s=e.selector,i=e.interval??500;if(!s)return this.formatError("Missing required 'selector' parameter");let a=await this.sendDaemonCommand(n,r,"loadall",{selector:s,interval:i,timeout:3e5});return a.ok?this.formatResult({ok:!0,selector:s,clickCount:a.result?.clickCount,timedOut:a.result?.timedOut,message:a.result?.message}):this.formatError(a.error??"Loadall failed")}async handleEvalraw(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.method,s=e.params??{};if(!r)return this.formatError("Missing required 'method' parameter");let i=await this.sendDaemonCommand(t,n,"evalraw",{method:r,params:s});return i.ok?this.formatResult({ok:!0,method:r,result:i.result?.result}):this.formatError(i.error??"Raw CDP command failed")}async resolveTarget(e){if(!e)throw new Error("Missing required 'target' parameter. Use 'chrome_session list' to see available targets.");let t=Gn();if(!t)throw new Error("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n;try{let l=await fetch(`http://127.0.0.1:${t}/json/list`);l.ok?n=await l.json():n=await Zt(t)}catch{n=await Zt(t)}let r=n.filter(l=>l.type==="page"&&!l.url.startsWith("chrome://")),s=e.toUpperCase(),i=r.filter(l=>l.id.toUpperCase().startsWith(s));if(i.length===0)throw new Error(`No target found matching prefix '${e}'`);if(i.length>1){let l=i.map(c=>c.id.slice(0,this.config.targetPrefixLength)).join(", ");throw new Error(`Ambiguous prefix '${e}' matches ${i.length} targets: ${l}`)}let a=i[0];return{targetId:a.id,wsUrl:a.webSocketDebuggerUrl}}async sendDaemonCommand(e,t,n,r){return await this.daemonManager.getOrCreateDaemon(e,t,{idleTimeoutMs:this.config.daemonIdleTimeoutS*1e3}),this.daemonManager.sendCommand(e,n,r)}resolveScreenshotPath(e){if(!e)return;let t;if(e.startsWith("/")?t=e:e.startsWith("./")||e.startsWith("../")?this.restrictToWorkspace&&this.workspace?t=Jn(this.workspace,e):t=Jn(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=Jn(this.workspace,e):t=Jn(ga(),`airclaw-screenshot-${Date.now()}.png`),this.restrictToWorkspace&&this.workspace&&!t.startsWith(this.workspace))throw new Error(`Screenshot path '${e}' is outside workspace (restrictToWorkspace is enabled)`);return t}saveScreenshot(e,t){let n=ua(e);da(n)||ca(n,{recursive:!0});let r=Buffer.from(t,"base64");la(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var tn=class extends W{constructor(t){super();this.relay=t}name="chrome_relay";description="Control Chrome browser through the relay extension. Commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach.";parameters={type:"object",properties:{command:{type:"string",enum:["list_tabs","navigate","click","type","screenshot","read","evaluate","attach","detach"],description:"The command to execute"},tabId:{type:"number",description:"Tab ID for tab-specific commands"},url:{type:"string",description:"URL to navigate to"},selector:{type:"string",description:"CSS selector for click command"},text:{type:"string",description:"Text to type"},expression:{type:"string",description:"JavaScript expression to evaluate"},format:{type:"string",description:"Screenshot format (png or jpeg)"}},required:["command"]};async execute(t){let n=String(t.command??"");try{switch(n){case"list_tabs":{let r=await this.relay.listTabs();return JSON.stringify(r,null,2)}case"navigate":{let r=Number(t.tabId),s=String(t.url??"");return r?s?(await this.relay.navigate(r,s),`Navigated tab ${r} to ${s}`):"Error: url is required":"Error: tabId is required"}case"click":{let r=Number(t.tabId),s=String(t.selector??"");return r?s?(await this.relay.click(r,s),`Clicked "${s}" in tab ${r}`):"Error: selector is required":"Error: tabId is required"}case"type":{let r=Number(t.tabId),s=String(t.text??""),i=t.selector?String(t.selector):void 0;return r?s?(await this.relay.type(r,s,i),`Typed "${s}" in tab ${r}${i?` (selector: ${i})`:""}`):"Error: text is required":"Error: tabId is required"}case"screenshot":{let r=Number(t.tabId),s=String(t.format??"png");return r?`Screenshot captured: ${(await this.relay.screenshot(r,s)).slice(0,100)}...`:"Error: tabId is required"}case"read":{let r=Number(t.tabId);if(!r)return"Error: tabId is required";let s=await this.relay.evaluate(r,"document.body.innerText");return JSON.stringify(s,null,2)}case"evaluate":{let r=Number(t.tabId),s=String(t.expression??"");if(!r)return"Error: tabId is required";if(!s)return"Error: expression is required";let i=await this.relay.evaluate(r,s);return JSON.stringify(i,null,2)}case"attach":{let r=Number(t.tabId);return r?(await this.relay.attachTab(r),`Attached to tab ${r}`):"Error: tabId is required"}case"detach":{let r=Number(t.tabId);return r?(await this.relay.detachTab(r),`Detached from tab ${r}`):"Error: tabId is required"}default:return`Unknown command: ${n}. Available commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach`}}catch(r){return`Error: ${r instanceof Error?r.message:String(r)}`}}};import se from"node:fs";import nn from"node:path";import{randomUUID as ma}from"node:crypto";var pa="automations",fa="index.json";function ha(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function Hr(o){return nn.join(o,pa)}function es(o){return nn.join(Hr(o),fa)}function qn(o,e){return nn.join(Hr(o),e)}function zr(o,e){return nn.join(qn(o,e),"rule.json")}function Vr(o,e){return nn.join(qn(o,e),"script.js")}function Xr(o){let e=Hr(o);se.existsSync(e)||se.mkdirSync(e,{recursive:!0})}function Hn(o){Xr(o);let e=es(o);if(!se.existsSync(e))return{rules:[]};try{let t=se.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=Se(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=Se(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&zn(o,n),n}catch{return{rules:[]}}}function zn(o,e){Xr(o);let t=es(o),n=`${t}.tmp`;se.writeFileSync(n,JSON.stringify(e,null,2)),se.renameSync(n,t)}function $t(o){return Hn(o).rules}function Se(o,e){let t=zr(o,e);if(!se.existsSync(t))return null;try{let n=se.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Vr(o,e);return se.existsSync(s)&&(r.scriptContent=se.readFileSync(s,"utf-8")),r}catch{return null}}function Vn(o,e){Xr(o);let t=ha(e.name)||ma().slice(0,8),n=Date.now(),r={id:t,name:e.name,description:e.description,createdAt:n,updatedAt:n,enabled:!0,stepCount:e.steps.length,steps:e.steps,scriptPath:`automations/${t}/script.js`,tags:e.tags||[],source:e.source||"manual",...e.toolType?{toolType:e.toolType}:{},...e.variables?{variables:e.variables}:{}},s=qn(o,t);se.existsSync(s)||se.mkdirSync(s,{recursive:!0});let i=zr(o,t);se.writeFileSync(i,JSON.stringify(r,null,2));let a=ts(r),l=Vr(o,t);se.writeFileSync(l,a);let c=Hn(o),u={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(u.toolType=e.toolType),c.rules.push(u),zn(o,c),r}function Xn(o,e,t){let n=Se(o,e);if(!n)return null;let r=Date.now(),s={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:r,stepCount:(t.steps||n.steps).length},i=zr(o,e);if(se.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=ts(s),u=Vr(o,e);se.writeFileSync(u,c)}let a=Hn(o),l=a.rules.findIndex(c=>c.id===e);if(l>=0){let c={id:s.id,name:s.name,description:s.description,enabled:s.enabled,updatedAt:s.updatedAt,stepCount:s.steps.length};s.toolType&&(c.toolType=s.toolType),a.rules[l]=c,zn(o,a)}return s}function Ot(o,e){let t=qn(o,e);if(!se.existsSync(t))return!1;se.rmSync(t,{recursive:!0,force:!0});let n=Hn(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(zn(o,n),!0):!1}function ts(o){let e=new Date().toISOString();return`// Automation: ${o.name}
192
+ - chrome_session evalraw --target "ABC123" --method "Page.getTitle" --params '{}'`;parameters={type:"object",properties:{command:{type:"string",description:"The command to execute",enum:["status","list","open","stop","snap","shot","eval","html","nav","net","click","clickxy","type","loadall","evalraw"]},target:{type:"string",description:"Target ID prefix (required for page interaction commands)"},url:{type:"string",description:"URL to open (for 'open' and 'nav' commands)"},path:{type:"string",description:"File path to save screenshot (for 'shot' command)"},selector:{type:"string",description:"CSS selector for element-specific operations (for 'shot', 'html', 'click', 'loadall' commands)"},expression:{type:"string",description:"JavaScript expression to evaluate (for 'eval' command)"},depth:{type:"number",description:"Maximum depth for accessibility tree (for 'snap' command)"},timeout:{type:"number",description:"Timeout in milliseconds (for 'nav' command)"},outer:{type:"boolean",description:"Return outer HTML (default true, for 'html' command)"},x:{type:"number",description:"X coordinate in CSS pixels (for 'clickxy' command)"},y:{type:"number",description:"Y coordinate in CSS pixels (for 'clickxy' command)"},text:{type:"string",description:"Text to type at focused element (for 'type' command)"},interval:{type:"number",description:"Interval in milliseconds between clicks (for 'loadall' command, default 500)"},method:{type:"string",description:"CDP method name (for 'evalraw' command)"},params:{type:"object",description:"CDP method parameters as JSON object (for 'evalraw' command)"}},required:["command"]};config;daemonManager;commands;workspace;restrictToWorkspace;constructor(e={},t,n=!1){super(),this.config={minChromeVersion:e.minChromeVersion??136,daemonIdleTimeoutS:e.daemonIdleTimeoutS??1200,targetPrefixLength:e.targetPrefixLength??8},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Mt.getInstance(),this.commands=new Map([["status",this.handleStatus.bind(this)],["list",this.handleList.bind(this)],["open",this.handleOpen.bind(this)],["stop",this.handleStop.bind(this)],["snap",this.handleSnap.bind(this)],["shot",this.handleShot.bind(this)],["eval",this.handleEval.bind(this)],["html",this.handleHtml.bind(this)],["nav",this.handleNav.bind(this)],["net",this.handleNet.bind(this)],["click",this.handleClick.bind(this)],["clickxy",this.handleClickxy.bind(this)],["type",this.handleType.bind(this)],["loadall",this.handleLoadall.bind(this)],["evalraw",this.handleEvalraw.bind(this)]])}async execute(e,t){let n=e.command;if(!n)return this.formatError("Missing required 'command' parameter. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw");let r=this.commands.get(n);if(!r)return this.formatError(`Unknown command '${n}'. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw`);try{return await r(e,t)}catch(s){let i=s instanceof Error?s.message:String(s);return this.formatError(`Command '${n}' failed: ${i}`)}}async handleStatus(){let e=this.config,t=await It();if(!t)return this.formatResult({available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or launch Chrome with --remote-debugging-port=9222"});if(t.pendingApproval)return this.formatResult({available:!1,pendingApproval:!0,reason:`Chrome is listening on port ${t.port} but remote debugging approval may be required`,hint:"Look for a remote debugging approval prompt in Chrome, or quit Chrome and relaunch with: open -a 'Google Chrome' --args --remote-debugging-port=9222",port:t.port});let{port:n,versionInfo:r}=t,s=r.Browser.match(/(\w+)\/(\d+)/),i=s?.[1]??"Chrome",a=s?parseInt(s[2],10):0;return a>0&&a<e.minChromeVersion?this.formatResult({available:!1,reason:`Chrome version ${a} is below minimum required version ${e.minChromeVersion}`,hint:`Update Chrome to version ${e.minChromeVersion} or higher`,version:r.Browser,port:n,browser:i}):this.formatResult({available:!0,version:r.Browser,protocolVersion:r["Protocol-Version"],userAgent:r["User-Agent"],webSocketDebuggerUrl:r.webSocketDebuggerUrl,port:n,browser:i})}async handleList(){let e=Wn();if(!e)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let t;try{let i=await fetch(`http://127.0.0.1:${e}/json/list`);i.ok?t=await i.json():t=await Zt(e)}catch{t=await Zt(e)}let n=t.filter(i=>i.type==="page"&&!i.url.startsWith("chrome://"));if(n.length===0)return this.formatResult({tabs:[],message:"No open tabs found"});let r=this.config.targetPrefixLength,s=n.map(i=>({id:i.id.slice(0,r),fullId:i.id,title:i.title,url:i.url}));return this.formatResult({tabs:s,count:s.length})}async handleOpen(e){let t=Wn();if(!t)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n=e.url??"about:blank",r=this.config.targetPrefixLength;try{let s=await fetch(`http://127.0.0.1:${t}/json/new?${n}`,{method:"PUT"});if(s.ok){let i=await s.json();return this.formatResult({success:!0,id:i.id.slice(0,r),fullId:i.id,url:i.url,message:`Opened new tab: ${i.url}`})}}catch{}try{let s=await es(t,n);return this.formatResult({success:!0,id:s.id.slice(0,r),fullId:s.id,url:s.url,message:`Opened new tab: ${s.url}`})}catch(s){return this.formatError(`Cannot open tab via HTTP or WebSocket on port ${t}: ${s instanceof Error?s.message:String(s)}. Run 'chrome_session status' for details.`)}}async handleStop(e){let t=e.target;if(t){let s=this.daemonManager.getActiveTargets().find(i=>i.toUpperCase().startsWith(t.toUpperCase()));return s?(this.daemonManager.stopDaemon(s),this.formatResult({success:!0,target:s.slice(0,this.config.targetPrefixLength),message:`Stopped daemon for target ${s.slice(0,this.config.targetPrefixLength)}`})):this.formatError(`No daemon found for target prefix '${t}'`)}let n=this.daemonManager.getActiveTargets().length;return n===0?this.formatResult({success:!0,message:"No active daemons to stop"}):(this.daemonManager.stopAll(),this.formatResult({success:!0,message:`Stopped ${n} daemon(s)`}))}async handleSnap(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.depth!==void 0&&(r.depth=e.depth);let s=await this.sendDaemonCommand(t,n,"snap",r);return s.ok?this.formatResult({tree:s.result?.tree,nodeCount:s.result?.nodeCount}):this.formatError(s.error??"Failed to get accessibility tree")}async handleShot(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.path,s=this.resolveScreenshotPath(r),i={};s&&(i.path=s),e.selector&&(i.selector=e.selector);let a=await this.sendDaemonCommand(t,n,"shot",i);return a.ok?(s&&a.result?.data&&this.saveScreenshot(s,a.result.data),this.formatResult({path:s,dpr:a.result?.dpr,viewport:a.result?.viewport,message:s?`Screenshot saved to ${s}`:"Screenshot captured (base64 data in 'data' field)",data:s?void 0:a.result?.data})):this.formatError(a.error??"Failed to capture screenshot")}async handleEval(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.expression;if(!r)return this.formatError("Missing required 'expression' parameter");let s=await this.sendDaemonCommand(t,n,"eval",{expression:r,awaitPromise:!0});return s.ok?this.formatResult({ok:!0,result:s.result?.result,type:s.result?.type,subtype:s.result?.subtype}):this.formatError(s.error??"JavaScript evaluation failed")}async handleHtml(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.selector&&(r.selector=e.selector),e.outer!==void 0&&(r.outer=e.outer);let s=await this.sendDaemonCommand(t,n,"html",r);return s.ok?this.formatResult({html:s.result?.html,selector:s.result?.selector}):this.formatError(s.error??"Failed to get HTML")}async handleNav(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.url;if(!r)return this.formatError("Missing required 'url' parameter");let s={url:r};e.timeout!==void 0&&(s.timeout=e.timeout);let i=await this.sendDaemonCommand(t,n,"nav",s);return i.ok?this.formatResult({ok:!0,url:i.result?.url,frameId:i.result?.frameId,loaderId:i.result?.loaderId,message:i.result?.message}):this.formatError(i.error??"Navigation failed")}async handleNet(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=await this.sendDaemonCommand(t,n,"net",{});return r.ok?this.formatResult({entries:r.result?.entries,count:r.result?.count}):this.formatError(r.error??"Failed to get network timing")}async handleClick(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.selector;if(!r)return this.formatError("Missing required 'selector' parameter");let s=await this.sendDaemonCommand(t,n,"click",{selector:r});return s.ok?this.formatResult({ok:!0,selector:r,tag:s.result?.tag,text:s.result?.text,message:s.result?.message}):this.formatError(s.error??"Click failed")}async handleClickxy(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.x,s=e.y;if(typeof r!="number"||typeof s!="number")return this.formatError("Missing required 'x' and 'y' parameters");let i=await this.sendDaemonCommand(t,n,"clickxy",{x:r,y:s});return i.ok?this.formatResult({ok:!0,x:r,y:s,message:`Clicked at (${r}, ${s})`}):this.formatError(i.error??"Click at coordinates failed")}async handleType(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.text;if(!r)return this.formatError("Missing required 'text' parameter");let s=await this.sendDaemonCommand(t,n,"type",{text:r});return s.ok?this.formatResult({ok:!0,text:r,message:`Typed ${r.length} character(s)`}):this.formatError(s.error??"Type failed")}async handleLoadall(e,t){let{targetId:n,wsUrl:r}=await this.resolveTarget(e.target),s=e.selector,i=e.interval??500;if(!s)return this.formatError("Missing required 'selector' parameter");let a=await this.sendDaemonCommand(n,r,"loadall",{selector:s,interval:i,timeout:3e5});return a.ok?this.formatResult({ok:!0,selector:s,clickCount:a.result?.clickCount,timedOut:a.result?.timedOut,message:a.result?.message}):this.formatError(a.error??"Loadall failed")}async handleEvalraw(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.method,s=e.params??{};if(!r)return this.formatError("Missing required 'method' parameter");let i=await this.sendDaemonCommand(t,n,"evalraw",{method:r,params:s});return i.ok?this.formatResult({ok:!0,method:r,result:i.result?.result}):this.formatError(i.error??"Raw CDP command failed")}async resolveTarget(e){if(!e)throw new Error("Missing required 'target' parameter. Use 'chrome_session list' to see available targets.");let t=Wn();if(!t)throw new Error("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n;try{let l=await fetch(`http://127.0.0.1:${t}/json/list`);l.ok?n=await l.json():n=await Zt(t)}catch{n=await Zt(t)}let r=n.filter(l=>l.type==="page"&&!l.url.startsWith("chrome://")),s=e.toUpperCase(),i=r.filter(l=>l.id.toUpperCase().startsWith(s));if(i.length===0)throw new Error(`No target found matching prefix '${e}'`);if(i.length>1){let l=i.map(c=>c.id.slice(0,this.config.targetPrefixLength)).join(", ");throw new Error(`Ambiguous prefix '${e}' matches ${i.length} targets: ${l}`)}let a=i[0];return{targetId:a.id,wsUrl:a.webSocketDebuggerUrl}}async sendDaemonCommand(e,t,n,r){return await this.daemonManager.getOrCreateDaemon(e,t,{idleTimeoutMs:this.config.daemonIdleTimeoutS*1e3}),this.daemonManager.sendCommand(e,n,r)}resolveScreenshotPath(e){if(!e)return;let t;if(e.startsWith("/")?t=e:e.startsWith("./")||e.startsWith("../")?this.restrictToWorkspace&&this.workspace?t=Jn(this.workspace,e):t=Jn(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=Jn(this.workspace,e):t=Jn(ba(),`airclaw-screenshot-${Date.now()}.png`),this.restrictToWorkspace&&this.workspace&&!t.startsWith(this.workspace))throw new Error(`Screenshot path '${e}' is outside workspace (restrictToWorkspace is enabled)`);return t}saveScreenshot(e,t){let n=ya(e);ha(n)||fa(n,{recursive:!0});let r=Buffer.from(t,"base64");pa(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var tn=class extends G{constructor(t){super();this.relay=t}name="chrome_relay";description="Control Chrome browser through the relay extension. Commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach.";parameters={type:"object",properties:{command:{type:"string",enum:["list_tabs","navigate","click","type","screenshot","read","evaluate","attach","detach"],description:"The command to execute"},tabId:{type:"number",description:"Tab ID for tab-specific commands"},url:{type:"string",description:"URL to navigate to"},selector:{type:"string",description:"CSS selector for click command"},text:{type:"string",description:"Text to type"},expression:{type:"string",description:"JavaScript expression to evaluate"},format:{type:"string",description:"Screenshot format (png or jpeg)"}},required:["command"]};async execute(t){let n=String(t.command??"");try{switch(n){case"list_tabs":{let r=await this.relay.listTabs();return JSON.stringify(r,null,2)}case"navigate":{let r=Number(t.tabId),s=String(t.url??"");return r?s?(await this.relay.navigate(r,s),`Navigated tab ${r} to ${s}`):"Error: url is required":"Error: tabId is required"}case"click":{let r=Number(t.tabId),s=String(t.selector??"");return r?s?(await this.relay.click(r,s),`Clicked "${s}" in tab ${r}`):"Error: selector is required":"Error: tabId is required"}case"type":{let r=Number(t.tabId),s=String(t.text??""),i=t.selector?String(t.selector):void 0;return r?s?(await this.relay.type(r,s,i),`Typed "${s}" in tab ${r}${i?` (selector: ${i})`:""}`):"Error: text is required":"Error: tabId is required"}case"screenshot":{let r=Number(t.tabId),s=String(t.format??"png");return r?`Screenshot captured: ${(await this.relay.screenshot(r,s)).slice(0,100)}...`:"Error: tabId is required"}case"read":{let r=Number(t.tabId);if(!r)return"Error: tabId is required";let s=await this.relay.evaluate(r,"document.body.innerText");return JSON.stringify(s,null,2)}case"evaluate":{let r=Number(t.tabId),s=String(t.expression??"");if(!r)return"Error: tabId is required";if(!s)return"Error: expression is required";let i=await this.relay.evaluate(r,s);return JSON.stringify(i,null,2)}case"attach":{let r=Number(t.tabId);return r?(await this.relay.attachTab(r),`Attached to tab ${r}`):"Error: tabId is required"}case"detach":{let r=Number(t.tabId);return r?(await this.relay.detachTab(r),`Detached from tab ${r}`):"Error: tabId is required"}default:return`Unknown command: ${n}. Available commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach`}}catch(r){return`Error: ${r instanceof Error?r.message:String(r)}`}}};import se from"node:fs";import nn from"node:path";import{randomUUID as va}from"node:crypto";var wa="automations",Sa="index.json";function ka(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function zr(o){return nn.join(o,wa)}function rs(o){return nn.join(zr(o),Sa)}function Hn(o,e){return nn.join(zr(o),e)}function Vr(o,e){return nn.join(Hn(o,e),"rule.json")}function Xr(o,e){return nn.join(Hn(o,e),"script.js")}function Yr(o){let e=zr(o);se.existsSync(e)||se.mkdirSync(e,{recursive:!0})}function zn(o){Yr(o);let e=rs(o);if(!se.existsSync(e))return{rules:[]};try{let t=se.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=ke(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=ke(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&Vn(o,n),n}catch{return{rules:[]}}}function Vn(o,e){Yr(o);let t=rs(o),n=`${t}.tmp`;se.writeFileSync(n,JSON.stringify(e,null,2)),se.renameSync(n,t)}function $t(o){return zn(o).rules}function ke(o,e){let t=Vr(o,e);if(!se.existsSync(t))return null;try{let n=se.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Xr(o,e);return se.existsSync(s)&&(r.scriptContent=se.readFileSync(s,"utf-8")),r}catch{return null}}function Xn(o,e){Yr(o);let t=ka(e.name)||va().slice(0,8),n=Date.now(),r={id:t,name:e.name,description:e.description,createdAt:n,updatedAt:n,enabled:!0,stepCount:e.steps.length,steps:e.steps,scriptPath:`automations/${t}/script.js`,tags:e.tags||[],source:e.source||"manual",...e.toolType?{toolType:e.toolType}:{},...e.variables?{variables:e.variables}:{}},s=Hn(o,t);se.existsSync(s)||se.mkdirSync(s,{recursive:!0});let i=Vr(o,t);se.writeFileSync(i,JSON.stringify(r,null,2));let a=os(r),l=Xr(o,t);se.writeFileSync(l,a);let c=zn(o),d={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(d.toolType=e.toolType),c.rules.push(d),Vn(o,c),r}function Yn(o,e,t){let n=ke(o,e);if(!n)return null;let r=Date.now(),s={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:r,stepCount:(t.steps||n.steps).length},i=Vr(o,e);if(se.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=os(s),d=Xr(o,e);se.writeFileSync(d,c)}let a=zn(o),l=a.rules.findIndex(c=>c.id===e);if(l>=0){let c={id:s.id,name:s.name,description:s.description,enabled:s.enabled,updatedAt:s.updatedAt,stepCount:s.steps.length};s.toolType&&(c.toolType=s.toolType),a.rules[l]=c,Vn(o,a)}return s}function Ot(o,e){let t=Hn(o,e);if(!se.existsSync(t))return!1;se.rmSync(t,{recursive:!0,force:!0});let n=zn(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(Vn(o,n),!0):!1}function os(o){let e=new Date().toISOString();return`// Automation: ${o.name}
193
193
  // Tool: ${o.toolType??"auto-detect"}
194
194
  // Generated: ${e}
195
195
  // Description: ${o.description}
@@ -210,24 +210,24 @@ fetch(URL, { method: 'POST' })
210
210
  else console.error('Failed:', r.error);
211
211
  })
212
212
  .catch(e => console.error('Could not reach everclaw:', e.message));
213
- `}Oe();var ns={chrome_session:{navigate:"nav",click:"click",type:"type",screenshot:"shot",read:"snap",eval:"eval"},chrome_relay:{navigate:"navigate",click:"click",type:"type",screenshot:"screenshot",read:"read",eval:"evaluate"}},Yr=o=>new Promise(e=>setTimeout(e,o)),Lt=class extends W{constructor(t,n){super();this.browserTool=n;this.workspace=X(t)}name="automation";description="Manage browser automation workflows. Commands: list, get, save, delete, run.";parameters={type:"object",properties:{command:{type:"string",enum:["list","get","save","delete","run"],description:"The command to execute"},id:{type:"string",description:"Automation ID (for get, delete, run)"},name:{type:"string",description:"Automation name (for save)"},description:{type:"string",description:"Brief description (for save)"},steps:{type:"array",items:{type:"object",properties:{order:{type:"number"},action:{type:"string"},target:{type:"string"},value:{type:"string"},description:{type:"string"},optional:{type:"boolean"},assert:{type:"object",properties:{check:{type:"string",enum:["selector_exists","selector_text","url_contains","eval_truthy"]},value:{type:"string"},expected:{type:"string"},timeoutMs:{type:"number"}}},retries:{type:"number"},retryDelayMs:{type:"number"}}},description:"Automation steps (for save)"},tags:{type:"array",items:{type:"string"},description:"Optional tags (for save)"},enabled:{type:"boolean",description:"Enable/disable (for save)"},variables:{type:"object",description:'Variable overrides for run command (e.g., {"USERNAME": "user"})'}},required:["command"]};workspace;async execute(t,n){let r=String(t.command??"");try{switch(r){case"list":{let s=$t(this.workspace);return JSON.stringify(s,null,2)}case"get":{let s=String(t.id??"");if(!s)return"Error: id is required for get command";let i=Se(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let u=this.browserTool?.name,g;if(s){let h={name:i,description:a,steps:l,tags:c};return u&&(h.toolType=u),g=Xn(this.workspace,s,h),g?`Updated automation '${g.name}' (${g.id})`:`Error: Automation '${s}' not found for update`}else{let h={name:i,description:a,steps:l,tags:c,source:"conversation"};return u&&(h.toolType=u),g=Vn(this.workspace,h),`Created automation '${g.name}' (${g.id})`}}case"delete":{let s=String(t.id??"");return s?Ot(this.workspace,s)?`Deleted automation '${s}'`:`Error: Automation '${s}' not found or could not be deleted`:"Error: id is required for delete command"}case"run":{let s=String(t.id??"");if(!s)return"Error: id is required for run command";let i=Se(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),u=await this.executeStepWithRetries(c,n,i),g=this.maskSensitiveValues(u,t.variables);s.push(` -> ${g.slice(0,200)}${g.length>200?"...":""}`)}catch(c){let u=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${u}`);else return s.push(` -> FAILED: ${u}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
213
+ `}Le();var ss={chrome_session:{navigate:"nav",click:"click",type:"type",screenshot:"shot",read:"snap",eval:"eval"},chrome_relay:{navigate:"navigate",click:"click",type:"type",screenshot:"screenshot",read:"read",eval:"evaluate"}},Qr=o=>new Promise(e=>setTimeout(e,o)),Lt=class extends G{constructor(t,n){super();this.browserTool=n;this.workspace=V(t)}name="automation";description="Manage browser automation workflows. Commands: list, get, save, delete, run.";parameters={type:"object",properties:{command:{type:"string",enum:["list","get","save","delete","run"],description:"The command to execute"},id:{type:"string",description:"Automation ID (for get, delete, run)"},name:{type:"string",description:"Automation name (for save)"},description:{type:"string",description:"Brief description (for save)"},steps:{type:"array",items:{type:"object",properties:{order:{type:"number"},action:{type:"string"},target:{type:"string"},value:{type:"string"},description:{type:"string"},optional:{type:"boolean"},assert:{type:"object",properties:{check:{type:"string",enum:["selector_exists","selector_text","url_contains","eval_truthy"]},value:{type:"string"},expected:{type:"string"},timeoutMs:{type:"number"}}},retries:{type:"number"},retryDelayMs:{type:"number"}}},description:"Automation steps (for save)"},tags:{type:"array",items:{type:"string"},description:"Optional tags (for save)"},enabled:{type:"boolean",description:"Enable/disable (for save)"},variables:{type:"object",description:'Variable overrides for run command (e.g., {"USERNAME": "user"})'}},required:["command"]};workspace;async execute(t,n){let r=String(t.command??"");try{switch(r){case"list":{let s=$t(this.workspace);return JSON.stringify(s,null,2)}case"get":{let s=String(t.id??"");if(!s)return"Error: id is required for get command";let i=ke(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let d=this.browserTool?.name,p;if(s){let h={name:i,description:a,steps:l,tags:c};return d&&(h.toolType=d),p=Yn(this.workspace,s,h),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let h={name:i,description:a,steps:l,tags:c,source:"conversation"};return d&&(h.toolType=d),p=Xn(this.workspace,h),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?Ot(this.workspace,s)?`Deleted automation '${s}'`:`Error: Automation '${s}' not found or could not be deleted`:"Error: id is required for delete command"}case"run":{let s=String(t.id??"");if(!s)return"Error: id is required for run command";let i=ke(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),d=await this.executeStepWithRetries(c,n,i),p=this.maskSensitiveValues(d,t.variables);s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`)}catch(c){let d=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${d}`);else return s.push(` -> FAILED: ${d}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
214
214
  `)}}return s.push(`Automation '${t.name}' completed successfully.`),s.join(`
215
- `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,u)=>{if(r&&r[u]!==void 0)return r[u];if(n&&n[u]?.defaultValue!==void 0)return n[u].defaultValue;if(n&&n[u]?.required)throw new Error(`Required variable '${u}' not provided`);return`\${${u}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await Yr(i)}throw a??new Error("Unknown error")}async executeStepOnce(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=this.browserTool.name,i=ns[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"";break;case"read":break;case"screenshot":t.target&&(l.selector=t.target);break;case"eval":l.expression=t.value??"";break;case"wait":let c=parseInt(t.value??"1000",10);return await Yr(c),`Waited ${c}ms`;default:throw new Error(`Unknown action: ${t.action}`)}return this.browserTool.execute(l,n?{signal:n}:void 0)}toExpression(t){switch(t.check){case"selector_exists":return`!!document.querySelector(${JSON.stringify(t.value)})`;case"selector_text":return`(document.querySelector(${JSON.stringify(t.value)})?.textContent?.trim() ?? "") === ${JSON.stringify(t.expected??"")}`;case"url_contains":return`window.location.href.includes(${JSON.stringify(t.value)})`;case"eval_truthy":return`!!(${t.value})`}}isAssertionPassing(t,n){try{let r=JSON.parse(t);if(n==="chrome_session"){let s=r.result;return s&&typeof s.value=="boolean"?s.value:s&&typeof s.value=="string"?s.value.length>0:s&&typeof s.value=="number"?s.value!==0:r.result===!0}return n==="chrome_relay"?r===!0:!1}catch{return!1}}async pollAssertion(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=t.timeoutMs??5e3,i=500,a=this.toExpression(t),l=Date.now();do{if(n?.aborted)throw new Error("Aborted during assertion");try{let c=this.browserTool.name,g=ns[c]?.eval;if(!g)throw new Error(`Evaluation not supported by ${c}`);let h={command:g,expression:a};c==="chrome_relay"&&r.tabId&&(h.tabId=r.tabId),c==="chrome_session"&&r.target&&(h.target=r.target);let T=await this.browserTool.execute(h);if(this.isAssertionPassing(T,c))return}catch{}if(Date.now()-l>=s)break;await Yr(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var Yn=class o{tools=new Map;guardEngine=null;register(e){this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}clear(){this.tools.clear()}get(e){return this.tools.get(e)}getDefinitions(){return[...this.tools.values()].map(e=>e.toSchema())}get toolNames(){return[...this.tools.keys()]}setGuardEngine(e){this.guardEngine=e}getGuardEngine(){return this.guardEngine}filterByNames(e){let t=new o;t.guardEngine=this.guardEngine;for(let n of e){let r=this.tools.get(n);r&&t.register(r)}return t}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{kind:"error",content:`Error: Tool '${e}' not found. Available: ${this.toolNames.join(", ")}`,retryable:!1};try{if(Y(n?.signal),this.guardEngine){let a=this.guardEngine.guard(e,t);if(a&&!a.isSafe){let l=a.findings.map(c=>` - [${c.severity}] ${c.title}: ${c.description}`).join(`
215
+ `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,d)=>{if(r&&r[d]!==void 0)return r[d];if(n&&n[d]?.defaultValue!==void 0)return n[d].defaultValue;if(n&&n[d]?.required)throw new Error(`Required variable '${d}' not provided`);return`\${${d}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await Qr(i)}throw a??new Error("Unknown error")}async executeStepOnce(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=this.browserTool.name,i=ss[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"";break;case"read":break;case"screenshot":t.target&&(l.selector=t.target);break;case"eval":l.expression=t.value??"";break;case"wait":let c=parseInt(t.value??"1000",10);return await Qr(c),`Waited ${c}ms`;default:throw new Error(`Unknown action: ${t.action}`)}return this.browserTool.execute(l,n?{signal:n}:void 0)}toExpression(t){switch(t.check){case"selector_exists":return`!!document.querySelector(${JSON.stringify(t.value)})`;case"selector_text":return`(document.querySelector(${JSON.stringify(t.value)})?.textContent?.trim() ?? "") === ${JSON.stringify(t.expected??"")}`;case"url_contains":return`window.location.href.includes(${JSON.stringify(t.value)})`;case"eval_truthy":return`!!(${t.value})`}}isAssertionPassing(t,n){try{let r=JSON.parse(t);if(n==="chrome_session"){let s=r.result;return s&&typeof s.value=="boolean"?s.value:s&&typeof s.value=="string"?s.value.length>0:s&&typeof s.value=="number"?s.value!==0:r.result===!0}return n==="chrome_relay"?r===!0:!1}catch{return!1}}async pollAssertion(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=t.timeoutMs??5e3,i=500,a=this.toExpression(t),l=Date.now();do{if(n?.aborted)throw new Error("Aborted during assertion");try{let c=this.browserTool.name,p=ss[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let h={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(h.tabId=r.tabId),c==="chrome_session"&&r.target&&(h.target=r.target);let w=await this.browserTool.execute(h);if(this.isAssertionPassing(w,c))return}catch{}if(Date.now()-l>=s)break;await Qr(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var Qn=class o{tools=new Map;guardEngine=null;register(e){this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}clear(){this.tools.clear()}get(e){return this.tools.get(e)}getDefinitions(){return[...this.tools.values()].map(e=>e.toSchema())}get toolNames(){return[...this.tools.keys()]}setGuardEngine(e){this.guardEngine=e}getGuardEngine(){return this.guardEngine}filterByNames(e){let t=new o;t.guardEngine=this.guardEngine;for(let n of e){let r=this.tools.get(n);r&&t.register(r)}return t}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{kind:"error",content:`Error: Tool '${e}' not found. Available: ${this.toolNames.join(", ")}`,retryable:!1};try{if(Y(n?.signal),this.guardEngine){let a=this.guardEngine.guard(e,t);if(a&&!a.isSafe){let l=a.findings.map(c=>` - [${c.severity}] ${c.title}: ${c.description}`).join(`
216
216
  `);return{kind:"error",content:`Security: Tool call blocked. The tool '${e}' was denied by the security guard.
217
217
 
218
218
  Findings:
219
219
  ${l}`,retryable:!1}}}let s=r.validateParams(t);if(s.length)return{kind:"error",content:`Error: Invalid parameters for tool '${e}': ${s.join("; ")}
220
220
 
221
- [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return Y(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(te(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
221
+ [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return Y(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(ne(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
222
222
 
223
- [Analyze the error above and try a different approach.]`,retryable:!0}}}};function rs(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function ya(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
223
+ [Analyze the error above and try a different approach.]`,retryable:!0}}}};function is(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Ca(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
224
224
 
225
- `).trim()}function ba(o){try{let e=new URL(o);return["http:","https:"].includes(e.protocol)?e.hostname?[!0,""]:[!1,"Missing domain"]:[!1,`Only http/https allowed, got '${e.protocol.replace(":","")}'`]}catch(e){return[!1,String(e)]}}var Qn=class extends W{constructor(t,n=5){super();this.apiKey=t;this.maxResults=n}name="web_search";description="Search the web. Returns titles, URLs, and snippets.";parameters={type:"object",properties:{query:{type:"string",description:"Search query"},count:{type:"integer",minimum:1,maximum:10,description:"Results (1-10)"}},required:["query"]};async execute(t,n){let r=String(t.query??""),s=Math.min(Math.max(Number(t.count??this.maxResults),1),10),i=this.apiKey||process.env.BRAVE_API_KEY||"";if(!i)return"Error: Brave Search API key not configured. Set tools.web.search.apiKey or BRAVE_API_KEY.";try{Y(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let u=(await l.json()).web?.results??[];if(!u.length)return`No results for: ${r}`;let g=[`Results for: ${r}`,""];return u.slice(0,s).forEach((h,T)=>{g.push(`${T+1}. ${h.title??""}`),g.push(` ${h.url??""}`),h.description&&g.push(` ${h.description}`)}),g.join(`
226
- `)}catch(a){if(te(a))throw a;return`Error: ${String(a)}`}}},Zn=class extends W{constructor(t=5e4){super();this.maxChars=t}name="web_fetch";description="Fetch URL and extract readable content (HTML to markdown/text).";parameters={type:"object",properties:{url:{type:"string",description:"URL to fetch"},extractMode:{type:"string",enum:["markdown","text"]},maxChars:{type:"integer",minimum:100}},required:["url"]};async execute(t,n){let r=String(t.url??""),s=String(t.extractMode??"markdown"),i=Number(t.maxChars??this.maxChars),[a,l]=ba(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{Y(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),u=c.headers.get("content-type")||"",g="",h="raw";if(u.includes("application/json"))g=JSON.stringify(await c.json(),null,2),h="json";else{let d=await c.text();u.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(d.slice(0,256))?(g=s==="text"?rs(d):ya(rs(d)),h="html"):g=d}let T=g.length>i,v=T?g.slice(0,i):g;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:h,truncated:T,length:v.length,text:v})}catch(c){if(te(c))throw c;return JSON.stringify({error:String(c),url:r})}}};pt();function Ke(o){return va.resolve(o.workspace)}function er(o){let e=Ke(o);return o.restrictToWorkspace?e:void 0}function wa(o){let e=[he({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new In(Ke(t),er(t))},{name:"write_file",create:t=>new _n(Ke(t),er(t))},{name:"edit_file",create:t=>new Mn(Ke(t),er(t))},{name:"list_dir",create:t=>new $n(Ke(t),er(t))}]}),he({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new Dn(t.execConfig?.timeout??60,Ke(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new ye,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),he({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new Qn(t.braveApiKey??null)},{name:"web_fetch",create:()=>new Zn}]})];return o.bus&&e.push(he({name:"builtin-messaging-tools",tools:[{name:"message",create:t=>{if(!t.bus)throw new Error("Builtin message tool requires a message bus");let n=new Ln(async r=>{t.turn?.isCurrent&&!t.turn.isCurrent()||await t.bus.publishOutbound(r)});return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.messageId),n}}]})),o.subagents&&e.push(he({name:"builtin-subagent-tools",tools:[{name:"spawn",create:t=>{if(!t.subagents)throw new Error("Builtin spawn tool requires a subagent manager");let n=new Nn(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey),n}}]})),o.cronService&&e.push(he({name:"builtin-scheduler-tools",tools:[{name:"cron",create:t=>{if(!t.cronService)throw new Error("Builtin cron tool requires a cron service");let n=new Pn(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(he({name:"builtin-session-tools",tools:[{name:"session.info",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.info tool requires a session manager");let n=new Fn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}},{name:"session.anchor",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.anchor tool requires a session manager");let n=new Bn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}},{name:"session.search",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.search tool requires a session manager");let n=new jn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(he({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new ht(t.chromeSessionConfig,Ke(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(he({name:"builtin-browser-relay-tools",tools:[{name:"chrome_relay",create:t=>{if(!t.browserRelay)throw new Error("Builtin chrome_relay tool requires a browser relay server");return new tn(t.browserRelay)}}]})),e.push(he({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new tn(t.browserRelay):t.chromeSessionConfig?.enabled?new ht(t.chromeSessionConfig,Ke(t),!!t.restrictToWorkspace):void 0;return new Lt(Ke(t),n)}}]})),e}function Sa(o){return Jr(wa(o))}function tr(o){let e=new Yn,t=Sa(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function ka(o){let e=[he({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new Yt({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??Ye())}]})];return o.heartbeat&&e.push(he({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new Qt(t.heartbeat.workspace,t.heartbeat.provider,t.heartbeat.model,t.heartbeat.onExecute,t.heartbeat.onNotify,t.heartbeat.intervalS??1800,t.heartbeat.enabled??!0)}}]})),e}function xa(o){return Jr(ka(o))}function Je(o){let e=xa(o),t=o.lifecycle??e.lifecycle,n={...o,lifecycle:t},r=e.jobs.get("cron")?.contribution;if(!r)throw new Error("Builtin cron job registration is missing");let s=r.create(n);if(!(s instanceof Yt))throw new Error("Builtin cron job registration produced an invalid service");let i=e.jobs.get("heartbeat")?.contribution,a;if(i){let l=i.create(n);if(!(l instanceof Qt))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}pt();var os="EVERCLAW_SUBAGENT_RESULT ";function Ta(){return`# Subagent
225
+ `).trim()}function xa(o){try{let e=new URL(o);return["http:","https:"].includes(e.protocol)?e.hostname?[!0,""]:[!1,"Missing domain"]:[!1,`Only http/https allowed, got '${e.protocol.replace(":","")}'`]}catch(e){return[!1,String(e)]}}var Zn=class extends G{constructor(t,n=5){super();this.apiKey=t;this.maxResults=n}name="web_search";description="Search the web. Returns titles, URLs, and snippets.";parameters={type:"object",properties:{query:{type:"string",description:"Search query"},count:{type:"integer",minimum:1,maximum:10,description:"Results (1-10)"}},required:["query"]};async execute(t,n){let r=String(t.query??""),s=Math.min(Math.max(Number(t.count??this.maxResults),1),10),i=this.apiKey||process.env.BRAVE_API_KEY||"";if(!i)return"Error: Brave Search API key not configured. Set tools.web.search.apiKey or BRAVE_API_KEY.";try{Y(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let d=(await l.json()).web?.results??[];if(!d.length)return`No results for: ${r}`;let p=[`Results for: ${r}`,""];return d.slice(0,s).forEach((h,w)=>{p.push(`${w+1}. ${h.title??""}`),p.push(` ${h.url??""}`),h.description&&p.push(` ${h.description}`)}),p.join(`
226
+ `)}catch(a){if(ne(a))throw a;return`Error: ${String(a)}`}}},er=class extends G{constructor(t=5e4){super();this.maxChars=t}name="web_fetch";description="Fetch URL and extract readable content (HTML to markdown/text).";parameters={type:"object",properties:{url:{type:"string",description:"URL to fetch"},extractMode:{type:"string",enum:["markdown","text"]},maxChars:{type:"integer",minimum:100}},required:["url"]};async execute(t,n){let r=String(t.url??""),s=String(t.extractMode??"markdown"),i=Number(t.maxChars??this.maxChars),[a,l]=xa(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{Y(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),d=c.headers.get("content-type")||"",p="",h="raw";if(d.includes("application/json"))p=JSON.stringify(await c.json(),null,2),h="json";else{let u=await c.text();d.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(u.slice(0,256))?(p=s==="text"?is(u):Ca(is(u)),h="html"):p=u}let w=p.length>i,v=w?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:h,truncated:w,length:v.length,text:v})}catch(c){if(ne(c))throw c;return JSON.stringify({error:String(c),url:r})}}};ft();function Ke(o){return Ta.resolve(o.workspace)}function tr(o){let e=Ke(o);return o.restrictToWorkspace?e:void 0}function Ra(o){let e=[ye({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new _n(Ke(t),tr(t))},{name:"write_file",create:t=>new Mn(Ke(t),tr(t))},{name:"edit_file",create:t=>new $n(Ke(t),tr(t))},{name:"list_dir",create:t=>new On(Ke(t),tr(t))}]}),ye({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new Nn(t.execConfig?.timeout??60,Ke(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new be,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),ye({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new Zn(t.braveApiKey??null)},{name:"web_fetch",create:()=>new er}]})];return o.bus&&e.push(ye({name:"builtin-messaging-tools",tools:[{name:"message",create:t=>{if(!t.bus)throw new Error("Builtin message tool requires a message bus");let n=new Dn(async r=>{t.turn?.isCurrent&&!t.turn.isCurrent()||await t.bus.publishOutbound(r)});return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.messageId),n}}]})),o.subagents&&e.push(ye({name:"builtin-subagent-tools",tools:[{name:"spawn",create:t=>{if(!t.subagents)throw new Error("Builtin spawn tool requires a subagent manager");let n=new jn(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey),n}}]})),o.cronService&&e.push(ye({name:"builtin-scheduler-tools",tools:[{name:"cron",create:t=>{if(!t.cronService)throw new Error("Builtin cron tool requires a cron service");let n=new In(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(ye({name:"builtin-session-tools",tools:[{name:"session.info",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.info tool requires a session manager");let n=new Bn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}},{name:"session.anchor",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.anchor tool requires a session manager");let n=new Gn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}},{name:"session.search",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.search tool requires a session manager");let n=new Fn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(ye({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new yt(t.chromeSessionConfig,Ke(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(ye({name:"builtin-browser-relay-tools",tools:[{name:"chrome_relay",create:t=>{if(!t.browserRelay)throw new Error("Builtin chrome_relay tool requires a browser relay server");return new tn(t.browserRelay)}}]})),e.push(ye({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new tn(t.browserRelay):t.chromeSessionConfig?.enabled?new yt(t.chromeSessionConfig,Ke(t),!!t.restrictToWorkspace):void 0;return new Lt(Ke(t),n)}}]})),e}function Aa(o){return Jr(Ra(o))}function nr(o){let e=new Qn,t=Aa(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function Ea(o){let e=[ye({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new Yt({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??Ye())}]})];return o.heartbeat&&e.push(ye({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new Qt(t.heartbeat.workspace,t.heartbeat.provider,t.heartbeat.model,t.heartbeat.onExecute,t.heartbeat.onNotify,t.heartbeat.intervalS??1800,t.heartbeat.enabled??!0)}}]})),e}function Pa(o){return Jr(Ea(o))}function qe(o){let e=Pa(o),t=o.lifecycle??e.lifecycle,n={...o,lifecycle:t},r=e.jobs.get("cron")?.contribution;if(!r)throw new Error("Builtin cron job registration is missing");let s=r.create(n);if(!(s instanceof Yt))throw new Error("Builtin cron job registration produced an invalid service");let i=e.jobs.get("heartbeat")?.contribution,a;if(i){let l=i.create(n);if(!(l instanceof Qt))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}ft();var as="EVERCLAW_SUBAGENT_RESULT ";function _a(){return`# Subagent
227
227
 
228
228
  Current Time: ${new Date().toLocaleString()}
229
229
 
230
- You are a subagent spawned by the main agent to complete a specific task. Stay focused and concise.`}async function Qr(o){let e=tr({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig});o.allowedTools&&o.allowedTools.length>0&&(e=e.filterByNames(o.allowedTools));let t=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:Ta()},{role:"user",content:o.task}],n="Task completed but no final response was generated.";for(let r=0;r<15;r++){Y(o.signal);let s=await o.provider.chat({messages:t,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(Y(o.signal),s.toolCalls.length){t.push({role:"assistant",content:s.content??"",tool_calls:s.toolCalls.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.arguments)}}))});for(let i of s.toolCalls){Y(o.signal);let a=await e.execute(i.name,i.arguments,o.signal?{signal:o.signal}:{});Y(o.signal);let l=typeof a=="object"&&"kind"in a?a.content??String(a):String(a);t.push({role:"tool",tool_call_id:i.id,name:i.name,content:l})}continue}n=s.content??n;break}return n}function Ra(){let o=process.argv[1]??"";return _t(o)}function Aa(o){let e=o.stderr.trim();return o.errorMessage?o.errorMessage:e||(o.failureAttribution==="exit_code"&&o.exitCode!=null?`Isolated subagent exited with code ${o.exitCode}.`:o.failureAttribution==="signal"&&o.signal?`Isolated subagent terminated by signal ${o.signal}.`:o.failureAttribution==="timeout"?"Isolated subagent timed out before producing a result.":"Isolated subagent failed before producing a result.")}function Ea(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(os));if(e)try{return JSON.parse(e.slice(os.length))}catch{return{status:"failed",errorMessage:"Isolated subagent returned an invalid result payload.",failureAttribution:"protocol"}}return o.status==="aborted"?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:Aa(o),failureAttribution:o.failureAttribution}}var nr=class{constructor(e=new ye,t=Ra){this.runner=e;this.resolveCommand=t}async execute(e){if(mt("subagent").mode!=="local-process")return{status:"failed",errorMessage:"Subagent isolation policy did not resolve to local-process execution.",failureAttribution:"protocol"};let n=this.resolveCommand(),r={command:{kind:"argv",file:n.file,args:n.args},cwd:e.workspace,env:{...n.env},stdinText:JSON.stringify({task:e.task,workspace:e.workspace,model:e.model,temperature:e.temperature,maxTokens:e.maxTokens,braveApiKey:e.braveApiKey,execConfig:e.execConfig,restrictToWorkspace:e.restrictToWorkspace,allowedTools:e.allowedTools,providerName:e.providerName}),maxCaptureBytes:1024*1024};e.signal&&(r.signal=e.signal);let s=await this.runner.run(r);return Ea(s)}},rr=class{sessionManager;constructor(e){this.sessionManager=e}async execute(e){if(!e.provider)return{status:"failed",errorMessage:"Inline subagent execution requires a provider to be provided.",failureAttribution:"protocol"};try{let t;if(e.sessionKey&&!this.sessionManager&&console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`),e.sessionKey&&this.sessionManager){let r=this.sessionManager.getOrCreate(e.sessionKey);r&&(t=r.fork().getHistory())}return{status:"completed",finalResult:await Qr({...e,provider:e.provider,existingMessages:t})}}catch(t){return te(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},or=class{constructor(e,t,n,r){this.bus=e;this.processExecutor=t;this.inlineExecutor=n;this.settings=r}running=new Map;controllers=new Map;sessionTasks=new Map;sessionGenerations=new Map;async spawn(e){let t=Ca().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s);let i=e.mode??"process",a=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName).finally(()=>{this.running.delete(t),this.controllers.delete(t);let l=this.sessionTasks.get(e.sessionKey);l&&(l.delete(t),l.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,a),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l){let c=this.controllers.get(e)?.signal,u=s==="inline"?this.inlineExecutor:this.processExecutor;try{let g={...this.settings,task:t};c&&(g.signal=c),i&&(g.provider=i),a&&(g.model=a),l&&(g.providerName=l);let h=await u.execute(g);if(h.status==="aborted"||!this.isSessionCurrent(r.sessionKey,r.generation))return;await this.publishOutcome(r,t,n,h)}catch(g){if(te(g)||!this.isSessionCurrent(r.sessionKey,r.generation))return;try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:g instanceof Error?g.message:String(g),failureAttribution:"exception"})}catch{}}}async publishOutcome(e,t,n,r){let s=r.status==="completed"?`[Subagent '${n}' completed successfully]
230
+ You are a subagent spawned by the main agent to complete a specific task. Stay focused and concise.`}async function Zr(o){let e=nr({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig});o.allowedTools&&o.allowedTools.length>0&&(e=e.filterByNames(o.allowedTools));let t=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:_a()},{role:"user",content:o.task}],n="Task completed but no final response was generated.";for(let r=0;r<15;r++){Y(o.signal);let s=await o.provider.chat({messages:t,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(Y(o.signal),s.toolCalls.length){t.push({role:"assistant",content:s.content??"",tool_calls:s.toolCalls.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.arguments)}}))});for(let i of s.toolCalls){Y(o.signal);let a=await e.execute(i.name,i.arguments,o.signal?{signal:o.signal}:{});Y(o.signal);let l=typeof a=="object"&&"kind"in a?a.content??String(a):String(a);t.push({role:"tool",tool_call_id:i.id,name:i.name,content:l})}continue}n=s.content??n;break}return n}function Ma(){let o=process.argv[1]??"";return _t(o)}function $a(o){let e=o.stderr.trim();return o.errorMessage?o.errorMessage:e||(o.failureAttribution==="exit_code"&&o.exitCode!=null?`Isolated subagent exited with code ${o.exitCode}.`:o.failureAttribution==="signal"&&o.signal?`Isolated subagent terminated by signal ${o.signal}.`:o.failureAttribution==="timeout"?"Isolated subagent timed out before producing a result.":"Isolated subagent failed before producing a result.")}function Oa(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(as));if(e)try{return JSON.parse(e.slice(as.length))}catch{return{status:"failed",errorMessage:"Isolated subagent returned an invalid result payload.",failureAttribution:"protocol"}}return o.status==="aborted"?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:$a(o),failureAttribution:o.failureAttribution}}var rr=class{constructor(e=new be,t=Ma){this.runner=e;this.resolveCommand=t}async execute(e){if(pt("subagent").mode!=="local-process")return{status:"failed",errorMessage:"Subagent isolation policy did not resolve to local-process execution.",failureAttribution:"protocol"};let n=this.resolveCommand(),r={command:{kind:"argv",file:n.file,args:n.args},cwd:e.workspace,env:{...n.env},stdinText:JSON.stringify({task:e.task,workspace:e.workspace,model:e.model,temperature:e.temperature,maxTokens:e.maxTokens,braveApiKey:e.braveApiKey,execConfig:e.execConfig,restrictToWorkspace:e.restrictToWorkspace,allowedTools:e.allowedTools,providerName:e.providerName}),maxCaptureBytes:1024*1024};e.signal&&(r.signal=e.signal);let s=await this.runner.run(r);return Oa(s)}},or=class{sessionManager;constructor(e){this.sessionManager=e}async execute(e){if(!e.provider)return{status:"failed",errorMessage:"Inline subagent execution requires a provider to be provided.",failureAttribution:"protocol"};try{let t;if(e.sessionKey&&!this.sessionManager&&console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`),e.sessionKey&&this.sessionManager){let r=this.sessionManager.getOrCreate(e.sessionKey);r&&(t=r.fork().getHistory())}return{status:"completed",finalResult:await Zr({...e,provider:e.provider,existingMessages:t})}}catch(t){return ne(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},sr=class{constructor(e,t,n,r){this.bus=e;this.processExecutor=t;this.inlineExecutor=n;this.settings=r}running=new Map;controllers=new Map;sessionTasks=new Map;sessionGenerations=new Map;async spawn(e){let t=Ia().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s);let i=e.mode??"process",a=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName).finally(()=>{this.running.delete(t),this.controllers.delete(t);let l=this.sessionTasks.get(e.sessionKey);l&&(l.delete(t),l.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,a),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l){let c=this.controllers.get(e)?.signal,d=s==="inline"?this.inlineExecutor:this.processExecutor;try{let p={...this.settings,task:t};c&&(p.signal=c),i&&(p.provider=i),a&&(p.model=a),l&&(p.providerName=l);let h=await d.execute(p);if(h.status==="aborted"||!this.isSessionCurrent(r.sessionKey,r.generation))return;await this.publishOutcome(r,t,n,h)}catch(p){if(ne(p)||!this.isSessionCurrent(r.sessionKey,r.generation))return;try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:p instanceof Error?p.message:String(p),failureAttribution:"exception"})}catch{}}}async publishOutcome(e,t,n,r){let s=r.status==="completed"?`[Subagent '${n}' completed successfully]
231
231
 
232
232
  Task: ${t}
233
233
 
@@ -241,7 +241,7 @@ Task: ${t}
241
241
  Error:
242
242
  ${r.errorMessage??"The isolated subagent failed before producing a result."}
243
243
 
244
- Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:s};await this.bus.publishInbound(i)}async cancelBySession(e){this.sessionGenerations.set(e,this.getSessionGeneration(e)+1);let t=[...this.sessionTasks.get(e)??[]],n=0;for(let r of t){let s=this.controllers.get(r);!s||s.signal.aborted||(s.abort(),n+=1)}return n}async cancelAll(){let e=[...this.sessionTasks.keys()],t=0;for(let n of e)t+=await this.cancelBySession(n);return t}getRunningCount(){return this.running.size}getSessionGeneration(e){return this.sessionGenerations.get(e)??0}isSessionCurrent(e,t){return this.getSessionGeneration(e)===t}};var sr=class{constructor(e=4,t=1){this.maxConcurrency=e;this.maxQueuedPerKey=t}states=new Map;readyKeys=[];readySet=new Set;inFlight=0;backpressured=0;lastBackpressureAt=null;enqueue(e,t,n={}){let r=this.getOrCreateState(e),s=r.generation;return!n.bypassCapacity&&r.queued.length>=this.maxQueuedPerKey?(this.backpressured+=1,this.lastBackpressureAt=new Date().toISOString(),this.cleanup(e),Promise.resolve({status:"rejected",reason:"backpressure"})):new Promise((i,a)=>{r.queued.push({generation:s,execute:t,resolve:i,reject:a}),r.running||this.queueKey(e),this.pump()})}cancel(e){let t=this.states.get(e);if(!t)return{running:!1,queued:0};t.generation+=1;let n=t.queued.length;for(let r of t.queued)r.resolve({status:"cancelled"});return t.queued=[],this.removeReadyKey(e),this.cleanup(e),{running:t.running,queued:n}}snapshot(){let e=[...this.states.entries()].map(([t,n])=>({key:t,running:n.running,queued:n.queued.length})).filter(t=>t.running||t.queued>0).sort((t,n)=>t.key.localeCompare(n.key));return{maxConcurrency:this.maxConcurrency,maxQueuedPerKey:this.maxQueuedPerKey,running:e.filter(t=>t.running).length,queued:e.reduce((t,n)=>t+n.queued,0),backpressured:this.backpressured,lastBackpressureAt:this.lastBackpressureAt,sessions:e}}getOrCreateState(e){let t=this.states.get(e);return t||(t={generation:0,running:!1,queued:[]},this.states.set(e,t)),t}isCurrent(e,t){return this.states.get(e)?.generation===t}queueKey(e){this.readySet.has(e)||(this.readySet.add(e),this.readyKeys.push(e))}removeReadyKey(e){if(!this.readySet.delete(e))return;let t=this.readyKeys.indexOf(e);t>=0&&this.readyKeys.splice(t,1)}cleanup(e){let t=this.states.get(e);!t||t.running||t.queued.length||this.states.delete(e)}pump(){for(;this.inFlight<this.maxConcurrency&&this.readyKeys.length;){let e=this.readyKeys.shift();this.readySet.delete(e);let t=this.states.get(e);if(!t||t.running||!t.queued.length){this.cleanup(e);continue}let n=t.queued.shift();t.running=!0,this.inFlight+=1,(async()=>{try{if(!this.isCurrent(e,n.generation)){n.resolve({status:"cancelled"});return}let r=await n.execute({isCurrent:()=>this.isCurrent(e,n.generation)});this.isCurrent(e,n.generation)?n.resolve({status:"completed",value:r}):n.resolve({status:"cancelled"})}catch(r){n.reject(r)}finally{let r=this.states.get(e);r&&(r.running=!1,r.queued.length&&this.queueKey(e),this.cleanup(e)),this.inFlight-=1,this.pump()}})()}}};function Zr(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import _e from"node:fs";import ir from"node:path";Oe();function Dt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function ss(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Pa(o){try{let e=JSON.parse(o);return Dt(e)?"metadata"in e||"last_consolidated"in e?{metadata:Dt(e.metadata)?e.metadata:{},lastConsolidated:typeof e.last_consolidated=="number"?e.last_consolidated:0}:{metadata:e,lastConsolidated:0}:{metadata:{},lastConsolidated:0}}catch{return{metadata:{},lastConsolidated:0}}}var ar=class o{key;messages=[];createdAt=ie();updatedAt=ie();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let u=this.messages[c];if(u?._type==="anchor"){n=u,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(g=>g.role==="tool"||g.tool_calls&&Array.isArray(g.tool_calls))||(i=i.slice(a)));let l=[];n&&l.push({role:"system",content:`[Context anchor: ${n.name}${n.summary?` \u2014 ${n.summary}`:""}]`,_type:"anchor_marker"});for(let c of i){let u={role:c.role,content:c.content??""};for(let g of["tool_calls","tool_call_id","name"])g in c&&(u[g]=c[g]);l.push(u)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=ie()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:ie()};return this.messages.push(n),this.updatedAt=ie(),n}getLastAnchor(){for(let e=this.messages.length-1;e>=0;e--){let t=this.messages[e];if(t&&t._type==="anchor")return t}return null}fork(){let e=new o(this.key);return e.messages=[...this.messages],e.createdAt=this.createdAt,e.updatedAt=this.updatedAt,e.metadata={...this.metadata},e.lastConsolidated=this.lastConsolidated,e}merge(e){if(e.key!==this.key)throw new Error("Cannot merge sessions with different keys");let t=e.messages.slice(this.messages.length);this.messages.push(...t),this.updatedAt=ie(),this.metadata={...this.metadata,...e.metadata}}getMessagesSinceLastAnchor(){let e=-1;for(let t=this.messages.length-1;t>=0;t--)if(this.messages[t]?._type==="anchor"){e=t;break}return e===-1?this.messages:this.messages.slice(e+1)}search(e,t=10){let n=e.toLowerCase(),r=[];for(let s of this.messages){if(s._type==="anchor")continue;let i=typeof s.content=="string"?s.content:JSON.stringify(s.content),a=i.toLowerCase(),l=a.indexOf(n);if(l!==-1){let c={role:String(s.role??"unknown"),content:i,score:a.length-n.length+l};typeof s.timestamp=="string"&&(c.timestamp=s.timestamp),r.push(c)}}return r.sort((s,i)=>s.score-i.score),{query:e,results:r.slice(0,t)}}},Qe=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=Ve(ir.join(e,"sessions")),this.workspaceKey=t.workspaceKey??ir.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return ir.join(this.sessionsDir,`${Co(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Le({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=Dt(t.metadata)?t.metadata:{},e.lastConsolidated=typeof t.last_consolidated=="number"?t.last_consolidated:0}applyPersistedRow(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt;let n=Pa(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=ss(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
244
+ Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:s};await this.bus.publishInbound(i)}async cancelBySession(e){this.sessionGenerations.set(e,this.getSessionGeneration(e)+1);let t=[...this.sessionTasks.get(e)??[]],n=0;for(let r of t){let s=this.controllers.get(r);!s||s.signal.aborted||(s.abort(),n+=1)}return n}async cancelAll(){let e=[...this.sessionTasks.keys()],t=0;for(let n of e)t+=await this.cancelBySession(n);return t}getRunningCount(){return this.running.size}getSessionGeneration(e){return this.sessionGenerations.get(e)??0}isSessionCurrent(e,t){return this.getSessionGeneration(e)===t}};var ir=class{constructor(e=4,t=1){this.maxConcurrency=e;this.maxQueuedPerKey=t}states=new Map;readyKeys=[];readySet=new Set;inFlight=0;backpressured=0;lastBackpressureAt=null;enqueue(e,t,n={}){let r=this.getOrCreateState(e),s=r.generation;return!n.bypassCapacity&&r.queued.length>=this.maxQueuedPerKey?(this.backpressured+=1,this.lastBackpressureAt=new Date().toISOString(),this.cleanup(e),Promise.resolve({status:"rejected",reason:"backpressure"})):new Promise((i,a)=>{r.queued.push({generation:s,execute:t,resolve:i,reject:a}),r.running||this.queueKey(e),this.pump()})}cancel(e){let t=this.states.get(e);if(!t)return{running:!1,queued:0};t.generation+=1;let n=t.queued.length;for(let r of t.queued)r.resolve({status:"cancelled"});return t.queued=[],this.removeReadyKey(e),this.cleanup(e),{running:t.running,queued:n}}snapshot(){let e=[...this.states.entries()].map(([t,n])=>({key:t,running:n.running,queued:n.queued.length})).filter(t=>t.running||t.queued>0).sort((t,n)=>t.key.localeCompare(n.key));return{maxConcurrency:this.maxConcurrency,maxQueuedPerKey:this.maxQueuedPerKey,running:e.filter(t=>t.running).length,queued:e.reduce((t,n)=>t+n.queued,0),backpressured:this.backpressured,lastBackpressureAt:this.lastBackpressureAt,sessions:e}}getOrCreateState(e){let t=this.states.get(e);return t||(t={generation:0,running:!1,queued:[]},this.states.set(e,t)),t}isCurrent(e,t){return this.states.get(e)?.generation===t}queueKey(e){this.readySet.has(e)||(this.readySet.add(e),this.readyKeys.push(e))}removeReadyKey(e){if(!this.readySet.delete(e))return;let t=this.readyKeys.indexOf(e);t>=0&&this.readyKeys.splice(t,1)}cleanup(e){let t=this.states.get(e);!t||t.running||t.queued.length||this.states.delete(e)}pump(){for(;this.inFlight<this.maxConcurrency&&this.readyKeys.length;){let e=this.readyKeys.shift();this.readySet.delete(e);let t=this.states.get(e);if(!t||t.running||!t.queued.length){this.cleanup(e);continue}let n=t.queued.shift();t.running=!0,this.inFlight+=1,(async()=>{try{if(!this.isCurrent(e,n.generation)){n.resolve({status:"cancelled"});return}let r=await n.execute({isCurrent:()=>this.isCurrent(e,n.generation)});this.isCurrent(e,n.generation)?n.resolve({status:"completed",value:r}):n.resolve({status:"cancelled"})}catch(r){n.reject(r)}finally{let r=this.states.get(e);r&&(r.running=!1,r.queued.length&&this.queueKey(e),this.cleanup(e)),this.inFlight-=1,this.pump()}})()}}};function eo(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import Me from"node:fs";import ar from"node:path";Le();function Dt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function ls(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function La(o){try{let e=JSON.parse(o);return Dt(e)?"metadata"in e||"last_consolidated"in e?{metadata:Dt(e.metadata)?e.metadata:{},lastConsolidated:typeof e.last_consolidated=="number"?e.last_consolidated:0}:{metadata:e,lastConsolidated:0}:{metadata:{},lastConsolidated:0}}catch{return{metadata:{},lastConsolidated:0}}}var lr=class o{key;messages=[];createdAt=ie();updatedAt=ie();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let d=this.messages[c];if(d?._type==="anchor"){n=d,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(p=>p.role==="tool"||p.tool_calls&&Array.isArray(p.tool_calls))||(i=i.slice(a)));let l=[];n&&l.push({role:"system",content:`[Context anchor: ${n.name}${n.summary?` \u2014 ${n.summary}`:""}]`,_type:"anchor_marker"});for(let c of i){let d={role:c.role,content:c.content??""};for(let p of["tool_calls","tool_call_id","name"])p in c&&(d[p]=c[p]);l.push(d)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=ie()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:ie()};return this.messages.push(n),this.updatedAt=ie(),n}getLastAnchor(){for(let e=this.messages.length-1;e>=0;e--){let t=this.messages[e];if(t&&t._type==="anchor")return t}return null}fork(){let e=new o(this.key);return e.messages=[...this.messages],e.createdAt=this.createdAt,e.updatedAt=this.updatedAt,e.metadata={...this.metadata},e.lastConsolidated=this.lastConsolidated,e}merge(e){if(e.key!==this.key)throw new Error("Cannot merge sessions with different keys");let t=e.messages.slice(this.messages.length);this.messages.push(...t),this.updatedAt=ie(),this.metadata={...this.metadata,...e.metadata}}getMessagesSinceLastAnchor(){let e=-1;for(let t=this.messages.length-1;t>=0;t--)if(this.messages[t]?._type==="anchor"){e=t;break}return e===-1?this.messages:this.messages.slice(e+1)}search(e,t=10){let n=e.toLowerCase(),r=[];for(let s of this.messages){if(s._type==="anchor")continue;let i=typeof s.content=="string"?s.content:JSON.stringify(s.content),a=i.toLowerCase(),l=a.indexOf(n);if(l!==-1){let c={role:String(s.role??"unknown"),content:i,score:a.length-n.length+l};typeof s.timestamp=="string"&&(c.timestamp=s.timestamp),r.push(c)}}return r.sort((s,i)=>s.score-i.score),{query:e,results:r.slice(0,t)}}},Qe=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=Ve(ar.join(e,"sessions")),this.workspaceKey=t.workspaceKey??ar.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return ar.join(this.sessionsDir,`${To(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=De({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=Dt(t.metadata)?t.metadata:{},e.lastConsolidated=typeof t.last_consolidated=="number"?t.last_consolidated:0}applyPersistedRow(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt;let n=La(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=ls(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
245
245
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
246
246
  ) VALUES (?, ?, ?, ?, ?, ?, ?)
247
247
  ON CONFLICT(workspace, session_key) DO UPDATE SET
@@ -249,68 +249,68 @@ Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channe
249
249
  chat_id = excluded.chat_id,
250
250
  created_at = excluded.created_at,
251
251
  updated_at = excluded.updated_at,
252
- metadata_json = excluded.metadata_json`).run(this.workspaceKey,e.key,t,n,e.createdAt,e.updatedAt,JSON.stringify({metadata:e.metadata,last_consolidated:e.lastConsolidated}))}readLegacySessionMetadata(e){if(!_e.existsSync(e))return null;try{let t=_e.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return Dt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!_e.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
252
+ metadata_json = excluded.metadata_json`).run(this.workspaceKey,e.key,t,n,e.createdAt,e.updatedAt,JSON.stringify({metadata:e.metadata,last_consolidated:e.lastConsolidated}))}readLegacySessionMetadata(e){if(!Me.existsSync(e))return null;try{let t=Me.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return Dt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!Me.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
253
253
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
254
- ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of _e.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=ir.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=ss(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??ie(),r.updated_at??r.created_at??ie(),JSON.stringify({metadata:Dt(r.metadata)?r.metadata:{},last_consolidated:typeof r.last_consolidated=="number"?r.last_consolidated:0}))}}readPersistedRow(e){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT created_at, updated_at, metadata_json
254
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of Me.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=ar.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=ls(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??ie(),r.updated_at??r.created_at??ie(),JSON.stringify({metadata:Dt(r.metadata)?r.metadata:{},last_consolidated:typeof r.last_consolidated=="number"?r.last_consolidated:0}))}}readPersistedRow(e){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT created_at, updated_at, metadata_json
255
255
  FROM session_metadata
256
- WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!_e.existsSync(t))return null;try{let r=_e.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let u=JSON.parse(c);if(!i&&Dt(u)&&u._type==="metadata"){i=u;continue}s.push(u)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new ar(e);return this.cache.set(e,n),n}save(e){let t=this.getSessionPath(e.key),n=`${t}.tmp`,r={_type:"metadata",key:e.key,created_at:e.createdAt,updated_at:e.updatedAt,metadata:e.metadata,last_consolidated:e.lastConsolidated},s=[JSON.stringify(r),...e.messages.map(i=>JSON.stringify(i))];try{_e.writeFileSync(n,`${s.join(`
256
+ WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!Me.existsSync(t))return null;try{let r=Me.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let d=JSON.parse(c);if(!i&&Dt(d)&&d._type==="metadata"){i=d;continue}s.push(d)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new lr(e);return this.cache.set(e,n),n}save(e){let t=this.getSessionPath(e.key),n=`${t}.tmp`,r={_type:"metadata",key:e.key,created_at:e.createdAt,updated_at:e.updatedAt,metadata:e.metadata,last_consolidated:e.lastConsolidated},s=[JSON.stringify(r),...e.messages.map(i=>JSON.stringify(i))];try{Me.writeFileSync(n,`${s.join(`
257
257
  `)}
258
- `,"utf8"),_e.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{_e.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return _e.existsSync(t)&&(_e.unlinkSync(t),n=!0),this.getStorage().prepare("DELETE FROM session_metadata WHERE workspace = ? AND session_key = ?").run(this.workspaceKey,e),this.cache.delete(e),n}listSessions(){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT session_key, created_at, updated_at
258
+ `,"utf8"),Me.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{Me.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return Me.existsSync(t)&&(Me.unlinkSync(t),n=!0),this.getStorage().prepare("DELETE FROM session_metadata WHERE workspace = ? AND session_key = ?").run(this.workspaceKey,e),this.cache.delete(e),n}listSessions(){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT session_key, created_at, updated_at
259
259
  FROM session_metadata
260
260
  WHERE workspace = ?
261
- ORDER BY updated_at DESC, session_key`).all(this.workspaceKey).map(t=>({key:t.session_key,created_at:t.created_at,updated_at:t.updated_at,path:this.getSessionPath(t.session_key)}))}load(e){let t=this.readPersistedRow(e),n=this.readTranscript(e);if(!t&&!n)return null;let r=new ar(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};Tt();var Ia=[{pattern:/ignore\s+all\s+(previous|prior|above)\s+(instructions?|prompts?|rules?|directives?)/i,label:"instruction override"},{pattern:/you\s+are\s+now\s+a\s+different\s+(ai|assistant|model|persona|person|entity)/i,label:"role hijacking"},{pattern:/(?:^|\s)system\s*:\s*you\s+are\b/i,label:"system prompt injection"},{pattern:/\[INST\]/i,label:"instruction marker [INST]"},{pattern:/<<SYS>>/i,label:"system marker <<SYS>>"},{pattern:/forget\s+(everything|all|your|the)\s+(you|previous|past)/i,label:"forget context injection"},{pattern:/disregard\s+(your|all|the|any)\s+(instructions?|rules?|guidelines?)/i,label:"disregard instructions injection"},{pattern:/pretend\s+(you\s+are|to\s+be)\s+(a|an|the)/i,label:"pretend role injection"},{pattern:/new\s+instructions?\s*:\s*(?:ignore|forget|disregard|skip)/i,label:"new instructions override"},{pattern:/(?:override|bypass|circumvent)\s+(the\s+)?(?:safety|security|content|filter|guard)/i,label:"safety bypass attempt"}],_a=/<\/?[a-zA-Z][^>]*\/?>/g,lr=class{config;constructor(e){this.config=e}sanitize(e){if(!this.config.enabled)return{safe:!1,sanitized:String(e??""),warnings:[]};let t=typeof e=="string"?e:String(e??""),n=[];if(t.length>this.config.maxInputLength&&(t=t.slice(0,this.config.maxInputLength),n.push(`Input truncated from ${typeof e=="string"?e.length:0} to ${this.config.maxInputLength} characters (maxInputLength).`)),this.config.stripHtmlTags){let r=t;t=t.replace(_a,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of Ia)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};Tt();le();function rn(o){return o.map(e=>{let t=e.content;if(typeof t=="string"&&t.length===0)return e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"};if(Array.isArray(t)){let n=t.filter(r=>!(typeof r=="object"&&r&&["text","input_text","output_text"].includes(r.type)&&!r.text));if(n.length!==t.length)return n.length>0?{...e,content:n}:e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"}}return e})}function is(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function as(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var cr=class{constructor(e,t,n,r={}){this.apiKey=e;this.apiBase=t;this.defaultModel=n;this.options=r}getDefaultModel(){return this.defaultModel}get requestFormat(){return this.options.apiFormat??"v1/chat/completions"}resolveModel(e){let t=e.trim();if(!t.includes("/"))return t;let n=t.split("/",2),r=n[0],s=n[1];return!r||!s?t:new Set(["custom",is(this.options.providerLabel??"")]).has(is(r))?s:t}buildHeaders(){let e={"Content-Type":"application/json",...this.options.extraHeaders??{}};return this.apiKey.trim()&&(e.Authorization=`Bearer ${this.apiKey}`),e}async readJson(e){try{return await e.json()}catch{return{}}}async chatCompletions(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),messages:rn(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning_effort:"medium"}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=n.choices?.[0];if(!r?.message)return{content:`Error calling LLM: ${JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=(r.message.tool_calls??[]).map(i=>({id:i.id,name:i.function.name,arguments:as(i.function.arguments)}));return{content:r.message.content??null,toolCalls:s,finishReason:r.finish_reason??"stop",usage:{prompt_tokens:n.usage?.prompt_tokens??0,completion_tokens:n.usage?.completion_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:r.message.reasoning_content??null}}toResponsesInput(e){let t=[];for(let n of rn(e)){let r=String(n.role??"");if(r==="tool"){t.push({type:"function_call_output",call_id:String(n.tool_call_id??""),output:typeof n.content=="string"?n.content:JSON.stringify(n.content??null)});continue}if(r==="assistant"&&Array.isArray(n.tool_calls))for(let s of n.tool_calls)t.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:typeof s.arguments=="string"?s.arguments:JSON.stringify(s.arguments??{})});(r==="system"||r==="user"||r==="assistant")&&t.push({role:r,content:n.content??""})}return t}async responses(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/responses`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),input:this.toResponsesInput(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_output_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning:{effort:"medium"}}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=Array.isArray(n.output)?n.output:[],s=r.filter(a=>a?.type==="function_call").map(a=>({id:String(a.call_id??a.id??""),name:String(a.name??""),arguments:as(a.arguments)}));return{content:r.filter(a=>a?.type==="message").flatMap(a=>Array.isArray(a?.content)?a.content:[]).filter(a=>a?.type==="output_text").map(a=>String(a.text??"")).join(`
262
- `).trim()||null,toolCalls:s,finishReason:s.length?"tool_calls":n.status??"stop",usage:{prompt_tokens:n.usage?.input_tokens??0,completion_tokens:n.usage?.output_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:null}}async chat(e){try{return Y(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(te(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Ma}from"nanoid";var dr=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let u=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let g of u){let h=g.function;h?.name&&l.push({functionCall:{name:h.name,args:this.parseToolArgs(h.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
261
+ ORDER BY updated_at DESC, session_key`).all(this.workspaceKey).map(t=>({key:t.session_key,created_at:t.created_at,updated_at:t.updated_at,path:this.getSessionPath(t.session_key)}))}load(e){let t=this.readPersistedRow(e),n=this.readTranscript(e);if(!t&&!n)return null;let r=new lr(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};Rt();var Da=[{pattern:/ignore\s+all\s+(previous|prior|above)\s+(instructions?|prompts?|rules?|directives?)/i,label:"instruction override"},{pattern:/you\s+are\s+now\s+a\s+different\s+(ai|assistant|model|persona|person|entity)/i,label:"role hijacking"},{pattern:/(?:^|\s)system\s*:\s*you\s+are\b/i,label:"system prompt injection"},{pattern:/\[INST\]/i,label:"instruction marker [INST]"},{pattern:/<<SYS>>/i,label:"system marker <<SYS>>"},{pattern:/forget\s+(everything|all|your|the)\s+(you|previous|past)/i,label:"forget context injection"},{pattern:/disregard\s+(your|all|the|any)\s+(instructions?|rules?|guidelines?)/i,label:"disregard instructions injection"},{pattern:/pretend\s+(you\s+are|to\s+be)\s+(a|an|the)/i,label:"pretend role injection"},{pattern:/new\s+instructions?\s*:\s*(?:ignore|forget|disregard|skip)/i,label:"new instructions override"},{pattern:/(?:override|bypass|circumvent)\s+(the\s+)?(?:safety|security|content|filter|guard)/i,label:"safety bypass attempt"}],Na=/<\/?[a-zA-Z][^>]*\/?>/g,cr=class{config;constructor(e){this.config=e}sanitize(e){if(!this.config.enabled)return{safe:!1,sanitized:String(e??""),warnings:[]};let t=typeof e=="string"?e:String(e??""),n=[];if(t.length>this.config.maxInputLength&&(t=t.slice(0,this.config.maxInputLength),n.push(`Input truncated from ${typeof e=="string"?e.length:0} to ${this.config.maxInputLength} characters (maxInputLength).`)),this.config.stripHtmlTags){let r=t;t=t.replace(Na,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of Da)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};Rt();ce();function rn(o){return o.map(e=>{let t=e.content;if(typeof t=="string"&&t.length===0)return e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"};if(Array.isArray(t)){let n=t.filter(r=>!(typeof r=="object"&&r&&["text","input_text","output_text"].includes(r.type)&&!r.text));if(n.length!==t.length)return n.length>0?{...e,content:n}:e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"}}return e})}function cs(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function ds(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var dr=class{constructor(e,t,n,r={}){this.apiKey=e;this.apiBase=t;this.defaultModel=n;this.options=r}getDefaultModel(){return this.defaultModel}get requestFormat(){return this.options.apiFormat??"v1/chat/completions"}resolveModel(e){let t=e.trim();if(!t.includes("/"))return t;let n=t.split("/",2),r=n[0],s=n[1];return!r||!s?t:new Set(["custom",cs(this.options.providerLabel??"")]).has(cs(r))?s:t}buildHeaders(){let e={"Content-Type":"application/json",...this.options.extraHeaders??{}};return this.apiKey.trim()&&(e.Authorization=`Bearer ${this.apiKey}`),e}async readJson(e){try{return await e.json()}catch{return{}}}async chatCompletions(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),messages:rn(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning_effort:"medium"}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=n.choices?.[0];if(!r?.message)return{content:`Error calling LLM: ${JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=(r.message.tool_calls??[]).map(i=>({id:i.id,name:i.function.name,arguments:ds(i.function.arguments)}));return{content:r.message.content??null,toolCalls:s,finishReason:r.finish_reason??"stop",usage:{prompt_tokens:n.usage?.prompt_tokens??0,completion_tokens:n.usage?.completion_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:r.message.reasoning_content??null}}toResponsesInput(e){let t=[];for(let n of rn(e)){let r=String(n.role??"");if(r==="tool"){t.push({type:"function_call_output",call_id:String(n.tool_call_id??""),output:typeof n.content=="string"?n.content:JSON.stringify(n.content??null)});continue}if(r==="assistant"&&Array.isArray(n.tool_calls))for(let s of n.tool_calls)t.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:typeof s.arguments=="string"?s.arguments:JSON.stringify(s.arguments??{})});(r==="system"||r==="user"||r==="assistant")&&t.push({role:r,content:n.content??""})}return t}async responses(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/responses`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),input:this.toResponsesInput(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_output_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning:{effort:"medium"}}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=Array.isArray(n.output)?n.output:[],s=r.filter(a=>a?.type==="function_call").map(a=>({id:String(a.call_id??a.id??""),name:String(a.name??""),arguments:ds(a.arguments)}));return{content:r.filter(a=>a?.type==="message").flatMap(a=>Array.isArray(a?.content)?a.content:[]).filter(a=>a?.type==="output_text").map(a=>String(a.text??"")).join(`
262
+ `).trim()||null,toolCalls:s,finishReason:s.length?"tool_calls":n.status??"stop",usage:{prompt_tokens:n.usage?.input_tokens??0,completion_tokens:n.usage?.output_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:null}}async chat(e){try{return Y(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(ne(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as ja}from"nanoid";var ur=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let d=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let p of d){let h=p.function;h?.name&&l.push({functionCall:{name:h.name,args:this.parseToolArgs(h.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
263
263
 
264
- `)}]});let s=(e.tools??[]).map(i=>i).filter(i=>i.type==="function"&&i.function?.name).map(i=>({name:i.function.name,description:i.function?.description??"",parameters:i.function?.parameters??{type:"object",properties:{}}}));return s.length&&(r.tools=[{functionDeclarations:s}],r.toolConfig={functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{Y(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],u=c.filter(v=>typeof v?.text=="string").map(v=>String(v.text)),g=c.filter(v=>v?.functionCall?.name).map(v=>({id:Ma(9),name:String(v.functionCall.name),arguments:this.parseToolArgs(v.functionCall.args)})),h={};a?.usageMetadata&&(h.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),h.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),h.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let T=String(l?.finishReason??"STOP").toLowerCase();return{content:u.length?u.join(`
265
- `):null,toolCalls:g,finishReason:T,usage:h,reasoningContent:null}}catch(t){if(te(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as $a}from"nanoid";le();var ur=class o{constructor(e,t,n,r){this.apiKey=e;this.apiBase=t;this.defaultModel=n;this.providerName=r}static DEFAULT_BASE_BY_PROVIDER={openrouter:"https://openrouter.ai/api/v1",openai:"https://api.openai.com/v1",deepseek:"https://api.deepseek.com/v1",groq:"https://api.groq.com/openai/v1",moonshot:"https://api.moonshot.ai/v1",minimax:"https://api.minimax.io/v1",dashscope:"https://dashscope.aliyuncs.com/compatible-mode/v1",zhipu:"https://open.bigmodel.cn/api/paas/v4",siliconflow:"https://api.siliconflow.cn/v1",volcengine:"https://ark.cn-beijing.volces.com/api/v3",vllm:"http://localhost:8000/v1",ollama:"http://localhost:11434/v1",zai:"https://api.z.ai/api/coding/paas/v4"};static UNSUPPORTED_PROVIDERS=new Set(["anthropic","gemini","openai_codex","github_copilot"]);getDefaultModel(){return this.defaultModel}resolveModel(e){let t=n=>n.toLowerCase().replace(/-/g,"_");if(e.includes("/")){let n=e.split("/",2),r=n[0],s=n[1];if(!r||!s)return e;if(t(r)==="github_copilot")return`github_copilot/${s}`;if(t(r)==="openai_codex")return`openai_codex/${s}`;if(t(r)==="groq")return s==="compound"||s==="compound-mini"?`groq/${s}`:s;if(t(r)==="ollama")return s}return e}async chat(e){let n={model:this.resolveModel(e.model??this.defaultModel),messages:rn(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice="auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{Y(e.signal);let r=(this.providerName??"").trim();if(r&&o.UNSUPPORTED_PROVIDERS.has(r))return{content:`Error calling LLM: provider '${r}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=this.apiBase??(r?o.DEFAULT_BASE_BY_PROVIDER[r]:void 0)??(this.apiKey?.startsWith("sk-or-")?o.DEFAULT_BASE_BY_PROVIDER.openrouter:void 0);if(!s)return{content:`Error calling LLM: api_base not configured. Set provider/api_base in ${at} or run everclaw onboard.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(`${s.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(n),...e.signal?{signal:e.signal}:{}}),l=await a.json();if(!a.ok){let g=l?.error?.code??"",h=l?.error?.message??JSON.stringify(l);return g==="model_not_found"?{content:`Error calling LLM: ${h}
266
- ${r==="groq"?"Try a Groq-supported model like llama-3.3-70b-versatile or openai/gpt-oss-120b. You can run `everclaw doctor`.":"Check your model id and provider access. You can run `everclaw doctor`."}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}:{content:`Error calling LLM: ${h}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let u=(c.message.tool_calls??[]).map(g=>({id:$a(9),name:g.function.name,arguments:typeof g.function.arguments=="string"?JSON.parse(g.function.arguments||"{}"):g.function.arguments}));return{content:c.message.content??null,toolCalls:u,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(te(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function Me(o){let e=o.agents.defaults.model,t=Xe(o,e),n=Mo(o,e),r=t&&ct(t)?Ct(o,t,e):null,s=new Set(["openai_codex","github_copilot"]),i=new Set(["anthropic"]);if(!t)throw new Error("No provider could be resolved from config. Run `everclaw onboard` and set provider/model/API key.");if(ct(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${at}.`);if(i.has(t))throw new Error(`Provider '${t}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`);if(!s.has(t)&&t!=="vllm"&&t!=="custom"&&!ct(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${at}.`);return t==="custom"||ct(t)?new cr(n?.apiKey||r?.apiKey||"no-key",kn(o,e)||r?.baseUrl||"http://localhost:8000/v1",e,{providerLabel:r?.name??t,apiFormat:r?.apiFormat,extraHeaders:r?.extraHeaders??n?.extraHeaders??null}):t==="gemini"?new dr(n?.apiKey||"",kn(o,e),e):new ur(n?.apiKey??null,kn(o,e),e,t)}sn();var mr=class extends W{constructor(t,n,r,s,i,a){super();this.serverName=t;this.remoteName=n;this.manager=a;this.name=r,this.description=s,this.parameters=i}name;description;parameters;validateParams(t){return[]}async execute(t,n){return this.manager.callTool(this.serverName,this.remoteName,t,n)}};function eo(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function ja(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function Fa(o,e=200){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var Nt=class o{constructor(e){this.input=e;let t=cs.resolve(e.workspace);this.context=new gt(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new Qe(t);this.sessions=n,this.lifecycle=e.lifecycle??Ye();let r=e.model??e.provider.getDefaultModel();this.subagents=new or(e.bus,e.subagentExecutor??new nr,e.subagentInlineExecutor??new rr(n),{workspace:t,model:r,temperature:e.temperature??.1,maxTokens:e.maxTokens??4096,braveApiKey:e.braveApiKey??null,execConfig:e.execConfig??{timeout:60,pathAppend:""},restrictToWorkspace:!!e.restrictToWorkspace}),this.tools=this.createToolRegistry();let s=Math.max(0,e.overloadControl?.maxQueuedPerSession??o.DEFAULT_MAX_QUEUED_PER_SESSION);this.maxRequestsPerWindow=Math.max(1,e.overloadControl?.maxRequestsPerWindow??o.DEFAULT_MAX_REQUESTS_PER_WINDOW),this.rateLimitWindowMs=Math.max(1,e.overloadControl?.rateLimitWindowMs??o.DEFAULT_RATE_LIMIT_WINDOW_MS),this.runtime=new sr(Math.max(1,e.maxConcurrentSessions??4),s)}context;sessions;tools;subagents;runtime;lifecycle;running=!1;acceptingWork=!0;consolidating=new Set;activeControllers=new Map;activeDispatches=new Set;mcpManager=new on;recentInboundBySession=new Map;static CANCELLED_SENTINEL=Symbol("cancelled");static TOOL_RESULT_MAX_CHARS=500;static SHUTDOWN_MESSAGE="Gateway is shutting down. Please try again later.";static SESSION_BUSY_MESSAGE="This session is busy right now. Please wait for the current response before sending more messages.";static DEFAULT_MAX_QUEUED_PER_SESSION=1;static DEFAULT_MAX_REQUESTS_PER_WINDOW=6;static DEFAULT_RATE_LIMIT_WINDOW_MS=3e4;maxRequestsPerWindow;rateLimitWindowMs;rateLimited=0;lastRateLimitedAt=null;get model(){return this.input.model??this.input.provider.getDefaultModel()}get channelsConfig(){return this.input.channelsConfig}isToolCallingEnabled(e=this.model){if(!this.input.loadConfig)return!0;let t=this.input.loadConfig(),n=xn(t,e);return n&&typeof n.toolCalling=="boolean"?n.toolCalling:!0}isReasoningEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=xn(t,e);return n&&typeof n.reasoning=="boolean"?n.reasoning:!1}isImageOutputEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=xn(t,e);return n&&typeof n.imageOutput=="boolean"?n.imageOutput:!1}resolveTurnModel(e){let t=String(e?._model??"").trim(),n=String(e?._provider??"").trim();if(!t||!this.input.loadConfig)return{model:this.model,provider:this.input.provider};let r=structuredClone(this.input.loadConfig());return r.agents.defaults.model=t,r.agents.defaults.provider=n||"auto",{model:t,provider:Me(r)}}getRuntimeState(){let e=this.runtime.snapshot();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(t=>t.queued>0).length,queuedMessages:e.queued,subagents:this.subagents.getRunningCount(),sessions:e.sessions,overload:{maxQueuedPerSession:e.maxQueuedPerKey,maxRequestsPerWindow:this.maxRequestsPerWindow,rateLimitWindowMs:this.rateLimitWindowMs,rateLimited:this.rateLimited,backpressured:e.backpressured,lastRateLimitedAt:this.lastRateLimitedAt,lastBackpressureAt:e.lastBackpressureAt}}}rateLimitMessage(e){return`This session is receiving messages too quickly. Please wait ${Math.max(1,Math.ceil(e/1e3))}s and try again.`}pruneRecentInbound(e,t=Date.now()){let n=(this.recentInboundBySession.get(e)??[]).filter(r=>t-r<this.rateLimitWindowMs);return n.length?this.recentInboundBySession.set(e,n):this.recentInboundBySession.delete(e),n}checkRateLimit(e){let t=Date.now(),n=this.pruneRecentInbound(e,t);if(n.length>=this.maxRequestsPerWindow){this.rateLimited+=1,this.lastRateLimitedAt=new Date(t).toISOString();let r=n[0];return r!=null?Math.max(1,this.rateLimitWindowMs-(t-r)):this.rateLimitWindowMs}return n.push(t),this.recentInboundBySession.set(e,n),null}makeDirectResult(e,t,n){return n==null?{outcome:e,content:t}:{outcome:e,content:t,retryAfterMs:n}}rejectIfOverloaded(e,t){if(e.channel==="system")return null;let n=this.checkRateLimit(t);return n==null?null:this.makeDirectResult("rate_limited",this.rateLimitMessage(n),n)}mapRuntimeResult(e){return e.status==="cancelled"?this.makeDirectResult("cancelled","Task was cancelled."):e.status==="rejected"?this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE):this.makeDirectResult("completed",e.value?.content??"")}async publishDirectResult(e,t,n){let r=t.outcome==="rate_limited"?{...n,_overload:t.outcome,_retry_after_ms:t.retryAfterMs??0}:t.outcome==="backpressure"?{...n,_overload:t.outcome}:n??{};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t.content,metadata:r})}async withAgentTurnLifecycle(e,t,n,r){await We(this.lifecycle.beforeAgentTurn,"beforeAgentTurn",{message:e,sessionKey:t,trigger:n});let s=null,i=!1,a=null;try{let l=await r();return s=l.response,i=l.cancelled,s}catch(l){a=l;try{let c=this.sessions.getOrCreate(t);c.messages.push({role:"assistant",content:null,_error:String(l),timestamp:new Date().toISOString()}),c.updatedAt=new Date().toISOString(),this.sessions.save(c)}catch(c){console.error(`[agent] failed to persist error turn for ${t}:`,c)}throw l}finally{await We(this.lifecycle.afterAgentTurn,"afterAgentTurn",{message:e,sessionKey:t,trigger:n,response:s,cancelled:i,error:a})}}createToolRegistry(e){let t=this.input.loadConfig?.(),n=t?.tools?.browserRelay?.enabled??!1,r=t?.tools?.chromeSession?.enabled??!1,s={workspace:cs.resolve(this.input.workspace),restrictToWorkspace:!!this.input.restrictToWorkspace,braveApiKey:this.input.braveApiKey??null,execConfig:this.input.execConfig??{timeout:60,pathAppend:""},bus:this.input.bus,subagents:this.subagents,sessionManager:this.sessions};if(e&&(s.turn=e),this.input.cronService&&(s.cronService=this.input.cronService),this.input.rtkConfig&&(s.rtkConfig=this.input.rtkConfig),this.input.rtkService&&(s.rtkService=this.input.rtkService),this.input.browserRelay&&n&&(s.browserRelay=this.input.browserRelay),r){let a=this.input.chromeSessionConfig??t?.tools?.chromeSession;a&&(s.chromeSessionConfig=a)}let i=tr(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i){let a=[...e],l=null,c=[],u=this.input.maxIterations??40,g=i?.model??this.model,h=i?.provider??this.input.provider,T=this.isToolCallingEnabled(g),v=this.isReasoningEnabled(g),d=this.isImageOutputEnabled(g),b=T?t.getDefinitions():void 0,k=AbortSignal.timeout(12e4),G=s?AbortSignal.any([s,k]):k;for(let L=0;L<u;L++){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Y(s);let N;try{N=await h.chat({messages:a,...b?{tools:b}:{},model:g,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...v?{reasoning:!0}:{},...d?{imageOutput:!0}:{},signal:G})}catch(B){if(te(B)){if(s?.aborted)throw B;return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1}}throw B}if(Y(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let z=N.reasoningContent||ja(N.content);if(z&&n&&r()&&await n(z,{event:"thinking",thinkingContent:z,toolHint:!1}),N.toolCalls.length){let B=eo(N.content);n&&B&&r()&&await n(B,{event:"answer",toolHint:!1});let ae=N.toolCalls.map(J=>({id:J.id,type:"function",function:{name:J.name,arguments:JSON.stringify(J.arguments)}}));n&&r()&&await n(this.toolHint(N.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:ae.map(J=>({...J,status:"running"}))}),this.context.addAssistantMessage(a,B,ae,z);for(let J of N.toolCalls){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Y(s),c.push(J.name);let Z=await t.execute(J.name,J.arguments,s?{signal:s}:{});if(Y(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let A=Z.kind==="cancelled"?"Task was cancelled.":Z.content;if(this.context.addToolResult(a,J.id,J.name,A),n&&r()&&await n(A,{event:"tool_result",toolHint:!0,tool_call:{id:J.id,type:"function",function:{name:J.name,arguments:JSON.stringify(J.arguments)},status:"completed",resultPreview:Fa(A,200)??null}}),Z.kind==="terminal")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!1,terminal:!0};if(Z.kind==="cancelled")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};if(Z.kind==="error"&&!Z.retryable)break}}else{l=eo(N.content),l&&n&&r()&&await n(l,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(a,l,void 0,z);break}}return l==null&&(l=`I reached the maximum number of tool call iterations (${u}) without completing the task.`),{finalContent:l,toolsUsed:c,messages:a,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${Zr(e)}:`,r));this.activeDispatches.add(n),n.finally(()=>this.activeDispatches.delete(n))}}stop(){this.running=!1}beginShutdown(){this.acceptingWork=!1}async shutdown(){this.beginShutdown(),this.running=!1;let e=await this.stopAllSessions();return this.activeDispatches.size>0&&await Promise.race([Promise.allSettled(this.activeDispatches),new Promise(n=>setTimeout(n,1e4))]),await this.mcpManager.closeAll(),await this.input.bus.publishInbound({channel:"system",senderId:"system",chatId:"gateway:shutdown",content:"",metadata:{_shutdown:!0}}),e}async processDirect(e,t="cli:direct",n="cli",r="direct",s){return(await this.processDirectResult(e,t,n,r,s)).content}async processDirectResult(e,t="cli:direct",n="cli",r="direct",s,i){let a={channel:n,senderId:"user",chatId:r,content:e,sessionKeyOverride:t,...i?{metadata:i}:{}};if((typeof e=="string"?e:e.find(g=>g.type==="text")?.text??"").trim().toLowerCase()==="/stop"){let g=await this.stopSession(t);return this.makeDirectResult("completed",g?`Stopped ${g} task(s).`:"No active task to stop.")}if(!this.acceptingWork)return this.makeDirectResult("shutdown",o.SHUTDOWN_MESSAGE);let c=this.rejectIfOverloaded(a,t);if(c)return c;let u=await this.runtime.enqueue(t,({isCurrent:g})=>this.withSessionController(t,h=>this.processMessage(a,t,s,g,h,"direct")));return u.status==="completed"&&u.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(u)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(te(r))return o.CANCELLED_SENTINEL;throw r}finally{this.activeControllers.get(e)===n&&this.activeControllers.delete(e)}}resolveSessionContext(e,t){let n=e.metadata?.message_id;if(e.channel==="system"){let r=String(e.chatId),s=r.includes(":"),i=s?r.split(/:(.*)/s,2)[0]:"cli",a=s?r.split(/:(.*)/s,2)[1]:r,l={key:`${i}:${a}`,channel:i,chatId:a};return n&&(l.messageId=n),l}return{key:t??Zr(e),channel:e.channel,chatId:e.chatId,...n?{messageId:n}:{}}}memoryNamespace(e){return e.includes(":")&&e.replace(/:/g,"_")||void 0}async consolidateMemory(e,t=!1,n=this.input.provider,r=this.model){return this.context.getMemoryStore(this.memoryNamespace(e.key)).consolidate(e,n,r,{archiveAll:t,memoryWindow:this.input.memoryWindow??100})}saveTurn(e,t,n,r){let s=t.slice(n);for(let i=0;i<s.length;i++){let l={...s[i]};l.role==="assistant"&&typeof l.content=="string"&&(l.content=eo(l.content)),l.role==="tool"&&typeof l.content=="string"&&l.content.length>o.TOOL_RESULT_MAX_CHARS&&(l._full_content=l.content,l.content=`${l.content.slice(0,o.TOOL_RESULT_MAX_CHARS)}
267
- ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(gt.RUNTIME_CONTEXT_TAG))&&(l.timestamp||(l.timestamp=new Date().toISOString()),l.role==="assistant"&&r?.length&&i===s.length-1&&(l.tools_used=r),e.messages.push(l))}e.updatedAt=new Date().toISOString()}sanitizeInput(e,t){if(!t.security?.enabled||!t.security.inputSanitizer?.enabled)return e;let n=new lr(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){return e==="/new"?t.messages.length&&!await this.consolidateMemory(t,!0,r.provider,r.model)?{response:{channel:n.channel,chatId:n.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(t.clear(),this.sessions.save(t),this.sessions.invalidate(t.key),{response:{channel:n.channel,chatId:n.chatId,content:"New session started."},cancelled:!1}):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
264
+ `)}]});let s=(e.tools??[]).map(i=>i).filter(i=>i.type==="function"&&i.function?.name).map(i=>({name:i.function.name,description:i.function?.description??"",parameters:i.function?.parameters??{type:"object",properties:{}}}));return s.length&&(r.tools=[{functionDeclarations:s}],r.toolConfig={functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{Y(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],d=c.filter(v=>typeof v?.text=="string").map(v=>String(v.text)),p=c.filter(v=>v?.functionCall?.name).map(v=>({id:ja(9),name:String(v.functionCall.name),arguments:this.parseToolArgs(v.functionCall.args)})),h={};a?.usageMetadata&&(h.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),h.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),h.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let w=String(l?.finishReason??"STOP").toLowerCase();return{content:d.length?d.join(`
265
+ `):null,toolCalls:p,finishReason:w,usage:h,reasoningContent:null}}catch(t){if(ne(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Fa}from"nanoid";ce();var gr=class o{constructor(e,t,n,r){this.apiKey=e;this.apiBase=t;this.defaultModel=n;this.providerName=r}static DEFAULT_BASE_BY_PROVIDER={openrouter:"https://openrouter.ai/api/v1",openai:"https://api.openai.com/v1",deepseek:"https://api.deepseek.com/v1",groq:"https://api.groq.com/openai/v1",moonshot:"https://api.moonshot.ai/v1",minimax:"https://api.minimax.io/v1",dashscope:"https://dashscope.aliyuncs.com/compatible-mode/v1",zhipu:"https://open.bigmodel.cn/api/paas/v4",siliconflow:"https://api.siliconflow.cn/v1",volcengine:"https://ark.cn-beijing.volces.com/api/v3",vllm:"http://localhost:8000/v1",ollama:"http://localhost:11434/v1",zai:"https://api.z.ai/api/coding/paas/v4"};static UNSUPPORTED_PROVIDERS=new Set(["anthropic","gemini","openai_codex","github_copilot"]);getDefaultModel(){return this.defaultModel}resolveModel(e){let t=n=>n.toLowerCase().replace(/-/g,"_");if(e.includes("/")){let n=e.split("/",2),r=n[0],s=n[1];if(!r||!s)return e;if(t(r)==="github_copilot")return`github_copilot/${s}`;if(t(r)==="openai_codex")return`openai_codex/${s}`;if(t(r)==="groq")return s==="compound"||s==="compound-mini"?`groq/${s}`:s;if(t(r)==="ollama")return s}return e}async chat(e){let n={model:this.resolveModel(e.model??this.defaultModel),messages:rn(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice="auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{Y(e.signal);let r=(this.providerName??"").trim();if(r&&o.UNSUPPORTED_PROVIDERS.has(r))return{content:`Error calling LLM: provider '${r}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=this.apiBase??(r?o.DEFAULT_BASE_BY_PROVIDER[r]:void 0)??(this.apiKey?.startsWith("sk-or-")?o.DEFAULT_BASE_BY_PROVIDER.openrouter:void 0);if(!s)return{content:`Error calling LLM: api_base not configured. Set provider/api_base in ${at} or run everclaw onboard.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(`${s.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(n),...e.signal?{signal:e.signal}:{}}),l=await a.json();if(!a.ok){let p=l?.error?.code??"",h=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${h}
266
+ ${r==="groq"?"Try a Groq-supported model like llama-3.3-70b-versatile or openai/gpt-oss-120b. You can run `everclaw doctor`.":"Check your model id and provider access. You can run `everclaw doctor`."}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}:{content:`Error calling LLM: ${h}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let d=(c.message.tool_calls??[]).map(p=>({id:Fa(9),name:p.function.name,arguments:typeof p.function.arguments=="string"?JSON.parse(p.function.arguments||"{}"):p.function.arguments}));return{content:c.message.content??null,toolCalls:d,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(ne(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function $e(o){let e=o.agents.defaults.model,t=Xe(o,e),n=$o(o,e),r=t&&ct(t)?Tt(o,t,e):null,s=new Set(["openai_codex","github_copilot"]),i=new Set(["anthropic"]);if(!t)throw new Error("No provider could be resolved from config. Run `everclaw onboard` and set provider/model/API key.");if(ct(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${at}.`);if(i.has(t))throw new Error(`Provider '${t}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`);if(!s.has(t)&&t!=="vllm"&&t!=="custom"&&!ct(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${at}.`);return t==="custom"||ct(t)?new dr(n?.apiKey||r?.apiKey||"no-key",kn(o,e)||r?.baseUrl||"http://localhost:8000/v1",e,{providerLabel:r?.name??t,apiFormat:r?.apiFormat,extraHeaders:r?.extraHeaders??n?.extraHeaders??null}):t==="gemini"?new ur(n?.apiKey||"",kn(o,e),e):new gr(n?.apiKey??null,kn(o,e),e,t)}sn();var pr=class extends G{constructor(t,n,r,s,i,a){super();this.serverName=t;this.remoteName=n;this.manager=a;this.name=r,this.description=s,this.parameters=i}name;description;parameters;validateParams(t){return[]}async execute(t,n){return this.manager.callTool(this.serverName,this.remoteName,t,n)}};function to(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function Ka(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function qa(o,e=200){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var Nt=class o{constructor(e){this.input=e;let t=gs.resolve(e.workspace);this.context=new mt(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new Qe(t);this.sessions=n,this.lifecycle=e.lifecycle??Ye();let r=e.model??e.provider.getDefaultModel();this.subagents=new sr(e.bus,e.subagentExecutor??new rr,e.subagentInlineExecutor??new or(n),{workspace:t,model:r,temperature:e.temperature??.1,maxTokens:e.maxTokens??4096,braveApiKey:e.braveApiKey??null,execConfig:e.execConfig??{timeout:60,pathAppend:""},restrictToWorkspace:!!e.restrictToWorkspace}),this.tools=this.createToolRegistry();let s=Math.max(0,e.overloadControl?.maxQueuedPerSession??o.DEFAULT_MAX_QUEUED_PER_SESSION);this.maxRequestsPerWindow=Math.max(1,e.overloadControl?.maxRequestsPerWindow??o.DEFAULT_MAX_REQUESTS_PER_WINDOW),this.rateLimitWindowMs=Math.max(1,e.overloadControl?.rateLimitWindowMs??o.DEFAULT_RATE_LIMIT_WINDOW_MS),this.runtime=new ir(Math.max(1,e.maxConcurrentSessions??4),s)}context;sessions;tools;subagents;runtime;lifecycle;running=!1;acceptingWork=!0;consolidating=new Set;activeControllers=new Map;activeDispatches=new Set;mcpManager=new on;recentInboundBySession=new Map;static CANCELLED_SENTINEL=Symbol("cancelled");static TOOL_RESULT_MAX_CHARS=500;static SHUTDOWN_MESSAGE="Gateway is shutting down. Please try again later.";static SESSION_BUSY_MESSAGE="This session is busy right now. Please wait for the current response before sending more messages.";static DEFAULT_MAX_QUEUED_PER_SESSION=1;static DEFAULT_MAX_REQUESTS_PER_WINDOW=6;static DEFAULT_RATE_LIMIT_WINDOW_MS=3e4;maxRequestsPerWindow;rateLimitWindowMs;rateLimited=0;lastRateLimitedAt=null;get model(){return this.input.model??this.input.provider.getDefaultModel()}get channelsConfig(){return this.input.channelsConfig}isToolCallingEnabled(e=this.model){if(!this.input.loadConfig)return!0;let t=this.input.loadConfig(),n=Cn(t,e);return n&&typeof n.toolCalling=="boolean"?n.toolCalling:!0}isReasoningEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=Cn(t,e);return n&&typeof n.reasoning=="boolean"?n.reasoning:!1}isImageOutputEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=Cn(t,e);return n&&typeof n.imageOutput=="boolean"?n.imageOutput:!1}resolveTurnModel(e){let t=String(e?._model??"").trim(),n=String(e?._provider??"").trim();if(!t||!this.input.loadConfig)return{model:this.model,provider:this.input.provider};let r=structuredClone(this.input.loadConfig());return r.agents.defaults.model=t,r.agents.defaults.provider=n||"auto",{model:t,provider:$e(r)}}getRuntimeState(){let e=this.runtime.snapshot();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(t=>t.queued>0).length,queuedMessages:e.queued,subagents:this.subagents.getRunningCount(),sessions:e.sessions,overload:{maxQueuedPerSession:e.maxQueuedPerKey,maxRequestsPerWindow:this.maxRequestsPerWindow,rateLimitWindowMs:this.rateLimitWindowMs,rateLimited:this.rateLimited,backpressured:e.backpressured,lastRateLimitedAt:this.lastRateLimitedAt,lastBackpressureAt:e.lastBackpressureAt}}}rateLimitMessage(e){return`This session is receiving messages too quickly. Please wait ${Math.max(1,Math.ceil(e/1e3))}s and try again.`}pruneRecentInbound(e,t=Date.now()){let n=(this.recentInboundBySession.get(e)??[]).filter(r=>t-r<this.rateLimitWindowMs);return n.length?this.recentInboundBySession.set(e,n):this.recentInboundBySession.delete(e),n}checkRateLimit(e){let t=Date.now(),n=this.pruneRecentInbound(e,t);if(n.length>=this.maxRequestsPerWindow){this.rateLimited+=1,this.lastRateLimitedAt=new Date(t).toISOString();let r=n[0];return r!=null?Math.max(1,this.rateLimitWindowMs-(t-r)):this.rateLimitWindowMs}return n.push(t),this.recentInboundBySession.set(e,n),null}makeDirectResult(e,t,n){return n==null?{outcome:e,content:t}:{outcome:e,content:t,retryAfterMs:n}}rejectIfOverloaded(e,t){if(e.channel==="system")return null;let n=this.checkRateLimit(t);return n==null?null:this.makeDirectResult("rate_limited",this.rateLimitMessage(n),n)}mapRuntimeResult(e){return e.status==="cancelled"?this.makeDirectResult("cancelled","Task was cancelled."):e.status==="rejected"?this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE):this.makeDirectResult("completed",e.value?.content??"")}async publishDirectResult(e,t,n){let r=t.outcome==="rate_limited"?{...n,_overload:t.outcome,_retry_after_ms:t.retryAfterMs??0}:t.outcome==="backpressure"?{...n,_overload:t.outcome}:n??{};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t.content,metadata:r})}async withAgentTurnLifecycle(e,t,n,r){await We(this.lifecycle.beforeAgentTurn,"beforeAgentTurn",{message:e,sessionKey:t,trigger:n});let s=null,i=!1,a=null;try{let l=await r();return s=l.response,i=l.cancelled,s}catch(l){a=l;try{let c=this.sessions.getOrCreate(t);c.messages.push({role:"assistant",content:null,_error:String(l),timestamp:new Date().toISOString()}),c.updatedAt=new Date().toISOString(),this.sessions.save(c)}catch(c){console.error(`[agent] failed to persist error turn for ${t}:`,c)}throw l}finally{await We(this.lifecycle.afterAgentTurn,"afterAgentTurn",{message:e,sessionKey:t,trigger:n,response:s,cancelled:i,error:a})}}createToolRegistry(e){let t=this.input.loadConfig?.(),n=t?.tools?.browserRelay?.enabled??!1,r=t?.tools?.chromeSession?.enabled??!1,s={workspace:gs.resolve(this.input.workspace),restrictToWorkspace:!!this.input.restrictToWorkspace,braveApiKey:this.input.braveApiKey??null,execConfig:this.input.execConfig??{timeout:60,pathAppend:""},bus:this.input.bus,subagents:this.subagents,sessionManager:this.sessions};if(e&&(s.turn=e),this.input.cronService&&(s.cronService=this.input.cronService),this.input.rtkConfig&&(s.rtkConfig=this.input.rtkConfig),this.input.rtkService&&(s.rtkService=this.input.rtkService),this.input.browserRelay&&n&&(s.browserRelay=this.input.browserRelay),r){let a=this.input.chromeSessionConfig??t?.tools?.chromeSession;a&&(s.chromeSessionConfig=a)}let i=nr(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i){let a=[...e],l=null,c=[],d=this.input.maxIterations??40,p=i?.model??this.model,h=i?.provider??this.input.provider,w=this.isToolCallingEnabled(p),v=this.isReasoningEnabled(p),u=this.isImageOutputEnabled(p),b=w?t.getDefinitions():void 0,C=AbortSignal.timeout(12e4),N=s?AbortSignal.any([s,C]):C;for(let q=0;q<d;q++){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Y(s);let I;try{I=await h.chat({messages:a,...b?{tools:b}:{},model:p,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...v?{reasoning:!0}:{},...u?{imageOutput:!0}:{},signal:N})}catch(Q){if(ne(Q)){if(s?.aborted)throw Q;return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1}}throw Q}if(Y(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let J=I.reasoningContent||Ka(I.content);if(J&&n&&r()&&await n(J,{event:"thinking",thinkingContent:J,toolHint:!1}),I.toolCalls.length){let Q=to(I.content);n&&Q&&r()&&await n(Q,{event:"answer",toolHint:!1});let z=I.toolCalls.map(W=>({id:W.id,type:"function",function:{name:W.name,arguments:JSON.stringify(W.arguments)}}));n&&r()&&await n(this.toolHint(I.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:z.map(W=>({...W,status:"running"}))}),this.context.addAssistantMessage(a,Q,z,J);for(let W of I.toolCalls){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Y(s),c.push(W.name);let X=await t.execute(W.name,W.arguments,s?{signal:s}:{});if(Y(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let ae=X.kind==="cancelled"?"Task was cancelled.":X.content;if(this.context.addToolResult(a,W.id,W.name,ae),n&&r()&&await n(ae,{event:"tool_result",toolHint:!0,tool_call:{id:W.id,type:"function",function:{name:W.name,arguments:JSON.stringify(W.arguments)},status:"completed",resultPreview:qa(ae,200)??null}}),X.kind==="terminal")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!1,terminal:!0};if(X.kind==="cancelled")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};if(X.kind==="error"&&!X.retryable)break}}else{l=to(I.content),l&&n&&r()&&await n(l,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(a,l,void 0,J);break}}return l==null&&(l=`I reached the maximum number of tool call iterations (${d}) without completing the task.`),{finalContent:l,toolsUsed:c,messages:a,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${eo(e)}:`,r));this.activeDispatches.add(n),n.finally(()=>this.activeDispatches.delete(n))}}stop(){this.running=!1}beginShutdown(){this.acceptingWork=!1}async shutdown(){this.beginShutdown(),this.running=!1;let e=await this.stopAllSessions();return this.activeDispatches.size>0&&await Promise.race([Promise.allSettled(this.activeDispatches),new Promise(n=>setTimeout(n,1e4))]),await this.mcpManager.closeAll(),await this.input.bus.publishInbound({channel:"system",senderId:"system",chatId:"gateway:shutdown",content:"",metadata:{_shutdown:!0}}),e}async processDirect(e,t="cli:direct",n="cli",r="direct",s){return(await this.processDirectResult(e,t,n,r,s)).content}async processDirectResult(e,t="cli:direct",n="cli",r="direct",s,i){let a={channel:n,senderId:"user",chatId:r,content:e,sessionKeyOverride:t,...i?{metadata:i}:{}};if((typeof e=="string"?e:e.find(p=>p.type==="text")?.text??"").trim().toLowerCase()==="/stop"){let p=await this.stopSession(t);return this.makeDirectResult("completed",p?`Stopped ${p} task(s).`:"No active task to stop.")}if(!this.acceptingWork)return this.makeDirectResult("shutdown",o.SHUTDOWN_MESSAGE);let c=this.rejectIfOverloaded(a,t);if(c)return c;let d=await this.runtime.enqueue(t,({isCurrent:p})=>this.withSessionController(t,h=>this.processMessage(a,t,s,p,h,"direct")));return d.status==="completed"&&d.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(d)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(ne(r))return o.CANCELLED_SENTINEL;throw r}finally{this.activeControllers.get(e)===n&&this.activeControllers.delete(e)}}resolveSessionContext(e,t){let n=e.metadata?.message_id;if(e.channel==="system"){let r=String(e.chatId),s=r.includes(":"),i=s?r.split(/:(.*)/s,2)[0]:"cli",a=s?r.split(/:(.*)/s,2)[1]:r,l={key:`${i}:${a}`,channel:i,chatId:a};return n&&(l.messageId=n),l}return{key:t??eo(e),channel:e.channel,chatId:e.chatId,...n?{messageId:n}:{}}}memoryNamespace(e){return e.includes(":")&&e.replace(/:/g,"_")||void 0}async consolidateMemory(e,t=!1,n=this.input.provider,r=this.model){return this.context.getMemoryStore(this.memoryNamespace(e.key)).consolidate(e,n,r,{archiveAll:t,memoryWindow:this.input.memoryWindow??100})}saveTurn(e,t,n,r){let s=t.slice(n);for(let i=0;i<s.length;i++){let l={...s[i]};l.role==="assistant"&&typeof l.content=="string"&&(l.content=to(l.content)),l.role==="tool"&&typeof l.content=="string"&&l.content.length>o.TOOL_RESULT_MAX_CHARS&&(l._full_content=l.content,l.content=`${l.content.slice(0,o.TOOL_RESULT_MAX_CHARS)}
267
+ ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(mt.RUNTIME_CONTEXT_TAG))&&(l.timestamp||(l.timestamp=new Date().toISOString()),l.role==="assistant"&&r?.length&&i===s.length-1&&(l.tools_used=r),e.messages.push(l))}e.updatedAt=new Date().toISOString()}sanitizeInput(e,t){if(!t.security?.enabled||!t.security.inputSanitizer?.enabled)return e;let n=new cr(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){return e==="/new"?t.messages.length&&!await this.consolidateMemory(t,!0,r.provider,r.model)?{response:{channel:n.channel,chatId:n.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(t.clear(),this.sessions.save(t),this.sessions.invalidate(t.key),{response:{channel:n.channel,chatId:n.chatId,content:"New session started."},cancelled:!1}):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
268
268
  /new - Start a new conversation
269
269
  /stop - Stop the current task
270
- /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n){let r=this.createToolRegistry(t);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let s of n)try{let i=await this.mcpManager.getServerTools(s);for(let a of i)r.register(new mr(a.serverName,a.remoteName,a.proxyName,a.description,a.inputSchema,this.mcpManager))}catch(i){console.warn(`MCP: failed to connect to '${s}': ${String(i)}`)}}return r}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(fe);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),u=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let{messages:q,newMessageStartIndex:re}=this.buildTurnPrompt(c,e,l,[]),p=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[]),{finalContent:m,messages:f,toolsUsed:w,cancelled:x,terminal:E}=await this.runAgentLoop(q,p,void 0,r,s,u);return x||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,f,re,w),{response:{channel:a.channel,chatId:a.chatId,content:m??"Background task completed."},cancelled:!1})}let h=(typeof e.content=="string"?e.content:e.content.find(q=>q.type==="text")?.text??"").trim().toLowerCase(),T=await this.resolveCommand(h,c,e,u);if(T)return T;let d=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],O=new Set(Object.keys(l?.tools?.mcpServers??{})),k=b.filter(q=>O.has(q)),G=b.filter(q=>!O.has(q)),L=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},k),{messages:N,newMessageStartIndex:z}=this.buildTurnPrompt(c,e,l,G),B=async(q,re)=>{if(!r())return;let p={...e.metadata,_progress:!0,_tool_hint:!!re?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:q,metadata:p})},{finalContent:ae,messages:J,toolsUsed:Z,cancelled:A,terminal:I}=await this.runAgentLoop(N,L,n??B,r,s,u);if(A||!r())return{response:null,cancelled:!0};let F=ae??"I've completed processing but have no response to give.";if(this.commitTurn(c,J,z,Z),d){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,u.provider,u.model)}finally{this.consolidating.delete(c.key)}}return I?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:F,metadata:e.metadata??{}},cancelled:!1}})}};Nr();pt();var Ba=1024*1024,Ua=300*1e3;function ds(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function Ga(o,e,t){let n=ds(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
270
+ /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n){let r=this.createToolRegistry(t);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let s of n)try{let i=await this.mcpManager.getServerTools(s);for(let a of i)r.register(new pr(a.serverName,a.remoteName,a.proxyName,a.description,a.inputSchema,this.mcpManager))}catch(i){console.warn(`MCP: failed to connect to '${s}': ${String(i)}`)}}return r}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),t.metadata&&(l.metadata=t.metadata),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(de);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),d=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let{messages:D,newMessageStartIndex:ee}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[]),{finalContent:g,messages:f,toolsUsed:k,cancelled:x,terminal:E}=await this.runAgentLoop(D,m,void 0,r,s,d);return x||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,f,ee,k),{response:{channel:a.channel,chatId:a.chatId,content:g??"Background task completed."},cancelled:!1})}let h=(typeof e.content=="string"?e.content:e.content.find(D=>D.type==="text")?.text??"").trim().toLowerCase(),w=await this.resolveCommand(h,c,e,d);if(w)return w;let u=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],P=new Set(Object.keys(l?.tools?.mcpServers??{})),C=b.filter(D=>P.has(D)),N=b.filter(D=>!P.has(D)),q=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},C),{messages:I,newMessageStartIndex:J}=this.buildTurnPrompt(c,e,l,N),Q=async(D,ee)=>{if(!r())return;let m={...e.metadata,_progress:!0,_tool_hint:!!ee?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:D,metadata:m})},{finalContent:z,messages:W,toolsUsed:X,cancelled:ae,terminal:T}=await this.runAgentLoop(I,q,n??Q,r,s,d);if(ae||!r())return{response:null,cancelled:!0};let j=z??"I've completed processing but have no response to give.";if(this.commitTurn(c,W,J,X),u){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,d.provider,d.model)}finally{this.consolidating.delete(c.key)}}return T?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:j,metadata:e.metadata??{}},cancelled:!1}})}};jr();ft();var Ja=1024*1024,Ha=300*1e3;function ms(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function za(o,e,t){let n=ms(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
271
271
  ${t.stdout.trim()}`:"",t.stderr.trim()?`STDERR:
272
272
  ${t.stderr.trim()}`:"",typeof t.exitCode=="number"?`Exit code: ${t.exitCode}`:"",t.signal?`Signal: ${t.signal}`:"",t.errorMessage?`Error: ${t.errorMessage}`:""].filter(Boolean).join(`
273
273
  `);return r?`${n} failed
274
- ${r}`:`${n} failed`}function Wa(){let o=process.argv[1]??"";return _t(o)}function pr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(Ua,e)}var to=class{constructor(e,t,n,r=new ye,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(mt(this.target).mode!=="local-process")throw new Error(`${ds(this.target)} requires local-process isolation`);let n=await this.runner.run({command:this.buildCommand(e.payload),cwd:e.cwd,env:e.env??this.defaultEnv,timeoutMs:this.timeoutMs,signal:e.signal,maxCaptureBytes:e.maxCaptureBytes??Ba});if(n.status==="aborted")throw Xt();if(n.status==="ok")return n.stdout;throw new Error(Ga(this.target,this.timeoutMs,n))}};function an(o){let e=Wa();return new to(o.target,o.timeoutMs,t=>({kind:"argv",file:e.file,args:[...e.args,"agent","--message",t.message,"--session",t.session,"--channel",t.channel,"--chat-id",t.chatId,"--raw-output"]}),o.runner,e.env)}var jt=class o{constructor(e,t,n){this.config=e;this.bus=t;this.debounce=n}running=!1;isAllowed(e){let t=this.config?.allowFrom??[];return!t.length||t.includes(String(e))?!0:String(e).includes("|")?String(e).split("|").some(n=>t.includes(n)):!1}static channelColors={telegram:"\x1B[36m",discord:"\x1B[35m"};async handleMessage(e){let t=typeof e.content=="string"?e.content:JSON.stringify(e.content),n=o.channelColors[this.name]??"\x1B[0m",r=t.length>80?t.slice(0,80)+"\u2026":t;if(!this.isAllowed(e.senderId)){console.log(`[${n}${this.name}\x1B[0m] \x1B[31mBLOCKED\x1B[0m from=${e.senderId}`);return}console.log(`[${n}${this.name}\x1B[0m] from=${e.senderId} chat=${e.chatId} "${r}"`);let s={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(s.media=e.media),e.metadata&&Object.keys(e.metadata).length>0&&(s.metadata=e.metadata),e.sessionKey&&(s.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(s)}get isRunning(){return this.running}};var Ft=class{buffers=new Map;config;onEmit;constructor(e,t){this.config=e,this.onEmit=t}submit(e){if(!this.config.enabled){this.onEmit(e);return}let t=`${e.channel}:${e.chatId}`,n=this.buffers.get(t);if(n){clearTimeout(n.quietTimer),n.messages.push(e),n.quietTimer=setTimeout(()=>this.emit(t),this.config.quietMs);return}let r=setTimeout(()=>this.emit(t),this.config.quietMs),s=setTimeout(()=>this.emit(t),this.config.maxWaitMs);this.buffers.set(t,{messages:[e],quietTimer:r,maxTimer:s})}emit(e){let t=this.buffers.get(e);if(!t)return;clearTimeout(t.quietTimer),clearTimeout(t.maxTimer),this.buffers.delete(e);let n=t.messages[0];if(!n)return;let r=t.messages.map(a=>typeof a.content=="string"?a.content:a.content.find(c=>c.type==="text")?.text??JSON.stringify(a.content)).join(`
275
- `),s=t.messages.flatMap(a=>a.media??[]),i=t.messages.reduce((a,l)=>({...a,...l.metadata??{}}),{});this.onEmit({...n,content:r,media:s.length>0?s:void 0,metadata:Object.keys(i).length>0?i:void 0})}flush(){for(let e of this.buffers.keys())this.emit(e)}get size(){return this.buffers.size}};function Ka(o,e=4e3){if(o.length<=e)return[o];let t=[],n=o;for(;n.length>e;){let r=n.slice(0,e),s=Math.max(r.lastIndexOf(`
276
- `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function Ja(o){if(!o)return"[Unsupported message]";if(o.text)return o.text;let e=o.caption?` ${o.caption}`:"";return o.photo?`[Photo]${e}`:o.video?`[Video]${e}`:o.voice?`[Voice message]${e}`:o.audio?`[Audio]${e}`:o.document?`[Document: ${o.document.file_name??"file"}]${e}`:o.sticker?`[Sticker ${o.sticker.emoji??""}]${e}`:o.location?`[Location]${e}`:o.contact?`[Contact]${e}`:`[Unsupported message]${e}`}var qa=new Set(["chatid","ping"]),Ha=3e3,fr=class extends jt{name="telegram";offset=0;inbox;botUsername=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t){super(e,t,e.debounce),this.inbox=new Ft(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}if(!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result?.username&&(this.botUsername=t.result.username.toLowerCase())}}catch{}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=Ja(s);if(l.startsWith("/")&&s.text){let u=l.slice(1).split(/[\s@]/)[0]?.toLowerCase();if(u&&qa.has(u)){await this.handleBotCommand(u,s);continue}}let c={message_id:s.message_id};this.botUsername&&s.text&&s.entities&&s.entities.some(g=>g.type==="mention"?s.text.substring(g.offset,g.offset+g.length).toLowerCase()===`@${this.botUsername}`:g.type==="text_mention")&&(c.bot_mentioned=!0),s.message_thread_id&&(c.thread_id=s.message_thread_id),this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:c,...s.message_thread_id&&{sessionKey:`telegram:${s.chat.id}:${s.message_thread_id}`}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async handleBotCommand(e,t){let n=String(t.chat.id);if(e==="chatid"){let r=t.chat.type??"private",s=r==="private"?t.from?.first_name??t.from?.username??"Private":t.chat.title??"Unknown";await this.sendChunk(n,`Chat ID: \`telegram:${n}\`
274
+ ${r}`:`${n} failed`}function Va(){let o=process.argv[1]??"";return _t(o)}function fr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(Ha,e)}var no=class{constructor(e,t,n,r=new be,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(pt(this.target).mode!=="local-process")throw new Error(`${ms(this.target)} requires local-process isolation`);let n=await this.runner.run({command:this.buildCommand(e.payload),cwd:e.cwd,env:e.env??this.defaultEnv,timeoutMs:this.timeoutMs,signal:e.signal,maxCaptureBytes:e.maxCaptureBytes??Ja});if(n.status==="aborted")throw Xt();if(n.status==="ok")return n.stdout;throw new Error(za(this.target,this.timeoutMs,n))}};function an(o){let e=Va();return new no(o.target,o.timeoutMs,t=>({kind:"argv",file:e.file,args:[...e.args,"agent","--message",t.message,"--session",t.session,"--channel",t.channel,"--chat-id",t.chatId,"--raw-output"]}),o.runner,e.env)}var jt=class o{constructor(e,t,n){this.config=e;this.bus=t;this.debounce=n}running=!1;isAllowed(e){let t=this.config?.allowFrom??[];return!t.length||t.includes(String(e))?!0:String(e).includes("|")?String(e).split("|").some(n=>t.includes(n)):!1}static channelColors={telegram:"\x1B[36m",discord:"\x1B[35m"};async handleMessage(e){let t=typeof e.content=="string"?e.content:JSON.stringify(e.content),n=o.channelColors[this.name]??"\x1B[0m",r=t.length>80?t.slice(0,80)+"\u2026":t;if(!this.isAllowed(e.senderId)){console.log(`[${n}${this.name}\x1B[0m] \x1B[31mBLOCKED\x1B[0m from=${e.senderId}`);return}console.log(`[${n}${this.name}\x1B[0m] from=${e.senderId} chat=${e.chatId} "${r}"`);let s={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(s.media=e.media),e.metadata&&Object.keys(e.metadata).length>0&&(s.metadata=e.metadata),e.sessionKey&&(s.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(s)}get isRunning(){return this.running}};var Ft=class{buffers=new Map;config;onEmit;constructor(e,t){this.config=e,this.onEmit=t}submit(e){if(!this.config.enabled){this.onEmit(e);return}let t=`${e.channel}:${e.chatId}`,n=this.buffers.get(t);if(n){clearTimeout(n.quietTimer),n.messages.push(e),n.quietTimer=setTimeout(()=>this.emit(t),this.config.quietMs);return}let r=setTimeout(()=>this.emit(t),this.config.quietMs),s=setTimeout(()=>this.emit(t),this.config.maxWaitMs);this.buffers.set(t,{messages:[e],quietTimer:r,maxTimer:s})}emit(e){let t=this.buffers.get(e);if(!t)return;clearTimeout(t.quietTimer),clearTimeout(t.maxTimer),this.buffers.delete(e);let n=t.messages[0];if(!n)return;let r=t.messages.map(a=>typeof a.content=="string"?a.content:a.content.find(c=>c.type==="text")?.text??JSON.stringify(a.content)).join(`
275
+ `),s=t.messages.flatMap(a=>a.media??[]),i=t.messages.reduce((a,l)=>({...a,...l.metadata??{}}),{});this.onEmit({...n,content:r,media:s.length>0?s:void 0,metadata:Object.keys(i).length>0?i:void 0})}flush(){for(let e of this.buffers.keys())this.emit(e)}get size(){return this.buffers.size}};function Xa(o,e=4e3){if(o.length<=e)return[o];let t=[],n=o;for(;n.length>e;){let r=n.slice(0,e),s=Math.max(r.lastIndexOf(`
276
+ `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function Ya(o){if(!o)return"[Unsupported message]";if(o.text)return o.text;let e=o.caption?` ${o.caption}`:"";return o.photo?`[Photo]${e}`:o.video?`[Video]${e}`:o.voice?`[Voice message]${e}`:o.audio?`[Audio]${e}`:o.document?`[Document: ${o.document.file_name??"file"}]${e}`:o.sticker?`[Sticker ${o.sticker.emoji??""}]${e}`:o.location?`[Location]${e}`:o.contact?`[Contact]${e}`:`[Unsupported message]${e}`}function Qa(o){return o.toLowerCase().replace(/[^a-z0-9_]/g,"_").slice(0,32)}var Za=new Set(["chatid","ping"]),el=3e3,hr=class extends jt{name="telegram";offset=0;inbox;botUsername=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t){super(e,t,e.debounce),this.inbox=new Ft(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}if(!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result?.username&&(this.botUsername=t.result.username.toLowerCase(),this.config.commands?.native!==!1&&await this.registerCommands())}}catch{}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=Ya(s);if(l.startsWith("/")&&s.text){let h=l.slice(1).split(/[\s@]/)[0]?.toLowerCase();if(h&&Za.has(h)){await this.handleBotCommand(h,s);continue}}let c={message_id:s.message_id};s.chat.type&&(c.chat_type=s.chat.type);let d=!1;if(this.botUsername&&s.text&&s.entities&&(d=s.entities.some(h=>h.type==="mention"?s.text.substring(h.offset,h.offset+h.length).toLowerCase().trim()===`@${this.botUsername}`:h.type==="text_mention")),s.chat.type==="group"||s.chat.type==="supergroup"){let h=this.config.groups?.allowedGroupIds;if(h!=null&&!h.includes(String(s.chat.id)))continue;if(this.config.groups?.requireMention!==!1){let v=l.startsWith("/"),u=!!s.reply_to_message?.from?.is_bot;if(!d&&!v&&!u)continue}}d&&this.botUsername&&(c.bot_mentioned=!0,s.text&&(l=l.replace(new RegExp(`@${this.botUsername}`,"gi"),"").trim())),s.message_thread_id&&(c.thread_id=s.message_thread_id),this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:c,...s.message_thread_id&&{sessionKey:`telegram:${s.chat.id}:${s.message_thread_id}`}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async registerCommands(){let e=[{command:"chatid",description:"Show this chat's ID for configuration"},{command:"ping",description:"Check if the bot is online"},{command:"new",description:"Start a new conversation session"},{command:"stop",description:"Stop the current task"},{command:"help",description:"Show available commands"}],t=(this.config.commands?.custom??[]).map(r=>({command:Qa(r.command),description:r.description})),n=[...e,...t].slice(0,100);try{let r=await fetch(this.api("setMyCommands"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commands:n})});if(!r.ok){let s=await r.json().catch(()=>({}));console.warn(`[telegram] setMyCommands failed: ${s?.description??r.status}`)}}catch{console.warn("[telegram] setMyCommands request failed")}}async handleBotCommand(e,t){let n=String(t.chat.id);if(e==="chatid"){let r=t.chat.type??"private",s=r==="private"?t.from?.first_name??t.from?.username??"Private":t.chat.title??"Unknown";await this.sendChunk(n,`Chat ID: \`telegram:${n}\`
277
277
  Name: ${s}
278
- Type: ${r}`,{message_id:t.message_id,thread_id:t.message_thread_id})}else if(e==="ping"){let r=Math.floor((Date.now()-this.startTime)/1e3);await this.sendChunk(n,`Pong! Uptime: ${r}s`,{message_id:t.message_id,thread_id:t.message_thread_id})}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;if(e.metadata?._progress){await this.sendTyping(e.chatId);return}let t=Ka(e.content||"");for(let n of t)await this.sendChunk(e.chatId,n,e.metadata)}async sendTyping(e){let t=Date.now(),n=this.lastTypingAt.get(e)??0;t-n<Ha||(this.lastTypingAt.set(e,t),await fetch(this.api("sendChatAction"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:e,action:"typing"})}).catch(()=>{}))}async sendChunk(e,t,n){let r={chat_id:e,text:t,parse_mode:"Markdown"},s=n?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s});let i=n?.thread_id;i&&(r.message_thread_id=i);let a=await this.fetchWithRetry(this.api("sendMessage"),r);if(a&&!a.ok&&a.status===400)try{if((await a.json()).description?.toLowerCase().includes("parse")){let c={...r};delete c.parse_mode,await this.fetchWithRetry(this.api("sendMessage"),c)}}catch{}}async fetchWithRetry(e,t,n=1){for(let r=0;r<=n;r++)try{return await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(s){r<n?await new Promise(i=>setTimeout(i,1e3)):console.error(`[telegram] send failed after ${n+1} attempts:`,s instanceof Error?s.message:String(s))}}};import us from"ws";var hr=class extends jt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new Ft(e.debounce,n=>this.handleMessage(n))}async start(){if(!this.config.token){console.error("Discord token not configured");return}for(this.running=!0;this.running;){try{await this.connectOnce()}catch{}this.running&&await new Promise(e=>setTimeout(e,2e3))}}async stop(){if(this.running=!1,this.hb&&(clearInterval(this.hb),this.hb=null),this.ws){try{this.ws.close()}catch{}this.ws=null}}async send(e){this.config.token&&await fetch(`https://discord.com/api/v10/channels/${e.chatId}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify({content:e.content||""})}).catch(()=>{})}async connectOnce(){await new Promise(e=>{let t=new us(this.config.gatewayUrl);this.ws=t,t.on("message",async n=>{let r;try{r=JSON.parse(n.toString())}catch{return}if(r.s!=null&&(this.seq=r.s),r.op===10){let s=Number(r.d?.heartbeat_interval??3e4);this.startHeartbeat(s),this.sendPayload({op:2,d:{token:this.config.token,intents:this.config.intents,properties:{os:process.platform,browser:"everclaw",device:"everclaw"}}});return}if(r.op===7){t.close();return}if(r.op!==11&&r.t==="MESSAGE_CREATE"){let s=r.d;if(!s||s.author?.bot)return;let i=String(s.content??"").trim();if(!i)return;let a=`${s.author?.id}${s.author?.username?`|${s.author.username}`:""}`;this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.channel_id),content:i,...s.attachments?.length?{media:s.attachments.map(l=>l.url)}:{},metadata:{message_id:s.id,guild_id:s.guild_id??null}})}}),t.on("close",()=>{this.hb&&(clearInterval(this.hb),this.hb=null),e()}),t.on("error",()=>{this.hb&&(clearInterval(this.hb),this.hb=null),e()})})}startHeartbeat(e){this.hb&&clearInterval(this.hb),this.hb=setInterval(()=>{this.sendPayload({op:1,d:this.seq})},e)}sendPayload(e){!this.ws||this.ws.readyState!==us.OPEN||this.ws.send(JSON.stringify(e))}};var gs="_shutdown",yr=class{constructor(e,t,n){this.config=e;this.bus=t;this.lifecycle=n??Ye(),this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new fr(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new hr(this.config.channels.discord,this.bus))}async startAll(){this.channels.size&&(this.stopping=!1,this.dispatchLoop=this.dispatchOutbound(),await Promise.all([...this.channels.values()].map(e=>e.start().catch(()=>{}))))}async stopAll(){this.stopping=!0,await Promise.all([...this.channels.values()].map(e=>e.stop().catch(()=>{}))),this.dispatchLoop&&(await this.bus.publishOutbound({channel:"system",chatId:"gateway:shutdown",content:"",metadata:{[gs]:!0}}),await this.dispatchLoop.catch(()=>{}),this.dispatchLoop=null)}getSkipReason(e){if(this.stopping)return"stopping";if(e.metadata?._progress){let t=!!e.metadata._tool_hint;if(t&&!this.config.channels.sendToolHints||!t&&!this.config.channels.sendProgress)return"progress_disabled"}return this.channels.has(e.channel)?null:"channel_unavailable"}async dispatchOutbound(){for(;;){let e=await this.bus.consumeOutbound();if(e.metadata?.[gs])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await We(this.lifecycle.beforeOutbound,"beforeOutbound",{message:e,hasChannel:t,skippedReason:n})}catch(i){s=i,console.warn(String(i))}if(!s&&!n){let i=this.channels.get(e.channel);if(i)try{await i.send(e),r=!0}catch(a){s=a}}try{await We(this.lifecycle.afterOutbound,"afterOutbound",{message:e,hasChannel:t,skippedReason:n,dispatched:r,error:s})}catch(i){console.warn(String(i))}}}get enabledChannels(){return[...this.channels.keys()]}getStatus(){return Object.fromEntries([...this.channels].map(([e,t])=>[e,{enabled:!0,running:t.isRunning}]))}};Ne();import{randomUUID as za}from"node:crypto";import Va from"node:path";function Xa(o,e=160){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:"No delivery content available."}function Ya(o){return Va.resolve(o)}function ms(o){if(!o)return null;let e=String(o.content??"");return{id:String(o.delivery_id??""),jobId:String(o.job_id??""),jobName:String(o.job_name??"Delivery"),sessionKey:String(o.session_key??""),channel:String(o.channel??"cli"),recipient:String(o.recipient??"direct"),content:e,contentPreview:Xa(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Bt=class{storage;workspace;constructor(e,t,n){this.workspace=Ya(e),this.storage=n??Le({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
278
+ Type: ${r}`,{message_id:t.message_id,thread_id:t.message_thread_id})}else if(e==="ping"){let r=Math.floor((Date.now()-this.startTime)/1e3);await this.sendChunk(n,`Pong! Uptime: ${r}s`,{message_id:t.message_id,thread_id:t.message_thread_id})}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;if(e.metadata?._progress){await this.sendTyping(e.chatId);return}let t=Xa(e.content||"");for(let n of t)await this.sendChunk(e.chatId,n,e.metadata)}async sendTyping(e){let t=Date.now(),n=this.lastTypingAt.get(e)??0;t-n<el||(this.lastTypingAt.set(e,t),await fetch(this.api("sendChatAction"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:e,action:"typing"})}).catch(()=>{}))}async sendChunk(e,t,n){let r={chat_id:e,text:t,parse_mode:"Markdown"},s=n?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s});let i=n?.thread_id;i&&(r.message_thread_id=i);let a=await this.fetchWithRetry(this.api("sendMessage"),r);if(a&&!a.ok&&a.status===400)try{if((await a.json()).description?.toLowerCase().includes("parse")){let c={...r};delete c.parse_mode,await this.fetchWithRetry(this.api("sendMessage"),c)}}catch{}}async fetchWithRetry(e,t,n=1){for(let r=0;r<=n;r++)try{return await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(s){r<n?await new Promise(i=>setTimeout(i,1e3)):console.error(`[telegram] send failed after ${n+1} attempts:`,s instanceof Error?s.message:String(s))}}};import ps from"ws";var yr=class extends jt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new Ft(e.debounce,n=>this.handleMessage(n))}async start(){if(!this.config.token){console.error("Discord token not configured");return}for(this.running=!0;this.running;){try{await this.connectOnce()}catch{}this.running&&await new Promise(e=>setTimeout(e,2e3))}}async stop(){if(this.running=!1,this.hb&&(clearInterval(this.hb),this.hb=null),this.ws){try{this.ws.close()}catch{}this.ws=null}}async send(e){this.config.token&&await fetch(`https://discord.com/api/v10/channels/${e.chatId}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify({content:e.content||""})}).catch(()=>{})}async connectOnce(){await new Promise(e=>{let t=new ps(this.config.gatewayUrl);this.ws=t,t.on("message",async n=>{let r;try{r=JSON.parse(n.toString())}catch{return}if(r.s!=null&&(this.seq=r.s),r.op===10){let s=Number(r.d?.heartbeat_interval??3e4);this.startHeartbeat(s),this.sendPayload({op:2,d:{token:this.config.token,intents:this.config.intents,properties:{os:process.platform,browser:"everclaw",device:"everclaw"}}});return}if(r.op===7){t.close();return}if(r.op!==11&&r.t==="MESSAGE_CREATE"){let s=r.d;if(!s||s.author?.bot)return;let i=String(s.content??"").trim();if(!i)return;let a=`${s.author?.id}${s.author?.username?`|${s.author.username}`:""}`;this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.channel_id),content:i,...s.attachments?.length?{media:s.attachments.map(l=>l.url)}:{},metadata:{message_id:s.id,guild_id:s.guild_id??null}})}}),t.on("close",()=>{this.hb&&(clearInterval(this.hb),this.hb=null),e()}),t.on("error",()=>{this.hb&&(clearInterval(this.hb),this.hb=null),e()})})}startHeartbeat(e){this.hb&&clearInterval(this.hb),this.hb=setInterval(()=>{this.sendPayload({op:1,d:this.seq})},e)}sendPayload(e){!this.ws||this.ws.readyState!==ps.OPEN||this.ws.send(JSON.stringify(e))}};var fs="_shutdown",br=class{constructor(e,t,n){this.config=e;this.bus=t;this.lifecycle=n??Ye(),this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new hr(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new yr(this.config.channels.discord,this.bus))}async startAll(){this.channels.size&&(this.stopping=!1,this.dispatchLoop=this.dispatchOutbound(),await Promise.all([...this.channels.values()].map(e=>e.start().catch(()=>{}))))}async stopAll(){this.stopping=!0,await Promise.all([...this.channels.values()].map(e=>e.stop().catch(()=>{}))),this.dispatchLoop&&(await this.bus.publishOutbound({channel:"system",chatId:"gateway:shutdown",content:"",metadata:{[fs]:!0}}),await this.dispatchLoop.catch(()=>{}),this.dispatchLoop=null)}getSkipReason(e){if(this.stopping)return"stopping";if(e.metadata?._progress){let t=!!e.metadata._tool_hint;if(t&&!this.config.channels.sendToolHints||!t&&!this.config.channels.sendProgress)return"progress_disabled"}return this.channels.has(e.channel)?null:"channel_unavailable"}async dispatchOutbound(){for(;;){let e=await this.bus.consumeOutbound();if(e.metadata?.[fs])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await We(this.lifecycle.beforeOutbound,"beforeOutbound",{message:e,hasChannel:t,skippedReason:n})}catch(i){s=i,console.warn(String(i))}if(!s&&!n){let i=this.channels.get(e.channel);if(i)try{await i.send(e),r=!0}catch(a){s=a}}try{await We(this.lifecycle.afterOutbound,"afterOutbound",{message:e,hasChannel:t,skippedReason:n,dispatched:r,error:s})}catch(i){console.warn(String(i))}}}get enabledChannels(){return[...this.channels.keys()]}getStatus(){return Object.fromEntries([...this.channels].map(([e,t])=>[e,{enabled:!0,running:t.isRunning}]))}};je();import{randomUUID as tl}from"node:crypto";import nl from"node:path";function rl(o,e=160){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:"No delivery content available."}function ol(o){return nl.resolve(o)}function hs(o){if(!o)return null;let e=String(o.content??"");return{id:String(o.delivery_id??""),jobId:String(o.job_id??""),jobName:String(o.job_name??"Delivery"),sessionKey:String(o.session_key??""),channel:String(o.channel??"cli"),recipient:String(o.recipient??"direct"),content:e,contentPreview:rl(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Bt=class{storage;workspace;constructor(e,t,n){this.workspace=ol(e),this.storage=n??De({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
279
279
  FROM inbox_deliveries
280
280
  WHERE workspace = ?
281
281
  AND (? = 1 OR cleared_at IS NULL)
282
- ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>ms(n)).filter(n=>n!==null)}get(e){let t=this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
282
+ ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>hs(n)).filter(n=>n!==null)}get(e){let t=this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
283
283
  FROM inbox_deliveries
284
- WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return ms(t)}record(e){let t=String(e.deliveredAt??ie()),n=za();return this.storage.prepare(`INSERT INTO inbox_deliveries (
284
+ WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return hs(t)}record(e){let t=String(e.deliveredAt??ie()),n=tl();return this.storage.prepare(`INSERT INTO inbox_deliveries (
285
285
  workspace, delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
286
286
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(this.workspace,n,String(e.jobId??""),String(e.jobName??"Delivery"),String(e.sessionKey??""),String(e.channel??"cli"),String(e.recipient??"direct"),String(e.content??""),t),this.get(n)}markCleared(e,t=ie()){return this.storage.prepare(`UPDATE inbox_deliveries
287
287
  SET cleared_at = COALESCE(cleared_at, ?)
288
- WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};Oe();Ne();import de,{existsSync as bt,unlinkSync as bl}from"node:fs";import ke,{join as vl}from"node:path";import{createServer as wl}from"node:http";import{spawn as As}from"node:child_process";function br(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function yt(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function ps(o){let e="local_process",t=yt(o.runtime.overload?.rateLimited)+yt(o.runtime.overload?.backpressured),n=yt(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,yt(o.config.tools.exec.timeout)),runningSubagents:yt(o.runtime.subagents),queuedMessages:yt(o.runtime.queuedMessages),queuedSessions:yt(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:br("mixed_same_host"),summary:r.shellWorkspaceRestrictionEnabled?"Everclaw currently uses a mixed same-host isolation boundary: shell exec runs in a local child process with workspace-aware guardrails, and spawned subagents now run in their own same-host child processes with cleanup guardrails.":"Everclaw currently uses a mixed same-host isolation boundary: shell exec runs in a local child process, and spawned subagents now run in their own same-host child processes with cleanup guardrails. No container or separate host sandbox is assumed today.",surfaces:[{key:"shell",label:"Shell exec",mode:e,modeLabel:br(e),boundary:r.shellWorkspaceRestrictionEnabled?"Commands run in a same-host child process with stdio capture, timeout cleanup, a dangerous-command denylist, and workspace path restriction.":"Commands run in a same-host child process with stdio capture, timeout cleanup, and a dangerous-command denylist, but without workspace path restriction.",evidence:["Isolation runner: local child process",`Workspace restriction: ${r.shellWorkspaceRestrictionEnabled?"enabled":"disabled"}`,`Exec timeout: ${r.execTimeoutSeconds}s`,"Dangerous command denylist is active"]},{key:"subagents",label:"Spawned subagents",mode:"local_process",modeLabel:br("local_process"),boundary:"Subagents run in a same-host child process with structured result capture and stop-triggered termination before reporting outcomes back into the main runtime.",evidence:[`Running now: ${r.runningSubagents}`,`Queued sessions now: ${r.queuedSessions}`,"Session stop terminates in-flight subagent processes"]},{key:"scheduled_jobs",label:"Cron + heartbeat jobs",mode:"mixed_same_host",modeLabel:br("mixed_same_host"),boundary:"Scheduling state remains durable in the main runtime. This subagent-focused view keeps job-isolation reporting conservative rather than asserting a separate operator-facing boundary here.",evidence:[`Configured jobs: ${r.scheduledJobs}`,`Heartbeat: ${r.heartbeatEnabled?"enabled":"disabled"}`,`Queued messages now: ${r.queuedMessages}`]}],decisionEvidence:{recommendation:"Keep first-wave isolation lightweight until interference, cleanup failures, or sustained shared-process pressure show that heavier isolation is worth the added complexity.",signals:r,observedSignals:[`${r.runningSubagents} subagent(s) running right now`,`${r.queuedMessages} queued message(s) across ${r.queuedSessions} session(s)`,`${r.deniedTurns} denied turn(s) since process start`,`${r.scheduledJobs} scheduled job(s) configured`],justifyHeavierIsolationWhen:["subagents interfere with unrelated turns or cannot be cleaned up reliably","shell guardrails prove insufficient for required operator workflows","shared-process queueing/backpressure becomes a recurring containment problem"]}}}import $e from"node:fs";import Ze from"node:path";import{randomUUID as Qa}from"node:crypto";function Za(o){return o.split(Ze.sep).join("/")}function el(o,e=120){let t=o.trim().replace(/\s+/g," ");return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var tl=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),nl={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function rl(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":tl.has(e)?"image":"binary"}function ln(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return nl[e]||"image"}function ol(o,e=!1,t=128*1024){if(!$e.existsSync(o)||!$e.statSync(o).isFile())return{exists:!1,sizeBytes:null,modifiedAt:null,kind:"missing",preview:"File no longer exists in the workspace.",content:null,truncated:!1};let n=$e.statSync(o),r=rl(o);if(r==="image"){let T=Math.min(n.size,5242881),v=Buffer.alloc(T),d=$e.openSync(o,"r");try{T>0&&$e.readSync(d,v,0,T,0)}finally{$e.closeSync(d)}let b=ln(o)==="image-jpeg"?"image/jpeg":ln(o)==="image-png"?"image/png":ln(o)==="image-gif"?"image/gif":ln(o)==="image-webp"?"image/webp":ln(o)==="image-svg"?"image/svg+xml":"image/png",O=v.toString("base64"),k=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:k?"Image preview truncated.":"Image preview available.",content:null,truncated:k,imageDataUrl:`data:${b};base64,${O}`}}if(r==="pdf")return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"pdf",preview:"PDF document. Use the preview to view.",content:null,truncated:!1};let s=Math.min(n.size,t+1),i=Buffer.alloc(s),a=$e.openSync(o,"r");try{s>0&&$e.readSync(a,i,0,s,0)}finally{$e.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let u=c.toString("utf8");if(u.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let g=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:g,preview:el(u),content:e?u:null,truncated:l}}var vr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=Ze.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Le({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return Ze.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=Ze.isAbsolute(t)?Ze.resolve(t):Ze.resolve(this.workspacePath,t);try{je(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!$e.existsSync(n))throw new Error(`File not found: ${t}`);if(!$e.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=Za(Ze.relative(this.workspacePath,n));return{relativePath:r,displayName:Ze.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
288
+ WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};Le();je();import ge,{existsSync as vt,unlinkSync as Tl}from"node:fs";import Ce,{join as Rl}from"node:path";import{createServer as Al}from"node:http";import{spawn as Is}from"node:child_process";function vr(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function bt(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function ys(o){let e="local_process",t=bt(o.runtime.overload?.rateLimited)+bt(o.runtime.overload?.backpressured),n=bt(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,bt(o.config.tools.exec.timeout)),runningSubagents:bt(o.runtime.subagents),queuedMessages:bt(o.runtime.queuedMessages),queuedSessions:bt(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:vr("mixed_same_host"),summary:r.shellWorkspaceRestrictionEnabled?"Everclaw currently uses a mixed same-host isolation boundary: shell exec runs in a local child process with workspace-aware guardrails, and spawned subagents now run in their own same-host child processes with cleanup guardrails.":"Everclaw currently uses a mixed same-host isolation boundary: shell exec runs in a local child process, and spawned subagents now run in their own same-host child processes with cleanup guardrails. No container or separate host sandbox is assumed today.",surfaces:[{key:"shell",label:"Shell exec",mode:e,modeLabel:vr(e),boundary:r.shellWorkspaceRestrictionEnabled?"Commands run in a same-host child process with stdio capture, timeout cleanup, a dangerous-command denylist, and workspace path restriction.":"Commands run in a same-host child process with stdio capture, timeout cleanup, and a dangerous-command denylist, but without workspace path restriction.",evidence:["Isolation runner: local child process",`Workspace restriction: ${r.shellWorkspaceRestrictionEnabled?"enabled":"disabled"}`,`Exec timeout: ${r.execTimeoutSeconds}s`,"Dangerous command denylist is active"]},{key:"subagents",label:"Spawned subagents",mode:"local_process",modeLabel:vr("local_process"),boundary:"Subagents run in a same-host child process with structured result capture and stop-triggered termination before reporting outcomes back into the main runtime.",evidence:[`Running now: ${r.runningSubagents}`,`Queued sessions now: ${r.queuedSessions}`,"Session stop terminates in-flight subagent processes"]},{key:"scheduled_jobs",label:"Cron + heartbeat jobs",mode:"mixed_same_host",modeLabel:vr("mixed_same_host"),boundary:"Scheduling state remains durable in the main runtime. This subagent-focused view keeps job-isolation reporting conservative rather than asserting a separate operator-facing boundary here.",evidence:[`Configured jobs: ${r.scheduledJobs}`,`Heartbeat: ${r.heartbeatEnabled?"enabled":"disabled"}`,`Queued messages now: ${r.queuedMessages}`]}],decisionEvidence:{recommendation:"Keep first-wave isolation lightweight until interference, cleanup failures, or sustained shared-process pressure show that heavier isolation is worth the added complexity.",signals:r,observedSignals:[`${r.runningSubagents} subagent(s) running right now`,`${r.queuedMessages} queued message(s) across ${r.queuedSessions} session(s)`,`${r.deniedTurns} denied turn(s) since process start`,`${r.scheduledJobs} scheduled job(s) configured`],justifyHeavierIsolationWhen:["subagents interfere with unrelated turns or cannot be cleaned up reliably","shell guardrails prove insufficient for required operator workflows","shared-process queueing/backpressure becomes a recurring containment problem"]}}}import Oe from"node:fs";import Ze from"node:path";import{randomUUID as sl}from"node:crypto";function il(o){return o.split(Ze.sep).join("/")}function al(o,e=120){let t=o.trim().replace(/\s+/g," ");return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var ll=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),cl={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function dl(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":ll.has(e)?"image":"binary"}function ln(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return cl[e]||"image"}function ul(o,e=!1,t=128*1024){if(!Oe.existsSync(o)||!Oe.statSync(o).isFile())return{exists:!1,sizeBytes:null,modifiedAt:null,kind:"missing",preview:"File no longer exists in the workspace.",content:null,truncated:!1};let n=Oe.statSync(o),r=dl(o);if(r==="image"){let w=Math.min(n.size,5242881),v=Buffer.alloc(w),u=Oe.openSync(o,"r");try{w>0&&Oe.readSync(u,v,0,w,0)}finally{Oe.closeSync(u)}let b=ln(o)==="image-jpeg"?"image/jpeg":ln(o)==="image-png"?"image/png":ln(o)==="image-gif"?"image/gif":ln(o)==="image-webp"?"image/webp":ln(o)==="image-svg"?"image/svg+xml":"image/png",P=v.toString("base64"),C=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:C?"Image preview truncated.":"Image preview available.",content:null,truncated:C,imageDataUrl:`data:${b};base64,${P}`}}if(r==="pdf")return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"pdf",preview:"PDF document. Use the preview to view.",content:null,truncated:!1};let s=Math.min(n.size,t+1),i=Buffer.alloc(s),a=Oe.openSync(o,"r");try{s>0&&Oe.readSync(a,i,0,s,0)}finally{Oe.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let d=c.toString("utf8");if(d.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let p=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:p,preview:al(d),content:e?d:null,truncated:l}}var wr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=Ze.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=De({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return Ze.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=Ze.isAbsolute(t)?Ze.resolve(t):Ze.resolve(this.workspacePath,t);try{Fe(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!Oe.existsSync(n))throw new Error(`File not found: ${t}`);if(!Oe.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=il(Ze.relative(this.workspacePath,n));return{relativePath:r,displayName:Ze.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
289
289
  FROM session_files
290
- WHERE workspace = ? AND session_key = ? AND file_id = ?`).get(this.workspaceKey,e,t)??null}summarizeRow(e,t=!1){let n=this.resolveAbsolutePath(e.relative_path),r=ol(n,t);return{id:e.file_id,sessionKey:e.session_key,name:e.display_name,relativePath:e.relative_path,absolutePath:n,createdAt:e.created_at,updatedAt:e.updated_at,exists:r.exists,sizeBytes:r.sizeBytes,modifiedAt:r.modifiedAt,kind:r.kind,preview:r.preview,content:r.content,truncated:r.truncated,imageDataUrl:r.imageDataUrl||null}}list(e){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
290
+ WHERE workspace = ? AND session_key = ? AND file_id = ?`).get(this.workspaceKey,e,t)??null}summarizeRow(e,t=!1){let n=this.resolveAbsolutePath(e.relative_path),r=ul(n,t);return{id:e.file_id,sessionKey:e.session_key,name:e.display_name,relativePath:e.relative_path,absolutePath:n,createdAt:e.created_at,updatedAt:e.updated_at,exists:r.exists,sizeBytes:r.sizeBytes,modifiedAt:r.modifiedAt,kind:r.kind,preview:r.preview,content:r.content,truncated:r.truncated,imageDataUrl:r.imageDataUrl||null}}list(e){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
291
291
  FROM session_files
292
292
  WHERE workspace = ? AND session_key = ?
293
293
  ORDER BY updated_at DESC, display_name COLLATE NOCASE ASC`).all(this.workspaceKey,e).map(n=>{let{content:r,truncated:s,...i}=this.summarizeRow(n,!1);return i})}associate(e,t){let n=this.resolveAssociationPath(t),r=this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
294
294
  FROM session_files
295
- WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:u,...g}=this.summarizeRow(r,!1);return{created:!1,file:g}}let s={session_key:e,file_id:Qa(),relative_path:n.relativePath,display_name:n.displayName,created_at:ie(),updated_at:ie()};this.getStorage().prepare(`INSERT INTO session_files (
295
+ WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:d,...p}=this.summarizeRow(r,!1);return{created:!1,file:p}}let s={session_key:e,file_id:sl(),relative_path:n.relativePath,display_name:n.displayName,created_at:ie(),updated_at:ie()};this.getStorage().prepare(`INSERT INTO session_files (
296
296
  workspace, session_key, file_id, relative_path, display_name, created_at, updated_at
297
297
  ) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(this.workspaceKey,s.session_key,s.file_id,s.relative_path,s.display_name,s.created_at,s.updated_at);let{content:i,truncated:a,...l}=this.summarizeRow(s,!1);return{created:!0,file:l}}get(e,t){let n=this.getRowById(e,t);return n?this.summarizeRow(n,!0):null}remove(e,t){let n=this.getStorage().prepare(`DELETE FROM session_files
298
- WHERE workspace = ? AND session_key = ? AND file_id = ?`).run(this.workspaceKey,e,t);return Number(n?.changes??0)>0}close(){this.storage?.close(),this.storage=null}};import sl from"node:os";import fs from"node:path";Ne();pt();Oe();var no="clawhub@latest",hs=12e4;function ys(o){let e=o?.runner??new ye,t=()=>{let n=_(),r=X(n.agents.defaults.workspace);return lt(r,!0),r};return{getSnapshot(){let n=t(),r=fs.join(n,"skills"),s=fs.join(sl.homedir(),".agents","skills"),i=new Ge(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${no} search <query> --limit 5`,installTemplate:wr(["install","<slug>"],n),list:wr(["list"],n),update:wr(["update","--all"],n)},restartHint:"Start a new session after installing a skill so the agent can load it.",skills:i.listResolvedSkills()}},async install(n){let r=String(n??"").trim();if(!Rn(r))throw new Error("Skill names must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.");let s=t(),i=await e.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",no,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:hs,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(al(i));return{slug:r,workspacePath:s,command:wr(["install",r],s),output:bs(i),restartRequired:!0}}}}function wr(o,e){return["npx","--yes",no,...o,"--workdir",e].map(il).join(" ")}function il(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function bs(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
298
+ WHERE workspace = ? AND session_key = ? AND file_id = ?`).run(this.workspaceKey,e,t);return Number(n?.changes??0)>0}close(){this.storage?.close(),this.storage=null}};import gl from"node:os";import bs from"node:path";je();ft();Le();var ro="clawhub@latest",vs=12e4;function ws(o){let e=o?.runner??new be,t=()=>{let n=M(),r=V(n.agents.defaults.workspace);return lt(r,!0),r};return{getSnapshot(){let n=t(),r=bs.join(n,"skills"),s=bs.join(gl.homedir(),".agents","skills"),i=new Ue(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${ro} search <query> --limit 5`,installTemplate:Sr(["install","<slug>"],n),list:Sr(["list"],n),update:Sr(["update","--all"],n)},restartHint:"Start a new session after installing a skill so the agent can load it.",skills:i.listResolvedSkills()}},async install(n){let r=String(n??"").trim();if(!An(r))throw new Error("Skill names must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.");let s=t(),i=await e.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",ro,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:vs,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(pl(i));return{slug:r,workspacePath:s,command:Sr(["install",r],s),output:Ss(i),restartRequired:!0}}}}function Sr(o,e){return["npx","--yes",ro,...o,"--workdir",e].map(ml).join(" ")}function ml(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function Ss(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
299
299
 
300
- `).trim()||"Skill installed."}function al(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(hs/1e3)} seconds.`;let e=bs(o),t=typeof o.exitCode=="number"?`
300
+ `).trim()||"Skill installed."}function pl(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(vs/1e3)} seconds.`;let e=Ss(o),t=typeof o.exitCode=="number"?`
301
301
  Exit code: ${o.exitCode}`:"",n=o.signal?`
302
- Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}Oe();le();import{scrypt as ll,randomBytes as ws,timingSafeEqual as cl}from"node:crypto";var Ss=64,ks=16384,xs=8,Cs=1,dl=5,vs=300*1e3;function ul(){let o=ws(16);o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=o.toString("hex");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}function Ts(o,e,t,n){let r=n??{};return new Promise((s,i)=>{ll(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function gl(o,e){let t=e??ws(16),n=await Ts(o,t,Ss,{N:ks,r:xs,p:Cs});return`${t.toString("hex")}:${n.toString("hex")}`}async function ml(o,e){let t=e.split(":");if(t.length!==2)return!1;let n=Buffer.from(t[0],"hex"),r=Buffer.from(t[1],"hex"),s=await Ts(o,n,Ss,{N:ks,r:xs,p:Cs});return s.length!==r.length?!1:cl(s,r)}var Sr=class{config;sessions=new Map;failedAttempts=new Map;constructor(e){this.config=e}updateConfig(e){this.config=e}get isEnabled(){return this.config.enabled}get hasPin(){return this.config.pinHash.length>0}async setPin(e){let t=await gl(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?ml(e,this.config.pinHash):!1}createSession(){let e=ul(),t=this.config.sessionTtlS*1e3,n=Date.now();return this.sessions.set(e,{expiresAt:n+t,lastActivity:n}),e}validateSession(e){let t=this.sessions.get(e);if(!t)return!1;let n=Date.now();if(n>t.expiresAt)return this.sessions.delete(e),!1;if(this.config.lockOnIdle&&this.config.idleTimeoutS>0){let r=this.config.idleTimeoutS*1e3;if(n-t.lastActivity>r)return this.sessions.delete(e),!1}return!0}invalidateSession(e){return this.sessions.delete(e)}touchSession(e){let t=this.sessions.get(e);return t?(t.lastActivity=Date.now(),!0):!1}get activeSessionCount(){return this.sessions.size}getFailedAttempts(e){return this.pruneExpiredAttempts(e),this.failedAttempts.get(e)?.timestamps.length??0}recordFailedAttempt(e){let t=this.failedAttempts.get(e)??{timestamps:[]};t.timestamps.push(Date.now()),this.failedAttempts.set(e,t)}isRateLimited(e){return this.getFailedAttempts(e)>=dl}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+vs-Date.now();return s>0?s:0}clearFailedAttempts(e){this.failedAttempts.delete(e)}pruneExpiredSessions(){let e=Date.now(),t=0;for(let[n,r]of this.sessions)e>r.expiresAt&&(this.sessions.delete(n),t++);return t}reset(){this.sessions.clear(),this.failedAttempts.clear()}pruneExpiredAttempts(e){let t=this.failedAttempts.get(e);if(!t)return;let n=Date.now()-vs;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function Es(o){let e=ke.extname(o).toLowerCase();return[".png",".jpg",".jpeg",".gif",".webp",".svg"].includes(e)?`image/${e===".svg"?"svg+xml":e.slice(1)}`:e===".pdf"?"application/pdf":e===".json"?"application/json":e===".md"?"text/markdown":e===".js"||e===".mjs"||e===".cjs"?"text/javascript":e===".ts"||e===".tsx"?"text/typescript":e===".jsx"?"text/jsx":e===".html"?"text/html":e===".css"?"text/css":e===".csv"?"text/csv":e===".tsv"?"text/tab-separated-values":[".txt",".log",".yml",".yaml",".xml",".sh",".py",".rb",".java",".go",".rs"].includes(e)?"text/plain":"application/octet-stream"}function Ps(o){return o.startsWith("text/")||o==="application/json"}function Sl(){let o=ze("dashboard");if(!o)return null;let e=ke.join(o,"index.html");return de.existsSync(e)?o:null}function ne(o){return new Promise(e=>{let t="";o.on("data",n=>{t+=n.toString(),t.length>2e6&&o.destroy()}),o.on("end",()=>{try{e(t?JSON.parse(t):{})}catch{e({})}}),o.on("error",()=>e({}))})}function y(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function kl(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Cr(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function Tr(o,e=96){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}function xl(o){let e=Cr(o),t=[...e].reverse().find(n=>Tr(n.content));return{messageCount:e.length,lastMessagePreview:t?Tr(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function Cl(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function io(o){return typeof o=="string"?o.trim():""}function Ds(o){return io(o?.metadata?.displayName)||null}function Tl(o){let e=new Set;for(let n of o){let r=Ds(n)?.match(/^#space\s+(\d+)$/i);if(!r)continue;let s=Number(r[1]);Number.isInteger(s)&&s>0&&e.add(s)}let t=1;for(;e.has(t);)t+=1;return`#Space ${t}`}function Rl(o,e){let t=Cl(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function so(o){let e=new Set,t=[];for(let n of[...Cr(o)].reverse()){if(n.role!=="user"||typeof n.content!="string")continue;let r=n.content.trim().replace(/\s+/g," ");if(!(!r||r.startsWith("/")||e.has(r))&&(e.add(r),t.push({id:`suggestion-${t.length+1}`,text:r,label:Tr(r,56)??r}),t.length>=3))break}return t}function xr(o,e,t,n){let{channel:r,chatId:s}=kl(o.key),i=xl(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Ds(n),createdAt:o.created_at,updatedAt:o.updated_at,isCurrent:o.key===e,isDefault:o.key===e,isRunning:t,messageCount:i.messageCount,lastMessagePreview:i.lastMessagePreview,lastMessageRole:i.lastMessageRole,isPinned:n?.metadata?.isPinned===!0,pinnedOrder:Number.isFinite(a)?a:null,recentOrder:Number.isFinite(l)?l:null}}function Is(o,e){return o.listSessions().map(t=>o.getOrCreate(String(t.key??""))).filter(t=>t.key&&t.key!==e&&t.metadata?.isPinned===!0).sort((t,n)=>{let r=Number.isFinite(Number(t.metadata?.pinnedOrder))?Number(t.metadata?.pinnedOrder):Number.POSITIVE_INFINITY,s=Number.isFinite(Number(n.metadata?.pinnedOrder))?Number(n.metadata?.pinnedOrder):Number.POSITIVE_INFINITY;if(r!==s)return r-s;let i=Date.parse(String(t.updatedAt??"")),a=Date.parse(String(n.updatedAt??"")),l=Number.isFinite(i)?i:0,c=Number.isFinite(a)?a:0;return l!==c?c-l:t.key.localeCompare(n.key)})}function _s(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function Ms(o,e){return o.listSessions().map(t=>o.getOrCreate(String(t.key??""))).filter(t=>t.key&&t.key!==e&&t.metadata?.isPinned!==!0).sort((t,n)=>{let r=Number.isFinite(Number(t.metadata?.recentOrder))?Number(t.metadata?.recentOrder):Number.POSITIVE_INFINITY,s=Number.isFinite(Number(n.metadata?.recentOrder))?Number(n.metadata?.recentOrder):Number.POSITIVE_INFINITY;if(r!==s)return r-s;let i=Date.parse(String(t.updatedAt??"")),a=Date.parse(String(n.updatedAt??"")),l=Number.isFinite(i)?i:0,c=Number.isFinite(a)?a:0;return l!==c?c-l:t.key.localeCompare(n.key)})}function $s(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function Al(o){return o.endsWith(".html")?"text/html; charset=utf-8":o.endsWith(".js")?"text/javascript; charset=utf-8":o.endsWith(".css")?"text/css; charset=utf-8":o.endsWith(".json")?"application/json; charset=utf-8":o.endsWith(".svg")?"image/svg+xml":"application/octet-stream"}function et(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function ao(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function El(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Os(o,e,t){return El(o.socket.remoteAddress)?!0:(y(e,403,{error:t}),!1)}function mn(o){return o.map(e=>String(e)).join(".")}function lo(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!et(t))return;t=t[n]}return t}function xe(o,e,t){if(e.length===0)return;let n=o;for(let s=0;s<e.length-1;s+=1){let i=e[s];if(typeof i=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${mn(e)}`);let c=n[i],u=e[s+1];c===void 0&&(n[i]=typeof u=="number"?[]:{}),n=n[i];continue}if(!et(n))throw new Error(`Expected object while writing ${mn(e)}`);let a=n[i],l=e[s+1];a===void 0&&(n[i]=typeof l=="number"?[]:{}),n=n[i]}let r=e[e.length-1];if(typeof r=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${mn(e)}`);n[r]=t;return}if(!et(n))throw new Error(`Expected object while writing ${mn(e)}`);n[r]=t}function qe(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??ao(o):null}}function Pl(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))xe(t,["providers",n,"apiKey"],qe(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{xe(t,["customLlmProviders",r,"apiKey"],qe(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),xe(t,["channels","telegram","token"],qe(o.channels.telegram.token)),xe(t,["channels","discord","token"],qe(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",xe(t,["security","auth","pinHash"],qe(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",xe(t,["tools","browserRelay","authToken"],qe(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",xe(t,["tools","web","search","apiKey"],qe(o.tools.web.search.apiKey)),e.tools.web.search.apiKey="";for(let[n,r]of Object.entries(o.tools.mcpServers??{})){for(let[s,i]of Object.entries(r.env??{}))xe(t,["tools","mcpServers",n,"env",s],qe(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))xe(t,["tools","mcpServers",n,"headers",s],qe(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function Ns(o,e,t,n){let r=lo(o,e),s=mn(e);if(r==null){if(!t&&!n)return null;if(!t&&n)return{action:"set",value:n};throw new Error(`Missing secretChanges action for '${s}'.`)}if(!et(r))throw new Error(`Invalid secretChanges entry for '${s}'.`);let i=r.action;if(i!=="keep"&&i!=="clear"&&i!=="set")throw new Error(`Invalid secretChanges action for '${s}'.`);if(i==="set"){let a=typeof r.value=="string"?r.value:n;if(!a)throw new Error(`secretChanges '${s}' must include a non-empty value when action is 'set'.`);return{action:i,value:a}}return{action:i}}function vt(o,e,t,n){let r=String(lo(e,n)??""),s=String(lo(o,n)??""),i=Ns(t,n,r,s);if(i){if(i.action==="keep"){xe(o,n,r);return}if(i.action==="clear"){xe(o,n,"");return}xe(o,n,i.value??s)}}function Ls(o){return et(o)&&Object.values(o).every(e=>typeof e=="string")}function Il(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function _l(o){if(!et(o))return["tools.mcpServers must be an object."];let e=[],t=new Set;for(let[n,r]of Object.entries(o)){let s=n.trim(),i=s||"(unnamed server)";if(!s){e.push("MCP server names cannot be empty.");continue}let a=s.toLowerCase();if(t.has(a)){e.push(`MCP server '${s}' is duplicated.`);continue}if(t.add(a),!et(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",u=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!Il(c)&&e.push(`MCP server '${i}' must use an http(s) or ws(s) URL.`),r.args!==void 0&&(!Array.isArray(r.args)||r.args.some(g=>typeof g!="string"))&&e.push(`MCP server '${i}' args must be an array of strings.`),r.env!==void 0&&!Ls(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!Ls(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(u)||u<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function Ml(o){if(Array.isArray(o.customAcpProviders))return o;let e=_();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var $l=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),Ol={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function js(o){let e=Sl(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??ys(),r=null,s=o.inboxService??null,i=!1;o.config.gateway.dashboard?.enabled!==!1&&!e&&(console.log("[gateway] Dashboard assets not found. The gateway is running in API-only mode."),console.log("[gateway] Install the full package or run `npm run build:dashboard` to enable the web UI."));let l=new Sr(o.config.security.auth),c=()=>(r||(r=new vr(o.workspacePath??process.cwd(),o.dataDir)),r),u=()=>(s||(s=new Bt(o.workspacePath??process.cwd(),o.dataDir)),s),g=v=>typeof o.sessionManager.listSessions!="function"?v===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===v)||v===o.sessionKey,h=(v,d)=>{let b=v||o.sessionKey;return g(b)?{sessionKey:b}:{error:{error:d,session:b}}},T=wl(async(v,d)=>{let b=v.method||"GET",O=new URL(v.url||"/",`http://${v.headers.host||"localhost"}`),k=O.pathname;d.setHeader("X-Content-Type-Options","nosniff"),d.setHeader("X-Frame-Options","DENY"),d.setHeader("Referrer-Policy","no-referrer"),d.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let G=Ol[b]??"\x1B[0m";if(console.log(`[gateway] ${G}${b}\x1B[0m ${k}`),l.isEnabled&&k.startsWith("/api/")&&!$l.has(k)){let p=v.headers["x-auth-token"];if(!p||typeof p!="string"||!l.validateSession(p))return y(d,401,{error:"Authentication required"});l.touchSession(p)}if(!l.isEnabled&&k==="/api/config"&&(b==="GET"||b==="PUT")&&!Os(v,d,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&k==="/api/auth/login"){let p=await ne(v),m=String(p.pin??"");if(!m)return y(d,400,{error:"PIN is required"});let f=v.socket.remoteAddress??"unknown";if(l.isRateLimited(f)){let E=l.getRateLimitRemainingMs(f);return y(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:E})}if(!l.hasPin)return y(d,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(m))return l.recordFailedAttempt(f),y(d,401,{error:"Invalid PIN"});l.clearFailedAttempts(f);let x=l.createSession();return y(d,200,{token:x})}if(b==="GET"&&k==="/api/auth/status")return y(d,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&k==="/api/auth/logout"){let p=v.headers["x-auth-token"];return!p||typeof p!="string"?y(d,200,{ok:!0}):(l.invalidateSession(p),y(d,200,{ok:!0}))}if(b==="POST"&&k==="/api/auth/set-pin"){let p=await ne(v),m=String(p.newPin??""),f=p.currentPin!==void 0?String(p.currentPin):void 0;if(!m)return y(d,400,{error:"newPin is required"});if(m.length!==6)return y(d,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(m))return y(d,400,{error:"PIN must contain only digits"});if(l.hasPin){let C=v.headers["x-auth-token"];if(!(C&&typeof C=="string"&&l.validateSession(C))){let M=v.socket.remoteAddress??"unknown";if(l.isRateLimited(M)){let V=l.getRateLimitRemainingMs(M);return y(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:V})}if(!f)return y(d,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(f))return l.recordFailedAttempt(M),y(d,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(M)}}else{let C=process.env.EVERCLAW_BOOTSTRAP_PIN;if(C&&String(p.bootstrapSecret??"")!==C)return y(d,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let w=!l.hasPin,x=await l.setPin(m);w||l.reset();let E=_();return E.security?.auth&&(E.security.auth.pinHash=x,oe(E)),y(d,200,{ok:!0,message:w?"PIN set successfully":"PIN changed successfully"})}let L=()=>y(d,503,{error:"Gateway is shutting down. Please try again later."}),N=k.match(/^\/api\/cron\/jobs\/([^/]+)$/),z=k.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),B=k.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),ae=k.match(/^\/api\/inbox-deliveries\/([^/]+)$/),J=k.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),Z=k.match(/^\/api\/sessions\/([^/]+)$/),A=k.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&k==="/api/chat"||b==="POST"&&k==="/api/sessions"||b==="PUT"&&!!Z||b==="PUT"&&k==="/api/config"||b==="POST"&&k==="/api/skills/install"||b==="POST"&&!!J||b==="POST"&&k==="/api/session-files"||b==="POST"&&k==="/api/cron/jobs"||b==="DELETE"&&!!A||b==="DELETE"&&!!N||b==="POST"&&!!z||b==="POST"&&!!B))return L();if(b==="GET"&&k==="/api/status"){let p=_(),m=o.agent.getRuntimeState(),f=o.cron.status(),w=ps({config:p,runtime:m,cron:f}),x=structuredClone(p.channels);x.telegram?.token&&(x.telegram.token=ao(x.telegram.token)),x.discord?.token&&(x.discord.token=ao(x.discord.token));let E=o.channelManager?.getStatus()??{};return y(d,200,{provider:p.agents.defaults.provider,model:p.agents.defaults.model,cron:f,channels:x,channelStatus:E,gateway:{...p.gateway,port:t},runtime:m,isolation:w,shutdown:{active:i||!m.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&k==="/api/chrome-session/status"){let p=_(),m=O.searchParams.get("port"),f=m?parseInt(m,10):p.tools.chromeSession?.debugPort??9222,w=p.tools.chromeSession?.minChromeVersion??136,x=await It(f);if(!x)return y(d,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:f});if(x.pendingApproval)return y(d,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${x.port} --user-data-dir=/tmp/chrome-debug-profile`,port:x.port,debugPort:f});let{port:E,versionInfo:C}=x,R=C.Browser.match(/(\w+)\/(\d+)/),M=R?.[1]??"Chrome",P=R?parseInt(R[2],10):0;return P>0&&P<w?y(d,200,{available:!1,reason:`Chrome version ${P} is below minimum required version ${w}`,hint:`Update Chrome to version ${w} or higher`,version:C.Browser,port:E,browser:M,debugPort:f}):y(d,200,{available:!0,version:C.Browser,remoteDebugging:!0,port:E,browser:M,debugPort:f})}if(b==="POST"&&k==="/api/chrome-session/launch"){let p=await ne(v),m=_(),f=p.port??m.tools.chromeSession?.debugPort??9222,w=await It(f);if(w&&!w.pendingApproval){let P=w.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(d,200,{ok:!0,launched:!1,alreadyRunning:!0,port:w.port,version:w.versionInfo.Browser,browser:P?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${w.port}. No need to launch.`})}if(w?.pendingApproval)return y(d,200,{ok:!1,launched:!1,pendingApproval:!0,port:w.port,message:"Chrome is running on this port but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow'."});let x="/tmp/chrome-debug-profile",E=vl(x,"DevToolsActivePort");try{bl(E)}catch{}let C=process.platform,R,M=[`--remote-debugging-port=${f}`,`--user-data-dir=${x}`];if(C==="darwin"){let P=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",`${process.env.HOME}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,"/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"],V=P.find(D=>bt(D));if(!V)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:P,hint:"Install Google Chrome or specify the path manually."});R=V}else if(C==="win32"){R="cmd.exe";let P=process.env.ProgramFiles??"C:\\Program Files",V=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",D=[`${P}\\Google\\Chrome\\Application\\chrome.exe`,`${V}\\Google\\Chrome\\Application\\chrome.exe`,`${P}\\Microsoft\\Edge\\Application\\msedge.exe`,`${V}\\Microsoft\\Edge\\Application\\msedge.exe`],me=D.find(Re=>bt(Re));if(!me)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:D,hint:"Install Google Chrome or Microsoft Edge."});M=["/c","start","",me,`--remote-debugging-port=${f}`]}else{let P=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],V=P.find(D=>bt(D));if(!V)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:P,hint:"Install Google Chrome or Chromium."});R=V}try{let P=As(R,M,{detached:!0,stdio:"ignore"}),V=await Promise.race([new Promise(Re=>P.once("error",Re)),new Promise(Re=>setTimeout(()=>Re(null),500))]);if(V)return y(d,500,{ok:!1,error:V.message,chromePath:R,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});P.unref();let D;for(let Re=0;Re<5&&(await new Promise(st=>setTimeout(st,1e3)),D=await It(f),!D);Re++);if(!D)return y(d,200,{ok:!1,launched:!0,port:f,chromePath:R,message:"Chrome was launched but CDP is not fully active. You may need to click 'Allow' in Chrome's remote debugging prompt, or try closing all existing Chrome windows first, then retry."});if(D.pendingApproval)return y(d,200,{ok:!1,launched:!0,pendingApproval:!0,port:D.port,chromePath:R,message:"Chrome was launched but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to enable agent control."});let me=D.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(d,200,{ok:!0,launched:!0,port:D.port,chromePath:R,version:D.versionInfo.Browser,browser:me?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${D.port}`})}catch(P){return y(d,500,{ok:!1,error:P instanceof Error?P.message:String(P),chromePath:R,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&k==="/api/browser-relay/status"){let m=_().tools.browserRelay;if(!m.enabled)return y(d,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:m.extensionPath});if(o.browserRelay){let f=o.browserRelay.getStatus();return y(d,200,{enabled:!0,connected:f.connected,attachedTabs:f.attachedTabs,lastPing:f.lastPing,extensionPath:m.extensionPath})}return y(d,200,{enabled:m.enabled,connected:!1,attachedTabs:[],extensionPath:m.extensionPath})}if(b==="GET"&&k==="/api/browser-relay/config"){if(!Os(v,d,"Browser Relay bootstrap is only available from localhost."))return;let p=_(),m=p.tools.browserRelay;return y(d,200,{enabled:m.enabled,port:p.gateway.port,token:m.enabled&&m.authToken||""})}if(b==="POST"&&k==="/api/browser-relay/launch"){let p=await ne(v),m=_(),f=p.extensionPath??m.tools.browserRelay.extensionPath;if(!f)return y(d,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let w=process.platform,x,E=[`--load-extension=${f}`,"--no-first-run","--no-default-browser-check"];if(w==="darwin")x=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(bt)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(w==="win32"){let C=process.env.ProgramFiles??"C:\\Program Files",R=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";x=[`${C}\\Google\\Chrome\\Application\\chrome.exe`,`${R}\\Google\\Chrome\\Application\\chrome.exe`].find(bt)??`${C}\\Google\\Chrome\\Application\\chrome.exe`}else x="google-chrome";try{return As(x,E,{detached:!0,stdio:"ignore"}).unref(),y(d,200,{ok:!0,launched:!0,extensionPath:f,message:`Chrome launched with extension from ${f}`})}catch(C){return y(d,500,{ok:!1,error:C instanceof Error?C.message:String(C),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let I=k.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),F=X(o.config.agents.defaults.workspace);if(b==="GET"&&k==="/api/automations"){let p=$t(F);return y(d,200,p)}if(b==="GET"&&I&&I[1]&&!I[2]){let p=I[1],m=Se(F,p);return m?y(d,200,m):y(d,404,{error:"Automation not found"})}if(b==="POST"&&k==="/api/automations"){let p=await ne(v);try{let m={name:String(p.name??"Untitled"),description:String(p.description??""),steps:p.steps||[],tags:p.tags||[],source:p.source||"manual"};p.toolType!==void 0&&(m.toolType=p.toolType),p.variables!==void 0&&(m.variables=p.variables);let f=Vn(F,m);return y(d,201,f)}catch(m){return y(d,400,{error:String(m)})}}if(b==="PUT"&&I&&I[1]&&!I[2]){let p=I[1],m=await ne(v),f={};m.name!==void 0&&(f.name=String(m.name)),m.description!==void 0&&(f.description=String(m.description)),m.enabled!==void 0&&(f.enabled=!!m.enabled),m.steps!==void 0&&(f.steps=m.steps),m.tags!==void 0&&(f.tags=m.tags),m.toolType!==void 0&&(f.toolType=m.toolType),m.variables!==void 0&&(f.variables=m.variables);let w=Xn(F,p,f);return w?y(d,200,w):y(d,404,{error:"Automation not found"})}if(b==="DELETE"&&I&&I[1]){let p=I[1];return Ot(F,p)?y(d,200,{ok:!0}):y(d,404,{error:"Automation not found"})}if(b==="POST"&&I&&I[1]&&I[2]==="/run"){let p=I[1],m=Se(F,p);return m?m.enabled?(o.agent.tools.execute("automation",{command:"run",id:p}).then(f=>{console.log(`[automation] Execution of '${m.name}' finished`,{logs:f.kind==="ok"?f.content:f})}).catch(f=>{console.error(`[automation] Execution of '${m.name}' failed`,{err:f})}),y(d,200,{ok:!0,message:`Automation '${m.name}' execution started in background.`})):y(d,400,{error:"Automation is disabled"}):y(d,404,{error:"Automation not found"})}if(b==="GET"&&k==="/api/history"){let p=String(O.searchParams.get("session")??"").trim(),m=h(p,"Session history not found.");if(m.error)return y(d,404,m.error);let f=m.sessionKey,w=o.sessionManager.getOrCreate(f);return y(d,200,{session:f,messages:Cr(w.messages)})}if(b==="GET"&&k==="/api/sessions"){let p=o.agent.getRuntimeState(),m=new Set((p.sessions||[]).filter(x=>x.running||x.queued>0).map(x=>x.key)),f=o.sessionManager.getOrCreate(o.sessionKey),w=o.sessionManager.listSessions().filter(x=>String(x.key??"")!==o.sessionKey).map(x=>{let E=String(x.key??"");return xr({key:E,created_at:String(x.created_at??f.createdAt),updated_at:String(x.updated_at??f.updatedAt)},o.sessionKey,m.has(E),o.sessionManager.getOrCreate(E))});return y(d,200,{currentSession:o.sessionKey,sessions:[xr({key:f.key,created_at:f.createdAt,updated_at:f.updatedAt},o.sessionKey,m.has(f.key),f),...w]})}if(b==="GET"&&k==="/api/files/preview"){let p=String(O.searchParams.get("path")??"").trim(),m=parseInt(O.searchParams.get("maxLines")??"100",10),f=o.workspacePath??process.cwd();if(!p)return y(d,400,{error:"path required"});try{je(p,f)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!bt(p))return y(d,404,{error:"file not found"});try{let w=de.statSync(p);if(w.isDirectory())return y(d,400,{error:"path is a directory"});let x=Es(p),E=de.readFileSync(p),C=null,R=!1;if(Ps(x)){let D=E.toString("utf-8").split(`
303
- `);R=D.length>m,C=D.slice(0,m).join(`
304
- `)}let M=ke.extname(p).toLowerCase(),P=x.startsWith("image/")?"image":x==="application/pdf"?"pdf":x==="text/csv"||x==="text/tab-separated-values"?"table":Ps(x)?M===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(M)?"code":"text":"binary";return y(d,200,{name:ke.basename(p),path:p,size:w.size,content:C,truncated:R,mimeType:x,previewType:P,extension:M})}catch(w){return y(d,500,{error:String(w)})}}if(b==="GET"&&k==="/api/files/content"){let p=String(O.searchParams.get("path")??"").trim(),m=o.workspacePath??process.cwd();if(!p)return y(d,400,{error:"path required"});try{je(p,m)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!bt(p))return y(d,404,{error:"file not found"});try{let f=de.statSync(p);if(f.isDirectory())return y(d,400,{error:"path is a directory"});d.statusCode=200,d.setHeader("Content-Type",Es(p)),d.setHeader("Content-Length",String(f.size)),de.createReadStream(p).pipe(d);return}catch(f){return y(d,500,{error:String(f)})}}if(b==="POST"&&k==="/api/sessions"){let p=await ne(v),m=new Set(o.sessionManager.listSessions().map(P=>String(P.key??"")));m.add(o.sessionKey);let f=String(p.key??"").trim(),w=[...m].map(P=>o.sessionManager.getOrCreate(P)),x=io(p.label),E=x||Tl(w),C=f||Rl(m,x),R=m.has(C),M=o.sessionManager.getOrCreate(C);return R||(M.metadata={...M.metadata,displayName:E},o.sessionManager.save(M)),y(d,200,{created:!R,session:xr({key:M.key,created_at:M.createdAt,updated_at:M.updatedAt},o.sessionKey,!1,M)})}if(Z&&b==="PUT"){let p=Z[1]?decodeURIComponent(Z[1]):void 0;if(!p)return y(d,400,"Invalid session key");let m=h(p,"Session not found.");if(m.error)return y(d,404,m.error);let f=await ne(v),w=io(f.label),x=Number(f.pinnedOrder),E=Number(f.recentOrder);if(w===void 0&&f.isPinned===void 0&&f.pinnedOrder===void 0&&f.recentOrder===void 0)return y(d,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:p});let C=o.sessionManager.getOrCreate(m.sessionKey);if(C.metadata={...C.metadata},w!==void 0&&(C.metadata.displayName=w),f.isPinned!==void 0&&(C.metadata.isPinned=!!f.isPinned),C.metadata.isPinned===!0){delete C.metadata.recentOrder;let M=[...Is(o.sessionManager,C.key)],P=Number.isFinite(x)?Math.max(0,Math.min(Math.trunc(x),M.length)):M.length;M.splice(P,0,C),_s(o.sessionManager,M),$s(o.sessionManager,Ms(o.sessionManager,C.key))}else{delete C.metadata.pinnedOrder,_s(o.sessionManager,Is(o.sessionManager,C.key));let M=[...Ms(o.sessionManager,C.key)],P=Number.isFinite(E)?Math.max(0,Math.min(Math.trunc(E),M.length)):M.length;M.splice(P,0,C),$s(o.sessionManager,M)}return o.sessionManager.save(C),y(d,200,{ok:!0,session:xr({key:C.key,created_at:C.createdAt,updated_at:C.updatedAt},o.sessionKey,!1,C)})}if(Z&&b==="DELETE"){let p=Z[1]?decodeURIComponent(Z[1]):void 0;if(!p)return y(d,400,"Invalid session key");let m=h(p,"Session not found.");if(m.error)return y(d,404,m.error);if(m.sessionKey===o.sessionKey)return y(d,400,{error:"The primary session cannot be deleted."});let f=o.sessionManager.delete(m.sessionKey);return y(d,200,{ok:f,session:p})}if(b==="GET"&&k==="/api/suggestions"){let p=String(O.searchParams.get("session")??"").trim(),m=h(p,"Session suggestions not found.");if(m.error)return y(d,404,m.error);let f=m.sessionKey,w=o.sessionManager.getOrCreate(f),x=_(),E=x.subagents?.find(R=>R.id==="advisor"),C=E?E.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let R=Me(x),M=await Qr({task:C+`
305
- Return ONLY a JSON array of strings, nothing else.`,provider:R,workspace:o.workspacePath??process.cwd(),model:x.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:x.tools.exec,restrictToWorkspace:x.tools.restrictToWorkspace,existingMessages:Cr(w.messages)}),P=[];try{let D=M.replace(/```json/g,"").replace(/```/g,"").trim();P=JSON.parse(D)}catch{P=so(w.messages).map(D=>D.text)}let V=Array.isArray(P)?P.slice(0,3).map((D,me)=>({id:`suggestion-${me+1}`,text:String(D),label:Tr(String(D),56)??String(D)})):so(w.messages);return y(d,200,{session:f,suggestions:V})}catch{return y(d,200,{session:f,suggestions:so(w.messages)})}}if(b==="GET"&&k==="/api/session-files"){let p=String(O.searchParams.get("session")??"").trim(),m=h(p,"Session files not found.");return m.error?y(d,404,m.error):y(d,200,{session:m.sessionKey,files:c().list(m.sessionKey)})}if(b==="GET"&&k==="/api/inbox-deliveries"){let p=O.searchParams.get("all")==="1",m=u();if(m.list({includeCleared:!0}).filter(x=>!x.clearedAt).length===0){let x=[{jobId:"demo-cron-daily-standup",jobName:"Daily standup reminder",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:`This is a sample cron notification to demonstrate the Inbox functionality. When real cron jobs run and deliver messages, they will appear here.
302
+ Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}Le();ce();import{scrypt as fl,randomBytes as Cs,timingSafeEqual as hl}from"node:crypto";var xs=64,Ts=16384,Rs=8,As=1,yl=5,ks=300*1e3;function bl(){let o=Cs(16);o[6]=o[6]&15|64,o[8]=o[8]&63|128;let e=o.toString("hex");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}function Es(o,e,t,n){let r=n??{};return new Promise((s,i)=>{fl(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function vl(o,e){let t=e??Cs(16),n=await Es(o,t,xs,{N:Ts,r:Rs,p:As});return`${t.toString("hex")}:${n.toString("hex")}`}async function wl(o,e){let t=e.split(":");if(t.length!==2)return!1;let n=Buffer.from(t[0],"hex"),r=Buffer.from(t[1],"hex"),s=await Es(o,n,xs,{N:Ts,r:Rs,p:As});return s.length!==r.length?!1:hl(s,r)}var kr=class{config;sessions=new Map;failedAttempts=new Map;constructor(e){this.config=e}updateConfig(e){this.config=e}get isEnabled(){return this.config.enabled}get hasPin(){return this.config.pinHash.length>0}async setPin(e){let t=await vl(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?wl(e,this.config.pinHash):!1}createSession(){let e=bl(),t=this.config.sessionTtlS*1e3,n=Date.now();return this.sessions.set(e,{expiresAt:n+t,lastActivity:n}),e}validateSession(e){let t=this.sessions.get(e);if(!t)return!1;let n=Date.now();if(n>t.expiresAt)return this.sessions.delete(e),!1;if(this.config.lockOnIdle&&this.config.idleTimeoutS>0){let r=this.config.idleTimeoutS*1e3;if(n-t.lastActivity>r)return this.sessions.delete(e),!1}return!0}invalidateSession(e){return this.sessions.delete(e)}touchSession(e){let t=this.sessions.get(e);return t?(t.lastActivity=Date.now(),!0):!1}get activeSessionCount(){return this.sessions.size}getFailedAttempts(e){return this.pruneExpiredAttempts(e),this.failedAttempts.get(e)?.timestamps.length??0}recordFailedAttempt(e){let t=this.failedAttempts.get(e)??{timestamps:[]};t.timestamps.push(Date.now()),this.failedAttempts.set(e,t)}isRateLimited(e){return this.getFailedAttempts(e)>=yl}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+ks-Date.now();return s>0?s:0}clearFailedAttempts(e){this.failedAttempts.delete(e)}pruneExpiredSessions(){let e=Date.now(),t=0;for(let[n,r]of this.sessions)e>r.expiresAt&&(this.sessions.delete(n),t++);return t}reset(){this.sessions.clear(),this.failedAttempts.clear()}pruneExpiredAttempts(e){let t=this.failedAttempts.get(e);if(!t)return;let n=Date.now()-ks;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function _s(o){let e=Ce.extname(o).toLowerCase();return[".png",".jpg",".jpeg",".gif",".webp",".svg"].includes(e)?`image/${e===".svg"?"svg+xml":e.slice(1)}`:e===".pdf"?"application/pdf":e===".json"?"application/json":e===".md"?"text/markdown":e===".js"||e===".mjs"||e===".cjs"?"text/javascript":e===".ts"||e===".tsx"?"text/typescript":e===".jsx"?"text/jsx":e===".html"?"text/html":e===".css"?"text/css":e===".csv"?"text/csv":e===".tsv"?"text/tab-separated-values":[".txt",".log",".yml",".yaml",".xml",".sh",".py",".rb",".java",".go",".rs"].includes(e)?"text/plain":"application/octet-stream"}function Ms(o){return o.startsWith("text/")||o==="application/json"}function El(){let o=ze("dashboard");if(!o)return null;let e=Ce.join(o,"index.html");return ge.existsSync(e)?o:null}function re(o){return new Promise(e=>{let t="";o.on("data",n=>{t+=n.toString(),t.length>2e6&&o.destroy()}),o.on("end",()=>{try{e(t?JSON.parse(t):{})}catch{e({})}}),o.on("error",()=>e({}))})}function y(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function Pl(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Tr(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function Rr(o,e=96){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}function Il(o){let e=Tr(o),t=[...e].reverse().find(n=>Rr(n.content));return{messageCount:e.length,lastMessagePreview:t?Rr(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function _l(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function ao(o){return typeof o=="string"?o.trim():""}function Fs(o){return ao(o?.metadata?.displayName)||null}function Ml(o){let e=new Set;for(let n of o){let r=Fs(n)?.match(/^#space\s+(\d+)$/i);if(!r)continue;let s=Number(r[1]);Number.isInteger(s)&&s>0&&e.add(s)}let t=1;for(;e.has(t);)t+=1;return`#Space ${t}`}function $l(o,e){let t=_l(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function io(o){let e=new Set,t=[];for(let n of[...Tr(o)].reverse()){if(n.role!=="user"||typeof n.content!="string")continue;let r=n.content.trim().replace(/\s+/g," ");if(!(!r||r.startsWith("/")||e.has(r))&&(e.add(r),t.push({id:`suggestion-${t.length+1}`,text:r,label:Rr(r,56)??r}),t.length>=3))break}return t}function xr(o,e,t,n){let{channel:r,chatId:s}=Pl(o.key),i=Il(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Fs(n),createdAt:o.created_at,updatedAt:o.updated_at,isCurrent:o.key===e,isDefault:o.key===e,isRunning:t,messageCount:i.messageCount,lastMessagePreview:i.lastMessagePreview,lastMessageRole:i.lastMessageRole,isPinned:n?.metadata?.isPinned===!0,pinnedOrder:Number.isFinite(a)?a:null,recentOrder:Number.isFinite(l)?l:null}}function $s(o,e){return o.listSessions().map(t=>o.getOrCreate(String(t.key??""))).filter(t=>t.key&&t.key!==e&&t.metadata?.isPinned===!0).sort((t,n)=>{let r=Number.isFinite(Number(t.metadata?.pinnedOrder))?Number(t.metadata?.pinnedOrder):Number.POSITIVE_INFINITY,s=Number.isFinite(Number(n.metadata?.pinnedOrder))?Number(n.metadata?.pinnedOrder):Number.POSITIVE_INFINITY;if(r!==s)return r-s;let i=Date.parse(String(t.updatedAt??"")),a=Date.parse(String(n.updatedAt??"")),l=Number.isFinite(i)?i:0,c=Number.isFinite(a)?a:0;return l!==c?c-l:t.key.localeCompare(n.key)})}function Os(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function Ls(o,e){return o.listSessions().map(t=>o.getOrCreate(String(t.key??""))).filter(t=>t.key&&t.key!==e&&t.metadata?.isPinned!==!0).sort((t,n)=>{let r=Number.isFinite(Number(t.metadata?.recentOrder))?Number(t.metadata?.recentOrder):Number.POSITIVE_INFINITY,s=Number.isFinite(Number(n.metadata?.recentOrder))?Number(n.metadata?.recentOrder):Number.POSITIVE_INFINITY;if(r!==s)return r-s;let i=Date.parse(String(t.updatedAt??"")),a=Date.parse(String(n.updatedAt??"")),l=Number.isFinite(i)?i:0,c=Number.isFinite(a)?a:0;return l!==c?c-l:t.key.localeCompare(n.key)})}function Ds(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function Ol(o){return o.endsWith(".html")?"text/html; charset=utf-8":o.endsWith(".js")?"text/javascript; charset=utf-8":o.endsWith(".css")?"text/css; charset=utf-8":o.endsWith(".json")?"application/json; charset=utf-8":o.endsWith(".svg")?"image/svg+xml":"application/octet-stream"}function et(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function lo(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function Ll(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Ns(o,e,t){return Ll(o.socket.remoteAddress)?!0:(y(e,403,{error:t}),!1)}function mn(o){return o.map(e=>String(e)).join(".")}function co(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!et(t))return;t=t[n]}return t}function xe(o,e,t){if(e.length===0)return;let n=o;for(let s=0;s<e.length-1;s+=1){let i=e[s];if(typeof i=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${mn(e)}`);let c=n[i],d=e[s+1];c===void 0&&(n[i]=typeof d=="number"?[]:{}),n=n[i];continue}if(!et(n))throw new Error(`Expected object while writing ${mn(e)}`);let a=n[i],l=e[s+1];a===void 0&&(n[i]=typeof l=="number"?[]:{}),n=n[i]}let r=e[e.length-1];if(typeof r=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${mn(e)}`);n[r]=t;return}if(!et(n))throw new Error(`Expected object while writing ${mn(e)}`);n[r]=t}function Je(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??lo(o):null}}function Dl(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))xe(t,["providers",n,"apiKey"],Je(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{xe(t,["customLlmProviders",r,"apiKey"],Je(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),xe(t,["channels","telegram","token"],Je(o.channels.telegram.token)),xe(t,["channels","discord","token"],Je(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",xe(t,["security","auth","pinHash"],Je(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",xe(t,["tools","browserRelay","authToken"],Je(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",xe(t,["tools","web","search","apiKey"],Je(o.tools.web.search.apiKey)),e.tools.web.search.apiKey="";for(let[n,r]of Object.entries(o.tools.mcpServers??{})){for(let[s,i]of Object.entries(r.env??{}))xe(t,["tools","mcpServers",n,"env",s],Je(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))xe(t,["tools","mcpServers",n,"headers",s],Je(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function Bs(o,e,t,n){let r=co(o,e),s=mn(e);if(r==null){if(!t&&!n)return null;if(!t&&n)return{action:"set",value:n};throw new Error(`Missing secretChanges action for '${s}'.`)}if(!et(r))throw new Error(`Invalid secretChanges entry for '${s}'.`);let i=r.action;if(i!=="keep"&&i!=="clear"&&i!=="set")throw new Error(`Invalid secretChanges action for '${s}'.`);if(i==="set"){let a=typeof r.value=="string"?r.value:n;if(!a)throw new Error(`secretChanges '${s}' must include a non-empty value when action is 'set'.`);return{action:i,value:a}}return{action:i}}function wt(o,e,t,n){let r=String(co(e,n)??""),s=String(co(o,n)??""),i=Bs(t,n,r,s);if(i){if(i.action==="keep"){xe(o,n,r);return}if(i.action==="clear"){xe(o,n,"");return}xe(o,n,i.value??s)}}function js(o){return et(o)&&Object.values(o).every(e=>typeof e=="string")}function Nl(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function jl(o){if(!et(o))return["tools.mcpServers must be an object."];let e=[],t=new Set;for(let[n,r]of Object.entries(o)){let s=n.trim(),i=s||"(unnamed server)";if(!s){e.push("MCP server names cannot be empty.");continue}let a=s.toLowerCase();if(t.has(a)){e.push(`MCP server '${s}' is duplicated.`);continue}if(t.add(a),!et(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",d=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!Nl(c)&&e.push(`MCP server '${i}' must use an http(s) or ws(s) URL.`),r.args!==void 0&&(!Array.isArray(r.args)||r.args.some(p=>typeof p!="string"))&&e.push(`MCP server '${i}' args must be an array of strings.`),r.env!==void 0&&!js(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!js(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(d)||d<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function Fl(o){if(Array.isArray(o.customAcpProviders))return o;let e=M();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var Bl=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),Gl={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Gs(o){let e=El(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??ws(),r=null,s=o.inboxService??null,i=!1;o.config.gateway.dashboard?.enabled!==!1&&!e&&(console.log("[gateway] Dashboard assets not found. The gateway is running in API-only mode."),console.log("[gateway] Install the full package or run `npm run build:dashboard` to enable the web UI."));let l=new kr(o.config.security.auth),c=()=>(r||(r=new wr(o.workspacePath??process.cwd(),o.dataDir)),r),d=()=>(s||(s=new Bt(o.workspacePath??process.cwd(),o.dataDir)),s),p=v=>typeof o.sessionManager.listSessions!="function"?v===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===v)||v===o.sessionKey,h=(v,u)=>{let b=v||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:u,session:b}}},w=Al(async(v,u)=>{let b=v.method||"GET",P=new URL(v.url||"/",`http://${v.headers.host||"localhost"}`),C=P.pathname;u.setHeader("X-Content-Type-Options","nosniff"),u.setHeader("X-Frame-Options","DENY"),u.setHeader("Referrer-Policy","no-referrer"),u.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let N=Gl[b]??"\x1B[0m";if(console.log(`[gateway] ${N}${b}\x1B[0m ${C}`),l.isEnabled&&C.startsWith("/api/")&&!Bl.has(C)){let m=v.headers["x-auth-token"];if(!m||typeof m!="string"||!l.validateSession(m))return y(u,401,{error:"Authentication required"});l.touchSession(m)}if(!l.isEnabled&&C==="/api/config"&&(b==="GET"||b==="PUT")&&!Ns(v,u,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&C==="/api/auth/login"){let m=await re(v),g=String(m.pin??"");if(!g)return y(u,400,{error:"PIN is required"});let f=v.socket.remoteAddress??"unknown";if(l.isRateLimited(f)){let E=l.getRateLimitRemainingMs(f);return y(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:E})}if(!l.hasPin)return y(u,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(g))return l.recordFailedAttempt(f),y(u,401,{error:"Invalid PIN"});l.clearFailedAttempts(f);let x=l.createSession();return y(u,200,{token:x})}if(b==="GET"&&C==="/api/auth/status")return y(u,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&C==="/api/auth/logout"){let m=v.headers["x-auth-token"];return!m||typeof m!="string"?y(u,200,{ok:!0}):(l.invalidateSession(m),y(u,200,{ok:!0}))}if(b==="POST"&&C==="/api/auth/set-pin"){let m=await re(v),g=String(m.newPin??""),f=m.currentPin!==void 0?String(m.currentPin):void 0;if(!g)return y(u,400,{error:"newPin is required"});if(g.length!==6)return y(u,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(g))return y(u,400,{error:"PIN must contain only digits"});if(l.hasPin){let R=v.headers["x-auth-token"];if(!(R&&typeof R=="string"&&l.validateSession(R))){let $=v.socket.remoteAddress??"unknown";if(l.isRateLimited($)){let H=l.getRateLimitRemainingMs($);return y(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:H})}if(!f)return y(u,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(f))return l.recordFailedAttempt($),y(u,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts($)}}else{let R=process.env.EVERCLAW_BOOTSTRAP_PIN;if(R&&String(m.bootstrapSecret??"")!==R)return y(u,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let k=!l.hasPin,x=await l.setPin(g);k||l.reset();let E=M();return E.security?.auth&&(E.security.auth.pinHash=x,oe(E)),y(u,200,{ok:!0,message:k?"PIN set successfully":"PIN changed successfully"})}let q=()=>y(u,503,{error:"Gateway is shutting down. Please try again later."}),I=C.match(/^\/api\/cron\/jobs\/([^/]+)$/),J=C.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),Q=C.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),z=C.match(/^\/api\/inbox-deliveries\/([^/]+)$/),W=C.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),X=C.match(/^\/api\/sessions\/([^/]+)$/),ae=C.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&C==="/api/chat"||b==="POST"&&C==="/api/sessions"||b==="PUT"&&!!X||b==="PUT"&&C==="/api/config"||b==="POST"&&C==="/api/skills/install"||b==="POST"&&!!W||b==="POST"&&C==="/api/session-files"||b==="POST"&&C==="/api/cron/jobs"||b==="DELETE"&&!!ae||b==="DELETE"&&!!I||b==="POST"&&!!J||b==="POST"&&!!Q))return q();if(b==="GET"&&C==="/api/status"){let m=M(),g=o.agent.getRuntimeState(),f=o.cron.status(),k=ys({config:m,runtime:g,cron:f}),x=structuredClone(m.channels);x.telegram?.token&&(x.telegram.token=lo(x.telegram.token)),x.discord?.token&&(x.discord.token=lo(x.discord.token));let E=o.channelManager?.getStatus()??{};return y(u,200,{provider:m.agents.defaults.provider,model:m.agents.defaults.model,cron:f,channels:x,channelStatus:E,gateway:{...m.gateway,port:t},runtime:g,isolation:k,shutdown:{active:i||!g.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&C==="/api/chrome-session/status"){let m=M(),g=P.searchParams.get("port"),f=g?parseInt(g,10):m.tools.chromeSession?.debugPort??9222,k=m.tools.chromeSession?.minChromeVersion??136,x=await It(f);if(!x)return y(u,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:f});if(x.pendingApproval)return y(u,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${x.port} --user-data-dir=/tmp/chrome-debug-profile`,port:x.port,debugPort:f});let{port:E,versionInfo:R}=x,A=R.Browser.match(/(\w+)\/(\d+)/),$=A?.[1]??"Chrome",_=A?parseInt(A[2],10):0;return _>0&&_<k?y(u,200,{available:!1,reason:`Chrome version ${_} is below minimum required version ${k}`,hint:`Update Chrome to version ${k} or higher`,version:R.Browser,port:E,browser:$,debugPort:f}):y(u,200,{available:!0,version:R.Browser,remoteDebugging:!0,port:E,browser:$,debugPort:f})}if(b==="POST"&&C==="/api/chrome-session/launch"){let m=await re(v),g=M(),f=m.port??g.tools.chromeSession?.debugPort??9222,k=await It(f);if(k&&!k.pendingApproval){let _=k.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(u,200,{ok:!0,launched:!1,alreadyRunning:!0,port:k.port,version:k.versionInfo.Browser,browser:_?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${k.port}. No need to launch.`})}if(k?.pendingApproval)return y(u,200,{ok:!1,launched:!1,pendingApproval:!0,port:k.port,message:"Chrome is running on this port but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow'."});let x="/tmp/chrome-debug-profile",E=Rl(x,"DevToolsActivePort");try{Tl(E)}catch{}let R=process.platform,A,$=[`--remote-debugging-port=${f}`,`--user-data-dir=${x}`];if(R==="darwin"){let _=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",`${process.env.HOME}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,"/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"],H=_.find(L=>vt(L));if(!H)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:_,hint:"Install Google Chrome or specify the path manually."});A=H}else if(R==="win32"){A="cmd.exe";let _=process.env.ProgramFiles??"C:\\Program Files",H=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",L=[`${_}\\Google\\Chrome\\Application\\chrome.exe`,`${H}\\Google\\Chrome\\Application\\chrome.exe`,`${_}\\Microsoft\\Edge\\Application\\msedge.exe`,`${H}\\Microsoft\\Edge\\Application\\msedge.exe`],fe=L.find(Ae=>vt(Ae));if(!fe)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:L,hint:"Install Google Chrome or Microsoft Edge."});$=["/c","start","",fe,`--remote-debugging-port=${f}`]}else{let _=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],H=_.find(L=>vt(L));if(!H)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:_,hint:"Install Google Chrome or Chromium."});A=H}try{let _=Is(A,$,{detached:!0,stdio:"ignore"}),H=await Promise.race([new Promise(Ae=>_.once("error",Ae)),new Promise(Ae=>setTimeout(()=>Ae(null),500))]);if(H)return y(u,500,{ok:!1,error:H.message,chromePath:A,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});_.unref();let L;for(let Ae=0;Ae<5&&(await new Promise(st=>setTimeout(st,1e3)),L=await It(f),!L);Ae++);if(!L)return y(u,200,{ok:!1,launched:!0,port:f,chromePath:A,message:"Chrome was launched but CDP is not fully active. You may need to click 'Allow' in Chrome's remote debugging prompt, or try closing all existing Chrome windows first, then retry."});if(L.pendingApproval)return y(u,200,{ok:!1,launched:!0,pendingApproval:!0,port:L.port,chromePath:A,message:"Chrome was launched but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to enable agent control."});let fe=L.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(u,200,{ok:!0,launched:!0,port:L.port,chromePath:A,version:L.versionInfo.Browser,browser:fe?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${L.port}`})}catch(_){return y(u,500,{ok:!1,error:_ instanceof Error?_.message:String(_),chromePath:A,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&C==="/api/browser-relay/status"){let g=M().tools.browserRelay;if(!g.enabled)return y(u,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:g.extensionPath});if(o.browserRelay){let f=o.browserRelay.getStatus();return y(u,200,{enabled:!0,connected:f.connected,attachedTabs:f.attachedTabs,lastPing:f.lastPing,extensionPath:g.extensionPath})}return y(u,200,{enabled:g.enabled,connected:!1,attachedTabs:[],extensionPath:g.extensionPath})}if(b==="GET"&&C==="/api/browser-relay/config"){if(!Ns(v,u,"Browser Relay bootstrap is only available from localhost."))return;let m=M(),g=m.tools.browserRelay;return y(u,200,{enabled:g.enabled,port:m.gateway.port,token:g.enabled&&g.authToken||""})}if(b==="POST"&&C==="/api/browser-relay/launch"){let m=await re(v),g=M(),f=m.extensionPath??g.tools.browserRelay.extensionPath;if(!f)return y(u,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let k=process.platform,x,E=[`--load-extension=${f}`,"--no-first-run","--no-default-browser-check"];if(k==="darwin")x=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(vt)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(k==="win32"){let R=process.env.ProgramFiles??"C:\\Program Files",A=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";x=[`${R}\\Google\\Chrome\\Application\\chrome.exe`,`${A}\\Google\\Chrome\\Application\\chrome.exe`].find(vt)??`${R}\\Google\\Chrome\\Application\\chrome.exe`}else x="google-chrome";try{return Is(x,E,{detached:!0,stdio:"ignore"}).unref(),y(u,200,{ok:!0,launched:!0,extensionPath:f,message:`Chrome launched with extension from ${f}`})}catch(R){return y(u,500,{ok:!1,error:R instanceof Error?R.message:String(R),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let T=C.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),j=V(o.config.agents.defaults.workspace);if(b==="GET"&&C==="/api/automations"){let m=$t(j);return y(u,200,m)}if(b==="GET"&&T&&T[1]&&!T[2]){let m=T[1],g=ke(j,m);return g?y(u,200,g):y(u,404,{error:"Automation not found"})}if(b==="POST"&&C==="/api/automations"){let m=await re(v);try{let g={name:String(m.name??"Untitled"),description:String(m.description??""),steps:m.steps||[],tags:m.tags||[],source:m.source||"manual"};m.toolType!==void 0&&(g.toolType=m.toolType),m.variables!==void 0&&(g.variables=m.variables);let f=Xn(j,g);return y(u,201,f)}catch(g){return y(u,400,{error:String(g)})}}if(b==="PUT"&&T&&T[1]&&!T[2]){let m=T[1],g=await re(v),f={};g.name!==void 0&&(f.name=String(g.name)),g.description!==void 0&&(f.description=String(g.description)),g.enabled!==void 0&&(f.enabled=!!g.enabled),g.steps!==void 0&&(f.steps=g.steps),g.tags!==void 0&&(f.tags=g.tags),g.toolType!==void 0&&(f.toolType=g.toolType),g.variables!==void 0&&(f.variables=g.variables);let k=Yn(j,m,f);return k?y(u,200,k):y(u,404,{error:"Automation not found"})}if(b==="DELETE"&&T&&T[1]){let m=T[1];return Ot(j,m)?y(u,200,{ok:!0}):y(u,404,{error:"Automation not found"})}if(b==="POST"&&T&&T[1]&&T[2]==="/run"){let m=T[1],g=ke(j,m);return g?g.enabled?(o.agent.tools.execute("automation",{command:"run",id:m}).then(f=>{console.log(`[automation] Execution of '${g.name}' finished`,{logs:f.kind==="ok"?f.content:f})}).catch(f=>{console.error(`[automation] Execution of '${g.name}' failed`,{err:f})}),y(u,200,{ok:!0,message:`Automation '${g.name}' execution started in background.`})):y(u,400,{error:"Automation is disabled"}):y(u,404,{error:"Automation not found"})}if(b==="GET"&&C==="/api/history"){let m=String(P.searchParams.get("session")??"").trim(),g=h(m,"Session history not found.");if(g.error)return y(u,404,g.error);let f=g.sessionKey,k=o.sessionManager.getOrCreate(f);return y(u,200,{session:f,messages:Tr(k.messages)})}if(b==="GET"&&C==="/api/sessions"){let m=o.agent.getRuntimeState(),g=new Set((m.sessions||[]).filter(x=>x.running||x.queued>0).map(x=>x.key)),f=o.sessionManager.getOrCreate(o.sessionKey),k=o.sessionManager.listSessions().filter(x=>String(x.key??"")!==o.sessionKey).map(x=>{let E=String(x.key??"");return xr({key:E,created_at:String(x.created_at??f.createdAt),updated_at:String(x.updated_at??f.updatedAt)},o.sessionKey,g.has(E),o.sessionManager.getOrCreate(E))});return y(u,200,{currentSession:o.sessionKey,sessions:[xr({key:f.key,created_at:f.createdAt,updated_at:f.updatedAt},o.sessionKey,g.has(f.key),f),...k]})}if(b==="GET"&&C==="/api/files/preview"){let m=String(P.searchParams.get("path")??"").trim(),g=parseInt(P.searchParams.get("maxLines")??"100",10),f=o.workspacePath??process.cwd();if(!m)return y(u,400,{error:"path required"});try{Fe(m,f)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!vt(m))return y(u,404,{error:"file not found"});try{let k=ge.statSync(m);if(k.isDirectory())return y(u,400,{error:"path is a directory"});let x=_s(m),E=ge.readFileSync(m),R=null,A=!1;if(Ms(x)){let L=E.toString("utf-8").split(`
303
+ `);A=L.length>g,R=L.slice(0,g).join(`
304
+ `)}let $=Ce.extname(m).toLowerCase(),_=x.startsWith("image/")?"image":x==="application/pdf"?"pdf":x==="text/csv"||x==="text/tab-separated-values"?"table":Ms(x)?$===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes($)?"code":"text":"binary";return y(u,200,{name:Ce.basename(m),path:m,size:k.size,content:R,truncated:A,mimeType:x,previewType:_,extension:$})}catch(k){return y(u,500,{error:String(k)})}}if(b==="GET"&&C==="/api/files/content"){let m=String(P.searchParams.get("path")??"").trim(),g=o.workspacePath??process.cwd();if(!m)return y(u,400,{error:"path required"});try{Fe(m,g)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!vt(m))return y(u,404,{error:"file not found"});try{let f=ge.statSync(m);if(f.isDirectory())return y(u,400,{error:"path is a directory"});u.statusCode=200,u.setHeader("Content-Type",_s(m)),u.setHeader("Content-Length",String(f.size)),ge.createReadStream(m).pipe(u);return}catch(f){return y(u,500,{error:String(f)})}}if(b==="POST"&&C==="/api/sessions"){let m=await re(v),g=new Set(o.sessionManager.listSessions().map(_=>String(_.key??"")));g.add(o.sessionKey);let f=String(m.key??"").trim(),k=[...g].map(_=>o.sessionManager.getOrCreate(_)),x=ao(m.label),E=x||Ml(k),R=f||$l(g,x),A=g.has(R),$=o.sessionManager.getOrCreate(R);return A||($.metadata={...$.metadata,displayName:E},o.sessionManager.save($)),y(u,200,{created:!A,session:xr({key:$.key,created_at:$.createdAt,updated_at:$.updatedAt},o.sessionKey,!1,$)})}if(X&&b==="PUT"){let m=X[1]?decodeURIComponent(X[1]):void 0;if(!m)return y(u,400,"Invalid session key");let g=h(m,"Session not found.");if(g.error)return y(u,404,g.error);let f=await re(v),k=ao(f.label),x=Number(f.pinnedOrder),E=Number(f.recentOrder);if(k===void 0&&f.isPinned===void 0&&f.pinnedOrder===void 0&&f.recentOrder===void 0)return y(u,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:m});let R=o.sessionManager.getOrCreate(g.sessionKey);if(R.metadata={...R.metadata},k!==void 0&&(R.metadata.displayName=k),f.isPinned!==void 0&&(R.metadata.isPinned=!!f.isPinned),R.metadata.isPinned===!0){delete R.metadata.recentOrder;let $=[...$s(o.sessionManager,R.key)],_=Number.isFinite(x)?Math.max(0,Math.min(Math.trunc(x),$.length)):$.length;$.splice(_,0,R),Os(o.sessionManager,$),Ds(o.sessionManager,Ls(o.sessionManager,R.key))}else{delete R.metadata.pinnedOrder,Os(o.sessionManager,$s(o.sessionManager,R.key));let $=[...Ls(o.sessionManager,R.key)],_=Number.isFinite(E)?Math.max(0,Math.min(Math.trunc(E),$.length)):$.length;$.splice(_,0,R),Ds(o.sessionManager,$)}return o.sessionManager.save(R),y(u,200,{ok:!0,session:xr({key:R.key,created_at:R.createdAt,updated_at:R.updatedAt},o.sessionKey,!1,R)})}if(X&&b==="DELETE"){let m=X[1]?decodeURIComponent(X[1]):void 0;if(!m)return y(u,400,"Invalid session key");let g=h(m,"Session not found.");if(g.error)return y(u,404,g.error);if(g.sessionKey===o.sessionKey)return y(u,400,{error:"The primary session cannot be deleted."});let f=o.sessionManager.delete(g.sessionKey);return y(u,200,{ok:f,session:m})}if(b==="GET"&&C==="/api/suggestions"){let m=String(P.searchParams.get("session")??"").trim(),g=h(m,"Session suggestions not found.");if(g.error)return y(u,404,g.error);let f=g.sessionKey,k=o.sessionManager.getOrCreate(f),x=M(),E=x.subagents?.find(A=>A.id==="advisor"),R=E?E.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let A=$e(x),$=await Zr({task:R+`
305
+ Return ONLY a JSON array of strings, nothing else.`,provider:A,workspace:o.workspacePath??process.cwd(),model:x.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:x.tools.exec,restrictToWorkspace:x.tools.restrictToWorkspace,existingMessages:Tr(k.messages)}),_=[];try{let L=$.replace(/```json/g,"").replace(/```/g,"").trim();_=JSON.parse(L)}catch{_=io(k.messages).map(L=>L.text)}let H=Array.isArray(_)?_.slice(0,3).map((L,fe)=>({id:`suggestion-${fe+1}`,text:String(L),label:Rr(String(L),56)??String(L)})):io(k.messages);return y(u,200,{session:f,suggestions:H})}catch{return y(u,200,{session:f,suggestions:io(k.messages)})}}if(b==="GET"&&C==="/api/session-files"){let m=String(P.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");return g.error?y(u,404,g.error):y(u,200,{session:g.sessionKey,files:c().list(g.sessionKey)})}if(b==="GET"&&C==="/api/inbox-deliveries"){let m=P.searchParams.get("all")==="1",g=d();if(g.list({includeCleared:!0}).filter(x=>!x.clearedAt).length===0){let x=[{jobId:"demo-cron-daily-standup",jobName:"Daily standup reminder",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:`This is a sample cron notification to demonstrate the Inbox functionality. When real cron jobs run and deliver messages, they will appear here.
306
306
 
307
- This delivery is from a demo cron job that runs daily to remind the team about the standup meeting.`},{jobId:"demo-cron-weekly-report",jobName:"Weekly progress report",sessionKey:"telegram:8281248569",channel:"telegram",recipient:"8281248569",content:"Your weekly progress report is ready. This demo delivery shows how proactive notifications from cron jobs appear in your inbox. You can clear this delivery once reviewed."},{jobId:"demo-cron-backup",jobName:"Backup completed",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:"Automated backup completed successfully at 3:00 AM. All project files have been archived to the backup location. This is a demo delivery for testing the inbox clear functionality."}],E=new Date;for(let C=0;C<x.length;C++){let R=x[C],M=new Date(E.getTime()-C*36e5).toISOString();m.record({jobId:R.jobId,jobName:R.jobName,sessionKey:R.sessionKey,channel:R.channel,recipient:R.recipient,content:R.content,deliveredAt:M})}}return y(d,200,{deliveries:m.list({includeCleared:p})})}if(ae&&b==="GET"){let p=ae[1];if(!p)return y(d,400,"Invalid delivery ID");let m=u().get(decodeURIComponent(p));return m?y(d,200,{delivery:m}):y(d,404,{error:"Inbox delivery not found."})}if(J&&b==="POST"){let p=J[1];if(!p)return y(d,400,"Invalid delivery ID");let m=u().markCleared(decodeURIComponent(p));return m?y(d,200,{ok:!0,delivery:m}):y(d,404,{error:"Inbox delivery not found."})}if(b==="POST"&&k==="/api/session-files"){let p=await ne(v),m=String(p.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(d,404,f.error);try{return y(d,200,c().associate(f.sessionKey,String(p.path??"")))}catch(w){return y(d,400,{error:w instanceof Error?w.message:String(w)})}}if(b==="POST"&&k==="/api/session-files/upload"){let p=await ne(v),m=String(p.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(d,404,f.error);let w=String(p.filename??"").trim(),x=String(p.content??"").trim();if(!w)return y(d,400,{error:"Filename is required."});if(!x)return y(d,400,{error:"File content is required."});let E=[".md",".txt",".pdf",".jpg",".jpeg",".png",".gif",".webp",".json",".js",".jsx",".ts",".tsx",".css",".html",".xml",".yml",".yaml",".py",".rb",".go",".rs",".java",".c",".cc",".cpp",".h",".hpp",".sh"],C=w.toLowerCase().slice(w.lastIndexOf("."));if(!C||!E.includes(C))return y(d,400,{error:`Unsupported file type. Allowed: ${E.join(", ")}`});try{let R=Buffer.from(x,"base64"),M=ke.join(o.workspacePath??process.cwd(),".session-uploads");de.existsSync(M)||de.mkdirSync(M,{recursive:!0});let P=w.replace(/[^a-zA-Z0-9._-]/g,"_"),V=ke.join(M,`${Date.now()}-${P}`);return de.writeFileSync(V,R),y(d,200,c().associate(f.sessionKey,V))}catch(R){return y(d,400,{error:R instanceof Error?R.message:String(R)})}}if(b==="POST"&&k==="/api/session-files/copy-local"){let p=await ne(v),m=String(p.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(d,404,f.error);let w=String(p.path??"").trim(),x=o.workspacePath??process.cwd();if(!w)return y(d,400,{error:"Path is required."});try{je(w,x)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!de.existsSync(w))return y(d,404,{error:"File not found."});try{return de.statSync(w).isDirectory()?y(d,400,{error:"Path is a directory."}):y(d,200,c().associate(f.sessionKey,w))}catch(E){return y(d,400,{error:E instanceof Error?E.message:String(E)})}}if(A&&b==="GET"){let p=String(O.searchParams.get("session")??"").trim(),m=h(p,"Session files not found.");if(m.error)return y(d,404,m.error);let f=A[1];if(!f)return y(d,400,"Invalid file ID");let w=c().get(m.sessionKey,decodeURIComponent(f));return w?y(d,200,{session:m.sessionKey,file:w}):y(d,404,{error:"Session file not found.",session:m.sessionKey})}if(A&&b==="DELETE"){let p=String(O.searchParams.get("session")??"").trim(),m=h(p,"Session files not found.");if(m.error)return y(d,404,m.error);let f=A[1];return f?y(d,200,{ok:c().remove(m.sessionKey,decodeURIComponent(f))}):y(d,400,"Invalid file ID")}if(b==="POST"&&k==="/api/chat/stream"){let p=await ne(v),m=p.message,f=String(p.session??"default:everclaw"),w=String(p.model??"").trim(),x=String(p._provider??"").trim(),E=Array.isArray(m)?m:String(m??"").trim();if(typeof E=="string"&&!E)return y(d,400,{error:"message required"});if(Array.isArray(E)&&E.length===0)return y(d,400,{error:"message required"});d.setHeader("Content-Type","text/event-stream"),d.setHeader("Cache-Control","no-cache"),d.setHeader("Connection","keep-alive"),d.flushHeaders();let C=P=>{d.write(`data: ${JSON.stringify(P)}
307
+ This delivery is from a demo cron job that runs daily to remind the team about the standup meeting.`},{jobId:"demo-cron-weekly-report",jobName:"Weekly progress report",sessionKey:"telegram:8281248569",channel:"telegram",recipient:"8281248569",content:"Your weekly progress report is ready. This demo delivery shows how proactive notifications from cron jobs appear in your inbox. You can clear this delivery once reviewed."},{jobId:"demo-cron-backup",jobName:"Backup completed",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:"Automated backup completed successfully at 3:00 AM. All project files have been archived to the backup location. This is a demo delivery for testing the inbox clear functionality."}],E=new Date;for(let R=0;R<x.length;R++){let A=x[R],$=new Date(E.getTime()-R*36e5).toISOString();g.record({jobId:A.jobId,jobName:A.jobName,sessionKey:A.sessionKey,channel:A.channel,recipient:A.recipient,content:A.content,deliveredAt:$})}}return y(u,200,{deliveries:g.list({includeCleared:m})})}if(z&&b==="GET"){let m=z[1];if(!m)return y(u,400,"Invalid delivery ID");let g=d().get(decodeURIComponent(m));return g?y(u,200,{delivery:g}):y(u,404,{error:"Inbox delivery not found."})}if(W&&b==="POST"){let m=W[1];if(!m)return y(u,400,"Invalid delivery ID");let g=d().markCleared(decodeURIComponent(m));return g?y(u,200,{ok:!0,delivery:g}):y(u,404,{error:"Inbox delivery not found."})}if(b==="POST"&&C==="/api/session-files"){let m=await re(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(u,404,f.error);try{return y(u,200,c().associate(f.sessionKey,String(m.path??"")))}catch(k){return y(u,400,{error:k instanceof Error?k.message:String(k)})}}if(b==="POST"&&C==="/api/session-files/upload"){let m=await re(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(u,404,f.error);let k=String(m.filename??"").trim(),x=String(m.content??"").trim();if(!k)return y(u,400,{error:"Filename is required."});if(!x)return y(u,400,{error:"File content is required."});let E=[".md",".txt",".pdf",".jpg",".jpeg",".png",".gif",".webp",".json",".js",".jsx",".ts",".tsx",".css",".html",".xml",".yml",".yaml",".py",".rb",".go",".rs",".java",".c",".cc",".cpp",".h",".hpp",".sh"],R=k.toLowerCase().slice(k.lastIndexOf("."));if(!R||!E.includes(R))return y(u,400,{error:`Unsupported file type. Allowed: ${E.join(", ")}`});try{let A=Buffer.from(x,"base64"),$=Ce.join(o.workspacePath??process.cwd(),".session-uploads");ge.existsSync($)||ge.mkdirSync($,{recursive:!0});let _=k.replace(/[^a-zA-Z0-9._-]/g,"_"),H=Ce.join($,`${Date.now()}-${_}`);return ge.writeFileSync(H,A),y(u,200,c().associate(f.sessionKey,H))}catch(A){return y(u,400,{error:A instanceof Error?A.message:String(A)})}}if(b==="POST"&&C==="/api/session-files/copy-local"){let m=await re(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(u,404,f.error);let k=String(m.path??"").trim(),x=o.workspacePath??process.cwd();if(!k)return y(u,400,{error:"Path is required."});try{Fe(k,x)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!ge.existsSync(k))return y(u,404,{error:"File not found."});try{return ge.statSync(k).isDirectory()?y(u,400,{error:"Path is a directory."}):y(u,200,c().associate(f.sessionKey,k))}catch(E){return y(u,400,{error:E instanceof Error?E.message:String(E)})}}if(ae&&b==="GET"){let m=String(P.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");if(g.error)return y(u,404,g.error);let f=ae[1];if(!f)return y(u,400,"Invalid file ID");let k=c().get(g.sessionKey,decodeURIComponent(f));return k?y(u,200,{session:g.sessionKey,file:k}):y(u,404,{error:"Session file not found.",session:g.sessionKey})}if(ae&&b==="DELETE"){let m=String(P.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");if(g.error)return y(u,404,g.error);let f=ae[1];return f?y(u,200,{ok:c().remove(g.sessionKey,decodeURIComponent(f))}):y(u,400,"Invalid file ID")}if(b==="POST"&&C==="/api/chat/stream"){let m=await re(v),g=m.message,f=String(m.session??"default:everclaw"),k=String(m.model??"").trim(),x=String(m._provider??"").trim(),E=Array.isArray(g)?g:String(g??"").trim();if(typeof E=="string"&&!E)return y(u,400,{error:"message required"});if(Array.isArray(E)&&E.length===0)return y(u,400,{error:"message required"});u.setHeader("Content-Type","text/event-stream"),u.setHeader("Cache-Control","no-cache"),u.setHeader("Connection","keep-alive"),u.flushHeaders();let R=_=>{u.write(`data: ${JSON.stringify(_)}
308
308
 
309
- `)},R="",M=[];try{let P=await o.agent.processDirectResult(E,f,"cli","dashboard",async(V,D)=>{if(D?.thinkingContent&&(R=D.thinkingContent),Array.isArray(D?.tool_calls)&&(M=D.tool_calls),D?.tool_call&&typeof D.tool_call=="object"){let me=D.tool_call,Re=typeof me.id=="string"?me.id:"";M=M.some(st=>st.id===Re)?M.map(st=>st.id===Re?{...st,...me}:st):[...M,me]}switch(D?.event){case"thinking":C({type:"thinking",content:D.thinkingContent??V});break;case"tool_calls":C({type:"tool_calls",tool_calls:M});break;case"tool_result":C({type:"tool_result",tool_call:D.tool_call,tool_calls:M});break;case"answer":C({type:"answer",content:V});break;default:C({type:"progress",content:V,toolHint:!!D?.toolHint,...D?.tool_calls?{tool_calls:D.tool_calls}:{}});break}},{...w?{_model:w}:{},...x?{_provider:x}:{},...Array.isArray(p.skillNames)&&p.skillNames.length?{skillNames:p.skillNames}:{}});P.outcome==="rate_limited"?C({type:"error",error:P.content,outcome:P.outcome,retryAfterMs:P.retryAfterMs??0}):P.outcome==="backpressure"||P.outcome==="shutdown"?C({type:"error",error:P.content,outcome:P.outcome}):C({type:"done",response:P.content,thinkingContent:R,tool_calls:M})}catch(P){C({type:"error",error:String(P)})}finally{d.end()}return}if(b==="POST"&&k==="/api/chat"){let p=await ne(v),m=p.message,f=String(p.session??"default:everclaw"),w=String(p.model??"").trim(),x=String(p._provider??"").trim(),E=Array.isArray(m)?m:String(m??"").trim();if(typeof E=="string"&&!E)return y(d,400,{error:"message required"});if(Array.isArray(E)&&E.length===0)return y(d,400,{error:"message required"});let C=[];try{let R=await o.agent.processDirectResult(E,f,"cli","dashboard",async(M,P)=>{C.push({content:M,toolHint:!!P?.toolHint,...P?.tool_calls?{tool_calls:P.tool_calls}:{}})},{...w?{_model:w}:{},...x?{_provider:x}:{}});return R.outcome==="rate_limited"?(d.setHeader("Retry-After",String(Math.max(1,Math.ceil((R.retryAfterMs??0)/1e3)))),y(d,429,{error:R.content,outcome:R.outcome,retryAfterMs:R.retryAfterMs??0,progress:C})):R.outcome==="backpressure"||R.outcome==="shutdown"?y(d,503,{error:R.content,outcome:R.outcome,progress:C}):y(d,200,{response:R.content,progress:C})}catch(R){return y(d,500,{error:String(R)})}}if(b==="GET"&&k==="/api/config")return y(d,200,Pl(_()));if(b==="GET"&&k==="/api/security/status"){let{ToolGuardEngine:p}=await Promise.resolve().then(()=>(oo(),Rs)),f=p.getInstance().getRules(),w=f.filter(E=>E.enabled),x=_();return y(d,200,{toolGuard:{enabled:x.security?.toolGuard?.enabled??!1,totalRules:f.length,enabledRules:w.length,defaultRules:f.filter(E=>!E.id.startsWith("user-")).length,userRules:x.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:x.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&k==="/api/config"){let p=await ne(v),m=et(p.config)?p.config:null;if(!m)return y(d,400,{error:"Request body must include a config object."});let f=Ml(m),w=_(),x=p.secretChanges;w.security?.auth&&f.security?.auth&&"pinHash"in w.security.auth&&(f.security.auth.pinHash=w.security.auth.pinHash);try{if(f.providers&&w.providers)for(let C of Object.keys(f.providers))f.providers[C]&&w.providers[C]&&vt(f,w,x,["providers",C,"apiKey"]);if(Array.isArray(f.customLlmProviders)&&Array.isArray(w.customLlmProviders))for(let C=0;C<f.customLlmProviders.length;C++){let R=f.customLlmProviders[C];if(!R)continue;let P=w.customLlmProviders.find(me=>me?.name===R.name)?.apiKey??"",V=R.apiKey??"",D=Ns(x,["customLlmProviders",C,"apiKey"],P,V);D&&(R.apiKey=D.action==="keep"?P:D.action==="clear"?"":D.value??V)}if(f.channels&&w.channels&&(vt(f,w,x,["channels","telegram","token"]),vt(f,w,x,["channels","discord","token"])),f.tools?.browserRelay&&w.tools?.browserRelay&&vt(f,w,x,["tools","browserRelay","authToken"]),f.tools?.web?.search&&w.tools?.web?.search&&vt(f,w,x,["tools","web","search","apiKey"]),f.tools?.mcpServers&&w.tools?.mcpServers)for(let C of Object.keys(f.tools.mcpServers)){let R=f.tools.mcpServers[C];if(R?.env)for(let M of Object.keys(R.env))vt(f,w,x,["tools","mcpServers",C,"env",M]);if(R?.headers)for(let M of Object.keys(R.headers))vt(f,w,x,["tools","mcpServers",C,"headers",M])}}catch(C){return y(d,400,{error:C instanceof Error?C.message:String(C)})}if(f.security?.auth?.enabled&&!f.security?.auth?.pinHash?.length)return y(d,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let E=_l(f.tools?.mcpServers??{});return E.length?y(d,400,{error:`Invalid MCP server configuration. ${E[0]}`,details:E}):(oe(f),l.updateConfig(f.security.auth),y(d,200,{ok:!0}))}if(b==="GET"&&k==="/api/subagents"){let p=_();return y(d,200,{subagents:p.subagents||[]})}if(b==="POST"&&k==="/api/subagents"){let p=await ne(v),m=_();m.subagents||(m.subagents=[]);let f=m.subagents.length,w={id:`subagent-${Date.now()}`,name:p.name||`SubAgent ${f+1}`,task:p.task||"",createdAt:Date.now()};return m.subagents.push(w),oe(m),y(d,200,w)}let q=k.match(/^\/api\/subagents\/([^/]+)$/);if(q&&b==="PUT"){let p=q[1];if(!p)return y(d,400,"Invalid subagent ID");let m=await ne(v),f=_();f.subagents||(f.subagents=[]);let w=f.subagents.findIndex(C=>C.id===p);if(w===-1)return y(d,404,{error:"Subagent not found"});let x=f.subagents[w];if(!x)return y(d,404,{error:"Subagent not found"});let E={id:m.id??x.id,name:m.name??x.name,task:m.task??x.task,createdAt:m.createdAt??x.createdAt};return f.subagents[w]=E,oe(f),y(d,200,E)}if(q&&b==="DELETE"){let p=q[1],m=_();m.subagents||(m.subagents=[]);let f=m.subagents.findIndex(w=>w.id===p);return f===-1?y(d,404,{error:"Subagent not found"}):(m.subagents.splice(f,1),oe(m),y(d,200,{ok:!0}))}if(b==="GET"&&k==="/api/skills")try{return y(d,200,n.getSnapshot())}catch(p){return y(d,500,{error:String(p)})}if(b==="POST"&&k==="/api/skills/install"){let p=await ne(v);try{let m=await n.install(String(p.slug??""));return y(d,200,m)}catch(m){return y(d,400,{error:m instanceof Error?m.message:String(m)})}}if(b==="GET"&&k==="/api/cron/jobs"){let p=O.searchParams.get("all")==="1";return y(d,200,o.cron.listJobs(p))}if(b==="POST"&&k==="/api/cron/jobs"){let p=await ne(v);try{let m={name:String(p.name??"job"),schedule:p.schedule,message:String(p.message??""),deliver:!!p.deliver,deleteAfterRun:!!p.deleteAfterRun};p.channel&&(m.channel=String(p.channel)),p.to&&(m.to=String(p.to));let f=o.cron.addJob(m);return y(d,200,f)}catch(m){return y(d,400,{error:String(m)})}}if(N&&b==="DELETE"){let p=N[1];return p?y(d,200,{ok:o.cron.removeJob(p)}):y(d,400,"Invalid job ID")}if(N&&b==="PUT"){let p=N[1];if(!p)return y(d,400,"Invalid job ID");let m=await ne(v),f={};m.name!==void 0&&(f.name=String(m.name)),m.schedule!==void 0&&(f.schedule=m.schedule),m.message!==void 0&&(f.message=String(m.message)),m.deliver!==void 0&&(f.deliver=!!m.deliver),m.channel!==void 0&&(f.channel=String(m.channel)),m.to!==void 0&&(f.to=String(m.to)),m.deleteAfterRun!==void 0&&(f.deleteAfterRun=!!m.deleteAfterRun);let w=o.cron.updateJob(p,f);return w?y(d,200,w):y(d,404,{error:"not found"})}if(z&&b==="POST"){let m=(await ne(v)).enabled!==!1,f=z[1];if(!f)return y(d,400,"Invalid job ID");let w=o.cron.enableJob(f,m);return w?y(d,200,w):y(d,404,{error:"not found"})}if(B&&b==="POST"){let p=await ne(v),m=B[1];if(!m)return y(d,400,"Invalid job ID");let f=await o.cron.runJob(m,!!p.force);return y(d,200,{ok:f})}let re=o.config.gateway.dashboard?.enabled!==!1;if(re&&e){let p=ke.resolve(e,k==="/"?"index.html":k.slice(1));if(!p.startsWith(ke.resolve(e)+ke.sep)&&p!==ke.resolve(e)&&(p=ke.join(e,"index.html")),(!de.existsSync(p)||de.statSync(p).isDirectory())&&(p=ke.join(e,"index.html")),!de.existsSync(p)){d.statusCode=404,d.end("Dashboard assets not found. Run npm run build.");return}d.statusCode=200,d.setHeader("Content-Type",Al(p)),de.createReadStream(p).pipe(d);return}if(!k.startsWith("/api/")){d.statusCode=404,d.end(re?"Dashboard assets not found. Install the full package or run `npm run build:dashboard`.":"Dashboard is disabled. API endpoints are still available.");return}d.statusCode=404,d.end("Dashboard is disabled. API endpoints are still available.")});return T.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(T),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((v,d)=>T.close(b=>{try{r?.close(),s?.close()}catch{}b?d(b):v()})))}}le();import{spawn as Rr}from"node:child_process";import{createWriteStream as Ll,existsSync as Ut,lstatSync as Dl,mkdirSync as Nl,readdirSync as jl,rmSync as pn}from"node:fs";import Ar from"node:path";import{pipeline as Fl}from"node:stream/promises";var Ce="0.28.0",Fs="https://github.com/rtk-ai/rtk/releases",Bs=3e4,Er={"darwin-arm64":"rtk-aarch64-apple-darwin.tar.gz","darwin-x64":"rtk-x86_64-apple-darwin.tar.gz","linux-arm64":"rtk-aarch64-unknown-linux-gnu.tar.gz","linux-x64":"rtk-x86_64-unknown-linux-musl.tar.gz","win32-x64":"rtk-x86_64-pc-windows-msvc.zip"},Bl=200,Ul=5e3;function Us(o){return Math.ceil(o.length/4)}function wt(o,e){let t=c=>c.split(".").map(u=>parseInt(u,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var Te=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return Ar.join(fn(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Ut(t)){let n=await this.getVersion(t);if(n&&wt(n,Ce))return this.runtime={available:!0,binaryPath:t,version:n},this.runtime;if(e.autoInstall&&process.env.CI!=="true"){console.error(`[rtk] Binary outdated (${n}, need ${Ce}). Re-downloading...`);try{return await this.install({version:e.version,force:!0})}catch(r){return console.error(`[rtk] Failed to re-download: ${r instanceof Error?r.message:String(r)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}if(e.autoInstall&&process.env.CI!=="true")try{return await this.install({version:e.version})}catch(n){return console.error(`[rtk] Auto-download failed: ${n instanceof Error?n.message:String(n)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}async install(e){let t=e?.version??"latest",n=`${process.platform}-${process.arch}`,r=Er[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Er).join(", ")}`);let s=o.binaryPath(),i=Ar.dirname(s);if(!e?.force&&Ut(s)){let c=await this.getVersion(s);if(c&&wt(c,Ce))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${Fs}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${Fs}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Ut(i)||Nl(i,{recursive:!0});let l=Ar.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:u}=await import("node:fs");u(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{Ut(l)&&pn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),Bs);try{let i=await fetch(e,{redirect:"follow",signal:r.signal});if(!i.ok)throw new Error(`Download failed: ${i.status} ${i.statusText}`);if(!i.body)throw new Error("Download failed: No response body");await Fl(n.fromWeb(i.body),Ll(t))}catch(i){throw pn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${Bs}ms`):i}finally{clearTimeout(s)}}async extractTarGz(e,t){let{renameSync:n}=await import("node:fs"),{mkdtemp:r}=await import("node:fs/promises"),{tmpdir:s}=await import("node:os"),{join:i}=await import("node:path");if(process.platform==="win32")throw new Error("tar.gz extraction on Windows is not supported \u2014 use .zip assets");let a=await r(i(s(),"rtk-extract-"));try{let l=Rr("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((u,g)=>{l.on("close",h=>{h===0?u():g(new Error(`tar extraction failed with code ${h}`))}),l.on("error",g)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{pn(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of jl(e)){let s=Ar.join(e,r),i=Dl(s);if(!i.isSymbolicLink()){if(i.isFile()&&n.includes(r))return s;if(i.isDirectory()){let a=this.findBinaryInDir(s,t);if(a)return a}}}return null}async extractZip(e,t){let{renameSync:n}=await import("node:fs"),{mkdtemp:r}=await import("node:fs/promises"),{tmpdir:s}=await import("node:os"),{join:i}=await import("node:path"),a=await r(i(s(),"rtk-extract-"));try{let l=Rr("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((u,g)=>{l.on("close",h=>{h===0?u():g(new Error(`PowerShell extraction failed with code ${h}`))}),l.on("error",g)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{pn(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Ut(e)&&pn(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Ut(e)?{installed:!0,version:await this.getVersion(e),binaryPath:e}:{installed:!1,version:null,binaryPath:e}}async getVersion(e){return new Promise(t=>{let n=Rr(e,["--version"]),r="";n.stdout?.on("data",s=>{r+=s.toString()}),n.on("close",s=>{if(s===0){let i=r.match(/(\d+\.\d+\.\d+)/);t(i?i[1]??null:r.trim()||null)}else t(null)}),n.on("error",()=>t(null))})}async compress(e){if(!this.runtime.available)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};if(e.stdout.length<Bl)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=Us(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=Us(n);return{stdout:n,stderr:e.stderr,compressed:!0,originalTokens:t,compressedTokens:r}}catch{return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0}}}async runRtkSummary(e,t){return new Promise((n,r)=>{let s=t?["-u","summary"]:["summary"],i=Rr(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},Ul);i.stdout?.on("data",u=>{a+=u.toString()}),i.stderr?.on("data",u=>{l+=u.toString()}),i.stdin?.end(e,"utf8"),i.on("close",u=>{clearTimeout(c),u===0?n(a):r(new Error(`rtk exited with code ${u}: ${l}`))}),i.on("error",u=>{clearTimeout(c),r(u)})})}};import{randomUUID as Gl}from"node:crypto";import co,{WebSocketServer as Wl}from"ws";var uo=class{wss=null;extension=null;config;onStatusChange;constructor(e,t){this.config=e,this.onStatusChange=t}handleUpgrade(e,t,n){if(!this.wss){t.destroy();return}let s=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`).searchParams.get("token");if(!this.config.enabled){t.write(`HTTP/1.1 503 Service Unavailable\r
309
+ `)},A="",$=[];try{let _=await o.agent.processDirectResult(E,f,"cli","dashboard",async(H,L)=>{if(L?.thinkingContent&&(A=L.thinkingContent),Array.isArray(L?.tool_calls)&&($=L.tool_calls),L?.tool_call&&typeof L.tool_call=="object"){let fe=L.tool_call,Ae=typeof fe.id=="string"?fe.id:"";$=$.some(st=>st.id===Ae)?$.map(st=>st.id===Ae?{...st,...fe}:st):[...$,fe]}switch(L?.event){case"thinking":R({type:"thinking",content:L.thinkingContent??H});break;case"tool_calls":R({type:"tool_calls",tool_calls:$});break;case"tool_result":R({type:"tool_result",tool_call:L.tool_call,tool_calls:$});break;case"answer":R({type:"answer",content:H});break;default:R({type:"progress",content:H,toolHint:!!L?.toolHint,...L?.tool_calls?{tool_calls:L.tool_calls}:{}});break}},{...k?{_model:k}:{},...x?{_provider:x}:{},...Array.isArray(m.skillNames)&&m.skillNames.length?{skillNames:m.skillNames}:{}});_.outcome==="rate_limited"?R({type:"error",error:_.content,outcome:_.outcome,retryAfterMs:_.retryAfterMs??0}):_.outcome==="backpressure"||_.outcome==="shutdown"?R({type:"error",error:_.content,outcome:_.outcome}):R({type:"done",response:_.content,thinkingContent:A,tool_calls:$})}catch(_){R({type:"error",error:String(_)})}finally{u.end()}return}if(b==="POST"&&C==="/api/chat"){let m=await re(v),g=m.message,f=String(m.session??"default:everclaw"),k=String(m.model??"").trim(),x=String(m._provider??"").trim(),E=Array.isArray(g)?g:String(g??"").trim();if(typeof E=="string"&&!E)return y(u,400,{error:"message required"});if(Array.isArray(E)&&E.length===0)return y(u,400,{error:"message required"});let R=[];try{let A=await o.agent.processDirectResult(E,f,"cli","dashboard",async($,_)=>{R.push({content:$,toolHint:!!_?.toolHint,..._?.tool_calls?{tool_calls:_.tool_calls}:{}})},{...k?{_model:k}:{},...x?{_provider:x}:{}});return A.outcome==="rate_limited"?(u.setHeader("Retry-After",String(Math.max(1,Math.ceil((A.retryAfterMs??0)/1e3)))),y(u,429,{error:A.content,outcome:A.outcome,retryAfterMs:A.retryAfterMs??0,progress:R})):A.outcome==="backpressure"||A.outcome==="shutdown"?y(u,503,{error:A.content,outcome:A.outcome,progress:R}):y(u,200,{response:A.content,progress:R})}catch(A){return y(u,500,{error:String(A)})}}if(b==="GET"&&C==="/api/config")return y(u,200,Dl(M()));if(b==="GET"&&C==="/api/security/status"){let{ToolGuardEngine:m}=await Promise.resolve().then(()=>(so(),Ps)),f=m.getInstance().getRules(),k=f.filter(E=>E.enabled),x=M();return y(u,200,{toolGuard:{enabled:x.security?.toolGuard?.enabled??!1,totalRules:f.length,enabledRules:k.length,defaultRules:f.filter(E=>!E.id.startsWith("user-")).length,userRules:x.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:x.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&C==="/api/config"){let m=await re(v),g=et(m.config)?m.config:null;if(!g)return y(u,400,{error:"Request body must include a config object."});let f=Fl(g),k=M(),x=m.secretChanges;k.security?.auth&&f.security?.auth&&"pinHash"in k.security.auth&&(f.security.auth.pinHash=k.security.auth.pinHash);try{if(f.providers&&k.providers)for(let R of Object.keys(f.providers))f.providers[R]&&k.providers[R]&&wt(f,k,x,["providers",R,"apiKey"]);if(Array.isArray(f.customLlmProviders)&&Array.isArray(k.customLlmProviders))for(let R=0;R<f.customLlmProviders.length;R++){let A=f.customLlmProviders[R];if(!A)continue;let _=k.customLlmProviders.find(fe=>fe?.name===A.name)?.apiKey??"",H=A.apiKey??"",L=Bs(x,["customLlmProviders",R,"apiKey"],_,H);L&&(A.apiKey=L.action==="keep"?_:L.action==="clear"?"":L.value??H)}if(f.channels&&k.channels&&(wt(f,k,x,["channels","telegram","token"]),wt(f,k,x,["channels","discord","token"])),f.tools?.browserRelay&&k.tools?.browserRelay&&wt(f,k,x,["tools","browserRelay","authToken"]),f.tools?.web?.search&&k.tools?.web?.search&&wt(f,k,x,["tools","web","search","apiKey"]),f.tools?.mcpServers&&k.tools?.mcpServers)for(let R of Object.keys(f.tools.mcpServers)){let A=f.tools.mcpServers[R];if(A?.env)for(let $ of Object.keys(A.env))wt(f,k,x,["tools","mcpServers",R,"env",$]);if(A?.headers)for(let $ of Object.keys(A.headers))wt(f,k,x,["tools","mcpServers",R,"headers",$])}}catch(R){return y(u,400,{error:R instanceof Error?R.message:String(R)})}if(f.security?.auth?.enabled&&!f.security?.auth?.pinHash?.length)return y(u,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let E=jl(f.tools?.mcpServers??{});return E.length?y(u,400,{error:`Invalid MCP server configuration. ${E[0]}`,details:E}):(oe(f),l.updateConfig(f.security.auth),y(u,200,{ok:!0}))}if(b==="GET"&&C==="/api/subagents"){let m=M();return y(u,200,{subagents:m.subagents||[]})}if(b==="POST"&&C==="/api/subagents"){let m=await re(v),g=M();g.subagents||(g.subagents=[]);let f=g.subagents.length,k={id:`subagent-${Date.now()}`,name:m.name||`SubAgent ${f+1}`,task:m.task||"",createdAt:Date.now()};return g.subagents.push(k),oe(g),y(u,200,k)}let D=C.match(/^\/api\/subagents\/([^/]+)$/);if(D&&b==="PUT"){let m=D[1];if(!m)return y(u,400,"Invalid subagent ID");let g=await re(v),f=M();f.subagents||(f.subagents=[]);let k=f.subagents.findIndex(R=>R.id===m);if(k===-1)return y(u,404,{error:"Subagent not found"});let x=f.subagents[k];if(!x)return y(u,404,{error:"Subagent not found"});let E={id:g.id??x.id,name:g.name??x.name,task:g.task??x.task,createdAt:g.createdAt??x.createdAt};return f.subagents[k]=E,oe(f),y(u,200,E)}if(D&&b==="DELETE"){let m=D[1],g=M();g.subagents||(g.subagents=[]);let f=g.subagents.findIndex(k=>k.id===m);return f===-1?y(u,404,{error:"Subagent not found"}):(g.subagents.splice(f,1),oe(g),y(u,200,{ok:!0}))}if(b==="GET"&&C==="/api/skills")try{return y(u,200,n.getSnapshot())}catch(m){return y(u,500,{error:String(m)})}if(b==="POST"&&C==="/api/skills/install"){let m=await re(v);try{let g=await n.install(String(m.slug??""));return y(u,200,g)}catch(g){return y(u,400,{error:g instanceof Error?g.message:String(g)})}}if(b==="GET"&&C==="/api/cron/jobs"){let m=P.searchParams.get("all")==="1";return y(u,200,o.cron.listJobs(m))}if(b==="POST"&&C==="/api/cron/jobs"){let m=await re(v);try{let g={name:String(m.name??"job"),schedule:m.schedule,message:String(m.message??""),deliver:!!m.deliver,deleteAfterRun:!!m.deleteAfterRun};m.channel&&(g.channel=String(m.channel)),m.to&&(g.to=String(m.to));let f=o.cron.addJob(g);return y(u,200,f)}catch(g){return y(u,400,{error:String(g)})}}if(I&&b==="DELETE"){let m=I[1];return m?y(u,200,{ok:o.cron.removeJob(m)}):y(u,400,"Invalid job ID")}if(I&&b==="PUT"){let m=I[1];if(!m)return y(u,400,"Invalid job ID");let g=await re(v),f={};g.name!==void 0&&(f.name=String(g.name)),g.schedule!==void 0&&(f.schedule=g.schedule),g.message!==void 0&&(f.message=String(g.message)),g.deliver!==void 0&&(f.deliver=!!g.deliver),g.channel!==void 0&&(f.channel=String(g.channel)),g.to!==void 0&&(f.to=String(g.to)),g.deleteAfterRun!==void 0&&(f.deleteAfterRun=!!g.deleteAfterRun);let k=o.cron.updateJob(m,f);return k?y(u,200,k):y(u,404,{error:"not found"})}if(J&&b==="POST"){let g=(await re(v)).enabled!==!1,f=J[1];if(!f)return y(u,400,"Invalid job ID");let k=o.cron.enableJob(f,g);return k?y(u,200,k):y(u,404,{error:"not found"})}if(Q&&b==="POST"){let m=await re(v),g=Q[1];if(!g)return y(u,400,"Invalid job ID");let f=await o.cron.runJob(g,!!m.force);return y(u,200,{ok:f})}let ee=o.config.gateway.dashboard?.enabled!==!1;if(ee&&e){let m=Ce.resolve(e,C==="/"?"index.html":C.slice(1));if(!m.startsWith(Ce.resolve(e)+Ce.sep)&&m!==Ce.resolve(e)&&(m=Ce.join(e,"index.html")),(!ge.existsSync(m)||ge.statSync(m).isDirectory())&&(m=Ce.join(e,"index.html")),!ge.existsSync(m)){u.statusCode=404,u.end("Dashboard assets not found. Run npm run build.");return}u.statusCode=200,u.setHeader("Content-Type",Ol(m)),ge.createReadStream(m).pipe(u);return}if(!C.startsWith("/api/")){u.statusCode=404,u.end(ee?"Dashboard assets not found. Install the full package or run `npm run build:dashboard`.":"Dashboard is disabled. API endpoints are still available.");return}u.statusCode=404,u.end("Dashboard is disabled. API endpoints are still available.")});return w.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(w),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((v,u)=>w.close(b=>{try{r?.close(),s?.close()}catch{}b?u(b):v()})))}}ce();import{spawn as Ar}from"node:child_process";import{createWriteStream as Ul,existsSync as Gt,lstatSync as Wl,mkdirSync as Kl,readdirSync as ql,rmSync as pn}from"node:fs";import Er from"node:path";import{pipeline as Jl}from"node:stream/promises";var Te="0.28.0",Us="https://github.com/rtk-ai/rtk/releases",Ws=3e4,Pr={"darwin-arm64":"rtk-aarch64-apple-darwin.tar.gz","darwin-x64":"rtk-x86_64-apple-darwin.tar.gz","linux-arm64":"rtk-aarch64-unknown-linux-gnu.tar.gz","linux-x64":"rtk-x86_64-unknown-linux-musl.tar.gz","win32-x64":"rtk-x86_64-pc-windows-msvc.zip"},Hl=200,zl=5e3;function Ks(o){return Math.ceil(o.length/4)}function St(o,e){let t=c=>c.split(".").map(d=>parseInt(d,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var Re=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return Er.join(fn(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Gt(t)){let n=await this.getVersion(t);if(n&&St(n,Te))return this.runtime={available:!0,binaryPath:t,version:n},this.runtime;if(e.autoInstall&&process.env.CI!=="true"){console.error(`[rtk] Binary outdated (${n}, need ${Te}). Re-downloading...`);try{return await this.install({version:e.version,force:!0})}catch(r){return console.error(`[rtk] Failed to re-download: ${r instanceof Error?r.message:String(r)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}if(e.autoInstall&&process.env.CI!=="true")try{return await this.install({version:e.version})}catch(n){return console.error(`[rtk] Auto-download failed: ${n instanceof Error?n.message:String(n)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}async install(e){let t=e?.version??"latest",n=`${process.platform}-${process.arch}`,r=Pr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Pr).join(", ")}`);let s=o.binaryPath(),i=Er.dirname(s);if(!e?.force&&Gt(s)){let c=await this.getVersion(s);if(c&&St(c,Te))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${Us}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${Us}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Gt(i)||Kl(i,{recursive:!0});let l=Er.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:d}=await import("node:fs");d(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{Gt(l)&&pn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),Ws);try{let i=await fetch(e,{redirect:"follow",signal:r.signal});if(!i.ok)throw new Error(`Download failed: ${i.status} ${i.statusText}`);if(!i.body)throw new Error("Download failed: No response body");await Jl(n.fromWeb(i.body),Ul(t))}catch(i){throw pn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${Ws}ms`):i}finally{clearTimeout(s)}}async extractTarGz(e,t){let{renameSync:n}=await import("node:fs"),{mkdtemp:r}=await import("node:fs/promises"),{tmpdir:s}=await import("node:os"),{join:i}=await import("node:path");if(process.platform==="win32")throw new Error("tar.gz extraction on Windows is not supported \u2014 use .zip assets");let a=await r(i(s(),"rtk-extract-"));try{let l=Ar("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((d,p)=>{l.on("close",h=>{h===0?d():p(new Error(`tar extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{pn(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of ql(e)){let s=Er.join(e,r),i=Wl(s);if(!i.isSymbolicLink()){if(i.isFile()&&n.includes(r))return s;if(i.isDirectory()){let a=this.findBinaryInDir(s,t);if(a)return a}}}return null}async extractZip(e,t){let{renameSync:n}=await import("node:fs"),{mkdtemp:r}=await import("node:fs/promises"),{tmpdir:s}=await import("node:os"),{join:i}=await import("node:path"),a=await r(i(s(),"rtk-extract-"));try{let l=Ar("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((d,p)=>{l.on("close",h=>{h===0?d():p(new Error(`PowerShell extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{pn(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Gt(e)&&pn(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Gt(e)?{installed:!0,version:await this.getVersion(e),binaryPath:e}:{installed:!1,version:null,binaryPath:e}}async getVersion(e){return new Promise(t=>{let n=Ar(e,["--version"]),r="";n.stdout?.on("data",s=>{r+=s.toString()}),n.on("close",s=>{if(s===0){let i=r.match(/(\d+\.\d+\.\d+)/);t(i?i[1]??null:r.trim()||null)}else t(null)}),n.on("error",()=>t(null))})}async compress(e){if(!this.runtime.available)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};if(e.stdout.length<Hl)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=Ks(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=Ks(n);return{stdout:n,stderr:e.stderr,compressed:!0,originalTokens:t,compressedTokens:r}}catch{return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0}}}async runRtkSummary(e,t){return new Promise((n,r)=>{let s=t?["-u","summary"]:["summary"],i=Ar(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},zl);i.stdout?.on("data",d=>{a+=d.toString()}),i.stderr?.on("data",d=>{l+=d.toString()}),i.stdin?.end(e,"utf8"),i.on("close",d=>{clearTimeout(c),d===0?n(a):r(new Error(`rtk exited with code ${d}: ${l}`))}),i.on("error",d=>{clearTimeout(c),r(d)})})}};import{randomUUID as Vl}from"node:crypto";import uo,{WebSocketServer as Xl}from"ws";var go=class{wss=null;extension=null;config;onStatusChange;constructor(e,t){this.config=e,this.onStatusChange=t}handleUpgrade(e,t,n){if(!this.wss){t.destroy();return}let s=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`).searchParams.get("token");if(!this.config.enabled){t.write(`HTTP/1.1 503 Service Unavailable\r
310
310
  \r
311
311
  Browser relay is disabled`),t.destroy();return}if(s!==this.config.authToken){t.write(`HTTP/1.1 401 Unauthorized\r
312
312
  \r
313
- Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new Wl({noServer:!0}),e.on("upgrade",(t,n,r)=>{new URL(t.url||"/",`http://${t.headers.host||"localhost"}`).pathname==="/ws/browser-relay"&&this.handleUpgrade(t,n,r)})}handleConnection(e){this.extension&&this.extension.ws.close();let t={ws:e,attachedTabs:new Set,lastPing:Date.now(),pendingCommands:new Map};this.extension=t,this.notifyStatusChange(),e.on("message",r=>{try{let s=JSON.parse(r.toString());this.handleMessage(t,s)}catch{}}),e.on("close",()=>{if(this.extension===t){for(let[,{reject:r,timeout:s}]of t.pendingCommands)clearTimeout(s),r(new Error("Extension disconnected"));this.extension=null,this.notifyStatusChange()}});let n=setInterval(()=>{e.readyState===co.OPEN&&e.send(JSON.stringify({type:"ping"}))},2e4);e.on("close",()=>clearInterval(n))}handleMessage(e,t){if(t.type==="pong"){e.lastPing=Date.now();return}if(t.type!=="cdp_event"){if(t.id&&e.pendingCommands.has(String(t.id))){let n=e.pendingCommands.get(String(t.id));e.pendingCommands.delete(String(t.id)),clearTimeout(n.timeout),t.error?n.reject(new Error(String(t.error))):n.resolve(t.result);return}t.type==="status"&&Array.isArray(t.attachedTabs)&&(e.attachedTabs=new Set(t.attachedTabs.map(Number)),this.notifyStatusChange())}}notifyStatusChange(){this.onStatusChange&&this.onStatusChange(this.getStatus())}getStatus(){return this.extension?{connected:this.extension.ws.readyState===co.OPEN,attachedTabs:[...this.extension.attachedTabs],lastPing:this.extension.lastPing}:{connected:!1,attachedTabs:[]}}async sendCommand(e,t={},n=3e4){if(!this.extension||this.extension.ws.readyState!==co.OPEN)throw new Error("Extension not connected");let r=Gl(),s={id:r,method:e,params:t};return new Promise((i,a)=>{let l=setTimeout(()=>{this.extension?.pendingCommands.delete(r),a(new Error("Command timeout"))},n);this.extension.pendingCommands.set(r,{resolve:i,reject:a,timeout:l}),this.extension.ws.send(JSON.stringify(s))})}async listTabs(){return await this.sendCommand("tabs.list")}async navigate(e,t){await this.sendCommand("tabs.navigate",{tabId:e,url:t})}async click(e,t){await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
313
+ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new Xl({noServer:!0}),e.on("upgrade",(t,n,r)=>{new URL(t.url||"/",`http://${t.headers.host||"localhost"}`).pathname==="/ws/browser-relay"&&this.handleUpgrade(t,n,r)})}handleConnection(e){this.extension&&this.extension.ws.close();let t={ws:e,attachedTabs:new Set,lastPing:Date.now(),pendingCommands:new Map};this.extension=t,this.notifyStatusChange(),e.on("message",r=>{try{let s=JSON.parse(r.toString());this.handleMessage(t,s)}catch{}}),e.on("close",()=>{if(this.extension===t){for(let[,{reject:r,timeout:s}]of t.pendingCommands)clearTimeout(s),r(new Error("Extension disconnected"));this.extension=null,this.notifyStatusChange()}});let n=setInterval(()=>{e.readyState===uo.OPEN&&e.send(JSON.stringify({type:"ping"}))},2e4);e.on("close",()=>clearInterval(n))}handleMessage(e,t){if(t.type==="pong"){e.lastPing=Date.now();return}if(t.type!=="cdp_event"){if(t.id&&e.pendingCommands.has(String(t.id))){let n=e.pendingCommands.get(String(t.id));e.pendingCommands.delete(String(t.id)),clearTimeout(n.timeout),t.error?n.reject(new Error(String(t.error))):n.resolve(t.result);return}t.type==="status"&&Array.isArray(t.attachedTabs)&&(e.attachedTabs=new Set(t.attachedTabs.map(Number)),this.notifyStatusChange())}}notifyStatusChange(){this.onStatusChange&&this.onStatusChange(this.getStatus())}getStatus(){return this.extension?{connected:this.extension.ws.readyState===uo.OPEN,attachedTabs:[...this.extension.attachedTabs],lastPing:this.extension.lastPing}:{connected:!1,attachedTabs:[]}}async sendCommand(e,t={},n=3e4){if(!this.extension||this.extension.ws.readyState!==uo.OPEN)throw new Error("Extension not connected");let r=Vl(),s={id:r,method:e,params:t};return new Promise((i,a)=>{let l=setTimeout(()=>{this.extension?.pendingCommands.delete(r),a(new Error("Command timeout"))},n);this.extension.pendingCommands.set(r,{resolve:i,reject:a,timeout:l}),this.extension.ws.send(JSON.stringify(s))})}async listTabs(){return await this.sendCommand("tabs.list")}async navigate(e,t){await this.sendCommand("tabs.navigate",{tabId:e,url:t})}async click(e,t){await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
314
314
  const el = document.querySelector(${JSON.stringify(t)});
315
315
  if (!el) throw new Error('Element not found: ' + ${JSON.stringify(t)});
316
316
  el.scrollIntoView({ block: 'center' });
@@ -323,41 +323,41 @@ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.ha
323
323
  el.focus();
324
324
  if (el.value !== undefined) el.value = '';
325
325
  return 'focused';
326
- })()`,returnByValue:!0}}),await this.sendCommand("cdp.send",{tabId:e,method:"Input.insertText",params:{text:t}})}async screenshot(e,t="png"){let n=await this.sendCommand("tabs.screenshot",{tabId:e,format:t});return n?.dataUrl??String(n)}async evaluate(e,t){let n=await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:t,returnByValue:!0}}),r=n?.result;return r?.type==="string"||r?.type==="number"||r?.type==="boolean"||r?.value!==void 0?r.value:n}async attachTab(e){await this.sendCommand("debugger.attach",{tabId:e}),this.extension?.attachedTabs.add(e),this.notifyStatusChange()}async detachTab(e){await this.sendCommand("debugger.detach",{tabId:e}),this.extension?.attachedTabs.delete(e),this.notifyStatusChange()}close(){this.extension&&(this.extension.ws.close(),this.extension=null),this.wss&&(this.wss.close(),this.wss=null)}};function Gs(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new uo(t,e)}oo();function Kl(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function Jl(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Pr=class{name="RuleBasedToolGuardian";compiledRules=[];constructor(e=[]){this.setRules(e)}setRules(e){this.compiledRules=e.filter(t=>t.enabled).map(t=>{let n;try{n=new RegExp(t.paramPattern)}catch{return null}return{rule:t,toolNameRegex:Kl(t.toolName),paramRegex:n}}).filter(t=>t!==null)}getRules(){return this.compiledRules.map(e=>e.rule)}guard(e){let t=[],{toolName:n,params:r}=e,s=Jl(r);for(let i of this.compiledRules){if(!i.toolNameRegex.test(n))continue;let a=i.paramRegex.exec(s);a&&t.push({id:`rule-${i.rule.id}-${Date.now()}-${t.length}`,ruleId:i.rule.id,category:i.rule.category,severity:i.rule.severity.toUpperCase(),title:i.rule.description,description:i.rule.description,toolName:n,matchedValue:a[0],matchedPattern:i.rule.paramPattern,remediation:i.rule.action==="deny"?"This action is blocked by security policy.":"This pattern has been flagged for review.",guardian:this.name})}return t}matchRules(e,t){return this.guard({toolName:e,params:t})}};un();import ql from"node:path";import Hl from"node:os";var Ws=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],Ks=["command","cmd"],zl=[{pattern:/(?:^|[/"'`\s])\.ssh[/"'`\s]/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"SSH directory access detected",description:"Access to ~/.ssh/ directory detected. This contains private keys and SSH configuration.",remediation:"Avoid accessing SSH keys and configuration files directly."},{pattern:/(?:^|[/"'`\s])\.aws[/"'`\s]/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"AWS credentials directory access detected",description:"Access to ~/.aws/ directory detected. This contains AWS credentials and configuration.",remediation:"Avoid accessing AWS credential files directly."},{pattern:/(?:^|[/"'`\s])\.gnupg[/"'`\s]/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"GPG directory access detected",description:"Access to ~/.gnupg/ directory detected. This contains PGP private keys.",remediation:"Avoid accessing GPG key material directly."},{pattern:/(?:^|[/"'`\s])\.env(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"Environment file access detected",description:"Access to .env file detected. This may contain secrets and API keys.",remediation:"Avoid accessing environment files that may contain secrets."},{pattern:/(?:^|[/"'`\s])\.npmrc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"NPM configuration access detected",description:"Access to .npmrc file detected. This may contain auth tokens.",remediation:"Avoid accessing npm configuration files that may contain tokens."},{pattern:/(?:^|[/"'`\s])\.netrc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"Netrc file access detected",description:"Access to .netrc file detected. This contains authentication credentials.",remediation:"Avoid accessing netrc configuration that may contain credentials."},{pattern:/(?:^|[/"'`\s])\.pypirc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"PyPI configuration access detected",description:"Access to .pypirc file detected. This may contain PyPI tokens.",remediation:"Avoid accessing PyPI configuration files."},{pattern:/(?:\/etc\/(?:passwd|shadow|sudoers|crontab|hosts|ssh))/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"System configuration file access detected",description:"Access to sensitive system configuration files detected.",remediation:"Avoid accessing system configuration files directly."},{pattern:/(?:\/proc\/(?:self|\d+)\/(?:mem|maps|status|environ|cmdline|fd))/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"Process information access detected",description:"Access to sensitive /proc filesystem entries detected.",remediation:"Avoid accessing process memory and information files."}],Js=Hl.homedir();function Vl(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,Js),e=e.replace(/\$HOME(?=[/\\])/,Js),e}function Xl(o,e){let t=[];for(let n of Ws){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}if(/^(?:exec|shell|run_command|execute)$/i.test(e))for(let n of Ks){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!Ws.includes(n)&&!Ks.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var Ir=class{name="FilePathToolGuardian";workspace;constructor(e){this.workspace=e||process.cwd()}setWorkspace(e){this.workspace=e}guard(e){let t=[],{toolName:n,params:r}=e;if(!r||typeof r!="object"||Array.isArray(r))return t;let s=Xl(r,n);for(let i of s){let a=Vl(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let u=this.checkWorkspaceEscape(a,n);u&&t.push(u)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of zl)a.pattern.test(i)&&r.push({id:`sensitive-path-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:`sensitive-path-${a.title.replace(/\s+/g,"-").toLowerCase()}`,category:a.category,severity:a.severity,title:a.title,description:a.description,toolName:n,matchedValue:this.truncateForDisplay(i),matchedPattern:a.pattern.source,remediation:a.remediation,guardian:this.name});return r}checkWorkspaceEscape(e,t){if(!ql.isAbsolute(e))return null;try{je(e,this.workspace)}catch{return{id:`workspace-escape-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-workspace-escape",category:"PATH_TRAVERSAL",severity:"MEDIUM",title:"Workspace escape detected",description:`Absolute path '${this.truncateForDisplay(e)}' is outside the configured workspace '${this.workspace}'.`,toolName:t,matchedValue:this.truncateForDisplay(e),remediation:"Use paths within the configured workspace directory.",guardian:this.name}}return null}truncateForDisplay(e,t=200){return e.length<=t?e:e.slice(0,t)+"\u2026"}};un();import go from"node:fs";import qs from"node:path";var Yl=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".woff",".woff2",".ttf",".otf",".eot",".pdf",".zip",".gz",".tar",".7z",".rar",".bz2",".xz",".mp3",".mp4",".avi",".mov",".wmv",".flv",".mkv",".exe",".dll",".so",".dylib",".bin",".dat"]),Ql=8192,Zl=.01;function ec(o){let e=Math.min(o.length,Ql);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=Zl}var tt=class{analyzers;constructor(e=[]){this.analyzers=e}scanSkill(e,t,n){let r=n?.maxFileCount??1e3,s=n?.maxFileSizeBytes??5242880,i={scannedFiles:0,skippedFiles:0,symlinksSkipped:0,oversizedFiles:0},a=[],l=this.walkDirectory(e,i);for(let g of l){if(i.scannedFiles>=r){i.skippedFiles++;continue}if(Yl.has(g.ext)){i.skippedFiles++;continue}if(g.size>s){i.oversizedFiles++;continue}let h;try{h=go.readFileSync(g.absPath)}catch{i.skippedFiles++;continue}if(ec(h)){i.skippedFiles++;continue}let T=h.toString("utf8"),v={filePath:g.absPath,extension:g.ext,size:g.size,content:T};for(let d of this.analyzers){let b=d.analyze(v);a.push(...b)}i.scannedFiles++}let c=tc(a),u=!a.some(g=>g.severity==="CRITICAL"||g.severity==="HIGH");return{skillName:t,findings:a,isSafe:u,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=go.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=qs.join(e,s.name);if(s.isSymbolicLink()){t.symlinksSkipped++;continue}if(s.isDirectory()){let a=this.walkDirectory(i,t);n.push(...a);continue}if(s.isFile())try{let a=go.lstatSync(i),l=qs.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function tc(o){if(o.length===0)return"SAFE";let e={CRITICAL:5,HIGH:4,MEDIUM:3,LOW:2,INFO:1,SAFE:0},t=0;for(let n of o){let r=e[n.severity]??0;r>t&&(t=r)}for(let[n,r]of Object.entries(e))if(r===t)return n;return"SAFE"}un();le();import nc from"node:fs";var rc=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".woff",".woff2",".ttf",".otf",".eot",".pdf",".zip",".gz",".tar",".7z",".rar",".bz2",".xz",".mp3",".mp4",".avi",".mov",".wmv",".flv",".mkv",".exe",".dll",".so",".dylib",".bin",".dat"]),oc=8192,sc=.01,nt=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=ze("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=nc.readFileSync(e,"utf8"),n=JSON.parse(t);return this.signatures=n,n}catch{return this.signatures=[],[]}}compilePattern(e,t){let n=this.compiledPatterns.get(e);if(n)return n;try{let r=new RegExp(t,"gm");return this.compiledPatterns.set(e,r),r}catch{return null}}isBinaryContent(e){let t=Math.min(e.length,oc);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=sc}isSkippedExtension(e){return rc.has(e)}analyze(e){let{extension:t,content:n}=e,r=[];if(this.isSkippedExtension(t)||this.isBinaryContent(n))return r;let s=this.loadSignatures();for(let i of s){if(!i.fileTypes.includes(t))continue;let a=this.compilePattern(i.id,i.pattern);if(!a)continue;a.lastIndex=0,a.exec(n)&&r.push({id:i.id,category:dn[i.category]??"COMMAND_INJECTION",severity:cn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};async function Hs(o){let e=structuredClone(o?.config??_()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=X(e.agents.defaults.workspace);lt(n,!0);let r=e.gateway.host,s=r==="127.0.0.1"||r==="localhost"||r==="::1",i=e.gateway.dashboard?.enabled!==!1,a=e.security?.auth?.enabled===!0;if(!s&&i&&!a)throw new Error("Dashboard is exposed on a non-loopback address ("+r+`) but authentication is not configured. Either:
326
+ })()`,returnByValue:!0}}),await this.sendCommand("cdp.send",{tabId:e,method:"Input.insertText",params:{text:t}})}async screenshot(e,t="png"){let n=await this.sendCommand("tabs.screenshot",{tabId:e,format:t});return n?.dataUrl??String(n)}async evaluate(e,t){let n=await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:t,returnByValue:!0}}),r=n?.result;return r?.type==="string"||r?.type==="number"||r?.type==="boolean"||r?.value!==void 0?r.value:n}async attachTab(e){await this.sendCommand("debugger.attach",{tabId:e}),this.extension?.attachedTabs.add(e),this.notifyStatusChange()}async detachTab(e){await this.sendCommand("debugger.detach",{tabId:e}),this.extension?.attachedTabs.delete(e),this.notifyStatusChange()}close(){this.extension&&(this.extension.ws.close(),this.extension=null),this.wss&&(this.wss.close(),this.wss=null)}};function qs(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new go(t,e)}so();function Yl(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function Ql(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Ir=class{name="RuleBasedToolGuardian";compiledRules=[];constructor(e=[]){this.setRules(e)}setRules(e){this.compiledRules=e.filter(t=>t.enabled).map(t=>{let n;try{n=new RegExp(t.paramPattern)}catch{return null}return{rule:t,toolNameRegex:Yl(t.toolName),paramRegex:n}}).filter(t=>t!==null)}getRules(){return this.compiledRules.map(e=>e.rule)}guard(e){let t=[],{toolName:n,params:r}=e,s=Ql(r);for(let i of this.compiledRules){if(!i.toolNameRegex.test(n))continue;let a=i.paramRegex.exec(s);a&&t.push({id:`rule-${i.rule.id}-${Date.now()}-${t.length}`,ruleId:i.rule.id,category:i.rule.category,severity:i.rule.severity.toUpperCase(),title:i.rule.description,description:i.rule.description,toolName:n,matchedValue:a[0],matchedPattern:i.rule.paramPattern,remediation:i.rule.action==="deny"?"This action is blocked by security policy.":"This pattern has been flagged for review.",guardian:this.name})}return t}matchRules(e,t){return this.guard({toolName:e,params:t})}};un();import Zl from"node:path";import ec from"node:os";var Js=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],Hs=["command","cmd"],tc=[{pattern:/(?:^|[/"'`\s])\.ssh[/"'`\s]/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"SSH directory access detected",description:"Access to ~/.ssh/ directory detected. This contains private keys and SSH configuration.",remediation:"Avoid accessing SSH keys and configuration files directly."},{pattern:/(?:^|[/"'`\s])\.aws[/"'`\s]/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"AWS credentials directory access detected",description:"Access to ~/.aws/ directory detected. This contains AWS credentials and configuration.",remediation:"Avoid accessing AWS credential files directly."},{pattern:/(?:^|[/"'`\s])\.gnupg[/"'`\s]/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"GPG directory access detected",description:"Access to ~/.gnupg/ directory detected. This contains PGP private keys.",remediation:"Avoid accessing GPG key material directly."},{pattern:/(?:^|[/"'`\s])\.env(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"Environment file access detected",description:"Access to .env file detected. This may contain secrets and API keys.",remediation:"Avoid accessing environment files that may contain secrets."},{pattern:/(?:^|[/"'`\s])\.npmrc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"NPM configuration access detected",description:"Access to .npmrc file detected. This may contain auth tokens.",remediation:"Avoid accessing npm configuration files that may contain tokens."},{pattern:/(?:^|[/"'`\s])\.netrc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"Netrc file access detected",description:"Access to .netrc file detected. This contains authentication credentials.",remediation:"Avoid accessing netrc configuration that may contain credentials."},{pattern:/(?:^|[/"'`\s])\.pypirc(?:[."'\s]|$|\\)/,category:"CREDENTIAL_EXPOSURE",severity:"HIGH",title:"PyPI configuration access detected",description:"Access to .pypirc file detected. This may contain PyPI tokens.",remediation:"Avoid accessing PyPI configuration files."},{pattern:/(?:\/etc\/(?:passwd|shadow|sudoers|crontab|hosts|ssh))/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"System configuration file access detected",description:"Access to sensitive system configuration files detected.",remediation:"Avoid accessing system configuration files directly."},{pattern:/(?:\/proc\/(?:self|\d+)\/(?:mem|maps|status|environ|cmdline|fd))/,category:"SENSITIVE_FILE_ACCESS",severity:"HIGH",title:"Process information access detected",description:"Access to sensitive /proc filesystem entries detected.",remediation:"Avoid accessing process memory and information files."}],zs=ec.homedir();function nc(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,zs),e=e.replace(/\$HOME(?=[/\\])/,zs),e}function rc(o,e){let t=[];for(let n of Js){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}if(/^(?:exec|shell|run_command|execute)$/i.test(e))for(let n of Hs){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!Js.includes(n)&&!Hs.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var _r=class{name="FilePathToolGuardian";workspace;constructor(e){this.workspace=e||process.cwd()}setWorkspace(e){this.workspace=e}guard(e){let t=[],{toolName:n,params:r}=e;if(!r||typeof r!="object"||Array.isArray(r))return t;let s=rc(r,n);for(let i of s){let a=nc(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let d=this.checkWorkspaceEscape(a,n);d&&t.push(d)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of tc)a.pattern.test(i)&&r.push({id:`sensitive-path-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:`sensitive-path-${a.title.replace(/\s+/g,"-").toLowerCase()}`,category:a.category,severity:a.severity,title:a.title,description:a.description,toolName:n,matchedValue:this.truncateForDisplay(i),matchedPattern:a.pattern.source,remediation:a.remediation,guardian:this.name});return r}checkWorkspaceEscape(e,t){if(!Zl.isAbsolute(e))return null;try{Fe(e,this.workspace)}catch{return{id:`workspace-escape-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-workspace-escape",category:"PATH_TRAVERSAL",severity:"MEDIUM",title:"Workspace escape detected",description:`Absolute path '${this.truncateForDisplay(e)}' is outside the configured workspace '${this.workspace}'.`,toolName:t,matchedValue:this.truncateForDisplay(e),remediation:"Use paths within the configured workspace directory.",guardian:this.name}}return null}truncateForDisplay(e,t=200){return e.length<=t?e:e.slice(0,t)+"\u2026"}};un();import mo from"node:fs";import Vs from"node:path";var oc=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".woff",".woff2",".ttf",".otf",".eot",".pdf",".zip",".gz",".tar",".7z",".rar",".bz2",".xz",".mp3",".mp4",".avi",".mov",".wmv",".flv",".mkv",".exe",".dll",".so",".dylib",".bin",".dat"]),sc=8192,ic=.01;function ac(o){let e=Math.min(o.length,sc);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=ic}var tt=class{analyzers;constructor(e=[]){this.analyzers=e}scanSkill(e,t,n){let r=n?.maxFileCount??1e3,s=n?.maxFileSizeBytes??5242880,i={scannedFiles:0,skippedFiles:0,symlinksSkipped:0,oversizedFiles:0},a=[],l=this.walkDirectory(e,i);for(let p of l){if(i.scannedFiles>=r){i.skippedFiles++;continue}if(oc.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let h;try{h=mo.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(ac(h)){i.skippedFiles++;continue}let w=h.toString("utf8"),v={filePath:p.absPath,extension:p.ext,size:p.size,content:w};for(let u of this.analyzers){let b=u.analyze(v);a.push(...b)}i.scannedFiles++}let c=lc(a),d=!a.some(p=>p.severity==="CRITICAL"||p.severity==="HIGH");return{skillName:t,findings:a,isSafe:d,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=mo.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=Vs.join(e,s.name);if(s.isSymbolicLink()){t.symlinksSkipped++;continue}if(s.isDirectory()){let a=this.walkDirectory(i,t);n.push(...a);continue}if(s.isFile())try{let a=mo.lstatSync(i),l=Vs.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function lc(o){if(o.length===0)return"SAFE";let e={CRITICAL:5,HIGH:4,MEDIUM:3,LOW:2,INFO:1,SAFE:0},t=0;for(let n of o){let r=e[n.severity]??0;r>t&&(t=r)}for(let[n,r]of Object.entries(e))if(r===t)return n;return"SAFE"}un();ce();import cc from"node:fs";var dc=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".woff",".woff2",".ttf",".otf",".eot",".pdf",".zip",".gz",".tar",".7z",".rar",".bz2",".xz",".mp3",".mp4",".avi",".mov",".wmv",".flv",".mkv",".exe",".dll",".so",".dylib",".bin",".dat"]),uc=8192,gc=.01,nt=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=ze("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=cc.readFileSync(e,"utf8"),n=JSON.parse(t);return this.signatures=n,n}catch{return this.signatures=[],[]}}compilePattern(e,t){let n=this.compiledPatterns.get(e);if(n)return n;try{let r=new RegExp(t,"gm");return this.compiledPatterns.set(e,r),r}catch{return null}}isBinaryContent(e){let t=Math.min(e.length,uc);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=gc}isSkippedExtension(e){return dc.has(e)}analyze(e){let{extension:t,content:n}=e,r=[];if(this.isSkippedExtension(t)||this.isBinaryContent(n))return r;let s=this.loadSignatures();for(let i of s){if(!i.fileTypes.includes(t))continue;let a=this.compilePattern(i.id,i.pattern);if(!a)continue;a.lastIndex=0,a.exec(n)&&r.push({id:i.id,category:dn[i.category]??"COMMAND_INJECTION",severity:cn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};async function Xs(o){let e=structuredClone(o?.config??M()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=V(e.agents.defaults.workspace);lt(n,!0);let r=e.gateway.host,s=r==="127.0.0.1"||r==="localhost"||r==="::1",i=e.gateway.dashboard?.enabled!==!1,a=e.security?.auth?.enabled===!0;if(!s&&i&&!a)throw new Error("Dashboard is exposed on a non-loopback address ("+r+`) but authentication is not configured. Either:
327
327
  1. Set security.auth.enabled = true and configure a PIN
328
328
  2. Set gateway.host = 127.0.0.1 (loopback only)
329
- 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new ut,c=o?.provider??Me(e),u=new Qe(n),g=De(),h=new Bt(n,g),T=pr(e.tools.exec.timeout),v=an({target:"scheduled-job",timeoutMs:T}),d=an({target:"background-job",timeoutMs:T}),{cron:b,heartbeat:O,lifecycle:k}=Je({cron:{dataDir:g,onJob:async(I,F)=>{let q=await v.run({payload:{message:I.payload.message,session:`cron:${I.id}`,channel:I.payload.channel??"cli",chatId:I.payload.to??"direct"},cwd:process.cwd(),signal:F?.signal});if(I.payload.deliver&&I.payload.to){let re=I.payload.channel??"cli",p=I.payload.to;await l.publishOutbound({channel:re,chatId:p,content:q});try{h.record({jobId:I.id,jobName:I.name,sessionKey:`cron:${I.id}`,channel:re,recipient:p,content:q})}catch(m){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${I.id}: ${m instanceof Error?m.message:String(m)}`)}}return q}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(I,F)=>{let re=u.listSessions().find(f=>(f.key??"").includes(":"))?.key??"cli:direct",[p,m]=re.split(/:(.*)/s,2);return d.run({payload:{message:I,session:"heartbeat",channel:p||"cli",chatId:m||"direct"},cwd:process.cwd(),signal:F?.signal})},onNotify:async I=>{let q=u.listSessions().find(m=>(m.key??"").includes(":"))?.key??"",[re,p]=q?q.split(/:(.*)/s,2):["cli","direct"];re!=="cli"&&re&&await l.publishOutbound({channel:re,chatId:p??"direct",content:I})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!O)throw new Error("Builtin heartbeat job registration is missing");let G,L;e.security.enabled&&(e.security.toolGuard.enabled&&(G=gn.getInstance(e),G.registerGuardian(new Pr(G.getRules())),G.registerGuardian(new Ir(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(L=new tt([new nt]),console.log("[security] Skill scanner initialized")));let N=new Te,z=await N.resolve(e.tools.rtk);z.available?console.log(`rtk ${z.version} \u2014 token compression enabled`):e.tools.rtk.enabled&&(e.tools.rtk.autoInstall&&process.env.CI==="true"?console.log("rtk not available \u2014 auto-install skipped in CI (run `everclaw rtk install` in Dockerfile)"):e.tools.rtk.autoInstall?console.log("rtk not available \u2014 auto-install failed; token compression disabled (run `everclaw rtk install` to retry)"):console.log("rtk not available \u2014 token compression disabled (run `everclaw rtk install` to enable)"));let B=null;if(e.tools.browserRelay.enabled&&e.tools.browserRelay.authToken){let I=Gs(e,F=>{F.connected&&console.log(`[browser-relay] Extension connected, ${F.attachedTabs.length} tabs attached`)});I&&(B=I,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let ae=new Nt({bus:l,provider:c,workspace:n,sessionManager:u,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:k,loadConfig:_,rtkConfig:e.tools.rtk,rtkService:N,...G?{guardEngine:G}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...L?{skillScanner:L}:{},...B?{browserRelay:B}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),J=new yr(e,l,k),Z=js({agent:ae,cron:b,config:e,dataDir:g,port:t,sessionManager:u,sessionKey:o?.sessionKey??"default:everclaw",inboxService:h,workspacePath:n,channelManager:J,...B?{browserRelay:B}:{}});await b.start(),await O.start();let A=ae.run();return await J.startAll(),{config:e,workspace:n,port:Z.port,loop:ae,heartbeat:O,cron:b,channels:J,dashboard:Z,enabledChannels:J.enabledChannels,runPromise:A,browserRelay:B}}async function mo(o){o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Mt.getInstance().stopAll(),await o.dashboard.close(),e}import U from"chalk";import{Command as ic}from"commander";Ne();var K={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function zs(){let o=new ic("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
329
+ 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new gt,c=o?.provider??$e(e),d=new Qe(n),p=Ne(),h=new Bt(n,p),w=fr(e.tools.exec.timeout),v=an({target:"scheduled-job",timeoutMs:w}),u=an({target:"background-job",timeoutMs:w}),{cron:b,heartbeat:P,lifecycle:C}=qe({cron:{dataDir:p,onJob:async(T,j)=>{let D=await v.run({payload:{message:T.payload.message,session:`cron:${T.id}`,channel:T.payload.channel??"cli",chatId:T.payload.to??"direct"},cwd:process.cwd(),signal:j?.signal});if(T.payload.deliver&&T.payload.to){let ee=T.payload.channel??"cli",m=T.payload.to;await l.publishOutbound({channel:ee,chatId:m,content:D});try{h.record({jobId:T.id,jobName:T.name,sessionKey:`cron:${T.id}`,channel:ee,recipient:m,content:D})}catch(g){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${T.id}: ${g instanceof Error?g.message:String(g)}`)}}return D}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(T,j)=>{let ee=d.listSessions().find(f=>(f.key??"").includes(":"))?.key??"cli:direct",[m,g]=ee.split(/:(.*)/s,2);return u.run({payload:{message:T,session:"heartbeat",channel:m||"cli",chatId:g||"direct"},cwd:process.cwd(),signal:j?.signal})},onNotify:async T=>{let D=d.listSessions().find(g=>(g.key??"").includes(":"))?.key??"",[ee,m]=D?D.split(/:(.*)/s,2):["cli","direct"];ee!=="cli"&&ee&&await l.publishOutbound({channel:ee,chatId:m??"direct",content:T})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!P)throw new Error("Builtin heartbeat job registration is missing");let N,q;e.security.enabled&&(e.security.toolGuard.enabled&&(N=gn.getInstance(e),N.registerGuardian(new Ir(N.getRules())),N.registerGuardian(new _r(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(q=new tt([new nt]),console.log("[security] Skill scanner initialized")));let I=new Re,J=await I.resolve(e.tools.rtk);J.available?console.log(`rtk ${J.version} \u2014 token compression enabled`):e.tools.rtk.enabled&&(e.tools.rtk.autoInstall&&process.env.CI==="true"?console.log("rtk not available \u2014 auto-install skipped in CI (run `everclaw rtk install` in Dockerfile)"):e.tools.rtk.autoInstall?console.log("rtk not available \u2014 auto-install failed; token compression disabled (run `everclaw rtk install` to retry)"):console.log("rtk not available \u2014 token compression disabled (run `everclaw rtk install` to enable)"));let Q=null;if(e.tools.browserRelay.enabled&&e.tools.browserRelay.authToken){let T=qs(e,j=>{j.connected&&console.log(`[browser-relay] Extension connected, ${j.attachedTabs.length} tabs attached`)});T&&(Q=T,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let z=new Nt({bus:l,provider:c,workspace:n,sessionManager:d,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:C,loadConfig:M,rtkConfig:e.tools.rtk,rtkService:I,...N?{guardEngine:N}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...q?{skillScanner:q}:{},...Q?{browserRelay:Q}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),W=new br(e,l,C),X=Gs({agent:z,cron:b,config:e,dataDir:p,port:t,sessionManager:d,sessionKey:o?.sessionKey??"default:everclaw",inboxService:h,workspacePath:n,channelManager:W,...Q?{browserRelay:Q}:{}});await b.start(),await P.start();let ae=z.run();return await W.startAll(),{config:e,workspace:n,port:X.port,loop:z,heartbeat:P,cron:b,channels:W,dashboard:X,enabledChannels:W.enabledChannels,runPromise:ae,browserRelay:Q}}async function po(o){o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Mt.getInstance().stopAll(),await o.dashboard.close(),e}import B from"chalk";import{Command as mc}from"commander";je();var U={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function Ys(){let o=new mc("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
330
330
  Examples:
331
331
  everclaw rtk install Install the latest rtk binary
332
332
  everclaw rtk update Update to the latest version
333
- everclaw rtk enable Enable token compression in config`),o.command("install").description("Download and install rtk binary").option("-v, --version <version>","Version to install (default: latest)","latest").option("-f, --force","Force reinstall even if already installed",!1).action(async e=>{let t=new Te;try{let n=await t.install({version:e.version,force:e.force});console.log(U.green(`
334
- rtk v${n.version} installed to ${n.binaryPath}`)),console.log(U.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(U.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=K.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Te,t=await e.getStatus();if(!t.installed){console.log(U.yellow("rtk is not installed."));return}await e.uninstall(),console.log(U.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new Te().getStatus(),n=_();console.log(U.cyan(`
333
+ everclaw rtk enable Enable token compression in config`),o.command("install").description("Download and install rtk binary").option("-v, --version <version>","Version to install (default: latest)","latest").option("-f, --force","Force reinstall even if already installed",!1).action(async e=>{let t=new Re;try{let n=await t.install({version:e.version,force:e.force});console.log(B.green(`
334
+ rtk v${n.version} installed to ${n.binaryPath}`)),console.log(B.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(B.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=U.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Re,t=await e.getStatus();if(!t.installed){console.log(B.yellow("rtk is not installed."));return}await e.uninstall(),console.log(B.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new Re().getStatus(),n=M();console.log(B.cyan(`
335
335
  RTK Token Compression
336
- `)),t.installed&&t.version?(console.log(` Status: ${U.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),wt(t.version,Ce)||(console.log(U.yellow(` Warning: Version ${t.version} is below minimum ${Ce}`)),console.log(U.gray(` Run ${U.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${U.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(U.gray(` Run ${U.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${U.gray("Not installed")}`),console.log(U.gray(` Fix: Run ${U.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?U.green("yes"):U.gray("no")}`),console.log(U.gray(`
337
- Minimum version: ${Ce}`)),console.log(U.gray(` Supported platforms: ${Object.keys(Er).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Te,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?U.cyan(`Current: v${n}`):U.gray("rtk is not installed."));try{console.log(U.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(U.green(`Already at latest version (v${r.version})`)):console.log(U.green(`
338
- rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(U.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=K.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=_();if(e.tools.rtk.enabled){console.log(U.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(U.green("RTK token compression enabled.")),console.log(U.gray("Restart the gateway for changes to take effect."))}),o.command("disable").description("Disable rtk token compression in config").action(()=>{let e=_();if(!e.tools.rtk.enabled){console.log(U.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(U.yellow("RTK token compression disabled.")),console.log(U.gray("Restart the gateway for changes to take effect.")),console.log(U.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}Tt();Ne();import{spawn as ac}from"node:child_process";import lc from"node:fs";import cc from"node:path";import j from"chalk";import{Command as dc,Option as uc}from"commander";function gc(){let o=process.argv[1];if(o){let e=cc.resolve(o);if(lc.existsSync(e))return e}return"everclaw"}async function mc(){let o=Ee();if(!o)return!0;if(!Ae(o.pid))return Pe(),!0;console.log(j.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(j.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await Br(o.pid,1e4)){console.log(j.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return Pe(),console.log(j.green("Gateway stopped.")),!0}async function Vs(o){let e=Ee();if(e&&Ae(e.pid)){console.error(j.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(j.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=K.PROCESS_CONFLICT;return}e&&Pe();let t=_(),n=fo(o.port,t.gateway.port),r=gc(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i="",a=ac(r,s,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env}});if(!a.pid){console.error(j.red("Failed to spawn gateway process.")),process.exitCode=K.GENERAL_ERROR;return}if(a.stderr?.on("data",l=>{i+=l.toString("utf8"),i.length>4096&&(i=i.slice(-4096))}),setTimeout(()=>{a.stderr?.destroy()},3e3).unref(),a.unref(),Fr({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!Ae(a.pid)){Pe(),console.error(j.red("Gateway process exited immediately.")),i.trim()?console.error(j.gray(i.trim().split(`
336
+ `)),t.installed&&t.version?(console.log(` Status: ${B.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),St(t.version,Te)||(console.log(B.yellow(` Warning: Version ${t.version} is below minimum ${Te}`)),console.log(B.gray(` Run ${B.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${B.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(B.gray(` Run ${B.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${B.gray("Not installed")}`),console.log(B.gray(` Fix: Run ${B.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?B.green("yes"):B.gray("no")}`),console.log(B.gray(`
337
+ Minimum version: ${Te}`)),console.log(B.gray(` Supported platforms: ${Object.keys(Pr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Re,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?B.cyan(`Current: v${n}`):B.gray("rtk is not installed."));try{console.log(B.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(B.green(`Already at latest version (v${r.version})`)):console.log(B.green(`
338
+ rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(B.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=U.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=M();if(e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(B.green("RTK token compression enabled.")),console.log(B.gray("Restart the gateway for changes to take effect."))}),o.command("disable").description("Disable rtk token compression in config").action(()=>{let e=M();if(!e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(B.yellow("RTK token compression disabled.")),console.log(B.gray("Restart the gateway for changes to take effect.")),console.log(B.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}Rt();je();import{spawn as pc}from"node:child_process";import fc from"node:fs";import hc from"node:path";import F from"chalk";import{Command as yc,Option as bc}from"commander";function vc(){let o=process.argv[1];if(o){let e=hc.resolve(o);if(fc.existsSync(e))return e}return"everclaw"}async function wc(){let o=Pe();if(!o)return!0;if(!Ee(o.pid))return Ie(),!0;console.log(F.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(F.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await Gr(o.pid,1e4)){console.log(F.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return Ie(),console.log(F.green("Gateway stopped.")),!0}async function Qs(o){let e=Pe();if(e&&Ee(e.pid)){console.error(F.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(F.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=U.PROCESS_CONFLICT;return}e&&Ie();let t=M(),n=ho(o.port,t.gateway.port),r=vc(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i="",a=pc(r,s,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env}});if(!a.pid){console.error(F.red("Failed to spawn gateway process.")),process.exitCode=U.GENERAL_ERROR;return}if(a.stderr?.on("data",l=>{i+=l.toString("utf8"),i.length>4096&&(i=i.slice(-4096))}),setTimeout(()=>{a.stderr?.destroy()},3e3).unref(),a.unref(),Br({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!Ee(a.pid)){Ie(),console.error(F.red("Gateway process exited immediately.")),i.trim()?console.error(F.gray(i.trim().split(`
339
339
  `).map(l=>` ${l}`).join(`
340
- `))):console.error(j.gray("No error output captured. Try running with -f for details.")),process.exitCode=K.GENERAL_ERROR;return}console.log(j.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(j.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(j.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function po(o){let e=_(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=fo(o.port,e.gateway.port));let n=Kt(e,process.env,t),r=n.gateway.port,s=Ee();if(s&&s.pid!==process.pid&&Ae(s.pid)){console.error(j.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(j.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=K.PROCESS_CONFLICT;return}s&&s.pid!==process.pid&&Pe();let i;try{i=await Hs({config:n,port:r,sessionKey:"default:everclaw"})}catch(g){console.log(j.red(String(g))),process.exitCode=K.GENERAL_ERROR;return}Fr({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(j.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(j.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(j.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(j.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(j.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async g=>a||(console.log(j.yellow(`
341
- Received ${g}. Shutting down gateway...`)),Pe(process.pid),a=mo(i).then(h=>{h>0&&console.log(j.gray(`Cancelled ${h} task(s) during shutdown.`))}).catch(h=>{process.exitCode=1,console.log(j.red(`Gateway shutdown failed: ${String(h)}`))}),a),c=()=>{l("SIGINT")},u=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",u);try{await i.runPromise,a&&await a}finally{Pe(process.pid),process.off("SIGINT",c),process.off("SIGTERM",u)}}function Xs(){let o=new dc("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
340
+ `))):console.error(F.gray("No error output captured. Try running with -f for details.")),process.exitCode=U.GENERAL_ERROR;return}console.log(F.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(F.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(F.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function fo(o){let e=M(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=ho(o.port,e.gateway.port));let n=Kt(e,process.env,t),r=n.gateway.port,s=Pe();if(s&&s.pid!==process.pid&&Ee(s.pid)){console.error(F.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(F.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=U.PROCESS_CONFLICT;return}s&&s.pid!==process.pid&&Ie();let i;try{i=await Xs({config:n,port:r,sessionKey:"default:everclaw"})}catch(p){console.log(F.red(String(p))),process.exitCode=U.GENERAL_ERROR;return}Br({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(F.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(F.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(F.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(F.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(F.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async p=>a||(console.log(F.yellow(`
341
+ Received ${p}. Shutting down gateway...`)),Ie(process.pid),a=po(i).then(h=>{h>0&&console.log(F.gray(`Cancelled ${h} task(s) during shutdown.`))}).catch(h=>{process.exitCode=1,console.log(F.red(`Gateway shutdown failed: ${String(h)}`))}),a),c=()=>{l("SIGINT")},d=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",d);try{await i.runPromise,a&&await a}finally{Ie(process.pid),process.off("SIGINT",c),process.off("SIGTERM",d)}}function Zs(){let o=new yc("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
342
342
  Examples:
343
343
  everclaw gateway Start the gateway in background (default)
344
344
  everclaw gateway start -f Start in foreground
345
345
  everclaw gateway status Check if gateway is running
346
346
  everclaw gateway restart Restart the gateway
347
- everclaw gateway stop Stop a running gateway`),o.command("start",{isDefault:!0}).description("Start the everclaw gateway in background (default when no subcommand given)").option("-p, --port <port>","Gateway port",String(fe.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new uc("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await po({port:e.port,host:e.host});return}if(e.foreground){await po({port:e.port,host:e.host});return}await Vs({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Ee();if(!e){console.log(j.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=K.GENERAL_ERROR;return}if(!Ae(e.pid)){console.log(j.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),Pe();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(j.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=K.GENERAL_ERROR;return}if(await Br(e.pid,1e4))Pe(),console.log(j.green("Gateway stopped."));else{console.log(j.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}Pe(),console.log(j.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(fe.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").option("--force","Start even if stop fails",!1).action(async e=>{if(!await mc()){if(!e.force){console.error(j.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=K.GENERAL_ERROR;return}console.log(j.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(j.cyan("Starting gateway...")),e.foreground?await po({port:e.port,host:e.host}):await Vs({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Ee();if(!e){console.log(j.yellow("Gateway is not running (no PID file found)."));return}if(!Ae(e.pid)){console.log(j.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=dt(e.startedAt);console.log(j.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`),console.log(` Started: ${e.startedAt}`)}),o}import H from"chalk";import{Command as pc}from"commander";import rt from"node:fs";import ot from"node:path";Ne();Oe();function Ys(){let o=new pc("skills").description("Manage skills");return o.addHelpText("after",`
347
+ everclaw gateway stop Stop a running gateway`),o.command("start",{isDefault:!0}).description("Start the everclaw gateway in background (default when no subcommand given)").option("-p, --port <port>","Gateway port",String(de.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new bc("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await fo({port:e.port,host:e.host});return}if(e.foreground){await fo({port:e.port,host:e.host});return}await Qs({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Pe();if(!e){console.log(F.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=U.GENERAL_ERROR;return}if(!Ee(e.pid)){console.log(F.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),Ie();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(F.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=U.GENERAL_ERROR;return}if(await Gr(e.pid,1e4))Ie(),console.log(F.green("Gateway stopped."));else{console.log(F.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}Ie(),console.log(F.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(de.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").option("--force","Start even if stop fails",!1).action(async e=>{if(!await wc()){if(!e.force){console.error(F.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=U.GENERAL_ERROR;return}console.log(F.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(F.cyan("Starting gateway...")),e.foreground?await fo({port:e.port,host:e.host}):await Qs({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Pe();if(!e){console.log(F.yellow("Gateway is not running (no PID file found)."));return}if(!Ee(e.pid)){console.log(F.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=ut(e.startedAt);console.log(F.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`),console.log(` Started: ${e.startedAt}`)}),o}import K from"chalk";import{Command as Sc}from"commander";import rt from"node:fs";import ot from"node:path";je();Le();function ei(){let o=new Sc("skills").description("Manage skills");return o.addHelpText("after",`
348
348
  Examples:
349
349
  everclaw skills list List all available skills
350
350
  everclaw skills show browser Show details for a skill
351
351
  everclaw skills create my-skill Create a new skill in workspace
352
- everclaw skills scan Run security scan on all skills`),o.command("list").description("List all available skills").option("-a, --all","Include unavailable and blocked skills",!1).action(e=>{let t=_(),n=X(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new tt([new nt]):null,a=new Ge(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(H.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(H.gray("No available skills. Use --all to see all skills."));return}console.log(H.cyan(`
352
+ everclaw skills scan Run security scan on all skills`),o.command("list").description("List all available skills").option("-a, --all","Include unavailable and blocked skills",!1).action(e=>{let t=M(),n=V(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new tt([new nt]):null,a=new Ue(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(K.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(K.gray("No available skills. Use --all to see all skills."));return}console.log(K.cyan(`
353
353
  Skills
354
- `)),console.log("Name".padEnd(28)+"Source".padEnd(12)+"Status".padEnd(12)+"Description"),console.log("-".repeat(80));for(let c of l){let u=c.status==="available"?H.green("available"):c.status==="blocked"?H.red("blocked"):H.yellow(c.status),g=c.description?.slice(0,40)??"";console.log(c.name.padEnd(28)+c.source.padEnd(12)+u.padEnd(20)+g)}console.log("")}),o.command("show <name>").description("Show skill details").action(e=>{let t=_(),n=X(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new tt([new nt]):null,l=new Ge(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(H.red(`Skill '${e}' not found.`)),console.log(H.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=K.GENERAL_ERROR;return}console.log(H.cyan(`
354
+ `)),console.log("Name".padEnd(28)+"Source".padEnd(12)+"Status".padEnd(12)+"Description"),console.log("-".repeat(80));for(let c of l){let d=c.status==="available"?K.green("available"):c.status==="blocked"?K.red("blocked"):K.yellow(c.status),p=c.description?.slice(0,40)??"";console.log(c.name.padEnd(28)+c.source.padEnd(12)+d.padEnd(20)+p)}console.log("")}),o.command("show <name>").description("Show skill details").action(e=>{let t=M(),n=V(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new tt([new nt]):null,l=new Ue(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(K.red(`Skill '${e}' not found.`)),console.log(K.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=U.GENERAL_ERROR;return}console.log(K.cyan(`
355
355
  Skill: ${l.name}
356
- `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?H.green("available"):H.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
356
+ `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?K.green("available"):K.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
357
357
  Description: ${l.description}
358
- `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=_(),n=X(t.agents.defaults.workspace),r=ot.join(n,"skills"),s=ot.join(r,e);if(!rt.existsSync(s)){console.log(H.red(`Skill '${e}' not found in workspace skills.`)),console.log(H.gray("Only workspace-scoped skills can be removed.")),process.exitCode=K.GENERAL_ERROR;return}rt.rmSync(s,{recursive:!0,force:!0}),console.log(H.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=_(),n=X(t.agents.defaults.workspace),r=ot.join(n,"skills");if(!rt.existsSync(r)){console.log(H.gray("No workspace skills directory found."));return}let s=new tt([new nt]),i=e?[e]:rt.readdirSync(r).filter(a=>rt.statSync(ot.join(r,a)).isDirectory());if(i.length===0){console.log(H.gray("No skills to scan."));return}console.log(H.cyan(`
358
+ `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=M(),n=V(t.agents.defaults.workspace),r=ot.join(n,"skills"),s=ot.join(r,e);if(!rt.existsSync(s)){console.log(K.red(`Skill '${e}' not found in workspace skills.`)),console.log(K.gray("Only workspace-scoped skills can be removed.")),process.exitCode=U.GENERAL_ERROR;return}rt.rmSync(s,{recursive:!0,force:!0}),console.log(K.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=M(),n=V(t.agents.defaults.workspace),r=ot.join(n,"skills");if(!rt.existsSync(r)){console.log(K.gray("No workspace skills directory found."));return}let s=new tt([new nt]),i=e?[e]:rt.readdirSync(r).filter(a=>rt.statSync(ot.join(r,a)).isDirectory());if(i.length===0){console.log(K.gray("No skills to scan."));return}console.log(K.cyan(`
359
359
  Skill Security Scan
360
- `));for(let a of i){let l=ot.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${H.green("passed")}`);else{console.log(`${a.padEnd(28)} ${H.red("blocked")}`);for(let u of c.findings)console.log(H.gray(` - ${u.severity}: ${u.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=_(),n=X(t.agents.defaults.workspace),r=ot.join(n,"skills"),s=ot.join(r,e);if(rt.existsSync(s)){console.log(H.red(`Skill '${e}' already exists.`)),process.exitCode=K.GENERAL_ERROR;return}rt.mkdirSync(s,{recursive:!0});let i=`---
360
+ `));for(let a of i){let l=ot.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${K.green("passed")}`);else{console.log(`${a.padEnd(28)} ${K.red("blocked")}`);for(let d of c.findings)console.log(K.gray(` - ${d.severity}: ${d.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=M(),n=V(t.agents.defaults.workspace),r=ot.join(n,"skills"),s=ot.join(r,e);if(rt.existsSync(s)){console.log(K.red(`Skill '${e}' already exists.`)),process.exitCode=U.GENERAL_ERROR;return}rt.mkdirSync(s,{recursive:!0});let i=`---
361
361
  name: ${e}
362
362
  description: A custom skill
363
363
  always_on: false
@@ -366,22 +366,22 @@ always_on: false
366
366
  # ${e}
367
367
 
368
368
  TODO: Add skill instructions here.
369
- `;rt.writeFileSync(ot.join(s,"SKILL.md"),i),console.log(H.green(`Created skill '${e}' at ${s}/SKILL.md`))}),o.command("install <slug>").description("Install a skill from ClawHub into the workspace").action(async e=>{if(!Rn(e)){console.log(H.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=K.GENERAL_ERROR;return}let t=_(),n=X(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(pt(),Ho)),s=new r,i="clawhub@latest",a=12e4;console.log(H.cyan(`Installing skill '${e}'...`));try{let l=await s.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",i,"install",e,"--workdir",n]},cwd:n,env:{...process.env},timeoutMs:a,maxCaptureBytes:1048576});if(l.status!=="ok"){let u=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
370
- `),g=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(H.red(`Failed to install skill '${e}'${g}: ${u||"unknown error"}`)),process.exitCode=K.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
371
- `);console.log(H.green(`Skill '${e}' installed successfully.`)),c&&console.log(H.gray(c)),console.log(H.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(H.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=K.CONNECTIVITY_ERROR}}),o}Ne();import ee from"chalk";import{Command as fc}from"commander";function hc(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function Qs(){let o=new fc("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
369
+ `;rt.writeFileSync(ot.join(s,"SKILL.md"),i),console.log(K.green(`Created skill '${e}' at ${s}/SKILL.md`))}),o.command("install <slug>").description("Install a skill from ClawHub into the workspace").action(async e=>{if(!An(e)){console.log(K.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=U.GENERAL_ERROR;return}let t=M(),n=V(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(ft(),Xo)),s=new r,i="clawhub@latest",a=12e4;console.log(K.cyan(`Installing skill '${e}'...`));try{let l=await s.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",i,"install",e,"--workdir",n]},cwd:n,env:{...process.env},timeoutMs:a,maxCaptureBytes:1048576});if(l.status!=="ok"){let d=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
370
+ `),p=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(K.red(`Failed to install skill '${e}'${p}: ${d||"unknown error"}`)),process.exitCode=U.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
371
+ `);console.log(K.green(`Skill '${e}' installed successfully.`)),c&&console.log(K.gray(c)),console.log(K.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(K.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=U.CONNECTIVITY_ERROR}}),o}je();import te from"chalk";import{Command as kc}from"commander";function Cc(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function ti(){let o=new kc("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
372
372
  Examples:
373
373
  everclaw mcp list List configured servers
374
374
  everclaw mcp add fs --command npx --args "-y @anthropic/mcp-server-filesystem /path"
375
375
  everclaw mcp test fs Test connectivity
376
- everclaw mcp tools fs List tools from a server`),o.command("list").description("List configured MCP servers").action(()=>{let t=_().tools.mcpServers,n=Object.keys(t);if(n.length===0){console.log(ee.gray("No MCP servers configured.")),console.log(ee.gray(`Run ${ee.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(ee.cyan(`
376
+ everclaw mcp tools fs List tools from a server`),o.command("list").description("List configured MCP servers").action(()=>{let t=M().tools.mcpServers,n=Object.keys(t);if(n.length===0){console.log(te.gray("No MCP servers configured.")),console.log(te.gray(`Run ${te.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(te.cyan(`
377
377
  MCP Servers
378
- `)),console.log("Name".padEnd(20)+"Transport".padEnd(10)+"Endpoint".padEnd(45)+"Timeout");for(let r of n){let s=t[r],i=s?.url?"http":"stdio",a=s?.url??(s?.command?`${s.command} ${(s.args??[]).join(" ")}`:""),l=s?.toolTimeout?`${s.toolTimeout}s`:"default";console.log(r.padEnd(20)+i.padEnd(10)+hc(a,45).padEnd(45)+l)}console.log("")}),o.command("add <name>").description("Add a new MCP server").option("--command <command>","Command to run (stdio transport)").option("--args <args...>","Arguments for the command").option("--url <url>","HTTP/SSE endpoint URL").option("--timeout <seconds>","Tool timeout in seconds").action((e,t)=>{if(!t.command&&!t.url){console.log(ee.red("Error: Either --command or --url is required.")),process.exitCode=K.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(ee.red("Error: --timeout must be a positive integer.")),process.exitCode=K.GENERAL_ERROR;return}n=i}let r=_(),s=r.tools.mcpServers;if(s[e]){console.log(ee.yellow(`MCP server '${e}' already exists.`)),process.exitCode=K.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(ee.green(`Added MCP server '${e}'.`)),console.log(ee.gray("Restart the gateway for changes to take effect."))}),o.command("remove <name>").description("Remove an MCP server from config").action(e=>{let t=_(),n=t.tools.mcpServers;if(!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=K.GENERAL_ERROR;return}delete n[e],oe(t),console.log(ee.green(`Removed MCP server '${e}'.`))}),o.command("show <name>").description("Show MCP server details").action(e=>{let r=_().tools.mcpServers[e];if(!r){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(ee.cyan(`
378
+ `)),console.log("Name".padEnd(20)+"Transport".padEnd(10)+"Endpoint".padEnd(45)+"Timeout");for(let r of n){let s=t[r],i=s?.url?"http":"stdio",a=s?.url??(s?.command?`${s.command} ${(s.args??[]).join(" ")}`:""),l=s?.toolTimeout?`${s.toolTimeout}s`:"default";console.log(r.padEnd(20)+i.padEnd(10)+Cc(a,45).padEnd(45)+l)}console.log("")}),o.command("add <name>").description("Add a new MCP server").option("--command <command>","Command to run (stdio transport)").option("--args <args...>","Arguments for the command").option("--url <url>","HTTP/SSE endpoint URL").option("--timeout <seconds>","Tool timeout in seconds").action((e,t)=>{if(!t.command&&!t.url){console.log(te.red("Error: Either --command or --url is required.")),process.exitCode=U.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(te.red("Error: --timeout must be a positive integer.")),process.exitCode=U.GENERAL_ERROR;return}n=i}let r=M(),s=r.tools.mcpServers;if(s[e]){console.log(te.yellow(`MCP server '${e}' already exists.`)),process.exitCode=U.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(te.green(`Added MCP server '${e}'.`)),console.log(te.gray("Restart the gateway for changes to take effect."))}),o.command("remove <name>").description("Remove an MCP server from config").action(e=>{let t=M(),n=t.tools.mcpServers;if(!n[e]){console.log(te.red(`MCP server '${e}' not found.`)),process.exitCode=U.GENERAL_ERROR;return}delete n[e],oe(t),console.log(te.green(`Removed MCP server '${e}'.`))}),o.command("show <name>").description("Show MCP server details").action(e=>{let r=M().tools.mcpServers[e];if(!r){console.log(te.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(te.cyan(`
379
379
  MCP Server: ${e}
380
- `)),console.log(` Transport: ${r.url?"HTTP/SSE":"stdio"}`),r.url?console.log(` URL: ${r.url}`):r.command&&(console.log(` Command: ${r.command}`),r.args?.length&&console.log(` Args: ${r.args.join(" ")}`)),r.toolTimeout&&console.log(` Timeout: ${r.toolTimeout}s`),r.env&&Object.keys(r.env).length>0&&console.log(` Env vars: ${Object.keys(r.env).join(", ")}`),console.log("")}),o.command("test [name]").description("Test connectivity to one or all MCP servers").action(async e=>{let n=_().tools.mcpServers,r=e?[e]:Object.keys(n);if(r.length===0){console.log(ee.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(ee.cyan(`
380
+ `)),console.log(` Transport: ${r.url?"HTTP/SSE":"stdio"}`),r.url?console.log(` URL: ${r.url}`):r.command&&(console.log(` Command: ${r.command}`),r.args?.length&&console.log(` Args: ${r.args.join(" ")}`)),r.toolTimeout&&console.log(` Timeout: ${r.toolTimeout}s`),r.env&&Object.keys(r.env).length>0&&console.log(` Env vars: ${Object.keys(r.env).join(", ")}`),console.log("")}),o.command("test [name]").description("Test connectivity to one or all MCP servers").action(async e=>{let n=M().tools.mcpServers,r=e?[e]:Object.keys(n);if(r.length===0){console.log(te.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(te.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(te.cyan(`
381
381
  MCP Connectivity Test
382
- `));let{McpClientManager:s}=await Promise.resolve().then(()=>(sn(),gr)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${ee.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${ee.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=K.CONNECTIVITY_ERROR}await i.closeAll(),console.log("")}),o.command("tools <name>").description("List tools exposed by an MCP server").action(async e=>{let n=_().tools.mcpServers;if(!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=K.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(sn(),gr)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(ee.gray(`No tools exposed by '${e}'.`));else{console.log(ee.cyan(`
382
+ `));let{McpClientManager:s}=await Promise.resolve().then(()=>(sn(),mr)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${te.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${te.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=U.CONNECTIVITY_ERROR}await i.closeAll(),console.log("")}),o.command("tools <name>").description("List tools exposed by an MCP server").action(async e=>{let n=M().tools.mcpServers;if(!n[e]){console.log(te.red(`MCP server '${e}' not found.`)),process.exitCode=U.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(sn(),mr)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(te.gray(`No tools exposed by '${e}'.`));else{console.log(te.cyan(`
383
383
  Tools from ${e} (${i.length})
384
- `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(ee.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=K.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}le();import be from"node:fs";import St from"node:os";import yc from"node:path";import{execSync as Zs}from"node:child_process";import $ from"chalk";import{Command as bc}from"commander";function ho(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function vc(){let o=process.argv[1];if(o){let e=yc.resolve(o);if(be.existsSync(e))return e}try{let e=Zs("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&be.existsSync(e))return e}catch{}return"everclaw"}function wc(o){let e=hn();return`[Unit]
384
+ `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(te.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=U.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}ce();import ve from"node:fs";import kt from"node:os";import xc from"node:path";import{execSync as ni}from"node:child_process";import O from"chalk";import{Command as Tc}from"commander";function yo(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function Rc(){let o=process.argv[1];if(o){let e=xc.resolve(o);if(ve.existsSync(e))return e}try{let e=ni("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&ve.existsSync(e))return e}catch{}return"everclaw"}function Ac(o){let e=hn();return`[Unit]
385
385
  Description=Everclaw AI Assistant Gateway
386
386
  After=network-online.target
387
387
  Wants=network-online.target
@@ -397,7 +397,7 @@ StandardError=append:${e}/gateway.stderr.log
397
397
 
398
398
  [Install]
399
399
  WantedBy=default.target
400
- `}function Sc(o){let e=hn();return`<?xml version="1.0" encoding="UTF-8"?>
400
+ `}function Ec(o){let e=hn();return`<?xml version="1.0" encoding="UTF-8"?>
401
401
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
402
402
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
403
403
  <plist version="1.0">
@@ -420,22 +420,22 @@ WantedBy=default.target
420
420
  <string>${e}/gateway.stderr.log</string>
421
421
  </dict>
422
422
  </plist>
423
- `}function ue(o){try{return{ok:!0,output:Zs(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function kc(){let o=ho(),e=St.homedir(),t=hn(e),n=vc();be.mkdirSync(t,{recursive:!0}),o==="linux"?await xc(e,n):o==="macos"?await Cc(e,n):(console.log($.red(`Service installation is not supported on '${process.platform}'.`)),console.log($.gray("Supported: Linux (systemd), macOS (launchd).")),process.exitCode=1)}async function xc(o,e){let t=Mr(o),n=yn(o),r=wc(e);console.log($.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),be.mkdirSync(t,{recursive:!0}),be.writeFileSync(n,r,"utf8"),console.log($.green(" Unit file written."));let s=ue("systemctl --user daemon-reload");s.ok||console.log($.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=ue("systemctl --user enable everclaw");i.ok?console.log($.green(" Service enabled.")):console.log($.yellow(` Warning: enable failed: ${i.output}`));let a=ue("systemctl --user start everclaw");a.ok?console.log($.green(" Service started.")):console.log($.yellow(` Warning: start failed: ${a.output}`));let l=ue(`loginctl show-user ${St.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log($.yellow(`
424
- Note: Linger is not enabled. The service will stop when you log out.`)),console.log($.gray(` Run: loginctl enable-linger ${St.userInfo().username}`)),console.log($.gray(" (This may require sudo or admin assistance.)"))),console.log($.green(`
425
- Service installed successfully.`)),console.log($.gray("Use: systemctl --user status everclaw")),console.log($.gray(" systemctl --user stop everclaw")),console.log($.gray(" journalctl --user -u everclaw -f"))}async function Cc(o,e){let t=$r(o),n=bn(o),r=Sc(e);console.log($.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),be.mkdirSync(t,{recursive:!0}),be.writeFileSync(n,r,"utf8"),console.log($.green(" Plist written.")),ue(`launchctl unload ${n} 2>/dev/null`);let s=ue(`launchctl load ${n}`);s.ok?console.log($.green(" Agent loaded.")):console.log($.yellow(` Warning: load failed: ${s.output}`)),console.log($.green(`
426
- Service installed successfully.`)),console.log($.gray("Use: launchctl list | grep everclaw")),console.log($.gray(" launchctl unload "+n)),console.log($.gray(" launchctl load "+n))}async function Tc(){let o=ho(),e=St.homedir();o==="linux"?await Rc(e):o==="macos"?await Ac(e):(console.log($.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function Rc(o){let e=yn(o);console.log($.cyan("Uninstalling systemd user service...")),ue("systemctl --user stop everclaw"),ue("systemctl --user disable everclaw"),be.existsSync(e)?(be.unlinkSync(e),console.log($.green(" Unit file removed."))):console.log($.gray(" No unit file found.")),ue("systemctl --user daemon-reload"),console.log($.green(`
427
- Service uninstalled.`))}async function Ac(o){let e=bn(o);console.log($.cyan("Uninstalling launchd user agent...")),ue(`launchctl unload ${e} 2>/dev/null`).ok&&console.log($.green(" Agent unloaded.")),be.existsSync(e)?(be.unlinkSync(e),console.log($.green(" Plist removed."))):console.log($.gray(" No plist found.")),console.log($.green(`
428
- Service uninstalled.`))}async function Ec(){let o=ho(),e=St.homedir();console.log($.cyan(`Service Registration Status
429
- `)),o==="linux"?await Pc(e):o==="macos"?await Ic(e):console.log($.gray(`Service management not supported on '${process.platform}'.`))}async function Pc(o){let e=yn(o),t=be.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?$.green(e):$.gray("not found")}`),!t){console.log($.gray(`
430
- Service is not installed. Run: everclaw service install`));return}let n=ue("systemctl --user is-enabled everclaw 2>/dev/null"),r=ue("systemctl --user is-active everclaw 2>/dev/null");console.log(`Enabled: ${n.ok&&n.output==="enabled"?$.green("yes"):$.yellow(n.output||"unknown")}`),console.log(`Active: ${r.ok&&r.output==="active"?$.green("running"):r.ok?$.yellow(r.output):$.gray("unknown")}`);let s=ue(`loginctl show-user ${St.userInfo().username} -p Linger`),i=s.ok&&s.output.includes("yes");console.log(`Linger: ${i?$.green("enabled"):$.yellow("disabled")} (survives logout)`),i||console.log($.gray(` Run: loginctl enable-linger ${St.userInfo().username}`))}async function Ic(o){let e=bn(o),t=be.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?$.green(e):$.gray("not found")}`),!t){console.log($.gray(`
431
- Service is not installed. Run: everclaw service install`));return}let n=ue("launchctl list ai.everclaw.gateway 2>/dev/null");if(n.ok){let r=n.output.match(/"PID"\s*=\s*(\d+)/),s=n.output.match(/"LastExitStatus"\s*=\s*(\d+)/);if(r)console.log(`Status: ${$.green("running")} (PID ${r[1]})`);else if(s){let i=parseInt(s[1],10);console.log(`Status: ${i===0?$.green("exited cleanly"):$.yellow(`exited with code ${i}`)}`)}else console.log(`Status: ${$.green("loaded")}`)}else console.log(`Status: ${$.gray("not loaded")}`)}function ei(){let o=new bc("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
423
+ `}function me(o){try{return{ok:!0,output:ni(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function Pc(){let o=yo(),e=kt.homedir(),t=hn(e),n=Rc();ve.mkdirSync(t,{recursive:!0}),o==="linux"?await Ic(e,n):o==="macos"?await _c(e,n):(console.log(O.red(`Service installation is not supported on '${process.platform}'.`)),console.log(O.gray("Supported: Linux (systemd), macOS (launchd).")),process.exitCode=1)}async function Ic(o,e){let t=$r(o),n=yn(o),r=Ac(e);console.log(O.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),ve.mkdirSync(t,{recursive:!0}),ve.writeFileSync(n,r,"utf8"),console.log(O.green(" Unit file written."));let s=me("systemctl --user daemon-reload");s.ok||console.log(O.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=me("systemctl --user enable everclaw");i.ok?console.log(O.green(" Service enabled.")):console.log(O.yellow(` Warning: enable failed: ${i.output}`));let a=me("systemctl --user start everclaw");a.ok?console.log(O.green(" Service started.")):console.log(O.yellow(` Warning: start failed: ${a.output}`));let l=me(`loginctl show-user ${kt.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log(O.yellow(`
424
+ Note: Linger is not enabled. The service will stop when you log out.`)),console.log(O.gray(` Run: loginctl enable-linger ${kt.userInfo().username}`)),console.log(O.gray(" (This may require sudo or admin assistance.)"))),console.log(O.green(`
425
+ Service installed successfully.`)),console.log(O.gray("Use: systemctl --user status everclaw")),console.log(O.gray(" systemctl --user stop everclaw")),console.log(O.gray(" journalctl --user -u everclaw -f"))}async function _c(o,e){let t=Or(o),n=bn(o),r=Ec(e);console.log(O.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),ve.mkdirSync(t,{recursive:!0}),ve.writeFileSync(n,r,"utf8"),console.log(O.green(" Plist written.")),me(`launchctl unload ${n} 2>/dev/null`);let s=me(`launchctl load ${n}`);s.ok?console.log(O.green(" Agent loaded.")):console.log(O.yellow(` Warning: load failed: ${s.output}`)),console.log(O.green(`
426
+ Service installed successfully.`)),console.log(O.gray("Use: launchctl list | grep everclaw")),console.log(O.gray(" launchctl unload "+n)),console.log(O.gray(" launchctl load "+n))}async function Mc(){let o=yo(),e=kt.homedir();o==="linux"?await $c(e):o==="macos"?await Oc(e):(console.log(O.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function $c(o){let e=yn(o);console.log(O.cyan("Uninstalling systemd user service...")),me("systemctl --user stop everclaw"),me("systemctl --user disable everclaw"),ve.existsSync(e)?(ve.unlinkSync(e),console.log(O.green(" Unit file removed."))):console.log(O.gray(" No unit file found.")),me("systemctl --user daemon-reload"),console.log(O.green(`
427
+ Service uninstalled.`))}async function Oc(o){let e=bn(o);console.log(O.cyan("Uninstalling launchd user agent...")),me(`launchctl unload ${e} 2>/dev/null`).ok&&console.log(O.green(" Agent unloaded.")),ve.existsSync(e)?(ve.unlinkSync(e),console.log(O.green(" Plist removed."))):console.log(O.gray(" No plist found.")),console.log(O.green(`
428
+ Service uninstalled.`))}async function Lc(){let o=yo(),e=kt.homedir();console.log(O.cyan(`Service Registration Status
429
+ `)),o==="linux"?await Dc(e):o==="macos"?await Nc(e):console.log(O.gray(`Service management not supported on '${process.platform}'.`))}async function Dc(o){let e=yn(o),t=ve.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?O.green(e):O.gray("not found")}`),!t){console.log(O.gray(`
430
+ Service is not installed. Run: everclaw service install`));return}let n=me("systemctl --user is-enabled everclaw 2>/dev/null"),r=me("systemctl --user is-active everclaw 2>/dev/null");console.log(`Enabled: ${n.ok&&n.output==="enabled"?O.green("yes"):O.yellow(n.output||"unknown")}`),console.log(`Active: ${r.ok&&r.output==="active"?O.green("running"):r.ok?O.yellow(r.output):O.gray("unknown")}`);let s=me(`loginctl show-user ${kt.userInfo().username} -p Linger`),i=s.ok&&s.output.includes("yes");console.log(`Linger: ${i?O.green("enabled"):O.yellow("disabled")} (survives logout)`),i||console.log(O.gray(` Run: loginctl enable-linger ${kt.userInfo().username}`))}async function Nc(o){let e=bn(o),t=ve.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?O.green(e):O.gray("not found")}`),!t){console.log(O.gray(`
431
+ Service is not installed. Run: everclaw service install`));return}let n=me("launchctl list ai.everclaw.gateway 2>/dev/null");if(n.ok){let r=n.output.match(/"PID"\s*=\s*(\d+)/),s=n.output.match(/"LastExitStatus"\s*=\s*(\d+)/);if(r)console.log(`Status: ${O.green("running")} (PID ${r[1]})`);else if(s){let i=parseInt(s[1],10);console.log(`Status: ${i===0?O.green("exited cleanly"):O.yellow(`exited with code ${i}`)}`)}else console.log(`Status: ${O.green("loaded")}`)}else console.log(`Status: ${O.gray("not loaded")}`)}function ri(){let o=new Tc("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
432
432
  Examples:
433
433
  everclaw service install Register and start the gateway as a system service
434
434
  everclaw service uninstall Remove the system service
435
435
  everclaw service status Show service registration status
436
436
 
437
- Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await kc()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await Tc()}),o.command("status").description("Show service registration status").action(async()=>{await Ec()}),o}var Mc=Io(),$c="0.3.0";function fo(o,e){let t=o?.trim();if(!t)return e;let n=Number(t);if(!Number.isInteger(n)||n<1||n>65535)throw new Error(`Invalid gateway port '${o}'. Expected an integer between 1 and 65535.`);return n}function oi(){if(process.env.DOCKER==="true"||ge.existsSync("/.dockerenv"))return"Docker";if(process.env.INVOCATION_ID)return"systemd";if(process.env.XPC_SERVICE_NAME||process.env.LAUNCH_DAEMON)return"launchd";if(process.env.PM2_HOME||process.env.pm_id)return"pm2";try{if(ge.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function Oc(o){if(process.platform==="win32")return null;try{let{execSync:e}=ci("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
438
- `);if(n.length<2)return null;let r=n[1].trim().split(/\s+/),s=parseInt(r[3],10);return Number.isNaN(s)?null:s*1024}catch{return null}}async function si(o){let e=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(e=!0)}catch{}e&&console.log(S.green(" Ollama detected on localhost:11434"));let t=await Fe({type:"select",name:"provider",message:"Choose your provider",choices:[{title:"OpenRouter (recommended \u2014 access 200+ models)",value:"openrouter"},{title:"OpenAI",value:"openai"},{title:"Ollama (local, no API key needed)",value:"ollama"},{title:"Zai (\u667A\u8C31 AI)",value:"zai"},{title:"Custom OpenAI-compatible provider",value:"custom"}]}),n=String(t.provider||"openrouter"),r=Mc[n]??[o.agents.defaults.model],s=await Fe({type:"select",name:"model",message:"Choose your model",choices:r.map(c=>({title:c,value:c}))}),i=String(s.model||r[0]),a="";if(n!=="vllm"&&n!=="ollama"){let c=await Fe({type:"password",name:"apiKey",message:"Enter API key",validate:u=>u&&u.trim().length>0?!0:"API key cannot be empty"});a=String(c.apiKey||"")}let l="";if(n==="custom"||n==="vllm"||n==="ollama"){let c=await Fe({type:"text",name:"apiBase",message:"Enter API base URL",initial:n==="ollama"?"http://localhost:11434/v1":n==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"});l=String(c.apiBase||"").trim()}if(n==="custom"){let c;try{c=new URL(l).hostname.replace(/\./g,"-")}catch{c="custom-provider"}o.customLlmProviders.push({name:c,baseUrl:l,apiKey:a,apiFormat:"v1/chat/completions",models:[{id:i,displayName:i}],extraHeaders:null}),o.agents.defaults.provider=Wt(c),o.agents.defaults.model=i}else{if(o.agents.defaults.provider=n,o.agents.defaults.model=i,n in o.providers){let c=o.providers[n];c&&(c.apiKey=a)}if((n==="vllm"||n==="ollama")&&l&&n in o.providers){let c=o.providers[n];c&&(c.apiBase=l)}}}async function ii(o){if((await Fe({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await Fe({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),n=String(t.channel||"telegram");if(n==="telegram"){let r=await Fe({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:s=>s&&s.trim().length>0?!0:"Token cannot be empty"});o.channels.telegram.enabled=!0,o.channels.telegram.token=String(r.token||"").trim()}else if(n==="discord"){let r=await Fe({type:"password",name:"token",message:"Enter Discord Bot Token",validate:s=>s&&s.trim().length>0?!0:"Token cannot be empty"});o.channels.discord.enabled=!0,o.channels.discord.token=String(r.token||"").trim()}}}function ai(o){let e=new _c;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version($c,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
437
+ Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await Pc()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await Mc()}),o.command("status").description("Show service registration status").action(async()=>{await Lc()}),o}var Fc=_o(),Bc="0.3.0";function ho(o,e){let t=o?.trim();if(!t)return e;let n=Number(t);if(!Number.isInteger(n)||n<1||n>65535)throw new Error(`Invalid gateway port '${o}'. Expected an integer between 1 and 65535.`);return n}function ai(){if(process.env.DOCKER==="true"||le.existsSync("/.dockerenv"))return"Docker";if(process.env.INVOCATION_ID)return"systemd";if(process.env.XPC_SERVICE_NAME||process.env.LAUNCH_DAEMON)return"launchd";if(process.env.PM2_HOME||process.env.pm_id)return"pm2";try{if(le.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function Gc(o){if(process.platform==="win32")return null;try{let{execSync:e}=gi("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
438
+ `);if(n.length<2)return null;let r=n[1].trim().split(/\s+/),s=parseInt(r[3],10);return Number.isNaN(s)?null:s*1024}catch{return null}}async function li(o){let e=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(e=!0)}catch{}e&&console.log(S.green(" Ollama detected on localhost:11434"));let t=await pe({type:"select",name:"provider",message:"Choose your provider",choices:[{title:"OpenRouter (recommended \u2014 access 200+ models)",value:"openrouter"},{title:"OpenAI",value:"openai"},{title:"Ollama (local, no API key needed)",value:"ollama"},{title:"Zai (\u667A\u8C31 AI)",value:"zai"},{title:"Custom OpenAI-compatible provider",value:"custom"}]}),n=String(t.provider||"openrouter"),r=Fc[n]??[o.agents.defaults.model],s=await pe({type:"select",name:"model",message:"Choose your model",choices:r.map(c=>({title:c,value:c}))}),i=String(s.model||r[0]),a="";if(n!=="vllm"&&n!=="ollama"){let c=await pe({type:"password",name:"apiKey",message:"Enter API key",validate:d=>d&&d.trim().length>0?!0:"API key cannot be empty"});a=String(c.apiKey||"")}let l="";if(n==="custom"||n==="vllm"||n==="ollama"){let c=await pe({type:"text",name:"apiBase",message:"Enter API base URL",initial:n==="ollama"?"http://localhost:11434/v1":n==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"});l=String(c.apiBase||"").trim()}if(n==="custom"){let c;try{c=new URL(l).hostname.replace(/\./g,"-")}catch{c="custom-provider"}o.customLlmProviders.push({name:c,baseUrl:l,apiKey:a,apiFormat:"v1/chat/completions",models:[{id:i,displayName:i}],extraHeaders:null}),o.agents.defaults.provider=Wt(c),o.agents.defaults.model=i}else{if(o.agents.defaults.provider=n,o.agents.defaults.model=i,n in o.providers){let c=o.providers[n];c&&(c.apiKey=a)}if((n==="vllm"||n==="ollama")&&l&&n in o.providers){let c=o.providers[n];c&&(c.apiBase=l)}}}async function ci(o){if((await pe({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await pe({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),n=String(t.channel||"telegram");if(n==="telegram"){let r=await pe({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:i=>i&&i.trim().length>0?!0:"Token cannot be empty"});if(o.channels.telegram.enabled=!0,o.channels.telegram.token=String(r.token||"").trim(),(await pe({type:"confirm",name:"enableGroups",message:"Enable Telegram group chat support?",initial:!0})).enableGroups){let i=await pe({type:"confirm",name:"requireMention",message:"Require @mention to respond in groups? (recommended)",initial:!0});if(o.channels.telegram.groups={requireMention:i.requireMention!==!1,allowedGroupIds:null},(await pe({type:"confirm",name:"restrictGroups",message:"Restrict to specific group IDs?",initial:!1})).restrictGroups){let l=await pe({type:"text",name:"groupIds",message:"Enter allowed group IDs (comma-separated, e.g., -1001234567890)"}),c=String(l.groupIds||"").split(",").map(d=>d.trim()).filter(d=>d.length>0);o.channels.telegram.groups.allowedGroupIds=c.length>0?c:null}}else o.channels.telegram.groups={requireMention:!0,allowedGroupIds:[]}}else if(n==="discord"){let r=await pe({type:"password",name:"token",message:"Enter Discord Bot Token",validate:s=>s&&s.trim().length>0?!0:"Token cannot be empty"});o.channels.discord.enabled=!0,o.channels.discord.token=String(r.token||"").trim()}}}function di(o){let e=new jc;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(Bc,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
439
439
  Examples:
440
440
  everclaw onboard Interactive setup wizard
441
441
  everclaw gateway Start the gateway server
@@ -443,41 +443,41 @@ Examples:
443
443
  everclaw doctor Check system health and connectivity
444
444
  everclaw status Show gateway status
445
445
 
446
- Documentation: https://docs.everclaw.ai`),e.addCommand(zs()),e.addCommand(Ys()),e.addCommand(Qs()),e.addCommand(Xs()),e.addCommand(ei()),o?.commands)for(let i of o.commands.values()){let a=e.command(i.contribution.name).description(i.contribution.description??"");i.contribution.builder&&i.contribution.builder(a),a.action(async l=>{await i.contribution.handler({},l)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").option("--skip-provider","Keep existing provider/model/apiKey config").option("--skip-channel","Keep existing channel config").option("--skip-workspace","Skip workspace creation and template sync").action(async i=>{let a=Rt(),l=ge.existsSync(a),c=_();if(l){console.log(`Config already exists at ${a}`);let g=ti.createInterface({input:ni,output:ri}),h=(await g.question("Overwrite? [y/N] ")).trim().toLowerCase();g.close(),h==="y"?(c=structuredClone(fe),oe(c),console.log(`Config reset to defaults at ${a}`)):(oe(c),console.log(`Config refreshed at ${a} (existing values preserved)`))}else oe(c),console.log(`Created config at ${a}`);if(i.skipWorkspace)console.log(S.gray("Skipping workspace setup (--skip-workspace)."));else{let g=X(c.agents.defaults.workspace);ge.existsSync(g)||(ge.mkdirSync(g,{recursive:!0}),console.log(`Created workspace at ${g}`)),lt(g)}if(i.provider||i.model||i.apiKey||i.apiBase||i.channel||i.channelToken||i.noChannel){if((i.provider??c.agents.defaults.provider)==="custom"&&i.apiKey&&i.apiBase){let h;try{h=new URL(i.apiBase).hostname.replace(/\./g,"-")}catch{h="custom-provider"}c.customLlmProviders.push({name:h,baseUrl:i.apiBase,apiKey:i.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),c.agents.defaults.provider=Wt(h)}else{if(i.provider&&(c.agents.defaults.provider=i.provider),i.apiKey){let h=c.agents.defaults.provider;if(h in c.providers){let T=c.providers[h];T&&(T.apiKey=i.apiKey)}}if(i.apiBase){let h=c.agents.defaults.provider;if(h in c.providers){let T=c.providers[h];T&&(T.apiBase=i.apiBase)}}}if(i.model&&(c.agents.defaults.model=i.model),i.noChannel||(i.channel==="telegram"&&i.channelToken?(c.channels.telegram.enabled=!0,c.channels.telegram.token=i.channelToken):i.channel==="discord"&&i.channelToken&&(c.channels.discord.enabled=!0,c.channels.discord.token=i.channelToken)),oe(c),console.log(S.green(`
447
- Config created via non-interactive mode.`)),!i.noTest){console.log(S.cyan(`
448
- Running connectivity test...`));try{let T=await Me(c).chat({messages:[{role:"user",content:"Reply with: OK"}],model:c.agents.defaults.model,maxTokens:16,temperature:0});(T.content||"").toLowerCase().includes("error")?console.log(S.red(`Connectivity test failed: ${T.content}`)):console.log(S.green(`Connectivity test passed: ${T.content??"(empty response)"}`))}catch(h){console.log(S.red(`Connectivity test failed: ${String(h)}`))}}console.log(S.yellow(`
446
+ Documentation: https://docs.everclaw.ai`),e.addCommand(Ys()),e.addCommand(ei()),e.addCommand(ti()),e.addCommand(Zs()),e.addCommand(ri()),o?.commands)for(let a of o.commands.values()){let l=e.command(a.contribution.name).description(a.contribution.description??"");a.contribution.builder&&a.contribution.builder(l),l.action(async c=>{await a.contribution.handler({},c)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").option("--skip-provider","Keep existing provider/model/apiKey config").option("--skip-channel","Keep existing channel config").option("--skip-workspace","Skip workspace creation and template sync").action(async a=>{let l=dt(),c=le.existsSync(l),d=M();if(c){console.log(`Config already exists at ${l}`);let h=oi.createInterface({input:si,output:ii}),w=(await h.question("Overwrite? [y/N] ")).trim().toLowerCase();h.close(),w==="y"?(d=structuredClone(de),oe(d),console.log(`Config reset to defaults at ${l}`)):(oe(d),console.log(`Config refreshed at ${l} (existing values preserved)`))}else oe(d),console.log(`Created config at ${l}`);if(a.skipWorkspace)console.log(S.gray("Skipping workspace setup (--skip-workspace)."));else{let h=V(d.agents.defaults.workspace);le.existsSync(h)||(le.mkdirSync(h,{recursive:!0}),console.log(`Created workspace at ${h}`)),lt(h)}if(a.provider||a.model||a.apiKey||a.apiBase||a.channel||a.channelToken||a.noChannel){if((a.provider??d.agents.defaults.provider)==="custom"&&a.apiKey&&a.apiBase){let w;try{w=new URL(a.apiBase).hostname.replace(/\./g,"-")}catch{w="custom-provider"}d.customLlmProviders.push({name:w,baseUrl:a.apiBase,apiKey:a.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),d.agents.defaults.provider=Wt(w)}else{if(a.provider&&(d.agents.defaults.provider=a.provider),a.apiKey){let w=d.agents.defaults.provider;if(w in d.providers){let v=d.providers[w];v&&(v.apiKey=a.apiKey)}}if(a.apiBase){let w=d.agents.defaults.provider;if(w in d.providers){let v=d.providers[w];v&&(v.apiBase=a.apiBase)}}}if(a.model&&(d.agents.defaults.model=a.model),a.noChannel||(a.channel==="telegram"&&a.channelToken?(d.channels.telegram.enabled=!0,d.channels.telegram.token=a.channelToken):a.channel==="discord"&&a.channelToken&&(d.channels.discord.enabled=!0,d.channels.discord.token=a.channelToken)),oe(d),console.log(S.green(`
447
+ Config created via non-interactive mode.`)),!a.noTest){console.log(S.cyan(`
448
+ Running connectivity test...`));try{let v=await $e(d).chat({messages:[{role:"user",content:"Reply with: OK"}],model:d.agents.defaults.model,maxTokens:16,temperature:0});(v.content||"").toLowerCase().includes("error")?console.log(S.red(`Connectivity test failed: ${v.content}`)):console.log(S.green(`Connectivity test passed: ${v.content??"(empty response)"}`))}catch(w){console.log(S.red(`Connectivity test failed: ${String(w)}`))}}console.log(S.yellow(`
449
449
  Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){if(console.log(S.cyan(`
450
450
  everclaw Setup Wizard`)),console.log(S.gray(`Use arrow keys to pick options.
451
- `)),i.skipProvider)console.log(S.gray(`Skipping provider setup (--skip-provider). Current: ${c.agents.defaults.provider} / ${c.agents.defaults.model}`));else{let g=c.agents.defaults.provider,h=c.agents.defaults.model;g!=="auto"&&g!==fe.agents.defaults.provider?(await Fe({type:"confirm",name:"keep",message:`Keep current provider (${g}, model: ${h})?`,initial:!0})).keep?console.log(S.gray(`Keeping provider: ${g} / ${h}`)):await si(c):await si(c)}if(i.skipChannel||i.noChannel)console.log(S.gray("Skipping channel setup (--skip-channel)."));else{let g=c.channels.telegram.enabled&&c.channels.telegram.token,h=c.channels.discord.enabled&&c.channels.discord.token;if(g||h){let T=[];g&&T.push("telegram"),h&&T.push("discord"),(await Fe({type:"confirm",name:"keep",message:`Keep current channel config (${T.join(", ")})?`,initial:!0})).keep?console.log(S.gray(`Keeping channel config: ${T.join(", ")}`)):await ii(c)}else await ii(c)}oe(c),console.log(S.green(`
451
+ `)),a.skipProvider)console.log(S.gray(`Skipping provider setup (--skip-provider). Current: ${d.agents.defaults.provider} / ${d.agents.defaults.model}`));else{let h=d.agents.defaults.provider,w=d.agents.defaults.model;h!=="auto"&&h!==de.agents.defaults.provider?(await pe({type:"confirm",name:"keep",message:`Keep current provider (${h}, model: ${w})?`,initial:!0})).keep?console.log(S.gray(`Keeping provider: ${h} / ${w}`)):await li(d):await li(d)}if(a.skipChannel||a.noChannel)console.log(S.gray("Skipping channel setup (--skip-channel)."));else{let h=d.channels.telegram.enabled&&d.channels.telegram.token,w=d.channels.discord.enabled&&d.channels.discord.token;if(h||w){let v=[];h&&v.push("telegram"),w&&v.push("discord"),(await pe({type:"confirm",name:"keep",message:`Keep current channel config (${v.join(", ")})?`,initial:!0})).keep?console.log(S.gray(`Keeping channel config: ${v.join(", ")}`)):await ci(d)}else await ci(d)}oe(d),console.log(S.green(`
452
452
  Configs created.`)),console.log(S.yellow("Run everclaw gateway")),console.log(S.yellow("or chat with agent: everclaw agent"));return}console.log(`
453
- everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${at}, then run everclaw gateway or everclaw agent.`)}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new yo("--channel <channel>").default("cli").hideHelp()).addOption(new yo("--chat-id <chatId>").default("direct").hideHelp()).addOption(new yo("--raw-output").default(!1).hideHelp()).action(async i=>{let a=_(),l=Kt(a,process.env),c=X(l.agents.defaults.workspace);lt(c,!0);let u=new ut,g;try{g=Me(l)}catch(d){console.log(S.red(String(d))),process.exitCode=1;return}let h=new Qe(c),{cron:T}=Je({cron:{dataDir:De()}}),v=new Nt({bus:u,provider:g,workspace:c,model:l.agents.defaults.model,temperature:l.agents.defaults.temperature,maxTokens:l.agents.defaults.maxTokens,maxIterations:l.agents.defaults.maxToolIterations,memoryWindow:l.agents.defaults.memoryWindow,braveApiKey:l.tools.web.search.apiKey||null,execConfig:l.tools.exec,cronService:T,restrictToWorkspace:l.tools.restrictToWorkspace,channelsConfig:l.channels,loadConfig:_});if(i.message){let d=await v.processDirect(String(i.message),String(i.session),String(i.channel),String(i.chatId));i.rawOutput?process.stdout.write(d):console.log(`
453
+ everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${at}, then run everclaw gateway or everclaw agent.`)}),e.command("config").description("Manage configuration").command("compact").description("Remove default values from config file (makes it sparse)").action(()=>{let a=dt();if(!le.existsSync(a)){console.log(S.red(`No config file found at ${a}`)),console.log(S.gray("Run `everclaw onboard` to create one.")),process.exitCode=1;return}let l=M();oe(l),console.log(S.green(`Config compacted at ${a}`))}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new bo("--channel <channel>").default("cli").hideHelp()).addOption(new bo("--chat-id <chatId>").default("direct").hideHelp()).addOption(new bo("--raw-output").default(!1).hideHelp()).action(async a=>{let l=M(),c=Kt(l,process.env),d=V(c.agents.defaults.workspace);lt(d,!0);let p=new gt,h;try{h=$e(c)}catch(b){console.log(S.red(String(b))),process.exitCode=1;return}let w=new Qe(d),{cron:v}=qe({cron:{dataDir:Ne()}}),u=new Nt({bus:p,provider:h,workspace:d,model:c.agents.defaults.model,temperature:c.agents.defaults.temperature,maxTokens:c.agents.defaults.maxTokens,maxIterations:c.agents.defaults.maxToolIterations,memoryWindow:c.agents.defaults.memoryWindow,braveApiKey:c.tools.web.search.apiKey||null,execConfig:c.tools.exec,cronService:v,restrictToWorkspace:c.tools.restrictToWorkspace,channelsConfig:c.channels,loadConfig:M});if(a.message){let b=await u.processDirect(String(a.message),String(a.session),String(a.channel),String(a.chatId));a.rawOutput?process.stdout.write(b):console.log(`
454
454
  everclaw
455
- ${d}
456
- `)}else{console.log("Interactive mode (type exit to quit)");let d=ti.createInterface({input:ni,output:ri});for(;;){let b=await d.question("You: "),O=b.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(O))break;let k=await v.processDirect(b,String(i.session));console.log(`
455
+ ${b}
456
+ `)}else{console.log("Interactive mode (type exit to quit)");let b=oi.createInterface({input:si,output:ii});for(;;){let P=await b.question("You: "),C=P.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(C))break;let N=await u.processDirect(P,String(a.session));console.log(`
457
457
  everclaw
458
- ${k}
459
- `)}d.close()}});let t=e.command("channels").description("Manage channels");t.addHelpText("after",`
458
+ ${N}
459
+ `)}b.close()}});let n=e.command("channels").description("Manage channels");n.addHelpText("after",`
460
460
  Examples:
461
- everclaw channels status Show channel configuration`),t.command("status").action(()=>{let i=_(),a=[["Telegram",i.channels.telegram.enabled?"yes":"no",i.channels.telegram.token?`token: ${i.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",i.channels.discord.enabled?"yes":"no",i.channels.discord.gatewayUrl]];for(let l of a){let c=l[0]??"",u=l[1]??"",g=l[2]??"";console.log(`${c.padEnd(12)} ${u.padEnd(3)} ${g}`)}}),t.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let n=e.command("auto").alias("automation").description("Manage browser automations");n.command("list").action(()=>{let i=_(),a=X(i.agents.defaults.workspace),l=$t(a);if(!l.length)return console.log("No automations found.");console.log(S.cyan(`
462
- Saved Automations:`));for(let c of l)console.log(`${S.bold(c.id)} | ${c.name} | ${c.stepCount||0} steps | ${c.enabled?S.green("enabled"):S.gray("disabled")}`),c.description&&console.log(S.gray(` ${c.description}`));console.log("")}),n.command("show <id>").action(i=>{let a=_(),l=X(a.agents.defaults.workspace),c=Se(l,i);if(!c)return console.log(S.red(`Automation '${i}' not found.`));console.log(S.cyan(`
463
- Automation: ${c.name} (${c.id})`)),console.log(S.gray(c.description||"No description")),console.log(`
464
- Steps (${c.steps.length}):`);for(let u of c.steps)console.log(` ${u.order}. ${u.description} (${u.action})`);c.scriptContent&&(console.log(S.yellow(`
465
- Generated Script:`)),console.log(S.gray("----------------------------------------")),console.log(c.scriptContent),console.log(S.gray("----------------------------------------"))),console.log("")}),n.command("run <id>").action(async i=>{let a=_(),l=X(a.agents.defaults.workspace),c=Se(l,i);if(!c)return console.log(S.red(`Automation '${i}' not found.`));let u;if(a.tools.chromeSession?.enabled&&(u=new ht(a.tools.chromeSession,l,!!a.tools.restrictToWorkspace)),!u)return console.log(S.red("No browser tool available. Enable chrome_session in config."));let g=new Lt(l,u);console.log(S.cyan(`Running automation: ${c.name}...`));let h=await g.execute({command:"run",id:i});console.log(h)}),n.command("remove").alias("delete").argument("<id>").action(i=>{let a=_(),l=X(a.agents.defaults.workspace);Ot(l,i)?console.log(S.green(`Removed automation '${i}'`)):console.log(S.red(`Automation '${i}' not found.`))});let r=e.command("cron").description("Manage scheduled tasks");return r.addHelpText("after",`
461
+ everclaw channels status Show channel configuration`),n.command("status").action(()=>{let a=M(),l=[["Telegram",a.channels.telegram.enabled?"yes":"no",a.channels.telegram.token?`token: ${a.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",a.channels.discord.enabled?"yes":"no",a.channels.discord.gatewayUrl]];for(let c of l){let d=c[0]??"",p=c[1]??"",h=c[2]??"";console.log(`${d.padEnd(12)} ${p.padEnd(3)} ${h}`)}}),n.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let r=e.command("auto").alias("automation").description("Manage browser automations");r.command("list").action(()=>{let a=M(),l=V(a.agents.defaults.workspace),c=$t(l);if(!c.length)return console.log("No automations found.");console.log(S.cyan(`
462
+ Saved Automations:`));for(let d of c)console.log(`${S.bold(d.id)} | ${d.name} | ${d.stepCount||0} steps | ${d.enabled?S.green("enabled"):S.gray("disabled")}`),d.description&&console.log(S.gray(` ${d.description}`));console.log("")}),r.command("show <id>").action(a=>{let l=M(),c=V(l.agents.defaults.workspace),d=ke(c,a);if(!d)return console.log(S.red(`Automation '${a}' not found.`));console.log(S.cyan(`
463
+ Automation: ${d.name} (${d.id})`)),console.log(S.gray(d.description||"No description")),console.log(`
464
+ Steps (${d.steps.length}):`);for(let p of d.steps)console.log(` ${p.order}. ${p.description} (${p.action})`);d.scriptContent&&(console.log(S.yellow(`
465
+ Generated Script:`)),console.log(S.gray("----------------------------------------")),console.log(d.scriptContent),console.log(S.gray("----------------------------------------"))),console.log("")}),r.command("run <id>").action(async a=>{let l=M(),c=V(l.agents.defaults.workspace),d=ke(c,a);if(!d)return console.log(S.red(`Automation '${a}' not found.`));let p;if(l.tools.chromeSession?.enabled&&(p=new yt(l.tools.chromeSession,c,!!l.tools.restrictToWorkspace)),!p)return console.log(S.red("No browser tool available. Enable chrome_session in config."));let h=new Lt(c,p);console.log(S.cyan(`Running automation: ${d.name}...`));let w=await h.execute({command:"run",id:a});console.log(w)}),r.command("remove").alias("delete").argument("<id>").action(a=>{let l=M(),c=V(l.agents.defaults.workspace);Ot(c,a)?console.log(S.green(`Removed automation '${a}'`)):console.log(S.red(`Automation '${a}' not found.`))});let s=e.command("cron").description("Manage scheduled tasks");return s.addHelpText("after",`
466
466
  Examples:
467
467
  everclaw cron list List all scheduled jobs
468
468
  everclaw cron add -n "daily" --cron "0 9 * * *" -m "Good morning!"
469
469
  everclaw cron add -n "reminder" --at "2024-12-25T09:00:00" -m "Merry Christmas!" -d --to "12345" --channel "telegram"
470
- everclaw cron run abc123 Run a job immediately`),r.command("list").option("-a, --all","Include disabled jobs",!1).action(i=>{let{cron:a}=Je({cron:{dataDir:De()}}),l=a.listJobs(!!i.all);if(!l.length)return console.log("No scheduled jobs.");for(let c of l){let u=c.schedule.kind==="every"?`every ${c.schedule.everyMs/1e3}s`:c.schedule.kind==="cron"?`${c.schedule.expr} (${c.schedule.tz??"local"})`:"one-time",g=c.state.nextRunAtMs?new Date(c.state.nextRunAtMs).toISOString():"";console.log(`${c.id} | ${c.name} | ${u} | ${c.enabled?"enabled":"disabled"} | ${g}`)}}),r.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(i=>{if(i.tz&&!i.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let a;if(i.every)a={kind:"every",everyMs:Number(i.every)*1e3};else if(i.cron){let c={kind:"cron",expr:String(i.cron)};i.tz&&(c.tz=String(i.tz)),a=c}else if(i.at){let c=new Date(String(i.at));if(Number.isNaN(c.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}a={kind:"at",atMs:c.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:l}=Je({cron:{dataDir:De()}});try{let c={name:String(i.name),schedule:a,message:String(i.message),deliver:!!i.deliver};i.to&&(c.to=String(i.to)),i.channel&&(c.channel=String(i.channel));let u=l.addJob(c);console.log(`Added job '${u.name}' (${u.id})`)}catch(c){console.log(`Error: ${String(c).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),r.command("remove").argument("<jobId>").action(i=>{let{cron:a}=Je({cron:{dataDir:De()}});a.removeJob(i)?console.log(`Removed job ${i}`):console.log(`Job ${i} not found`)}),r.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((i,a)=>{let{cron:l}=Je({cron:{dataDir:De()}}),c=l.enableJob(i,!a.disable);if(!c)return console.log(`Job ${i} not found`);console.log(`Job '${c.name}' ${a.disable?"disabled":"enabled"}`)}),r.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(i,a)=>{let l=_(),c=X(l.agents.defaults.workspace),u;try{u=Me(l)}catch(b){console.log(S.red(String(b))),process.exitCode=1;return}let g=new ut,h=pr(l.tools.exec.timeout),T=an({target:"scheduled-job",timeoutMs:h}),{cron:v}=Je({cron:{dataDir:De(),onJob:async(b,O)=>{let k=await T.run({payload:{message:b.payload.message,session:`cron:${b.id}`,channel:b.payload.channel??"cli",chatId:b.payload.to??"direct"},cwd:process.cwd(),signal:O?.signal});return d.push(k),k}}}),d=[];await v.runJob(i,!!a.force)?(console.log("Job executed"),d.length&&console.log(d[0])):(console.log(`Failed to run job ${i}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let a=!!e.opts().json,l=Rt(),c=_(),u=X(c.agents.defaults.workspace),g=c.gateway.port,h=null;try{let d=await fetch(`http://127.0.0.1:${g}/api/status`,{signal:AbortSignal.timeout(2e3)});d.ok&&(h=await d.json())}catch{}let v=await new Te().getStatus();if(a){let d={gateway:{running:!!h,port:h?h.gateway?.port??g:null},model:c.agents.defaults.model,provider:Xe(c)??null,config:{path:l,exists:ge.existsSync(l)},workspace:{path:u,exists:ge.existsSync(u)},rtk:{installed:v.installed,version:v.version??null,binaryPath:v.binaryPath}};if(h){let b=h.runtime,O=h.channelStatus,k=Ee();d.gateway={running:!0,port:h.gateway?.port??g,pid:k?.pid??null,uptime:k?dt(k.startedAt):null},d.agent={acceptingWork:b?.acceptingWork??!0,activeSessions:b?.activeSessions??0,queuedMessages:b?.queuedMessages??0,subagents:b?.subagents??0},d.channels=O??{}}console.log(JSON.stringify(d,null,2));return}if(console.log(S.cyan(`everclaw Status
471
- `)),h){let d=h.runtime,b=h.gateway,O=h.channelStatus,k=Ee(),G=k?dt(k.startedAt):"unknown";console.log(`Gateway: ${S.green("running")} (port ${b?.port??g}, uptime ${G})`),console.log(`Agent: ${d?.acceptingWork?S.green("idle (accepting work)"):S.yellow("busy")}`),console.log(` Active sessions: ${d?.activeSessions??0}`),console.log(` Queued messages: ${d?.queuedMessages??0}`),console.log(` Subagents: ${d?.subagents??0}`);let L=d?.overload;if(L&&typeof L.rateLimited=="number"&&L.rateLimited>0&&console.log(` Rate limited: ${S.yellow(String(L.rateLimited))} (window: ${L.rateLimitWindowMs??0}ms)`),O&&Object.keys(O).length>0){console.log(`
472
- Channels:`);for(let[N,z]of Object.entries(O)){let ae=z?.running?S.green("connected"):S.gray("disconnected");console.log(` ${N.padEnd(12)} ${ae}`)}}}else console.log(`Gateway: ${S.gray("not running")}`);console.log(`
473
- Model: ${c.agents.defaults.model}`),console.log(`Provider: ${Xe(c)??"none"}`),console.log(`Config: ${l} ${ge.existsSync(l)?"yes":"no"}`),console.log(`Workspace: ${u} ${ge.existsSync(u)?"yes":"no"}`),console.log(`
474
- RTK Token Compression:`),v.installed&&v.version?(console.log(` Status: ${S.green("Available")} (v${v.version})`),console.log(` Binary: ${v.binaryPath}`)):v.installed?(console.log(` Status: ${S.yellow("Installed but broken")}`),console.log(` Binary: ${v.binaryPath}`),console.log(S.gray(` Run ${S.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${S.gray("Not installed")}`),c.tools.rtk.autoInstall?console.log(S.gray(" Auto-install is enabled and will download on first gateway start")):console.log(S.gray(` Run ${S.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let a=!!e.opts().json,l=_(),c=Kt(l,process.env),u=Xe(c),g=[],h={ok:!0,warnings:[]},T=Ee(),v=T&&Ae(T.pid);h.system={gateway:v?{running:!0,pid:T.pid,port:T.port,uptime:dt(T.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:oi()??"standalone"},a||(console.log(S.cyan(`everclaw doctor
475
- `)),console.log(S.bold("System:")),console.log(v?` Gateway: ${S.green("running")} (PID ${T.pid}, port ${T.port}, uptime ${dt(T.startedAt)})`:` Gateway: ${S.gray("not running")}`));let d=process.versions.node,b=parseInt(d.split(".")[0]??"0",10);b<20&&g.push("Node.js version below 20 may have compatibility issues");let O=process.getuid?.()===0;if(O&&g.push("Running as root is not recommended for security"),!a){b>=20?console.log(` Node.js: ${S.green(d)}`):console.log(` Node.js: ${S.yellow(d)} (recommend v20+)`),console.log(O?` Running as: ${S.red("root")} (not recommended)`:` Running as: ${S.green("non-root")}`);let A=oi();console.log(A?` Supervisor: ${S.green(A)}`:` Supervisor: ${S.gray("standalone")}`)}let k=Rt();if(ge.existsSync(k))try{let F=!!(ge.statSync(k).mode&511&7);h.system.configPermissions={ok:!F,path:k},F&&g.push("Config file is world-readable \u2014 contains API keys"),a||console.log(F?` Config: ${S.yellow("world-readable")} (${k})`:` Config: ${S.green("ok")} (${k})`)}catch{a||console.log(` Config: ${S.gray("unable to check")}`)}try{let A=De();ge.statSync(A);let I=Oc(A);if(I!==null){let F=Math.round(I/1048576);h.system.diskSpace={freeMB:F,path:A,ok:I>=100*1024*1024},I<100*1024*1024&&g.push(`Low disk space: ${F}MB free in ${A}`),a||(I<100*1024*1024?console.log(` Disk space: ${S.yellow(`${F}MB free`)} (${A})`):console.log(` Disk space: ${S.green(`${F}MB free`)} (${A})`))}}catch{}let G=X(c.agents.defaults.workspace);if(ge.existsSync(G))try{let F=!!(ge.statSync(G).mode&511&2);h.system.workspace={ok:!F,path:G},F&&g.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),a||console.log(F?` Workspace: ${S.yellow("world-writable")} (${G})`:` Workspace: ${S.green("ok")} (${G})`)}catch{a||console.log(` Workspace: ${S.gray("unable to check")}`)}else h.system.workspace={ok:!0,path:G,created:!1},a||console.log(` Workspace: ${S.gray("not created")} (${G})`);let L=c.security;if(h.security={enabled:L.enabled,auth:L.auth.enabled,toolGuard:L.toolGuard.enabled,skillScanner:L.skillScanner.enabled,inputSanitizer:L.inputSanitizer.enabled,pathBoundary:c.tools.restrictToWorkspace},a)L.toolGuard.enabled&&L.toolGuard.failOpen&&g.push("Tool guard is fail-open \u2014 consider fail-closed for production"),L.skillScanner.enabled||g.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),c.tools.restrictToWorkspace||g.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!L.auth.enabled&&c.gateway.host!=="127.0.0.1"&&c.gateway.host!=="localhost"&&g.push("Dashboard exposed on non-loopback without auth");else{if(console.log(S.bold(`
476
- Security:`)),console.log(` Master switch: ${L.enabled?S.green("enabled"):S.gray("disabled")}`),L.auth.enabled){let A=L.auth.sessionTtlS?`${Math.floor(L.auth.sessionTtlS/60)}min`:"default",I=L.auth.idleTimeoutS?`${Math.floor(L.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${S.green("enabled")} (PIN, session TTL: ${A}, idle lock: ${I})`)}else console.log(` Authentication: ${S.gray("disabled")}`),c.gateway.host!=="127.0.0.1"&&c.gateway.host!=="localhost"&&g.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${L.toolGuard.enabled?S.green("enabled"):S.gray("disabled")}`),L.toolGuard.enabled&&L.toolGuard.failOpen&&g.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${L.skillScanner.enabled?S.green("enabled"):S.gray("disabled")}`),L.skillScanner.enabled||g.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${L.inputSanitizer.enabled?S.green("enabled"):S.gray("disabled")}`),console.log(` Path Boundary: ${c.tools.restrictToWorkspace?S.green("workspace-restricted"):S.yellow("unrestricted")}`),c.tools.restrictToWorkspace||g.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let N=Oo(c);for(let A of N)g.includes(A)||g.push(A);h.provider={name:u??null,model:c.agents.defaults.model},a||(console.log(S.bold(`
477
- Provider:`)),console.log(` Resolved: ${u??"none"}`),console.log(` Model: ${c.agents.defaults.model}`));let B=await new Te().getStatus();h.rtk={installed:B.installed,version:B.version??null,binaryPath:B.binaryPath},B.installed&&B.version&&!wt(B.version,Ce)&&g.push(`RTK version ${B.version} is below minimum ${Ce}`),a||(console.log(S.bold(`
478
- RTK Token Compression:`)),B.installed&&B.version?wt(B.version,Ce)?console.log(` Status: ${S.green("Available")} (v${B.version})`):console.log(` Status: ${S.yellow("Outdated")} (v${B.version}, min: ${Ce})`):console.log(` Status: ${S.gray("Not installed")}`));let ae=Object.keys(c.tools.mcpServers);if(ae.length>0){let A={};a||console.log(S.bold(`
479
- MCP Servers:`));for(let I of ae)try{let{McpClientManager:F}=await Promise.resolve().then(()=>(sn(),gr)),q=new F;q.updateConfig(c.tools.mcpServers);let re=await q.getServerTools(I);await q.closeAll(),A[I]={connected:!0,tools:re.length},a||console.log(` ${I.padEnd(20)} ${S.green("\u2713 connected")} (${re.length} tools)`)}catch(F){let q=F instanceof Error?F.message:String(F);A[I]={connected:!1,error:q},a||console.log(` ${I.padEnd(20)} ${S.red("\u2717 "+q)}`)}h.mcp=A}let J={};if(c.channels.telegram.enabled){let A=c.channels.telegram.token,I=A?/^\d+:[A-Za-z0-9_-]{30,}$/.test(A):!1;J.telegram={enabled:!0,configured:!!A,validFormat:I},A?I||g.push("Telegram token format does not match expected pattern"):g.push("Telegram channel enabled but no token configured")}if(c.channels.discord.enabled){let A=c.channels.discord.token,I=A?A.length>=50&&/^[A-Za-z0-9._-]+$/.test(A):!1;J.discord={enabled:!0,configured:!!A,validFormat:I},A?I||g.push("Discord token format does not match expected pattern"):g.push("Discord channel enabled but no token configured")}if(Object.keys(J).length>0&&(h.channels=J,!a)){if(console.log(S.bold(`
480
- Channel Tokens:`)),c.channels.telegram.enabled){let A=c.channels.telegram.token;A&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(A)?console.log(` Telegram: ${S.green("valid format")}`):console.log(A?` Telegram: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${S.red("not configured")}`)}if(c.channels.discord.enabled){let A=c.channels.discord.token;A&&A.length>=50&&/^[A-Za-z0-9._-]+$/.test(A)?console.log(` Discord: ${S.green("valid format")}`):console.log(A?` Discord: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${S.red("not configured")}`)}}a||console.log(S.bold(`
481
- LLM Connectivity:`));let Z;try{Z=Me(c)}catch(A){h.llm={connected:!1,error:String(A)},h.ok=!1,h.warnings=g,console.log(a?JSON.stringify(h,null,2):` ${S.red("Failed to create provider: "+String(A))}`),process.exitCode=K.GENERAL_ERROR;return}try{let A=await Z.chat({messages:[{role:"user",content:"Reply with: OK"}],model:c.agents.defaults.model,maxTokens:16,temperature:0});if((A.content||"").toLowerCase().includes("error")){h.llm={connected:!1,error:A.content},h.ok=!1,h.warnings=g,console.log(a?JSON.stringify(h,null,2):` ${S.red("Failed: "+A.content)}`),process.exitCode=K.CONNECTIVITY_ERROR;return}h.llm={connected:!0},a||console.log(` ${S.green("Passed")}: ${A.content??"(empty response)"}`)}catch(A){h.llm={connected:!1,error:String(A)},h.ok=!1,h.warnings=g,console.log(a?JSON.stringify(h,null,2):` ${S.red("Failed: "+String(A))}`),process.exitCode=K.CONNECTIVITY_ERROR;return}if(h.warnings=g,a){console.log(JSON.stringify(h,null,2));return}if(g.length>0){console.log(S.bold(`
482
- Warnings:`));for(let A of g)console.log(` ${S.yellow("\u26A0")} ${A}`)}console.log(S.green(`
483
- Doctor check complete.`))}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(i=>{let a=i.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(a)){console.log(`Unknown OAuth provider: ${i}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${i} is not yet implemented in TypeScript port.`)}),e}Eo(process.argv);var Lc=ai();Lc.parseAsync(process.argv);
470
+ everclaw cron run abc123 Run a job immediately`),s.command("list").option("-a, --all","Include disabled jobs",!1).action(a=>{let{cron:l}=qe({cron:{dataDir:Ne()}}),c=l.listJobs(!!a.all);if(!c.length)return console.log("No scheduled jobs.");for(let d of c){let p=d.schedule.kind==="every"?`every ${d.schedule.everyMs/1e3}s`:d.schedule.kind==="cron"?`${d.schedule.expr} (${d.schedule.tz??"local"})`:"one-time",h=d.state.nextRunAtMs?new Date(d.state.nextRunAtMs).toISOString():"";console.log(`${d.id} | ${d.name} | ${p} | ${d.enabled?"enabled":"disabled"} | ${h}`)}}),s.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(a=>{if(a.tz&&!a.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let l;if(a.every)l={kind:"every",everyMs:Number(a.every)*1e3};else if(a.cron){let d={kind:"cron",expr:String(a.cron)};a.tz&&(d.tz=String(a.tz)),l=d}else if(a.at){let d=new Date(String(a.at));if(Number.isNaN(d.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}l={kind:"at",atMs:d.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:c}=qe({cron:{dataDir:Ne()}});try{let d={name:String(a.name),schedule:l,message:String(a.message),deliver:!!a.deliver};a.to&&(d.to=String(a.to)),a.channel&&(d.channel=String(a.channel));let p=c.addJob(d);console.log(`Added job '${p.name}' (${p.id})`)}catch(d){console.log(`Error: ${String(d).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),s.command("remove").argument("<jobId>").action(a=>{let{cron:l}=qe({cron:{dataDir:Ne()}});l.removeJob(a)?console.log(`Removed job ${a}`):console.log(`Job ${a} not found`)}),s.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((a,l)=>{let{cron:c}=qe({cron:{dataDir:Ne()}}),d=c.enableJob(a,!l.disable);if(!d)return console.log(`Job ${a} not found`);console.log(`Job '${d.name}' ${l.disable?"disabled":"enabled"}`)}),s.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(a,l)=>{let c=M(),d=V(c.agents.defaults.workspace),p;try{p=$e(c)}catch(P){console.log(S.red(String(P))),process.exitCode=1;return}let h=new gt,w=fr(c.tools.exec.timeout),v=an({target:"scheduled-job",timeoutMs:w}),{cron:u}=qe({cron:{dataDir:Ne(),onJob:async(P,C)=>{let N=await v.run({payload:{message:P.payload.message,session:`cron:${P.id}`,channel:P.payload.channel??"cli",chatId:P.payload.to??"direct"},cwd:process.cwd(),signal:C?.signal});return b.push(N),N}}}),b=[];await u.runJob(a,!!l.force)?(console.log("Job executed"),b.length&&console.log(b[0])):(console.log(`Failed to run job ${a}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let l=!!e.opts().json,c=dt(),d=M(),p=V(d.agents.defaults.workspace),h=d.gateway.port,w=null;try{let b=await fetch(`http://127.0.0.1:${h}/api/status`,{signal:AbortSignal.timeout(2e3)});b.ok&&(w=await b.json())}catch{}let u=await new Re().getStatus();if(l){let b={gateway:{running:!!w,port:w?w.gateway?.port??h:null},model:d.agents.defaults.model,provider:Xe(d)??null,config:{path:c,exists:le.existsSync(c)},workspace:{path:p,exists:le.existsSync(p)},rtk:{installed:u.installed,version:u.version??null,binaryPath:u.binaryPath}};if(w){let P=w.runtime,C=w.channelStatus,N=Pe();b.gateway={running:!0,port:w.gateway?.port??h,pid:N?.pid??null,uptime:N?ut(N.startedAt):null},b.agent={acceptingWork:P?.acceptingWork??!0,activeSessions:P?.activeSessions??0,queuedMessages:P?.queuedMessages??0,subagents:P?.subagents??0},b.channels=C??{}}console.log(JSON.stringify(b,null,2));return}if(console.log(S.cyan(`everclaw Status
471
+ `)),w){let b=w.runtime,P=w.gateway,C=w.channelStatus,N=Pe(),q=N?ut(N.startedAt):"unknown";console.log(`Gateway: ${S.green("running")} (port ${P?.port??h}, uptime ${q})`),console.log(`Agent: ${b?.acceptingWork?S.green("idle (accepting work)"):S.yellow("busy")}`),console.log(` Active sessions: ${b?.activeSessions??0}`),console.log(` Queued messages: ${b?.queuedMessages??0}`),console.log(` Subagents: ${b?.subagents??0}`);let I=b?.overload;if(I&&typeof I.rateLimited=="number"&&I.rateLimited>0&&console.log(` Rate limited: ${S.yellow(String(I.rateLimited))} (window: ${I.rateLimitWindowMs??0}ms)`),C&&Object.keys(C).length>0){console.log(`
472
+ Channels:`);for(let[J,Q]of Object.entries(C)){let W=Q?.running?S.green("connected"):S.gray("disconnected");console.log(` ${J.padEnd(12)} ${W}`)}}}else console.log(`Gateway: ${S.gray("not running")}`);console.log(`
473
+ Model: ${d.agents.defaults.model}`),console.log(`Provider: ${Xe(d)??"none"}`),console.log(`Config: ${c} ${le.existsSync(c)?"yes":"no"}`),console.log(`Workspace: ${p} ${le.existsSync(p)?"yes":"no"}`),console.log(`
474
+ RTK Token Compression:`),u.installed&&u.version?(console.log(` Status: ${S.green("Available")} (v${u.version})`),console.log(` Binary: ${u.binaryPath}`)):u.installed?(console.log(` Status: ${S.yellow("Installed but broken")}`),console.log(` Binary: ${u.binaryPath}`),console.log(S.gray(` Run ${S.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${S.gray("Not installed")}`),d.tools.rtk.autoInstall?console.log(S.gray(" Auto-install is enabled and will download on first gateway start")):console.log(S.gray(` Run ${S.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let l=!!e.opts().json,c=M(),d=Kt(c,process.env),p=Xe(d),h=[],w={ok:!0,warnings:[]},v=Pe(),u=v&&Ee(v.pid);w.system={gateway:u?{running:!0,pid:v.pid,port:v.port,uptime:ut(v.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:ai()??"standalone"},l||(console.log(S.cyan(`everclaw doctor
475
+ `)),console.log(S.bold("System:")),console.log(u?` Gateway: ${S.green("running")} (PID ${v.pid}, port ${v.port}, uptime ${ut(v.startedAt)})`:` Gateway: ${S.gray("not running")}`));let b=process.versions.node,P=parseInt(b.split(".")[0]??"0",10);P<20&&h.push("Node.js version below 20 may have compatibility issues");let C=process.getuid?.()===0;if(C&&h.push("Running as root is not recommended for security"),!l){P>=20?console.log(` Node.js: ${S.green(b)}`):console.log(` Node.js: ${S.yellow(b)} (recommend v20+)`),console.log(C?` Running as: ${S.red("root")} (not recommended)`:` Running as: ${S.green("non-root")}`);let T=ai();console.log(T?` Supervisor: ${S.green(T)}`:` Supervisor: ${S.gray("standalone")}`)}let N=dt();if(le.existsSync(N))try{let D=!!(le.statSync(N).mode&511&7);w.system.configPermissions={ok:!D,path:N},D&&h.push("Config file is world-readable \u2014 contains API keys"),l||console.log(D?` Config: ${S.yellow("world-readable")} (${N})`:` Config: ${S.green("ok")} (${N})`)}catch{l||console.log(` Config: ${S.gray("unable to check")}`)}try{let T=Ne();le.statSync(T);let j=Gc(T);if(j!==null){let D=Math.round(j/1048576);w.system.diskSpace={freeMB:D,path:T,ok:j>=100*1024*1024},j<100*1024*1024&&h.push(`Low disk space: ${D}MB free in ${T}`),l||(j<100*1024*1024?console.log(` Disk space: ${S.yellow(`${D}MB free`)} (${T})`):console.log(` Disk space: ${S.green(`${D}MB free`)} (${T})`))}}catch{}let q=V(d.agents.defaults.workspace);if(le.existsSync(q))try{let D=!!(le.statSync(q).mode&511&2);w.system.workspace={ok:!D,path:q},D&&h.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),l||console.log(D?` Workspace: ${S.yellow("world-writable")} (${q})`:` Workspace: ${S.green("ok")} (${q})`)}catch{l||console.log(` Workspace: ${S.gray("unable to check")}`)}else w.system.workspace={ok:!0,path:q,created:!1},l||console.log(` Workspace: ${S.gray("not created")} (${q})`);let I=d.security;if(w.security={enabled:I.enabled,auth:I.auth.enabled,toolGuard:I.toolGuard.enabled,skillScanner:I.skillScanner.enabled,inputSanitizer:I.inputSanitizer.enabled,pathBoundary:d.tools.restrictToWorkspace},l)I.toolGuard.enabled&&I.toolGuard.failOpen&&h.push("Tool guard is fail-open \u2014 consider fail-closed for production"),I.skillScanner.enabled||h.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),d.tools.restrictToWorkspace||h.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!I.auth.enabled&&d.gateway.host!=="127.0.0.1"&&d.gateway.host!=="localhost"&&h.push("Dashboard exposed on non-loopback without auth");else{if(console.log(S.bold(`
476
+ Security:`)),console.log(` Master switch: ${I.enabled?S.green("enabled"):S.gray("disabled")}`),I.auth.enabled){let T=I.auth.sessionTtlS?`${Math.floor(I.auth.sessionTtlS/60)}min`:"default",j=I.auth.idleTimeoutS?`${Math.floor(I.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${S.green("enabled")} (PIN, session TTL: ${T}, idle lock: ${j})`)}else console.log(` Authentication: ${S.gray("disabled")}`),d.gateway.host!=="127.0.0.1"&&d.gateway.host!=="localhost"&&h.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${I.toolGuard.enabled?S.green("enabled"):S.gray("disabled")}`),I.toolGuard.enabled&&I.toolGuard.failOpen&&h.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${I.skillScanner.enabled?S.green("enabled"):S.gray("disabled")}`),I.skillScanner.enabled||h.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${I.inputSanitizer.enabled?S.green("enabled"):S.gray("disabled")}`),console.log(` Path Boundary: ${d.tools.restrictToWorkspace?S.green("workspace-restricted"):S.yellow("unrestricted")}`),d.tools.restrictToWorkspace||h.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let J=No(d);for(let T of J)h.includes(T)||h.push(T);w.provider={name:p??null,model:d.agents.defaults.model},l||(console.log(S.bold(`
477
+ Provider:`)),console.log(` Resolved: ${p??"none"}`),console.log(` Model: ${d.agents.defaults.model}`));let z=await new Re().getStatus();w.rtk={installed:z.installed,version:z.version??null,binaryPath:z.binaryPath},z.installed&&z.version&&!St(z.version,Te)&&h.push(`RTK version ${z.version} is below minimum ${Te}`),l||(console.log(S.bold(`
478
+ RTK Token Compression:`)),z.installed&&z.version?St(z.version,Te)?console.log(` Status: ${S.green("Available")} (v${z.version})`):console.log(` Status: ${S.yellow("Outdated")} (v${z.version}, min: ${Te})`):console.log(` Status: ${S.gray("Not installed")}`));let W=Object.keys(d.tools.mcpServers);if(W.length>0){let T={};l||console.log(S.bold(`
479
+ MCP Servers:`));for(let j of W)try{let{McpClientManager:D}=await Promise.resolve().then(()=>(sn(),mr)),ee=new D;ee.updateConfig(d.tools.mcpServers);let m=await ee.getServerTools(j);await ee.closeAll(),T[j]={connected:!0,tools:m.length},l||console.log(` ${j.padEnd(20)} ${S.green("\u2713 connected")} (${m.length} tools)`)}catch(D){let ee=D instanceof Error?D.message:String(D);T[j]={connected:!1,error:ee},l||console.log(` ${j.padEnd(20)} ${S.red("\u2717 "+ee)}`)}w.mcp=T}let X={};if(d.channels.telegram.enabled){let T=d.channels.telegram.token,j=T?/^\d+:[A-Za-z0-9_-]{30,}$/.test(T):!1;X.telegram={enabled:!0,configured:!!T,validFormat:j},T?j||h.push("Telegram token format does not match expected pattern"):h.push("Telegram channel enabled but no token configured")}if(d.channels.discord.enabled){let T=d.channels.discord.token,j=T?T.length>=50&&/^[A-Za-z0-9._-]+$/.test(T):!1;X.discord={enabled:!0,configured:!!T,validFormat:j},T?j||h.push("Discord token format does not match expected pattern"):h.push("Discord channel enabled but no token configured")}if(Object.keys(X).length>0&&(w.channels=X,!l)){if(console.log(S.bold(`
480
+ Channel Tokens:`)),d.channels.telegram.enabled){let T=d.channels.telegram.token;T&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(T)?console.log(` Telegram: ${S.green("valid format")}`):console.log(T?` Telegram: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${S.red("not configured")}`)}if(d.channels.discord.enabled){let T=d.channels.discord.token;T&&T.length>=50&&/^[A-Za-z0-9._-]+$/.test(T)?console.log(` Discord: ${S.green("valid format")}`):console.log(T?` Discord: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${S.red("not configured")}`)}}l||console.log(S.bold(`
481
+ LLM Connectivity:`));let ae;try{ae=$e(d)}catch(T){w.llm={connected:!1,error:String(T)},w.ok=!1,w.warnings=h,console.log(l?JSON.stringify(w,null,2):` ${S.red("Failed to create provider: "+String(T))}`),process.exitCode=U.GENERAL_ERROR;return}try{let T=await ae.chat({messages:[{role:"user",content:"Reply with: OK"}],model:d.agents.defaults.model,maxTokens:16,temperature:0});if((T.content||"").toLowerCase().includes("error")){w.llm={connected:!1,error:T.content},w.ok=!1,w.warnings=h,console.log(l?JSON.stringify(w,null,2):` ${S.red("Failed: "+T.content)}`),process.exitCode=U.CONNECTIVITY_ERROR;return}w.llm={connected:!0},l||console.log(` ${S.green("Passed")}: ${T.content??"(empty response)"}`)}catch(T){w.llm={connected:!1,error:String(T)},w.ok=!1,w.warnings=h,console.log(l?JSON.stringify(w,null,2):` ${S.red("Failed: "+String(T))}`),process.exitCode=U.CONNECTIVITY_ERROR;return}if(w.warnings=h,l){console.log(JSON.stringify(w,null,2));return}if(h.length>0){console.log(S.bold(`
482
+ Warnings:`));for(let T of h)console.log(` ${S.yellow("\u26A0")} ${T}`)}console.log(S.green(`
483
+ Doctor check complete.`))}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(a=>{let l=a.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(l)){console.log(`Unknown OAuth provider: ${a}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${a} is not yet implemented in TypeScript port.`)}),e}Po(process.argv);var Uc=di();Uc.parseAsync(process.argv);