everclaw 0.3.15 → 0.3.17

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 va=Object.defineProperty;var Sa=(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 Pe=(o,e)=>()=>(o&&(e=o(o=0)),e);var $n=(o,e)=>{for(var t in e)va(o,t,{get:e[t],enumerable:!0})};import os from"node:fs";import Ze from"node:os";import be from"node:path";import{fileURLToPath as ka}from"node:url";function Ln(o=Ze.homedir()){return be.join(o,mt)}function is(o=Ze.homedir()){return be.join(o,mt,"workspace")}function as(o=Ze.homedir()){return be.join(o,mt,"config.json")}function We(o=Ze.homedir()){return be.join(o,mt,"logs")}function so(o=Ze.homedir()){return be.join(o,".config","systemd","user")}function io(o=Ze.homedir()){return be.join(o,"Library","LaunchAgents")}function On(o=Ze.homedir()){return be.join(so(o),"everclaw.service")}function Nn(o=Ze.homedir()){return be.join(io(o),"ai.everclaw.gateway.plist")}function Ca(){let o=ka(import.meta.url),e=be.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:be.resolve(e,"..")}function cs(...o){let e=be.resolve(ls,...o);if(!os.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function et(...o){let e=be.resolve(ls,...o);return os.existsSync(e)?e:null}var mt,pt,ss,ls,de=Pe(()=>{"use strict";mt=".everclaw",pt="~/.everclaw/config.json",ss=be.join("~",mt,"workspace");ls=Ca()});import Dn from"node:fs";import Ke from"node:path";import ao from"node:os";function tt(o){return Dn.mkdirSync(o,{recursive:!0}),o}function jn(){return tt(Ln(ao.homedir()))}function Z(o){let e=o?o.replace(/^~(?=$|[\\/])/,ao.homedir()):is(ao.homedir());return tt(Ke.resolve(e))}function ds(o){return o.replace(xa,"_").trim()}function ft(o,e=!1){let t=et("templates");if(!t)return[];let n=[],r=(i,a)=>{Dn.existsSync(a)||(tt(Ke.dirname(a)),i?Dn.copyFileSync(i,a):Dn.writeFileSync(a,"","utf8"),n.push(Ke.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(Ke.join(t,i),Ke.join(o,i));if(r(Ke.join(t,"memory","MEMORY.md"),Ke.join(o,"memory","MEMORY.md")),r(null,Ke.join(o,"memory","HISTORY.md")),tt(Ke.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var xa,je=Pe(()=>{"use strict";de();xa=/[<>:"/\\|?*]/g});function hs(){let o={};for(let e of fs)e.models.length>0&&(o[e.spec.name]=e.models);return o}function co(){return fs.map(o=>o.spec)}var fs,uo=Pe(()=>{"use strict";fs=[{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 It(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function tn(o){return`${$t}${It(o)}`}function ys(o,e){let t=It(e.startsWith($t)?e.slice($t.length):e);return o.customLlmProviders.find(n=>It(n.name)===t)??null}function La(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?ys(o,n):null}function ht(o){return!!o&&o.startsWith($t)}function Lt(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return ys(o,n);let r=La(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 nt(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Lt(o,t,e);return a?tn(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=It(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of en){let l=o.providers[a.name];if(s&&It(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of en){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(It(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of en){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Lt(o,t,e);return i?tn(i.name):null}function bs(o,e){let t=nt(o,e);if(t&&ht(t)){let n=Lt(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function Bn(o,e){let t=nt(o,e);if(!t)return null;if(ht(t))return Lt(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=en.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function Un(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($t)){let s=n.slice($t.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 en,$a,$t,me,Ot=Pe(()=>{"use strict";de();uo();en=co(),$a=Object.fromEntries(co().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),$t="custom:",me={agents:{defaults:{workspace:ss,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:$a,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,stealth:{enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}},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}},logging:{enabled:!0,level:"info",retentionHours:4,maxFileSizeMb:10,purgeIntervalMs:6e5},compaction:{enabled:!0,microCompactThresholdRatio:.6,autoCompactThresholdRatio:.8,keepRecentMessages:10,maxConsecutiveFailures:3}}});import Gn from"node:fs";import Oa from"node:path";function yt(){return as()}function Be(){return jn()}function ws(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]=ws(t[n],r):t[n]=r;return t}function Wn(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)=>Wn(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]&&Wn(t[i],n[i]))}function Da(o){return o.apiKey===""&&o.apiBase===null&&o.extraHeaders===null&&(o.models===void 0||o.models.length===0)}function vs(o,e,t=""){if(Na.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 Wn(o,e)?void 0:o;if(t==="providers"){let a=o,l=e,c={},d=!1;for(let[p,g]of Object.entries(a)){let x=l[p];x?Wn(g,x)||(c[p]=g,d=!0):Da(g)||(c[p]=g,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=vs(c,d,l);p!==void 0&&(s[a]=p,i=!0)}}return i?s:void 0}function ja(o,e=me){return vs(o,e)??{}}function _(o){let e=o??yt();if(!Gn.existsSync(e))return structuredClone(me);try{let t=Gn.readFileSync(e,"utf8"),n=JSON.parse(t),r=ws(structuredClone(me),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=me.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(me)}}function oe(o,e){let t=e??yt();Gn.mkdirSync(Oa.dirname(t),{recursive:!0});let n=ja(o);Gn.writeFileSync(t,JSON.stringify(n,null,2),"utf8")}function Ss(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(r=>r.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");let n=o.channels?.telegram?.groups?.allowedGroupIds;n!=null&&!Array.isArray(n)&&e.push(`Telegram groups.allowedGroupIds should be an array (e.g. ["${n}"]), got ${typeof n}`);for(let[r,s]of Object.entries(o.tools?.mcpServers??{}))!s.command&&!s.url&&e.push(`MCP server '${r}' has neither command nor URL configured`),s.command&&s.url&&e.push(`MCP server '${r}' has both command and URL \u2014 must use one`),s.toolTimeout!==void 0&&(!Number.isFinite(s.toolTimeout)||s.toolTimeout<=0)&&e.push(`MCP server '${r}' has invalid toolTimeout`);return e}var Na,Ue=Pe(()=>{"use strict";Ot();de();je();Na=new Set(["agents.defaults.model","agents.defaults.provider","gateway.port"])});function ce(o){if(!o)return 0;let e=typeof o=="string"?o:JSON.stringify(o);return Math.ceil(e.length/4)}function xs(o){let e=4;if(typeof o.content=="string")e+=ce(o.content);else if(Array.isArray(o.content))for(let t of o.content)t&&typeof t=="object"&&("text"in t&&typeof t.text=="string"&&(e+=ce(t.text)),"image_url"in t&&(e+=85));if(Array.isArray(o.tool_calls))for(let t of o.tool_calls)e+=ce(t);return o.tool_call_id&&(e+=10),o.name&&(e+=ce(o.name)),o.reasoning_content&&(e+=ce(o.reasoning_content)),e}function Je(o){let e=0;for(let t of o)e+=xs(t);return e+=o.length*3,e+3}function Kn(o,e){if(e){let n=e.providers?.[e.agents.defaults.provider]?.models?.find(r=>r.id.toLowerCase()===o.toLowerCase())?.capabilities;if(n?.contextWindow)return n.contextWindow;for(let r of e.customLlmProviders??[]){let s=r.models.find(i=>i.id.toLowerCase()===o.toLowerCase());if(s?.capabilities?.contextWindow)return s.capabilities.contextWindow}}let t=o.toLowerCase();for(let[n,r]of Object.entries(Ga))if(n.toLowerCase()===t||t.includes(n.toLowerCase()))return r;return Wa}function Dt(o,e){return Kn(o,e)-Ka}function fo(o,e,t,n){let r=Je(o),s=Dt(t,n);return r>=s*e}var Ga,Wa,Ka,jt=Pe(()=>{"use strict";Ga={"gpt-4.1":1047576,"gpt-4.1-mini":1047576,"gpt-4.1-nano":1047576,"gpt-4o":128e3,"gpt-4o-mini":128e3,"gpt-4-turbo":128e3,"gpt-4":8192,"gpt-3.5-turbo":16385,"claude-sonnet-4":2e5,"claude-sonnet-4-20250514":2e5,"claude-3-5-sonnet":2e5,"claude-3-5-sonnet-20241022":2e5,"claude-3-5-haiku":2e5,"claude-3-opus":2e5,"claude-3-sonnet":2e5,"claude-3-haiku":2e5,"gemini-2.5-pro":1e6,"gemini-2.0-flash":1e6,"gemini-1.5-pro":1e6,"gemini-1.5-flash":1e6,"deepseek-chat":64e3,"deepseek-reasoner":64e3,"grok-2":131072,"grok-2-mini":131072},Wa=128e3,Ka=16384});var Ds={};$n(Ds,{LocalProcessIsolationRunner:()=>ve,selectExecutionIsolationPolicy:()=>St});import{spawn as Ns}from"node:child_process";function St(o){return{...rl[o]}}var rl,ve,kt=Pe(()=>{"use strict";rl={"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."}};ve=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,g=(v,O)=>{let G=typeof v=="string"?v:v.toString("utf8"),I=t-Buffer.byteLength(O);return I<=0?O:O+G.slice(0,I)};s.stdout?.on("data",v=>{a=g(v,a)}),s.stderr?.on("data",v=>{l=g(v,l)});let x=null,y=v=>{c||(c=!0,d=v,p=v==="timeout",this.killChild(s,"SIGTERM"),x=setTimeout(()=>this.killChild(s,"SIGKILL"),250),x.unref?.())},u=()=>y("abort");e.signal?.aborted?u():e.signal?.addEventListener("abort",u,{once:!0});let b=n!=null?setTimeout(()=>y("timeout"),n):null;b?.unref?.();let T=await new Promise(v=>{let O=!1,G=I=>{O||(O=!0,v(I))};s.once("error",I=>{i.current=I,G({code:null,signal:null})}),s.once("close",(I,V)=>G({code:I,signal:V}))});return b&&clearTimeout(b),x&&clearTimeout(x),e.signal?.removeEventListener("abort",u),d==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:d,errorMessage:i.current.message}:T.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:T.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:T.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:d,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?Ns(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):Ns(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 Lr={};$n(Lr,{McpClientManager:()=>bn});import{Client as nc}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as rc}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as oc}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as sc}from"@modelcontextprotocol/sdk/client/sse.js";function ti(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var bn,wn=Pe(()=>{"use strict";bn=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(`
2
+ var ka=Object.defineProperty;var Ca=(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 Le=(o,e)=>()=>(o&&(e=o(o=0)),e);var $n=(o,e)=>{for(var t in e)ka(o,t,{get:e[t],enumerable:!0})};import is from"node:fs";import et from"node:os";import be from"node:path";import{fileURLToPath as xa}from"node:url";function On(o=et.homedir()){return be.join(o,pt)}function ls(o=et.homedir()){return be.join(o,pt,"workspace")}function cs(o=et.homedir()){return be.join(o,pt,"config.json")}function xe(o=et.homedir()){return be.join(o,pt,"logs")}function io(o=et.homedir()){return be.join(o,".config","systemd","user")}function ao(o=et.homedir()){return be.join(o,"Library","LaunchAgents")}function Nn(o=et.homedir()){return be.join(io(o),"everclaw.service")}function Dn(o=et.homedir()){return be.join(ao(o),"ai.everclaw.gateway.plist")}function Ta(){let o=xa(import.meta.url),e=be.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:be.resolve(e,"..")}function us(...o){let e=be.resolve(ds,...o);if(!is.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function tt(...o){let e=be.resolve(ds,...o);return is.existsSync(e)?e:null}var pt,ft,as,ds,ce=Le(()=>{"use strict";pt=".everclaw",ft="~/.everclaw/config.json",as=be.join("~",pt,"workspace");ds=Ta()});import jn from"node:fs";import Je from"node:path";import lo from"node:os";function nt(o){return jn.mkdirSync(o,{recursive:!0}),o}function Fn(){return nt(On(lo.homedir()))}function Z(o){let e=o?o.replace(/^~(?=$|[\\/])/,lo.homedir()):ls(lo.homedir());return nt(Je.resolve(e))}function gs(o){return o.replace(Ra,"_").trim()}function ht(o,e=!1){let t=tt("templates");if(!t)return[];let n=[],r=(i,a)=>{jn.existsSync(a)||(nt(Je.dirname(a)),i?jn.copyFileSync(i,a):jn.writeFileSync(a,"","utf8"),n.push(Je.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(Je.join(t,i),Je.join(o,i));if(r(Je.join(t,"memory","MEMORY.md"),Je.join(o,"memory","MEMORY.md")),r(null,Je.join(o,"memory","HISTORY.md")),nt(Je.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var Ra,Be=Le(()=>{"use strict";ce();Ra=/[<>:"/\\|?*]/g});function bs(){let o={};for(let e of ys)e.models.length>0&&(o[e.spec.name]=e.models);return o}function uo(){return ys.map(o=>o.spec)}var ys,go=Le(()=>{"use strict";ys=[{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 Lt(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function nn(o){return`${$t}${Lt(o)}`}function ws(o,e){let t=Lt(e.startsWith($t)?e.slice($t.length):e);return o.customLlmProviders.find(n=>Lt(n.name)===t)??null}function Na(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?ws(o,n):null}function yt(o){return!!o&&o.startsWith($t)}function Ot(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return ws(o,n);let r=Na(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 rt(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Ot(o,t,e);return a?nn(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=Lt(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of tn){let l=o.providers[a.name];if(s&&Lt(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of tn){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(Lt(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of tn){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Ot(o,t,e);return i?nn(i.name):null}function vs(o,e){let t=rt(o,e);if(t&&yt(t)){let n=Ot(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function Un(o,e){let t=rt(o,e);if(!t)return null;if(yt(t))return Ot(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=tn.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function Gn(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($t)){let s=n.slice($t.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 tn,Oa,$t,me,Nt=Le(()=>{"use strict";ce();go();tn=uo(),Oa=Object.fromEntries(uo().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),$t="custom:",me={agents:{defaults:{workspace:as,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:Oa,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,stealth:{enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}},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}},logging:{enabled:!0,level:"info",retentionHours:4,maxFileSizeMb:10,purgeIntervalMs:6e5},compaction:{enabled:!0,microCompactThresholdRatio:.6,autoCompactThresholdRatio:.8,keepRecentMessages:10,maxConsecutiveFailures:3}}});import Wn from"node:fs";import Da from"node:path";function bt(){return cs()}function Ge(){return Fn()}function Ss(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]=Ss(t[n],r):t[n]=r;return t}function Kn(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)=>Kn(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]&&Kn(t[i],n[i]))}function Fa(o){return o.apiKey===""&&o.apiBase===null&&o.extraHeaders===null&&(o.models===void 0||o.models.length===0)}function ks(o,e,t=""){if(ja.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 Kn(o,e)?void 0:o;if(t==="providers"){let a=o,l=e,c={},d=!1;for(let[p,g]of Object.entries(a)){let x=l[p];x?Kn(g,x)||(c[p]=g,d=!0):Fa(g)||(c[p]=g,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=ks(c,d,l);p!==void 0&&(s[a]=p,i=!0)}}return i?s:void 0}function Ba(o,e=me){return ks(o,e)??{}}function _(o){let e=o??bt();if(!Wn.existsSync(e))return structuredClone(me);try{let t=Wn.readFileSync(e,"utf8"),n=JSON.parse(t),r=Ss(structuredClone(me),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=me.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(me)}}function oe(o,e){let t=e??bt();Wn.mkdirSync(Da.dirname(t),{recursive:!0});let n=Ba(o);Wn.writeFileSync(t,JSON.stringify(n,null,2),"utf8")}function Cs(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(r=>r.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");let n=o.channels?.telegram?.groups?.allowedGroupIds;n!=null&&!Array.isArray(n)&&e.push(`Telegram groups.allowedGroupIds should be an array (e.g. ["${n}"]), got ${typeof n}`);for(let[r,s]of Object.entries(o.tools?.mcpServers??{}))!s.command&&!s.url&&e.push(`MCP server '${r}' has neither command nor URL configured`),s.command&&s.url&&e.push(`MCP server '${r}' has both command and URL \u2014 must use one`),s.toolTimeout!==void 0&&(!Number.isFinite(s.toolTimeout)||s.toolTimeout<=0)&&e.push(`MCP server '${r}' has invalid toolTimeout`);return e}var ja,We=Le(()=>{"use strict";Nt();ce();Be();ja=new Set(["agents.defaults.model","agents.defaults.provider","gateway.port"])});function de(o){if(!o)return 0;let e=typeof o=="string"?o:JSON.stringify(o);return Math.ceil(e.length/4)}function Rs(o){let e=4;if(typeof o.content=="string")e+=de(o.content);else if(Array.isArray(o.content))for(let t of o.content)t&&typeof t=="object"&&("text"in t&&typeof t.text=="string"&&(e+=de(t.text)),"image_url"in t&&(e+=85));if(Array.isArray(o.tool_calls))for(let t of o.tool_calls)e+=de(t);return o.tool_call_id&&(e+=10),o.name&&(e+=de(o.name)),o.reasoning_content&&(e+=de(o.reasoning_content)),e}function He(o){let e=0;for(let t of o)e+=Rs(t);return e+=o.length*3,e+3}function Jn(o,e){if(e){let n=e.providers?.[e.agents.defaults.provider]?.models?.find(r=>r.id.toLowerCase()===o.toLowerCase())?.capabilities;if(n?.contextWindow)return n.contextWindow;for(let r of e.customLlmProviders??[]){let s=r.models.find(i=>i.id.toLowerCase()===o.toLowerCase());if(s?.capabilities?.contextWindow)return s.capabilities.contextWindow}}let t=o.toLowerCase();for(let[n,r]of Object.entries(Ka))if(n.toLowerCase()===t||t.includes(n.toLowerCase()))return r;return Ja}function jt(o,e){return Jn(o,e)-Ha}function ho(o,e,t,n){let r=He(o),s=jt(t,n);return r>=s*e}var Ka,Ja,Ha,Ft=Le(()=>{"use strict";Ka={"gpt-4.1":1047576,"gpt-4.1-mini":1047576,"gpt-4.1-nano":1047576,"gpt-4o":128e3,"gpt-4o-mini":128e3,"gpt-4-turbo":128e3,"gpt-4":8192,"gpt-3.5-turbo":16385,"claude-sonnet-4":2e5,"claude-sonnet-4-20250514":2e5,"claude-3-5-sonnet":2e5,"claude-3-5-sonnet-20241022":2e5,"claude-3-5-haiku":2e5,"claude-3-opus":2e5,"claude-3-sonnet":2e5,"claude-3-haiku":2e5,"gemini-2.5-pro":1e6,"gemini-2.0-flash":1e6,"gemini-1.5-pro":1e6,"gemini-1.5-flash":1e6,"deepseek-chat":64e3,"deepseek-reasoner":64e3,"grok-2":131072,"grok-2-mini":131072},Ja=128e3,Ha=16384});var Fs={};$n(Fs,{LocalProcessIsolationRunner:()=>ve,selectExecutionIsolationPolicy:()=>kt});import{spawn as js}from"node:child_process";function kt(o){return{...sl[o]}}var sl,ve,Ct=Le(()=>{"use strict";sl={"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."}};ve=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,g=(v,O)=>{let G=typeof v=="string"?v:v.toString("utf8"),I=t-Buffer.byteLength(O);return I<=0?O:O+G.slice(0,I)};s.stdout?.on("data",v=>{a=g(v,a)}),s.stderr?.on("data",v=>{l=g(v,l)});let x=null,y=v=>{c||(c=!0,d=v,p=v==="timeout",this.killChild(s,"SIGTERM"),x=setTimeout(()=>this.killChild(s,"SIGKILL"),250),x.unref?.())},u=()=>y("abort");e.signal?.aborted?u():e.signal?.addEventListener("abort",u,{once:!0});let b=n!=null?setTimeout(()=>y("timeout"),n):null;b?.unref?.();let T=await new Promise(v=>{let O=!1,G=I=>{O||(O=!0,v(I))};s.once("error",I=>{i.current=I,G({code:null,signal:null})}),s.once("close",(I,V)=>G({code:I,signal:V}))});return b&&clearTimeout(b),x&&clearTimeout(x),e.signal?.removeEventListener("abort",u),d==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:d,errorMessage:i.current.message}:T.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:T.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:T.code,signal:T.signal,failureAttribution:T.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:d,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?js(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):js(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 Or={};$n(Or,{McpClientManager:()=>wn});import{Client as oc}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as sc}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as ic}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as ac}from"@modelcontextprotocol/sdk/client/sse.js";function ri(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var wn,vn=Le(()=>{"use strict";wn=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
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 nc({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=ti(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${ti(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 rc({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 oc(s,{requestInit:{headers:a}})}catch{return new sc(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 oi={};$n(oi,{aggressiveMicroCompact:()=>Dr,estimateMicroCompactSavings:()=>ri,microCompact:()=>Nr,wouldMicroCompactHelp:()=>ni});function Nr(o,e=10){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=typeof a.name=="string"?a.name:"";if(!Po.has(l))continue;let c=a.content;if(typeof c!="string"||c===Ye)continue;let d=ce(c);t[i]={...a,content:Ye},n+=d-ce(Ye),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function Dr(o,e=4){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=a.content;if(typeof l!="string"||l===Ye)continue;let c=ce(l);t[i]={...a,content:Ye},n+=c-ce(Ye),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function ni(o,e=10){let t=Math.max(0,o.length-e);for(let n=0;n<t;n++){let r=o[n];if(!r||r.role!=="tool")continue;let s=typeof r.name=="string"?r.name:"";if(!Po.has(s))continue;let i=r.content;if(typeof i=="string"&&i!==Ye&&i.length>100)return!0}return!1}function ri(o,e=10){let t=0,n=Math.max(0,o.length-e);for(let r=0;r<n;r++){let s=o[r];if(!s||s.role!=="tool")continue;let i=typeof s.name=="string"?s.name:"";if(!Po.has(i))continue;let a=s.content;typeof a=="string"&&a!==Ye&&(t+=ce(a)-ce(Ye))}return t}var Po,Ye,vn=Pe(()=>{"use strict";jt();Po=new Set(["read_file","exec","grep_search","list_dir","web_search","web_fetch","write_file","edit_file","glob_search","list_directory","Read","Execute","Grep","Glob","LS","FetchUrl","WebSearch","exa___web_search_exa","exa___web_fetch_exa","context7___resolve-library-id","context7___query-docs","deepwiki___read_wiki_structure","deepwiki___read_wiki_contents","deepwiki___ask_question"]),Ye="[Tool result cleared to save context]"});var Tn,Rn,An=Pe(()=>{"use strict";Tn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(Tn||{}),Rn=(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))(Rn||{})});var Mi={};$n(Mi,{ToolGuardEngine:()=>En});import Uc from"node:fs";function Gc(){if(Hr)return Hr;try{let o=et("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Uc.readFileSync(o,"utf8"),t=JSON.parse(e);return Hr=t,t}catch{return[]}}function Kc(o){if(o.length===0)return"SAFE";let e=Bo.SAFE;for(let t of o){let n=Bo[t.severity]??Bo.SAFE;n<e&&(e=n)}return Wc[e]??"SAFE"}var Hr,Bo,Wc,En,Uo=Pe(()=>{"use strict";Ue();An();de();Hr=null;Bo={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Wc={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};En=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,Hr=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 g=p.guard({toolName:e,params:t});g.length>0&&r.push(...g),s.push(p.name)}catch(g){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(g)}`),!a){let x={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(g)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(x)}}let l=performance.now()-n,c=Kc(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=Gc(),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 gs from"node:path";import{createRequire as Ta}from"node:module";function le(){return new Date().toISOString()}je();var Ra=Ta(import.meta.url),Fn=null;function Aa(){return Fn||(Fn=Ra("node:sqlite").DatabaseSync,Fn)}function ms(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 us=[{version:1,name:"create-operational-state-tables",sql:`
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 oc({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=ri(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${ri(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 sc({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 ic(s,{requestInit:{headers:a}})}catch{return new ac(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 ii={};$n(ii,{aggressiveMicroCompact:()=>jr,estimateMicroCompactSavings:()=>si,microCompact:()=>Dr,wouldMicroCompactHelp:()=>oi});function Dr(o,e=10){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=typeof a.name=="string"?a.name:"";if(!Mo.has(l))continue;let c=a.content;if(typeof c!="string"||c===Xe)continue;let d=de(c);t[i]={...a,content:Xe},n+=d-de(Xe),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function jr(o,e=4){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=a.content;if(typeof l!="string"||l===Xe)continue;let c=de(l);t[i]={...a,content:Xe},n+=c-de(Xe),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function oi(o,e=10){let t=Math.max(0,o.length-e);for(let n=0;n<t;n++){let r=o[n];if(!r||r.role!=="tool")continue;let s=typeof r.name=="string"?r.name:"";if(!Mo.has(s))continue;let i=r.content;if(typeof i=="string"&&i!==Xe&&i.length>100)return!0}return!1}function si(o,e=10){let t=0,n=Math.max(0,o.length-e);for(let r=0;r<n;r++){let s=o[r];if(!s||s.role!=="tool")continue;let i=typeof s.name=="string"?s.name:"";if(!Mo.has(i))continue;let a=s.content;typeof a=="string"&&a!==Xe&&(t+=de(a)-de(Xe))}return t}var Mo,Xe,Sn=Le(()=>{"use strict";Ft();Mo=new Set(["read_file","exec","grep_search","list_dir","web_search","web_fetch","write_file","edit_file","glob_search","list_directory","Read","Execute","Grep","Glob","LS","FetchUrl","WebSearch","exa___web_search_exa","exa___web_fetch_exa","context7___resolve-library-id","context7___query-docs","deepwiki___read_wiki_structure","deepwiki___read_wiki_contents","deepwiki___ask_question"]),Xe="[Tool result cleared to save context]"});var Rn,An,En=Le(()=>{"use strict";Rn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(Rn||{}),An=(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))(An||{})});var Li={};$n(Li,{ToolGuardEngine:()=>_n});import Wc from"node:fs";function Kc(){if(qr)return qr;try{let o=tt("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Wc.readFileSync(o,"utf8"),t=JSON.parse(e);return qr=t,t}catch{return[]}}function Hc(o){if(o.length===0)return"SAFE";let e=Uo.SAFE;for(let t of o){let n=Uo[t.severity]??Uo.SAFE;n<e&&(e=n)}return Jc[e]??"SAFE"}var qr,Uo,Jc,_n,Go=Le(()=>{"use strict";We();En();ce();qr=null;Uo={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Jc={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};_n=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,qr=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 g=p.guard({toolName:e,params:t});g.length>0&&r.push(...g),s.push(p.name)}catch(g){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(g)}`),!a){let x={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(g)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(x)}}let l=performance.now()-n,c=Hc(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=Kc(),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 ps from"node:path";import{createRequire as Aa}from"node:module";function le(){return new Date().toISOString()}Be();var Ea=Aa(import.meta.url),Bn=null;function _a(){return Bn||(Bn=Ea("node:sqlite").DatabaseSync,Bn)}function fs(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 ms=[{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,44 +68,44 @@ var va=Object.defineProperty;var Sa=(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 Ea(o=jn()){return gs.join(o,"runtime","operations.sqlite")}var lo=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 ms(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
71
+ `}];function Pa(o=Fn()){return ps.join(o,"runtime","operations.sqlite")}var co=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 fs(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 _a(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 Ma(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 Fe(o={}){let e=o.dbPath??Ea(o.dataDir);tt(gs.dirname(e));let t=Aa(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),_a(n);let r=us.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 us)i.has(a.version)||ms(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,le())});return new lo(n,e)}var Pa=new Set(["agent","gateway"]);function Ma(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function Ia(o){let e=Ma(o);return!!e&&Pa.has(e)}function ps(o,e={}){if(!Ia(o))return!1;let t=e.openStorage??Fe,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}}Ue();Ot();import ue from"node:fs";import ma from"node:readline/promises";import{stdin as pa,stdout as fa}from"node:process";import{Command as pu,Option as rs}from"commander";import ye from"prompts";import S from"chalk";function Fa(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 ks(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 nn(o,e,t){let n=Fa(e),r=ks(o,n);return t?ks(r,t):r}de();de();import Nt from"node:fs";import Cs from"node:path";import Ba from"node:os";var Ua="gateway.pid";function go(){return Cs.join(Ba.homedir(),mt,Ua)}function mo(o){let e=go();Nt.mkdirSync(Cs.dirname(e),{recursive:!0}),Nt.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Ie(){let o=go();if(!Nt.existsSync(o))return null;try{let e=Nt.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function $e(o){let e=go();try{if(!Nt.existsSync(e))return;if(o!==void 0){let t=Ie();if(t&&t.pid!==o)return}Nt.unlinkSync(e)}catch{}}function Me(o){try{return process.kill(o,0),!0}catch{return!1}}async function po(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Me(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Me(o)}function bt(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(" ")}je();var rn=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 wt=class{inbound=new rn;outbound=new rn;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 mi from"node:path";import As from"node:fs";import zn from"node:path";import Es from"node:os";jt();import on from"node:fs";import Jn from"node:path";var Ts=1e3,Ja=250,Hn=`
80
- ... (truncated for archival)`;function Rs(o){return Math.max(0,Math.floor(o*4))}function Ha(o,e){if(e<=0)return"";let t=Rs(e);if(o.length<=t)return o;let n=Math.max(0,t-Hn.length);return`${Hn}${o.slice(-n)}`}function qa(o,e){if(e<=0||o.length===0)return{text:"",omittedLines:o.length};let t=Rs(e),n=[],r=0,s=0;for(let i=o.length-1;i>=0;i--){let a=o[i],l=n.length?1:0,c=t-r-l;if(c<=0){s=i+1;break}if(a.length<=c){n.unshift(a),r+=a.length+l;continue}let d=Math.max(0,c-Hn.length);n.unshift(`${Hn}${a.slice(-d)}`),r=t,s=i;break}return{text:n.join(`
81
- `),omittedLines:s}}var za=[{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"]}}}];function Va(o){let e=o.match(/```(?:json)?\s*([\s\S]*?)```/i);if(e?.[1])return e[1].trim();let t=o.indexOf("{"),n=o.lastIndexOf("}");return t===-1||n===-1||n<t?null:o.slice(t,n+1).trim()}function Ya(o){if(!o)return null;let e=Va(o.trim());if(!e)return null;try{let t=JSON.parse(e);if(!t||typeof t!="object"||Array.isArray(t))return null;let n=t;return n.history_entry==null&&n.memory_update==null?null:n}catch{return null}}var sn=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Jn.join(e,"memory");this.memoryDir=t?Jn.join(n,t):n,on.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Jn.join(this.memoryDir,"MEMORY.md"),this.historyFile=Jn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return on.existsSync(this.memoryFile)?on.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){on.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){on.appendFileSync(this.historyFile,`${e.trim()}
79
+ `)}function Ue(o={}){let e=o.dbPath??Pa(o.dataDir);nt(ps.dirname(e));let t=_a(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),Ma(n);let r=ms.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 ms)i.has(a.version)||fs(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,le())});return new co(n,e)}var Ia=new Set(["agent","gateway"]);function La(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function $a(o){let e=La(o);return!!e&&Ia.has(e)}function hs(o,e={}){if(!$a(o))return!1;let t=e.openStorage??Ue,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}}We();Nt();import ue from"node:fs";import fa from"node:readline/promises";import{stdin as ha,stdout as ya}from"node:process";import{Command as Su,Option as ss}from"commander";import ye from"prompts";import S from"chalk";function Ua(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 xs(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 rn(o,e,t){let n=Ua(e),r=xs(o,n);return t?xs(r,t):r}ce();ce();import Dt from"node:fs";import Ts from"node:path";import Ga from"node:os";var Wa="gateway.pid";function mo(){return Ts.join(Ga.homedir(),pt,Wa)}function po(o){let e=mo();Dt.mkdirSync(Ts.dirname(e),{recursive:!0}),Dt.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Oe(){let o=mo();if(!Dt.existsSync(o))return null;try{let e=Dt.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function Te(o){let e=mo();try{if(!Dt.existsSync(e))return;if(o!==void 0){let t=Oe();if(t&&t.pid!==o)return}Dt.unlinkSync(e)}catch{}}function $e(o){try{return process.kill(o,0),!0}catch{return!1}}async function fo(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!$e(o))return!0;await new Promise(n=>setTimeout(n,200))}return!$e(o)}function wt(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(" ")}Be();var on=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 vt=class{inbound=new on;outbound=new on;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 fi from"node:path";import _s from"node:fs";import Vn from"node:path";import Ps from"node:os";Ft();import sn from"node:fs";import Hn from"node:path";var As=1e3,qa=250,qn=`
80
+ ... (truncated for archival)`;function Es(o){return Math.max(0,Math.floor(o*4))}function za(o,e){if(e<=0)return"";let t=Es(e);if(o.length<=t)return o;let n=Math.max(0,t-qn.length);return`${qn}${o.slice(-n)}`}function Va(o,e){if(e<=0||o.length===0)return{text:"",omittedLines:o.length};let t=Es(e),n=[],r=0,s=0;for(let i=o.length-1;i>=0;i--){let a=o[i],l=n.length?1:0,c=t-r-l;if(c<=0){s=i+1;break}if(a.length<=c){n.unshift(a),r+=a.length+l;continue}let d=Math.max(0,c-qn.length);n.unshift(`${qn}${a.slice(-d)}`),r=t,s=i;break}return{text:n.join(`
81
+ `),omittedLines:s}}var Ya=[{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"]}}}];function Xa(o){let e=o.match(/```(?:json)?\s*([\s\S]*?)```/i);if(e?.[1])return e[1].trim();let t=o.indexOf("{"),n=o.lastIndexOf("}");return t===-1||n===-1||n<t?null:o.slice(t,n+1).trim()}function Qa(o){if(!o)return null;let e=Xa(o.trim());if(!e)return null;try{let t=JSON.parse(e);if(!t||typeof t!="object"||Array.isArray(t))return null;let n=t;return n.history_entry==null&&n.memory_update==null?null:n}catch{return null}}var an=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Hn.join(e,"memory");this.memoryDir=t?Hn.join(n,t):n,sn.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Hn.join(this.memoryDir,"MEMORY.md"),this.historyFile=Hn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return sn.existsSync(this.memoryFile)?sn.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){sn.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){sn.appendFileSync(this.historyFile,`${e.trim()}
82
82
 
83
83
  `,"utf8")}getMemoryContext(){let e=this.readLongTerm();return e?`## Long-term Memory
84
84
  ${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 D of a)D._type==="anchor"?c.push(D):d.push(D);let p=[];for(let D of c)p.push(`[ANCHOR] ${D.name}: ${D.summary??"(no summary)"}`);for(let D of d){if(!D.content&&!D._full_content)continue;let Y=Array.isArray(D.tools_used)&&D.tools_used.length?` [tools: ${D.tools_used.join(", ")}]`:"",j=D._full_content??D.content;p.push(`[${String(D.timestamp??"?").slice(0,16)}] ${String(D.role).toUpperCase()}${Y}: ${String(j)}`)}let g=this.readLongTerm(),x=p.join(`
85
- `),y=g||"(empty)",u="## Conversation to Process",b=x,T=ce(`Process this conversation and call the save_memory tool with your consolidation.
85
+ `),y=g||"(empty)",u="## Conversation to Process",b=x,T=de(`Process this conversation and call the save_memory tool with your consolidation.
86
86
 
87
87
  ## Current Long-term Memory
88
88
 
89
89
 
90
90
  ## Conversation to Process
91
- `),v=ce(g||"(empty)"),O=ce(x),G=T+v+O,I=Kn(n),V=Math.floor(I*.9);if(G>V){let D=Math.max(1,V-T),Y=Math.min(v,Math.max(Ja,Math.floor(D*.3))),j=Math.min(v,Math.max(0,D-Ts),Y),J=Math.max(Ts,D-j);if(j<v&&(y=Ha(y,j)),J<O){let U=qa(p,J);b=U.text,u=U.text!==x?`## Conversation to Process (truncated, most recent ${p.length-U.omittedLines} entries)`:"## Conversation to Process"}}let N=`Process this conversation and call the save_memory tool with your consolidation. If tool calling is unavailable, respond with JSON only using the shape {"history_entry":"...","memory_update":"..."}.
91
+ `),v=de(g||"(empty)"),O=de(x),G=T+v+O,I=Jn(n),V=Math.floor(I*.9);if(G>V){let D=Math.max(1,V-T),Y=Math.min(v,Math.max(qa,Math.floor(D*.3))),j=Math.min(v,Math.max(0,D-As),Y),J=Math.max(As,D-j);if(j<v&&(y=za(y,j)),J<O){let U=Va(p,J);b=U.text,u=U.text!==x?`## Conversation to Process (truncated, most recent ${p.length-U.omittedLines} entries)`:"## Conversation to Process"}}let N=`Process this conversation and call the save_memory tool with your consolidation. If tool calling is unavailable, respond with JSON only using the shape {"history_entry":"...","memory_update":"..."}.
92
92
 
93
93
  ## Current Long-term Memory
94
94
  ${y}
95
95
 
96
96
  ${u}
97
- ${b}`;try{let D=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool. If tool calling is unavailable, respond with JSON only containing history_entry and memory_update."},{role:"user",content:N}],tools:za,toolChoice:"required"}),j=D.toolCalls[0]?.arguments??Ya(D.content);if(!j)return!1;let J=j.history_entry,U=j.memory_update;if(J!=null&&this.appendHistory(typeof J=="string"?J:JSON.stringify(J)),U!=null){let f=typeof U=="string"?U:JSON.stringify(U);f!==g&&this.writeLongTerm(f)}let L=s?0:e.messages.length-l,K=e.messages.slice(0,L),B=-1;for(let f=K.length-1;f>=0;f--)if(K[f]?._type==="anchor"){B=f;break}return B!==-1?e.lastConsolidated=B+1:e.lastConsolidated=L,!0}catch{return!1}}};de();import an from"node:fs";import ln from"node:path";var ho=/^[a-z0-9][a-z0-9-]*$/;function qn(o){return ho.test(o)}var He=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=ln.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??cs("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}
97
+ ${b}`;try{let D=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool. If tool calling is unavailable, respond with JSON only containing history_entry and memory_update."},{role:"user",content:N}],tools:Ya,toolChoice:"required"}),j=D.toolCalls[0]?.arguments??Qa(D.content);if(!j)return!1;let J=j.history_entry,U=j.memory_update;if(J!=null&&this.appendHistory(typeof J=="string"?J:JSON.stringify(J)),U!=null){let f=typeof U=="string"?U:JSON.stringify(U);f!==g&&this.writeLongTerm(f)}let $=s?0:e.messages.length-l,K=e.messages.slice(0,$),B=-1;for(let f=K.length-1;f>=0;f--)if(K[f]?._type==="anchor"){B=f;break}return B!==-1?e.lastConsolidated=B+1:e.lastConsolidated=$,!0}catch{return!1}}};ce();import ln from"node:fs";import cn from"node:path";var yo=/^[a-z0-9][a-z0-9-]*$/;function zn(o){return yo.test(o)}var qe=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=cn.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??us("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}
98
98
 
99
99
  ${this.stripFrontmatter(r.content)}`)}return t.join(`
100
100
 
101
101
  ---
102
102
 
103
103
  `)}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(`
104
- `)}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(!an.existsSync(t))continue;let r=an.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=ln.join(t,s.name,"SKILL.md");an.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=an.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=ln.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}'`):ho.test(l)||a.push(`frontmatter name '${l}' must match ${ho}`):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(`---
104
+ `)}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(!ln.existsSync(t))continue;let r=ln.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=cn.join(t,s.name,"SKILL.md");ln.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=ln.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=cn.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}'`):yo.test(l)||a.push(`frontmatter name '${l}' must match ${yo}`):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(`---
105
105
  `)||e.startsWith(`---\r
106
- `)))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(ln.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>an.existsSync(ln.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}
106
+ `)))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(cn.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>ln.existsSync(cn.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}
107
107
 
108
- 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 vt=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new sn(e),this.skills=new He(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 sn(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
108
+ 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 St=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new an(e),this.skills=new qe(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 an(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
109
109
 
110
110
  ${i}`);let a=this.skills.getAlwaysSkills();if(a.length){let c=this.skills.loadSkillsForContext(a);c&&n.push(`# Active Skills
111
111
 
@@ -124,47 +124,47 @@ ${l}`),n.join(`
124
124
  You are everclaw, a helpful AI assistant.
125
125
 
126
126
  ## Runtime
127
- ${Es.platform()} ${Es.arch()}, Node ${process.version}
127
+ ${Ps.platform()} ${Ps.arch()}, Node ${process.version}
128
128
 
129
129
  ## Workspace
130
130
  Your workspace is at: ${this.workspace}
131
- - Long-term memory: ${zn.join(this.workspace,"memory","MEMORY.md")}
132
- - History log: ${zn.join(this.workspace,"memory","HISTORY.md")}
133
- - Custom skills: ${zn.join(this.workspace,"skills","{skill-name}","SKILL.md")}
131
+ - Long-term memory: ${Vn.join(this.workspace,"memory","MEMORY.md")}
132
+ - History log: ${Vn.join(this.workspace,"memory","HISTORY.md")}
133
+ - Custom skills: ${Vn.join(this.workspace,"skills","{skill-name}","SKILL.md")}
134
134
 
135
135
  ## Guidelines
136
136
  - State intent before tool calls, but never claim results before receiving them.
137
137
  - Before modifying a file, read it first.
138
- - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=zn.join(this.workspace,t);As.existsSync(n)&&e.push(`## ${t}
138
+ - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=Vn.join(this.workspace,t);_s.existsSync(n)&&e.push(`## ${t}
139
139
 
140
- ${As.readFileSync(n,"utf8")}`)}return e.join(`
140
+ ${_s.readFileSync(n,"utf8")}`)}return e.join(`
141
141
 
142
142
  `)}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}
143
143
  ${s.join(`
144
144
  `)}`}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}buildNotificationContext(e){let t=e.status==="completed"?"\u2713":"\u2717";if(e.kind==="cron_completed"||e.kind==="subagent_completed"||e.kind==="subagent_failed"){let n=[`[${t}] ${e.kind==="cron_completed"?"Cron Job":"Subagent"}: ${e.label}`,`Task: ${e.originalTask}`,`Status: ${e.status}`];e.result&&n.push(`Result: ${e.result}`),e.error&&n.push(`Error: ${e.error}`);let r=e.kind==="cron_completed"?"cron job":"subagent";return n.push("",`The ${r} has finished. Acknowledge this result briefly and continue with any follow-up work if needed.`),n.join(`
145
145
  `)}return`[${t}] Task: ${e.label}
146
- Status: ${e.status}`}};import{randomUUID as ql}from"node:crypto";import Gl from"node:path";import{randomUUID as Ps}from"node:crypto";import Za from"cron-parser";function wo(o){return o??"builtin"}function _s(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function rt(){return _s()}function Vn(o,e,t,n){let r=wo(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 Xa(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:wo(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 we(o){return{...o,source:"builtin"}}var yo=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:wo(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=_s();for(let i of this.extensions.values()){for(let a of i.tools??[])Vn("tool",e,i,a);for(let a of i.channels??[])Vn("channel",t,i,a);for(let a of i.jobs??[])Vn("job",n,i,a);for(let a of i.commands??[])Vn("command",r,i,a);for(let a of i.lifecycle??[])Xa(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 Qa(o){return o instanceof Error?o.message:String(o)}var bo=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${Qa(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function qe(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new bo(e,n.extension,n.source,n.contribution.name,r)}}function vo(o){let e=new yo;for(let t of o)e.register(t);return e.compose()}function cn(){let o=new Error("Operation aborted");return o.name="AbortError",o}function se(o){return o instanceof Error&&o.name==="AbortError"}function te(o){if(o?.aborted)throw cn()}function Ce(){return Date.now()}var el="default";function Ft(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 Za.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Ms(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 dn=class{constructor(e={},t,n=rt()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??el}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Fe({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,
146
+ Status: ${e.status}`}};import{randomUUID as Vl}from"node:crypto";import Kl from"node:path";import{randomUUID as Is}from"node:crypto";import tl from"cron-parser";function vo(o){return o??"builtin"}function Ms(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function ot(){return Ms()}function Yn(o,e,t,n){let r=vo(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 Za(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:vo(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 we(o){return{...o,source:"builtin"}}var bo=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:vo(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=Ms();for(let i of this.extensions.values()){for(let a of i.tools??[])Yn("tool",e,i,a);for(let a of i.channels??[])Yn("channel",t,i,a);for(let a of i.jobs??[])Yn("job",n,i,a);for(let a of i.commands??[])Yn("command",r,i,a);for(let a of i.lifecycle??[])Za(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 el(o){return o instanceof Error?o.message:String(o)}var wo=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${el(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function ze(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new wo(e,n.extension,n.source,n.contribution.name,r)}}function So(o){let e=new bo;for(let t of o)e.register(t);return e.compose()}function dn(){let o=new Error("Operation aborted");return o.name="AbortError",o}function se(o){return o instanceof Error&&o.name==="AbortError"}function te(o){if(o?.aborted)throw dn()}function Re(){return Date.now()}var nl="default";function Bt(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 tl.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Ls(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 un=class{constructor(e={},t,n=ot()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??nl}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Ue({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,
147
147
  next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
148
148
  FROM cron_jobs
149
149
  WHERE workspace = ?
150
150
  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 (
151
151
  workspace, job_id, name, enabled, schedule_json, payload_json,
152
152
  state_json, next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
153
- ) 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-Ce())))}async onTimer(){let e=this.loadStore(),t=Ce(),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=Ce(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await qe(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 qe(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":se(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=Ce(),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=Ft(e.schedule,Ce())}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:Ft(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=Ce(),n={id:Ps().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:Ft({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=Ce();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();Ms(e.schedule);let n=Ce(),r={id:Ps().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:Ft(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=Ce(),r.state.nextRunAtMs=t?Ft(r.schedule,Ce()):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&&(Ms(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Ft(t.schedule,Ce()):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=Ce(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import Is from"node:fs";import tl from"node:path";var nl=[{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"]}}}],un=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 tl.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!Is.existsSync(this.heartbeatFile))return null;let e=Is.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.
153
+ ) 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-Re())))}async onTimer(){let e=this.loadStore(),t=Re(),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=Re(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await ze(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 ze(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":se(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=Re(),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=Bt(e.schedule,Re())}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:Bt(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=Re(),n={id:Is().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:Bt({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=Re();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();Ls(e.schedule);let n=Re(),r={id:Is().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:Bt(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=Re(),r.state.nextRunAtMs=t?Bt(r.schedule,Re()):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&&(Ls(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Bt(t.schedule,Re()):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=Re(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import $s from"node:fs";import rl from"node:path";var ol=[{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"]}}}],gn=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 rl.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!$s.existsSync(this.heartbeatFile))return null;let e=$s.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.
154
154
 
155
- ${e}`}],tools:nl});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=>{se(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 z=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 Yn=class extends z{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:
155
+ ${e}`}],tools:ol});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=>{se(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 z=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 Xn=class extends z{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:
156
156
  ${t.map(n=>`- ${n.name} (id: ${n.id}, ${n.schedule.kind})`).join(`
157
- `)}`:"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 xe from"node:fs";import Bt from"node:path";import Le from"node:fs";import pe from"node:path";function $s(o){let e=pe.resolve(o);for(;e!=="/"&&e!==".";)try{return Le.lstatSync(e),e}catch{let t=pe.dirname(e);if(t===e)break;e=t}return e||"/"}function Ls(o,e){let t=pe.resolve(o),n=pe.resolve(e),r=n.endsWith(pe.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+pe.sep);if(!Le.existsSync(r))return s;try{let i=r;try{i=Le.realpathSync.native(r)}catch{}if(Le.existsSync(t)){let c=Le.realpathSync.native(t);return c===i||c.startsWith(i+pe.sep)}let a=$s(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=Le.realpathSync.native(a);if(c===i||c.startsWith(i+pe.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=pe.dirname(l);if(c===l)break;try{if(Le.lstatSync(c).isSymbolicLink()){let p=Le.realpathSync.native(c);if(p!==i&&!p.startsWith(i+pe.sep))return!1}}catch{}l=c}return s}catch{return!1}}function Os(o,e){let t=pe.resolve(o),n=pe.resolve(e);if(!Ls(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=pe.dirname(t),s=$s(r),i=n;try{Le.existsSync(n)&&(i=Le.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=Le.realpathSync.native(s);if(a!==i&&!a.startsWith(i+pe.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 Ge(o,e){if(!Ls(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function tr(o,e,t,n=!1){let r=o.startsWith("~")?Bt.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Bt.isAbsolute(r)?r:e?Bt.join(e,r):r,i=Bt.resolve(s);if(t)try{n?Os(i,t):Ge(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var Xn=class extends z{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=tr(String(t.path),this.workspace,this.allowedDir);return xe.existsSync(r)?xe.statSync(r).isFile()?xe.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)}`}}},Qn=class extends z{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=tr(String(t.path),this.workspace,this.allowedDir,!0);xe.mkdirSync(Bt.dirname(r),{recursive:!0});let s=String(t.content??"");return xe.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},Zn=class extends z{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=tr(String(t.path),this.workspace,this.allowedDir,!0);if(!xe.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=xe.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.`:(xe.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)}`}}},er=class extends z{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=tr(String(t.path),this.workspace,this.allowedDir);if(!xe.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!xe.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=xe.readdirSync(r).sort().map(i=>{let a=Bt.join(r,i);return`${xe.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
158
- `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var nr=class extends z{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 So from"node:path";kt();var rr=class extends z{constructor(t=60,n,r=!1,s="",i=new ve,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=So.resolve(a),c=So.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;te(n?.signal);let a=St("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${So.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 cn();if(d.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=d.stdout?`${d.stdout}${d.status==="failed"?`
157
+ `)}`:"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 Ae from"node:fs";import Ut from"node:path";import Ne from"node:fs";import pe from"node:path";function Os(o){let e=pe.resolve(o);for(;e!=="/"&&e!==".";)try{return Ne.lstatSync(e),e}catch{let t=pe.dirname(e);if(t===e)break;e=t}return e||"/"}function Ns(o,e){let t=pe.resolve(o),n=pe.resolve(e),r=n.endsWith(pe.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+pe.sep);if(!Ne.existsSync(r))return s;try{let i=r;try{i=Ne.realpathSync.native(r)}catch{}if(Ne.existsSync(t)){let c=Ne.realpathSync.native(t);return c===i||c.startsWith(i+pe.sep)}let a=Os(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=Ne.realpathSync.native(a);if(c===i||c.startsWith(i+pe.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=pe.dirname(l);if(c===l)break;try{if(Ne.lstatSync(c).isSymbolicLink()){let p=Ne.realpathSync.native(c);if(p!==i&&!p.startsWith(i+pe.sep))return!1}}catch{}l=c}return s}catch{return!1}}function Ds(o,e){let t=pe.resolve(o),n=pe.resolve(e);if(!Ns(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=pe.dirname(t),s=Os(r),i=n;try{Ne.existsSync(n)&&(i=Ne.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=Ne.realpathSync.native(s);if(a!==i&&!a.startsWith(i+pe.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 Ke(o,e){if(!Ns(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function nr(o,e,t,n=!1){let r=o.startsWith("~")?Ut.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Ut.isAbsolute(r)?r:e?Ut.join(e,r):r,i=Ut.resolve(s);if(t)try{n?Ds(i,t):Ke(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var Qn=class extends z{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=nr(String(t.path),this.workspace,this.allowedDir);return Ae.existsSync(r)?Ae.statSync(r).isFile()?Ae.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)}`}}},Zn=class extends z{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=nr(String(t.path),this.workspace,this.allowedDir,!0);Ae.mkdirSync(Ut.dirname(r),{recursive:!0});let s=String(t.content??"");return Ae.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},er=class extends z{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=nr(String(t.path),this.workspace,this.allowedDir,!0);if(!Ae.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=Ae.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.`:(Ae.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)}`}}},tr=class extends z{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=nr(String(t.path),this.workspace,this.allowedDir);if(!Ae.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!Ae.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=Ae.readdirSync(r).sort().map(i=>{let a=Ut.join(r,i);return`${Ae.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
158
+ `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var rr=class extends z{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 ko from"node:path";Ct();var or=class extends z{constructor(t=60,n,r=!1,s="",i=new ve,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=ko.resolve(a),c=ko.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;te(n?.signal);let a=kt("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${ko.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 dn();if(d.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=d.stdout?`${d.stdout}${d.status==="failed"?`
159
159
  `:""}`:"";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 g=d.stderr.trim()?`STDERR:
160
160
  ${d.stderr}
161
161
  `:"",x=d.status==="failed"&&typeof d.exitCode=="number"?`
162
162
  Exit code: ${d.exitCode}`:"",y=d.status==="failed"&&d.signal?`
163
163
  Signal: ${d.signal}`:"",u=`${p}${g}${x}${y}`.trim();return u?u.length>1e4?`${u.slice(0,1e4)}
164
- ... (truncated, ${u.length-1e4} more chars)`:u:d.status==="failed"?d.errorMessage?`Error executing command: ${d.errorMessage}`:"Error executing command":"(no output)"}};var js={general:{name:"general",description:"General-purpose subagent with full tool access",systemPromptSuffix:"Complete the assigned task using all available tools."},researcher:{name:"researcher",description:"Read-only researcher \u2014 no file modifications",systemPromptSuffix:"Research and report findings. Do NOT modify any files.",allowedTools:["read_file","list_files","search","web_search","web_fetch","session.info","session.search"]},coder:{name:"coder",description:"Code modification specialist",systemPromptSuffix:"Implement the requested code changes.",deniedTools:["web_search","web_fetch"]}};function ko(o){return js[o]}function Fs(){return Object.values(js)}var or=class extends z{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."},context:{type:"string",enum:["fresh","fork"],description:"Context mode: 'fresh' (default) starts with minimal context, 'fork' inherits parent conversation for prompt cache reuse."},type:{type:"string",description:`Agent type defining available tools and behavior. Available types: ${Fs().map(t=>`'${t.name}'`).join(", ")}. Defaults to 'general'.`}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";parentSystemPrompt;setContext(t,n,r=`${t}:${n}`,s){this.originChannel=t,this.originChatId=n,this.sessionKey=r,this.parentSystemPrompt=s}async execute(t,n){let r=t.context??"fresh",s=t.type??"general",i={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey,contextMode:r,agentType:s};return t.model!=null&&(i.model=String(t.model)),t.provider!=null&&(i.providerName=String(t.provider)),r==="fork"&&this.parentSystemPrompt&&(i.parentSystemPrompt=this.parentSystemPrompt),this.manager.spawn(i)}};var sr=class extends z{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 ir=class extends z{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+=vt.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 ar=class extends z{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 ol,existsSync as sl}from"node:fs";import{join as ne}from"node:path";import il from"node:http";import{homedir as al}from"node:os";import ll from"node:net";import Us from"ws";var cl={existsSync:sl,readFileSync:ol},Bs=cl;var dl=il,Gs=dl;var ul=1;var gl="/tmp/chrome-debug-profile";function ml(o){let e=o??process.platform,t=al(),n=ne(gl,"DevToolsActivePort");switch(e){case"darwin":return[n,ne(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),ne(t,"Library/Application Support/Chromium/DevToolsActivePort"),ne(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),ne(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),ne(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||ne(t,".config");return[n,ne(r,"google-chrome","DevToolsActivePort"),ne(r,"chromium","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),ne(r,"microsoft-edge","DevToolsActivePort"),ne(r,"vivaldi","DevToolsActivePort"),ne(t,".config","google-chrome","DevToolsActivePort"),ne(t,".config","chromium","DevToolsActivePort"),ne(t,"snap","chromium","common","chromium","DevToolsActivePort"),ne(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),ne(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||ne(t,"AppData","Local");return[n,ne(r,"Google","Chrome","User Data","DevToolsActivePort"),ne(r,"Chromium","User Data","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),ne(r,"Microsoft","Edge","User Data","DevToolsActivePort"),ne(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function cr(o){return dr(o)?.port}function dr(o){let e=ml(o);for(let t of e)try{if(!Bs.existsSync(t))continue;let r=Bs.readFileSync(t,"utf-8").split(`
165
- `),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 pl(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=Gs.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 fl(o,e="127.0.0.1"){return new Promise(t=>{let n=new ll.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 hl(o){return new Promise(e=>{try{let t=new Us(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 Ut(o=9222){let e=dr(),t=e?.port??o;if(await fl(t)){for(let r=0;r<2;r++){try{let s=await pl(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 hl(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=Gs.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 gn(o){let t=dr()?.browserWsPath;if(!t)return[];let n=await lr.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 Ws(o,e){let n=dr()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await lr.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 lr=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 Us(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!==ul)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 yl}from"node:child_process";import{createConnection as bl}from"node:net";import{tmpdir as wl}from"node:os";import{join as Js,dirname as vl}from"node:path";import{unlink as Sl,unlinkSync as kl,mkdirSync as Cl,existsSync as ur}from"node:fs";import Ct from"node:fs";function Gt(o){let e="electron"in process.versions,t=o;try{t=Ct.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!Ct.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!Ct.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(Ct.existsSync(a)){try{n=Ct.realpathSync(a)}catch{n=a}r=!1}else if(Ct.existsSync(l)){try{n=Ct.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 xl=null,Tl=null,Rl=null,Al=!1;function mn(){return Tl??process.platform}function El(){return xl??yl}function _l(){return Rl??bl}function Pl(o,e){let t=mn(),n=e??wl(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:Js(n,`airclaw-daemon-${r}.sock`)}function Ks(o,e){let t=o.split(`
166
- `),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 Wt=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=Pl(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(mn()==="win32"||ur(r)){let x={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,x);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),mn()!=="win32"&&ur(r))try{kl(r)}catch{}}}let i=vl(r);if(!ur(i)&&mn()!=="win32")try{Cl(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),Al)return;let l=Js(import.meta.dirname,"daemon-worker"),{file:c,args:d,env:p}=Gt(l),g=El()(c,[...d,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=g,g.on("exit",()=>{this.cleanupDaemon(e)}),g.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((x,y)=>{let u=setTimeout(()=>{y(new Error("Daemon startup timeout"))},1e4),b=T=>{T.toString("utf8").includes("READY")&&(clearTimeout(u),g.stdout?.off("data",b),x())};g.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=_l()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=Ks(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})+`
167
- `;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=Ks(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"));mn()!=="win32"&&ur(t.socketPath)&&Sl(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as Ml,mkdirSync as Il,existsSync as $l}from"node:fs";import{dirname as Ll,join as gr}from"node:path";import{tmpdir as Ol}from"node:os";var Co={minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},xt=class extends z{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
164
+ ... (truncated, ${u.length-1e4} more chars)`:u:d.status==="failed"?d.errorMessage?`Error executing command: ${d.errorMessage}`:"Error executing command":"(no output)"}};var Bs={general:{name:"general",description:"General-purpose subagent with full tool access",systemPromptSuffix:"Complete the assigned task using all available tools."},researcher:{name:"researcher",description:"Read-only researcher \u2014 no file modifications",systemPromptSuffix:"Research and report findings. Do NOT modify any files.",allowedTools:["read_file","list_files","search","web_search","web_fetch","session.info","session.search"]},coder:{name:"coder",description:"Code modification specialist",systemPromptSuffix:"Implement the requested code changes.",deniedTools:["web_search","web_fetch"]}};function Co(o){return Bs[o]}function Us(){return Object.values(Bs)}var sr=class extends z{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."},context:{type:"string",enum:["fresh","fork"],description:"Context mode: 'fresh' (default) starts with minimal context, 'fork' inherits parent conversation for prompt cache reuse."},type:{type:"string",description:`Agent type defining available tools and behavior. Available types: ${Us().map(t=>`'${t.name}'`).join(", ")}. Defaults to 'general'.`}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";parentSystemPrompt;setContext(t,n,r=`${t}:${n}`,s){this.originChannel=t,this.originChatId=n,this.sessionKey=r,this.parentSystemPrompt=s}async execute(t,n){let r=t.context??"fresh",s=t.type??"general",i={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey,contextMode:r,agentType:s};return t.model!=null&&(i.model=String(t.model)),t.provider!=null&&(i.providerName=String(t.provider)),r==="fork"&&this.parentSystemPrompt&&(i.parentSystemPrompt=this.parentSystemPrompt),this.manager.spawn(i)}};var ir=class extends z{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 ar=class extends z{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+=St.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 lr=class extends z{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 il,existsSync as al}from"node:fs";import{join as ne}from"node:path";import ll from"node:http";import{homedir as cl}from"node:os";import dl from"node:net";import Ws from"ws";var ul={existsSync:al,readFileSync:il},Gs=ul;var gl=ll,Ks=gl;var ml=1;var pl="/tmp/chrome-debug-profile";function fl(o){let e=o??process.platform,t=cl(),n=ne(pl,"DevToolsActivePort");switch(e){case"darwin":return[n,ne(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),ne(t,"Library/Application Support/Chromium/DevToolsActivePort"),ne(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),ne(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),ne(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||ne(t,".config");return[n,ne(r,"google-chrome","DevToolsActivePort"),ne(r,"chromium","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),ne(r,"microsoft-edge","DevToolsActivePort"),ne(r,"vivaldi","DevToolsActivePort"),ne(t,".config","google-chrome","DevToolsActivePort"),ne(t,".config","chromium","DevToolsActivePort"),ne(t,"snap","chromium","common","chromium","DevToolsActivePort"),ne(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),ne(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||ne(t,"AppData","Local");return[n,ne(r,"Google","Chrome","User Data","DevToolsActivePort"),ne(r,"Chromium","User Data","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),ne(r,"Microsoft","Edge","User Data","DevToolsActivePort"),ne(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function dr(o){return ur(o)?.port}function ur(o){let e=fl(o);for(let t of e)try{if(!Gs.existsSync(t))continue;let r=Gs.readFileSync(t,"utf-8").split(`
165
+ `),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 hl(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=Ks.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 yl(o,e="127.0.0.1"){return new Promise(t=>{let n=new dl.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 bl(o){return new Promise(e=>{try{let t=new Ws(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 Gt(o=9222){let e=ur(),t=e?.port??o;if(await yl(t)){for(let r=0;r<2;r++){try{let s=await hl(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 bl(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=Ks.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 mn(o){let t=ur()?.browserWsPath;if(!t)return[];let n=await cr.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 Js(o,e){let n=ur()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await cr.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 cr=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 Ws(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!==ml)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 wl}from"node:child_process";import{createConnection as vl}from"node:net";import{tmpdir as Sl}from"node:os";import{join as qs,dirname as kl}from"node:path";import{unlink as Cl,unlinkSync as xl,mkdirSync as Tl,existsSync as gr}from"node:fs";import xt from"node:fs";function Wt(o){let e="electron"in process.versions,t=o;try{t=xt.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!xt.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!xt.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(xt.existsSync(a)){try{n=xt.realpathSync(a)}catch{n=a}r=!1}else if(xt.existsSync(l)){try{n=xt.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 Rl=null,Al=null,El=null,_l=!1;function pn(){return Al??process.platform}function Pl(){return Rl??wl}function Ml(){return El??vl}function Il(o,e){let t=pn(),n=e??Sl(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:qs(n,`airclaw-daemon-${r}.sock`)}function Hs(o,e){let t=o.split(`
166
+ `),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 Kt=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=Il(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(pn()==="win32"||gr(r)){let x={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,x);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),pn()!=="win32"&&gr(r))try{xl(r)}catch{}}}let i=kl(r);if(!gr(i)&&pn()!=="win32")try{Tl(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),_l)return;let l=qs(import.meta.dirname,"daemon-worker"),{file:c,args:d,env:p}=Wt(l),g=Pl()(c,[...d,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=g,g.on("exit",()=>{this.cleanupDaemon(e)}),g.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((x,y)=>{let u=setTimeout(()=>{y(new Error("Daemon startup timeout"))},1e4),b=T=>{T.toString("utf8").includes("READY")&&(clearTimeout(u),g.stdout?.off("data",b),x())};g.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=Ml()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=Hs(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})+`
167
+ `;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=Hs(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"));pn()!=="win32"&&gr(t.socketPath)&&Cl(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as Ll,mkdirSync as $l,existsSync as Ol}from"node:fs";import{dirname as Nl,join as mr}from"node:path";import{tmpdir as Dl}from"node:os";var xo={minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},Tt=class extends z{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
168
168
 
169
169
  Core Commands:
170
170
  - status: Check Chrome connectivity, version, and remote debugging status
@@ -199,7 +199,7 @@ Examples:
199
199
  - chrome_session clickxy --target "ABC123" --x 100 --y 200
200
200
  - chrome_session type --target "ABC123" --text "Hello World"
201
201
  - chrome_session loadall --target "ABC123" --selector "button.load-more" --interval 500
202
- - 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??Co.minChromeVersion,daemonIdleTimeoutS:e.daemonIdleTimeoutS??Co.daemonIdleTimeoutS,targetPrefixLength:e.targetPrefixLength??Co.targetPrefixLength,...e.stealth?{stealth:e.stealth}:{}},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Wt.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 Ut();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=cr();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 gn(e)}catch{t=await gn(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=cr();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 Ws(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=cr();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 gn(t)}catch{n=await gn(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.config.stealth?.enabled&&await this.daemonManager.sendCommand(e,"setStealthConfig",{stealth:this.config.stealth}),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=gr(this.workspace,e):t=gr(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=gr(this.workspace,e):t=gr(Ol(),`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=Ll(e);$l(n)||Il(n,{recursive:!0});let r=Buffer.from(t,"base64");Ml(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var pn=class extends z{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 ae from"node:fs";import fn from"node:path";import{randomUUID as Nl}from"node:crypto";var Dl="automations",jl="index.json";function Fl(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function xo(o){return fn.join(o,Dl)}function Hs(o){return fn.join(xo(o),jl)}function mr(o,e){return fn.join(xo(o),e)}function To(o,e){return fn.join(mr(o,e),"rule.json")}function Ro(o,e){return fn.join(mr(o,e),"script.js")}function Ao(o){let e=xo(o);ae.existsSync(e)||ae.mkdirSync(e,{recursive:!0})}function pr(o){Ao(o);let e=Hs(o);if(!ae.existsSync(e))return{rules:[]};try{let t=ae.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=Te(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=Te(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&fr(o,n),n}catch{return{rules:[]}}}function fr(o,e){Ao(o);let t=Hs(o),n=`${t}.tmp`;ae.writeFileSync(n,JSON.stringify(e,null,2)),ae.renameSync(n,t)}function Kt(o){return pr(o).rules}function Te(o,e){let t=To(o,e);if(!ae.existsSync(t))return null;try{let n=ae.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Ro(o,e);return ae.existsSync(s)&&(r.scriptContent=ae.readFileSync(s,"utf-8")),r}catch{return null}}function hr(o,e){Ao(o);let t=Fl(e.name)||Nl().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=mr(o,t);ae.existsSync(s)||ae.mkdirSync(s,{recursive:!0});let i=To(o,t);ae.writeFileSync(i,JSON.stringify(r,null,2));let a=qs(r),l=Ro(o,t);ae.writeFileSync(l,a);let c=pr(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),fr(o,c),r}function yr(o,e,t){let n=Te(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=To(o,e);if(ae.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=qs(s),d=Ro(o,e);ae.writeFileSync(d,c)}let a=pr(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,fr(o,a)}return s}function Jt(o,e){let t=mr(o,e);if(!ae.existsSync(t))return!1;ae.rmSync(t,{recursive:!0,force:!0});let n=pr(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(fr(o,n),!0):!1}function qs(o){let e=new Date().toISOString();return`// Automation: ${o.name}
202
+ - 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??xo.minChromeVersion,daemonIdleTimeoutS:e.daemonIdleTimeoutS??xo.daemonIdleTimeoutS,targetPrefixLength:e.targetPrefixLength??xo.targetPrefixLength,...e.stealth?{stealth:e.stealth}:{}},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Kt.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 Gt();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=dr();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 mn(e)}catch{t=await mn(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=dr();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 Js(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=dr();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 mn(t)}catch{n=await mn(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.config.stealth?.enabled&&await this.daemonManager.sendCommand(e,"setStealthConfig",{stealth:this.config.stealth}),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=mr(this.workspace,e):t=mr(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=mr(this.workspace,e):t=mr(Dl(),`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=Nl(e);Ol(n)||$l(n,{recursive:!0});let r=Buffer.from(t,"base64");Ll(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var fn=class extends z{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 ae from"node:fs";import hn from"node:path";import{randomUUID as jl}from"node:crypto";var Fl="automations",Bl="index.json";function Ul(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function To(o){return hn.join(o,Fl)}function zs(o){return hn.join(To(o),Bl)}function pr(o,e){return hn.join(To(o),e)}function Ro(o,e){return hn.join(pr(o,e),"rule.json")}function Ao(o,e){return hn.join(pr(o,e),"script.js")}function Eo(o){let e=To(o);ae.existsSync(e)||ae.mkdirSync(e,{recursive:!0})}function fr(o){Eo(o);let e=zs(o);if(!ae.existsSync(e))return{rules:[]};try{let t=ae.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=Ee(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=Ee(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&hr(o,n),n}catch{return{rules:[]}}}function hr(o,e){Eo(o);let t=zs(o),n=`${t}.tmp`;ae.writeFileSync(n,JSON.stringify(e,null,2)),ae.renameSync(n,t)}function Jt(o){return fr(o).rules}function Ee(o,e){let t=Ro(o,e);if(!ae.existsSync(t))return null;try{let n=ae.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Ao(o,e);return ae.existsSync(s)&&(r.scriptContent=ae.readFileSync(s,"utf-8")),r}catch{return null}}function yr(o,e){Eo(o);let t=Ul(e.name)||jl().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=pr(o,t);ae.existsSync(s)||ae.mkdirSync(s,{recursive:!0});let i=Ro(o,t);ae.writeFileSync(i,JSON.stringify(r,null,2));let a=Vs(r),l=Ao(o,t);ae.writeFileSync(l,a);let c=fr(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),hr(o,c),r}function br(o,e,t){let n=Ee(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=Ro(o,e);if(ae.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=Vs(s),d=Ao(o,e);ae.writeFileSync(d,c)}let a=fr(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,hr(o,a)}return s}function Ht(o,e){let t=pr(o,e);if(!ae.existsSync(t))return!1;ae.rmSync(t,{recursive:!0,force:!0});let n=fr(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(hr(o,n),!0):!1}function Vs(o){let e=new Date().toISOString();return`// Automation: ${o.name}
203
203
  // Tool: ${o.toolType??"auto-detect"}
204
204
  // Generated: ${e}
205
205
  // Description: ${o.description}
@@ -220,9 +220,9 @@ fetch(URL, { method: 'POST' })
220
220
  else console.error('Failed:', r.error);
221
221
  })
222
222
  .catch(e => console.error('Could not reach everclaw:', e.message));
223
- `}je();var zs={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"}},hn=o=>new Promise(e=>setTimeout(e,o)),Ht=class extends z{constructor(t,n,r){super();this.browserTool=n;this.stealthConfig=r;this.workspace=Z(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=Kt(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=Te(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 g={name:i,description:a,steps:l,tags:c};return d&&(g.toolType=d),p=yr(this.workspace,s,g),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let g={name:i,description:a,steps:l,tags:c,source:"conversation"};return d&&(g.toolType=d),p=hr(this.workspace,g),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?Jt(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=Te(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}l.stealth?.preDelay&&await hn(l.stealth.preDelay),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);if(s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`),this.stealthConfig?.enabled){let[g,x]=this.stealthConfig.interStepDelay;await hn(g+Math.random()*(x-g))}}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(`
223
+ `}Be();var Ys={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"}},yn=o=>new Promise(e=>setTimeout(e,o)),qt=class extends z{constructor(t,n,r){super();this.browserTool=n;this.stealthConfig=r;this.workspace=Z(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=Jt(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=Ee(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 g={name:i,description:a,steps:l,tags:c};return d&&(g.toolType=d),p=br(this.workspace,s,g),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let g={name:i,description:a,steps:l,tags:c,source:"conversation"};return d&&(g.toolType=d),p=yr(this.workspace,g),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?Ht(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=Ee(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}l.stealth?.preDelay&&await yn(l.stealth.preDelay),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);if(s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`),this.stealthConfig?.enabled){let[g,x]=this.stealthConfig.interStepDelay;await yn(g+Math.random()*(x-g))}}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(`
224
224
  `)}}return s.push(`Automation '${t.name}' completed successfully.`),s.join(`
225
- `)}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 hn(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=zs[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??"",t.stealth?.typingSpeed&&(l.typingSpeed=t.stealth.typingSpeed);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 hn(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=zs[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let g={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(g.tabId=r.tabId),c==="chrome_session"&&r.target&&(g.target=r.target);let x=await this.browserTool.execute(g);if(this.isAssertionPassing(x,c))return}catch{}if(Date.now()-l>=s)break;await hn(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var br=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}excludeByNames(e){let t=new Set(e),n=new o;n.guardEngine=this.guardEngine;for(let[r,s]of this.tools)t.has(r)||n.register(s);return n}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(te(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(`
225
+ `)}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 yn(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=Ys[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??"",t.stealth?.typingSpeed&&(l.typingSpeed=t.stealth.typingSpeed);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 yn(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=Ys[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let g={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(g.tabId=r.tabId),c==="chrome_session"&&r.target&&(g.target=r.target);let x=await this.browserTool.execute(g);if(this.isAssertionPassing(x,c))return}catch{}if(Date.now()-l>=s)break;await yn(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var wr=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}excludeByNames(e){let t=new Set(e),n=new o;n.guardEngine=this.guardEngine;for(let[r,s]of this.tools)t.has(r)||n.register(s);return n}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(te(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(`
226
226
  `);return{kind:"error",content:`Security: Tool call blocked. The tool '${e}' was denied by the security guard.
227
227
 
228
228
  Findings:
@@ -230,10 +230,10 @@ ${l}`,retryable:!1}}}let s=r.validateParams(t);if(s.length)return{kind:"error",c
230
230
 
231
231
  [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return te(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(se(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
232
232
 
233
- [Analyze the error above and try a different approach.]`,retryable:!0}}}};function Vs(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Bl(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
233
+ [Analyze the error above and try a different approach.]`,retryable:!0}}}};function Xs(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Gl(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
234
234
 
235
- `).trim()}function Ul(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 wr=class extends z{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{te(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((g,x)=>{p.push(`${x+1}. ${g.title??""}`),p.push(` ${g.url??""}`),g.description&&p.push(` ${g.description}`)}),p.join(`
236
- `)}catch(a){if(se(a))throw a;return`Error: ${String(a)}`}}},vr=class extends z{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]=Ul(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{te(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="",g="raw";if(d.includes("application/json"))p=JSON.stringify(await c.json(),null,2),g="json";else{let u=await c.text();d.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(u.slice(0,256))?(p=s==="text"?Vs(u):Bl(Vs(u)),g="html"):p=u}let x=p.length>i,y=x?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:g,truncated:x,length:y.length,text:y})}catch(c){if(se(c))throw c;return JSON.stringify({error:String(c),url:r})}}};kt();function ze(o){return Gl.resolve(o.workspace)}function Sr(o){let e=ze(o);return o.restrictToWorkspace?e:void 0}function Wl(o){let e=[we({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new Xn(ze(t),Sr(t))},{name:"write_file",create:t=>new Qn(ze(t),Sr(t))},{name:"edit_file",create:t=>new Zn(ze(t),Sr(t))},{name:"list_dir",create:t=>new er(ze(t),Sr(t))}]}),we({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new rr(t.execConfig?.timeout??60,ze(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new ve,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),we({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new wr(t.braveApiKey??null)},{name:"web_fetch",create:()=>new vr}]})];return o.bus&&e.push(we({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 nr(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(we({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 or(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey,t.turn.systemPrompt),n}}]})),o.cronService&&e.push(we({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 Yn(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(we({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 ir;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 ar;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 sr;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(we({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new xt(t.chromeSessionConfig,ze(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(we({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 pn(t.browserRelay)}}]})),e.push(we({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new pn(t.browserRelay):t.chromeSessionConfig?.enabled?new xt(t.chromeSessionConfig,ze(t),!!t.restrictToWorkspace):void 0;return new Ht(ze(t),n,t.chromeSessionConfig?.stealth)}}]})),e}function Kl(o){return vo(Wl(o))}function kr(o){let e=new br,t=Kl(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function Jl(o){let e=[we({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new dn({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??rt())}]})];return o.heartbeat&&e.push(we({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new un(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 Hl(o){return vo(Jl(o))}function Ve(o){let e=Hl(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 dn))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 un))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}var Cr=class{tasks=new Map;order=[];register(e,t,n,r){let s=new Date().toISOString(),i={id:e,type:t,label:n,sessionKey:r,createdAt:s,status:"pending",startedAt:null,completedAt:null,result:null,error:null};return this.tasks.set(e,i),this.order.push(e),this.enforceLimit(),i}transition(e,t,n,r){let s=this.tasks.get(e);if(!s)return;let i=new Date().toISOString(),a={status:t};t==="running"&&s.startedAt===null&&(a.startedAt=i),this.isTerminal(t)&&(a.completedAt=i,n!==void 0&&(a.result=n),r!==void 0&&(a.error=r)),Object.assign(s,a)}get(e){return this.tasks.get(e)}getBySession(e){return[...this.tasks.values()].filter(t=>t.sessionKey===e)}getRunning(){return[...this.tasks.values()].filter(e=>e.status==="running")}getPending(){return[...this.tasks.values()].filter(e=>e.status==="pending")}getAll(){return[...this.tasks.values()].map(e=>({...e}))}isTerminal(e){return e==="completed"||e==="failed"||e==="killed"}prune(e=36e5){let t=Date.now(),n=[];for(let r of this.tasks.values())if(this.isTerminal(r.status)&&r.completedAt){let s=new Date(r.completedAt).getTime();t-s>e&&n.push(r.id)}for(let r of n){this.tasks.delete(r);let s=this.order.indexOf(r);s!==-1&&this.order.splice(s,1)}return n.length}enforceLimit(){for(;this.order.length>100;){let e=this.order.shift();if(!e)continue;let t=this.tasks.get(e);if(t)if(this.isTerminal(t.status))this.tasks.delete(e);else{this.order.unshift(e);break}}}count(){return this.tasks.size}countByStatus(){let e={pending:0,running:0,completed:0,failed:0,killed:0};for(let t of this.tasks.values())e[t.status]++;return e}};kt();var Ys="EVERCLAW_SUBAGENT_RESULT ";function Xs(o,e){let t=new Date().toLocaleString(),n=e??"You are operating as a subagent spawned by the main agent to complete a specific task. Stay focused and concise. Complete the assigned task and report your findings.";return o?`${o}
235
+ `).trim()}function Wl(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 vr=class extends z{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{te(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((g,x)=>{p.push(`${x+1}. ${g.title??""}`),p.push(` ${g.url??""}`),g.description&&p.push(` ${g.description}`)}),p.join(`
236
+ `)}catch(a){if(se(a))throw a;return`Error: ${String(a)}`}}},Sr=class extends z{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]=Wl(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{te(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="",g="raw";if(d.includes("application/json"))p=JSON.stringify(await c.json(),null,2),g="json";else{let u=await c.text();d.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(u.slice(0,256))?(p=s==="text"?Xs(u):Gl(Xs(u)),g="html"):p=u}let x=p.length>i,y=x?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:g,truncated:x,length:y.length,text:y})}catch(c){if(se(c))throw c;return JSON.stringify({error:String(c),url:r})}}};Ct();function Ve(o){return Kl.resolve(o.workspace)}function kr(o){let e=Ve(o);return o.restrictToWorkspace?e:void 0}function Jl(o){let e=[we({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new Qn(Ve(t),kr(t))},{name:"write_file",create:t=>new Zn(Ve(t),kr(t))},{name:"edit_file",create:t=>new er(Ve(t),kr(t))},{name:"list_dir",create:t=>new tr(Ve(t),kr(t))}]}),we({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new or(t.execConfig?.timeout??60,Ve(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new ve,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),we({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new vr(t.braveApiKey??null)},{name:"web_fetch",create:()=>new Sr}]})];return o.bus&&e.push(we({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 rr(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(we({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 sr(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey,t.turn.systemPrompt),n}}]})),o.cronService&&e.push(we({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 Xn(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(we({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 ar;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 lr;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 ir;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(we({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new Tt(t.chromeSessionConfig,Ve(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(we({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 fn(t.browserRelay)}}]})),e.push(we({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new fn(t.browserRelay):t.chromeSessionConfig?.enabled?new Tt(t.chromeSessionConfig,Ve(t),!!t.restrictToWorkspace):void 0;return new qt(Ve(t),n,t.chromeSessionConfig?.stealth)}}]})),e}function Hl(o){return So(Jl(o))}function Cr(o){let e=new wr,t=Hl(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function ql(o){let e=[we({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new un({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??ot())}]})];return o.heartbeat&&e.push(we({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new gn(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 zl(o){return So(ql(o))}function Ye(o){let e=zl(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 un))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 gn))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}var xr=class{tasks=new Map;order=[];register(e,t,n,r){let s=new Date().toISOString(),i={id:e,type:t,label:n,sessionKey:r,createdAt:s,status:"pending",startedAt:null,completedAt:null,result:null,error:null};return this.tasks.set(e,i),this.order.push(e),this.enforceLimit(),i}transition(e,t,n,r){let s=this.tasks.get(e);if(!s)return;let i=new Date().toISOString(),a={status:t};t==="running"&&s.startedAt===null&&(a.startedAt=i),this.isTerminal(t)&&(a.completedAt=i,n!==void 0&&(a.result=n),r!==void 0&&(a.error=r)),Object.assign(s,a)}get(e){return this.tasks.get(e)}getBySession(e){return[...this.tasks.values()].filter(t=>t.sessionKey===e)}getRunning(){return[...this.tasks.values()].filter(e=>e.status==="running")}getPending(){return[...this.tasks.values()].filter(e=>e.status==="pending")}getAll(){return[...this.tasks.values()].map(e=>({...e}))}isTerminal(e){return e==="completed"||e==="failed"||e==="killed"}prune(e=36e5){let t=Date.now(),n=[];for(let r of this.tasks.values())if(this.isTerminal(r.status)&&r.completedAt){let s=new Date(r.completedAt).getTime();t-s>e&&n.push(r.id)}for(let r of n){this.tasks.delete(r);let s=this.order.indexOf(r);s!==-1&&this.order.splice(s,1)}return n.length}enforceLimit(){for(;this.order.length>100;){let e=this.order.shift();if(!e)continue;let t=this.tasks.get(e);if(t)if(this.isTerminal(t.status))this.tasks.delete(e);else{this.order.unshift(e);break}}}count(){return this.tasks.size}countByStatus(){let e={pending:0,running:0,completed:0,failed:0,killed:0};for(let t of this.tasks.values())e[t.status]++;return e}};Ct();var Qs="EVERCLAW_SUBAGENT_RESULT ";function Zs(o,e){let t=new Date().toLocaleString(),n=e??"You are operating as a subagent spawned by the main agent to complete a specific task. Stay focused and concise. Complete the assigned task and report your findings.";return o?`${o}
237
237
 
238
238
  ---
239
239
 
@@ -245,7 +245,7 @@ ${n}`:`# Subagent
245
245
 
246
246
  Current Time: ${t}
247
247
 
248
- ${n}`}async function Eo(o){let e=kr({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig}),t=o.definition;t?.allowedTools&&t.allowedTools.length>0?e=e.filterByNames(t.allowedTools):t?.deniedTools&&t.deniedTools.length>0&&(e=e.excludeByNames(t.deniedTools));let n=t?.systemPromptSuffix,r;if(o.contextMode==="fork"&&o.existingMessages?.length){let i=n?`# Subagent Mode
248
+ ${n}`}async function _o(o){let e=Cr({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig}),t=o.definition;t?.allowedTools&&t.allowedTools.length>0?e=e.filterByNames(t.allowedTools):t?.deniedTools&&t.deniedTools.length>0&&(e=e.excludeByNames(t.deniedTools));let n=t?.systemPromptSuffix,r;if(o.contextMode==="fork"&&o.existingMessages?.length){let i=n?`# Subagent Mode
249
249
 
250
250
  ${n}`:`# Subagent Mode
251
251
 
@@ -253,7 +253,7 @@ You are operating as a subagent spawned by the main agent to complete a specific
253
253
 
254
254
  ---
255
255
 
256
- ${i}`}:a),r.push({role:"user",content:o.task})}else o.contextMode==="inherit-system"&&o.parentSystemPrompt?r=[{role:"system",content:Xs(o.parentSystemPrompt,n)},{role:"user",content:o.task}]:r=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:Xs(void 0,n)},{role:"user",content:o.task}];let s="Task completed but no final response was generated.";for(let i=0;i<15;i++){te(o.signal);let a=await o.provider.chat({messages:r,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(te(o.signal),a.toolCalls.length){r.push({role:"assistant",content:a.content??"",tool_calls:a.toolCalls.map(l=>({id:l.id,type:"function",function:{name:l.name,arguments:JSON.stringify(l.arguments)}}))});for(let l of a.toolCalls){te(o.signal);let c=await e.execute(l.name,l.arguments,o.signal?{signal:o.signal}:{});te(o.signal);let d=typeof c=="object"&&"kind"in c?c.content??String(c):String(c);r.push({role:"tool",tool_call_id:l.id,name:l.name,content:d})}continue}s=a.content??s;break}return s}function zl(){let o=process.argv[1]??"";return Gt(o)}function Vl(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 Yl(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(Ys));if(e)try{return JSON.parse(e.slice(Ys.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:Vl(o),failureAttribution:o.failureAttribution}}var xr=class{constructor(e=new ve,t=zl){this.runner=e;this.resolveCommand=t}async execute(e){if(St("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 Yl(s)}},Tr=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,n=e.contextMode??"fresh";if(n==="fork"&&e.sessionKey)if(!this.sessionManager)console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`);else{let a=this.sessionManager.getOrCreate(e.sessionKey);a&&(t=a.fork().getHistory())}let r=e.agentType?ko(e.agentType):void 0,s={...e,provider:e.provider,existingMessages:t,contextMode:n,...e.parentSystemPrompt?{parentSystemPrompt:e.parentSystemPrompt}:{},...r?{definition:r}:{}};return{status:"completed",finalResult:await Eo(s)}}catch(t){return se(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},Rr=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;taskTracker=new Cr;getTaskTracker(){return this.taskTracker}getTaskSnapshot(){return this.taskTracker.prune(),this.taskTracker.getAll()}async spawn(e){let t=ql().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),this.taskTracker.register(t,"subagent",n,e.sessionKey);let i=e.mode??"process",a=e.agentType?ko(e.agentType):void 0,l=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName,e.contextMode,e.parentSystemPrompt,a).finally(()=>{this.running.delete(t),this.controllers.delete(t);let c=this.sessionTasks.get(e.sessionKey);c&&(c.delete(t),c.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,l),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,c,d,p){let g=this.controllers.get(e)?.signal,x=s==="inline"?this.inlineExecutor:this.processExecutor;this.taskTracker.transition(e,"running");try{let y={...this.settings,task:t};g&&(y.signal=g),i&&(y.provider=i),a&&(y.model=a),l&&(y.providerName=l),c&&(y.contextMode=c),d&&(y.parentSystemPrompt=d),p&&(y.agentType=p.name);let u=await x.execute(y);if(u.status==="aborted"){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}u.status==="completed"?this.taskTracker.transition(e,"completed",u.finalResult??void 0):this.taskTracker.transition(e,"failed",void 0,u.errorMessage??void 0),await this.publishOutcome(r,t,n,u,e)}catch(y){if(se(y)){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}let u=y instanceof Error?y.message:String(y);this.taskTracker.transition(e,"failed",void 0,u);try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:u,failureAttribution:"exception"},e)}catch{}}}async publishOutcome(e,t,n,r,s){let i={kind:r.status==="completed"?"subagent_completed":"subagent_failed",taskId:s,label:n,status:r.status==="completed"?"completed":"failed",originalTask:t,...r.finalResult?{result:r.finalResult}:{},...r.errorMessage?{error:r.errorMessage}:{}},a=r.status==="completed"?r.finalResult??"Task completed.":r.errorMessage??"Subagent failed.",l={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:a,metadata:{_notification:i}};await this.bus.publishInbound(l)}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 Ar=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 _o(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import Oe from"node:fs";import Er from"node:path";je();function qt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Qs(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Xl(o){try{let e=JSON.parse(o);return qt(e)?"metadata"in e||"last_consolidated"in e?{metadata:qt(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 _r=class o{key;messages=[];createdAt=le();updatedAt=le();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=le()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:le()};return this.messages.push(n),this.updatedAt=le(),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=le(),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)}}},ot=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=tt(Er.join(e,"sessions")),this.workspaceKey=t.workspaceKey??Er.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return Er.join(this.sessionsDir,`${ds(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Fe({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=qt(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=Xl(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=Qs(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
256
+ ${i}`}:a),r.push({role:"user",content:o.task})}else o.contextMode==="inherit-system"&&o.parentSystemPrompt?r=[{role:"system",content:Zs(o.parentSystemPrompt,n)},{role:"user",content:o.task}]:r=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:Zs(void 0,n)},{role:"user",content:o.task}];let s="Task completed but no final response was generated.";for(let i=0;i<15;i++){te(o.signal);let a=await o.provider.chat({messages:r,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(te(o.signal),a.toolCalls.length){r.push({role:"assistant",content:a.content??"",tool_calls:a.toolCalls.map(l=>({id:l.id,type:"function",function:{name:l.name,arguments:JSON.stringify(l.arguments)}}))});for(let l of a.toolCalls){te(o.signal);let c=await e.execute(l.name,l.arguments,o.signal?{signal:o.signal}:{});te(o.signal);let d=typeof c=="object"&&"kind"in c?c.content??String(c):String(c);r.push({role:"tool",tool_call_id:l.id,name:l.name,content:d})}continue}s=a.content??s;break}return s}function Yl(){let o=process.argv[1]??"";return Wt(o)}function Xl(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 Ql(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(Qs));if(e)try{return JSON.parse(e.slice(Qs.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:Xl(o),failureAttribution:o.failureAttribution}}var Tr=class{constructor(e=new ve,t=Yl){this.runner=e;this.resolveCommand=t}async execute(e){if(kt("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 Ql(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,n=e.contextMode??"fresh";if(n==="fork"&&e.sessionKey)if(!this.sessionManager)console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`);else{let a=this.sessionManager.getOrCreate(e.sessionKey);a&&(t=a.fork().getHistory())}let r=e.agentType?Co(e.agentType):void 0,s={...e,provider:e.provider,existingMessages:t,contextMode:n,...e.parentSystemPrompt?{parentSystemPrompt:e.parentSystemPrompt}:{},...r?{definition:r}:{}};return{status:"completed",finalResult:await _o(s)}}catch(t){return se(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},Ar=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;taskTracker=new xr;getTaskTracker(){return this.taskTracker}getTaskSnapshot(){return this.taskTracker.prune(),this.taskTracker.getAll()}async spawn(e){let t=Vl().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),this.taskTracker.register(t,"subagent",n,e.sessionKey);let i=e.mode??"process",a=e.agentType?Co(e.agentType):void 0,l=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName,e.contextMode,e.parentSystemPrompt,a).finally(()=>{this.running.delete(t),this.controllers.delete(t);let c=this.sessionTasks.get(e.sessionKey);c&&(c.delete(t),c.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,l),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,c,d,p){let g=this.controllers.get(e)?.signal,x=s==="inline"?this.inlineExecutor:this.processExecutor;this.taskTracker.transition(e,"running");try{let y={...this.settings,task:t};g&&(y.signal=g),i&&(y.provider=i),a&&(y.model=a),l&&(y.providerName=l),c&&(y.contextMode=c),d&&(y.parentSystemPrompt=d),p&&(y.agentType=p.name);let u=await x.execute(y);if(u.status==="aborted"){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}u.status==="completed"?this.taskTracker.transition(e,"completed",u.finalResult??void 0):this.taskTracker.transition(e,"failed",void 0,u.errorMessage??void 0),await this.publishOutcome(r,t,n,u,e)}catch(y){if(se(y)){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}let u=y instanceof Error?y.message:String(y);this.taskTracker.transition(e,"failed",void 0,u);try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:u,failureAttribution:"exception"},e)}catch{}}}async publishOutcome(e,t,n,r,s){let i={kind:r.status==="completed"?"subagent_completed":"subagent_failed",taskId:s,label:n,status:r.status==="completed"?"completed":"failed",originalTask:t,...r.finalResult?{result:r.finalResult}:{},...r.errorMessage?{error:r.errorMessage}:{}},a=r.status==="completed"?r.finalResult??"Task completed.":r.errorMessage??"Subagent failed.",l={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:a,metadata:{_notification:i}};await this.bus.publishInbound(l)}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 Er=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 Po(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import De from"node:fs";import _r from"node:path";Be();function zt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function ei(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Zl(o){try{let e=JSON.parse(o);return zt(e)?"metadata"in e||"last_consolidated"in e?{metadata:zt(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 Pr=class o{key;messages=[];createdAt=le();updatedAt=le();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=le()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:le()};return this.messages.push(n),this.updatedAt=le(),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=le(),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)}}},st=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=nt(_r.join(e,"sessions")),this.workspaceKey=t.workspaceKey??_r.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return _r.join(this.sessionsDir,`${gs(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Ue({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=zt(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=Zl(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=ei(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
257
257
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
258
258
  ) VALUES (?, ?, ?, ?, ?, ?, ?)
259
259
  ON CONFLICT(workspace, session_key) DO UPDATE SET
@@ -261,21 +261,21 @@ ${i}`}:a),r.push({role:"user",content:o.task})}else o.contextMode==="inherit-sys
261
261
  chat_id = excluded.chat_id,
262
262
  created_at = excluded.created_at,
263
263
  updated_at = excluded.updated_at,
264
- 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(!Oe.existsSync(e))return null;try{let t=Oe.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return qt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!Oe.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
264
+ 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(!De.existsSync(e))return null;try{let t=De.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return zt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!De.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
265
265
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
266
- ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of Oe.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=Er.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=Qs(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??le(),r.updated_at??r.created_at??le(),JSON.stringify({metadata:qt(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
266
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of De.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=_r.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=ei(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??le(),r.updated_at??r.created_at??le(),JSON.stringify({metadata:zt(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
267
267
  FROM session_metadata
268
- WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!Oe.existsSync(t))return null;try{let r=Oe.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&&qt(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 _r(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{Oe.writeFileSync(n,`${s.join(`
268
+ WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!De.existsSync(t))return null;try{let r=De.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&&zt(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 Pr(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{De.writeFileSync(n,`${s.join(`
269
269
  `)}
270
- `,"utf8"),Oe.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{Oe.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return Oe.existsSync(t)&&(Oe.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
270
+ `,"utf8"),De.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{De.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return De.existsSync(t)&&(De.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
271
271
  FROM session_metadata
272
272
  WHERE workspace = ?
273
- 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 _r(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};Ot();var Ql=[{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"}],Zl=/<\/?[a-zA-Z][^>]*\/?>/g,Pr=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(Zl,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of Ql)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};Ot();de();function yn(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 Zs(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function ei(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var Mr=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",Zs(this.options.providerLabel??"")]).has(Zs(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:yn(e.messages),tools:e.tools,tool_choice:e.tools?.length?e.toolChoice??"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:ei(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 yn(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?e.toolChoice??"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:ei(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(`
274
- `).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 te(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as ec}from"nanoid";var Ir=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 g=p.function;g?.name&&l.push({functionCall:{name:g.name,args:this.parseToolArgs(g.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(`
273
+ 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 Pr(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};Nt();var ec=[{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"}],tc=/<\/?[a-zA-Z][^>]*\/?>/g,Mr=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(tc,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of ec)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};Nt();ce();function bn(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 ti(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function ni(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var Ir=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",ti(this.options.providerLabel??"")]).has(ti(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:bn(e.messages),tools:e.tools,tool_choice:e.tools?.length?e.toolChoice??"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:ni(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 bn(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?e.toolChoice??"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:ni(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(`
274
+ `).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 te(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as nc}from"nanoid";var Lr=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 g=p.function;g?.name&&l.push({functionCall:{name:g.name,args:this.parseToolArgs(g.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(`
275
275
 
276
- `)}]});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=e.toolChoice==="required"?{functionCallingConfig:{mode:"ANY",allowedFunctionNames:s.map(i=>i.name)}}:{functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{te(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(y=>typeof y?.text=="string").map(y=>String(y.text)),p=c.filter(y=>y?.functionCall?.name).map(y=>({id:ec(9),name:String(y.functionCall.name),arguments:this.parseToolArgs(y.functionCall.args)})),g={};a?.usageMetadata&&(g.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),g.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),g.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let x=String(l?.finishReason??"STOP").toLowerCase();return{content:d.length?d.join(`
277
- `):null,toolCalls:p,finishReason:x,usage:g,reasoningContent:null}}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as tc}from"nanoid";de();var $r=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:yn(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice=e.toolChoice??"auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{te(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 ${pt} 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??"",g=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${g}
278
- ${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: ${g}`,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:tc(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(se(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function Ne(o){let e=o.agents.defaults.model,t=nt(o,e),n=bs(o,e),r=t&&ht(t)?Lt(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(ht(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${pt}.`);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"&&!ht(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${pt}.`);return t==="custom"||ht(t)?new Mr(n?.apiKey||r?.apiKey||"no-key",Bn(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 Ir(n?.apiKey||"",Bn(o,e),e):new $r(n?.apiKey??null,Bn(o,e),e,t)}wn();var Or=class extends z{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)}};jt();vn();jt();vn();function Tt(o,e){let t=Math.max(0,o.length-e);for(;t>0&&o[t]?.role==="tool";)t--;return o.slice(t)}function si(){return`Your task is to create a detailed summary of the conversation so far.
276
+ `)}]});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=e.toolChoice==="required"?{functionCallingConfig:{mode:"ANY",allowedFunctionNames:s.map(i=>i.name)}}:{functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{te(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(y=>typeof y?.text=="string").map(y=>String(y.text)),p=c.filter(y=>y?.functionCall?.name).map(y=>({id:nc(9),name:String(y.functionCall.name),arguments:this.parseToolArgs(y.functionCall.args)})),g={};a?.usageMetadata&&(g.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),g.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),g.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let x=String(l?.finishReason??"STOP").toLowerCase();return{content:d.length?d.join(`
277
+ `):null,toolCalls:p,finishReason:x,usage:g,reasoningContent:null}}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as rc}from"nanoid";ce();var $r=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:bn(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice=e.toolChoice??"auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{te(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 ${ft} 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??"",g=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${g}
278
+ ${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: ${g}`,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:rc(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(se(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function je(o){let e=o.agents.defaults.model,t=rt(o,e),n=vs(o,e),r=t&&yt(t)?Ot(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(yt(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${ft}.`);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"&&!yt(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${ft}.`);return t==="custom"||yt(t)?new Ir(n?.apiKey||r?.apiKey||"no-key",Un(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 Lr(n?.apiKey||"",Un(o,e),e):new $r(n?.apiKey??null,Un(o,e),e,t)}vn();var Nr=class extends z{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)}};Ft();Sn();Ft();Sn();function Rt(o,e){let t=Math.max(0,o.length-e);for(;t>0&&o[t]?.role==="tool";)t--;return o.slice(t)}function ai(){return`Your task is to create a detailed summary of the conversation so far.
279
279
  This summary should capture all technical details essential for continuing work.
280
280
 
281
281
  Respond with TEXT ONLY. Do NOT call any tools.
@@ -291,65 +291,65 @@ Your summary should include:
291
291
  7. Current Work: What was being worked on immediately before this summary
292
292
  8. Next Step: The immediate next action to take
293
293
 
294
- Wrap your analysis in <analysis> tags, then provide the summary in <summary> tags.`}function ii(o){let e=o.match(/<summary>([\s\S]*?)<\/summary>/);return e?.[1]?e[1].trim():o.match(/<analysis>([\s\S]*?)<\/analysis>/)?o.slice(o.indexOf("</analysis>")+11).trim()||o:o.trim()}function ai(o){let e=[`## Conversation to Summarize
294
+ Wrap your analysis in <analysis> tags, then provide the summary in <summary> tags.`}function li(o){let e=o.match(/<summary>([\s\S]*?)<\/summary>/);return e?.[1]?e[1].trim():o.match(/<analysis>([\s\S]*?)<\/analysis>/)?o.slice(o.indexOf("</analysis>")+11).trim()||o:o.trim()}function ci(o){let e=[`## Conversation to Summarize
295
295
  `];for(let t of o){let n=String(t.role??"unknown").toUpperCase();if(n!=="SYSTEM"){if(n==="USER"){let r=typeof t.content=="string"?t.content:Array.isArray(t.content)?t.content.map(s=>s.type==="text"?s.text:"[non-text content]").join(`
296
296
  `):String(t.content);e.push(`[USER]: ${r}`)}else if(n==="ASSISTANT"){let r=typeof t.content=="string"?t.content:"",s=Array.isArray(t.tool_calls)?t.tool_calls.map(i=>{let a=i.function?.name??i.name??"unknown",l=i.function?.arguments??i.arguments??"{}";return`Tool: ${a}(${typeof l=="string"?l:JSON.stringify(l)})`}).join(`
297
297
  `):"";e.push(`[ASSISTANT]: ${r}${s?`
298
298
  ${s}`:""}`)}else if(n==="TOOL"){let r=String(t.name??"unknown"),s=typeof t.content=="string"?t.content.length>500?`${t.content.slice(0,500)}... (truncated)`:t.content:"[non-text content]";e.push(`[TOOL ${r}]: ${s}`)}}}return e.join(`
299
299
 
300
- `)}function Sn(o){return{role:"user",content:`[Compacted Summary]
300
+ `)}function kn(o){return{role:"user",content:`[Compacted Summary]
301
301
 
302
302
  This session continues from a compacted conversation. Here's a summary of what happened:
303
303
 
304
- ${o}`}}async function kn(o,e,t){let n=si(),r=ai(o),i=(await e.chat({model:t,messages:[{role:"system",content:n},{role:"user",content:r}],maxTokens:16384})).content||"";return ii(i)}var li=.8,ci=.6,di=3,ui=10,Mo={consecutiveFailures:0,lastCompactAt:null,totalCompactions:0};async function Io(o,e,t,n,r){let s=n?.compaction?.autoCompactThresholdRatio??li,i=n?.compaction?.keepRecentMessages??ui,a=n?.compaction?.maxConsecutiveFailures??di,l=Je(o),c=Dt(t,n);if(l<c*s)return{compacted:!1,messages:o,method:"none",tokensBefore:l,tokensAfter:l,tokensFreed:0};if(r.consecutiveFailures>=a)return{compacted:!1,messages:o,method:"failed",tokensBefore:l,tokensAfter:l,tokensFreed:0};let d=Nr(o,i),p=Je(d.messages);if(p<c*s)return{compacted:!0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p};try{let g=await kn(o,e,t),x=Sn(g),y=o.find(v=>v.role==="system"),u=Tt(o,i),b=[];y&&b.push(y),b.push(x),b.push(...u);let T=Je(b);return r.consecutiveFailures=0,r.lastCompactAt=new Date().toISOString(),r.totalCompactions++,{compacted:!0,messages:b,method:"auto",tokensBefore:l,tokensAfter:T,tokensFreed:l-T}}catch{return r.consecutiveFailures++,{compacted:d.messagesCleared>0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p}}}function $o(o,e,t){let n=t?.compaction?.microCompactThresholdRatio??ci;return fo(o,n,e,t)}jt();vn();var gi=3,Lo=10,ic=.3;function Oo(o){if(!o)return!1;let e=String(o).toLowerCase();return["context length","context window","too long","maximum context","token limit","input is longer than","exceeds maximum","413","prompt is too long","request too large"].some(n=>e.includes(n))}async function No(o,e,t,n){let r=Dr(o,Lo).messages,s=Je(r),i=Dt(t,n);if(s<i*.9)return{messages:r,retries:1,method:"aggressive_micro"};for(let c=1;c<=gi;c++){let d=Math.max(Lo,Math.floor(r.length*ic*(1/c))),p=r.find(x=>x.role==="system"),g=Tt(r,d);if(r=p?[p,...g]:g,s=Je(r),s<i*.7)try{let x=await kn(r,e,t),y=Sn(x),u=[];return p&&u.push(p),u.push(y),u.push(...Tt(r,Math.floor(d/2))),{messages:u,retries:c,method:"llm"}}catch{continue}}let a=r.find(c=>c.role==="system"),l=Tt(r,Lo);return r=a?[a,...l]:l,{messages:r,retries:gi,method:"truncate"}}function Do(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function ac(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function lc(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 zt=class o{constructor(e){this.input=e;let t=mi.resolve(e.workspace);this.context=new vt(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new ot(t);this.sessions=n,this.lifecycle=e.lifecycle??rt();let r=e.model??e.provider.getDefaultModel();this.subagents=new Rr(e.bus,e.subagentExecutor??new xr,e.subagentInlineExecutor??new Tr(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 Ar(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 bn;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;compactionStats={microCompactions:0,autoCompactions:0,reactiveCompactions:0,tokensFreed:0,consecutiveFailures:0};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=Un(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=Un(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=Un(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:Ne(r)}}getRuntimeState(){let e=this.runtime.snapshot(),t=this.input.loadConfig?.();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(n=>n.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},tasks:this.subagents.getTaskSnapshot(),compaction:{enabled:t?.compaction?.enabled??!0,microCompactions:this.compactionStats.microCompactions,autoCompactions:this.compactionStats.autoCompactions,reactiveCompactions:this.compactionStats.reactiveCompactions,tokensFreed:this.compactionStats.tokensFreed,circuitBreakerTripped:this.compactionStats.consecutiveFailures>=(t?.compaction?.maxConsecutiveFailures??3)}}}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 qe(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 qe(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:mi.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){let a=this.context.buildSystemPrompt(e.skillNames,e.memoryNamespace);s.turn={...e,systemPrompt:a}}if(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=kr(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,a={...Mo}){let l=[...e],c=null,d=[],p=this.input.maxIterations??40,g=i?.model??this.model,x=i?.provider??this.input.provider,y=this.isToolCallingEnabled(g),u=this.isReasoningEnabled(g),b=this.isImageOutputEnabled(g),T=y?t.getDefinitions():void 0,O=AbortSignal.timeout(12e4),G=s?AbortSignal.any([s,O]):O,I=0;for(let V=0;V<p;V++){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s);let N=this.input.loadConfig?.(),D=await Io(l,x,g,N,a);D.compacted&&(l.length=0,l.push(...D.messages));let Y;try{Y=await x.chat({messages:l,...T?{tools:T}:{},model:g,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...u?{reasoning:!0}:{},...b?{imageOutput:!0}:{},signal:G})}catch(J){if(Oo(J)){if(I++,this.compactionStats.consecutiveFailures++,I>2)throw J;console.error(`[compact] reactive: triggered by context_overflow (attempt ${I})`);let U=await No(l,x,g,N);this.compactionStats.reactiveCompactions++,this.compactionStats.consecutiveFailures=0,l.length=0,l.push(...U.messages),V--;continue}if(se(J)){if(s?.aborted)throw J;return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1}}throw J}if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let j=Y.reasoningContent||ac(Y.content);if(j&&n&&r()&&await n(j,{event:"thinking",thinkingContent:j,toolHint:!1}),Y.toolCalls.length){let J=Do(Y.content);n&&J&&r()&&await n(J,{event:"answer",toolHint:!1});let U=Y.toolCalls.map(L=>({id:L.id,type:"function",function:{name:L.name,arguments:JSON.stringify(L.arguments)}}));n&&r()&&await n(this.toolHint(Y.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:U.map(L=>({...L,status:"running"}))}),this.context.addAssistantMessage(l,J,U,j);for(let L of Y.toolCalls){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s),d.push(L.name);let K=await t.execute(L.name,L.arguments,s?{signal:s}:{});if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let B=K.kind==="cancelled"?"Task was cancelled.":K.content;if(this.context.addToolResult(l,L.id,L.name,B),n&&r()&&await n(B,{event:"tool_result",toolHint:!0,tool_call:{id:L.id,type:"function",function:{name:L.name,arguments:JSON.stringify(L.arguments)},status:"completed",resultPreview:lc(B,200)??null}}),K.kind==="terminal")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!1,terminal:!0};if(K.kind==="cancelled")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};if(K.kind==="error"&&!K.retryable)break}if($o(l,g,N)){let{microCompact:L}=await Promise.resolve().then(()=>(vn(),oi)),K=L(l,N?.compaction?.keepRecentMessages??10);K.messagesCleared>0&&(l.length=0,l.push(...K.messages))}}else{c=Do(Y.content),c&&n&&r()&&await n(c,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(l,c,void 0,j);break}}return c==null&&(c=`I reached the maximum number of tool call iterations (${p}) without completing the task.`),{finalContent:c,toolsUsed:d,messages:l,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 ${_o(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,g=>this.processMessage(a,t,s,p,g,"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(se(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??_o(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})}async clearSessionContext(e,t,n,r){return e.messages.length&&!await this.consolidateMemory(e,!0,n.provider,n.model)?{response:{channel:t.channel,chatId:t.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(e.clear(),this.sessions.save(e),{response:{channel:t.channel,chatId:t.chatId,content:r},cancelled:!1})}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=Do(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)}
305
- ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(vt.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 Pr(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){if(e==="/new"){let s=await this.clearSessionContext(t,n,r,"New session started.");return s.response.content==="New session started."&&this.sessions.invalidate(t.key),s}return e==="/reset"?await this.clearSessionContext(t,n,r,"Session context cleared."):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
304
+ ${o}`}}async function Cn(o,e,t){let n=ai(),r=ci(o),i=(await e.chat({model:t,messages:[{role:"system",content:n},{role:"user",content:r}],maxTokens:16384})).content||"";return li(i)}var di=.8,ui=.6,gi=3,mi=10,Io={consecutiveFailures:0,lastCompactAt:null,totalCompactions:0};async function Lo(o,e,t,n,r){let s=n?.compaction?.autoCompactThresholdRatio??di,i=n?.compaction?.keepRecentMessages??mi,a=n?.compaction?.maxConsecutiveFailures??gi,l=He(o),c=jt(t,n);if(l<c*s)return{compacted:!1,messages:o,method:"none",tokensBefore:l,tokensAfter:l,tokensFreed:0};if(r.consecutiveFailures>=a)return{compacted:!1,messages:o,method:"failed",tokensBefore:l,tokensAfter:l,tokensFreed:0};let d=Dr(o,i),p=He(d.messages);if(p<c*s)return{compacted:!0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p};try{let g=await Cn(o,e,t),x=kn(g),y=o.find(v=>v.role==="system"),u=Rt(o,i),b=[];y&&b.push(y),b.push(x),b.push(...u);let T=He(b);return r.consecutiveFailures=0,r.lastCompactAt=new Date().toISOString(),r.totalCompactions++,{compacted:!0,messages:b,method:"auto",tokensBefore:l,tokensAfter:T,tokensFreed:l-T}}catch{return r.consecutiveFailures++,{compacted:d.messagesCleared>0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p}}}function $o(o,e,t){let n=t?.compaction?.microCompactThresholdRatio??ui;return ho(o,n,e,t)}Ft();Sn();var pi=3,Oo=10,lc=.3;function No(o){if(!o)return!1;let e=String(o).toLowerCase();return["context length","context window","too long","maximum context","token limit","input is longer than","exceeds maximum","413","prompt is too long","request too large"].some(n=>e.includes(n))}async function Do(o,e,t,n){let r=jr(o,Oo).messages,s=He(r),i=jt(t,n);if(s<i*.9)return{messages:r,retries:1,method:"aggressive_micro"};for(let c=1;c<=pi;c++){let d=Math.max(Oo,Math.floor(r.length*lc*(1/c))),p=r.find(x=>x.role==="system"),g=Rt(r,d);if(r=p?[p,...g]:g,s=He(r),s<i*.7)try{let x=await Cn(r,e,t),y=kn(x),u=[];return p&&u.push(p),u.push(y),u.push(...Rt(r,Math.floor(d/2))),{messages:u,retries:c,method:"llm"}}catch{continue}}let a=r.find(c=>c.role==="system"),l=Rt(r,Oo);return r=a?[a,...l]:l,{messages:r,retries:pi,method:"truncate"}}function jo(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function cc(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function dc(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 Vt=class o{constructor(e){this.input=e;let t=fi.resolve(e.workspace);this.context=new St(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new st(t);this.sessions=n,this.lifecycle=e.lifecycle??ot();let r=e.model??e.provider.getDefaultModel();this.subagents=new Ar(e.bus,e.subagentExecutor??new Tr,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 Er(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 wn;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;compactionStats={microCompactions:0,autoCompactions:0,reactiveCompactions:0,tokensFreed:0,consecutiveFailures:0};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=Gn(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=Gn(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=Gn(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:je(r)}}getRuntimeState(){let e=this.runtime.snapshot(),t=this.input.loadConfig?.();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(n=>n.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},tasks:this.subagents.getTaskSnapshot(),compaction:{enabled:t?.compaction?.enabled??!0,microCompactions:this.compactionStats.microCompactions,autoCompactions:this.compactionStats.autoCompactions,reactiveCompactions:this.compactionStats.reactiveCompactions,tokensFreed:this.compactionStats.tokensFreed,circuitBreakerTripped:this.compactionStats.consecutiveFailures>=(t?.compaction?.maxConsecutiveFailures??3)}}}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 ze(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 ze(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:fi.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){let a=this.context.buildSystemPrompt(e.skillNames,e.memoryNamespace);s.turn={...e,systemPrompt:a}}if(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=Cr(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,a={...Io}){let l=[...e],c=null,d=[],p=this.input.maxIterations??40,g=i?.model??this.model,x=i?.provider??this.input.provider,y=this.isToolCallingEnabled(g),u=this.isReasoningEnabled(g),b=this.isImageOutputEnabled(g),T=y?t.getDefinitions():void 0,O=AbortSignal.timeout(12e4),G=s?AbortSignal.any([s,O]):O,I=0;for(let V=0;V<p;V++){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s);let N=this.input.loadConfig?.(),D=await Lo(l,x,g,N,a);D.compacted&&(l.length=0,l.push(...D.messages));let Y;try{Y=await x.chat({messages:l,...T?{tools:T}:{},model:g,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...u?{reasoning:!0}:{},...b?{imageOutput:!0}:{},signal:G})}catch(J){if(No(J)){if(I++,this.compactionStats.consecutiveFailures++,I>2)throw J;console.error(`[compact] reactive: triggered by context_overflow (attempt ${I})`);let U=await Do(l,x,g,N);this.compactionStats.reactiveCompactions++,this.compactionStats.consecutiveFailures=0,l.length=0,l.push(...U.messages),V--;continue}if(se(J)){if(s?.aborted)throw J;return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1}}throw J}if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let j=Y.reasoningContent||cc(Y.content);if(j&&n&&r()&&await n(j,{event:"thinking",thinkingContent:j,toolHint:!1}),Y.toolCalls.length){let J=jo(Y.content);n&&J&&r()&&await n(J,{event:"answer",toolHint:!1});let U=Y.toolCalls.map($=>({id:$.id,type:"function",function:{name:$.name,arguments:JSON.stringify($.arguments)}}));n&&r()&&await n(this.toolHint(Y.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:U.map($=>({...$,status:"running"}))}),this.context.addAssistantMessage(l,J,U,j);for(let $ of Y.toolCalls){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s),d.push($.name);let K=await t.execute($.name,$.arguments,s?{signal:s}:{});if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let B=K.kind==="cancelled"?"Task was cancelled.":K.content;if(this.context.addToolResult(l,$.id,$.name,B),n&&r()&&await n(B,{event:"tool_result",toolHint:!0,tool_call:{id:$.id,type:"function",function:{name:$.name,arguments:JSON.stringify($.arguments)},status:"completed",resultPreview:dc(B,200)??null}}),K.kind==="terminal")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!1,terminal:!0};if(K.kind==="cancelled")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};if(K.kind==="error"&&!K.retryable)break}if($o(l,g,N)){let{microCompact:$}=await Promise.resolve().then(()=>(Sn(),ii)),K=$(l,N?.compaction?.keepRecentMessages??10);K.messagesCleared>0&&(l.length=0,l.push(...K.messages))}}else{c=jo(Y.content),c&&n&&r()&&await n(c,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(l,c,void 0,j);break}}return c==null&&(c=`I reached the maximum number of tool call iterations (${p}) without completing the task.`),{finalContent:c,toolsUsed:d,messages:l,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 ${Po(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,g=>this.processMessage(a,t,s,p,g,"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(se(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??Po(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})}async clearSessionContext(e,t,n,r){return e.messages.length&&!await this.consolidateMemory(e,!0,n.provider,n.model)?{response:{channel:t.channel,chatId:t.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(e.clear(),this.sessions.save(e),{response:{channel:t.channel,chatId:t.chatId,content:r},cancelled:!1})}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=jo(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)}
305
+ ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(St.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 Mr(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){if(e==="/new"){let s=await this.clearSessionContext(t,n,r,"New session started.");return s.response.content==="New session started."&&this.sessions.invalidate(t.key),s}return e==="/reset"?await this.clearSessionContext(t,n,r,"Session context cleared."):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
306
306
  /new - Start a new conversation
307
307
  /reset - Clear the current session context
308
308
  /stop - Stop the current task
309
- /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n,r){let s=this.memoryNamespace(t.sessionKey),i={...t};r&&(i.skillNames=r),s&&(i.memoryNamespace=s);let a=this.createToolRegistry(i);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let l of n)try{let c=await this.mcpManager.getServerTools(l);for(let d of c)a.register(new Or(d.serverName,d.remoteName,d.proxyName,d.description,d.inputSchema,this.mcpManager))}catch(c){console.warn(`MCP: failed to connect to '${l}': ${String(c)}`)}}return a}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(me);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 B=e.metadata?._notification;if(B){let P=this.context.buildNotificationContext(B),M={...e,content:P},{messages:Q,newMessageStartIndex:F}=this.buildTurnPrompt(c,M,l,[]),ge=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:ee,messages:Qe,toolsUsed:In,cancelled:gt,terminal:wu}=await this.runAgentLoop(Q,ge,void 0,r,s,d);return gt||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,Qe,F,In),{response:{channel:a.channel,chatId:a.chatId,content:ee??"Task notification processed."},cancelled:!1})}let{messages:f,newMessageStartIndex:h}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:k,messages:C,toolsUsed:A,cancelled:R,terminal:E}=await this.runAgentLoop(f,m,void 0,r,s,d);return R||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,C,h,A),{response:{channel:a.channel,chatId:a.chatId,content:k??"Background task completed."},cancelled:!1})}let g=(typeof e.content=="string"?e.content:e.content.find(B=>B.type==="text")?.text??"").trim().toLowerCase(),x=await this.resolveCommand(g,c,e,d);if(x)return x;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:[],T=Object.keys(l?.tools?.mcpServers??{}),v=new Set(T),O=b.length?b.filter(B=>v.has(B)):T,G=b.filter(B=>!v.has(B)),I=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},O,G),{messages:V,newMessageStartIndex:N}=this.buildTurnPrompt(c,e,l,G),D=async(B,f)=>{if(!r())return;let h={...e.metadata,_progress:!0,_tool_hint:!!f?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:B,metadata:h})},{finalContent:Y,messages:j,toolsUsed:J,cancelled:U,terminal:L}=await this.runAgentLoop(V,I,n??D,r,s,d);if(U||!r())return{response:null,cancelled:!0};let K=Y??"I've completed processing but have no response to give.";if(this.commitTurn(c,j,N,J),u){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,d.provider,d.model)}finally{this.consolidating.delete(c.key)}}return L?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:K,metadata:e.metadata??{}},cancelled:!1}})}};uo();kt();var cc=1024*1024,dc=300*1e3;function pi(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function uc(o,e,t){let n=pi(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
309
+ /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n,r){let s=this.memoryNamespace(t.sessionKey),i={...t};r&&(i.skillNames=r),s&&(i.memoryNamespace=s);let a=this.createToolRegistry(i);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let l of n)try{let c=await this.mcpManager.getServerTools(l);for(let d of c)a.register(new Nr(d.serverName,d.remoteName,d.proxyName,d.description,d.inputSchema,this.mcpManager))}catch(c){console.warn(`MCP: failed to connect to '${l}': ${String(c)}`)}}return a}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(me);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 B=e.metadata?._notification;if(B){let P=this.context.buildNotificationContext(B),M={...e,content:P},{messages:Q,newMessageStartIndex:F}=this.buildTurnPrompt(c,M,l,[]),ge=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:ee,messages:Ze,toolsUsed:Ln,cancelled:mt,terminal:Ru}=await this.runAgentLoop(Q,ge,void 0,r,s,d);return mt||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,Ze,F,Ln),{response:{channel:a.channel,chatId:a.chatId,content:ee??"Task notification processed."},cancelled:!1})}let{messages:f,newMessageStartIndex:h}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:k,messages:C,toolsUsed:A,cancelled:R,terminal:E}=await this.runAgentLoop(f,m,void 0,r,s,d);return R||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,C,h,A),{response:{channel:a.channel,chatId:a.chatId,content:k??"Background task completed."},cancelled:!1})}let g=(typeof e.content=="string"?e.content:e.content.find(B=>B.type==="text")?.text??"").trim().toLowerCase(),x=await this.resolveCommand(g,c,e,d);if(x)return x;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:[],T=Object.keys(l?.tools?.mcpServers??{}),v=new Set(T),O=b.length?b.filter(B=>v.has(B)):T,G=b.filter(B=>!v.has(B)),I=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},O,G),{messages:V,newMessageStartIndex:N}=this.buildTurnPrompt(c,e,l,G),D=async(B,f)=>{if(!r())return;let h={...e.metadata,_progress:!0,_tool_hint:!!f?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:B,metadata:h})},{finalContent:Y,messages:j,toolsUsed:J,cancelled:U,terminal:$}=await this.runAgentLoop(V,I,n??D,r,s,d);if(U||!r())return{response:null,cancelled:!0};let K=Y??"I've completed processing but have no response to give.";if(this.commitTurn(c,j,N,J),u){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,d.provider,d.model)}finally{this.consolidating.delete(c.key)}}return $?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:K,metadata:e.metadata??{}},cancelled:!1}})}};go();Ct();var uc=1024*1024,gc=300*1e3;function hi(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function mc(o,e,t){let n=hi(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
310
310
  ${t.stdout.trim()}`:"",t.stderr.trim()?`STDERR:
311
311
  ${t.stderr.trim()}`:"",typeof t.exitCode=="number"?`Exit code: ${t.exitCode}`:"",t.signal?`Signal: ${t.signal}`:"",t.errorMessage?`Error: ${t.errorMessage}`:""].filter(Boolean).join(`
312
312
  `);return r?`${n} failed
313
- ${r}`:`${n} failed`}function gc(){let o=process.argv[1]??"";return Gt(o)}function jr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(dc,e)}var jo=class{constructor(e,t,n,r=new ve,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(St(this.target).mode!=="local-process")throw new Error(`${pi(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??cc});if(n.status==="aborted")throw cn();if(n.status==="ok")return n.stdout;throw new Error(uc(this.target,this.timeoutMs,n))}};function Cn(o){let e=gc();return new jo(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 Vt=class o{constructor(e,t,n,r){this.config=e;this.bus=t;this.debounce=n;this.logger=r}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,s=e.metadata?._skip_allow_from===!0,i=typeof e.metadata?.chat_type=="string"?e.metadata.chat_type:void 0,a=e.metadata?{...e.metadata}:void 0;if(a&&"_skip_allow_from"in a&&delete a._skip_allow_from,!s&&!this.isAllowed(e.senderId)){this.logger?.info("message.inbound","blocked",{channel:this.name,chatId:e.chatId,senderId:e.senderId,reason:"allow_from",chatType:i,groupTitle:typeof a?.chat_title=="string"?a.chat_title:void 0,content:r}),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}"`),this.logger?.info("message.inbound","received",{channel:this.name,chatId:e.chatId,senderId:e.senderId,chatType:i,groupTitle:typeof a?.chat_title=="string"?a.chat_title:void 0,threadId:a?.thread_id,botMentioned:a?.bot_mentioned===!0,content:r});let l={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(l.media=e.media),a&&Object.keys(a).length>0&&(l.metadata=a),e.sessionKey&&(l.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(l)}get isRunning(){return this.running}};var Yt=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(`
314
- `),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 fi(o){return o.message?{kind:"message",msg:o.message}:o.edited_message?{kind:"edited_message",msg:o.edited_message}:o.channel_post?{kind:"channel_post",msg:o.channel_post}:o.edited_channel_post?{kind:"edited_channel_post",msg:o.edited_channel_post}:{kind:"unknown",msg:null}}function mc(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(`
315
- `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function pc(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 fc(o){return o?o.text??o.caption??null:null}function hc(o){return o?o.entities??o.caption_entities??[]:[]}function yc(o){return o.toLowerCase().replace(/[^a-z0-9_]/g,"_").slice(0,32)}var bc=new Set(["chatid","ping"]);function wc(o){let e=o.match(/^\/([a-zA-Z0-9_]+)(?:@([a-zA-Z0-9_]+))?(?:\s|$)/);return e?{name:e[1].toLowerCase(),target:e[2]?.toLowerCase()??null}:null}var vc=3e3,Fr=class extends Vt{name="telegram";offset=0;inbox;botUsername=null;botId=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t,n){super(e,t,e.debounce,n),this.inbox=new Yt(e.debounce,r=>this.handleMessage(r))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured"),this.logger?.error("channel","telegram.start_failed",{reason:"missing_token"});return}if(this.logger?.info("channel","telegram.start",{mode:"polling"}),!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result&&(t.result.id&&(this.botId=String(t.result.id)),t.result.username&&(this.botUsername=t.result.username.toLowerCase(),this.logger?.info("channel","telegram.identity",{botId:this.botId,botUsername:this.botUsername}),this.config.commands?.native!==!1&&await this.registerCommands()))}else this.logger?.warn("channel","telegram.get_me_failed",{status:e.status})}catch(e){this.logger?.warn("channel","telegram.get_me_failed",{error:e instanceof Error?e.message:String(e)})}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","edited_message","channel_post","edited_channel_post"]));let t=await fetch(e);if(!t.ok){this.logger?.warn("channel","telegram.get_updates_failed",{status:t.status}),await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok){this.logger?.warn("channel","telegram.get_updates_rejected",{description:n.description??"unknown"});continue}n.result&&n.result.length>0&&this.logger?.info("channel","telegram.updates_received",{count:n.result.length,updateKinds:n.result.map(r=>fi(r).kind).join(",")});for(let r of n.result??[]){this.offset=r.update_id+1;let{kind:s,msg:i}=fi(r);if(!i){this.logger?.info("channel","telegram.update_skipped",{updateId:r.update_id,reason:"unsupported_update_type",updateKind:s});continue}if(i.from?.is_bot){this.logger?.debug("channel","telegram.update_skipped",{updateId:r.update_id,chatId:String(i.chat.id),reason:"sender_is_bot",updateKind:s});continue}let a=i.from?.id!=null?String(i.from.id):i.sender_chat?.id!=null?`chat:${i.sender_chat.id}`:"unknown",l=i.from?.username?`${a}|@${i.from.username}`:i.sender_chat?.username?`${a}|@${i.sender_chat.username}`:i.sender_chat?.title?`${a}|${i.sender_chat.title}`:a,c=pc(i),d=fc(i),p=hc(i),g=d?wc(d):null,x=g?.target!=null&&this.botUsername!=null&&g.target!==this.botUsername;if(g&&!x&&bc.has(g.name)){await this.handleBotCommand(g.name,i),this.logger?.info("channel","telegram.command_handled",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),command:g.name,chatType:i.chat.type??"unknown"});continue}let y={message_id:i.message_id};i.chat.type&&(y.chat_type=i.chat.type),i.chat.title&&(y.chat_title=i.chat.title),i.sender_chat?.id!=null&&(y.sender_chat_id=String(i.sender_chat.id)),i.sender_chat?.title&&(y.sender_chat_title=i.sender_chat.title),!i.from&&i.sender_chat&&(y.sender_is_chat=!0);let u=!1;if(this.botUsername&&d&&p.length>0&&(u=p.some(T=>T.type==="mention"?d.substring(T.offset,T.offset+T.length).toLowerCase().trim()===`@${this.botUsername}`:T.type==="text_mention"?!0:T.type==="bot_command"?d.substring(T.offset,T.offset+T.length).toLowerCase().includes(`@${this.botUsername}`):!1)),i.chat.type==="group"||i.chat.type==="supergroup"){let T=this.config.groups?.allowedGroupIds,v=T==null?null:Array.isArray(T)?T:[String(T)];if(v!==null&&!v.includes(String(i.chat.id))){this.logger?.info("channel","telegram.inbound_skipped",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),chatType:i.chat.type??"unknown",groupTitle:i.chat.title??null,senderId:l,reason:"group_not_allowed"});continue}y._skip_allow_from=!0;let O=this.config.groups?.requireMention!==!1;if(O){let G=!!g&&!x,I=!!(i.reply_to_message?.from?.is_bot&&(!this.botId||String(i.reply_to_message.from.id)===this.botId));if(!u&&!G&&!I){this.logger?.info("channel","telegram.inbound_skipped",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),chatType:i.chat.type??"unknown",groupTitle:i.chat.title??null,senderId:l,reason:"group_activation",requireMention:O});continue}}}u&&this.botUsername&&(y.bot_mentioned=!0,d&&(c=c.replace(new RegExp(`@${this.botUsername}`,"gi"),"").trim())),i.message_thread_id&&(y.thread_id=i.message_thread_id),this.inbox.submit({channel:this.name,senderId:l,chatId:String(i.chat.id),content:c,metadata:y,...i.message_thread_id&&{sessionKey:`telegram:${i.chat.id}:${i.message_thread_id}`}})}}catch(e){this.logger?.warn("channel","telegram.poll_loop_error",{error:e instanceof Error?e.message:String(e)}),await new Promise(t=>setTimeout(t,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:"reset",description:"Clear the current session context"},{command:"stop",description:"Stop the current task"},{command:"help",description:"Show available commands"}],t=(this.config.commands?.custom??[]).map(r=>({command:yc(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}\`
313
+ ${r}`:`${n} failed`}function pc(){let o=process.argv[1]??"";return Wt(o)}function Fr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(gc,e)}var Fo=class{constructor(e,t,n,r=new ve,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(kt(this.target).mode!=="local-process")throw new Error(`${hi(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??uc});if(n.status==="aborted")throw dn();if(n.status==="ok")return n.stdout;throw new Error(mc(this.target,this.timeoutMs,n))}};function xn(o){let e=pc();return new Fo(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 Yt=class o{constructor(e,t,n,r){this.config=e;this.bus=t;this.debounce=n;this.logger=r}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,s=e.metadata?._skip_allow_from===!0,i=typeof e.metadata?.chat_type=="string"?e.metadata.chat_type:void 0,a=e.metadata?{...e.metadata}:void 0;if(a&&"_skip_allow_from"in a&&delete a._skip_allow_from,!s&&!this.isAllowed(e.senderId)){this.logger?.info("message.inbound","blocked",{channel:this.name,chatId:e.chatId,senderId:e.senderId,reason:"allow_from",chatType:i,groupTitle:typeof a?.chat_title=="string"?a.chat_title:void 0,content:r}),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}"`),this.logger?.info("message.inbound","received",{channel:this.name,chatId:e.chatId,senderId:e.senderId,chatType:i,groupTitle:typeof a?.chat_title=="string"?a.chat_title:void 0,threadId:a?.thread_id,botMentioned:a?.bot_mentioned===!0,content:r});let l={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(l.media=e.media),a&&Object.keys(a).length>0&&(l.metadata=a),e.sessionKey&&(l.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(l)}get isRunning(){return this.running}};var Xt=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(`
314
+ `),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 yi(o){return o.message?{kind:"message",msg:o.message}:o.edited_message?{kind:"edited_message",msg:o.edited_message}:o.channel_post?{kind:"channel_post",msg:o.channel_post}:o.edited_channel_post?{kind:"edited_channel_post",msg:o.edited_channel_post}:{kind:"unknown",msg:null}}function fc(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(`
315
+ `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function hc(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 yc(o){return o?o.text??o.caption??null:null}function bc(o){return o?o.entities??o.caption_entities??[]:[]}function wc(o){return o.toLowerCase().replace(/[^a-z0-9_]/g,"_").slice(0,32)}var vc=new Set(["chatid","ping"]);function Sc(o){let e=o.match(/^\/([a-zA-Z0-9_]+)(?:@([a-zA-Z0-9_]+))?(?:\s|$)/);return e?{name:e[1].toLowerCase(),target:e[2]?.toLowerCase()??null}:null}var kc=3e3,Br=class extends Yt{name="telegram";offset=0;inbox;botUsername=null;botId=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t,n){super(e,t,e.debounce,n),this.inbox=new Xt(e.debounce,r=>this.handleMessage(r))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured"),this.logger?.error("channel","telegram.start_failed",{reason:"missing_token"});return}if(this.logger?.info("channel","telegram.start",{mode:"polling"}),!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result&&(t.result.id&&(this.botId=String(t.result.id)),t.result.username&&(this.botUsername=t.result.username.toLowerCase(),this.logger?.info("channel","telegram.identity",{botId:this.botId,botUsername:this.botUsername}),this.config.commands?.native!==!1&&await this.registerCommands()))}else this.logger?.warn("channel","telegram.get_me_failed",{status:e.status})}catch(e){this.logger?.warn("channel","telegram.get_me_failed",{error:e instanceof Error?e.message:String(e)})}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","edited_message","channel_post","edited_channel_post"]));let t=await fetch(e);if(!t.ok){this.logger?.warn("channel","telegram.get_updates_failed",{status:t.status}),await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok){this.logger?.warn("channel","telegram.get_updates_rejected",{description:n.description??"unknown"});continue}n.result&&n.result.length>0&&this.logger?.info("channel","telegram.updates_received",{count:n.result.length,updateKinds:n.result.map(r=>yi(r).kind).join(",")});for(let r of n.result??[]){this.offset=r.update_id+1;let{kind:s,msg:i}=yi(r);if(!i){this.logger?.info("channel","telegram.update_skipped",{updateId:r.update_id,reason:"unsupported_update_type",updateKind:s});continue}if(i.from?.is_bot&&!i.sender_chat){this.logger?.info("channel","telegram.update_skipped",{updateId:r.update_id,chatId:String(i.chat.id),reason:"sender_is_bot",updateKind:s,fromId:i.from?.id!=null?String(i.from.id):void 0});continue}let a=i.sender_chat?.id!=null?`chat:${i.sender_chat.id}`:i.from?.id!=null?String(i.from.id):"unknown",l=i.sender_chat?.username?`${a}|@${i.sender_chat.username}`:i.sender_chat?.title?`${a}|${i.sender_chat.title}`:i.from?.username?`${a}|@${i.from.username}`:a,c=hc(i),d=yc(i),p=bc(i),g=d?Sc(d):null,x=g?.target!=null&&this.botUsername!=null&&g.target!==this.botUsername;if(g&&!x&&vc.has(g.name)){await this.handleBotCommand(g.name,i),this.logger?.info("channel","telegram.command_handled",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),command:g.name,chatType:i.chat.type??"unknown"});continue}let y={message_id:i.message_id};i.chat.type&&(y.chat_type=i.chat.type),i.chat.title&&(y.chat_title=i.chat.title),i.sender_chat?.id!=null&&(y.sender_chat_id=String(i.sender_chat.id)),i.sender_chat?.title&&(y.sender_chat_title=i.sender_chat.title),i.sender_chat&&(y.sender_is_chat=!0);let u=!1;if(this.botUsername&&d&&p.length>0&&(u=p.some(T=>T.type==="mention"?d.substring(T.offset,T.offset+T.length).toLowerCase().trim()===`@${this.botUsername}`:T.type==="text_mention"?!0:T.type==="bot_command"?d.substring(T.offset,T.offset+T.length).toLowerCase().includes(`@${this.botUsername}`):!1)),i.chat.type==="group"||i.chat.type==="supergroup"){let T=this.config.groups?.allowedGroupIds,v=T==null?null:Array.isArray(T)?T:[String(T)];if(v!==null&&!v.includes(String(i.chat.id))){this.logger?.info("channel","telegram.inbound_skipped",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),chatType:i.chat.type??"unknown",groupTitle:i.chat.title??null,senderId:l,reason:"group_not_allowed"});continue}y._skip_allow_from=!0;let O=this.config.groups?.requireMention!==!1;if(O){let G=!!g&&!x,I=!!(i.reply_to_message?.from?.is_bot&&(!this.botId||String(i.reply_to_message.from.id)===this.botId));if(!u&&!G&&!I){this.logger?.info("channel","telegram.inbound_skipped",{updateId:r.update_id,updateKind:s,chatId:String(i.chat.id),chatType:i.chat.type??"unknown",groupTitle:i.chat.title??null,senderId:l,reason:"group_activation",requireMention:O});continue}}}u&&this.botUsername&&(y.bot_mentioned=!0,d&&(c=c.replace(new RegExp(`@${this.botUsername}`,"gi"),"").trim())),i.message_thread_id&&(y.thread_id=i.message_thread_id),this.inbox.submit({channel:this.name,senderId:l,chatId:String(i.chat.id),content:c,metadata:y,...i.message_thread_id&&{sessionKey:`telegram:${i.chat.id}:${i.message_thread_id}`}})}}catch(e){this.logger?.warn("channel","telegram.poll_loop_error",{error:e instanceof Error?e.message:String(e)}),await new Promise(t=>setTimeout(t,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:"reset",description:"Clear the current session context"},{command:"stop",description:"Stop the current task"},{command:"help",description:"Show available commands"}],t=(this.config.commands?.custom??[]).map(r=>({command:wc(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}\`
316
316
  Name: ${s}
317
- 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=mc(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<vc||(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 hi from"ws";var Br=class extends Vt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t,n){super(e,t,e.debounce,n),this.inbox=new Yt(e.debounce,r=>this.handleMessage(r))}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 hi(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!==hi.OPEN||this.ws.send(JSON.stringify(e))}};var yi="_shutdown",Ur=class{constructor(e,t,n,r){this.config=e;this.bus=t;this.lifecycle=n??rt(),this.logger=r,this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;logger;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new Fr(this.config.channels.telegram,this.bus,this.logger)),this.config.channels.discord.enabled&&this.channels.set("discord",new Br(this.config.channels.discord,this.bus,this.logger))}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:{[yi]:!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?.[yi])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await qe(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,this.logger?.info("message.outbound","sent",{channel:e.channel,chatId:e.chatId,replyToMessageId:e.metadata?.message_id,threadId:e.metadata?.thread_id,progress:e.metadata?._progress===!0,content:e.content.slice(0,80)})}catch(a){s=a,this.logger?.error("message.outbound","failed",{channel:e.channel,chatId:e.chatId,error:a instanceof Error?a.message:String(a),content:e.content.slice(0,80)})}}else n&&this.logger?.info("message.outbound","skipped",{channel:e.channel,chatId:e.chatId,reason:n,progress:e.metadata?._progress===!0,content:e.content.slice(0,80)});try{await qe(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}]))}};Ue();import{randomUUID as Sc}from"node:crypto";import kc from"node:path";function Cc(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 xc(o){return kc.resolve(o)}function bi(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:Cc(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Xt=class{storage;workspace;constructor(e,t,n){this.workspace=xc(e),this.storage=n??Fe({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
317
+ 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=fc(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<kc||(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 bi from"ws";var Ur=class extends Yt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t,n){super(e,t,e.debounce,n),this.inbox=new Xt(e.debounce,r=>this.handleMessage(r))}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 bi(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!==bi.OPEN||this.ws.send(JSON.stringify(e))}};var wi="_shutdown",Gr=class{constructor(e,t,n,r){this.config=e;this.bus=t;this.lifecycle=n??ot(),this.logger=r,this.initChannels()}channels=new Map;channelTasks=new Map;dispatchLoop=null;stopping=!1;lifecycle;logger;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new Br(this.config.channels.telegram,this.bus,this.logger)),this.config.channels.discord.enabled&&this.channels.set("discord",new Ur(this.config.channels.discord,this.bus,this.logger))}async startAll(){if(this.channels.size){this.stopping=!1,this.dispatchLoop=this.dispatchOutbound();for(let[e,t]of this.channels){if(this.channelTasks.has(e))continue;let n=t.start().catch(r=>{this.logger?.error("channel","start_failed",{channel:e,error:r instanceof Error?r.message:String(r)})}).finally(()=>{this.channelTasks.delete(e)});this.channelTasks.set(e,n)}}}async stopAll(){this.stopping=!0,await Promise.all([...this.channels.values()].map(e=>e.stop().catch(()=>{}))),await Promise.allSettled(this.channelTasks.values()),this.dispatchLoop&&(await this.bus.publishOutbound({channel:"system",chatId:"gateway:shutdown",content:"",metadata:{[wi]:!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?.[wi])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await ze(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,this.logger?.info("message.outbound","sent",{channel:e.channel,chatId:e.chatId,replyToMessageId:e.metadata?.message_id,threadId:e.metadata?.thread_id,progress:e.metadata?._progress===!0,content:e.content.slice(0,80)})}catch(a){s=a,this.logger?.error("message.outbound","failed",{channel:e.channel,chatId:e.chatId,error:a instanceof Error?a.message:String(a),content:e.content.slice(0,80)})}}else n&&this.logger?.info("message.outbound","skipped",{channel:e.channel,chatId:e.chatId,reason:n,progress:e.metadata?._progress===!0,content:e.content.slice(0,80)});try{await ze(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}]))}};We();import{randomUUID as Cc}from"node:crypto";import xc from"node:path";function Tc(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 Rc(o){return xc.resolve(o)}function vi(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:Tc(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Qt=class{storage;workspace;constructor(e,t,n){this.workspace=Rc(e),this.storage=n??Ue({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
318
318
  FROM inbox_deliveries
319
319
  WHERE workspace = ?
320
320
  AND (? = 1 OR cleared_at IS NULL)
321
- ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>bi(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
321
+ ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>vi(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
322
322
  FROM inbox_deliveries
323
- WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return bi(t)}record(e){let t=String(e.deliveredAt??le()),n=Sc();return this.storage.prepare(`INSERT INTO inbox_deliveries (
323
+ WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return vi(t)}record(e){let t=String(e.deliveredAt??le()),n=Cc();return this.storage.prepare(`INSERT INTO inbox_deliveries (
324
324
  workspace, delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
325
325
  ) 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=le()){return this.storage.prepare(`UPDATE inbox_deliveries
326
326
  SET cleared_at = COALESCE(cleared_at, ?)
327
- WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};je();Ue();import fe,{existsSync as At,unlinkSync as Jc}from"node:fs";import Re,{join as Hc}from"node:path";import{createServer as qc}from"node:http";import{spawn as Ii}from"node:child_process";function Gr(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function Rt(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function wi(o){let e="local_process",t=Rt(o.runtime.overload?.rateLimited)+Rt(o.runtime.overload?.backpressured),n=Rt(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,Rt(o.config.tools.exec.timeout)),runningSubagents:Rt(o.runtime.subagents),queuedMessages:Rt(o.runtime.queuedMessages),queuedSessions:Rt(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:Gr("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:Gr(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:Gr("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:Gr("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 De from"node:fs";import st from"node:path";import{randomUUID as Tc}from"node:crypto";function Rc(o){return o.split(st.sep).join("/")}function Ac(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 Ec=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),_c={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function Pc(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":Ec.has(e)?"image":"binary"}function xn(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return _c[e]||"image"}function Mc(o,e=!1,t=128*1024){if(!De.existsSync(o)||!De.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=De.statSync(o),r=Pc(o);if(r==="image"){let x=Math.min(n.size,5242881),y=Buffer.alloc(x),u=De.openSync(o,"r");try{x>0&&De.readSync(u,y,0,x,0)}finally{De.closeSync(u)}let b=xn(o)==="image-jpeg"?"image/jpeg":xn(o)==="image-png"?"image/png":xn(o)==="image-gif"?"image/gif":xn(o)==="image-webp"?"image/webp":xn(o)==="image-svg"?"image/svg+xml":"image/png",T=y.toString("base64"),v=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:v?"Image preview truncated.":"Image preview available.",content:null,truncated:v,imageDataUrl:`data:${b};base64,${T}`}}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=De.openSync(o,"r");try{s>0&&De.readSync(a,i,0,s,0)}finally{De.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:Ac(d),content:e?d:null,truncated:l}}var Wr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=st.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Fe({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return st.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=st.isAbsolute(t)?st.resolve(t):st.resolve(this.workspacePath,t);try{Ge(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!De.existsSync(n))throw new Error(`File not found: ${t}`);if(!De.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=Rc(st.relative(this.workspacePath,n));return{relativePath:r,displayName:st.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
327
+ WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};Be();We();import fe,{existsSync as Et,unlinkSync as qc}from"node:fs";import _e,{join as zc}from"node:path";import{createServer as Vc}from"node:http";import{spawn as $i}from"node:child_process";function Wr(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function At(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function Si(o){let e="local_process",t=At(o.runtime.overload?.rateLimited)+At(o.runtime.overload?.backpressured),n=At(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,At(o.config.tools.exec.timeout)),runningSubagents:At(o.runtime.subagents),queuedMessages:At(o.runtime.queuedMessages),queuedSessions:At(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:Wr("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:Wr(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:Wr("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:Wr("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 Fe from"node:fs";import it from"node:path";import{randomUUID as Ac}from"node:crypto";function Ec(o){return o.split(it.sep).join("/")}function _c(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 Pc=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),Mc={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function Ic(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":Pc.has(e)?"image":"binary"}function Tn(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return Mc[e]||"image"}function Lc(o,e=!1,t=128*1024){if(!Fe.existsSync(o)||!Fe.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=Fe.statSync(o),r=Ic(o);if(r==="image"){let x=Math.min(n.size,5242881),y=Buffer.alloc(x),u=Fe.openSync(o,"r");try{x>0&&Fe.readSync(u,y,0,x,0)}finally{Fe.closeSync(u)}let b=Tn(o)==="image-jpeg"?"image/jpeg":Tn(o)==="image-png"?"image/png":Tn(o)==="image-gif"?"image/gif":Tn(o)==="image-webp"?"image/webp":Tn(o)==="image-svg"?"image/svg+xml":"image/png",T=y.toString("base64"),v=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:v?"Image preview truncated.":"Image preview available.",content:null,truncated:v,imageDataUrl:`data:${b};base64,${T}`}}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=Fe.openSync(o,"r");try{s>0&&Fe.readSync(a,i,0,s,0)}finally{Fe.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:_c(d),content:e?d:null,truncated:l}}var Kr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=it.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Ue({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return it.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=it.isAbsolute(t)?it.resolve(t):it.resolve(this.workspacePath,t);try{Ke(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!Fe.existsSync(n))throw new Error(`File not found: ${t}`);if(!Fe.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=Ec(it.relative(this.workspacePath,n));return{relativePath:r,displayName:it.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
328
328
  FROM session_files
329
- 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=Mc(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
329
+ 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=Lc(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
330
330
  FROM session_files
331
331
  WHERE workspace = ? AND session_key = ?
332
332
  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
333
333
  FROM session_files
334
- 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:Tc(),relative_path:n.relativePath,display_name:n.displayName,created_at:le(),updated_at:le()};this.getStorage().prepare(`INSERT INTO session_files (
334
+ 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:Ac(),relative_path:n.relativePath,display_name:n.displayName,created_at:le(),updated_at:le()};this.getStorage().prepare(`INSERT INTO session_files (
335
335
  workspace, session_key, file_id, relative_path, display_name, created_at, updated_at
336
336
  ) 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
337
- 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 Ic from"node:os";import vi from"node:path";Ue();kt();je();var Fo="clawhub@latest",Si=12e4;function ki(o){let e=o?.runner??new ve,t=()=>{let n=_(),r=Z(n.agents.defaults.workspace);return ft(r,!0),r};return{getSnapshot(){let n=t(),r=vi.join(n,"skills"),s=vi.join(Ic.homedir(),".agents","skills"),i=new He(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${Fo} search <query> --limit 5`,installTemplate:Kr(["install","<slug>"],n),list:Kr(["list"],n),update:Kr(["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(!qn(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",Fo,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:Si,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(Lc(i));return{slug:r,workspacePath:s,command:Kr(["install",r],s),output:Ci(i),restartRequired:!0}}}}function Kr(o,e){return["npx","--yes",Fo,...o,"--workdir",e].map($c).join(" ")}function $c(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function Ci(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
337
+ 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 $c from"node:os";import ki from"node:path";We();Ct();Be();var Bo="clawhub@latest",Ci=12e4;function xi(o){let e=o?.runner??new ve,t=()=>{let n=_(),r=Z(n.agents.defaults.workspace);return ht(r,!0),r};return{getSnapshot(){let n=t(),r=ki.join(n,"skills"),s=ki.join($c.homedir(),".agents","skills"),i=new qe(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${Bo} search <query> --limit 5`,installTemplate:Jr(["install","<slug>"],n),list:Jr(["list"],n),update:Jr(["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(!zn(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",Bo,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:Ci,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(Nc(i));return{slug:r,workspacePath:s,command:Jr(["install",r],s),output:Ti(i),restartRequired:!0}}}}function Jr(o,e){return["npx","--yes",Bo,...o,"--workdir",e].map(Oc).join(" ")}function Oc(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function Ti(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
338
338
 
339
- `).trim()||"Skill installed."}function Lc(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(Si/1e3)} seconds.`;let e=Ci(o),t=typeof o.exitCode=="number"?`
339
+ `).trim()||"Skill installed."}function Nc(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(Ci/1e3)} seconds.`;let e=Ti(o),t=typeof o.exitCode=="number"?`
340
340
  Exit code: ${o.exitCode}`:"",n=o.signal?`
341
- Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}je();de();import{scrypt as Oc,randomBytes as Ti,timingSafeEqual as Nc}from"node:crypto";var Ri=64,Ai=16384,Ei=8,_i=1,Dc=5,xi=300*1e3;function jc(){let o=Ti(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 Pi(o,e,t,n){let r=n??{};return new Promise((s,i)=>{Oc(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function Fc(o,e){let t=e??Ti(16),n=await Pi(o,t,Ri,{N:Ai,r:Ei,p:_i});return`${t.toString("hex")}:${n.toString("hex")}`}async function Bc(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 Pi(o,n,Ri,{N:Ai,r:Ei,p:_i});return s.length!==r.length?!1:Nc(s,r)}var Jr=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 Fc(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?Bc(e,this.config.pinHash):!1}createSession(){let e=jc(),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)>=Dc}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+xi-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()-xi;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function $i(o){let e=Re.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 Li(o){return o.startsWith("text/")||o==="application/json"}function zc(){let o=et("dashboard");if(!o)return null;let e=Re.join(o,"index.html");return fe.existsSync(e)?o:null}function ie(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 w(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function Vc(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function zr(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function Vr(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 Yc(o){let e=zr(o),t=[...e].reverse().find(n=>Vr(n.content));return{messageCount:e.length,lastMessagePreview:t?Vr(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function Xc(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Wo(o){return typeof o=="string"?o.trim():""}function Ui(o){return Wo(o?.metadata?.displayName)||null}function Qc(o){let e=new Set;for(let n of o){let r=Ui(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 Zc(o,e){let t=Xc(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function Go(o){let e=new Set,t=[];for(let n of[...zr(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:Vr(r,56)??r}),t.length>=3))break}return t}function qr(o,e,t,n){let{channel:r,chatId:s}=Vc(o.key),i=Yc(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Ui(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 Oi(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 Ni(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function Di(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 ji(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function ed(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 it(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Ko(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function td(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Fi(o,e,t){return td(o.socket.remoteAddress)?!0:(w(e,403,{error:t}),!1)}function _n(o){return o.map(e=>String(e)).join(".")}function Jo(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!it(t))return;t=t[n]}return t}function Ae(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 ${_n(e)}`);let c=n[i],d=e[s+1];c===void 0&&(n[i]=typeof d=="number"?[]:{}),n=n[i];continue}if(!it(n))throw new Error(`Expected object while writing ${_n(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 ${_n(e)}`);n[r]=t;return}if(!it(n))throw new Error(`Expected object while writing ${_n(e)}`);n[r]=t}function Xe(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??Ko(o):null}}function nd(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))Ae(t,["providers",n,"apiKey"],Xe(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{Ae(t,["customLlmProviders",r,"apiKey"],Xe(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),Ae(t,["channels","telegram","token"],Xe(o.channels.telegram.token)),Ae(t,["channels","discord","token"],Xe(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",Ae(t,["security","auth","pinHash"],Xe(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",Ae(t,["tools","browserRelay","authToken"],Xe(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",Ae(t,["tools","web","search","apiKey"],Xe(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??{}))Ae(t,["tools","mcpServers",n,"env",s],Xe(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))Ae(t,["tools","mcpServers",n,"headers",s],Xe(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function Gi(o,e,t,n){let r=Jo(o,e),s=_n(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(!it(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 Et(o,e,t,n){let r=String(Jo(e,n)??""),s=String(Jo(o,n)??""),i=Gi(t,n,r,s);if(i){if(i.action==="keep"){Ae(o,n,r);return}if(i.action==="clear"){Ae(o,n,"");return}Ae(o,n,i.value??s)}}function Bi(o){return it(o)&&Object.values(o).every(e=>typeof e=="string")}function rd(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function od(o){if(!it(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),!it(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&&!rd(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&&!Bi(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!Bi(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 sd(o){if(Array.isArray(o.customAcpProviders))return o;let e=_();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var id=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),ad={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Wi(o){let e=zc(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??ki(),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 Jr(o.config.security.auth),c=()=>(r||(r=new Wr(o.workspacePath??process.cwd(),o.dataDir)),r),d=()=>(s||(s=new Xt(o.workspacePath??process.cwd(),o.dataDir)),s),p=y=>typeof o.sessionManager.listSessions!="function"?y===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===y)||y===o.sessionKey,g=(y,u)=>{let b=y||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:u,session:b}}},x=qc(async(y,u)=>{let b=y.method||"GET",T=new URL(y.url||"/",`http://${y.headers.host||"localhost"}`),v=T.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 O=ad[b]??"\x1B[0m";if(console.log(`[gateway] ${O}${b}\x1B[0m ${v}`),l.isEnabled&&v.startsWith("/api/")&&!id.has(v)){let f=y.headers["x-auth-token"];if(!f||typeof f!="string"||!l.validateSession(f))return w(u,401,{error:"Authentication required"});l.touchSession(f)}if(!l.isEnabled&&v==="/api/config"&&(b==="GET"||b==="PUT")&&!Fi(y,u,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&v==="/api/auth/login"){let f=await ie(y),h=String(f.pin??"");if(!h)return w(u,400,{error:"PIN is required"});let m=y.socket.remoteAddress??"unknown";if(l.isRateLimited(m)){let A=l.getRateLimitRemainingMs(m);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:A})}if(!l.hasPin)return w(u,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(h))return l.recordFailedAttempt(m),w(u,401,{error:"Invalid PIN"});l.clearFailedAttempts(m);let C=l.createSession();return w(u,200,{token:C})}if(b==="GET"&&v==="/api/auth/status")return w(u,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&v==="/api/auth/logout"){let f=y.headers["x-auth-token"];return!f||typeof f!="string"?w(u,200,{ok:!0}):(l.invalidateSession(f),w(u,200,{ok:!0}))}if(b==="POST"&&v==="/api/auth/set-pin"){let f=await ie(y),h=String(f.newPin??""),m=f.currentPin!==void 0?String(f.currentPin):void 0;if(!h)return w(u,400,{error:"newPin is required"});if(h.length!==6)return w(u,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(h))return w(u,400,{error:"PIN must contain only digits"});if(l.hasPin){let R=y.headers["x-auth-token"];if(!(R&&typeof R=="string"&&l.validateSession(R))){let P=y.socket.remoteAddress??"unknown";if(l.isRateLimited(P)){let Q=l.getRateLimitRemainingMs(P);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:Q})}if(!m)return w(u,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(m))return l.recordFailedAttempt(P),w(u,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(P)}}else{let R=process.env.EVERCLAW_BOOTSTRAP_PIN;if(R&&String(f.bootstrapSecret??"")!==R)return w(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,C=await l.setPin(h);k||l.reset();let A=_();return A.security?.auth&&(A.security.auth.pinHash=C,oe(A)),w(u,200,{ok:!0,message:k?"PIN set successfully":"PIN changed successfully"})}let G=()=>w(u,503,{error:"Gateway is shutting down. Please try again later."}),I=v.match(/^\/api\/cron\/jobs\/([^/]+)$/),V=v.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),N=v.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),D=v.match(/^\/api\/inbox-deliveries\/([^/]+)$/),Y=v.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),j=v.match(/^\/api\/sessions\/([^/]+)$/),J=v.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&v==="/api/chat"||b==="POST"&&v==="/api/sessions"||b==="PUT"&&!!j||b==="PUT"&&v==="/api/config"||b==="POST"&&v==="/api/skills/install"||b==="POST"&&!!Y||b==="POST"&&v==="/api/session-files"||b==="POST"&&v==="/api/cron/jobs"||b==="DELETE"&&!!J||b==="DELETE"&&!!I||b==="POST"&&!!V||b==="POST"&&!!N))return G();if(b==="GET"&&v==="/api/status"){let f=_(),h=o.agent.getRuntimeState(),m=o.cron.status(),k=wi({config:f,runtime:h,cron:m}),C=structuredClone(f.channels);C.telegram?.token&&(C.telegram.token=Ko(C.telegram.token)),C.discord?.token&&(C.discord.token=Ko(C.discord.token));let A=o.channelManager?.getStatus()??{};return w(u,200,{provider:f.agents.defaults.provider,model:f.agents.defaults.model,cron:m,channels:C,channelStatus:A,gateway:{...f.gateway,port:t},runtime:h,isolation:k,shutdown:{active:i||!h.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&v==="/api/chrome-session/status"){let f=_(),h=T.searchParams.get("port"),m=h?parseInt(h,10):f.tools.chromeSession?.debugPort??9222,k=f.tools.chromeSession?.minChromeVersion??136,C=await Ut(m);if(!C)return w(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:m});if(C.pendingApproval)return w(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=${C.port} --user-data-dir=/tmp/chrome-debug-profile`,port:C.port,debugPort:m});let{port:A,versionInfo:R}=C,E=R.Browser.match(/(\w+)\/(\d+)/),P=E?.[1]??"Chrome",M=E?parseInt(E[2],10):0;return M>0&&M<k?w(u,200,{available:!1,reason:`Chrome version ${M} is below minimum required version ${k}`,hint:`Update Chrome to version ${k} or higher`,version:R.Browser,port:A,browser:P,debugPort:m}):w(u,200,{available:!0,version:R.Browser,remoteDebugging:!0,port:A,browser:P,debugPort:m})}if(b==="POST"&&v==="/api/chrome-session/launch"){let f=await ie(y),h=_(),m=f.port??h.tools.chromeSession?.debugPort??9222,k=await Ut(m);if(k&&!k.pendingApproval){let M=k.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!1,alreadyRunning:!0,port:k.port,version:k.versionInfo.Browser,browser:M?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${k.port}. No need to launch.`})}if(k?.pendingApproval)return w(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 C="/tmp/chrome-debug-profile",A=Hc(C,"DevToolsActivePort");try{Jc(A)}catch{}let R=process.platform,E,P=[`--remote-debugging-port=${m}`,`--user-data-dir=${C}`];if(R==="darwin"){let M=["/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"],Q=M.find(F=>At(F));if(!Q)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or specify the path manually."});E=Q}else if(R==="win32"){E="cmd.exe";let M=process.env.ProgramFiles??"C:\\Program Files",Q=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",F=[`${M}\\Google\\Chrome\\Application\\chrome.exe`,`${Q}\\Google\\Chrome\\Application\\chrome.exe`,`${M}\\Microsoft\\Edge\\Application\\msedge.exe`,`${Q}\\Microsoft\\Edge\\Application\\msedge.exe`],ge=F.find(ee=>At(ee));if(!ge)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:F,hint:"Install Google Chrome or Microsoft Edge."});P=["/c","start","",ge,`--remote-debugging-port=${m}`]}else{let M=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],Q=M.find(F=>At(F));if(!Q)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or Chromium."});E=Q}try{let M=Ii(E,P,{detached:!0,stdio:"ignore"}),Q=await Promise.race([new Promise(ee=>M.once("error",ee)),new Promise(ee=>setTimeout(()=>ee(null),500))]);if(Q)return w(u,500,{ok:!1,error:Q.message,chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});M.unref();let F;for(let ee=0;ee<5&&(await new Promise(Qe=>setTimeout(Qe,1e3)),F=await Ut(m),!F);ee++);if(!F)return w(u,200,{ok:!1,launched:!0,port:m,chromePath:E,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(F.pendingApproval)return w(u,200,{ok:!1,launched:!0,pendingApproval:!0,port:F.port,chromePath:E,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 ge=F.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!0,port:F.port,chromePath:E,version:F.versionInfo.Browser,browser:ge?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${F.port}`})}catch(M){return w(u,500,{ok:!1,error:M instanceof Error?M.message:String(M),chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&v==="/api/browser-relay/status"){let h=_().tools.browserRelay;if(!h.enabled)return w(u,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:h.extensionPath});if(o.browserRelay){let m=o.browserRelay.getStatus();return w(u,200,{enabled:!0,connected:m.connected,attachedTabs:m.attachedTabs,lastPing:m.lastPing,extensionPath:h.extensionPath})}return w(u,200,{enabled:h.enabled,connected:!1,attachedTabs:[],extensionPath:h.extensionPath})}if(b==="GET"&&v==="/api/browser-relay/config"){if(!Fi(y,u,"Browser Relay bootstrap is only available from localhost."))return;let f=_(),h=f.tools.browserRelay;return w(u,200,{enabled:h.enabled,port:f.gateway.port,token:h.enabled&&h.authToken||""})}if(b==="POST"&&v==="/api/browser-relay/launch"){let f=await ie(y),h=_(),m=f.extensionPath??h.tools.browserRelay.extensionPath;if(!m)return w(u,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let k=process.platform,C,A=[`--load-extension=${m}`,"--no-first-run","--no-default-browser-check"];if(k==="darwin")C=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(At)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(k==="win32"){let R=process.env.ProgramFiles??"C:\\Program Files",E=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";C=[`${R}\\Google\\Chrome\\Application\\chrome.exe`,`${E}\\Google\\Chrome\\Application\\chrome.exe`].find(At)??`${R}\\Google\\Chrome\\Application\\chrome.exe`}else C="google-chrome";try{return Ii(C,A,{detached:!0,stdio:"ignore"}).unref(),w(u,200,{ok:!0,launched:!0,extensionPath:m,message:`Chrome launched with extension from ${m}`})}catch(R){return w(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 U=v.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),L=Z(o.config.agents.defaults.workspace);if(b==="GET"&&v==="/api/automations"){let f=Kt(L);return w(u,200,f)}if(b==="GET"&&U&&U[1]&&!U[2]){let f=U[1],h=Te(L,f);return h?w(u,200,h):w(u,404,{error:"Automation not found"})}if(b==="POST"&&v==="/api/automations"){let f=await ie(y);try{let h={name:String(f.name??"Untitled"),description:String(f.description??""),steps:f.steps||[],tags:f.tags||[],source:f.source||"manual"};f.toolType!==void 0&&(h.toolType=f.toolType),f.variables!==void 0&&(h.variables=f.variables);let m=hr(L,h);return w(u,201,m)}catch(h){return w(u,400,{error:String(h)})}}if(b==="PUT"&&U&&U[1]&&!U[2]){let f=U[1],h=await ie(y),m={};h.name!==void 0&&(m.name=String(h.name)),h.description!==void 0&&(m.description=String(h.description)),h.enabled!==void 0&&(m.enabled=!!h.enabled),h.steps!==void 0&&(m.steps=h.steps),h.tags!==void 0&&(m.tags=h.tags),h.toolType!==void 0&&(m.toolType=h.toolType),h.variables!==void 0&&(m.variables=h.variables);let k=yr(L,f,m);return k?w(u,200,k):w(u,404,{error:"Automation not found"})}if(b==="DELETE"&&U&&U[1]){let f=U[1];return Jt(L,f)?w(u,200,{ok:!0}):w(u,404,{error:"Automation not found"})}if(b==="POST"&&U&&U[1]&&U[2]==="/run"){let f=U[1],h=Te(L,f);return h?h.enabled?(o.agent.tools.execute("automation",{command:"run",id:f}).then(m=>{console.log(`[automation] Execution of '${h.name}' finished`,{logs:m.kind==="ok"?m.content:m})}).catch(m=>{console.error(`[automation] Execution of '${h.name}' failed`,{err:m})}),w(u,200,{ok:!0,message:`Automation '${h.name}' execution started in background.`})):w(u,400,{error:"Automation is disabled"}):w(u,404,{error:"Automation not found"})}if(b==="GET"&&v==="/api/history"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session history not found.");if(h.error)return w(u,404,h.error);let m=h.sessionKey,k=o.sessionManager.getOrCreate(m);return w(u,200,{session:m,messages:zr(k.messages)})}if(b==="GET"&&v==="/api/sessions"){let f=o.agent.getRuntimeState(),h=new Set((f.sessions||[]).filter(C=>C.running||C.queued>0).map(C=>C.key)),m=o.sessionManager.getOrCreate(o.sessionKey),k=o.sessionManager.listSessions().filter(C=>String(C.key??"")!==o.sessionKey).map(C=>{let A=String(C.key??"");return qr({key:A,created_at:String(C.created_at??m.createdAt),updated_at:String(C.updated_at??m.updatedAt)},o.sessionKey,h.has(A),o.sessionManager.getOrCreate(A))});return w(u,200,{currentSession:o.sessionKey,sessions:[qr({key:m.key,created_at:m.createdAt,updated_at:m.updatedAt},o.sessionKey,h.has(m.key),m),...k]})}if(b==="GET"&&v==="/api/files/preview"){let f=String(T.searchParams.get("path")??"").trim(),h=parseInt(T.searchParams.get("maxLines")??"100",10),m=o.workspacePath??process.cwd();if(!f)return w(u,400,{error:"path required"});try{Ge(f,m)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!At(f))return w(u,404,{error:"file not found"});try{let k=fe.statSync(f);if(k.isDirectory())return w(u,400,{error:"path is a directory"});let C=$i(f),A=fe.readFileSync(f),R=null,E=!1;if(Li(C)){let F=A.toString("utf-8").split(`
341
+ Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}Be();ce();import{scrypt as Dc,randomBytes as Ai,timingSafeEqual as jc}from"node:crypto";var Ei=64,_i=16384,Pi=8,Mi=1,Fc=5,Ri=300*1e3;function Bc(){let o=Ai(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 Ii(o,e,t,n){let r=n??{};return new Promise((s,i)=>{Dc(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function Uc(o,e){let t=e??Ai(16),n=await Ii(o,t,Ei,{N:_i,r:Pi,p:Mi});return`${t.toString("hex")}:${n.toString("hex")}`}async function Gc(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 Ii(o,n,Ei,{N:_i,r:Pi,p:Mi});return s.length!==r.length?!1:jc(s,r)}var Hr=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 Uc(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?Gc(e,this.config.pinHash):!1}createSession(){let e=Bc(),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)>=Fc}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+Ri-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()-Ri;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function Oi(o){let e=_e.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 Ni(o){return o.startsWith("text/")||o==="application/json"}function Yc(){let o=tt("dashboard");if(!o)return null;let e=_e.join(o,"index.html");return fe.existsSync(e)?o:null}function ie(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 w(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function Xc(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Vr(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function Yr(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 Qc(o){let e=Vr(o),t=[...e].reverse().find(n=>Yr(n.content));return{messageCount:e.length,lastMessagePreview:t?Yr(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function Zc(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Ko(o){return typeof o=="string"?o.trim():""}function Wi(o){return Ko(o?.metadata?.displayName)||null}function ed(o){let e=new Set;for(let n of o){let r=Wi(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 td(o,e){let t=Zc(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function Wo(o){let e=new Set,t=[];for(let n of[...Vr(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:Yr(r,56)??r}),t.length>=3))break}return t}function zr(o,e,t,n){let{channel:r,chatId:s}=Xc(o.key),i=Qc(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Wi(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 Di(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 ji(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function Fi(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 Bi(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function nd(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 at(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Jo(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function rd(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Ui(o,e,t){return rd(o.socket.remoteAddress)?!0:(w(e,403,{error:t}),!1)}function Pn(o){return o.map(e=>String(e)).join(".")}function Ho(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!at(t))return;t=t[n]}return t}function Pe(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 ${Pn(e)}`);let c=n[i],d=e[s+1];c===void 0&&(n[i]=typeof d=="number"?[]:{}),n=n[i];continue}if(!at(n))throw new Error(`Expected object while writing ${Pn(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 ${Pn(e)}`);n[r]=t;return}if(!at(n))throw new Error(`Expected object while writing ${Pn(e)}`);n[r]=t}function Qe(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??Jo(o):null}}function od(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))Pe(t,["providers",n,"apiKey"],Qe(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{Pe(t,["customLlmProviders",r,"apiKey"],Qe(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),Pe(t,["channels","telegram","token"],Qe(o.channels.telegram.token)),Pe(t,["channels","discord","token"],Qe(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",Pe(t,["security","auth","pinHash"],Qe(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",Pe(t,["tools","browserRelay","authToken"],Qe(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",Pe(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??{}))Pe(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??{}))Pe(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 Ki(o,e,t,n){let r=Ho(o,e),s=Pn(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(!at(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 _t(o,e,t,n){let r=String(Ho(e,n)??""),s=String(Ho(o,n)??""),i=Ki(t,n,r,s);if(i){if(i.action==="keep"){Pe(o,n,r);return}if(i.action==="clear"){Pe(o,n,"");return}Pe(o,n,i.value??s)}}function Gi(o){return at(o)&&Object.values(o).every(e=>typeof e=="string")}function sd(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function id(o){if(!at(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),!at(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&&!sd(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&&!Gi(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!Gi(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 ad(o){if(Array.isArray(o.customAcpProviders))return o;let e=_();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var ld=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),cd={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Ji(o){let e=Yc(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??xi(),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 Hr(o.config.security.auth),c=()=>(r||(r=new Kr(o.workspacePath??process.cwd(),o.dataDir)),r),d=()=>(s||(s=new Qt(o.workspacePath??process.cwd(),o.dataDir)),s),p=y=>typeof o.sessionManager.listSessions!="function"?y===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===y)||y===o.sessionKey,g=(y,u)=>{let b=y||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:u,session:b}}},x=Vc(async(y,u)=>{let b=y.method||"GET",T=new URL(y.url||"/",`http://${y.headers.host||"localhost"}`),v=T.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 O=cd[b]??"\x1B[0m";if(console.log(`[gateway] ${O}${b}\x1B[0m ${v}`),l.isEnabled&&v.startsWith("/api/")&&!ld.has(v)){let f=y.headers["x-auth-token"];if(!f||typeof f!="string"||!l.validateSession(f))return w(u,401,{error:"Authentication required"});l.touchSession(f)}if(!l.isEnabled&&v==="/api/config"&&(b==="GET"||b==="PUT")&&!Ui(y,u,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&v==="/api/auth/login"){let f=await ie(y),h=String(f.pin??"");if(!h)return w(u,400,{error:"PIN is required"});let m=y.socket.remoteAddress??"unknown";if(l.isRateLimited(m)){let A=l.getRateLimitRemainingMs(m);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:A})}if(!l.hasPin)return w(u,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(h))return l.recordFailedAttempt(m),w(u,401,{error:"Invalid PIN"});l.clearFailedAttempts(m);let C=l.createSession();return w(u,200,{token:C})}if(b==="GET"&&v==="/api/auth/status")return w(u,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&v==="/api/auth/logout"){let f=y.headers["x-auth-token"];return!f||typeof f!="string"?w(u,200,{ok:!0}):(l.invalidateSession(f),w(u,200,{ok:!0}))}if(b==="POST"&&v==="/api/auth/set-pin"){let f=await ie(y),h=String(f.newPin??""),m=f.currentPin!==void 0?String(f.currentPin):void 0;if(!h)return w(u,400,{error:"newPin is required"});if(h.length!==6)return w(u,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(h))return w(u,400,{error:"PIN must contain only digits"});if(l.hasPin){let R=y.headers["x-auth-token"];if(!(R&&typeof R=="string"&&l.validateSession(R))){let P=y.socket.remoteAddress??"unknown";if(l.isRateLimited(P)){let Q=l.getRateLimitRemainingMs(P);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:Q})}if(!m)return w(u,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(m))return l.recordFailedAttempt(P),w(u,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(P)}}else{let R=process.env.EVERCLAW_BOOTSTRAP_PIN;if(R&&String(f.bootstrapSecret??"")!==R)return w(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,C=await l.setPin(h);k||l.reset();let A=_();return A.security?.auth&&(A.security.auth.pinHash=C,oe(A)),w(u,200,{ok:!0,message:k?"PIN set successfully":"PIN changed successfully"})}let G=()=>w(u,503,{error:"Gateway is shutting down. Please try again later."}),I=v.match(/^\/api\/cron\/jobs\/([^/]+)$/),V=v.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),N=v.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),D=v.match(/^\/api\/inbox-deliveries\/([^/]+)$/),Y=v.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),j=v.match(/^\/api\/sessions\/([^/]+)$/),J=v.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&v==="/api/chat"||b==="POST"&&v==="/api/sessions"||b==="PUT"&&!!j||b==="PUT"&&v==="/api/config"||b==="POST"&&v==="/api/skills/install"||b==="POST"&&!!Y||b==="POST"&&v==="/api/session-files"||b==="POST"&&v==="/api/cron/jobs"||b==="DELETE"&&!!J||b==="DELETE"&&!!I||b==="POST"&&!!V||b==="POST"&&!!N))return G();if(b==="GET"&&v==="/api/status"){let f=_(),h=o.agent.getRuntimeState(),m=o.cron.status(),k=Si({config:f,runtime:h,cron:m}),C=structuredClone(f.channels);C.telegram?.token&&(C.telegram.token=Jo(C.telegram.token)),C.discord?.token&&(C.discord.token=Jo(C.discord.token));let A=o.channelManager?.getStatus()??{};return w(u,200,{provider:f.agents.defaults.provider,model:f.agents.defaults.model,cron:m,channels:C,channelStatus:A,gateway:{...f.gateway,port:t},runtime:h,isolation:k,shutdown:{active:i||!h.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&v==="/api/chrome-session/status"){let f=_(),h=T.searchParams.get("port"),m=h?parseInt(h,10):f.tools.chromeSession?.debugPort??9222,k=f.tools.chromeSession?.minChromeVersion??136,C=await Gt(m);if(!C)return w(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:m});if(C.pendingApproval)return w(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=${C.port} --user-data-dir=/tmp/chrome-debug-profile`,port:C.port,debugPort:m});let{port:A,versionInfo:R}=C,E=R.Browser.match(/(\w+)\/(\d+)/),P=E?.[1]??"Chrome",M=E?parseInt(E[2],10):0;return M>0&&M<k?w(u,200,{available:!1,reason:`Chrome version ${M} is below minimum required version ${k}`,hint:`Update Chrome to version ${k} or higher`,version:R.Browser,port:A,browser:P,debugPort:m}):w(u,200,{available:!0,version:R.Browser,remoteDebugging:!0,port:A,browser:P,debugPort:m})}if(b==="POST"&&v==="/api/chrome-session/launch"){let f=await ie(y),h=_(),m=f.port??h.tools.chromeSession?.debugPort??9222,k=await Gt(m);if(k&&!k.pendingApproval){let M=k.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!1,alreadyRunning:!0,port:k.port,version:k.versionInfo.Browser,browser:M?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${k.port}. No need to launch.`})}if(k?.pendingApproval)return w(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 C="/tmp/chrome-debug-profile",A=zc(C,"DevToolsActivePort");try{qc(A)}catch{}let R=process.platform,E,P=[`--remote-debugging-port=${m}`,`--user-data-dir=${C}`];if(R==="darwin"){let M=["/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"],Q=M.find(F=>Et(F));if(!Q)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or specify the path manually."});E=Q}else if(R==="win32"){E="cmd.exe";let M=process.env.ProgramFiles??"C:\\Program Files",Q=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",F=[`${M}\\Google\\Chrome\\Application\\chrome.exe`,`${Q}\\Google\\Chrome\\Application\\chrome.exe`,`${M}\\Microsoft\\Edge\\Application\\msedge.exe`,`${Q}\\Microsoft\\Edge\\Application\\msedge.exe`],ge=F.find(ee=>Et(ee));if(!ge)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:F,hint:"Install Google Chrome or Microsoft Edge."});P=["/c","start","",ge,`--remote-debugging-port=${m}`]}else{let M=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],Q=M.find(F=>Et(F));if(!Q)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or Chromium."});E=Q}try{let M=$i(E,P,{detached:!0,stdio:"ignore"}),Q=await Promise.race([new Promise(ee=>M.once("error",ee)),new Promise(ee=>setTimeout(()=>ee(null),500))]);if(Q)return w(u,500,{ok:!1,error:Q.message,chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});M.unref();let F;for(let ee=0;ee<5&&(await new Promise(Ze=>setTimeout(Ze,1e3)),F=await Gt(m),!F);ee++);if(!F)return w(u,200,{ok:!1,launched:!0,port:m,chromePath:E,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(F.pendingApproval)return w(u,200,{ok:!1,launched:!0,pendingApproval:!0,port:F.port,chromePath:E,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 ge=F.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!0,port:F.port,chromePath:E,version:F.versionInfo.Browser,browser:ge?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${F.port}`})}catch(M){return w(u,500,{ok:!1,error:M instanceof Error?M.message:String(M),chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&v==="/api/browser-relay/status"){let h=_().tools.browserRelay;if(!h.enabled)return w(u,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:h.extensionPath});if(o.browserRelay){let m=o.browserRelay.getStatus();return w(u,200,{enabled:!0,connected:m.connected,attachedTabs:m.attachedTabs,lastPing:m.lastPing,extensionPath:h.extensionPath})}return w(u,200,{enabled:h.enabled,connected:!1,attachedTabs:[],extensionPath:h.extensionPath})}if(b==="GET"&&v==="/api/browser-relay/config"){if(!Ui(y,u,"Browser Relay bootstrap is only available from localhost."))return;let f=_(),h=f.tools.browserRelay;return w(u,200,{enabled:h.enabled,port:f.gateway.port,token:h.enabled&&h.authToken||""})}if(b==="POST"&&v==="/api/browser-relay/launch"){let f=await ie(y),h=_(),m=f.extensionPath??h.tools.browserRelay.extensionPath;if(!m)return w(u,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let k=process.platform,C,A=[`--load-extension=${m}`,"--no-first-run","--no-default-browser-check"];if(k==="darwin")C=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(Et)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(k==="win32"){let R=process.env.ProgramFiles??"C:\\Program Files",E=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";C=[`${R}\\Google\\Chrome\\Application\\chrome.exe`,`${E}\\Google\\Chrome\\Application\\chrome.exe`].find(Et)??`${R}\\Google\\Chrome\\Application\\chrome.exe`}else C="google-chrome";try{return $i(C,A,{detached:!0,stdio:"ignore"}).unref(),w(u,200,{ok:!0,launched:!0,extensionPath:m,message:`Chrome launched with extension from ${m}`})}catch(R){return w(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 U=v.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),$=Z(o.config.agents.defaults.workspace);if(b==="GET"&&v==="/api/automations"){let f=Jt($);return w(u,200,f)}if(b==="GET"&&U&&U[1]&&!U[2]){let f=U[1],h=Ee($,f);return h?w(u,200,h):w(u,404,{error:"Automation not found"})}if(b==="POST"&&v==="/api/automations"){let f=await ie(y);try{let h={name:String(f.name??"Untitled"),description:String(f.description??""),steps:f.steps||[],tags:f.tags||[],source:f.source||"manual"};f.toolType!==void 0&&(h.toolType=f.toolType),f.variables!==void 0&&(h.variables=f.variables);let m=yr($,h);return w(u,201,m)}catch(h){return w(u,400,{error:String(h)})}}if(b==="PUT"&&U&&U[1]&&!U[2]){let f=U[1],h=await ie(y),m={};h.name!==void 0&&(m.name=String(h.name)),h.description!==void 0&&(m.description=String(h.description)),h.enabled!==void 0&&(m.enabled=!!h.enabled),h.steps!==void 0&&(m.steps=h.steps),h.tags!==void 0&&(m.tags=h.tags),h.toolType!==void 0&&(m.toolType=h.toolType),h.variables!==void 0&&(m.variables=h.variables);let k=br($,f,m);return k?w(u,200,k):w(u,404,{error:"Automation not found"})}if(b==="DELETE"&&U&&U[1]){let f=U[1];return Ht($,f)?w(u,200,{ok:!0}):w(u,404,{error:"Automation not found"})}if(b==="POST"&&U&&U[1]&&U[2]==="/run"){let f=U[1],h=Ee($,f);return h?h.enabled?(o.agent.tools.execute("automation",{command:"run",id:f}).then(m=>{console.log(`[automation] Execution of '${h.name}' finished`,{logs:m.kind==="ok"?m.content:m})}).catch(m=>{console.error(`[automation] Execution of '${h.name}' failed`,{err:m})}),w(u,200,{ok:!0,message:`Automation '${h.name}' execution started in background.`})):w(u,400,{error:"Automation is disabled"}):w(u,404,{error:"Automation not found"})}if(b==="GET"&&v==="/api/history"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session history not found.");if(h.error)return w(u,404,h.error);let m=h.sessionKey,k=o.sessionManager.getOrCreate(m);return w(u,200,{session:m,messages:Vr(k.messages)})}if(b==="GET"&&v==="/api/sessions"){let f=o.agent.getRuntimeState(),h=new Set((f.sessions||[]).filter(C=>C.running||C.queued>0).map(C=>C.key)),m=o.sessionManager.getOrCreate(o.sessionKey),k=o.sessionManager.listSessions().filter(C=>String(C.key??"")!==o.sessionKey).map(C=>{let A=String(C.key??"");return zr({key:A,created_at:String(C.created_at??m.createdAt),updated_at:String(C.updated_at??m.updatedAt)},o.sessionKey,h.has(A),o.sessionManager.getOrCreate(A))});return w(u,200,{currentSession:o.sessionKey,sessions:[zr({key:m.key,created_at:m.createdAt,updated_at:m.updatedAt},o.sessionKey,h.has(m.key),m),...k]})}if(b==="GET"&&v==="/api/files/preview"){let f=String(T.searchParams.get("path")??"").trim(),h=parseInt(T.searchParams.get("maxLines")??"100",10),m=o.workspacePath??process.cwd();if(!f)return w(u,400,{error:"path required"});try{Ke(f,m)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!Et(f))return w(u,404,{error:"file not found"});try{let k=fe.statSync(f);if(k.isDirectory())return w(u,400,{error:"path is a directory"});let C=Oi(f),A=fe.readFileSync(f),R=null,E=!1;if(Ni(C)){let F=A.toString("utf-8").split(`
342
342
  `);E=F.length>h,R=F.slice(0,h).join(`
343
- `)}let P=Re.extname(f).toLowerCase(),M=C.startsWith("image/")?"image":C==="application/pdf"?"pdf":C==="text/csv"||C==="text/tab-separated-values"?"table":Li(C)?P===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(P)?"code":"text":"binary";return w(u,200,{name:Re.basename(f),path:f,size:k.size,content:R,truncated:E,mimeType:C,previewType:M,extension:P})}catch(k){return w(u,500,{error:String(k)})}}if(b==="GET"&&v==="/api/files/content"){let f=String(T.searchParams.get("path")??"").trim(),h=o.workspacePath??process.cwd();if(!f)return w(u,400,{error:"path required"});try{Ge(f,h)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!At(f))return w(u,404,{error:"file not found"});try{let m=fe.statSync(f);if(m.isDirectory())return w(u,400,{error:"path is a directory"});u.statusCode=200,u.setHeader("Content-Type",$i(f)),u.setHeader("Content-Length",String(m.size)),fe.createReadStream(f).pipe(u);return}catch(m){return w(u,500,{error:String(m)})}}if(b==="POST"&&v==="/api/sessions"){let f=await ie(y),h=new Set(o.sessionManager.listSessions().map(M=>String(M.key??"")));h.add(o.sessionKey);let m=String(f.key??"").trim(),k=[...h].map(M=>o.sessionManager.getOrCreate(M)),C=Wo(f.label),A=C||Qc(k),R=m||Zc(h,C),E=h.has(R),P=o.sessionManager.getOrCreate(R);return E||(P.metadata={...P.metadata,displayName:A},o.sessionManager.save(P)),w(u,200,{created:!E,session:qr({key:P.key,created_at:P.createdAt,updated_at:P.updatedAt},o.sessionKey,!1,P)})}if(j&&b==="PUT"){let f=j[1]?decodeURIComponent(j[1]):void 0;if(!f)return w(u,400,"Invalid session key");let h=g(f,"Session not found.");if(h.error)return w(u,404,h.error);let m=await ie(y),k=Wo(m.label),C=Number(m.pinnedOrder),A=Number(m.recentOrder);if(k===void 0&&m.isPinned===void 0&&m.pinnedOrder===void 0&&m.recentOrder===void 0)return w(u,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:f});let R=o.sessionManager.getOrCreate(h.sessionKey);if(R.metadata={...R.metadata},k!==void 0&&(R.metadata.displayName=k),m.isPinned!==void 0&&(R.metadata.isPinned=!!m.isPinned),R.metadata.isPinned===!0){delete R.metadata.recentOrder;let P=[...Oi(o.sessionManager,R.key)],M=Number.isFinite(C)?Math.max(0,Math.min(Math.trunc(C),P.length)):P.length;P.splice(M,0,R),Ni(o.sessionManager,P),ji(o.sessionManager,Di(o.sessionManager,R.key))}else{delete R.metadata.pinnedOrder,Ni(o.sessionManager,Oi(o.sessionManager,R.key));let P=[...Di(o.sessionManager,R.key)],M=Number.isFinite(A)?Math.max(0,Math.min(Math.trunc(A),P.length)):P.length;P.splice(M,0,R),ji(o.sessionManager,P)}return o.sessionManager.save(R),w(u,200,{ok:!0,session:qr({key:R.key,created_at:R.createdAt,updated_at:R.updatedAt},o.sessionKey,!1,R)})}if(j&&b==="DELETE"){let f=j[1]?decodeURIComponent(j[1]):void 0;if(!f)return w(u,400,"Invalid session key");let h=g(f,"Session not found.");if(h.error)return w(u,404,h.error);if(h.sessionKey===o.sessionKey)return w(u,400,{error:"The primary session cannot be deleted."});let m=o.sessionManager.delete(h.sessionKey);return w(u,200,{ok:m,session:f})}if(b==="GET"&&v==="/api/suggestions"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session suggestions not found.");if(h.error)return w(u,404,h.error);let m=h.sessionKey,k=o.sessionManager.getOrCreate(m),C=_(),A=C.subagents?.find(E=>E.id==="advisor"),R=A?A.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let E=Ne(C),P=await Eo({task:R+`
344
- Return ONLY a JSON array of strings, nothing else.`,provider:E,workspace:o.workspacePath??process.cwd(),model:C.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:C.tools.exec,restrictToWorkspace:C.tools.restrictToWorkspace,existingMessages:zr(k.messages)}),M=[];try{let F=P.replace(/```json/g,"").replace(/```/g,"").trim();M=JSON.parse(F)}catch{M=Go(k.messages).map(F=>F.text)}let Q=Array.isArray(M)?M.slice(0,3).map((F,ge)=>({id:`suggestion-${ge+1}`,text:String(F),label:Vr(String(F),56)??String(F)})):Go(k.messages);return w(u,200,{session:m,suggestions:Q})}catch{return w(u,200,{session:m,suggestions:Go(k.messages)})}}if(b==="GET"&&v==="/api/session-files"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");return h.error?w(u,404,h.error):w(u,200,{session:h.sessionKey,files:c().list(h.sessionKey)})}if(b==="GET"&&v==="/api/inbox-deliveries"){let f=T.searchParams.get("all")==="1",h=d();if(h.list({includeCleared:!0}).filter(C=>!C.clearedAt).length===0){let C=[{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.
343
+ `)}let P=_e.extname(f).toLowerCase(),M=C.startsWith("image/")?"image":C==="application/pdf"?"pdf":C==="text/csv"||C==="text/tab-separated-values"?"table":Ni(C)?P===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(P)?"code":"text":"binary";return w(u,200,{name:_e.basename(f),path:f,size:k.size,content:R,truncated:E,mimeType:C,previewType:M,extension:P})}catch(k){return w(u,500,{error:String(k)})}}if(b==="GET"&&v==="/api/files/content"){let f=String(T.searchParams.get("path")??"").trim(),h=o.workspacePath??process.cwd();if(!f)return w(u,400,{error:"path required"});try{Ke(f,h)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!Et(f))return w(u,404,{error:"file not found"});try{let m=fe.statSync(f);if(m.isDirectory())return w(u,400,{error:"path is a directory"});u.statusCode=200,u.setHeader("Content-Type",Oi(f)),u.setHeader("Content-Length",String(m.size)),fe.createReadStream(f).pipe(u);return}catch(m){return w(u,500,{error:String(m)})}}if(b==="POST"&&v==="/api/sessions"){let f=await ie(y),h=new Set(o.sessionManager.listSessions().map(M=>String(M.key??"")));h.add(o.sessionKey);let m=String(f.key??"").trim(),k=[...h].map(M=>o.sessionManager.getOrCreate(M)),C=Ko(f.label),A=C||ed(k),R=m||td(h,C),E=h.has(R),P=o.sessionManager.getOrCreate(R);return E||(P.metadata={...P.metadata,displayName:A},o.sessionManager.save(P)),w(u,200,{created:!E,session:zr({key:P.key,created_at:P.createdAt,updated_at:P.updatedAt},o.sessionKey,!1,P)})}if(j&&b==="PUT"){let f=j[1]?decodeURIComponent(j[1]):void 0;if(!f)return w(u,400,"Invalid session key");let h=g(f,"Session not found.");if(h.error)return w(u,404,h.error);let m=await ie(y),k=Ko(m.label),C=Number(m.pinnedOrder),A=Number(m.recentOrder);if(k===void 0&&m.isPinned===void 0&&m.pinnedOrder===void 0&&m.recentOrder===void 0)return w(u,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:f});let R=o.sessionManager.getOrCreate(h.sessionKey);if(R.metadata={...R.metadata},k!==void 0&&(R.metadata.displayName=k),m.isPinned!==void 0&&(R.metadata.isPinned=!!m.isPinned),R.metadata.isPinned===!0){delete R.metadata.recentOrder;let P=[...Di(o.sessionManager,R.key)],M=Number.isFinite(C)?Math.max(0,Math.min(Math.trunc(C),P.length)):P.length;P.splice(M,0,R),ji(o.sessionManager,P),Bi(o.sessionManager,Fi(o.sessionManager,R.key))}else{delete R.metadata.pinnedOrder,ji(o.sessionManager,Di(o.sessionManager,R.key));let P=[...Fi(o.sessionManager,R.key)],M=Number.isFinite(A)?Math.max(0,Math.min(Math.trunc(A),P.length)):P.length;P.splice(M,0,R),Bi(o.sessionManager,P)}return o.sessionManager.save(R),w(u,200,{ok:!0,session:zr({key:R.key,created_at:R.createdAt,updated_at:R.updatedAt},o.sessionKey,!1,R)})}if(j&&b==="DELETE"){let f=j[1]?decodeURIComponent(j[1]):void 0;if(!f)return w(u,400,"Invalid session key");let h=g(f,"Session not found.");if(h.error)return w(u,404,h.error);if(h.sessionKey===o.sessionKey)return w(u,400,{error:"The primary session cannot be deleted."});let m=o.sessionManager.delete(h.sessionKey);return w(u,200,{ok:m,session:f})}if(b==="GET"&&v==="/api/suggestions"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session suggestions not found.");if(h.error)return w(u,404,h.error);let m=h.sessionKey,k=o.sessionManager.getOrCreate(m),C=_(),A=C.subagents?.find(E=>E.id==="advisor"),R=A?A.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let E=je(C),P=await _o({task:R+`
344
+ Return ONLY a JSON array of strings, nothing else.`,provider:E,workspace:o.workspacePath??process.cwd(),model:C.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:C.tools.exec,restrictToWorkspace:C.tools.restrictToWorkspace,existingMessages:Vr(k.messages)}),M=[];try{let F=P.replace(/```json/g,"").replace(/```/g,"").trim();M=JSON.parse(F)}catch{M=Wo(k.messages).map(F=>F.text)}let Q=Array.isArray(M)?M.slice(0,3).map((F,ge)=>({id:`suggestion-${ge+1}`,text:String(F),label:Yr(String(F),56)??String(F)})):Wo(k.messages);return w(u,200,{session:m,suggestions:Q})}catch{return w(u,200,{session:m,suggestions:Wo(k.messages)})}}if(b==="GET"&&v==="/api/session-files"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");return h.error?w(u,404,h.error):w(u,200,{session:h.sessionKey,files:c().list(h.sessionKey)})}if(b==="GET"&&v==="/api/inbox-deliveries"){let f=T.searchParams.get("all")==="1",h=d();if(h.list({includeCleared:!0}).filter(C=>!C.clearedAt).length===0){let C=[{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.
345
345
 
346
- 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."}],A=new Date;for(let R=0;R<C.length;R++){let E=C[R],P=new Date(A.getTime()-R*36e5).toISOString();h.record({jobId:E.jobId,jobName:E.jobName,sessionKey:E.sessionKey,channel:E.channel,recipient:E.recipient,content:E.content,deliveredAt:P})}}return w(u,200,{deliveries:h.list({includeCleared:f})})}if(D&&b==="GET"){let f=D[1];if(!f)return w(u,400,"Invalid delivery ID");let h=d().get(decodeURIComponent(f));return h?w(u,200,{delivery:h}):w(u,404,{error:"Inbox delivery not found."})}if(Y&&b==="POST"){let f=Y[1];if(!f)return w(u,400,"Invalid delivery ID");let h=d().markCleared(decodeURIComponent(f));return h?w(u,200,{ok:!0,delivery:h}):w(u,404,{error:"Inbox delivery not found."})}if(b==="POST"&&v==="/api/session-files"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);try{return w(u,200,c().associate(m.sessionKey,String(f.path??"")))}catch(k){return w(u,400,{error:k instanceof Error?k.message:String(k)})}}if(b==="POST"&&v==="/api/session-files/upload"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(f.filename??"").trim(),C=String(f.content??"").trim();if(!k)return w(u,400,{error:"Filename is required."});if(!C)return w(u,400,{error:"File content is required."});let A=[".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||!A.includes(R))return w(u,400,{error:`Unsupported file type. Allowed: ${A.join(", ")}`});try{let E=Buffer.from(C,"base64"),P=Re.join(o.workspacePath??process.cwd(),".session-uploads");fe.existsSync(P)||fe.mkdirSync(P,{recursive:!0});let M=k.replace(/[^a-zA-Z0-9._-]/g,"_"),Q=Re.join(P,`${Date.now()}-${M}`);return fe.writeFileSync(Q,E),w(u,200,c().associate(m.sessionKey,Q))}catch(E){return w(u,400,{error:E instanceof Error?E.message:String(E)})}}if(b==="POST"&&v==="/api/session-files/copy-local"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(f.path??"").trim(),C=o.workspacePath??process.cwd();if(!k)return w(u,400,{error:"Path is required."});try{Ge(k,C)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!fe.existsSync(k))return w(u,404,{error:"File not found."});try{return fe.statSync(k).isDirectory()?w(u,400,{error:"Path is a directory."}):w(u,200,c().associate(m.sessionKey,k))}catch(A){return w(u,400,{error:A instanceof Error?A.message:String(A)})}}if(J&&b==="GET"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");if(h.error)return w(u,404,h.error);let m=J[1];if(!m)return w(u,400,"Invalid file ID");let k=c().get(h.sessionKey,decodeURIComponent(m));return k?w(u,200,{session:h.sessionKey,file:k}):w(u,404,{error:"Session file not found.",session:h.sessionKey})}if(J&&b==="DELETE"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");if(h.error)return w(u,404,h.error);let m=J[1];return m?w(u,200,{ok:c().remove(h.sessionKey,decodeURIComponent(m))}):w(u,400,"Invalid file ID")}if(b==="POST"&&v==="/api/chat/stream"){let f=await ie(y),h=f.message,m=String(f.session??"default:everclaw"),k=String(f.model??"").trim(),C=String(f._provider??"").trim(),A=Array.isArray(h)?h:String(h??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(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=M=>{u.write(`data: ${JSON.stringify(M)}
346
+ 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."}],A=new Date;for(let R=0;R<C.length;R++){let E=C[R],P=new Date(A.getTime()-R*36e5).toISOString();h.record({jobId:E.jobId,jobName:E.jobName,sessionKey:E.sessionKey,channel:E.channel,recipient:E.recipient,content:E.content,deliveredAt:P})}}return w(u,200,{deliveries:h.list({includeCleared:f})})}if(D&&b==="GET"){let f=D[1];if(!f)return w(u,400,"Invalid delivery ID");let h=d().get(decodeURIComponent(f));return h?w(u,200,{delivery:h}):w(u,404,{error:"Inbox delivery not found."})}if(Y&&b==="POST"){let f=Y[1];if(!f)return w(u,400,"Invalid delivery ID");let h=d().markCleared(decodeURIComponent(f));return h?w(u,200,{ok:!0,delivery:h}):w(u,404,{error:"Inbox delivery not found."})}if(b==="POST"&&v==="/api/session-files"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);try{return w(u,200,c().associate(m.sessionKey,String(f.path??"")))}catch(k){return w(u,400,{error:k instanceof Error?k.message:String(k)})}}if(b==="POST"&&v==="/api/session-files/upload"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(f.filename??"").trim(),C=String(f.content??"").trim();if(!k)return w(u,400,{error:"Filename is required."});if(!C)return w(u,400,{error:"File content is required."});let A=[".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||!A.includes(R))return w(u,400,{error:`Unsupported file type. Allowed: ${A.join(", ")}`});try{let E=Buffer.from(C,"base64"),P=_e.join(o.workspacePath??process.cwd(),".session-uploads");fe.existsSync(P)||fe.mkdirSync(P,{recursive:!0});let M=k.replace(/[^a-zA-Z0-9._-]/g,"_"),Q=_e.join(P,`${Date.now()}-${M}`);return fe.writeFileSync(Q,E),w(u,200,c().associate(m.sessionKey,Q))}catch(E){return w(u,400,{error:E instanceof Error?E.message:String(E)})}}if(b==="POST"&&v==="/api/session-files/copy-local"){let f=await ie(y),h=String(f.session??"").trim(),m=g(h,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(f.path??"").trim(),C=o.workspacePath??process.cwd();if(!k)return w(u,400,{error:"Path is required."});try{Ke(k,C)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!fe.existsSync(k))return w(u,404,{error:"File not found."});try{return fe.statSync(k).isDirectory()?w(u,400,{error:"Path is a directory."}):w(u,200,c().associate(m.sessionKey,k))}catch(A){return w(u,400,{error:A instanceof Error?A.message:String(A)})}}if(J&&b==="GET"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");if(h.error)return w(u,404,h.error);let m=J[1];if(!m)return w(u,400,"Invalid file ID");let k=c().get(h.sessionKey,decodeURIComponent(m));return k?w(u,200,{session:h.sessionKey,file:k}):w(u,404,{error:"Session file not found.",session:h.sessionKey})}if(J&&b==="DELETE"){let f=String(T.searchParams.get("session")??"").trim(),h=g(f,"Session files not found.");if(h.error)return w(u,404,h.error);let m=J[1];return m?w(u,200,{ok:c().remove(h.sessionKey,decodeURIComponent(m))}):w(u,400,"Invalid file ID")}if(b==="POST"&&v==="/api/chat/stream"){let f=await ie(y),h=f.message,m=String(f.session??"default:everclaw"),k=String(f.model??"").trim(),C=String(f._provider??"").trim(),A=Array.isArray(h)?h:String(h??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(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=M=>{u.write(`data: ${JSON.stringify(M)}
347
347
 
348
- `)},E="",P=[];try{let M,Q={...k?{_model:k}:{},...C?{_provider:C}:{},...Array.isArray(f.skillNames)&&f.skillNames.length?{skillNames:f.skillNames}:{},...f._notification?{_notification:f._notification}:{}};f._notification&&(M=f._notification);let F=await o.agent.processDirectResult(A,m,"cli","dashboard",async(ge,ee)=>{if(ee?.thinkingContent&&(E=ee.thinkingContent),Array.isArray(ee?.tool_calls)&&(P=ee.tool_calls),ee?.tool_call&&typeof ee.tool_call=="object"){let Qe=ee.tool_call,In=typeof Qe.id=="string"?Qe.id:"";P=P.some(gt=>gt.id===In)?P.map(gt=>gt.id===In?{...gt,...Qe}:gt):[...P,Qe]}switch(ee?.event){case"thinking":R({type:"thinking",content:ee.thinkingContent??ge});break;case"tool_calls":R({type:"tool_calls",tool_calls:P});break;case"tool_result":R({type:"tool_result",tool_call:ee.tool_call,tool_calls:P});break;case"answer":R({type:"answer",content:ge});break;default:R({type:"progress",content:ge,toolHint:!!ee?.toolHint,...ee?.tool_calls?{tool_calls:ee.tool_calls}:{}});break}},Q);F.outcome==="rate_limited"?R({type:"error",error:F.content,outcome:F.outcome,retryAfterMs:F.retryAfterMs??0}):F.outcome==="backpressure"||F.outcome==="shutdown"?R({type:"error",error:F.content,outcome:F.outcome}):(M&&R({type:"notification",notification:M}),R({type:"done",response:F.content,thinkingContent:E,tool_calls:P,...M?{_notification:M}:{}}))}catch(M){R({type:"error",error:String(M)})}finally{u.end()}return}if(b==="POST"&&v==="/api/chat"){let f=await ie(y),h=f.message,m=String(f.session??"default:everclaw"),k=String(f.model??"").trim(),C=String(f._provider??"").trim(),A=Array.isArray(h)?h:String(h??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(u,400,{error:"message required"});let R=[];try{let E=await o.agent.processDirectResult(A,m,"cli","dashboard",async(P,M)=>{R.push({content:P,toolHint:!!M?.toolHint,...M?.tool_calls?{tool_calls:M.tool_calls}:{}})},{...k?{_model:k}:{},...C?{_provider:C}:{}});return E.outcome==="rate_limited"?(u.setHeader("Retry-After",String(Math.max(1,Math.ceil((E.retryAfterMs??0)/1e3)))),w(u,429,{error:E.content,outcome:E.outcome,retryAfterMs:E.retryAfterMs??0,progress:R})):E.outcome==="backpressure"||E.outcome==="shutdown"?w(u,503,{error:E.content,outcome:E.outcome,progress:R}):w(u,200,{response:E.content,progress:R})}catch(E){return w(u,500,{error:String(E)})}}if(b==="GET"&&v==="/api/config")return w(u,200,nd(_()));if(b==="GET"&&v==="/api/security/status"){let{ToolGuardEngine:f}=await Promise.resolve().then(()=>(Uo(),Mi)),m=f.getInstance().getRules(),k=m.filter(A=>A.enabled),C=_();return w(u,200,{toolGuard:{enabled:C.security?.toolGuard?.enabled??!1,totalRules:m.length,enabledRules:k.length,defaultRules:m.filter(A=>!A.id.startsWith("user-")).length,userRules:C.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:C.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&v==="/api/config"){let f=await ie(y),h=it(f.config)?f.config:null;if(!h)return w(u,400,{error:"Request body must include a config object."});let m=sd(h),k=_(),C=f.secretChanges;k.security?.auth&&m.security?.auth&&"pinHash"in k.security.auth&&(m.security.auth.pinHash=k.security.auth.pinHash);try{if(m.providers&&k.providers)for(let R of Object.keys(m.providers))m.providers[R]&&k.providers[R]&&Et(m,k,C,["providers",R,"apiKey"]);if(Array.isArray(m.customLlmProviders)&&Array.isArray(k.customLlmProviders))for(let R=0;R<m.customLlmProviders.length;R++){let E=m.customLlmProviders[R];if(!E)continue;let M=k.customLlmProviders.find(ge=>ge?.name===E.name)?.apiKey??"",Q=E.apiKey??"",F=Gi(C,["customLlmProviders",R,"apiKey"],M,Q);F&&(E.apiKey=F.action==="keep"?M:F.action==="clear"?"":F.value??Q)}if(m.channels&&k.channels&&(Et(m,k,C,["channels","telegram","token"]),Et(m,k,C,["channels","discord","token"])),m.tools?.browserRelay&&k.tools?.browserRelay&&Et(m,k,C,["tools","browserRelay","authToken"]),m.tools?.web?.search&&k.tools?.web?.search&&Et(m,k,C,["tools","web","search","apiKey"]),m.tools?.mcpServers&&k.tools?.mcpServers)for(let R of Object.keys(m.tools.mcpServers)){let E=m.tools.mcpServers[R];if(E?.env)for(let P of Object.keys(E.env))Et(m,k,C,["tools","mcpServers",R,"env",P]);if(E?.headers)for(let P of Object.keys(E.headers))Et(m,k,C,["tools","mcpServers",R,"headers",P])}}catch(R){return w(u,400,{error:R instanceof Error?R.message:String(R)})}if(m.security?.auth?.enabled&&!m.security?.auth?.pinHash?.length)return w(u,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let A=od(m.tools?.mcpServers??{});return A.length?w(u,400,{error:`Invalid MCP server configuration. ${A[0]}`,details:A}):(oe(m),l.updateConfig(m.security.auth),w(u,200,{ok:!0}))}if(b==="GET"&&v==="/api/subagents"){let f=_();return w(u,200,{subagents:f.subagents||[]})}if(b==="POST"&&v==="/api/subagents"){let f=await ie(y),h=_();h.subagents||(h.subagents=[]);let m=h.subagents.length,k={id:`subagent-${Date.now()}`,name:f.name||`SubAgent ${m+1}`,task:f.task||"",createdAt:Date.now(),...f.type?{type:f.type}:{},...f.contextMode?{contextMode:f.contextMode}:{}};return h.subagents.push(k),oe(h),w(u,200,k)}let K=v.match(/^\/api\/subagents\/([^/]+)$/);if(K&&b==="PUT"){let f=K[1];if(!f)return w(u,400,"Invalid subagent ID");let h=await ie(y),m=_();m.subagents||(m.subagents=[]);let k=m.subagents.findIndex(Q=>Q.id===f);if(k===-1)return w(u,404,{error:"Subagent not found"});let C=m.subagents[k];if(!C)return w(u,404,{error:"Subagent not found"});let A={id:h.id??C.id,name:h.name??C.name,task:h.task??C.task,createdAt:h.createdAt??C.createdAt},R=h.provider!==void 0?h.provider:C.provider,E=h.model!==void 0?h.model:C.model,P=h.type!==void 0?h.type:C.type,M=h.contextMode!==void 0?h.contextMode:C.contextMode;return R&&(A.provider=R),E&&(A.model=E),P&&(A.type=P),M&&(A.contextMode=M),m.subagents[k]=A,oe(m),w(u,200,A)}if(K&&b==="DELETE"){let f=K[1],h=_();h.subagents||(h.subagents=[]);let m=h.subagents.findIndex(k=>k.id===f);return m===-1?w(u,404,{error:"Subagent not found"}):(h.subagents.splice(m,1),oe(h),w(u,200,{ok:!0}))}if(b==="GET"&&v==="/api/skills")try{return w(u,200,n.getSnapshot())}catch(f){return w(u,500,{error:String(f)})}if(b==="POST"&&v==="/api/skills/install"){let f=await ie(y);try{let h=await n.install(String(f.slug??""));return w(u,200,h)}catch(h){return w(u,400,{error:h instanceof Error?h.message:String(h)})}}if(b==="GET"&&v==="/api/cron/jobs"){let f=T.searchParams.get("all")==="1";return w(u,200,o.cron.listJobs(f))}if(b==="POST"&&v==="/api/cron/jobs"){let f=await ie(y);try{let h={name:String(f.name??"job"),schedule:f.schedule,message:String(f.message??""),deliver:!!f.deliver,deleteAfterRun:!!f.deleteAfterRun};f.channel&&(h.channel=String(f.channel)),f.to&&(h.to=String(f.to));let m=o.cron.addJob(h);return w(u,200,m)}catch(h){return w(u,400,{error:String(h)})}}if(I&&b==="DELETE"){let f=I[1];return f?w(u,200,{ok:o.cron.removeJob(f)}):w(u,400,"Invalid job ID")}if(I&&b==="PUT"){let f=I[1];if(!f)return w(u,400,"Invalid job ID");let h=await ie(y),m={};h.name!==void 0&&(m.name=String(h.name)),h.schedule!==void 0&&(m.schedule=h.schedule),h.message!==void 0&&(m.message=String(h.message)),h.deliver!==void 0&&(m.deliver=!!h.deliver),h.channel!==void 0&&(m.channel=String(h.channel)),h.to!==void 0&&(m.to=String(h.to)),h.deleteAfterRun!==void 0&&(m.deleteAfterRun=!!h.deleteAfterRun);let k=o.cron.updateJob(f,m);return k?w(u,200,k):w(u,404,{error:"not found"})}if(V&&b==="POST"){let h=(await ie(y)).enabled!==!1,m=V[1];if(!m)return w(u,400,"Invalid job ID");let k=o.cron.enableJob(m,h);return k?w(u,200,k):w(u,404,{error:"not found"})}if(N&&b==="POST"){let f=await ie(y),h=N[1];if(!h)return w(u,400,"Invalid job ID");let m=await o.cron.runJob(h,!!f.force);return w(u,200,{ok:m})}let B=o.config.gateway.dashboard?.enabled!==!1;if(B&&e){let f=Re.resolve(e,v==="/"?"index.html":v.slice(1));if(!f.startsWith(Re.resolve(e)+Re.sep)&&f!==Re.resolve(e)&&(f=Re.join(e,"index.html")),(!fe.existsSync(f)||fe.statSync(f).isDirectory())&&(f=Re.join(e,"index.html")),!fe.existsSync(f)){u.statusCode=404,u.end("Dashboard assets not found. Run npm run build.");return}u.statusCode=200,u.setHeader("Content-Type",ed(f)),fe.createReadStream(f).pipe(u);return}if(!v.startsWith("/api/")){u.statusCode=404,u.end(B?"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 x.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(x),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((y,u)=>x.close(b=>{try{r?.close(),s?.close()}catch{}b?u(b):y()})))}}de();import{spawn as Yr}from"node:child_process";import{createWriteStream as ld,existsSync as Qt,lstatSync as cd,mkdirSync as dd,readdirSync as ud,rmSync as Pn}from"node:fs";import Xr from"node:path";import{pipeline as gd}from"node:stream/promises";var Ee="0.28.0",Ki="https://github.com/rtk-ai/rtk/releases",Ji=3e4,Qr={"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"},md=200,pd=5e3;function Hi(o){return Math.ceil(o.length/4)}function _t(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 _e=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return Xr.join(Ln(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Qt(t)){let n=await this.getVersion(t);if(n&&_t(n,Ee))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 ${Ee}). 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=Qr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Qr).join(", ")}`);let s=o.binaryPath(),i=Xr.dirname(s);if(!e?.force&&Qt(s)){let c=await this.getVersion(s);if(c&&_t(c,Ee))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${Ki}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${Ki}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Qt(i)||dd(i,{recursive:!0});let l=Xr.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{Qt(l)&&Pn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),Ji);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 gd(n.fromWeb(i.body),ld(t))}catch(i){throw Pn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${Ji}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=Yr("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`tar extraction failed with code ${g}`))}),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 ud(e)){let s=Xr.join(e,r),i=cd(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=Yr("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`PowerShell extraction failed with code ${g}`))}),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();Qt(e)&&Pn(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Qt(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=Yr(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<md)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=Hi(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=Hi(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=Yr(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},pd);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 fd}from"node:crypto";import Ho,{WebSocketServer as hd}from"ws";var qo=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
348
+ `)},E="",P=[];try{let M,Q={...k?{_model:k}:{},...C?{_provider:C}:{},...Array.isArray(f.skillNames)&&f.skillNames.length?{skillNames:f.skillNames}:{},...f._notification?{_notification:f._notification}:{}};f._notification&&(M=f._notification);let F=await o.agent.processDirectResult(A,m,"cli","dashboard",async(ge,ee)=>{if(ee?.thinkingContent&&(E=ee.thinkingContent),Array.isArray(ee?.tool_calls)&&(P=ee.tool_calls),ee?.tool_call&&typeof ee.tool_call=="object"){let Ze=ee.tool_call,Ln=typeof Ze.id=="string"?Ze.id:"";P=P.some(mt=>mt.id===Ln)?P.map(mt=>mt.id===Ln?{...mt,...Ze}:mt):[...P,Ze]}switch(ee?.event){case"thinking":R({type:"thinking",content:ee.thinkingContent??ge});break;case"tool_calls":R({type:"tool_calls",tool_calls:P});break;case"tool_result":R({type:"tool_result",tool_call:ee.tool_call,tool_calls:P});break;case"answer":R({type:"answer",content:ge});break;default:R({type:"progress",content:ge,toolHint:!!ee?.toolHint,...ee?.tool_calls?{tool_calls:ee.tool_calls}:{}});break}},Q);F.outcome==="rate_limited"?R({type:"error",error:F.content,outcome:F.outcome,retryAfterMs:F.retryAfterMs??0}):F.outcome==="backpressure"||F.outcome==="shutdown"?R({type:"error",error:F.content,outcome:F.outcome}):(M&&R({type:"notification",notification:M}),R({type:"done",response:F.content,thinkingContent:E,tool_calls:P,...M?{_notification:M}:{}}))}catch(M){R({type:"error",error:String(M)})}finally{u.end()}return}if(b==="POST"&&v==="/api/chat"){let f=await ie(y),h=f.message,m=String(f.session??"default:everclaw"),k=String(f.model??"").trim(),C=String(f._provider??"").trim(),A=Array.isArray(h)?h:String(h??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(u,400,{error:"message required"});let R=[];try{let E=await o.agent.processDirectResult(A,m,"cli","dashboard",async(P,M)=>{R.push({content:P,toolHint:!!M?.toolHint,...M?.tool_calls?{tool_calls:M.tool_calls}:{}})},{...k?{_model:k}:{},...C?{_provider:C}:{}});return E.outcome==="rate_limited"?(u.setHeader("Retry-After",String(Math.max(1,Math.ceil((E.retryAfterMs??0)/1e3)))),w(u,429,{error:E.content,outcome:E.outcome,retryAfterMs:E.retryAfterMs??0,progress:R})):E.outcome==="backpressure"||E.outcome==="shutdown"?w(u,503,{error:E.content,outcome:E.outcome,progress:R}):w(u,200,{response:E.content,progress:R})}catch(E){return w(u,500,{error:String(E)})}}if(b==="GET"&&v==="/api/config")return w(u,200,od(_()));if(b==="GET"&&v==="/api/security/status"){let{ToolGuardEngine:f}=await Promise.resolve().then(()=>(Go(),Li)),m=f.getInstance().getRules(),k=m.filter(A=>A.enabled),C=_();return w(u,200,{toolGuard:{enabled:C.security?.toolGuard?.enabled??!1,totalRules:m.length,enabledRules:k.length,defaultRules:m.filter(A=>!A.id.startsWith("user-")).length,userRules:C.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:C.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&v==="/api/config"){let f=await ie(y),h=at(f.config)?f.config:null;if(!h)return w(u,400,{error:"Request body must include a config object."});let m=ad(h),k=_(),C=f.secretChanges;k.security?.auth&&m.security?.auth&&"pinHash"in k.security.auth&&(m.security.auth.pinHash=k.security.auth.pinHash);try{if(m.providers&&k.providers)for(let R of Object.keys(m.providers))m.providers[R]&&k.providers[R]&&_t(m,k,C,["providers",R,"apiKey"]);if(Array.isArray(m.customLlmProviders)&&Array.isArray(k.customLlmProviders))for(let R=0;R<m.customLlmProviders.length;R++){let E=m.customLlmProviders[R];if(!E)continue;let M=k.customLlmProviders.find(ge=>ge?.name===E.name)?.apiKey??"",Q=E.apiKey??"",F=Ki(C,["customLlmProviders",R,"apiKey"],M,Q);F&&(E.apiKey=F.action==="keep"?M:F.action==="clear"?"":F.value??Q)}if(m.channels&&k.channels&&(_t(m,k,C,["channels","telegram","token"]),_t(m,k,C,["channels","discord","token"])),m.tools?.browserRelay&&k.tools?.browserRelay&&_t(m,k,C,["tools","browserRelay","authToken"]),m.tools?.web?.search&&k.tools?.web?.search&&_t(m,k,C,["tools","web","search","apiKey"]),m.tools?.mcpServers&&k.tools?.mcpServers)for(let R of Object.keys(m.tools.mcpServers)){let E=m.tools.mcpServers[R];if(E?.env)for(let P of Object.keys(E.env))_t(m,k,C,["tools","mcpServers",R,"env",P]);if(E?.headers)for(let P of Object.keys(E.headers))_t(m,k,C,["tools","mcpServers",R,"headers",P])}}catch(R){return w(u,400,{error:R instanceof Error?R.message:String(R)})}if(m.security?.auth?.enabled&&!m.security?.auth?.pinHash?.length)return w(u,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let A=id(m.tools?.mcpServers??{});return A.length?w(u,400,{error:`Invalid MCP server configuration. ${A[0]}`,details:A}):(oe(m),l.updateConfig(m.security.auth),w(u,200,{ok:!0}))}if(b==="GET"&&v==="/api/subagents"){let f=_();return w(u,200,{subagents:f.subagents||[]})}if(b==="POST"&&v==="/api/subagents"){let f=await ie(y),h=_();h.subagents||(h.subagents=[]);let m=h.subagents.length,k={id:`subagent-${Date.now()}`,name:f.name||`SubAgent ${m+1}`,task:f.task||"",createdAt:Date.now(),...f.type?{type:f.type}:{},...f.contextMode?{contextMode:f.contextMode}:{}};return h.subagents.push(k),oe(h),w(u,200,k)}let K=v.match(/^\/api\/subagents\/([^/]+)$/);if(K&&b==="PUT"){let f=K[1];if(!f)return w(u,400,"Invalid subagent ID");let h=await ie(y),m=_();m.subagents||(m.subagents=[]);let k=m.subagents.findIndex(Q=>Q.id===f);if(k===-1)return w(u,404,{error:"Subagent not found"});let C=m.subagents[k];if(!C)return w(u,404,{error:"Subagent not found"});let A={id:h.id??C.id,name:h.name??C.name,task:h.task??C.task,createdAt:h.createdAt??C.createdAt},R=h.provider!==void 0?h.provider:C.provider,E=h.model!==void 0?h.model:C.model,P=h.type!==void 0?h.type:C.type,M=h.contextMode!==void 0?h.contextMode:C.contextMode;return R&&(A.provider=R),E&&(A.model=E),P&&(A.type=P),M&&(A.contextMode=M),m.subagents[k]=A,oe(m),w(u,200,A)}if(K&&b==="DELETE"){let f=K[1],h=_();h.subagents||(h.subagents=[]);let m=h.subagents.findIndex(k=>k.id===f);return m===-1?w(u,404,{error:"Subagent not found"}):(h.subagents.splice(m,1),oe(h),w(u,200,{ok:!0}))}if(b==="GET"&&v==="/api/skills")try{return w(u,200,n.getSnapshot())}catch(f){return w(u,500,{error:String(f)})}if(b==="POST"&&v==="/api/skills/install"){let f=await ie(y);try{let h=await n.install(String(f.slug??""));return w(u,200,h)}catch(h){return w(u,400,{error:h instanceof Error?h.message:String(h)})}}if(b==="GET"&&v==="/api/cron/jobs"){let f=T.searchParams.get("all")==="1";return w(u,200,o.cron.listJobs(f))}if(b==="POST"&&v==="/api/cron/jobs"){let f=await ie(y);try{let h={name:String(f.name??"job"),schedule:f.schedule,message:String(f.message??""),deliver:!!f.deliver,deleteAfterRun:!!f.deleteAfterRun};f.channel&&(h.channel=String(f.channel)),f.to&&(h.to=String(f.to));let m=o.cron.addJob(h);return w(u,200,m)}catch(h){return w(u,400,{error:String(h)})}}if(I&&b==="DELETE"){let f=I[1];return f?w(u,200,{ok:o.cron.removeJob(f)}):w(u,400,"Invalid job ID")}if(I&&b==="PUT"){let f=I[1];if(!f)return w(u,400,"Invalid job ID");let h=await ie(y),m={};h.name!==void 0&&(m.name=String(h.name)),h.schedule!==void 0&&(m.schedule=h.schedule),h.message!==void 0&&(m.message=String(h.message)),h.deliver!==void 0&&(m.deliver=!!h.deliver),h.channel!==void 0&&(m.channel=String(h.channel)),h.to!==void 0&&(m.to=String(h.to)),h.deleteAfterRun!==void 0&&(m.deleteAfterRun=!!h.deleteAfterRun);let k=o.cron.updateJob(f,m);return k?w(u,200,k):w(u,404,{error:"not found"})}if(V&&b==="POST"){let h=(await ie(y)).enabled!==!1,m=V[1];if(!m)return w(u,400,"Invalid job ID");let k=o.cron.enableJob(m,h);return k?w(u,200,k):w(u,404,{error:"not found"})}if(N&&b==="POST"){let f=await ie(y),h=N[1];if(!h)return w(u,400,"Invalid job ID");let m=await o.cron.runJob(h,!!f.force);return w(u,200,{ok:m})}let B=o.config.gateway.dashboard?.enabled!==!1;if(B&&e){let f=_e.resolve(e,v==="/"?"index.html":v.slice(1));if(!f.startsWith(_e.resolve(e)+_e.sep)&&f!==_e.resolve(e)&&(f=_e.join(e,"index.html")),(!fe.existsSync(f)||fe.statSync(f).isDirectory())&&(f=_e.join(e,"index.html")),!fe.existsSync(f)){u.statusCode=404,u.end("Dashboard assets not found. Run npm run build.");return}u.statusCode=200,u.setHeader("Content-Type",nd(f)),fe.createReadStream(f).pipe(u);return}if(!v.startsWith("/api/")){u.statusCode=404,u.end(B?"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 x.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(x),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((y,u)=>x.close(b=>{try{r?.close(),s?.close()}catch{}b?u(b):y()})))}}ce();import{spawn as Xr}from"node:child_process";import{createWriteStream as dd,existsSync as Zt,lstatSync as ud,mkdirSync as gd,readdirSync as md,rmSync as Mn}from"node:fs";import Qr from"node:path";import{pipeline as pd}from"node:stream/promises";var Me="0.28.0",Hi="https://github.com/rtk-ai/rtk/releases",qi=3e4,Zr={"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"},fd=200,hd=5e3;function zi(o){return Math.ceil(o.length/4)}function Pt(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 Ie=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return Qr.join(On(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Zt(t)){let n=await this.getVersion(t);if(n&&Pt(n,Me))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 ${Me}). 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=Zr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Zr).join(", ")}`);let s=o.binaryPath(),i=Qr.dirname(s);if(!e?.force&&Zt(s)){let c=await this.getVersion(s);if(c&&Pt(c,Me))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${Hi}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${Hi}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Zt(i)||gd(i,{recursive:!0});let l=Qr.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{Zt(l)&&Mn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),qi);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 pd(n.fromWeb(i.body),dd(t))}catch(i){throw Mn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${qi}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=Xr("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`tar extraction failed with code ${g}`))}),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{Mn(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of md(e)){let s=Qr.join(e,r),i=ud(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=Xr("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`PowerShell extraction failed with code ${g}`))}),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{Mn(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Zt(e)&&Mn(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Zt(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=Xr(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<fd)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=zi(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=zi(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=Xr(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},hd);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 yd}from"node:crypto";import qo,{WebSocketServer as bd}from"ws";var zo=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
349
349
  \r
350
350
  Browser relay is disabled`),t.destroy();return}if(s!==this.config.authToken){t.write(`HTTP/1.1 401 Unauthorized\r
351
351
  \r
352
- Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new hd({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===Ho.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===Ho.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!==Ho.OPEN)throw new Error("Extension not connected");let r=fd(),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){let r=(await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
352
+ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new bd({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===qo.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===qo.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!==qo.OPEN)throw new Error("Extension not connected");let r=yd(),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){let r=(await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
353
353
  const el = document.querySelector(${JSON.stringify(t)});
354
354
  if (!el) throw new Error('Element not found: ' + ${JSON.stringify(t)});
355
355
  el.scrollIntoView({ block: 'center' });
@@ -362,42 +362,42 @@ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.ha
362
362
  el.focus();
363
363
  if (el.value !== undefined) el.value = '';
364
364
  return 'focused';
365
- })()`,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 qi(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new qo(t,e)}Uo();function yd(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function bd(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Zr=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:yd(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=bd(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})}};An();import wd from"node:path";import vd from"node:os";var zi=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],Vi=["command","cmd"],Sd=[{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."}],Yi=vd.homedir();function kd(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,Yi),e=e.replace(/\$HOME(?=[/\\])/,Yi),e}function Cd(o,e){let t=[];for(let n of zi){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 Vi){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!zi.includes(n)&&!Vi.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var eo=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=Cd(r,n);for(let i of s){let a=kd(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 Sd)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(!wd.isAbsolute(e))return null;try{Ge(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"}};An();import zo from"node:fs";import Xi from"node:path";var xd=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"]),Td=8192,Rd=.01;function Ad(o){let e=Math.min(o.length,Td);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=Rd}var at=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(xd.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let g;try{g=zo.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(Ad(g)){i.skippedFiles++;continue}let x=g.toString("utf8"),y={filePath:p.absPath,extension:p.ext,size:p.size,content:x};for(let u of this.analyzers){let b=u.analyze(y);a.push(...b)}i.scannedFiles++}let c=Ed(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=zo.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=Xi.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=zo.lstatSync(i),l=Xi.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function Ed(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"}An();de();import _d from"node:fs";var Pd=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"]),Md=8192,Id=.01,lt=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=et("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=_d.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,Md);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=Id}isSkippedExtension(e){return Pd.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:Rn[i.category]??"COMMAND_INJECTION",severity:Tn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};var Pt={debug:0,info:1,warn:2,error:3};function Qi(o,e){return Pt[o]>=Pt[e]}var Zi=[/api[_-]?key/i,/apikey/i,/secret/i,/token/i,/password/i,/pin/i,/credential/i,/credentials/i,/private[_-]?key/i,/privatekey/i,/auth/i,/session[_-]?id/i],ea=[/^[A-Za-z0-9_-]{20,}$/,/^\d+:[A-Za-z0-9_-]{30,}$/,/^sk-[A-Za-z0-9]{20,}$/,/^sk-or-v1-[A-Za-z0-9]{20,}$/,/^Bearer\s+/i],Vo=200;import Mn from"node:fs";import $d from"node:path";var to=class{constructor(e,t){this.logsDir=e;this.maxFileSizeBytes=t;this.ensureLogsDir()}currentHour=null;currentFilePath=null;writeError=!1;ensureLogsDir(){try{Mn.existsSync(this.logsDir)||Mn.mkdirSync(this.logsDir,{recursive:!0,mode:448})}catch(e){console.error(`[logging] Failed to create logs directory: ${e instanceof Error?e.message:String(e)}`),this.writeError=!0}}getCurrentHourKey(){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return`${t}-${n}-${r}-${s}`}resolveCurrentFile(){let e=this.getCurrentHourKey();return(this.currentHour!==e||this.currentFilePath===null)&&(this.currentHour=e,this.currentFilePath=$d.join(this.logsDir,`gateway-${e}.jsonl`)),this.currentFilePath}checkFileSize(e){try{return Mn.statSync(e).size<this.maxFileSizeBytes}catch{return!0}}append(e){if(!this.writeError)try{let t=this.resolveCurrentFile();if(Mn.existsSync(t)&&!this.checkFileSize(t)){console.warn(`[logging] Log file ${t} exceeded max size, skipping write`);return}let n=JSON.stringify(e)+`
366
- `;Mn.appendFileSync(t,n,"utf8")}catch(t){if(t instanceof Error){let n=t;if(n.code==="ENOSPC"){console.warn("[logging] Disk full, disabling file logging"),this.writeError=!0;return}if(n.code==="EACCES"){console.warn("[logging] Permission denied, disabling file logging"),this.writeError=!0;return}}console.error(`[logging] Failed to write log entry: ${t instanceof Error?t.message:String(t)}`)}}hasWriteError(){return this.writeError}resetWriteError(){this.writeError=!1}};import ta from"node:fs";import Ld from"node:path";var no=class{constructor(e,t){this.logsDir=e;this.retentionHours=t}timer=null;purge(){let e=Date.now(),t=this.retentionHours*60*60*1e3,n=e-t;try{let r=ta.readdirSync(this.logsDir);for(let s of r){if(!s.startsWith("gateway-")||!s.endsWith(".jsonl"))continue;let i=s.slice(8,-6),a=this.parseHourTimestamp(i);if(a!==null&&a<n){let l=Ld.join(this.logsDir,s);try{ta.unlinkSync(l)}catch(c){console.warn(`[logging] Failed to purge ${s}: ${c instanceof Error?c.message:String(c)}`)}}}}catch(r){console.warn(`[logging] Purge scan failed: ${r instanceof Error?r.message:String(r)}`)}}parseHourTimestamp(e){let t=/^(\d{4})-(\d{2})-(\d{2})-(\d{2})$/.exec(e);if(!t)return null;let n=parseInt(t[1],10),r=parseInt(t[2],10)-1,s=parseInt(t[3],10),i=parseInt(t[4],10),a=new Date(n,r,s,i,0,0,0);return Number.isNaN(a.getTime())?null:a.getTime()}startTimer(e){this.timer===null&&(this.timer=setInterval(()=>{this.purge()},e),this.timer.unref())}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};function Od(o){return Zi.some(e=>e.test(o))}function Nd(o){return typeof o!="string"||o.length<10?!1:ea.some(e=>e.test(o))}function Yo(o,e){return o.length<=e?o:o.slice(0,e-1)+"\u2026"}function Xo(o,e,t=0){if(t>5)return"[max depth reached]";if(Od(o))return typeof e=="string"&&e.length>0?e.length>8?`${e.slice(0,4)}****${e.slice(-4)}`:"****":"[REDACTED]";if(Nd(e))return"[REDACTED]";if(typeof e=="string")return o.toLowerCase().includes("content")||o.toLowerCase().includes("message")?Yo(e,Vo):e;if(Array.isArray(e))return e.length>20?[`[array of ${e.length} items]`]:e.map((n,r)=>Xo(`[${r}]`,n,t+1));if(e instanceof Error)return{name:e.name,message:Yo(e.message,Vo),stack:e.stack?Yo(e.stack,500):void 0};if(e!==null&&typeof e=="object"){let n={},r=Object.entries(e);if(r.length>50)return`[object with ${r.length} keys]`;for(let[s,i]of r)n[s]=Xo(s,i,t+1);return n}return e}function na(o){let e={};for(let[t,n]of Object.entries(o))e[t]=Xo(t,n,0);return e}var ro=class o{static instance=null;writer;purger;level;enabled;started=!1;constructor(e,t){this.enabled=e.enabled,this.level=e.level,this.writer=new to(t,e.maxFileSizeMb*1024*1024),this.purger=new no(t,e.retentionHours)}static getInstance(e,t){return o.instance||(o.instance=new o(e,t)),o.instance}static resetInstance(){o.instance&&(o.instance.stop(),o.instance=null)}start(){this.started||(this.started=!0,this.purger.purge(),this.purger.startTimer(6e5))}stop(){this.started&&(this.started=!1,this.purger.stopTimer())}log(e,t,n,r){let s=r?na(r):{};if(this.writeToConsole(e,t,n,s),!this.enabled||!Qi(e,this.level))return;let i={ts:new Date().toISOString(),level:e,category:t,event:n,data:s};this.writer.append(i)}info(e,t,n){this.log("info",e,t,n)}warn(e,t,n){this.log("warn",e,t,n)}error(e,t,n){this.log("error",e,t,n)}debug(e,t,n){this.log("debug",e,t,n)}writeToConsole(e,t,n,r){let s=new Date().toISOString(),i=this.formatConsolePrefix(t),a=this.formatDataPreview(r);switch(e){case"error":console.error(`${s} ${i} ${n} ${a}`);break;case"warn":console.warn(`${s} ${i} ${n} ${a}`);break;default:console.log(`${s} ${i} ${n} ${a}`)}}formatConsolePrefix(e){return`${{"message.inbound":"\x1B[36m","message.outbound":"\x1B[35m","agent.turn":"\x1B[32m","agent.tool":"\x1B[33m",gateway:"\x1B[34m",channel:"\x1B[35m",security:"\x1B[31m"}[e]??"\x1B[0m"}[${e}]\x1B[0m`}formatDataPreview(e){let t=[];for(let[n,r]of Object.entries(e)){if(t.length>=3)break;let s=typeof r=="string"&&r.length>40?`${r.slice(0,39)}\u2026`:String(r);t.push(`${n}=${s}`)}return t.join(" ")}};de();async function ra(o){let e=structuredClone(o?.config??_()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=Z(e.agents.defaults.workspace);ft(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:
365
+ })()`,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 Vi(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new zo(t,e)}Go();function wd(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function vd(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var eo=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:wd(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=vd(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})}};En();import Sd from"node:path";import kd from"node:os";var Yi=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],Xi=["command","cmd"],Cd=[{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."}],Qi=kd.homedir();function xd(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,Qi),e=e.replace(/\$HOME(?=[/\\])/,Qi),e}function Td(o,e){let t=[];for(let n of Yi){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 Xi){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!Yi.includes(n)&&!Xi.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var to=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=Td(r,n);for(let i of s){let a=xd(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 Cd)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(!Sd.isAbsolute(e))return null;try{Ke(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"}};En();import Vo from"node:fs";import Zi from"node:path";var Rd=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"]),Ad=8192,Ed=.01;function _d(o){let e=Math.min(o.length,Ad);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=Ed}var lt=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(Rd.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let g;try{g=Vo.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(_d(g)){i.skippedFiles++;continue}let x=g.toString("utf8"),y={filePath:p.absPath,extension:p.ext,size:p.size,content:x};for(let u of this.analyzers){let b=u.analyze(y);a.push(...b)}i.scannedFiles++}let c=Pd(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=Vo.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=Zi.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=Vo.lstatSync(i),l=Zi.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function Pd(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"}En();ce();import Md from"node:fs";var Id=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"]),Ld=8192,$d=.01,ct=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=tt("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=Md.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,Ld);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=$d}isSkippedExtension(e){return Id.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:An[i.category]??"COMMAND_INJECTION",severity:Rn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};var Mt={debug:0,info:1,warn:2,error:3};function ea(o,e){return Mt[o]>=Mt[e]}var ta=[/api[_-]?key/i,/apikey/i,/secret/i,/token/i,/password/i,/pin/i,/credential/i,/credentials/i,/private[_-]?key/i,/privatekey/i,/auth/i,/session[_-]?id/i],na=[/^[A-Za-z0-9_-]{20,}$/,/^\d+:[A-Za-z0-9_-]{30,}$/,/^sk-[A-Za-z0-9]{20,}$/,/^sk-or-v1-[A-Za-z0-9]{20,}$/,/^Bearer\s+/i],Yo=200;import In from"node:fs";import Od from"node:path";var no=class{constructor(e,t){this.logsDir=e;this.maxFileSizeBytes=t;this.ensureLogsDir()}currentHour=null;currentFilePath=null;writeError=!1;ensureLogsDir(){try{In.existsSync(this.logsDir)||In.mkdirSync(this.logsDir,{recursive:!0,mode:448})}catch(e){console.error(`[logging] Failed to create logs directory: ${e instanceof Error?e.message:String(e)}`),this.writeError=!0}}getCurrentHourKey(){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return`${t}-${n}-${r}-${s}`}resolveCurrentFile(){let e=this.getCurrentHourKey();return(this.currentHour!==e||this.currentFilePath===null)&&(this.currentHour=e,this.currentFilePath=Od.join(this.logsDir,`gateway-${e}.jsonl`)),this.currentFilePath}checkFileSize(e){try{return In.statSync(e).size<this.maxFileSizeBytes}catch{return!0}}append(e){if(!this.writeError)try{let t=this.resolveCurrentFile();if(In.existsSync(t)&&!this.checkFileSize(t)){console.warn(`[logging] Log file ${t} exceeded max size, skipping write`);return}let n=JSON.stringify(e)+`
366
+ `;In.appendFileSync(t,n,"utf8")}catch(t){if(t instanceof Error){let n=t;if(n.code==="ENOSPC"){console.warn("[logging] Disk full, disabling file logging"),this.writeError=!0;return}if(n.code==="EACCES"){console.warn("[logging] Permission denied, disabling file logging"),this.writeError=!0;return}}console.error(`[logging] Failed to write log entry: ${t instanceof Error?t.message:String(t)}`)}}hasWriteError(){return this.writeError}resetWriteError(){this.writeError=!1}};import ra from"node:fs";import Nd from"node:path";var ro=class{constructor(e,t){this.logsDir=e;this.retentionHours=t}timer=null;purge(){let e=Date.now(),t=this.retentionHours*60*60*1e3,n=e-t;try{let r=ra.readdirSync(this.logsDir);for(let s of r){if(!s.startsWith("gateway-")||!s.endsWith(".jsonl"))continue;let i=s.slice(8,-6),a=this.parseHourTimestamp(i);if(a!==null&&a<n){let l=Nd.join(this.logsDir,s);try{ra.unlinkSync(l)}catch(c){console.warn(`[logging] Failed to purge ${s}: ${c instanceof Error?c.message:String(c)}`)}}}}catch(r){console.warn(`[logging] Purge scan failed: ${r instanceof Error?r.message:String(r)}`)}}parseHourTimestamp(e){let t=/^(\d{4})-(\d{2})-(\d{2})-(\d{2})$/.exec(e);if(!t)return null;let n=parseInt(t[1],10),r=parseInt(t[2],10)-1,s=parseInt(t[3],10),i=parseInt(t[4],10),a=new Date(n,r,s,i,0,0,0);return Number.isNaN(a.getTime())?null:a.getTime()}startTimer(e){this.timer===null&&(this.timer=setInterval(()=>{this.purge()},e),this.timer.unref())}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};function Dd(o){return ta.some(e=>e.test(o))}function jd(o){return typeof o!="string"||o.length<10?!1:na.some(e=>e.test(o))}function Xo(o,e){return o.length<=e?o:o.slice(0,e-1)+"\u2026"}function Qo(o,e,t=0){if(t>5)return"[max depth reached]";if(Dd(o))return typeof e=="string"&&e.length>0?e.length>8?`${e.slice(0,4)}****${e.slice(-4)}`:"****":"[REDACTED]";if(jd(e))return"[REDACTED]";if(typeof e=="string")return o.toLowerCase().includes("content")||o.toLowerCase().includes("message")?Xo(e,Yo):e;if(Array.isArray(e))return e.length>20?[`[array of ${e.length} items]`]:e.map((n,r)=>Qo(`[${r}]`,n,t+1));if(e instanceof Error)return{name:e.name,message:Xo(e.message,Yo),stack:e.stack?Xo(e.stack,500):void 0};if(e!==null&&typeof e=="object"){let n={},r=Object.entries(e);if(r.length>50)return`[object with ${r.length} keys]`;for(let[s,i]of r)n[s]=Qo(s,i,t+1);return n}return e}function oa(o){let e={};for(let[t,n]of Object.entries(o))e[t]=Qo(t,n,0);return e}var oo=class o{static instance=null;writer;purger;level;enabled;started=!1;constructor(e,t){this.enabled=e.enabled,this.level=e.level,this.writer=new no(t,e.maxFileSizeMb*1024*1024),this.purger=new ro(t,e.retentionHours)}static getInstance(e,t){return o.instance||(o.instance=new o(e,t)),o.instance}static resetInstance(){o.instance&&(o.instance.stop(),o.instance=null)}start(){this.started||(this.started=!0,this.purger.purge(),this.purger.startTimer(6e5))}stop(){this.started&&(this.started=!1,this.purger.stopTimer())}log(e,t,n,r){let s=r?oa(r):{};if(this.writeToConsole(e,t,n,s),!this.enabled||!ea(e,this.level))return;let i={ts:new Date().toISOString(),level:e,category:t,event:n,data:s};this.writer.append(i)}info(e,t,n){this.log("info",e,t,n)}warn(e,t,n){this.log("warn",e,t,n)}error(e,t,n){this.log("error",e,t,n)}debug(e,t,n){this.log("debug",e,t,n)}writeToConsole(e,t,n,r){let s=new Date().toISOString(),i=this.formatConsolePrefix(t),a=this.formatDataPreview(r);switch(e){case"error":console.error(`${s} ${i} ${n} ${a}`);break;case"warn":console.warn(`${s} ${i} ${n} ${a}`);break;default:console.log(`${s} ${i} ${n} ${a}`)}}formatConsolePrefix(e){return`${{"message.inbound":"\x1B[36m","message.outbound":"\x1B[35m","agent.turn":"\x1B[32m","agent.tool":"\x1B[33m",gateway:"\x1B[34m",channel:"\x1B[35m",security:"\x1B[31m"}[e]??"\x1B[0m"}[${e}]\x1B[0m`}formatDataPreview(e){let t=[];for(let[n,r]of Object.entries(e)){if(t.length>=3)break;let s=typeof r=="string"&&r.length>40?`${r.slice(0,39)}\u2026`:String(r);t.push(`${n}=${s}`)}return t.join(" ")}};ce();async function sa(o){let e=structuredClone(o?.config??_()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=Z(e.agents.defaults.workspace);ht(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:
367
367
  1. Set security.auth.enabled = true and configure a PIN
368
368
  2. Set gateway.host = 127.0.0.1 (loopback only)
369
- 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=ro.getInstance(e.logging,We());l.start(),l.info("gateway","start",{port:t,host:e.gateway.host,pid:process.pid,channels:e.channels.telegram.enabled||e.channels.discord.enabled?[e.channels.telegram.enabled?"telegram":null,e.channels.discord.enabled?"discord":null].filter(Boolean):[]});let c=new wt,d=o?.provider??Ne(e),p=new ot(n),g=Be(),x=new Xt(n,g),y=jr(e.tools.exec.timeout),u=Cn({target:"scheduled-job",timeoutMs:y}),b=Cn({target:"background-job",timeoutMs:y}),{cron:T,heartbeat:v,lifecycle:O}=Ve({cron:{dataDir:g,onJob:async(L,K)=>{let B=null,f=null;try{B=await u.run({payload:{message:L.payload.message,session:`cron:${L.id}`,channel:L.payload.channel??"cli",chatId:L.payload.to??"direct"},cwd:process.cwd(),signal:K?.signal})}catch(A){f=A instanceof Error?A.message:String(A)}let h=L.payload.channel??"cli",m=L.payload.to??"direct";if(L.payload.deliver&&L.payload.to&&B){await c.publishOutbound({channel:h,chatId:m,content:B});try{x.record({jobId:L.id,jobName:L.name,sessionKey:`cron:${L.id}`,channel:h,recipient:m,content:B})}catch(A){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${L.id}: ${A instanceof Error?A.message:String(A)}`)}}let k={kind:"cron_completed",taskId:L.id,label:L.name,status:B?"completed":"failed",result:B??"",error:f??"",originalTask:L.payload.message},C={channel:"system",senderId:"cron",chatId:`${h}:${m}`,content:B??f??"Cron job completed",metadata:{_notification:k}};return await c.publishInbound(C),B??f??"Cron job failed"}},heartbeat:{workspace:n,provider:d,model:e.agents.defaults.model,onExecute:async(L,K)=>{let f=p.listSessions().find(k=>(k.key??"").includes(":"))?.key??"cli:direct",[h,m]=f.split(/:(.*)/s,2);return b.run({payload:{message:L,session:"heartbeat",channel:h||"cli",chatId:m||"direct"},cwd:process.cwd(),signal:K?.signal})},onNotify:async L=>{let B=p.listSessions().find(m=>(m.key??"").includes(":"))?.key??"",[f,h]=B?B.split(/:(.*)/s,2):["cli","direct"];f!=="cli"&&f&&await c.publishOutbound({channel:f,chatId:h??"direct",content:L})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!v)throw new Error("Builtin heartbeat job registration is missing");let G,I;e.security.enabled&&(e.security.toolGuard.enabled&&(G=En.getInstance(e),G.registerGuardian(new Zr(G.getRules())),G.registerGuardian(new eo(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(I=new at([new lt]),console.log("[security] Skill scanner initialized")));let V=new _e,N=await V.resolve(e.tools.rtk);N.available?console.log(`rtk ${N.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 D=null;if(e.tools.browserRelay.enabled&&e.tools.browserRelay.authToken){let L=qi(e,K=>{K.connected&&console.log(`[browser-relay] Extension connected, ${K.attachedTabs.length} tabs attached`)});L&&(D=L,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let Y=new zt({bus:c,provider:d,workspace:n,sessionManager:p,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:T,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:O,loadConfig:_,rtkConfig:e.tools.rtk,rtkService:V,...G?{guardEngine:G}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...I?{skillScanner:I}:{},...D?{browserRelay:D}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),j=new Ur(e,c,O,l),J=Wi({agent:Y,cron:T,config:e,dataDir:g,port:t,sessionManager:p,sessionKey:o?.sessionKey??"default:everclaw",inboxService:x,workspacePath:n,channelManager:j,...D?{browserRelay:D}:{}});await T.start(),await v.start();let U=Y.run();return await j.startAll(),{config:e,workspace:n,port:J.port,loop:Y,heartbeat:v,cron:T,channels:j,dashboard:J,enabledChannels:j.enabledChannels,runPromise:U,browserRelay:D,logger:l}}async function Qo(o){o.logger?.info("gateway","stop",{reason:"shutdown"}),o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Wt.getInstance().stopAll(),await o.dashboard.close(),o.logger?.stop(),e}import q from"chalk";import{Command as Dd}from"commander";Ue();var H={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function oa(){let o=new Dd("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
369
+ 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=oo.getInstance(e.logging,xe());l.start(),l.info("gateway","start",{port:t,host:e.gateway.host,pid:process.pid,channels:e.channels.telegram.enabled||e.channels.discord.enabled?[e.channels.telegram.enabled?"telegram":null,e.channels.discord.enabled?"discord":null].filter(Boolean):[]});let c=new vt,d=o?.provider??je(e),p=new st(n),g=Ge(),x=new Qt(n,g),y=Fr(e.tools.exec.timeout),u=xn({target:"scheduled-job",timeoutMs:y}),b=xn({target:"background-job",timeoutMs:y}),{cron:T,heartbeat:v,lifecycle:O}=Ye({cron:{dataDir:g,onJob:async($,K)=>{let B=null,f=null;try{B=await u.run({payload:{message:$.payload.message,session:`cron:${$.id}`,channel:$.payload.channel??"cli",chatId:$.payload.to??"direct"},cwd:process.cwd(),signal:K?.signal})}catch(A){f=A instanceof Error?A.message:String(A)}let h=$.payload.channel??"cli",m=$.payload.to??"direct";if($.payload.deliver&&$.payload.to&&B){await c.publishOutbound({channel:h,chatId:m,content:B});try{x.record({jobId:$.id,jobName:$.name,sessionKey:`cron:${$.id}`,channel:h,recipient:m,content:B})}catch(A){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${$.id}: ${A instanceof Error?A.message:String(A)}`)}}let k={kind:"cron_completed",taskId:$.id,label:$.name,status:B?"completed":"failed",result:B??"",error:f??"",originalTask:$.payload.message},C={channel:"system",senderId:"cron",chatId:`${h}:${m}`,content:B??f??"Cron job completed",metadata:{_notification:k}};return await c.publishInbound(C),B??f??"Cron job failed"}},heartbeat:{workspace:n,provider:d,model:e.agents.defaults.model,onExecute:async($,K)=>{let f=p.listSessions().find(k=>(k.key??"").includes(":"))?.key??"cli:direct",[h,m]=f.split(/:(.*)/s,2);return b.run({payload:{message:$,session:"heartbeat",channel:h||"cli",chatId:m||"direct"},cwd:process.cwd(),signal:K?.signal})},onNotify:async $=>{let B=p.listSessions().find(m=>(m.key??"").includes(":"))?.key??"",[f,h]=B?B.split(/:(.*)/s,2):["cli","direct"];f!=="cli"&&f&&await c.publishOutbound({channel:f,chatId:h??"direct",content:$})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!v)throw new Error("Builtin heartbeat job registration is missing");let G,I;e.security.enabled&&(e.security.toolGuard.enabled&&(G=_n.getInstance(e),G.registerGuardian(new eo(G.getRules())),G.registerGuardian(new to(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(I=new lt([new ct]),console.log("[security] Skill scanner initialized")));let V=new Ie,N=await V.resolve(e.tools.rtk);N.available?console.log(`rtk ${N.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 D=null;if(e.tools.browserRelay.enabled&&e.tools.browserRelay.authToken){let $=Vi(e,K=>{K.connected&&console.log(`[browser-relay] Extension connected, ${K.attachedTabs.length} tabs attached`)});$&&(D=$,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let Y=new Vt({bus:c,provider:d,workspace:n,sessionManager:p,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:T,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:O,loadConfig:_,rtkConfig:e.tools.rtk,rtkService:V,...G?{guardEngine:G}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...I?{skillScanner:I}:{},...D?{browserRelay:D}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),j=new Gr(e,c,O,l),J=Ji({agent:Y,cron:T,config:e,dataDir:g,port:t,sessionManager:p,sessionKey:o?.sessionKey??"default:everclaw",inboxService:x,workspacePath:n,channelManager:j,...D?{browserRelay:D}:{}});await T.start(),await v.start();let U=Y.run();return await j.startAll(),{config:e,workspace:n,port:J.port,loop:Y,heartbeat:v,cron:T,channels:j,dashboard:J,enabledChannels:j.enabledChannels,runPromise:U,browserRelay:D,logger:l}}async function Zo(o){o.logger?.info("gateway","stop",{reason:"shutdown"}),o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Kt.getInstance().stopAll(),await o.dashboard.close(),o.logger?.stop(),e}import q from"chalk";import{Command as Fd}from"commander";We();var H={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function ia(){let o=new Fd("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
370
370
  Examples:
371
371
  everclaw rtk install Install the latest rtk binary
372
372
  everclaw rtk update Update to the latest version
373
- 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 _e;try{let n=await t.install({version:e.version,force:e.force});console.log(q.green(`
374
- rtk v${n.version} installed to ${n.binaryPath}`)),console.log(q.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(q.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new _e,t=await e.getStatus();if(!t.installed){console.log(q.yellow("rtk is not installed."));return}await e.uninstall(),console.log(q.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new _e().getStatus(),n=_();console.log(q.cyan(`
373
+ 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 Ie;try{let n=await t.install({version:e.version,force:e.force});console.log(q.green(`
374
+ rtk v${n.version} installed to ${n.binaryPath}`)),console.log(q.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(q.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Ie,t=await e.getStatus();if(!t.installed){console.log(q.yellow("rtk is not installed."));return}await e.uninstall(),console.log(q.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new Ie().getStatus(),n=_();console.log(q.cyan(`
375
375
  RTK Token Compression
376
- `)),t.installed&&t.version?(console.log(` Status: ${q.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),_t(t.version,Ee)||(console.log(q.yellow(` Warning: Version ${t.version} is below minimum ${Ee}`)),console.log(q.gray(` Run ${q.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${q.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(q.gray(` Run ${q.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${q.gray("Not installed")}`),console.log(q.gray(` Fix: Run ${q.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?q.green("yes"):q.gray("no")}`),console.log(q.gray(`
377
- Minimum version: ${Ee}`)),console.log(q.gray(` Supported platforms: ${Object.keys(Qr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new _e,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?q.cyan(`Current: v${n}`):q.gray("rtk is not installed."));try{console.log(q.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(q.green(`Already at latest version (v${r.version})`)):console.log(q.green(`
378
- rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(q.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=_();if(e.tools.rtk.enabled){console.log(q.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(q.green("RTK token compression enabled.")),console.log(q.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(q.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(q.yellow("RTK token compression disabled.")),console.log(q.gray("Restart the gateway for changes to take effect.")),console.log(q.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}Ot();Ue();import{spawn as jd}from"node:child_process";import Fd from"node:fs";import Bd from"node:path";import W from"chalk";import{Command as Ud,Option as Gd}from"commander";function Wd(){let o=process.argv[1];if(o){let e=Bd.resolve(o);if(Fd.existsSync(e))return e}return"everclaw"}async function Kd(){let o=Ie();if(!o)return!0;if(!Me(o.pid))return $e(),!0;console.log(W.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(W.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await po(o.pid,1e4)){console.log(W.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return $e(),console.log(W.green("Gateway stopped.")),!0}async function sa(o){let e=Ie();if(e&&Me(e.pid)){console.error(W.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(W.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=H.PROCESS_CONFLICT;return}e&&$e();let t=_(),n=es(o.port,t.gateway.port),r=Wd(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i="",a=jd(r,s,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env}});if(!a.pid){console.error(W.red("Failed to spawn gateway process.")),process.exitCode=H.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(),mo({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!Me(a.pid)){$e(),console.error(W.red("Gateway process exited immediately.")),i.trim()?console.error(W.gray(i.trim().split(`
379
- `).map(l=>` ${l}`).join(`
380
- `))):console.error(W.gray("No error output captured. Try running with -f for details.")),process.exitCode=H.GENERAL_ERROR;return}console.log(W.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(W.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(W.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function Zo(o){let e=_(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=es(o.port,e.gateway.port));let n=nn(e,process.env,t),r=n.gateway.port,s=Ie();if(s&&s.pid!==process.pid&&Me(s.pid)){console.error(W.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(W.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=H.PROCESS_CONFLICT;return}s&&s.pid!==process.pid&&$e();let i;try{i=await ra({config:n,port:r,sessionKey:"default:everclaw"})}catch(p){console.log(W.red(String(p))),process.exitCode=H.GENERAL_ERROR;return}mo({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(W.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(W.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(W.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(W.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(W.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async p=>a||(console.log(W.yellow(`
381
- Received ${p}. Shutting down gateway...`)),$e(process.pid),a=Qo(i).then(g=>{g>0&&console.log(W.gray(`Cancelled ${g} task(s) during shutdown.`))}).catch(g=>{process.exitCode=1,console.log(W.red(`Gateway shutdown failed: ${String(g)}`))}),a),c=()=>{l("SIGINT")},d=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",d);try{await i.runPromise,a&&await a}finally{$e(process.pid),process.off("SIGINT",c),process.off("SIGTERM",d)}}function ia(){let o=new Ud("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
376
+ `)),t.installed&&t.version?(console.log(` Status: ${q.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),Pt(t.version,Me)||(console.log(q.yellow(` Warning: Version ${t.version} is below minimum ${Me}`)),console.log(q.gray(` Run ${q.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${q.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(q.gray(` Run ${q.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${q.gray("Not installed")}`),console.log(q.gray(` Fix: Run ${q.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?q.green("yes"):q.gray("no")}`),console.log(q.gray(`
377
+ Minimum version: ${Me}`)),console.log(q.gray(` Supported platforms: ${Object.keys(Zr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Ie,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?q.cyan(`Current: v${n}`):q.gray("rtk is not installed."));try{console.log(q.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(q.green(`Already at latest version (v${r.version})`)):console.log(q.green(`
378
+ rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(q.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=_();if(e.tools.rtk.enabled){console.log(q.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(q.green("RTK token compression enabled.")),console.log(q.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(q.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(q.yellow("RTK token compression disabled.")),console.log(q.gray("Restart the gateway for changes to take effect.")),console.log(q.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}Nt();We();import{spawn as Bd}from"node:child_process";import Se from"node:fs";import ts from"node:path";import W from"chalk";import{Command as Ud,Option as Gd}from"commander";ce();var Wd="gateway.stdout.log",Kd="gateway.stderr.log";function Jd(o=xe()){return{stdoutPath:ts.join(o,Wd),stderrPath:ts.join(o,Kd)}}function Hd(){let o=xe();Se.mkdirSync(o,{recursive:!0,mode:448});let{stdoutPath:e,stderrPath:t}=Jd(o),n=Se.existsSync(t)?Se.statSync(t).size:0;return{stdoutFd:Se.openSync(e,"a"),stderrFd:Se.openSync(t,"a"),stdoutPath:e,stderrPath:t,stderrOffset:n}}function qd(o){try{Se.closeSync(o.stdoutFd)}catch{}try{Se.closeSync(o.stderrFd)}catch{}}function zd(o,e=0,t=4096){if(!Se.existsSync(o))return"";let n=Se.statSync(o).size;if(n<=e)return"";let r=Math.max(e,n-t),s=n-r,i=Se.openSync(o,"r");try{let a=Buffer.alloc(s);return Se.readSync(i,a,0,s,r),a.toString("utf8").trim()}finally{Se.closeSync(i)}}function Vd(){let o=(n,r)=>{let s=r instanceof Error?r.stack??r.message:String(r);Te(process.pid),console.error(`[gateway] ${n}: ${s}`)},e=n=>{o("uncaughtException",n),process.exit(1)},t=n=>{o("unhandledRejection",n),process.exit(1)};return process.once("uncaughtException",e),process.once("unhandledRejection",t),()=>{process.off("uncaughtException",e),process.off("unhandledRejection",t)}}function Yd(){let o=process.argv[1];if(o){let e=ts.resolve(o);if(Se.existsSync(e))return e}return"everclaw"}async function Xd(){let o=Oe();if(!o)return!0;if(!$e(o.pid))return Te(),!0;console.log(W.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(W.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await fo(o.pid,1e4)){console.log(W.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return Te(),console.log(W.green("Gateway stopped.")),!0}async function aa(o){let e=Oe();if(e&&$e(e.pid)){console.error(W.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(W.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=H.PROCESS_CONFLICT;return}e&&Te();let t=_(),n=ns(o.port,t.gateway.port),r=Yd(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i=Hd(),a=Bd(r,s,{detached:!0,stdio:["ignore",i.stdoutFd,i.stderrFd],env:{...process.env}});if(qd(i),!a.pid){console.error(W.red("Failed to spawn gateway process.")),process.exitCode=H.GENERAL_ERROR;return}if(a.unref(),po({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!$e(a.pid)){Te(),console.error(W.red("Gateway process exited immediately."));let l=zd(i.stderrPath,i.stderrOffset);console.error(l?W.gray(l.split(`
379
+ `).map(c=>` ${c}`).join(`
380
+ `)):W.gray(`No stderr output captured. Check ${i.stderrPath} or run with -f for details.`)),process.exitCode=H.GENERAL_ERROR;return}console.log(W.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(W.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(W.gray(`Logs: ${i.stdoutPath} and ${i.stderrPath}`)),console.log(W.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function es(o){let e=_(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=ns(o.port,e.gateway.port));let n=rn(e,process.env,t),r=n.gateway.port,s=Vd(),i=Oe();if(i&&i.pid!==process.pid&&$e(i.pid)){console.error(W.red(`Gateway is already running (PID ${i.pid}, port ${i.port}).`)),console.error(W.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=H.PROCESS_CONFLICT,s();return}i&&i.pid!==process.pid&&Te();let a;try{a=await sa({config:n,port:r,sessionKey:"default:everclaw"})}catch(g){console.log(W.red(String(g))),process.exitCode=H.GENERAL_ERROR,s();return}po({pid:process.pid,port:a.port,startedAt:new Date().toISOString()}),console.log(W.cyan(`Starting everclaw gateway on port ${a.port}...`)),a.enabledChannels.length?console.log(W.green(`Channels enabled: ${a.enabledChannels.join(", ")}`)):console.log(W.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(W.green(`Dashboard: http://localhost:${a.port}/chat`)),console.log(W.gray("Gateway running. Press Ctrl+C to stop."));let l=null,c=async g=>l||(console.log(W.yellow(`
381
+ Received ${g}. Shutting down gateway...`)),Te(process.pid),l=Zo(a).then(x=>{x>0&&console.log(W.gray(`Cancelled ${x} task(s) during shutdown.`))}).catch(x=>{process.exitCode=1,console.log(W.red(`Gateway shutdown failed: ${String(x)}`))}),l),d=()=>{c("SIGINT")},p=()=>{c("SIGTERM")};process.once("SIGINT",d),process.once("SIGTERM",p);try{await a.runPromise,l&&await l}finally{Te(process.pid),process.off("SIGINT",d),process.off("SIGTERM",p),s()}}function la(){let o=new Ud("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
382
382
  Examples:
383
383
  everclaw gateway Start the gateway in background (default)
384
384
  everclaw gateway start -f Start in foreground
385
385
  everclaw gateway status Check if gateway is running
386
386
  everclaw gateway restart Restart the gateway
387
- 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(me.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new Gd("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await Zo({port:e.port,host:e.host});return}if(e.foreground){await Zo({port:e.port,host:e.host});return}await sa({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Ie();if(!e){console.log(W.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=H.GENERAL_ERROR;return}if(!Me(e.pid)){console.log(W.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),$e();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(W.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=H.GENERAL_ERROR;return}if(await po(e.pid,1e4))$e(),console.log(W.green("Gateway stopped."));else{console.log(W.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}$e(),console.log(W.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(me.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 Kd()){if(!e.force){console.error(W.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=H.GENERAL_ERROR;return}console.log(W.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(W.cyan("Starting gateway...")),e.foreground?await Zo({port:e.port,host:e.host}):await sa({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Ie();if(!e){console.log(W.yellow("Gateway is not running (no PID file found)."));return}if(!Me(e.pid)){console.log(W.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=bt(e.startedAt),n=null;try{let d=await fetch(`http://127.0.0.1:${e.port}/api/status`,{signal:AbortSignal.timeout(2e3)});d.ok&&(n=await d.json())}catch{}console.log(W.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`);let r=n?.runtime,s=r?.tasks||[],i=r?.compaction,a=s.filter(d=>d.status==="running"),l=s.filter(d=>d.status==="completed"),c=s.filter(d=>d.status==="failed");if(console.log(` Tasks: ${a.length} running, ${l.length} completed, ${c.length} failed`),i){let d=i.tokensFreed,p=g=>g>=1e6?`${(g/1e6).toFixed(1)}M`:g>=1e3?`${(g/1e3).toFixed(1)}K`:String(g);console.log(` Compaction: ${i.microCompactions??0} micro, ${i.autoCompactions??0} auto, ${d?p(d):0} tokens freed`)}}),o}import X from"chalk";import{Command as Jd}from"commander";import ct from"node:fs";import dt from"node:path";Ue();je();function aa(){let o=new Jd("skills").description("Manage skills");return o.addHelpText("after",`
387
+ 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(me.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new Gd("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await es({port:e.port,host:e.host});return}if(e.foreground){await es({port:e.port,host:e.host});return}await aa({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Oe();if(!e){console.log(W.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=H.GENERAL_ERROR;return}if(!$e(e.pid)){console.log(W.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),Te();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(W.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=H.GENERAL_ERROR;return}if(await fo(e.pid,1e4))Te(),console.log(W.green("Gateway stopped."));else{console.log(W.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}Te(),console.log(W.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(me.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 Xd()){if(!e.force){console.error(W.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=H.GENERAL_ERROR;return}console.log(W.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(W.cyan("Starting gateway...")),e.foreground?await es({port:e.port,host:e.host}):await aa({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Oe();if(!e){console.log(W.yellow("Gateway is not running (no PID file found)."));return}if(!$e(e.pid)){console.log(W.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=wt(e.startedAt),n=null;try{let d=await fetch(`http://127.0.0.1:${e.port}/api/status`,{signal:AbortSignal.timeout(2e3)});d.ok&&(n=await d.json())}catch{}console.log(W.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`);let r=n?.runtime,s=r?.tasks||[],i=r?.compaction,a=s.filter(d=>d.status==="running"),l=s.filter(d=>d.status==="completed"),c=s.filter(d=>d.status==="failed");if(console.log(` Tasks: ${a.length} running, ${l.length} completed, ${c.length} failed`),i){let d=i.tokensFreed,p=g=>g>=1e6?`${(g/1e6).toFixed(1)}M`:g>=1e3?`${(g/1e3).toFixed(1)}K`:String(g);console.log(` Compaction: ${i.microCompactions??0} micro, ${i.autoCompactions??0} auto, ${d?p(d):0} tokens freed`)}}),o}import X from"chalk";import{Command as Qd}from"commander";import dt from"node:fs";import ut from"node:path";We();Be();function ca(){let o=new Qd("skills").description("Manage skills");return o.addHelpText("after",`
388
388
  Examples:
389
389
  everclaw skills list List all available skills
390
390
  everclaw skills show browser Show details for a skill
391
391
  everclaw skills create my-skill Create a new skill in workspace
392
- 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=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new at([new lt]):null,a=new He(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(X.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(X.gray("No available skills. Use --all to see all skills."));return}console.log(X.cyan(`
392
+ 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=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new lt([new ct]):null,a=new qe(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(X.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(X.gray("No available skills. Use --all to see all skills."));return}console.log(X.cyan(`
393
393
  Skills
394
- `)),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"?X.green("available"):c.status==="blocked"?X.red("blocked"):X.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=_(),n=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new at([new lt]):null,l=new He(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(X.red(`Skill '${e}' not found.`)),console.log(X.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=H.GENERAL_ERROR;return}console.log(X.cyan(`
394
+ `)),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"?X.green("available"):c.status==="blocked"?X.red("blocked"):X.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=_(),n=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new lt([new ct]):null,l=new qe(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(X.red(`Skill '${e}' not found.`)),console.log(X.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=H.GENERAL_ERROR;return}console.log(X.cyan(`
395
395
  Skill: ${l.name}
396
396
  `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?X.green("available"):X.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
397
397
  Description: ${l.description}
398
- `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills"),s=dt.join(r,e);if(!ct.existsSync(s)){console.log(X.red(`Skill '${e}' not found in workspace skills.`)),console.log(X.gray("Only workspace-scoped skills can be removed.")),process.exitCode=H.GENERAL_ERROR;return}ct.rmSync(s,{recursive:!0,force:!0}),console.log(X.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills");if(!ct.existsSync(r)){console.log(X.gray("No workspace skills directory found."));return}let s=new at([new lt]),i=e?[e]:ct.readdirSync(r).filter(a=>ct.statSync(dt.join(r,a)).isDirectory());if(i.length===0){console.log(X.gray("No skills to scan."));return}console.log(X.cyan(`
398
+ `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=ut.join(n,"skills"),s=ut.join(r,e);if(!dt.existsSync(s)){console.log(X.red(`Skill '${e}' not found in workspace skills.`)),console.log(X.gray("Only workspace-scoped skills can be removed.")),process.exitCode=H.GENERAL_ERROR;return}dt.rmSync(s,{recursive:!0,force:!0}),console.log(X.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=ut.join(n,"skills");if(!dt.existsSync(r)){console.log(X.gray("No workspace skills directory found."));return}let s=new lt([new ct]),i=e?[e]:dt.readdirSync(r).filter(a=>dt.statSync(ut.join(r,a)).isDirectory());if(i.length===0){console.log(X.gray("No skills to scan."));return}console.log(X.cyan(`
399
399
  Skill Security Scan
400
- `));for(let a of i){let l=dt.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${X.green("passed")}`);else{console.log(`${a.padEnd(28)} ${X.red("blocked")}`);for(let d of c.findings)console.log(X.gray(` - ${d.severity}: ${d.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills"),s=dt.join(r,e);if(ct.existsSync(s)){console.log(X.red(`Skill '${e}' already exists.`)),process.exitCode=H.GENERAL_ERROR;return}ct.mkdirSync(s,{recursive:!0});let i=`---
400
+ `));for(let a of i){let l=ut.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${X.green("passed")}`);else{console.log(`${a.padEnd(28)} ${X.red("blocked")}`);for(let d of c.findings)console.log(X.gray(` - ${d.severity}: ${d.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=_(),n=Z(t.agents.defaults.workspace),r=ut.join(n,"skills"),s=ut.join(r,e);if(dt.existsSync(s)){console.log(X.red(`Skill '${e}' already exists.`)),process.exitCode=H.GENERAL_ERROR;return}dt.mkdirSync(s,{recursive:!0});let i=`---
401
401
  name: ${e}
402
402
  description: A custom skill
403
403
  always_on: false
@@ -406,22 +406,22 @@ always_on: false
406
406
  # ${e}
407
407
 
408
408
  TODO: Add skill instructions here.
409
- `;ct.writeFileSync(dt.join(s,"SKILL.md"),i),console.log(X.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(!qn(e)){console.log(X.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=H.GENERAL_ERROR;return}let t=_(),n=Z(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(kt(),Ds)),s=new r,i="clawhub@latest",a=12e4;console.log(X.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(`
409
+ `;dt.writeFileSync(ut.join(s,"SKILL.md"),i),console.log(X.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(!zn(e)){console.log(X.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=H.GENERAL_ERROR;return}let t=_(),n=Z(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(Ct(),Fs)),s=new r,i="clawhub@latest",a=12e4;console.log(X.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(`
410
410
  `),p=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(X.red(`Failed to install skill '${e}'${p}: ${d||"unknown error"}`)),process.exitCode=H.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
411
- `);console.log(X.green(`Skill '${e}' installed successfully.`)),c&&console.log(X.gray(c)),console.log(X.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(X.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o}Ue();import re from"chalk";import{Command as Hd}from"commander";function qd(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function la(){let o=new Hd("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
411
+ `);console.log(X.green(`Skill '${e}' installed successfully.`)),c&&console.log(X.gray(c)),console.log(X.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(X.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=H.CONNECTIVITY_ERROR}}),o}We();import re from"chalk";import{Command as Zd}from"commander";function eu(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function da(){let o=new Zd("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
412
412
  Examples:
413
413
  everclaw mcp list List configured servers
414
414
  everclaw mcp add fs --command npx --args "-y @anthropic/mcp-server-filesystem /path"
415
415
  everclaw mcp test fs Test connectivity
416
416
  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(re.gray("No MCP servers configured.")),console.log(re.gray(`Run ${re.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(re.cyan(`
417
417
  MCP Servers
418
- `)),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)+qd(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(re.red("Error: Either --command or --url is required.")),process.exitCode=H.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(re.red("Error: --timeout must be a positive integer.")),process.exitCode=H.GENERAL_ERROR;return}n=i}let r=_(),s=r.tools.mcpServers;if(s[e]){console.log(re.yellow(`MCP server '${e}' already exists.`)),process.exitCode=H.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(re.green(`Added MCP server '${e}'.`)),console.log(re.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=H.GENERAL_ERROR;return}delete n[e],oe(t),console.log(re.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(re.cyan(`
418
+ `)),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)+eu(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(re.red("Error: Either --command or --url is required.")),process.exitCode=H.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(re.red("Error: --timeout must be a positive integer.")),process.exitCode=H.GENERAL_ERROR;return}n=i}let r=_(),s=r.tools.mcpServers;if(s[e]){console.log(re.yellow(`MCP server '${e}' already exists.`)),process.exitCode=H.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(re.green(`Added MCP server '${e}'.`)),console.log(re.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=H.GENERAL_ERROR;return}delete n[e],oe(t),console.log(re.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(re.cyan(`
419
419
  MCP Server: ${e}
420
420
  `)),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(re.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(re.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(re.cyan(`
421
421
  MCP Connectivity Test
422
- `));let{McpClientManager:s}=await Promise.resolve().then(()=>(wn(),Lr)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${re.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${re.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=H.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=H.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(wn(),Lr)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(re.gray(`No tools exposed by '${e}'.`));else{console.log(re.cyan(`
422
+ `));let{McpClientManager:s}=await Promise.resolve().then(()=>(vn(),Or)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${re.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${re.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=H.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(re.red(`MCP server '${e}' not found.`)),process.exitCode=H.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(vn(),Or)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(re.gray(`No tools exposed by '${e}'.`));else{console.log(re.cyan(`
423
423
  Tools from ${e} (${i.length})
424
- `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(re.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=H.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}de();import Se from"node:fs";import Mt from"node:os";import zd from"node:path";import{execSync as ca}from"node:child_process";import $ from"chalk";import{Command as Vd}from"commander";function ts(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function Yd(){let o=process.argv[1];if(o){let e=zd.resolve(o);if(Se.existsSync(e))return e}try{let e=ca("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&Se.existsSync(e))return e}catch{}return"everclaw"}function Xd(o){let e=We();return`[Unit]
424
+ `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(re.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=H.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}ce();import ke from"node:fs";import It from"node:os";import tu from"node:path";import{execSync as ua}from"node:child_process";import L from"chalk";import{Command as nu}from"commander";function rs(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function ru(){let o=process.argv[1];if(o){let e=tu.resolve(o);if(ke.existsSync(e))return e}try{let e=ua("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&ke.existsSync(e))return e}catch{}return"everclaw"}function ou(o){let e=xe();return`[Unit]
425
425
  Description=Everclaw AI Assistant Gateway
426
426
  After=network-online.target
427
427
  Wants=network-online.target
@@ -437,7 +437,7 @@ StandardError=append:${e}/gateway.stderr.log
437
437
 
438
438
  [Install]
439
439
  WantedBy=default.target
440
- `}function Qd(o){let e=We();return`<?xml version="1.0" encoding="UTF-8"?>
440
+ `}function su(o){let e=xe();return`<?xml version="1.0" encoding="UTF-8"?>
441
441
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
442
442
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
443
443
  <plist version="1.0">
@@ -460,21 +460,21 @@ WantedBy=default.target
460
460
  <string>${e}/gateway.stderr.log</string>
461
461
  </dict>
462
462
  </plist>
463
- `}function he(o){try{return{ok:!0,output:ca(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function Zd(){let o=ts(),e=Mt.homedir(),t=We(e),n=Yd();Se.mkdirSync(t,{recursive:!0}),o==="linux"?await eu(e,n):o==="macos"?await tu(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 eu(o,e){let t=so(o),n=On(o),r=Xd(e);console.log($.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),Se.mkdirSync(t,{recursive:!0}),Se.writeFileSync(n,r,"utf8"),console.log($.green(" Unit file written."));let s=he("systemctl --user daemon-reload");s.ok||console.log($.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=he("systemctl --user enable everclaw");i.ok?console.log($.green(" Service enabled.")):console.log($.yellow(` Warning: enable failed: ${i.output}`));let a=he("systemctl --user start everclaw");a.ok?console.log($.green(" Service started.")):console.log($.yellow(` Warning: start failed: ${a.output}`));let l=he(`loginctl show-user ${Mt.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log($.yellow(`
464
- Note: Linger is not enabled. The service will stop when you log out.`)),console.log($.gray(` Run: loginctl enable-linger ${Mt.userInfo().username}`)),console.log($.gray(" (This may require sudo or admin assistance.)"))),console.log($.green(`
465
- 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 tu(o,e){let t=io(o),n=Nn(o),r=Qd(e);console.log($.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),Se.mkdirSync(t,{recursive:!0}),Se.writeFileSync(n,r,"utf8"),console.log($.green(" Plist written.")),he(`launchctl unload ${n} 2>/dev/null`);let s=he(`launchctl load ${n}`);s.ok?console.log($.green(" Agent loaded.")):console.log($.yellow(` Warning: load failed: ${s.output}`)),console.log($.green(`
466
- 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 nu(){let o=ts(),e=Mt.homedir();o==="linux"?await ru(e):o==="macos"?await ou(e):(console.log($.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function ru(o){let e=On(o);console.log($.cyan("Uninstalling systemd user service...")),he("systemctl --user stop everclaw"),he("systemctl --user disable everclaw"),Se.existsSync(e)?(Se.unlinkSync(e),console.log($.green(" Unit file removed."))):console.log($.gray(" No unit file found.")),he("systemctl --user daemon-reload"),console.log($.green(`
467
- Service uninstalled.`))}async function ou(o){let e=Nn(o);console.log($.cyan("Uninstalling launchd user agent...")),he(`launchctl unload ${e} 2>/dev/null`).ok&&console.log($.green(" Agent unloaded.")),Se.existsSync(e)?(Se.unlinkSync(e),console.log($.green(" Plist removed."))):console.log($.gray(" No plist found.")),console.log($.green(`
468
- Service uninstalled.`))}async function su(){let o=ts(),e=Mt.homedir();console.log($.cyan(`Service Registration Status
469
- `)),o==="linux"?await iu(e):o==="macos"?await au(e):console.log($.gray(`Service management not supported on '${process.platform}'.`))}async function iu(o){let e=On(o),t=Se.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?$.green(e):$.gray("not found")}`),!t){console.log($.gray(`
470
- Service is not installed. Run: everclaw service install`));return}let n=he("systemctl --user is-enabled everclaw 2>/dev/null"),r=he("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=he(`loginctl show-user ${Mt.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 ${Mt.userInfo().username}`))}async function au(o){let e=Nn(o),t=Se.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?$.green(e):$.gray("not found")}`),!t){console.log($.gray(`
471
- Service is not installed. Run: everclaw service install`));return}let n=he("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 da(){let o=new Vd("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
463
+ `}function he(o){try{return{ok:!0,output:ua(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function iu(){let o=rs(),e=It.homedir(),t=xe(e),n=ru();ke.mkdirSync(t,{recursive:!0}),o==="linux"?await au(e,n):o==="macos"?await lu(e,n):(console.log(L.red(`Service installation is not supported on '${process.platform}'.`)),console.log(L.gray("Supported: Linux (systemd), macOS (launchd).")),process.exitCode=1)}async function au(o,e){let t=io(o),n=Nn(o),r=ou(e);console.log(L.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),ke.mkdirSync(t,{recursive:!0}),ke.writeFileSync(n,r,"utf8"),console.log(L.green(" Unit file written."));let s=he("systemctl --user daemon-reload");s.ok||console.log(L.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=he("systemctl --user enable everclaw");i.ok?console.log(L.green(" Service enabled.")):console.log(L.yellow(` Warning: enable failed: ${i.output}`));let a=he("systemctl --user start everclaw");a.ok?console.log(L.green(" Service started.")):console.log(L.yellow(` Warning: start failed: ${a.output}`));let l=he(`loginctl show-user ${It.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log(L.yellow(`
464
+ Note: Linger is not enabled. The service will stop when you log out.`)),console.log(L.gray(` Run: loginctl enable-linger ${It.userInfo().username}`)),console.log(L.gray(" (This may require sudo or admin assistance.)"))),console.log(L.green(`
465
+ Service installed successfully.`)),console.log(L.gray("Use: systemctl --user status everclaw")),console.log(L.gray(" systemctl --user stop everclaw")),console.log(L.gray(" journalctl --user -u everclaw -f"))}async function lu(o,e){let t=ao(o),n=Dn(o),r=su(e);console.log(L.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),ke.mkdirSync(t,{recursive:!0}),ke.writeFileSync(n,r,"utf8"),console.log(L.green(" Plist written.")),he(`launchctl unload ${n} 2>/dev/null`);let s=he(`launchctl load ${n}`);s.ok?console.log(L.green(" Agent loaded.")):console.log(L.yellow(` Warning: load failed: ${s.output}`)),console.log(L.green(`
466
+ Service installed successfully.`)),console.log(L.gray("Use: launchctl list | grep everclaw")),console.log(L.gray(" launchctl unload "+n)),console.log(L.gray(" launchctl load "+n))}async function cu(){let o=rs(),e=It.homedir();o==="linux"?await du(e):o==="macos"?await uu(e):(console.log(L.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function du(o){let e=Nn(o);console.log(L.cyan("Uninstalling systemd user service...")),he("systemctl --user stop everclaw"),he("systemctl --user disable everclaw"),ke.existsSync(e)?(ke.unlinkSync(e),console.log(L.green(" Unit file removed."))):console.log(L.gray(" No unit file found.")),he("systemctl --user daemon-reload"),console.log(L.green(`
467
+ Service uninstalled.`))}async function uu(o){let e=Dn(o);console.log(L.cyan("Uninstalling launchd user agent...")),he(`launchctl unload ${e} 2>/dev/null`).ok&&console.log(L.green(" Agent unloaded.")),ke.existsSync(e)?(ke.unlinkSync(e),console.log(L.green(" Plist removed."))):console.log(L.gray(" No plist found.")),console.log(L.green(`
468
+ Service uninstalled.`))}async function gu(){let o=rs(),e=It.homedir();console.log(L.cyan(`Service Registration Status
469
+ `)),o==="linux"?await mu(e):o==="macos"?await pu(e):console.log(L.gray(`Service management not supported on '${process.platform}'.`))}async function mu(o){let e=Nn(o),t=ke.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?L.green(e):L.gray("not found")}`),!t){console.log(L.gray(`
470
+ Service is not installed. Run: everclaw service install`));return}let n=he("systemctl --user is-enabled everclaw 2>/dev/null"),r=he("systemctl --user is-active everclaw 2>/dev/null");console.log(`Enabled: ${n.ok&&n.output==="enabled"?L.green("yes"):L.yellow(n.output||"unknown")}`),console.log(`Active: ${r.ok&&r.output==="active"?L.green("running"):r.ok?L.yellow(r.output):L.gray("unknown")}`);let s=he(`loginctl show-user ${It.userInfo().username} -p Linger`),i=s.ok&&s.output.includes("yes");console.log(`Linger: ${i?L.green("enabled"):L.yellow("disabled")} (survives logout)`),i||console.log(L.gray(` Run: loginctl enable-linger ${It.userInfo().username}`))}async function pu(o){let e=Dn(o),t=ke.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?L.green(e):L.gray("not found")}`),!t){console.log(L.gray(`
471
+ Service is not installed. Run: everclaw service install`));return}let n=he("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: ${L.green("running")} (PID ${r[1]})`);else if(s){let i=parseInt(s[1],10);console.log(`Status: ${i===0?L.green("exited cleanly"):L.yellow(`exited with code ${i}`)}`)}else console.log(`Status: ${L.green("loaded")}`)}else console.log(`Status: ${L.gray("not loaded")}`)}function ga(){let o=new nu("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
472
472
  Examples:
473
473
  everclaw service install Register and start the gateway as a system service
474
474
  everclaw service uninstall Remove the system service
475
475
  everclaw service status Show service registration status
476
476
 
477
- Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await Zd()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await nu()}),o.command("status").description("Show service registration status").action(async()=>{await su()}),o}de();import ke from"node:fs";import ns from"node:path";import{Command as cu}from"commander";import ut from"chalk";import Zt from"chalk";var lu={debug:Zt.gray,info:Zt.cyan,warn:Zt.yellow,error:Zt.red},oo=class{format(e){let t=Zt.dim(e.ts),n=this.formatLevel(e.level),r=Zt.bold(`[${e.category}]`),s=e.event,i=this.formatData(e.data);return`${t} ${n} ${r} ${s} ${i}`}formatJson(e){return JSON.stringify(e)}formatLevel(e){let t=lu[e];return t(e.toUpperCase().padEnd(5))}formatData(e){let t=[];for(let[n,r]of Object.entries(e))if(r!=null)if(typeof r=="string")r.length>80?t.push(`${n}="${r.slice(0,77)}\u2026"`):r.includes(" ")||r.includes('"')||r.includes("=")?t.push(`${n}="${r}"`):t.push(`${n}=${r}`);else if(typeof r=="number"||typeof r=="boolean")t.push(`${n}=${r}`);else if(r instanceof Error)t.push(`${n}="${r.message}"`);else try{let s=JSON.stringify(r);s.length>80?t.push(`${n}=${s.slice(0,77)}\u2026`):t.push(`${n}=${s}`)}catch{t.push(`${n}=[circular]`)}return t.join(" ")}};function ga(){let o=new cu("logs").description("View gateway logs").option("-f, --follow","Follow log output (tail -f style)").option("-l, --level <level>","Minimum log level (debug, info, warn, error)","info").option("-c, --category <category>","Filter by category prefix").option("-n, --lines <n>","Number of lines to show","100").option("--json","Output raw JSONL").option("--since <duration>","Show logs from last N minutes/hours (e.g., 30m, 2h)").addHelpText("after",`
477
+ Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await iu()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await cu()}),o.command("status").description("Show service registration status").action(async()=>{await gu()}),o}ce();import Ce from"node:fs";import os from"node:path";import{Command as hu}from"commander";import gt from"chalk";import en from"chalk";var fu={debug:en.gray,info:en.cyan,warn:en.yellow,error:en.red},so=class{format(e){let t=en.dim(e.ts),n=this.formatLevel(e.level),r=en.bold(`[${e.category}]`),s=e.event,i=this.formatData(e.data);return`${t} ${n} ${r} ${s} ${i}`}formatJson(e){return JSON.stringify(e)}formatLevel(e){let t=fu[e];return t(e.toUpperCase().padEnd(5))}formatData(e){let t=[];for(let[n,r]of Object.entries(e))if(r!=null)if(typeof r=="string")r.length>80?t.push(`${n}="${r.slice(0,77)}\u2026"`):r.includes(" ")||r.includes('"')||r.includes("=")?t.push(`${n}="${r}"`):t.push(`${n}=${r}`);else if(typeof r=="number"||typeof r=="boolean")t.push(`${n}=${r}`);else if(r instanceof Error)t.push(`${n}="${r.message}"`);else try{let s=JSON.stringify(r);s.length>80?t.push(`${n}=${s.slice(0,77)}\u2026`):t.push(`${n}=${s}`)}catch{t.push(`${n}=[circular]`)}return t.join(" ")}};function pa(){let o=new hu("logs").description("View gateway logs").option("-f, --follow","Follow log output (tail -f style)").option("-l, --level <level>","Minimum log level (debug, info, warn, error)","info").option("-c, --category <category>","Filter by category prefix").option("-n, --lines <n>","Number of lines to show","100").option("--json","Output raw JSONL").option("--since <duration>","Show logs from last N minutes/hours (e.g., 30m, 2h)").addHelpText("after",`
478
478
  Examples:
479
479
  everclaw logs Show last 100 log entries
480
480
  everclaw logs -f Follow logs in real-time
@@ -482,10 +482,10 @@ Examples:
482
482
  everclaw logs --category agent Show agent-related logs
483
483
  everclaw logs --since 30m Show logs from last 30 minutes
484
484
  everclaw logs --json Output raw JSONL format
485
- everclaw logs clear Clear all log files`);return o.command("clear").description("Clear all log files").action(()=>{let e=We();if(!ke.existsSync(e)){console.log(ut.gray("No logs directory found."));return}let t=ke.readdirSync(e).filter(r=>r.startsWith("gateway-")&&r.endsWith(".jsonl"));if(t.length===0){console.log(ut.gray("No log files to clear."));return}let n=0;for(let r of t)try{ke.unlinkSync(ns.join(e,r)),n++}catch(s){console.log(ut.red(`Failed to delete ${r}: ${s instanceof Error?s.message:String(s)}`))}console.log(ut.green(`Cleared ${n} log file(s).`))}),o.action(async e=>{let t=We(),n=du(e.level)||"info",r=e.category,s=e.since?uu(e.since):null,i=parseInt(e.lines,10),a=new oo;if(!ke.existsSync(t)){console.log(ut.gray("No logs directory found. Is the gateway running?"));return}let l=ke.readdirSync(t).filter(c=>c.startsWith("gateway-")&&c.endsWith(".jsonl")).sort();if(l.length===0){console.log(ut.gray("No log files found."));return}e.follow?await mu(t,l,n,r,s,e.json,a):await gu(t,l,n,r,s,i,e.json,a)}),o}function du(o){let e=o.toLowerCase();return e==="debug"||e==="info"||e==="warn"||e==="error"?e:null}function uu(o){let e=/^(\d+)(m|h)$/.exec(o);if(!e)return null;let t=parseInt(e[1],10),n=e[2];return n==="m"?t*60*1e3:n==="h"?t*60*60*1e3:null}async function gu(o,e,t,n,r,s,i,a){let l=r?Date.now()-r:null,c=[];for(let p of e){let g=ns.join(o,p),y=ke.readFileSync(g,"utf8").split(`
486
- `).filter(u=>u.trim());for(let u of y){let b;try{b=JSON.parse(u)}catch{continue}if(l){let T=new Date(b.ts).getTime();if(Number.isNaN(T)||T<l)continue}Pt[b.level]<Pt[t]||n&&!b.category.startsWith(n)||c.push(b)}}let d=c.slice(-s);for(let p of d)console.log(i?a.formatJson(p):a.format(p));d.length===0&&console.log(ut.gray("No matching log entries found."))}async function mu(o,e,t,n,r,s,i){let a=r?Date.now()-r:null,l=ua(o),c=0;ke.existsSync(l)&&(c=ke.statSync(l).size);let d=setInterval(()=>{try{let p=ua(o);if(p!==l&&(l=p,c=0),!ke.existsSync(l))return;let g=ke.statSync(l);if(g.size>c){let x=ke.openSync(l,"r"),y=Buffer.alloc(g.size-c);ke.readSync(x,y,0,y.length,c),ke.closeSync(x);let b=y.toString("utf8").split(`
487
- `).filter(T=>T.trim());for(let T of b){let v;try{v=JSON.parse(T)}catch{continue}if(a){let O=new Date(v.ts).getTime();if(Number.isNaN(O)||O<a)continue}Pt[v.level]<Pt[t]||n&&!v.category.startsWith(n)||console.log(s?i.formatJson(v):i.format(v))}c=g.size}}catch(p){console.error(ut.red(`Error watching logs: ${p instanceof Error?p.message:String(p)}`))}},500);process.on("SIGINT",()=>{clearInterval(d),process.exit(0)}),await new Promise(()=>{})}function ua(o){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return ns.join(o,`gateway-${t}-${n}-${r}-${s}.jsonl`)}var fu=hs(),hu="0.3.0";function es(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 ha(){if(process.env.DOCKER==="true"||ue.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(ue.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function yu(o){if(process.platform==="win32")return null;try{let{execSync:e}=Sa("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
488
- `);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 ya(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 ye({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=fu[n]??[o.agents.defaults.model],s=await ye({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 ye({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 ye({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=tn(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 ba(o){if((await ye({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await ye({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 ye({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 ye({type:"confirm",name:"enableGroups",message:"Enable Telegram group chat support?",initial:!0})).enableGroups){let i=await ye({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 ye({type:"confirm",name:"restrictGroups",message:"Restrict to specific group IDs?",initial:!1})).restrictGroups){let l=await ye({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 ye({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 wa(o){let e=new pu;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(hu,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
485
+ everclaw logs clear Clear all log files`);return o.command("clear").description("Clear all log files").action(()=>{let e=xe();if(!Ce.existsSync(e)){console.log(gt.gray("No logs directory found."));return}let t=Ce.readdirSync(e).filter(r=>r.startsWith("gateway-")&&r.endsWith(".jsonl"));if(t.length===0){console.log(gt.gray("No log files to clear."));return}let n=0;for(let r of t)try{Ce.unlinkSync(os.join(e,r)),n++}catch(s){console.log(gt.red(`Failed to delete ${r}: ${s instanceof Error?s.message:String(s)}`))}console.log(gt.green(`Cleared ${n} log file(s).`))}),o.action(async e=>{let t=xe(),n=yu(e.level)||"info",r=e.category,s=e.since?bu(e.since):null,i=parseInt(e.lines,10),a=new so;if(!Ce.existsSync(t)){console.log(gt.gray("No logs directory found. Is the gateway running?"));return}let l=Ce.readdirSync(t).filter(c=>c.startsWith("gateway-")&&c.endsWith(".jsonl")).sort();if(l.length===0){console.log(gt.gray("No log files found."));return}e.follow?await vu(t,l,n,r,s,e.json,a):await wu(t,l,n,r,s,i,e.json,a)}),o}function yu(o){let e=o.toLowerCase();return e==="debug"||e==="info"||e==="warn"||e==="error"?e:null}function bu(o){let e=/^(\d+)(m|h)$/.exec(o);if(!e)return null;let t=parseInt(e[1],10),n=e[2];return n==="m"?t*60*1e3:n==="h"?t*60*60*1e3:null}async function wu(o,e,t,n,r,s,i,a){let l=r?Date.now()-r:null,c=[];for(let p of e){let g=os.join(o,p),y=Ce.readFileSync(g,"utf8").split(`
486
+ `).filter(u=>u.trim());for(let u of y){let b;try{b=JSON.parse(u)}catch{continue}if(l){let T=new Date(b.ts).getTime();if(Number.isNaN(T)||T<l)continue}Mt[b.level]<Mt[t]||n&&!b.category.startsWith(n)||c.push(b)}}let d=c.slice(-s);for(let p of d)console.log(i?a.formatJson(p):a.format(p));d.length===0&&console.log(gt.gray("No matching log entries found."))}async function vu(o,e,t,n,r,s,i){let a=r?Date.now()-r:null,l=ma(o),c=0;Ce.existsSync(l)&&(c=Ce.statSync(l).size);let d=setInterval(()=>{try{let p=ma(o);if(p!==l&&(l=p,c=0),!Ce.existsSync(l))return;let g=Ce.statSync(l);if(g.size>c){let x=Ce.openSync(l,"r"),y=Buffer.alloc(g.size-c);Ce.readSync(x,y,0,y.length,c),Ce.closeSync(x);let b=y.toString("utf8").split(`
487
+ `).filter(T=>T.trim());for(let T of b){let v;try{v=JSON.parse(T)}catch{continue}if(a){let O=new Date(v.ts).getTime();if(Number.isNaN(O)||O<a)continue}Mt[v.level]<Mt[t]||n&&!v.category.startsWith(n)||console.log(s?i.formatJson(v):i.format(v))}c=g.size}}catch(p){console.error(gt.red(`Error watching logs: ${p instanceof Error?p.message:String(p)}`))}},500);process.on("SIGINT",()=>{clearInterval(d),process.exit(0)}),await new Promise(()=>{})}function ma(o){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return os.join(o,`gateway-${t}-${n}-${r}-${s}.jsonl`)}var ku=bs(),Cu="0.3.0";function ns(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 ba(){if(process.env.DOCKER==="true"||ue.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(ue.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function xu(o){if(process.platform==="win32")return null;try{let{execSync:e}=Ca("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
488
+ `);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 wa(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 ye({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=ku[n]??[o.agents.defaults.model],s=await ye({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 ye({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 ye({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=nn(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 va(o){if((await ye({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await ye({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 ye({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 ye({type:"confirm",name:"enableGroups",message:"Enable Telegram group chat support?",initial:!0})).enableGroups){let i=await ye({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 ye({type:"confirm",name:"restrictGroups",message:"Restrict to specific group IDs?",initial:!1})).restrictGroups){let l=await ye({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 ye({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 Sa(o){let e=new Su;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(Cu,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
489
489
  Examples:
490
490
  everclaw onboard Interactive setup wizard
491
491
  everclaw gateway Start the gateway server
@@ -493,42 +493,42 @@ Examples:
493
493
  everclaw doctor Check system health and connectivity
494
494
  everclaw status Show gateway status
495
495
 
496
- Documentation: https://docs.everclaw.ai`),e.addCommand(oa()),e.addCommand(aa()),e.addCommand(la()),e.addCommand(ia()),e.addCommand(da()),e.addCommand(ga()),o?.commands)for(let c of o.commands.values()){let d=e.command(c.contribution.name).description(c.contribution.description??"");c.contribution.builder&&c.contribution.builder(d),d.action(async p=>{await c.contribution.handler({},p)})}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 c=>{let d=yt(),p=ue.existsSync(d),g=_();if(p){console.log(`Config already exists at ${d}`);let y=ma.createInterface({input:pa,output:fa}),u=(await y.question("Overwrite? [y/N] ")).trim().toLowerCase();y.close(),u==="y"?(g=structuredClone(me),oe(g),console.log(`Config reset to defaults at ${d}`)):(oe(g),console.log(`Config refreshed at ${d} (existing values preserved)`))}else oe(g),console.log(`Created config at ${d}`);if(c.skipWorkspace)console.log(S.gray("Skipping workspace setup (--skip-workspace)."));else{let y=Z(g.agents.defaults.workspace);ue.existsSync(y)||(ue.mkdirSync(y,{recursive:!0}),console.log(`Created workspace at ${y}`)),ft(y)}if(c.provider||c.model||c.apiKey||c.apiBase||c.channel||c.channelToken||c.noChannel){if((c.provider??g.agents.defaults.provider)==="custom"&&c.apiKey&&c.apiBase){let u;try{u=new URL(c.apiBase).hostname.replace(/\./g,"-")}catch{u="custom-provider"}g.customLlmProviders.push({name:u,baseUrl:c.apiBase,apiKey:c.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),g.agents.defaults.provider=tn(u)}else{if(c.provider&&(g.agents.defaults.provider=c.provider),c.apiKey){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiKey=c.apiKey)}}if(c.apiBase){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiBase=c.apiBase)}}}if(c.model&&(g.agents.defaults.model=c.model),c.noChannel||(c.channel==="telegram"&&c.channelToken?(g.channels.telegram.enabled=!0,g.channels.telegram.token=c.channelToken):c.channel==="discord"&&c.channelToken&&(g.channels.discord.enabled=!0,g.channels.discord.token=c.channelToken)),oe(g),console.log(S.green(`
496
+ Documentation: https://docs.everclaw.ai`),e.addCommand(ia()),e.addCommand(ca()),e.addCommand(da()),e.addCommand(la()),e.addCommand(ga()),e.addCommand(pa()),o?.commands)for(let c of o.commands.values()){let d=e.command(c.contribution.name).description(c.contribution.description??"");c.contribution.builder&&c.contribution.builder(d),d.action(async p=>{await c.contribution.handler({},p)})}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 c=>{let d=bt(),p=ue.existsSync(d),g=_();if(p){console.log(`Config already exists at ${d}`);let y=fa.createInterface({input:ha,output:ya}),u=(await y.question("Overwrite? [y/N] ")).trim().toLowerCase();y.close(),u==="y"?(g=structuredClone(me),oe(g),console.log(`Config reset to defaults at ${d}`)):(oe(g),console.log(`Config refreshed at ${d} (existing values preserved)`))}else oe(g),console.log(`Created config at ${d}`);if(c.skipWorkspace)console.log(S.gray("Skipping workspace setup (--skip-workspace)."));else{let y=Z(g.agents.defaults.workspace);ue.existsSync(y)||(ue.mkdirSync(y,{recursive:!0}),console.log(`Created workspace at ${y}`)),ht(y)}if(c.provider||c.model||c.apiKey||c.apiBase||c.channel||c.channelToken||c.noChannel){if((c.provider??g.agents.defaults.provider)==="custom"&&c.apiKey&&c.apiBase){let u;try{u=new URL(c.apiBase).hostname.replace(/\./g,"-")}catch{u="custom-provider"}g.customLlmProviders.push({name:u,baseUrl:c.apiBase,apiKey:c.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),g.agents.defaults.provider=nn(u)}else{if(c.provider&&(g.agents.defaults.provider=c.provider),c.apiKey){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiKey=c.apiKey)}}if(c.apiBase){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiBase=c.apiBase)}}}if(c.model&&(g.agents.defaults.model=c.model),c.noChannel||(c.channel==="telegram"&&c.channelToken?(g.channels.telegram.enabled=!0,g.channels.telegram.token=c.channelToken):c.channel==="discord"&&c.channelToken&&(g.channels.discord.enabled=!0,g.channels.discord.token=c.channelToken)),oe(g),console.log(S.green(`
497
497
  Config created via non-interactive mode.`)),!c.noTest){console.log(S.cyan(`
498
- Running connectivity test...`));try{let b=await Ne(g).chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});(b.content||"").toLowerCase().includes("error")?console.log(S.red(`Connectivity test failed: ${b.content}`)):console.log(S.green(`Connectivity test passed: ${b.content??"(empty response)"}`))}catch(u){console.log(S.red(`Connectivity test failed: ${String(u)}`))}}console.log(S.yellow(`
498
+ Running connectivity test...`));try{let b=await je(g).chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});(b.content||"").toLowerCase().includes("error")?console.log(S.red(`Connectivity test failed: ${b.content}`)):console.log(S.green(`Connectivity test passed: ${b.content??"(empty response)"}`))}catch(u){console.log(S.red(`Connectivity test failed: ${String(u)}`))}}console.log(S.yellow(`
499
499
  Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){if(console.log(S.cyan(`
500
500
  everclaw Setup Wizard`)),console.log(S.gray(`Use arrow keys to pick options.
501
- `)),c.skipProvider)console.log(S.gray(`Skipping provider setup (--skip-provider). Current: ${g.agents.defaults.provider} / ${g.agents.defaults.model}`));else{let y=g.agents.defaults.provider,u=g.agents.defaults.model;y!=="auto"&&y!==me.agents.defaults.provider?(await ye({type:"confirm",name:"keep",message:`Keep current provider (${y}, model: ${u})?`,initial:!0})).keep?console.log(S.gray(`Keeping provider: ${y} / ${u}`)):await ya(g):await ya(g)}if(c.skipChannel||c.noChannel)console.log(S.gray("Skipping channel setup (--skip-channel)."));else{let y=g.channels.telegram.enabled&&g.channels.telegram.token,u=g.channels.discord.enabled&&g.channels.discord.token;if(y||u){let b=[];y&&b.push("telegram"),u&&b.push("discord"),(await ye({type:"confirm",name:"keep",message:`Keep current channel config (${b.join(", ")})?`,initial:!0})).keep?console.log(S.gray(`Keeping channel config: ${b.join(", ")}`)):await ba(g)}else await ba(g)}oe(g),console.log(S.green(`
501
+ `)),c.skipProvider)console.log(S.gray(`Skipping provider setup (--skip-provider). Current: ${g.agents.defaults.provider} / ${g.agents.defaults.model}`));else{let y=g.agents.defaults.provider,u=g.agents.defaults.model;y!=="auto"&&y!==me.agents.defaults.provider?(await ye({type:"confirm",name:"keep",message:`Keep current provider (${y}, model: ${u})?`,initial:!0})).keep?console.log(S.gray(`Keeping provider: ${y} / ${u}`)):await wa(g):await wa(g)}if(c.skipChannel||c.noChannel)console.log(S.gray("Skipping channel setup (--skip-channel)."));else{let y=g.channels.telegram.enabled&&g.channels.telegram.token,u=g.channels.discord.enabled&&g.channels.discord.token;if(y||u){let b=[];y&&b.push("telegram"),u&&b.push("discord"),(await ye({type:"confirm",name:"keep",message:`Keep current channel config (${b.join(", ")})?`,initial:!0})).keep?console.log(S.gray(`Keeping channel config: ${b.join(", ")}`)):await va(g)}else await va(g)}oe(g),console.log(S.green(`
502
502
  Configs created.`)),console.log(S.yellow("Run everclaw gateway")),console.log(S.yellow("or chat with agent: everclaw agent"));return}console.log(`
503
- everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${pt}, 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 c=yt();if(!ue.existsSync(c)){console.log(S.red(`No config file found at ${c}`)),console.log(S.gray("Run `everclaw onboard` to create one.")),process.exitCode=1;return}let d=_();oe(d),console.log(S.green(`Config compacted at ${c}`))}),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 rs("--channel <channel>").default("cli").hideHelp()).addOption(new rs("--chat-id <chatId>").default("direct").hideHelp()).addOption(new rs("--raw-output").default(!1).hideHelp()).action(async c=>{let d=_(),p=nn(d,process.env),g=Z(p.agents.defaults.workspace);ft(g,!0);let x=new wt,y;try{y=Ne(p)}catch(v){console.log(S.red(String(v))),process.exitCode=1;return}let u=new ot(g),{cron:b}=Ve({cron:{dataDir:Be()}}),T=new zt({bus:x,provider:y,workspace:g,model:p.agents.defaults.model,temperature:p.agents.defaults.temperature,maxTokens:p.agents.defaults.maxTokens,maxIterations:p.agents.defaults.maxToolIterations,memoryWindow:p.agents.defaults.memoryWindow,braveApiKey:p.tools.web.search.apiKey||null,execConfig:p.tools.exec,cronService:b,restrictToWorkspace:p.tools.restrictToWorkspace,channelsConfig:p.channels,loadConfig:_});if(c.message){let v=await T.processDirect(String(c.message),String(c.session),String(c.channel),String(c.chatId));c.rawOutput?process.stdout.write(v):console.log(`
503
+ everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${ft}, 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 c=bt();if(!ue.existsSync(c)){console.log(S.red(`No config file found at ${c}`)),console.log(S.gray("Run `everclaw onboard` to create one.")),process.exitCode=1;return}let d=_();oe(d),console.log(S.green(`Config compacted at ${c}`))}),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 ss("--channel <channel>").default("cli").hideHelp()).addOption(new ss("--chat-id <chatId>").default("direct").hideHelp()).addOption(new ss("--raw-output").default(!1).hideHelp()).action(async c=>{let d=_(),p=rn(d,process.env),g=Z(p.agents.defaults.workspace);ht(g,!0);let x=new vt,y;try{y=je(p)}catch(v){console.log(S.red(String(v))),process.exitCode=1;return}let u=new st(g),{cron:b}=Ye({cron:{dataDir:Ge()}}),T=new Vt({bus:x,provider:y,workspace:g,model:p.agents.defaults.model,temperature:p.agents.defaults.temperature,maxTokens:p.agents.defaults.maxTokens,maxIterations:p.agents.defaults.maxToolIterations,memoryWindow:p.agents.defaults.memoryWindow,braveApiKey:p.tools.web.search.apiKey||null,execConfig:p.tools.exec,cronService:b,restrictToWorkspace:p.tools.restrictToWorkspace,channelsConfig:p.channels,loadConfig:_});if(c.message){let v=await T.processDirect(String(c.message),String(c.session),String(c.channel),String(c.chatId));c.rawOutput?process.stdout.write(v):console.log(`
504
504
  everclaw
505
505
  ${v}
506
- `)}else{console.log("Interactive mode (type exit to quit)");let v=ma.createInterface({input:pa,output:fa});for(;;){let O=await v.question("You: "),G=O.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(G))break;let I=await T.processDirect(O,String(c.session));console.log(`
506
+ `)}else{console.log("Interactive mode (type exit to quit)");let v=fa.createInterface({input:ha,output:ya});for(;;){let O=await v.question("You: "),G=O.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(G))break;let I=await T.processDirect(O,String(c.session));console.log(`
507
507
  everclaw
508
508
  ${I}
509
509
  `)}v.close()}});let n=e.command("channels").description("Manage channels");n.addHelpText("after",`
510
510
  Examples:
511
- everclaw channels status Show channel configuration`),n.command("status").action(()=>{let c=_(),d=[["Telegram",c.channels.telegram.enabled?"yes":"no",c.channels.telegram.token?`token: ${c.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",c.channels.discord.enabled?"yes":"no",c.channels.discord.gatewayUrl]];for(let p of d){let g=p[0]??"",x=p[1]??"",y=p[2]??"";console.log(`${g.padEnd(12)} ${x.padEnd(3)} ${y}`)}}),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 c=_(),d=Z(c.agents.defaults.workspace),p=Kt(d);if(!p.length)return console.log("No automations found.");console.log(S.cyan(`
512
- Saved Automations:`));for(let g of p)console.log(`${S.bold(g.id)} | ${g.name} | ${g.stepCount||0} steps | ${g.enabled?S.green("enabled"):S.gray("disabled")}`),g.description&&console.log(S.gray(` ${g.description}`));console.log("")}),r.command("show <id>").action(c=>{let d=_(),p=Z(d.agents.defaults.workspace),g=Te(p,c);if(!g)return console.log(S.red(`Automation '${c}' not found.`));console.log(S.cyan(`
511
+ everclaw channels status Show channel configuration`),n.command("status").action(()=>{let c=_(),d=[["Telegram",c.channels.telegram.enabled?"yes":"no",c.channels.telegram.token?`token: ${c.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",c.channels.discord.enabled?"yes":"no",c.channels.discord.gatewayUrl]];for(let p of d){let g=p[0]??"",x=p[1]??"",y=p[2]??"";console.log(`${g.padEnd(12)} ${x.padEnd(3)} ${y}`)}}),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 c=_(),d=Z(c.agents.defaults.workspace),p=Jt(d);if(!p.length)return console.log("No automations found.");console.log(S.cyan(`
512
+ Saved Automations:`));for(let g of p)console.log(`${S.bold(g.id)} | ${g.name} | ${g.stepCount||0} steps | ${g.enabled?S.green("enabled"):S.gray("disabled")}`),g.description&&console.log(S.gray(` ${g.description}`));console.log("")}),r.command("show <id>").action(c=>{let d=_(),p=Z(d.agents.defaults.workspace),g=Ee(p,c);if(!g)return console.log(S.red(`Automation '${c}' not found.`));console.log(S.cyan(`
513
513
  Automation: ${g.name} (${g.id})`)),console.log(S.gray(g.description||"No description")),console.log(`
514
514
  Steps (${g.steps.length}):`);for(let x of g.steps)console.log(` ${x.order}. ${x.description} (${x.action})`);g.scriptContent&&(console.log(S.yellow(`
515
- Generated Script:`)),console.log(S.gray("----------------------------------------")),console.log(g.scriptContent),console.log(S.gray("----------------------------------------"))),console.log("")}),r.command("run <id>").action(async c=>{let d=_(),p=Z(d.agents.defaults.workspace),g=Te(p,c);if(!g)return console.log(S.red(`Automation '${c}' not found.`));let x;if(d.tools.chromeSession?.enabled&&(x=new xt(d.tools.chromeSession,p,!!d.tools.restrictToWorkspace)),!x)return console.log(S.red("No browser tool available. Enable chrome_session in config."));let y=new Ht(p,x,d.tools.chromeSession?.stealth);console.log(S.cyan(`Running automation: ${g.name}...`));let u=await y.execute({command:"run",id:c});console.log(u)}),r.command("remove").alias("delete").argument("<id>").action(c=>{let d=_(),p=Z(d.agents.defaults.workspace);Jt(p,c)?console.log(S.green(`Removed automation '${c}'`)):console.log(S.red(`Automation '${c}' not found.`))});let s=e.command("cron").description("Manage scheduled tasks");s.addHelpText("after",`
515
+ Generated Script:`)),console.log(S.gray("----------------------------------------")),console.log(g.scriptContent),console.log(S.gray("----------------------------------------"))),console.log("")}),r.command("run <id>").action(async c=>{let d=_(),p=Z(d.agents.defaults.workspace),g=Ee(p,c);if(!g)return console.log(S.red(`Automation '${c}' not found.`));let x;if(d.tools.chromeSession?.enabled&&(x=new Tt(d.tools.chromeSession,p,!!d.tools.restrictToWorkspace)),!x)return console.log(S.red("No browser tool available. Enable chrome_session in config."));let y=new qt(p,x,d.tools.chromeSession?.stealth);console.log(S.cyan(`Running automation: ${g.name}...`));let u=await y.execute({command:"run",id:c});console.log(u)}),r.command("remove").alias("delete").argument("<id>").action(c=>{let d=_(),p=Z(d.agents.defaults.workspace);Ht(p,c)?console.log(S.green(`Removed automation '${c}'`)):console.log(S.red(`Automation '${c}' not found.`))});let s=e.command("cron").description("Manage scheduled tasks");s.addHelpText("after",`
516
516
  Examples:
517
517
  everclaw cron list List all scheduled jobs
518
518
  everclaw cron add -n "daily" --cron "0 9 * * *" -m "Good morning!"
519
519
  everclaw cron add -n "reminder" --at "2024-12-25T09:00:00" -m "Merry Christmas!" -d --to "12345" --channel "telegram"
520
- everclaw cron run abc123 Run a job immediately`),s.command("list").option("-a, --all","Include disabled jobs",!1).action(c=>{let{cron:d}=Ve({cron:{dataDir:Be()}}),p=d.listJobs(!!c.all);if(!p.length)return console.log("No scheduled jobs.");for(let g of p){let x=g.schedule.kind==="every"?`every ${g.schedule.everyMs/1e3}s`:g.schedule.kind==="cron"?`${g.schedule.expr} (${g.schedule.tz??"local"})`:"one-time",y=g.state.nextRunAtMs?new Date(g.state.nextRunAtMs).toISOString():"";console.log(`${g.id} | ${g.name} | ${x} | ${g.enabled?"enabled":"disabled"} | ${y}`)}}),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(c=>{if(c.tz&&!c.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let d;if(c.every)d={kind:"every",everyMs:Number(c.every)*1e3};else if(c.cron){let g={kind:"cron",expr:String(c.cron)};c.tz&&(g.tz=String(c.tz)),d=g}else if(c.at){let g=new Date(String(c.at));if(Number.isNaN(g.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}d={kind:"at",atMs:g.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:p}=Ve({cron:{dataDir:Be()}});try{let g={name:String(c.name),schedule:d,message:String(c.message),deliver:!!c.deliver};c.to&&(g.to=String(c.to)),c.channel&&(g.channel=String(c.channel));let x=p.addJob(g);console.log(`Added job '${x.name}' (${x.id})`)}catch(g){console.log(`Error: ${String(g).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),s.command("remove").argument("<jobId>").action(c=>{let{cron:d}=Ve({cron:{dataDir:Be()}});d.removeJob(c)?console.log(`Removed job ${c}`):console.log(`Job ${c} not found`)}),s.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((c,d)=>{let{cron:p}=Ve({cron:{dataDir:Be()}}),g=p.enableJob(c,!d.disable);if(!g)return console.log(`Job ${c} not found`);console.log(`Job '${g.name}' ${d.disable?"disabled":"enabled"}`)}),s.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(c,d)=>{let p=_(),g=Z(p.agents.defaults.workspace),x;try{x=Ne(p)}catch(O){console.log(S.red(String(O))),process.exitCode=1;return}let y=new wt,u=jr(p.tools.exec.timeout),b=Cn({target:"scheduled-job",timeoutMs:u}),{cron:T}=Ve({cron:{dataDir:Be(),onJob:async(O,G)=>{let I=await b.run({payload:{message:O.payload.message,session:`cron:${O.id}`,channel:O.payload.channel??"cli",chatId:O.payload.to??"direct"},cwd:process.cwd(),signal:G?.signal});return v.push(I),I}}}),v=[];await T.runJob(c,!!d.force)?(console.log("Job executed"),v.length&&console.log(v[0])):(console.log(`Failed to run job ${c}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let d=!!e.opts().json,p=yt(),g=_(),x=Z(g.agents.defaults.workspace),y=g.gateway.port,u=null;try{let v=await fetch(`http://127.0.0.1:${y}/api/status`,{signal:AbortSignal.timeout(2e3)});v.ok&&(u=await v.json())}catch{}let T=await new _e().getStatus();if(d){let v={gateway:{running:!!u,port:u?u.gateway?.port??y:null},model:g.agents.defaults.model,provider:nt(g)??null,config:{path:p,exists:ue.existsSync(p)},workspace:{path:x,exists:ue.existsSync(x)},rtk:{installed:T.installed,version:T.version??null,binaryPath:T.binaryPath}};if(u){let O=u.runtime,G=u.channelStatus,I=Ie();v.gateway={running:!0,port:u.gateway?.port??y,pid:I?.pid??null,uptime:I?bt(I.startedAt):null},v.agent={acceptingWork:O?.acceptingWork??!0,activeSessions:O?.activeSessions??0,queuedMessages:O?.queuedMessages??0,subagents:O?.subagents??0},v.channels=G??{}}console.log(JSON.stringify(v,null,2));return}if(console.log(S.cyan(`everclaw Status
521
- `)),u){let v=u.runtime,O=u.gateway,G=u.channelStatus,I=Ie(),V=I?bt(I.startedAt):"unknown";console.log(`Gateway: ${S.green("running")} (port ${O?.port??y}, uptime ${V})`),console.log(`Agent: ${v?.acceptingWork?S.green("idle (accepting work)"):S.yellow("busy")}`),console.log(` Active sessions: ${v?.activeSessions??0}`),console.log(` Queued messages: ${v?.queuedMessages??0}`),console.log(` Subagents: ${v?.subagents??0}`);let N=v?.overload;if(N&&typeof N.rateLimited=="number"&&N.rateLimited>0&&console.log(` Rate limited: ${S.yellow(String(N.rateLimited))} (window: ${N.rateLimitWindowMs??0}ms)`),G&&Object.keys(G).length>0){console.log(`
520
+ everclaw cron run abc123 Run a job immediately`),s.command("list").option("-a, --all","Include disabled jobs",!1).action(c=>{let{cron:d}=Ye({cron:{dataDir:Ge()}}),p=d.listJobs(!!c.all);if(!p.length)return console.log("No scheduled jobs.");for(let g of p){let x=g.schedule.kind==="every"?`every ${g.schedule.everyMs/1e3}s`:g.schedule.kind==="cron"?`${g.schedule.expr} (${g.schedule.tz??"local"})`:"one-time",y=g.state.nextRunAtMs?new Date(g.state.nextRunAtMs).toISOString():"";console.log(`${g.id} | ${g.name} | ${x} | ${g.enabled?"enabled":"disabled"} | ${y}`)}}),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(c=>{if(c.tz&&!c.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let d;if(c.every)d={kind:"every",everyMs:Number(c.every)*1e3};else if(c.cron){let g={kind:"cron",expr:String(c.cron)};c.tz&&(g.tz=String(c.tz)),d=g}else if(c.at){let g=new Date(String(c.at));if(Number.isNaN(g.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}d={kind:"at",atMs:g.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:p}=Ye({cron:{dataDir:Ge()}});try{let g={name:String(c.name),schedule:d,message:String(c.message),deliver:!!c.deliver};c.to&&(g.to=String(c.to)),c.channel&&(g.channel=String(c.channel));let x=p.addJob(g);console.log(`Added job '${x.name}' (${x.id})`)}catch(g){console.log(`Error: ${String(g).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),s.command("remove").argument("<jobId>").action(c=>{let{cron:d}=Ye({cron:{dataDir:Ge()}});d.removeJob(c)?console.log(`Removed job ${c}`):console.log(`Job ${c} not found`)}),s.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((c,d)=>{let{cron:p}=Ye({cron:{dataDir:Ge()}}),g=p.enableJob(c,!d.disable);if(!g)return console.log(`Job ${c} not found`);console.log(`Job '${g.name}' ${d.disable?"disabled":"enabled"}`)}),s.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(c,d)=>{let p=_(),g=Z(p.agents.defaults.workspace),x;try{x=je(p)}catch(O){console.log(S.red(String(O))),process.exitCode=1;return}let y=new vt,u=Fr(p.tools.exec.timeout),b=xn({target:"scheduled-job",timeoutMs:u}),{cron:T}=Ye({cron:{dataDir:Ge(),onJob:async(O,G)=>{let I=await b.run({payload:{message:O.payload.message,session:`cron:${O.id}`,channel:O.payload.channel??"cli",chatId:O.payload.to??"direct"},cwd:process.cwd(),signal:G?.signal});return v.push(I),I}}}),v=[];await T.runJob(c,!!d.force)?(console.log("Job executed"),v.length&&console.log(v[0])):(console.log(`Failed to run job ${c}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let d=!!e.opts().json,p=bt(),g=_(),x=Z(g.agents.defaults.workspace),y=g.gateway.port,u=null;try{let v=await fetch(`http://127.0.0.1:${y}/api/status`,{signal:AbortSignal.timeout(2e3)});v.ok&&(u=await v.json())}catch{}let T=await new Ie().getStatus();if(d){let v={gateway:{running:!!u,port:u?u.gateway?.port??y:null},model:g.agents.defaults.model,provider:rt(g)??null,config:{path:p,exists:ue.existsSync(p)},workspace:{path:x,exists:ue.existsSync(x)},rtk:{installed:T.installed,version:T.version??null,binaryPath:T.binaryPath}};if(u){let O=u.runtime,G=u.channelStatus,I=Oe();v.gateway={running:!0,port:u.gateway?.port??y,pid:I?.pid??null,uptime:I?wt(I.startedAt):null},v.agent={acceptingWork:O?.acceptingWork??!0,activeSessions:O?.activeSessions??0,queuedMessages:O?.queuedMessages??0,subagents:O?.subagents??0},v.channels=G??{}}console.log(JSON.stringify(v,null,2));return}if(console.log(S.cyan(`everclaw Status
521
+ `)),u){let v=u.runtime,O=u.gateway,G=u.channelStatus,I=Oe(),V=I?wt(I.startedAt):"unknown";console.log(`Gateway: ${S.green("running")} (port ${O?.port??y}, uptime ${V})`),console.log(`Agent: ${v?.acceptingWork?S.green("idle (accepting work)"):S.yellow("busy")}`),console.log(` Active sessions: ${v?.activeSessions??0}`),console.log(` Queued messages: ${v?.queuedMessages??0}`),console.log(` Subagents: ${v?.subagents??0}`);let N=v?.overload;if(N&&typeof N.rateLimited=="number"&&N.rateLimited>0&&console.log(` Rate limited: ${S.yellow(String(N.rateLimited))} (window: ${N.rateLimitWindowMs??0}ms)`),G&&Object.keys(G).length>0){console.log(`
522
522
  Channels:`);for(let[D,Y]of Object.entries(G)){let J=Y?.running?S.green("connected"):S.gray("disconnected");console.log(` ${D.padEnd(12)} ${J}`)}}}else console.log(`Gateway: ${S.gray("not running")}`);console.log(`
523
- Model: ${g.agents.defaults.model}`),console.log(`Provider: ${nt(g)??"none"}`),console.log(`Config: ${p} ${ue.existsSync(p)?"yes":"no"}`),console.log(`Workspace: ${x} ${ue.existsSync(x)?"yes":"no"}`),console.log(`
524
- RTK Token Compression:`),T.installed&&T.version?(console.log(` Status: ${S.green("Available")} (v${T.version})`),console.log(` Binary: ${T.binaryPath}`)):T.installed?(console.log(` Status: ${S.yellow("Installed but broken")}`),console.log(` Binary: ${T.binaryPath}`),console.log(S.gray(` Run ${S.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${S.gray("Not installed")}`),g.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 d=!!e.opts().json,p=_(),g=nn(p,process.env),x=nt(g),y=[],u={ok:!0,warnings:[]},b=Ie(),T=b&&Me(b.pid);u.system={gateway:T?{running:!0,pid:b.pid,port:b.port,uptime:bt(b.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:ha()??"standalone"},d||(console.log(S.cyan(`everclaw doctor
525
- `)),console.log(S.bold("System:")),console.log(T?` Gateway: ${S.green("running")} (PID ${b.pid}, port ${b.port}, uptime ${bt(b.startedAt)})`:` Gateway: ${S.gray("not running")}`));let v=process.versions.node,O=parseInt(v.split(".")[0]??"0",10);O<20&&y.push("Node.js version below 20 may have compatibility issues");let G=process.getuid?.()===0;if(G&&y.push("Running as root is not recommended for security"),!d){O>=20?console.log(` Node.js: ${S.green(v)}`):console.log(` Node.js: ${S.yellow(v)} (recommend v20+)`),console.log(G?` Running as: ${S.red("root")} (not recommended)`:` Running as: ${S.green("non-root")}`);let m=ha();console.log(m?` Supervisor: ${S.green(m)}`:` Supervisor: ${S.gray("standalone")}`)}let I=yt();if(ue.existsSync(I))try{let C=!!(ue.statSync(I).mode&511&7);u.system.configPermissions={ok:!C,path:I},C&&y.push("Config file is world-readable \u2014 contains API keys"),d||console.log(C?` Config: ${S.yellow("world-readable")} (${I})`:` Config: ${S.green("ok")} (${I})`)}catch{d||console.log(` Config: ${S.gray("unable to check")}`)}try{let m=Be();ue.statSync(m);let k=yu(m);if(k!==null){let C=Math.round(k/1048576);u.system.diskSpace={freeMB:C,path:m,ok:k>=100*1024*1024},k<100*1024*1024&&y.push(`Low disk space: ${C}MB free in ${m}`),d||(k<100*1024*1024?console.log(` Disk space: ${S.yellow(`${C}MB free`)} (${m})`):console.log(` Disk space: ${S.green(`${C}MB free`)} (${m})`))}}catch{}let V=Z(g.agents.defaults.workspace);if(ue.existsSync(V))try{let C=!!(ue.statSync(V).mode&511&2);u.system.workspace={ok:!C,path:V},C&&y.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),d||console.log(C?` Workspace: ${S.yellow("world-writable")} (${V})`:` Workspace: ${S.green("ok")} (${V})`)}catch{d||console.log(` Workspace: ${S.gray("unable to check")}`)}else u.system.workspace={ok:!0,path:V,created:!1},d||console.log(` Workspace: ${S.gray("not created")} (${V})`);let N=g.security;if(u.security={enabled:N.enabled,auth:N.auth.enabled,toolGuard:N.toolGuard.enabled,skillScanner:N.skillScanner.enabled,inputSanitizer:N.inputSanitizer.enabled,pathBoundary:g.tools.restrictToWorkspace},d)N.toolGuard.enabled&&N.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),N.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!N.auth.enabled&&g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");else{if(console.log(S.bold(`
526
- Security:`)),console.log(` Master switch: ${N.enabled?S.green("enabled"):S.gray("disabled")}`),N.auth.enabled){let m=N.auth.sessionTtlS?`${Math.floor(N.auth.sessionTtlS/60)}min`:"default",k=N.auth.idleTimeoutS?`${Math.floor(N.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${S.green("enabled")} (PIN, session TTL: ${m}, idle lock: ${k})`)}else console.log(` Authentication: ${S.gray("disabled")}`),g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${N.toolGuard.enabled?S.green("enabled"):S.gray("disabled")}`),N.toolGuard.enabled&&N.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${N.skillScanner.enabled?S.green("enabled"):S.gray("disabled")}`),N.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${N.inputSanitizer.enabled?S.green("enabled"):S.gray("disabled")}`),console.log(` Path Boundary: ${g.tools.restrictToWorkspace?S.green("workspace-restricted"):S.yellow("unrestricted")}`),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let D=Ss(g);for(let m of D)y.includes(m)||y.push(m);u.provider={name:x??null,model:g.agents.defaults.model},d||(console.log(S.bold(`
527
- Provider:`)),console.log(` Resolved: ${x??"none"}`),console.log(` Model: ${g.agents.defaults.model}`));let j=await new _e().getStatus();u.rtk={installed:j.installed,version:j.version??null,binaryPath:j.binaryPath},j.installed&&j.version&&!_t(j.version,Ee)&&y.push(`RTK version ${j.version} is below minimum ${Ee}`),d||(console.log(S.bold(`
528
- RTK Token Compression:`)),j.installed&&j.version?_t(j.version,Ee)?console.log(` Status: ${S.green("Available")} (v${j.version})`):console.log(` Status: ${S.yellow("Outdated")} (v${j.version}, min: ${Ee})`):console.log(` Status: ${S.gray("Not installed")}`));let J=Object.keys(g.tools.mcpServers);if(J.length>0){let m={};d||console.log(S.bold(`
529
- MCP Servers:`));for(let k of J)try{let{McpClientManager:C}=await Promise.resolve().then(()=>(wn(),Lr)),A=new C;A.updateConfig(g.tools.mcpServers);let R=await A.getServerTools(k);await A.closeAll(),m[k]={connected:!0,tools:R.length},d||console.log(` ${k.padEnd(20)} ${S.green("\u2713 connected")} (${R.length} tools)`)}catch(C){let A=C instanceof Error?C.message:String(C);m[k]={connected:!1,error:A},d||console.log(` ${k.padEnd(20)} ${S.red("\u2717 "+A)}`)}u.mcp=m}let U={};if(g.channels.telegram.enabled){let m=g.channels.telegram.token,k=m?/^\d+:[A-Za-z0-9_-]{30,}$/.test(m):!1;U.telegram={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Telegram token format does not match expected pattern"):y.push("Telegram channel enabled but no token configured")}if(g.channels.discord.enabled){let m=g.channels.discord.token,k=m?m.length>=50&&/^[A-Za-z0-9._-]+$/.test(m):!1;U.discord={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Discord token format does not match expected pattern"):y.push("Discord channel enabled but no token configured")}if(Object.keys(U).length>0&&(u.channels=U,!d)){if(console.log(S.bold(`
523
+ Model: ${g.agents.defaults.model}`),console.log(`Provider: ${rt(g)??"none"}`),console.log(`Config: ${p} ${ue.existsSync(p)?"yes":"no"}`),console.log(`Workspace: ${x} ${ue.existsSync(x)?"yes":"no"}`),console.log(`
524
+ RTK Token Compression:`),T.installed&&T.version?(console.log(` Status: ${S.green("Available")} (v${T.version})`),console.log(` Binary: ${T.binaryPath}`)):T.installed?(console.log(` Status: ${S.yellow("Installed but broken")}`),console.log(` Binary: ${T.binaryPath}`),console.log(S.gray(` Run ${S.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${S.gray("Not installed")}`),g.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 d=!!e.opts().json,p=_(),g=rn(p,process.env),x=rt(g),y=[],u={ok:!0,warnings:[]},b=Oe(),T=b&&$e(b.pid);u.system={gateway:T?{running:!0,pid:b.pid,port:b.port,uptime:wt(b.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:ba()??"standalone"},d||(console.log(S.cyan(`everclaw doctor
525
+ `)),console.log(S.bold("System:")),console.log(T?` Gateway: ${S.green("running")} (PID ${b.pid}, port ${b.port}, uptime ${wt(b.startedAt)})`:` Gateway: ${S.gray("not running")}`));let v=process.versions.node,O=parseInt(v.split(".")[0]??"0",10);O<20&&y.push("Node.js version below 20 may have compatibility issues");let G=process.getuid?.()===0;if(G&&y.push("Running as root is not recommended for security"),!d){O>=20?console.log(` Node.js: ${S.green(v)}`):console.log(` Node.js: ${S.yellow(v)} (recommend v20+)`),console.log(G?` Running as: ${S.red("root")} (not recommended)`:` Running as: ${S.green("non-root")}`);let m=ba();console.log(m?` Supervisor: ${S.green(m)}`:` Supervisor: ${S.gray("standalone")}`)}let I=bt();if(ue.existsSync(I))try{let C=!!(ue.statSync(I).mode&511&7);u.system.configPermissions={ok:!C,path:I},C&&y.push("Config file is world-readable \u2014 contains API keys"),d||console.log(C?` Config: ${S.yellow("world-readable")} (${I})`:` Config: ${S.green("ok")} (${I})`)}catch{d||console.log(` Config: ${S.gray("unable to check")}`)}try{let m=Ge();ue.statSync(m);let k=xu(m);if(k!==null){let C=Math.round(k/1048576);u.system.diskSpace={freeMB:C,path:m,ok:k>=100*1024*1024},k<100*1024*1024&&y.push(`Low disk space: ${C}MB free in ${m}`),d||(k<100*1024*1024?console.log(` Disk space: ${S.yellow(`${C}MB free`)} (${m})`):console.log(` Disk space: ${S.green(`${C}MB free`)} (${m})`))}}catch{}let V=Z(g.agents.defaults.workspace);if(ue.existsSync(V))try{let C=!!(ue.statSync(V).mode&511&2);u.system.workspace={ok:!C,path:V},C&&y.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),d||console.log(C?` Workspace: ${S.yellow("world-writable")} (${V})`:` Workspace: ${S.green("ok")} (${V})`)}catch{d||console.log(` Workspace: ${S.gray("unable to check")}`)}else u.system.workspace={ok:!0,path:V,created:!1},d||console.log(` Workspace: ${S.gray("not created")} (${V})`);let N=g.security;if(u.security={enabled:N.enabled,auth:N.auth.enabled,toolGuard:N.toolGuard.enabled,skillScanner:N.skillScanner.enabled,inputSanitizer:N.inputSanitizer.enabled,pathBoundary:g.tools.restrictToWorkspace},d)N.toolGuard.enabled&&N.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),N.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!N.auth.enabled&&g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");else{if(console.log(S.bold(`
526
+ Security:`)),console.log(` Master switch: ${N.enabled?S.green("enabled"):S.gray("disabled")}`),N.auth.enabled){let m=N.auth.sessionTtlS?`${Math.floor(N.auth.sessionTtlS/60)}min`:"default",k=N.auth.idleTimeoutS?`${Math.floor(N.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${S.green("enabled")} (PIN, session TTL: ${m}, idle lock: ${k})`)}else console.log(` Authentication: ${S.gray("disabled")}`),g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${N.toolGuard.enabled?S.green("enabled"):S.gray("disabled")}`),N.toolGuard.enabled&&N.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${N.skillScanner.enabled?S.green("enabled"):S.gray("disabled")}`),N.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${N.inputSanitizer.enabled?S.green("enabled"):S.gray("disabled")}`),console.log(` Path Boundary: ${g.tools.restrictToWorkspace?S.green("workspace-restricted"):S.yellow("unrestricted")}`),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let D=Cs(g);for(let m of D)y.includes(m)||y.push(m);u.provider={name:x??null,model:g.agents.defaults.model},d||(console.log(S.bold(`
527
+ Provider:`)),console.log(` Resolved: ${x??"none"}`),console.log(` Model: ${g.agents.defaults.model}`));let j=await new Ie().getStatus();u.rtk={installed:j.installed,version:j.version??null,binaryPath:j.binaryPath},j.installed&&j.version&&!Pt(j.version,Me)&&y.push(`RTK version ${j.version} is below minimum ${Me}`),d||(console.log(S.bold(`
528
+ RTK Token Compression:`)),j.installed&&j.version?Pt(j.version,Me)?console.log(` Status: ${S.green("Available")} (v${j.version})`):console.log(` Status: ${S.yellow("Outdated")} (v${j.version}, min: ${Me})`):console.log(` Status: ${S.gray("Not installed")}`));let J=Object.keys(g.tools.mcpServers);if(J.length>0){let m={};d||console.log(S.bold(`
529
+ MCP Servers:`));for(let k of J)try{let{McpClientManager:C}=await Promise.resolve().then(()=>(vn(),Or)),A=new C;A.updateConfig(g.tools.mcpServers);let R=await A.getServerTools(k);await A.closeAll(),m[k]={connected:!0,tools:R.length},d||console.log(` ${k.padEnd(20)} ${S.green("\u2713 connected")} (${R.length} tools)`)}catch(C){let A=C instanceof Error?C.message:String(C);m[k]={connected:!1,error:A},d||console.log(` ${k.padEnd(20)} ${S.red("\u2717 "+A)}`)}u.mcp=m}let U={};if(g.channels.telegram.enabled){let m=g.channels.telegram.token,k=m?/^\d+:[A-Za-z0-9_-]{30,}$/.test(m):!1;U.telegram={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Telegram token format does not match expected pattern"):y.push("Telegram channel enabled but no token configured")}if(g.channels.discord.enabled){let m=g.channels.discord.token,k=m?m.length>=50&&/^[A-Za-z0-9._-]+$/.test(m):!1;U.discord={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Discord token format does not match expected pattern"):y.push("Discord channel enabled but no token configured")}if(Object.keys(U).length>0&&(u.channels=U,!d)){if(console.log(S.bold(`
530
530
  Channel Tokens:`)),g.channels.telegram.enabled){let m=g.channels.telegram.token;m&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(m)?console.log(` Telegram: ${S.green("valid format")}`):console.log(m?` Telegram: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${S.red("not configured")}`)}if(g.channels.discord.enabled){let m=g.channels.discord.token;m&&m.length>=50&&/^[A-Za-z0-9._-]+$/.test(m)?console.log(` Discord: ${S.green("valid format")}`):console.log(m?` Discord: ${S.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${S.red("not configured")}`)}}d||console.log(S.bold(`
531
- LLM Connectivity:`));let L;try{L=Ne(g)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed to create provider: "+String(m))}`),process.exitCode=H.GENERAL_ERROR;return}try{let m=await L.chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});if((m.content||"").toLowerCase().includes("error")){u.llm={connected:!1,error:m.content},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed: "+m.content)}`),process.exitCode=H.CONNECTIVITY_ERROR;return}u.llm={connected:!0},d||console.log(` ${S.green("Passed")}: ${m.content??"(empty response)"}`)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed: "+String(m))}`),process.exitCode=H.CONNECTIVITY_ERROR;return}u.warnings=y;let K=g.compaction||{},B=K.enabled!==!1,h=g.tools?.chromeSession?.stealth?.enabled??!1;if(u.compaction={enabled:B,...B?{microCompactThresholdRatio:K.microCompactThresholdRatio??.6,autoCompactThresholdRatio:K.autoCompactThresholdRatio??.8,keepRecentMessages:K.keepRecentMessages??10}:{}},u.stealth={enabled:h,chromeEnabled:g.tools?.chromeSession?.enabled??!1},d||(console.log(S.bold(`
531
+ LLM Connectivity:`));let $;try{$=je(g)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed to create provider: "+String(m))}`),process.exitCode=H.GENERAL_ERROR;return}try{let m=await $.chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});if((m.content||"").toLowerCase().includes("error")){u.llm={connected:!1,error:m.content},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed: "+m.content)}`),process.exitCode=H.CONNECTIVITY_ERROR;return}u.llm={connected:!0},d||console.log(` ${S.green("Passed")}: ${m.content??"(empty response)"}`)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${S.red("Failed: "+String(m))}`),process.exitCode=H.CONNECTIVITY_ERROR;return}u.warnings=y;let K=g.compaction||{},B=K.enabled!==!1,h=g.tools?.chromeSession?.stealth?.enabled??!1;if(u.compaction={enabled:B,...B?{microCompactThresholdRatio:K.microCompactThresholdRatio??.6,autoCompactThresholdRatio:K.autoCompactThresholdRatio??.8,keepRecentMessages:K.keepRecentMessages??10}:{}},u.stealth={enabled:h,chromeEnabled:g.tools?.chromeSession?.enabled??!1},d||(console.log(S.bold(`
532
532
  Compaction:`)),console.log(` Status: ${B?S.green("enabled"):S.gray("disabled")}`),B&&(console.log(` Micro: ${((K.microCompactThresholdRatio??.6)*100).toFixed(0)}% threshold`),console.log(` Auto: ${((K.autoCompactThresholdRatio??.8)*100).toFixed(0)}% threshold`),console.log(` Keep: ${K.keepRecentMessages??10} messages`)),console.log(S.bold(`
533
533
  Stealth:`)),console.log(` Status: ${h?S.green("enabled"):S.gray("disabled")}`),g.tools?.chromeSession?.enabled?console.log(` Chrome: ${S.green("enabled")}`):console.log(` Chrome: ${S.gray("disabled")}`)),d){console.log(JSON.stringify(u,null,2));return}if(y.length>0){console.log(S.bold(`
534
534
  Warnings:`));for(let m of y)console.log(` ${S.yellow("\u26A0")} ${m}`)}console.log(S.green(`
@@ -536,4 +536,4 @@ Doctor check complete.`))}),e.command("provider").description("Manage providers"
536
536
  `)),console.log("ID".padEnd(12)+"Type".padEnd(12)+"Status".padEnd(12)+"Label".padEnd(40)+"Duration"),console.log("-".repeat(88));for(let v of T){let O=String(v.id||"").slice(0,10).padEnd(12),G=String(v.type||"unknown").padEnd(12),I=String(v.status||"pending"),V=String(v.label||"Untitled").slice(0,38).padEnd(40),N=v.startedAt?new Date(v.startedAt):null,D=N?`${Math.floor((Date.now()-N.getTime())/1e3)}s`:"-",Y=I==="running"?S.blue(I.padEnd(12)):I==="completed"?S.green(I.padEnd(12)):I==="failed"?S.red(I.padEnd(12)):I==="killed"?S.gray(I.padEnd(12)):I.padEnd(12);console.log(`${O}${G}${Y}${V}${D}`)}});let a=e.command("compact").description("Context compaction telemetry and configuration");a.command("status").description("Show compaction stats from the running gateway").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,x=_().gateway.port,y=null;try{let v=await fetch(`http://127.0.0.1:${x}/api/status`,{signal:AbortSignal.timeout(2e3)});v.ok&&(y=await v.json())}catch{console.log(S.gray("Gateway not running. Use `everclaw gateway start` to start the gateway.")),process.exitCode=H.GENERAL_ERROR;return}let b=y?.runtime?.compaction;if(p){console.log(JSON.stringify(b||{},null,2));return}if(!b){console.log(S.gray("Compaction stats not available."));return}console.log(S.cyan(`Context Compaction
537
537
  `)),console.log(` Status: ${b.enabled?S.green("enabled"):S.gray("disabled")}`),console.log(` Micro compactions: ${b.microCompactions??0}`),console.log(` Auto compactions: ${b.autoCompactions??0}`),console.log(` Reactive compactions: ${b.reactiveCompactions??0}`);let T=b.tokensFreed;console.log(` Tokens freed: ${T?T>=1e3?`${(T/1e3).toFixed(1)}K`:T:0}`),b.circuitBreakerTripped&&console.log(` Circuit breaker: ${S.red("tripped")} (compaction paused)`)}),a.command("config").description("Show compaction configuration").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,x=_().compaction||{};if(p){console.log(JSON.stringify(x,null,2));return}console.log(S.cyan(`Compaction Configuration
538
538
  `)),console.log(` Enabled: ${x.enabled!==!1?S.green("yes"):S.gray("no")}`),console.log(` Micro-compact threshold: ${((x.microCompactThresholdRatio??.6)*100).toFixed(0)}%`),console.log(` Auto-compact threshold: ${((x.autoCompactThresholdRatio??.8)*100).toFixed(0)}%`),console.log(` Keep recent messages: ${x.keepRecentMessages??10}`),console.log(` Max consecutive failures: ${x.maxConsecutiveFailures??3}`)});let l=e.command("stealth").description("Stealth mode configuration for Chrome automation");return l.command("status").description("Show stealth mode configuration").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,g=_(),x=g.tools?.chromeSession?.stealth??{enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]};if(p){console.log(JSON.stringify(x,null,2));return}if(console.log(S.cyan(`Stealth Mode Configuration
539
- `)),console.log(` Status: ${x.enabled?S.green("enabled"):S.gray("disabled")}`),g.tools?.chromeSession?.enabled?console.log(` Chrome Session: ${S.green("enabled")}`):console.log(` Chrome Session: ${S.gray("disabled")}`),x.enabled){console.log(` Cursor movement: ${x.cursorMovement!==!1?S.green("yes"):S.gray("no")}`),console.log(` Humanized typing: ${x.humanizedTyping!==!1?S.green("yes"):S.gray("no")}`);let y=x.interStepDelay||[300,1500];console.log(` Inter-step delay: ${y[0]}\u2013${y[1]} ms`)}}),l.command("enable").description("Enable stealth mode").action(async()=>{let c=_();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!0,oe(c),console.log(S.green("Stealth mode enabled. Restart gateway for changes to take effect."))}),l.command("disable").description("Disable stealth mode").action(async()=>{let c=_();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!1,oe(c),console.log(S.gray("Stealth mode disabled. Restart gateway for changes to take effect."))}),e}ps(process.argv);var bu=wa();bu.parseAsync(process.argv);
539
+ `)),console.log(` Status: ${x.enabled?S.green("enabled"):S.gray("disabled")}`),g.tools?.chromeSession?.enabled?console.log(` Chrome Session: ${S.green("enabled")}`):console.log(` Chrome Session: ${S.gray("disabled")}`),x.enabled){console.log(` Cursor movement: ${x.cursorMovement!==!1?S.green("yes"):S.gray("no")}`),console.log(` Humanized typing: ${x.humanizedTyping!==!1?S.green("yes"):S.gray("no")}`);let y=x.interStepDelay||[300,1500];console.log(` Inter-step delay: ${y[0]}\u2013${y[1]} ms`)}}),l.command("enable").description("Enable stealth mode").action(async()=>{let c=_();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!0,oe(c),console.log(S.green("Stealth mode enabled. Restart gateway for changes to take effect."))}),l.command("disable").description("Disable stealth mode").action(async()=>{let c=_();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!1,oe(c),console.log(S.gray("Stealth mode disabled. Restart gateway for changes to take effect."))}),e}hs(process.argv);var Tu=Sa();Tu.parseAsync(process.argv);