everclaw 0.3.0 → 0.3.2

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,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var ws=Object.defineProperty;var Be=(o,e)=>()=>(o&&(e=o(o=0)),e);var Ss=(o,e)=>{for(var t in e)ws(o,t,{get:e[t],enumerable:!0})};import jr from"node:fs";import ar from"node:os";import Ie from"node:path";import{fileURLToPath as ks}from"node:url";function Wt(o=ar.homedir()){return Ie.join(o,Gt)}function Fr(o=ar.homedir()){return Ie.join(o,Gt,"workspace")}function Ur(o=ar.homedir()){return Ie.join(o,Gt,"config.json")}function xs(){let o=ks(import.meta.url),e=Ie.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:Ie.resolve(e,"..")}function Wr(...o){let e=Ie.resolve(Gr,...o);if(!jr.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function _e(...o){let e=Ie.resolve(Gr,...o);return jr.existsSync(e)?e:null}var Gt,Fe,Br,Gr,se=Be(()=>{"use strict";Gt=".everclaw",Fe="~/.everclaw/config.json",Br=Ie.join("~",Gt,"workspace");Gr=xs()});import Jt from"node:fs";import xe from"node:path";import lr from"node:os";function Me(o){return Jt.mkdirSync(o,{recursive:!0}),o}function Kt(){return Me(Wt(lr.homedir()))}function Y(o){let e=o?o.replace(/^~(?=$|[\\/])/,lr.homedir()):Fr(lr.homedir());return Me(xe.resolve(e))}function Jr(o){return o.replace(Cs,"_").trim()}function Ue(o,e=!1){let t=_e("templates");if(!t)return[];let n=[],r=(i,a)=>{Jt.existsSync(a)||(Me(xe.dirname(a)),i?Jt.copyFileSync(i,a):Jt.writeFileSync(a,"","utf8"),n.push(xe.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(xe.join(t,i),xe.join(o,i));if(r(xe.join(t,"memory","MEMORY.md"),xe.join(o,"memory","MEMORY.md")),r(null,xe.join(o,"memory","HISTORY.md")),Me(xe.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var Cs,Ce=Be(()=>{"use strict";se();Cs=/[<>:"/\\|?*]/g});function Xr(){let o={};for(let e of Vr)e.models.length>0&&(o[e.spec.name]=e.models);return o}function dr(){return Vr.map(o=>o.spec)}var Vr,ur=Be(()=>{"use strict";Vr=[{spec:{name:"custom",keywords:[],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["custom/model-name"]},{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 Ye(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function Yr(o){return`${Qe}${Ye(o)}`}function Qr(o,e){let t=Ye(e.startsWith(Qe)?e.slice(Qe.length):e);return o.customLlmProviders.find(n=>Ye(n.name)===t)??null}function Ls(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?Qr(o,n):null}function Ge(o){return!!o&&o.startsWith(Qe)}function Ze(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return Qr(o,n);let r=Ls(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 We(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Ze(o,t,e);return a?Yr(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=Ye(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of yt){let l=o.providers[a.name];if(s&&Ye(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of yt){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(Ye(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of yt){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Ze(o,t,e);return i?Yr(i.name):null}function Zr(o,e){let t=We(o,e);if(t&&Ge(t)){let n=Ze(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function Ht(o,e){let t=We(o,e);if(!t)return null;if(Ge(t))return Ze(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=yt.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function zt(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(Qe)){let s=n.slice(Qe.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 yt,Os,Qe,Se,bt=Be(()=>{"use strict";se();ur();yt=dr(),Os=Object.fromEntries(dr().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),Qe="custom:",Se={agents:{defaults:{workspace:Br,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:Os,customLlmProviders:[],customAcpProviders:[],gateway:{host:"127.0.0.1",port:6767,dashboard:{enabled:!0},heartbeat:{enabled:!0,intervalS:1800}},tools:{web:{search:{apiKey:"",maxResults:5}},exec:{timeout:60,pathAppend:""},restrictToWorkspace:!1,mcpServers:{},chromeSession:{enabled:!1,debugPort:9222,minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},browserRelay:{enabled:!1,authToken:"",extensionPath:""},rtk:{enabled:!0,autoInstall:!0,ultraCompact:!1,version:"latest"}},security:{enabled:!1,auth:{enabled:!1,pinHash:"",sessionTtlS:3600,lockOnIdle:!1,idleTimeoutS:900},toolGuard:{enabled:!1,guardedTools:null,deniedTools:[],rules:[],failOpen:!0},skillScanner:{enabled:!1,scanOnLoad:!1,blockUnsafe:!0,maxFileCount:1e3,maxFileSizeBytes:5242880},inputSanitizer:{enabled:!1,maxInputLength:5e4,stripHtmlTags:!1,blockPromptInjection:!1}}}});import Vt from"node:fs";import $s from"node:path";function vt(){return Ur()}function Te(){return Kt()}function eo(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]=eo(t[n],r):t[n]=r;return t}function O(o){let e=o??vt();if(!Vt.existsSync(e))return structuredClone(Se);try{let t=Vt.readFileSync(e,"utf8"),n=JSON.parse(t),r=eo(structuredClone(Se),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=Se.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(Se)}}function ie(o,e){let t=e??vt();Vt.mkdirSync($s.dirname(t),{recursive:!0}),Vt.writeFileSync(t,JSON.stringify(o,null,2),"utf8")}var et=Be(()=>{"use strict";bt();se();Ce()});var $t,Dt,Nt=Be(()=>{"use strict";$t=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))($t||{}),Dt=(u=>(u.COMMAND_INJECTION="COMMAND_INJECTION",u.DATA_EXFILTRATION="DATA_EXFILTRATION",u.PATH_TRAVERSAL="PATH_TRAVERSAL",u.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",u.NETWORK_ABUSE="NETWORK_ABUSE",u.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",u.RESOURCE_ABUSE="RESOURCE_ABUSE",u.PROMPT_INJECTION="PROMPT_INJECTION",u.CODE_EXECUTION="CODE_EXECUTION",u.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",u))(Dt||{})});var qo={};Ss(qo,{ToolGuardEngine:()=>jt});import Sa from"node:fs";function ka(){if(Vn)return Vn;try{let o=_e("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Sa.readFileSync(o,"utf8"),t=JSON.parse(e);return Vn=t,t}catch{return[]}}function Ca(o){if(o.length===0)return"SAFE";let e=Er.SAFE;for(let t of o){let n=Er[t.severity]??Er.SAFE;n<e&&(e=n)}return xa[e]??"SAFE"}var Vn,Er,xa,jt,Pr=Be(()=>{"use strict";et();Nt();se();Vn=null;Er={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},xa={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};jt=class o{static instance=null;config;guardians=[];mergedRules=[];loadFromDisk;constructor(e){this.loadFromDisk=e===void 0,this.config=e??O(),this.reloadRules()}static getInstance(e){return o.instance||(o.instance=new o(e)),o.instance}static resetInstance(){o.instance=null,Vn=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 y=p.guard({toolName:e,params:t});y.length>0&&r.push(...y),s.push(p.name)}catch(y){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(y)}`),!a){let C={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(y)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(C)}}let l=performance.now()-n,c=Ca(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=O());let e=ka(),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 qr from"node:path";import{createRequire as Ts}from"node:module";function X(){return new Date().toISOString()}Ce();var As=Ts(import.meta.url),qt=null;function Rs(){return qt||(qt=As("node:sqlite").DatabaseSync,qt)}function Hr(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 Kr=[{version:1,name:"create-operational-state-tables",sql:`
2
+ var Hs=Object.defineProperty;var zs=(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 Oe=(o,e)=>()=>(o&&(e=o(o=0)),e);var xr=(o,e)=>{for(var t in e)Hs(o,t,{get:e[t],enumerable:!0})};import oo from"node:fs";import Cr from"node:os";import Ue from"node:path";import{fileURLToPath as Vs}from"node:url";function dn(o=Cr.homedir()){return Ue.join(o,ht)}function io(o=Cr.homedir()){return Ue.join(o,ht,"workspace")}function ao(o=Cr.homedir()){return Ue.join(o,ht,"config.json")}function Xs(){let o=Vs(import.meta.url),e=Ue.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:Ue.resolve(e,"..")}function co(...o){let e=Ue.resolve(lo,...o);if(!oo.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function We(...o){let e=Ue.resolve(lo,...o);return oo.existsSync(e)?e:null}var ht,nt,so,lo,ue=Oe(()=>{"use strict";ht=".everclaw",nt="~/.everclaw/config.json",so=Ue.join("~",ht,"workspace");lo=Xs()});import un from"node:fs";import $e from"node:path";import Tr from"node:os";function Ke(o){return un.mkdirSync(o,{recursive:!0}),o}function gn(){return Ke(dn(Tr.homedir()))}function V(o){let e=o?o.replace(/^~(?=$|[\\/])/,Tr.homedir()):io(Tr.homedir());return Ke($e.resolve(e))}function uo(o){return o.replace(Ys,"_").trim()}function rt(o,e=!1){let t=We("templates");if(!t)return[];let n=[],r=(i,a)=>{un.existsSync(a)||(Ke($e.dirname(a)),i?un.copyFileSync(i,a):un.writeFileSync(a,"","utf8"),n.push($e.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r($e.join(t,i),$e.join(o,i));if(r($e.join(t,"memory","MEMORY.md"),$e.join(o,"memory","MEMORY.md")),r(null,$e.join(o,"memory","HISTORY.md")),Ke($e.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var Ys,Ae=Oe(()=>{"use strict";ue();Ys=/[<>:"/\\|?*]/g});function yo(){let o={};for(let e of ho)e.models.length>0&&(o[e.spec.name]=e.models);return o}function Ar(){return ho.map(o=>o.spec)}var ho,Er=Oe(()=>{"use strict";ho=[{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 yt(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function jt(o){return`${bt}${yt(o)}`}function bo(o,e){let t=yt(e.startsWith(bt)?e.slice(bt.length):e);return o.customLlmProviders.find(n=>yt(n.name)===t)??null}function ai(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?bo(o,n):null}function ot(o){return!!o&&o.startsWith(bt)}function vt(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return bo(o,n);let r=ai(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 Je(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=vt(o,t,e);return a?jt(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=yt(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of Dt){let l=o.providers[a.name];if(s&&yt(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of Dt){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(yt(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of Dt){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=vt(o,t,e);return i?jt(i.name):null}function vo(o,e){let t=Je(o,e);if(t&&ot(t)){let n=vt(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function pn(o,e){let t=Je(o,e);if(!t)return null;if(ot(t))return vt(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=Dt.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function fn(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(bt)){let s=n.slice(bt.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 Dt,ii,bt,pe,wt=Oe(()=>{"use strict";ue();Er();Dt=Ar(),ii=Object.fromEntries(Ar().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),bt="custom:",pe={agents:{defaults:{workspace:so,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:ii,customLlmProviders:[],customAcpProviders:[],gateway:{host:"127.0.0.1",port:6767,dashboard:{enabled:!0},heartbeat:{enabled:!0,intervalS:1800}},tools:{web:{search:{apiKey:"",maxResults:5}},exec:{timeout:60,pathAppend:""},restrictToWorkspace:!1,mcpServers:{},chromeSession:{enabled:!1,debugPort:9222,minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},browserRelay:{enabled:!1,authToken:"",extensionPath:""},rtk:{enabled:!0,autoInstall:!0,ultraCompact:!1,version:"latest"}},security:{enabled:!1,auth:{enabled:!1,pinHash:"",sessionTtlS:3600,lockOnIdle:!1,idleTimeoutS:900},toolGuard:{enabled:!1,guardedTools:null,deniedTools:[],rules:[],failOpen:!0},skillScanner:{enabled:!1,scanOnLoad:!1,blockUnsafe:!0,maxFileCount:1e3,maxFileSizeBytes:5242880},inputSanitizer:{enabled:!1,maxInputLength:5e4,stripHtmlTags:!1,blockPromptInjection:!1}}}});import hn from"node:fs";import li from"node:path";function St(){return ao()}function Pe(){return gn()}function wo(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]=wo(t[n],r):t[n]=r;return t}function $(o){let e=o??St();if(!hn.existsSync(e))return structuredClone(pe);try{let t=hn.readFileSync(e,"utf8"),n=JSON.parse(t),r=wo(structuredClone(pe),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=pe.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(pe)}}function re(o,e){let t=e??St();hn.mkdirSync(li.dirname(t),{recursive:!0}),hn.writeFileSync(t,JSON.stringify(o,null,2),"utf8")}function So(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(n=>n.name===t)&&e.push(`Provider '${t}' is not in the provider catalog and no matching customLlmProvider exists`),o.gateway.host!=="127.0.0.1"&&o.gateway.host!=="localhost"&&o.gateway.host!=="::1"&&o.gateway.dashboard?.enabled!==!1&&!o.security?.auth?.enabled&&e.push("Dashboard exposed on non-loopback address without authentication"),o.security?.toolGuard?.enabled&&o.security?.toolGuard?.failOpen&&e.push("Tool guard is fail-open \u2014 consider fail-closed for production"),o.channels?.telegram?.enabled&&!o.channels.telegram.token&&e.push("Telegram channel enabled but no token configured"),o.channels?.discord?.enabled&&!o.channels.discord.token&&e.push("Discord channel enabled but no token configured");for(let[n,r]of Object.entries(o.tools?.mcpServers??{}))!r.command&&!r.url&&e.push(`MCP server '${n}' has neither command nor URL configured`),r.command&&r.url&&e.push(`MCP server '${n}' has both command and URL \u2014 must use one`),r.toolTimeout!==void 0&&(!Number.isFinite(r.toolTimeout)||r.toolTimeout<=0)&&e.push(`MCP server '${n}' has invalid toolTimeout`);return e}var Ie=Oe(()=>{"use strict";wt();ue();Ae()});var Lo={};xr(Lo,{LocalProcessIsolationRunner:()=>me,selectExecutionIsolationPolicy:()=>lt});import{spawn as $o}from"node:child_process";function lt(o){return{...vi[o]}}var vi,me,ct=Oe(()=>{"use strict";vi={"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."}};me=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,u=null,p=!1,h=(w,F)=>{let A=typeof w=="string"?w:w.toString("utf8"),N=t-Buffer.byteLength(F);return N<=0?F:F+A.slice(0,N)};s.stdout?.on("data",w=>{a=h(w,a)}),s.stderr?.on("data",w=>{l=h(w,l)});let T=null,v=w=>{c||(c=!0,u=w,p=w==="timeout",this.killChild(s,"SIGTERM"),T=setTimeout(()=>this.killChild(s,"SIGKILL"),250),T.unref?.())},d=()=>v("abort");e.signal?.aborted?d():e.signal?.addEventListener("abort",d,{once:!0});let b=n!=null?setTimeout(()=>v("timeout"),n):null;b?.unref?.();let _=await new Promise(w=>{let F=!1,A=N=>{F||(F=!0,w(N))};s.once("error",N=>{i.current=N,A({code:null,signal:null})}),s.once("close",(N,U)=>A({code:N,signal:U}))});return b&&clearTimeout(b),T&&clearTimeout(T),e.signal?.removeEventListener("abort",d),u==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:_.code,signal:_.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:_.code,signal:_.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:_.code,signal:_.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:u,errorMessage:i.current.message}:_.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:_.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:_.code,signal:_.signal,failureAttribution:_.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:u,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?$o(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):$o(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={};xr(or,{McpClientManager:()=>Zt});import{Client as va}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as wa}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Sa}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as ka}from"@modelcontextprotocol/sdk/client/sse.js";function Xo(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var Zt,en=Oe(()=>{"use strict";Zt=class{connections=new Map;servers={};updateConfig(e){this.servers=e}async getServerTools(e){return(await this.ensureConnected(e)).tools}async callTool(e,t,n,r){let s=await this.ensureConnected(e),i=(s.timeout||60)*1e3,a=new AbortController,l=setTimeout(()=>a.abort(),i);r?.signal&&r.signal.addEventListener("abort",()=>a.abort(),{once:!0});try{let c=await s.client.callTool({name:t,arguments:n},void 0,{signal:a.signal});return c.isError?`Error: ${Array.isArray(c.content)?c.content.map(p=>p.text??JSON.stringify(p)).join(`
3
+ `):String(c.content??"Unknown error")}`:Array.isArray(c.content)?c.content.map(p=>p.type==="text"?p.text:JSON.stringify(p)).filter(Boolean).join(`
4
+ `)||"OK":c.content?String(c.content):"OK"}finally{clearTimeout(l)}}async closeAll(){let e=[...this.connections.entries()];this.connections.clear();for(let[,t]of e)try{await(await t).client.close()}catch{}}async closeServer(e){let t=this.connections.get(e);if(t){this.connections.delete(e);try{await(await t).client.close()}catch{}}}ensureConnected(e){let t=this.connections.get(e);return t||(t=this.connectServer(e),this.connections.set(e,t),t.catch(()=>this.connections.delete(e)),t)}async connectServer(e){let t=this.servers[e];if(!t)throw new Error(`MCP server '${e}' is not configured.`);let n=this.createTransport(e,t),r=new va({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=Xo(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${Xo(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 wa({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 Sa(s,{requestInit:{headers:a}})}catch{return new ka(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 rn,on,sn=Oe(()=>{"use strict";rn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(rn||{}),on=(u=>(u.COMMAND_INJECTION="COMMAND_INJECTION",u.DATA_EXFILTRATION="DATA_EXFILTRATION",u.PATH_TRAVERSAL="PATH_TRAVERSAL",u.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",u.NETWORK_ABUSE="NETWORK_ABUSE",u.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",u.RESOURCE_ABUSE="RESOURCE_ABUSE",u.PROMPT_INJECTION="PROMPT_INJECTION",u.CODE_EXECUTION="CODE_EXECUTION",u.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",u))(on||{})});var ps={};xr(ps,{ToolGuardEngine:()=>an});import Xa from"node:fs";function Ya(){if(pr)return pr;try{let o=We("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Xa.readFileSync(o,"utf8"),t=JSON.parse(e);return pr=t,t}catch{return[]}}function Za(o){if(o.length===0)return"SAFE";let e=Hr.SAFE;for(let t of o){let n=Hr[t.severity]??Hr.SAFE;n<e&&(e=n)}return Qa[e]??"SAFE"}var pr,Hr,Qa,an,zr=Oe(()=>{"use strict";Ie();sn();ue();pr=null;Hr={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Qa={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};an=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,pr=null}isDenied(e){return!this.config.security.enabled||!this.config.security.toolGuard.enabled?!1:this.config.security.toolGuard.deniedTools.includes(e)}isGuarded(e){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return!1;let t=this.config.security.toolGuard.guardedTools;return t===null?!0:t.includes(e)}guard(e,t){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return null;if(this.isDenied(e)){let p={id:`denied-${e}-${Date.now()}`,ruleId:"denied-tools-list",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Tool '${e}' is denied`,description:`The tool '${e}' is in the denied tools list and cannot be executed.`,toolName:e,guardian:"ToolGuardEngine"};return{toolName:e,params:t,findings:[p],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!1,maxSeverity:"CRITICAL"}}if(!this.isGuarded(e))return{toolName:e,params:t,findings:[],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!0,maxSeverity:"SAFE"};let n=performance.now(),r=[],s=[],i=[],a=this.config.security.toolGuard.failOpen!==!1;for(let p of this.guardians)try{let h=p.guard({toolName:e,params:t});h.length>0&&r.push(...h),s.push(p.name)}catch(h){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(h)}`),!a){let T={id:`guardian-error-${p.name}-${Date.now()}`,ruleId:"guardian-error",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Guardian '${p.name}' failed`,description:`Security guardian encountered an error and failOpen is disabled: ${String(h)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(T)}}let l=performance.now()-n,c=Za(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=Ya(),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 mo from"node:path";import{createRequire as Qs}from"node:module";function se(){return new Date().toISOString()}Ae();var Zs=Qs(import.meta.url),mn=null;function ei(){return mn||(mn=Zs("node:sqlite").DatabaseSync,mn)}function po(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 go=[{version:1,name:"create-operational-state-tables",sql:`
3
5
  CREATE TABLE IF NOT EXISTS session_metadata (
4
6
  workspace TEXT NOT NULL,
5
7
  session_key TEXT NOT NULL,
@@ -66,36 +68,36 @@ var ws=Object.defineProperty;var Be=(o,e)=>()=>(o&&(e=o(o=0)),e);var Ss=(o,e)=>{
66
68
 
67
69
  CREATE INDEX IF NOT EXISTS idx_inbox_deliveries_workspace_cleared_at
68
70
  ON inbox_deliveries (workspace, cleared_at, delivered_at DESC);
69
- `}];function Es(o=Kt()){return qr.join(o,"runtime","operations.sqlite")}var cr=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 Hr(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
71
+ `}];function ti(o=gn()){return mo.join(o,"runtime","operations.sqlite")}var Rr=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 po(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
70
72
  FROM schema_migrations
71
- 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 Ps(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 ni(o){o.exec(`
72
74
  CREATE TABLE IF NOT EXISTS schema_migrations (
73
75
  version INTEGER PRIMARY KEY,
74
76
  name TEXT NOT NULL,
75
77
  applied_at TEXT NOT NULL
76
78
  );
77
- `)}function we(o={}){let e=o.dbPath??Es(o.dataDir);Me(qr.dirname(e));let t=Rs(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),Ps(n);let r=Kr.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 Kr)i.has(a.version)||Hr(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,X())});return new cr(n,e)}var Is=new Set(["agent","gateway"]);function _s(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function Ms(o){let e=_s(o);return!!e&&Is.has(e)}function zr(o,e={}){if(!Ms(o))return!1;let t=e.openStorage??we,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}}et();bt();import Ut from"node:fs";import hs from"node:readline/promises";import{stdin as ys,stdout as bs}from"node:process";import{Command as pl,Option as Nr}from"commander";import Ne from"prompts";import P from"chalk";function Ds(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 to(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 Xt(o,e,t){let n=Ds(e),r=to(o,n);return t?to(r,t):r}se();Ce();var wt=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 Je=class{inbound=new wt;outbound=new wt;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 Po from"node:path";import ro from"node:fs";import Qt from"node:path";import oo from"node:os";import St from"node:fs";import Yt from"node:path";var Ns=[{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"]}}}],kt=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Yt.join(e,"memory");this.memoryDir=t?Yt.join(n,t):n,St.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Yt.join(this.memoryDir,"MEMORY.md"),this.historyFile=Yt.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return St.existsSync(this.memoryFile)?St.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){St.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){St.appendFileSync(this.historyFile,`${e.trim()}
79
+ `)}function Ee(o={}){let e=o.dbPath??ti(o.dataDir);Ke(mo.dirname(e));let t=ei(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),ni(n);let r=go.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 go)i.has(a.version)||po(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,se())});return new Rr(n,e)}var ri=new Set(["agent","gateway"]);function oi(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function si(o){let e=oi(o);return!!e&&ri.has(e)}function fo(o,e={}){if(!si(o))return!1;let t=e.openStorage??Ee,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}}Ie();wt();import ce from"node:fs";import Us from"node:readline/promises";import{stdin as Ws,stdout as Ks}from"node:process";import{Command as zl,Option as ro}from"commander";import et from"prompts";import k from"chalk";function ci(o){let e={};if(o.EVERCLAW_PROVIDER&&(e.provider=o.EVERCLAW_PROVIDER),o.EVERCLAW_MODEL&&(e.model=o.EVERCLAW_MODEL),o.EVERCLAW_API_KEY&&(e.apiKey=o.EVERCLAW_API_KEY),o.EVERCLAW_API_BASE&&(e.apiBase=o.EVERCLAW_API_BASE),o.EVERCLAW_GATEWAY_HOST&&(e.gatewayHost=o.EVERCLAW_GATEWAY_HOST),o.EVERCLAW_GATEWAY_PORT){let t=Number(o.EVERCLAW_GATEWAY_PORT);Number.isNaN(t)||(e.gatewayPort=t)}if(o.EVERCLAW_DASHBOARD!==void 0){let t=o.EVERCLAW_DASHBOARD.toLowerCase();(t==="true"||t==="false")&&(e.dashboardEnabled=t==="true")}return e}function ko(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 Ft(o,e,t){let n=ci(e),r=ko(o,n);return t?ko(r,t):r}ue();ue();import kt from"node:fs";import xo from"node:path";import di from"node:os";var ui="gateway.pid";function Pr(){return xo.join(di.homedir(),ht,ui)}function Co(o){let e=Pr();kt.mkdirSync(xo.dirname(e),{recursive:!0}),kt.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Me(){let o=Pr();if(!kt.existsSync(o))return null;try{let e=kt.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function Ne(o){let e=Pr();try{if(!kt.existsSync(e))return;if(o!==void 0){let t=Me();if(t&&t.pid!==o)return}kt.unlinkSync(e)}catch{}}function Le(o){try{return process.kill(o,0),!0}catch{return!1}}async function Ir(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Le(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Le(o)}function st(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(" ")}Ae();var Bt=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 it=class{inbound=new Bt;outbound=new Bt;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 Yo from"node:path";import To from"node:fs";import vn from"node:path";import Ro from"node:os";import Gt from"node:fs";import yn from"node:path";var gi=[{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"]}}}],Ut=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=yn.join(e,"memory");this.memoryDir=t?yn.join(n,t):n,Gt.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=yn.join(this.memoryDir,"MEMORY.md"),this.historyFile=yn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return Gt.existsSync(this.memoryFile)?Gt.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){Gt.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){Gt.appendFileSync(this.historyFile,`${e.trim()}
78
80
 
79
81
  `,"utf8")}getMemoryContext(){let e=this.readLongTerm();return e?`## Long-term Memory
80
- ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],u=[];for(let w of a)w._type==="anchor"?c.push(w):u.push(w);let p=[];for(let w of c)p.push(`[ANCHOR] ${w.name}: ${w.summary??"(no summary)"}`);for(let w of u){if(!w.content&&!w._full_content)continue;let d=Array.isArray(w.tools_used)&&w.tools_used.length?` [tools: ${w.tools_used.join(", ")}]`:"",b=w._full_content??w.content;p.push(`[${String(w.timestamp??"?").slice(0,16)}] ${String(w.role).toUpperCase()}${d}: ${String(b)}`)}let y=this.readLongTerm(),C=`Process this conversation and call the save_memory tool with your consolidation.
82
+ ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],u=[];for(let v of a)v._type==="anchor"?c.push(v):u.push(v);let p=[];for(let v of c)p.push(`[ANCHOR] ${v.name}: ${v.summary??"(no summary)"}`);for(let v of u){if(!v.content&&!v._full_content)continue;let d=Array.isArray(v.tools_used)&&v.tools_used.length?` [tools: ${v.tools_used.join(", ")}]`:"",b=v._full_content??v.content;p.push(`[${String(v.timestamp??"?").slice(0,16)}] ${String(v.role).toUpperCase()}${d}: ${String(b)}`)}let h=this.readLongTerm(),T=`Process this conversation and call the save_memory tool with your consolidation.
81
83
 
82
84
  ## Current Long-term Memory
83
- ${y||"(empty)"}
85
+ ${h||"(empty)"}
84
86
 
85
87
  ## Conversation to Process
86
88
  ${p.join(`
87
- `)}`;try{let w=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool."},{role:"user",content:C}],tools:Ns});if(!w.toolCalls.length)return!1;let d=w.toolCalls[0];if(!d)return!1;let b=d.arguments??{},I=b.history_entry,k=b.memory_update;if(I!=null&&this.appendHistory(typeof I=="string"?I:JSON.stringify(I)),k!=null){let N=typeof k=="string"?k:JSON.stringify(k);N!==y&&this.writeLongTerm(N)}let $=s?0:e.messages.length-l,j=e.messages.slice(0,$),M=-1;for(let N=j.length-1;N>=0;N--)if(j[N]?._type==="anchor"){M=N;break}return M!==-1?e.lastConsolidated=M+1:e.lastConsolidated=$,!0}catch{return!1}}};se();import xt from"node:fs";import Ct from"node:path";var mr=/^[a-z0-9][a-z0-9-]*$/;function no(o){return mr.test(o)}var tt=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=Ct.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??Wr("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}
89
+ `)}`;try{let v=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool."},{role:"user",content:T}],tools:gi});if(!v.toolCalls.length)return!1;let d=v.toolCalls[0];if(!d)return!1;let b=d.arguments??{},_=b.history_entry,w=b.memory_update;if(_!=null&&this.appendHistory(typeof _=="string"?_:JSON.stringify(_)),w!=null){let U=typeof w=="string"?w:JSON.stringify(w);U!==h&&this.writeLongTerm(U)}let F=s?0:e.messages.length-l,A=e.messages.slice(0,F),N=-1;for(let U=A.length-1;U>=0;U--)if(A[U]?._type==="anchor"){N=U;break}return N!==-1?e.lastConsolidated=N+1:e.lastConsolidated=F,!0}catch{return!1}}};ue();import Wt from"node:fs";import Kt from"node:path";var Mr=/^[a-z0-9][a-z0-9-]*$/;function bn(o){return Mr.test(o)}var De=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=Kt.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??co("skills"),this.scannerConfig=r??null,this.scanner=s??null}listSkills(e=!0){return(e?this.getResolvedSkills().filter(n=>n.status==="available"):this.getResolvedSkills()).map(({name:n,path:r,source:s})=>({name:n,path:r,source:s}))}listResolvedSkills(){return this.getResolvedSkills().map(({content:e,metadata:t,runtimeMeta:n,...r})=>r)}loadSkill(e){let t=this.getSkillByName(e);return t?.status==="available"?t.content:null}loadSkillsForContext(e){let t=[];for(let n of e){let r=this.getSkillByName(n);if(!r){t.push(this.renderLoadFailure(n,`Skill '${n}' is not installed. ${this.getAvailableSkillsHint()}`));continue}if(r.status!=="available"){let s=r.status==="malformed"?`Skill '${n}' is malformed: ${r.reason}.`:r.status==="blocked"?`Skill '${n}' is blocked by security scanner: ${r.reason}.`:`Skill '${n}' is unavailable: ${r.reason}.`;t.push(this.renderLoadFailure(n,s));continue}t.push(`### Skill: ${n}
88
90
 
89
91
  ${this.stripFrontmatter(r.content)}`)}return t.join(`
90
92
 
91
93
  ---
92
94
 
93
95
  `)}buildSkillsSummary(){let e=this.getResolvedSkills();if(!e.length)return"";let t=r=>r.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;"),n=["<skills>"];for(let r of e)n.push(` <skill available="${r.status==="available"}" source="${t(r.source)}">`),n.push(` <name>${t(r.name)}</name>`),n.push(` <description>${t(r.description)}</description>`),n.push(` <location>${t(r.path)}</location>`),n.push(` <status>${t(r.status)}</status>`),r.reason&&n.push(` <reason>${t(r.reason)}</reason>`),n.push(" </skill>");return n.push("</skills>"),n.join(`
94
- `)}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(!xt.existsSync(t))continue;let r=xt.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=Ct.join(t,s.name,"SKILL.md");xt.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=xt.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=Ct.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}'`):mr.test(l)||a.push(`frontmatter name '${l}' must match ${mr}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let u=s.always;return u!==void 0&&typeof u!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:u??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
96
+ `)}getAlwaysSkills(){return this.getResolvedSkills().filter(e=>e.status==="available"&&e.always).map(e=>e.name)}getSkillMetadata(e){return this.getSkillByName(e)?.metadata??null}stripFrontmatter(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length).trim():e}getResolvedSkills(){let e=new Map;for(let{root:t,source:n}of this.getSkillRoots()){if(!Wt.existsSync(t))continue;let r=Wt.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=Kt.join(t,s.name,"SKILL.md");Wt.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=Wt.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=Kt.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}'`):Mr.test(l)||a.push(`frontmatter name '${l}' must match ${Mr}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let u=s.always;return u!==void 0&&typeof u!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:u??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
95
97
  `)||e.startsWith(`---\r
96
- `)))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(Ct.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>xt.existsSync(Ct.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}
98
+ `)))return{frontmatter:null,error:"missing YAML frontmatter"};let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);return t?{frontmatter:t[1]??null,error:null}:{frontmatter:null,error:"unterminated YAML frontmatter"}}parseFrontmatter(e){let t={},n=[];for(let r of e.split(/\r?\n/)){let s=r.trim();if(!s)continue;let i=s.indexOf(":");if(i<=0){n.push(`invalid frontmatter line '${s}'`);continue}let a=s.slice(0,i).trim(),l=s.slice(i+1).trim();t[a]=this.parseFrontmatterValue(l)}return{metadata:t,errors:n}}parseFrontmatterValue(e){let t=e.replace(/^['"]|['"]$/g,"");return t==="true"?!0:t==="false"?!1:t}parseRuntimeMetadata(e){if(e===void 0||e==="")return{runtimeMeta:{},errors:[]};if(typeof e!="string")return{runtimeMeta:{},errors:["frontmatter field 'metadata' must be a JSON object string"]};let t;try{t=JSON.parse(e)}catch{return{runtimeMeta:{},errors:["frontmatter field 'metadata' must contain valid JSON"]}}if(!this.isRecord(t))return{runtimeMeta:{},errors:["frontmatter field 'metadata' must decode to an object"]};let n=t.everclaw??t.openclaw??{};if(!this.isRecord(n))return{runtimeMeta:{},errors:["skill metadata for 'everclaw'/'openclaw' must be an object"]};let r=[],s={};if(n.always!==void 0&&(typeof n.always!="boolean"?r.push("skill metadata field 'always' must be a boolean"):s.always=n.always),n.requires!==void 0)if(!this.isRecord(n.requires))r.push("skill metadata field 'requires' must be an object");else{let i=n.requires.bins,a=n.requires.env;i!==void 0&&!this.isStringArray(i)&&r.push("skill metadata field 'requires.bins' must be an array of strings"),a!==void 0&&!this.isStringArray(a)&&r.push("skill metadata field 'requires.env' must be an array of strings");let l={};this.isStringArray(i)&&(l.bins=i),this.isStringArray(a)&&(l.env=a),Object.keys(l).length>0&&(s.requires=l)}return{runtimeMeta:s,errors:r}}getRequirementErrors(e){let t=e.requires??{},n=(t.bins??[]).filter(i=>!this.hasBinary(i)),r=(t.env??[]).filter(i=>!process.env[i]),s=[];return n.length&&s.push(`missing required binaries: ${n.join(", ")}`),r.length&&s.push(`missing required env vars: ${r.join(", ")}`),s}hasBinary(e){let t=(process.env.PATH??"").split(Kt.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>Wt.existsSync(Kt.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}
97
99
 
98
- 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 Ke=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new kt(e),this.skills=new tt(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 kt(this.workspace,e):this.defaultMemory}buildSystemPrompt(e,t){let n=[this.getIdentity()],r=this.loadBootstrapFiles();r&&n.push(r);let i=this.getMemoryStore(t).getMemoryContext();i&&n.push(`# Memory
100
+ Error: ${t}`}isRecord(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}isStringArray(e){return Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim().length>0)}};var at=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new Ut(e),this.skills=new De(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 Ut(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
99
101
 
100
102
  ${i}`);let a=this.skills.getAlwaysSkills();if(a.length){let c=this.skills.loadSkillsForContext(a);c&&n.push(`# Active Skills
101
103
 
@@ -114,45 +116,45 @@ ${l}`),n.join(`
114
116
  You are everclaw, a helpful AI assistant.
115
117
 
116
118
  ## Runtime
117
- ${oo.platform()} ${oo.arch()}, Node ${process.version}
119
+ ${Ro.platform()} ${Ro.arch()}, Node ${process.version}
118
120
 
119
121
  ## Workspace
120
122
  Your workspace is at: ${this.workspace}
121
- - Long-term memory: ${Qt.join(this.workspace,"memory","MEMORY.md")}
122
- - History log: ${Qt.join(this.workspace,"memory","HISTORY.md")}
123
- - Custom skills: ${Qt.join(this.workspace,"skills","{skill-name}","SKILL.md")}
123
+ - Long-term memory: ${vn.join(this.workspace,"memory","MEMORY.md")}
124
+ - History log: ${vn.join(this.workspace,"memory","HISTORY.md")}
125
+ - Custom skills: ${vn.join(this.workspace,"skills","{skill-name}","SKILL.md")}
124
126
 
125
127
  ## Guidelines
126
128
  - State intent before tool calls, but never claim results before receiving them.
127
129
  - Before modifying a file, read it first.
128
- - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=Qt.join(this.workspace,t);ro.existsSync(n)&&e.push(`## ${t}
130
+ - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=vn.join(this.workspace,t);To.existsSync(n)&&e.push(`## ${t}
129
131
 
130
- ${ro.readFileSync(n,"utf8")}`)}return e.join(`
132
+ ${To.readFileSync(n,"utf8")}`)}return e.join(`
131
133
 
132
134
  `)}static buildRuntimeContext(e,t){let r=[`Current Time: ${new Date().toISOString()}`];return e&&t&&(r.push(`Channel: ${e}`),r.push(`Chat ID: ${t}`)),`${o.RUNTIME_CONTEXT_TAG}
133
135
  ${r.join(`
134
- `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}};import{randomUUID as Li}from"node:crypto";import Pi from"node:path";import{randomUUID as io}from"node:crypto";import Fs from"cron-parser";function fr(o){return o??"builtin"}function so(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function Oe(){return so()}function Zt(o,e,t,n){let r=fr(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 js(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:fr(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 oe(o){return{...o,source:"builtin"}}var gr=class{extensions=new Map;register(e){if(this.extensions.has(e.name))throw new Error(`Extension '${e.name}' is already registered`);return this.extensions.set(e.name,{...e,source:fr(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=so();for(let i of this.extensions.values()){for(let a of i.tools??[])Zt("tool",e,i,a);for(let a of i.channels??[])Zt("channel",t,i,a);for(let a of i.jobs??[])Zt("job",n,i,a);for(let a of i.commands??[])Zt("command",r,i,a);for(let a of i.lifecycle??[])js(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 Bs(o){return o instanceof Error?o.message:String(o)}var pr=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${Bs(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function Ae(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new pr(e,n.extension,n.source,n.contribution.name,r)}}function hr(o){let e=new gr;for(let t of o)e.register(t);return e.compose()}function Tt(){let o=new Error("Operation aborted");return o.name="AbortError",o}function J(o){return o instanceof Error&&o.name==="AbortError"}function U(o){if(o?.aborted)throw Tt()}function ae(){return Date.now()}var Us="default";function nt(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 Fs.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function ao(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 At=class{constructor(e={},t,n=Oe()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??Us}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=we({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,
136
+ `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}};import{randomUUID as ca}from"node:crypto";import oa from"node:path";import{randomUUID as Eo}from"node:crypto";import fi from"cron-parser";function $r(o){return o??"builtin"}function Ao(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function qe(){return Ao()}function wn(o,e,t,n){let r=$r(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 mi(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:$r(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 ge(o){return{...o,source:"builtin"}}var _r=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:$r(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=Ao();for(let i of this.extensions.values()){for(let a of i.tools??[])wn("tool",e,i,a);for(let a of i.channels??[])wn("channel",t,i,a);for(let a of i.jobs??[])wn("job",n,i,a);for(let a of i.commands??[])wn("command",r,i,a);for(let a of i.lifecycle??[])mi(s,i,a)}return{extensions:this.list(),tools:e,channels:t,jobs:n,commands:r,lifecycle:{beforeAgentTurn:s.beforeAgentTurn,afterAgentTurn:s.afterAgentTurn,beforeOutbound:s.beforeOutbound,afterOutbound:s.afterOutbound,beforeScheduledJob:s.beforeScheduledJob,afterScheduledJob:s.afterScheduledJob,shutdown:s.shutdown}}}};function pi(o){return o instanceof Error?o.message:String(o)}var Or=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${pi(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function je(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new Or(e,n.extension,n.source,n.contribution.name,r)}}function Lr(o){let e=new _r;for(let t of o)e.register(t);return e.compose()}function Jt(){let o=new Error("Operation aborted");return o.name="AbortError",o}function ee(o){return o instanceof Error&&o.name==="AbortError"}function X(o){if(o?.aborted)throw Jt()}function fe(){return Date.now()}var hi="default";function xt(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 fi.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Po(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 qt=class{constructor(e={},t,n=qe()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??hi}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Ee({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,
135
137
  next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
136
138
  FROM cron_jobs
137
139
  WHERE workspace = ?
138
140
  ORDER BY created_at_ms, job_id`).all(this.workspaceKey).map(t=>this.rowToJob(t))}}loadStore(){return this.store?this.store:(this.store=this.readStoreFromStorage(),this.store)}saveStore(){if(!this.store)return;let e=this.getStorage();e.transaction(()=>{e.prepare("DELETE FROM cron_jobs WHERE workspace = ?").run(this.workspaceKey);let t=e.prepare(`INSERT INTO cron_jobs (
139
141
  workspace, job_id, name, enabled, schedule_json, payload_json,
140
142
  state_json, next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
141
- ) 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-ae())))}async onTimer(){let e=this.loadStore(),t=ae(),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=ae(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await Ae(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 Ae(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":J(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=ae(),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=nt(e.schedule,ae())}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:nt(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=ae(),n={id:io().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:nt({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=ae();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();ao(e.schedule);let n=ae(),r={id:io().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:nt(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=ae(),r.state.nextRunAtMs=t?nt(r.schedule,ae()):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&&(ao(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?nt(t.schedule,ae()):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=ae(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import lo from"node:fs";import Gs from"node:path";var Ws=[{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"]}}}],Rt=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 Gs.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!lo.existsSync(this.heartbeatFile))return null;let e=lo.readFileSync(this.heartbeatFile,"utf8");return e.trim()?e:null}async decide(e){let t=await this.provider.chat({model:this.model,messages:[{role:"system",content:"You are a heartbeat agent. Call the heartbeat tool to report your decision."},{role:"user",content:`Review the following HEARTBEAT.md and decide whether there are active tasks.
143
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let n of this.store.jobs)t.run(this.workspaceKey,n.id,n.name,n.enabled?1:0,JSON.stringify(n.schedule),JSON.stringify(n.payload),JSON.stringify(n.state),n.state.nextRunAtMs,n.deleteAfterRun?1:0,n.createdAtMs,n.updatedAtMs)})}getNextWakeMs(){let t=this.loadStore().jobs.filter(n=>n.enabled&&n.state.nextRunAtMs).map(n=>n.state.nextRunAtMs);return t.length?Math.min(...t):null}armTimer(){this.timer&&clearTimeout(this.timer);let e=this.getNextWakeMs();!this.running||!e||(this.timer=setTimeout(()=>{this.onTimer()},Math.max(0,e-fe())))}async onTimer(){let e=this.loadStore(),t=fe(),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=fe(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await je(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 je(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":ee(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=fe(),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=xt(e.schedule,fe())}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:xt(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=fe(),n={id:Eo().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:xt({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=fe();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();Po(e.schedule);let n=fe(),r={id:Eo().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:xt(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=fe(),r.state.nextRunAtMs=t?xt(r.schedule,fe()):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&&(Po(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?xt(t.schedule,fe()):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=fe(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import Io from"node:fs";import yi from"node:path";var bi=[{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"]}}}],Ht=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 yi.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!Io.existsSync(this.heartbeatFile))return null;let e=Io.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.
142
144
 
143
- ${e}`}],tools:Ws});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=>{J(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 D=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 en=class extends D{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let u={kind:"cron",expr:s};i&&(u.tz=i),l=u}else if(a){let u=new Date(a);if(Number.isNaN(u.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:u.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let u=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${u.name}' (id: ${u.id})`}catch(u){return`Error: ${String(u).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
145
+ ${e}`}],tools:bi});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=>{ee(e)||console.warn(String(e))}).finally(()=>this.schedule())},this.intervalS*1e3))}async executeTasks(e){if(!this.onExecute)throw new Error("Heartbeat execution callback is not configured");let t=new AbortController;this.activeController=t;try{return await this.onExecute(e,{signal:t.signal})}finally{this.activeController===t&&(this.activeController=null)}}async tick(){let e=this.readHeartbeat();if(!e)return;let{action:t,tasks:n}=await this.decide(e);if(t!=="run"||!this.onExecute)return;let r=await this.executeTasks(n);r&&this.onNotify&&await this.onNotify(r)}async triggerNow(){let e=this.readHeartbeat();if(!e)return null;let{action:t,tasks:n}=await this.decide(e);return t!=="run"||!this.onExecute?null:this.executeTasks(n)}};var G=class o{static typeMap={string:e=>typeof e=="string",integer:e=>Number.isInteger(e),number:e=>typeof e=="number"&&Number.isFinite(e),boolean:e=>typeof e=="boolean",array:e=>Array.isArray(e),object:e=>!!e&&typeof e=="object"&&!Array.isArray(e)};validateParams(e){let t=this.parameters??{};if(t.type!=="object")throw new Error(`Schema must be object type, got ${String(t.type)}`);return this.validateValue(e,{...t,type:"object"},"parameter")}validateValue(e,t,n){let r=t.type,s=[];if(r&&o.typeMap[r]&&!o.typeMap[r](e))return[`${n} should be ${r}`];if(t.enum&&!t.enum.includes(e)&&s.push(`${n} must be one of ${JSON.stringify(t.enum)}`),(r==="integer"||r==="number")&&typeof e=="number"&&(typeof t.minimum=="number"&&e<t.minimum&&s.push(`${n} must be >= ${t.minimum}`),typeof t.maximum=="number"&&e>t.maximum&&s.push(`${n} must be <= ${t.maximum}`)),r==="string"&&typeof e=="string"&&(typeof t.minLength=="number"&&e.length<t.minLength&&s.push(`${n} must be at least ${t.minLength} chars`),typeof t.maxLength=="number"&&e.length>t.maxLength&&s.push(`${n} must be at most ${t.maxLength} chars`)),r==="object"&&e&&typeof e=="object"&&!Array.isArray(e)){let i=e,a=t.properties??{};for(let l of t.required??[])l in i||s.push(`missing required ${n==="parameter"?l:`${n}.${l}`}`);for(let[l,c]of Object.entries(i))a[l]&&s.push(...this.validateValue(c,a[l],n==="parameter"?l:`${n}.${l}`))}return r==="array"&&Array.isArray(e)&&t.items&&typeof t.items=="object"&&e.forEach((i,a)=>s.push(...this.validateValue(i,t.items,`${n}[${a}]`))),s}toSchema(){return{type:"function",function:{name:this.name,description:this.description,parameters:this.parameters}}}};var Sn=class extends G{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let u={kind:"cron",expr:s};i&&(u.tz=i),l=u}else if(a){let u=new Date(a);if(Number.isNaN(u.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:u.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let u=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${u.name}' (id: ${u.id})`}catch(u){return`Error: ${String(u).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
144
146
  ${t.map(n=>`- ${n.name} (id: ${n.id}, ${n.schedule.kind})`).join(`
145
- `)}`:"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 le from"node:fs";import rt from"node:path";import fe from"node:fs";import ee from"node:path";function co(o){let e=ee.resolve(o);for(;e!=="/"&&e!==".";)try{return fe.lstatSync(e),e}catch{let t=ee.dirname(e);if(t===e)break;e=t}return e||"/"}function uo(o,e){let t=ee.resolve(o),n=ee.resolve(e),r=n.endsWith(ee.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+ee.sep);if(!fe.existsSync(r))return s;try{let i=r;try{i=fe.realpathSync.native(r)}catch{}if(fe.existsSync(t)){let c=fe.realpathSync.native(t);return c===i||c.startsWith(i+ee.sep)}let a=co(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=fe.realpathSync.native(a);if(c===i||c.startsWith(i+ee.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=ee.dirname(l);if(c===l)break;try{if(fe.lstatSync(c).isSymbolicLink()){let p=fe.realpathSync.native(c);if(p!==i&&!p.startsWith(i+ee.sep))return!1}}catch{}l=c}return s}catch{return!1}}function mo(o,e){let t=ee.resolve(o),n=ee.resolve(e);if(!uo(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=ee.dirname(t),s=co(r),i=n;try{fe.existsSync(n)&&(i=fe.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=fe.realpathSync.native(s);if(a!==i&&!a.startsWith(i+ee.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(!uo(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function sn(o,e,t,n=!1){let r=o.startsWith("~")?rt.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=rt.isAbsolute(r)?r:e?rt.join(e,r):r,i=rt.resolve(s);if(t)try{n?mo(i,t):ke(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var tn=class extends D{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=sn(String(t.path),this.workspace,this.allowedDir);return le.existsSync(r)?le.statSync(r).isFile()?le.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)}`}}},nn=class extends D{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=sn(String(t.path),this.workspace,this.allowedDir,!0);le.mkdirSync(rt.dirname(r),{recursive:!0});let s=String(t.content??"");return le.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},rn=class extends D{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=sn(String(t.path),this.workspace,this.allowedDir,!0);if(!le.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=le.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.`:(le.writeFileSync(r,s.replace(i,a),"utf8"),`Successfully edited ${r}`):`Error: old_text not found in ${String(t.path)}. Verify the file content.`}catch(r){return`Error editing file: ${String(r)}`}}},on=class extends D{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=sn(String(t.path),this.workspace,this.allowedDir);if(!le.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!le.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=le.readdirSync(r).sort().map(i=>{let a=rt.join(r,i);return`${le.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
146
- `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var an=class extends D{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,u=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${u}`:u}catch(c){return`Error sending message: ${String(c)}`}}};import yr from"node:path";import{spawn as go}from"node:child_process";var Js={"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."}};function ot(o){return{...Js[o]}}var ce=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,u=null,p=!1,y=(k,$)=>{let j=typeof k=="string"?k:k.toString("utf8"),M=t-Buffer.byteLength($);return M<=0?$:$+j.slice(0,M)};s.stdout?.on("data",k=>{a=y(k,a)}),s.stderr?.on("data",k=>{l=y(k,l)});let C=null,w=k=>{c||(c=!0,u=k,p=k==="timeout",this.killChild(s,"SIGTERM"),C=setTimeout(()=>this.killChild(s,"SIGKILL"),250),C.unref?.())},d=()=>w("abort");e.signal?.aborted?d():e.signal?.addEventListener("abort",d,{once:!0});let b=n!=null?setTimeout(()=>w("timeout"),n):null;b?.unref?.();let I=await new Promise(k=>{let $=!1,j=M=>{$||($=!0,k(M))};s.once("error",M=>{i.current=M,j({code:null,signal:null})}),s.once("close",(M,N)=>j({code:M,signal:N}))});return b&&clearTimeout(b),C&&clearTimeout(C),e.signal?.removeEventListener("abort",d),u==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:I.code,signal:I.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:I.code,signal:I.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:I.code,signal:I.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:u,errorMessage:i.current.message}:I.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:I.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:u,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:I.code,signal:I.signal,failureAttribution:I.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:u,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?go(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):go(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 ln=class extends D{constructor(t=60,n,r=!1,s="",i=new ce,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=yr.resolve(a),c=yr.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;U(n?.signal);let a=ot("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${yr.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let u=await this.runner.run(c);if(u.status==="aborted")throw Tt();if(u.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=u.stdout?`${u.stdout}${u.status==="failed"?`
147
- `:""}`:"";if(this.rtkService?.getRuntime().available&&p)try{let b=await this.rtkService.compress({command:r,stdout:p,stderr:u.stderr,exitCode:u.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(p=b.stdout)}catch{}let y=u.stderr.trim()?`STDERR:
147
+ `)}`:"No scheduled jobs."}removeJob(t){return t?this.cron.removeJob(t)?`Removed job ${t}`:`Job ${t} not found`:"Error: job_id is required for remove"}};import he from"node:fs";import Ct from"node:path";import xe from"node:fs";import ae from"node:path";function Mo(o){let e=ae.resolve(o);for(;e!=="/"&&e!==".";)try{return xe.lstatSync(e),e}catch{let t=ae.dirname(e);if(t===e)break;e=t}return e||"/"}function _o(o,e){let t=ae.resolve(o),n=ae.resolve(e),r=n.endsWith(ae.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+ae.sep);if(!xe.existsSync(r))return s;try{let i=r;try{i=xe.realpathSync.native(r)}catch{}if(xe.existsSync(t)){let c=xe.realpathSync.native(t);return c===i||c.startsWith(i+ae.sep)}let a=Mo(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=xe.realpathSync.native(a);if(c===i||c.startsWith(i+ae.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=ae.dirname(l);if(c===l)break;try{if(xe.lstatSync(c).isSymbolicLink()){let p=xe.realpathSync.native(c);if(p!==i&&!p.startsWith(i+ae.sep))return!1}}catch{}l=c}return s}catch{return!1}}function Oo(o,e){let t=ae.resolve(o),n=ae.resolve(e);if(!_o(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=ae.dirname(t),s=Mo(r),i=n;try{xe.existsSync(n)&&(i=xe.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=xe.realpathSync.native(s);if(a!==i&&!a.startsWith(i+ae.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 _e(o,e){if(!_o(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function Rn(o,e,t,n=!1){let r=o.startsWith("~")?Ct.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Ct.isAbsolute(r)?r:e?Ct.join(e,r):r,i=Ct.resolve(s);if(t)try{n?Oo(i,t):_e(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var kn=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="read_file";description="Read the contents of a file at the given path.";parameters={type:"object",properties:{path:{type:"string",description:"The file path to read"}},required:["path"]};async execute(t,n){try{let r=Rn(String(t.path),this.workspace,this.allowedDir);return he.existsSync(r)?he.statSync(r).isFile()?he.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)}`}}},xn=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="write_file";description="Write content to a file at the given path. Creates parent directories if needed.";parameters={type:"object",properties:{path:{type:"string"},content:{type:"string"}},required:["path","content"]};async execute(t,n){try{let r=Rn(String(t.path),this.workspace,this.allowedDir,!0);he.mkdirSync(Ct.dirname(r),{recursive:!0});let s=String(t.content??"");return he.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},Cn=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="edit_file";description="Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file.";parameters={type:"object",properties:{path:{type:"string"},old_text:{type:"string"},new_text:{type:"string"}},required:["path","old_text","new_text"]};async execute(t,n){try{let r=Rn(String(t.path),this.workspace,this.allowedDir,!0);if(!he.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=he.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.`:(he.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)}`}}},Tn=class extends G{constructor(t,n){super();this.workspace=t;this.allowedDir=n}name="list_dir";description="List the contents of a directory.";parameters={type:"object",properties:{path:{type:"string"}},required:["path"]};async execute(t,n){try{let r=Rn(String(t.path),this.workspace,this.allowedDir);if(!he.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!he.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=he.readdirSync(r).sort().map(i=>{let a=Ct.join(r,i);return`${he.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
148
+ `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var An=class extends G{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,u=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${u}`:u}catch(c){return`Error sending message: ${String(c)}`}}};import Nr from"node:path";ct();var En=class extends G{constructor(t=60,n,r=!1,s="",i=new me,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=Nr.resolve(a),c=Nr.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;X(n?.signal);let a=lt("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${Nr.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let u=await this.runner.run(c);if(u.status==="aborted")throw Jt();if(u.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=u.stdout?`${u.stdout}${u.status==="failed"?`
149
+ `:""}`:"";if(this.rtkService?.getRuntime().available&&p)try{let b=await this.rtkService.compress({command:r,stdout:p,stderr:u.stderr,exitCode:u.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(p=b.stdout)}catch{}let h=u.stderr.trim()?`STDERR:
148
150
  ${u.stderr}
149
- `:"",C=u.status==="failed"&&typeof u.exitCode=="number"?`
150
- Exit code: ${u.exitCode}`:"",w=u.status==="failed"&&u.signal?`
151
- Signal: ${u.signal}`:"",d=`${p}${y}${C}${w}`.trim();return d?d.length>1e4?`${d.slice(0,1e4)}
152
- ... (truncated, ${d.length-1e4} more chars)`:d:u.status==="failed"?u.errorMessage?`Error executing command: ${u.errorMessage}`:"Error executing command":"(no output)"}};var cn=class extends D{constructor(t){super();this.manager=t}name="spawn";description="Spawn a subagent to handle a task in the background.";parameters={type:"object",properties:{task:{type:"string",description:"The task for the subagent to complete"},label:{type:"string",description:"Optional short label"},model:{type:"string",description:"Optional model override (e.g. 'anthropic/claude-sonnet-4'). Falls back to subagent config or global default if omitted."},provider:{type:"string",description:"Optional provider override (e.g. 'openai'). Falls back to subagent config or global default if omitted."}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";setContext(t,n,r=`${t}:${n}`){this.originChannel=t,this.originChatId=n,this.sessionKey=r}async execute(t,n){let r={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey};return t.model!=null&&(r.model=String(t.model)),t.provider!=null&&(r.providerName=String(t.provider)),this.manager.spawn(r)}};var dn=class extends D{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 un=class extends D{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+=Ke.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 mn=class extends D{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 Ks,existsSync as qs}from"node:fs";import{join as G}from"node:path";import Hs from"node:http";import{homedir as zs}from"node:os";import Vs from"node:net";import fo from"ws";var Xs={existsSync:qs,readFileSync:Ks},po=Xs;var Ys=Hs,ho=Ys;var Qs=1;var Zs="/tmp/chrome-debug-profile";function ei(o){let e=o??process.platform,t=zs(),n=G(Zs,"DevToolsActivePort");switch(e){case"darwin":return[n,G(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),G(t,"Library/Application Support/Chromium/DevToolsActivePort"),G(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),G(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),G(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||G(t,".config");return[n,G(r,"google-chrome","DevToolsActivePort"),G(r,"chromium","DevToolsActivePort"),G(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),G(r,"microsoft-edge","DevToolsActivePort"),G(r,"vivaldi","DevToolsActivePort"),G(t,".config","google-chrome","DevToolsActivePort"),G(t,".config","chromium","DevToolsActivePort"),G(t,"snap","chromium","common","chromium","DevToolsActivePort"),G(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),G(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||G(t,"AppData","Local");return[n,G(r,"Google","Chrome","User Data","DevToolsActivePort"),G(r,"Chromium","User Data","DevToolsActivePort"),G(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),G(r,"Microsoft","Edge","User Data","DevToolsActivePort"),G(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function pn(o){return fn(o)?.port}function fn(o){let e=ei(o);for(let t of e)try{if(!po.existsSync(t))continue;let r=po.readFileSync(t,"utf-8").split(`
153
- `),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 ti(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=ho.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 ni(o,e="127.0.0.1"){return new Promise(t=>{let n=new Vs.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 ri(o){return new Promise(e=>{try{let t=new fo(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 st(o=9222){let e=fn(),t=e?.port??o;if(await ni(t)){for(let r=0;r<2;r++){try{let s=await ti(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 ri(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=ho.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 Et(o){let t=fn()?.browserWsPath;if(!t)return[];let n=await gn.connect(`ws://127.0.0.1:${o}${t}`);try{return((await n.send("Target.getTargets")).targetInfos??[]).map(i=>({id:i.targetId,type:i.type,title:i.title,url:i.url,webSocketDebuggerUrl:i.webSocketDebuggerUrl??`ws://127.0.0.1:${o}/devtools/page/${i.targetId}`}))}finally{n.close()}}async function yo(o,e){let n=fn()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await gn.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 gn=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 fo(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!==Qs)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 oi}from"node:child_process";import{createConnection as si}from"node:net";import{tmpdir as ii}from"node:os";import{join as vo,dirname as ai}from"node:path";import{unlink as li,unlinkSync as ci,mkdirSync as di,existsSync as yn}from"node:fs";import hn from"node:fs";function it(o){let e="electron"in process.versions,t,n;if(o.endsWith(".js")){if(!hn.existsSync(o))throw new Error(`No executable found: ${o}.js does not exist.`);t=o,n=!1}else if(o.endsWith(".ts")){if(!hn.existsSync(o))throw new Error(`No executable found: ${o}.ts does not exist.`);t=o,n=!0}else{let i=o+".js",a=o+".ts";if(hn.existsSync(i))t=i,n=!1;else if(hn.existsSync(a))t=a,n=!0;else throw new Error(`No executable found: neither ${i} nor ${a} exists.`)}let r=process.execPath,s=n?["--import","tsx",t]:[t];return e?{file:r,args:s,env:{...process.env,ELECTRON_RUN_AS_NODE:"1"}}:{file:r,args:s,env:process.env}}var ui=null,mi=null,gi=null,pi=!1;function Pt(){return mi??process.platform}function fi(){return ui??oi}function hi(){return gi??si}function yi(o,e){let t=Pt(),n=e??ii(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:vo(n,`airclaw-daemon-${r}.sock`)}function bo(o,e){let t=o.split(`
154
- `),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 at=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=yi(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(Pt()==="win32"||yn(r)){let C={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,C);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),Pt()!=="win32"&&yn(r))try{ci(r)}catch{}}}let i=ai(r);if(!yn(i)&&Pt()!=="win32")try{di(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),pi)return;let l=vo(import.meta.dirname,"daemon-worker"),{file:c,args:u,env:p}=it(l),y=fi()(c,[...u,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=y,y.on("exit",()=>{this.cleanupDaemon(e)}),y.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((C,w)=>{let d=setTimeout(()=>{w(new Error("Daemon startup timeout"))},1e4),b=I=>{I.toString("utf8").includes("READY")&&(clearTimeout(d),y.stdout?.off("data",b),C())};y.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=hi()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=bo(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})+`
155
- `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(u){r.pendingCommands.delete(s),c(u)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=bo(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"));Pt()!=="win32"&&yn(t.socketPath)&&li(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as bi,mkdirSync as vi,existsSync as wi}from"node:fs";import{dirname as Si,join as bn}from"node:path";import{tmpdir as ki}from"node:os";var qe=class extends D{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
151
+ `:"",T=u.status==="failed"&&typeof u.exitCode=="number"?`
152
+ Exit code: ${u.exitCode}`:"",v=u.status==="failed"&&u.signal?`
153
+ Signal: ${u.signal}`:"",d=`${p}${h}${T}${v}`.trim();return d?d.length>1e4?`${d.slice(0,1e4)}
154
+ ... (truncated, ${d.length-1e4} more chars)`:d:u.status==="failed"?u.errorMessage?`Error executing command: ${u.errorMessage}`:"Error executing command":"(no output)"}};var Pn=class extends G{constructor(t){super();this.manager=t}name="spawn";description="Spawn a subagent to handle a task in the background.";parameters={type:"object",properties:{task:{type:"string",description:"The task for the subagent to complete"},label:{type:"string",description:"Optional short label"},model:{type:"string",description:"Optional model override (e.g. 'anthropic/claude-sonnet-4'). Falls back to subagent config or global default if omitted."},provider:{type:"string",description:"Optional provider override (e.g. 'openai'). Falls back to subagent config or global default if omitted."}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";setContext(t,n,r=`${t}:${n}`){this.originChannel=t,this.originChatId=n,this.sessionKey=r}async execute(t,n){let r={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey};return t.model!=null&&(r.model=String(t.model)),t.provider!=null&&(r.providerName=String(t.provider)),this.manager.spawn(r)}};var In=class extends G{name="session.search";description="Search the current session's message history for content matching the query.";parameters={type:"object",properties:{query:{type:"string",description:"The search query to match against message content"},limit:{type:"integer",description:"Maximum number of results to return",minimum:1,maximum:100}},required:["query"]};sessionManager=null;sessionKey="cli:direct";constructor(){super()}setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e,t){if(!this.sessionManager)return"Error: Session manager not available";let n=String(e.query??""),r=typeof e.limit=="number"?Math.min(Math.max(1,Math.floor(e.limit)),100):10;if(!n)return"Error: Query cannot be empty";let i=this.sessionManager.getOrCreate(this.sessionKey).search(n,r);return JSON.stringify(i,null,2)}};var Mn=class extends G{name="session.info";description="Returns information about the current session: message count, token estimate, last anchor name, and messages since last anchor.";parameters={type:"object",properties:{},required:[]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=this.sessionManager.getOrCreate(this.sessionKey),n=t.getHistory(1e3),r=0;for(let l of n)r+=at.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 _n=class extends G{name="session.anchor";description="Create a named anchor in the session. Messages before the anchor become eligible for summarization. Anchors survive consolidation.";parameters={type:"object",properties:{name:{type:"string",description:"The name of the anchor"},summary:{type:"string",description:"Optional summary describing what happened before this anchor"}},required:["name"]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=String(e.name??"");if(!t)return"Error: Anchor name is required";let n=e.summary!=null?String(e.summary):void 0,s=this.sessionManager.getOrCreate(this.sessionKey).anchor(t,n);return JSON.stringify({success:!0,anchor:{name:s.name,summary:s.summary,timestamp:s.timestamp}},null,2)}};import{readFileSync as wi,existsSync as Si}from"node:fs";import{join as Y}from"node:path";import ki from"node:http";import{homedir as xi}from"node:os";import Ci from"node:net";import Do from"ws";var Ti={existsSync:Si,readFileSync:wi},No=Ti;var Ri=ki,jo=Ri;var Ai=1;var Ei="/tmp/chrome-debug-profile";function Pi(o){let e=o??process.platform,t=xi(),n=Y(Ei,"DevToolsActivePort");switch(e){case"darwin":return[n,Y(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),Y(t,"Library/Application Support/Chromium/DevToolsActivePort"),Y(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),Y(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),Y(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||Y(t,".config");return[n,Y(r,"google-chrome","DevToolsActivePort"),Y(r,"chromium","DevToolsActivePort"),Y(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),Y(r,"microsoft-edge","DevToolsActivePort"),Y(r,"vivaldi","DevToolsActivePort"),Y(t,".config","google-chrome","DevToolsActivePort"),Y(t,".config","chromium","DevToolsActivePort"),Y(t,"snap","chromium","common","chromium","DevToolsActivePort"),Y(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),Y(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||Y(t,"AppData","Local");return[n,Y(r,"Google","Chrome","User Data","DevToolsActivePort"),Y(r,"Chromium","User Data","DevToolsActivePort"),Y(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),Y(r,"Microsoft","Edge","User Data","DevToolsActivePort"),Y(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function $n(o){return Ln(o)?.port}function Ln(o){let e=Pi(o);for(let t of e)try{if(!No.existsSync(t))continue;let r=No.readFileSync(t,"utf-8").split(`
155
+ `),s=r[0]?.trim(),i=r[1]?.trim()||void 0;if(s){let a=parseInt(s,10);if(a>0&&a<=65535)return{port:a,browserWsPath:i}}}catch{}}function Ii(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=jo.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 Mi(o,e="127.0.0.1"){return new Promise(t=>{let n=new Ci.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 _i(o){return new Promise(e=>{try{let t=new Do(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 Tt(o=9222){let e=Ln(),t=e?.port??o;if(await Mi(t)){for(let r=0;r<2;r++){try{let s=await Ii(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 _i(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=jo.get(`http://127.0.0.1:${t}/json/version`,{timeout:3e3},i=>{i.resume(),i.statusCode===404||i.statusCode===403?r({port:t,versionInfo:{},pendingApproval:!0}):r(void 0)});s.on("error",()=>r(void 0)),s.on("timeout",()=>{s.destroy(),r(void 0)})})}}async function zt(o){let t=Ln()?.browserWsPath;if(!t)return[];let n=await On.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 Fo(o,e){let n=Ln()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await On.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 On=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 Do(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!==Ai)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 Oi}from"node:child_process";import{createConnection as $i}from"node:net";import{tmpdir as Li}from"node:os";import{join as Go,dirname as Ni}from"node:path";import{unlink as Di,unlinkSync as ji,mkdirSync as Fi,existsSync as Nn}from"node:fs";import dt from"node:fs";function Rt(o){let e="electron"in process.versions,t=o;try{t=dt.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!dt.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!dt.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(dt.existsSync(a)){try{n=dt.realpathSync(a)}catch{n=a}r=!1}else if(dt.existsSync(l)){try{n=dt.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 Bi=null,Gi=null,Ui=null,Wi=!1;function Vt(){return Gi??process.platform}function Ki(){return Bi??Oi}function Ji(){return Ui??$i}function qi(o,e){let t=Vt(),n=e??Li(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:Go(n,`airclaw-daemon-${r}.sock`)}function Bo(o,e){let t=o.split(`
156
+ `),n=t.pop()??"";for(let r of t){let s=r.trim();if(s)try{let i=JSON.parse(s);e(i)}catch{}}return n}var At=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=qi(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(Vt()==="win32"||Nn(r)){let T={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,T);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),Vt()!=="win32"&&Nn(r))try{ji(r)}catch{}}}let i=Ni(r);if(!Nn(i)&&Vt()!=="win32")try{Fi(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),Wi)return;let l=Go(import.meta.dirname,"daemon-worker"),{file:c,args:u,env:p}=Rt(l),h=Ki()(c,[...u,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=h,h.on("exit",()=>{this.cleanupDaemon(e)}),h.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((T,v)=>{let d=setTimeout(()=>{v(new Error("Daemon startup timeout"))},1e4),b=_=>{_.toString("utf8").includes("READY")&&(clearTimeout(d),h.stdout?.off("data",b),T())};h.stdout?.on("data",b)}),await this.connectToDaemon(e)}async connectToDaemon(e){let t=this.daemons.get(e);if(!t)throw new Error(`No daemon for target ${e}`);return new Promise((n,r)=>{let s=Ji()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=Bo(t.ndjsonBuffer+i.toString("utf8"),a=>{let l=t.pendingCommands.get(a.id);l&&(t.pendingCommands.delete(a.id),l.resolve(a))})}),s.on("close",()=>{t.clientSocket=null;for(let[,i]of t.pendingCommands)i.reject(new Error("Daemon socket closed"));t.pendingCommands.clear()}),s.on("error",()=>{}),n()}),s.on("error",i=>{r(new Error(`Failed to connect to daemon: ${i.message}`))}),setTimeout(()=>{t.clientSocket||(s.destroy(),r(new Error("Daemon connection timeout")))},5e3)})}async sendCommand(e,t,n={}){let r=this.daemons.get(e);if(!r)throw new Error(`No daemon for target ${e}`);if(!r.clientSocket)throw new Error(`Daemon socket not connected for ${e}`);let s=r.commandId++,a=JSON.stringify({id:s,cmd:t,args:n})+`
157
+ `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(u){r.pendingCommands.delete(s),c(u)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=Bo(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"));Vt()!=="win32"&&Nn(t.socketPath)&&Di(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as Hi,mkdirSync as zi,existsSync as Vi}from"node:fs";import{dirname as Xi,join as Dn}from"node:path";import{tmpdir as Yi}from"node:os";var ut=class extends G{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
156
158
 
157
159
  Core Commands:
158
160
  - status: Check Chrome connectivity, version, and remote debugging status
@@ -187,7 +189,7 @@ Examples:
187
189
  - chrome_session clickxy --target "ABC123" --x 100 --y 200
188
190
  - chrome_session type --target "ABC123" --text "Hello World"
189
191
  - chrome_session loadall --target "ABC123" --selector "button.load-more" --interval 500
190
- - chrome_session evalraw --target "ABC123" --method "Page.getTitle" --params '{}'`;parameters={type:"object",properties:{command:{type:"string",description:"The command to execute",enum:["status","list","open","stop","snap","shot","eval","html","nav","net","click","clickxy","type","loadall","evalraw"]},target:{type:"string",description:"Target ID prefix (required for page interaction commands)"},url:{type:"string",description:"URL to open (for 'open' and 'nav' commands)"},path:{type:"string",description:"File path to save screenshot (for 'shot' command)"},selector:{type:"string",description:"CSS selector for element-specific operations (for 'shot', 'html', 'click', 'loadall' commands)"},expression:{type:"string",description:"JavaScript expression to evaluate (for 'eval' command)"},depth:{type:"number",description:"Maximum depth for accessibility tree (for 'snap' command)"},timeout:{type:"number",description:"Timeout in milliseconds (for 'nav' command)"},outer:{type:"boolean",description:"Return outer HTML (default true, for 'html' command)"},x:{type:"number",description:"X coordinate in CSS pixels (for 'clickxy' command)"},y:{type:"number",description:"Y coordinate in CSS pixels (for 'clickxy' command)"},text:{type:"string",description:"Text to type at focused element (for 'type' command)"},interval:{type:"number",description:"Interval in milliseconds between clicks (for 'loadall' command, default 500)"},method:{type:"string",description:"CDP method name (for 'evalraw' command)"},params:{type:"object",description:"CDP method parameters as JSON object (for 'evalraw' command)"}},required:["command"]};config;daemonManager;commands;workspace;restrictToWorkspace;constructor(e={},t,n=!1){super(),this.config={minChromeVersion:e.minChromeVersion??136,daemonIdleTimeoutS:e.daemonIdleTimeoutS??1200,targetPrefixLength:e.targetPrefixLength??8},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=at.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 st();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=pn();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 Et(e)}catch{t=await Et(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=pn();if(!t)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n=e.url??"about:blank",r=this.config.targetPrefixLength;try{let s=await fetch(`http://127.0.0.1:${t}/json/new?${n}`,{method:"PUT"});if(s.ok){let i=await s.json();return this.formatResult({success:!0,id:i.id.slice(0,r),fullId:i.id,url:i.url,message:`Opened new tab: ${i.url}`})}}catch{}try{let s=await yo(t,n);return this.formatResult({success:!0,id:s.id.slice(0,r),fullId:s.id,url:s.url,message:`Opened new tab: ${s.url}`})}catch(s){return this.formatError(`Cannot open tab via HTTP or WebSocket on port ${t}: ${s instanceof Error?s.message:String(s)}. Run 'chrome_session status' for details.`)}}async handleStop(e){let t=e.target;if(t){let s=this.daemonManager.getActiveTargets().find(i=>i.toUpperCase().startsWith(t.toUpperCase()));return s?(this.daemonManager.stopDaemon(s),this.formatResult({success:!0,target:s.slice(0,this.config.targetPrefixLength),message:`Stopped daemon for target ${s.slice(0,this.config.targetPrefixLength)}`})):this.formatError(`No daemon found for target prefix '${t}'`)}let n=this.daemonManager.getActiveTargets().length;return n===0?this.formatResult({success:!0,message:"No active daemons to stop"}):(this.daemonManager.stopAll(),this.formatResult({success:!0,message:`Stopped ${n} daemon(s)`}))}async handleSnap(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.depth!==void 0&&(r.depth=e.depth);let s=await this.sendDaemonCommand(t,n,"snap",r);return s.ok?this.formatResult({tree:s.result?.tree,nodeCount:s.result?.nodeCount}):this.formatError(s.error??"Failed to get accessibility tree")}async handleShot(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.path,s=this.resolveScreenshotPath(r),i={};s&&(i.path=s),e.selector&&(i.selector=e.selector);let a=await this.sendDaemonCommand(t,n,"shot",i);return a.ok?(s&&a.result?.data&&this.saveScreenshot(s,a.result.data),this.formatResult({path:s,dpr:a.result?.dpr,viewport:a.result?.viewport,message:s?`Screenshot saved to ${s}`:"Screenshot captured (base64 data in 'data' field)",data:s?void 0:a.result?.data})):this.formatError(a.error??"Failed to capture screenshot")}async handleEval(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.expression;if(!r)return this.formatError("Missing required 'expression' parameter");let s=await this.sendDaemonCommand(t,n,"eval",{expression:r,awaitPromise:!0});return s.ok?this.formatResult({ok:!0,result:s.result?.result,type:s.result?.type,subtype:s.result?.subtype}):this.formatError(s.error??"JavaScript evaluation failed")}async handleHtml(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r={};e.selector&&(r.selector=e.selector),e.outer!==void 0&&(r.outer=e.outer);let s=await this.sendDaemonCommand(t,n,"html",r);return s.ok?this.formatResult({html:s.result?.html,selector:s.result?.selector}):this.formatError(s.error??"Failed to get HTML")}async handleNav(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.url;if(!r)return this.formatError("Missing required 'url' parameter");let s={url:r};e.timeout!==void 0&&(s.timeout=e.timeout);let i=await this.sendDaemonCommand(t,n,"nav",s);return i.ok?this.formatResult({ok:!0,url:i.result?.url,frameId:i.result?.frameId,loaderId:i.result?.loaderId,message:i.result?.message}):this.formatError(i.error??"Navigation failed")}async handleNet(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=await this.sendDaemonCommand(t,n,"net",{});return r.ok?this.formatResult({entries:r.result?.entries,count:r.result?.count}):this.formatError(r.error??"Failed to get network timing")}async handleClick(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.selector;if(!r)return this.formatError("Missing required 'selector' parameter");let s=await this.sendDaemonCommand(t,n,"click",{selector:r});return s.ok?this.formatResult({ok:!0,selector:r,tag:s.result?.tag,text:s.result?.text,message:s.result?.message}):this.formatError(s.error??"Click failed")}async handleClickxy(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.x,s=e.y;if(typeof r!="number"||typeof s!="number")return this.formatError("Missing required 'x' and 'y' parameters");let i=await this.sendDaemonCommand(t,n,"clickxy",{x:r,y:s});return i.ok?this.formatResult({ok:!0,x:r,y:s,message:`Clicked at (${r}, ${s})`}):this.formatError(i.error??"Click at coordinates failed")}async handleType(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.text;if(!r)return this.formatError("Missing required 'text' parameter");let s=await this.sendDaemonCommand(t,n,"type",{text:r});return s.ok?this.formatResult({ok:!0,text:r,message:`Typed ${r.length} character(s)`}):this.formatError(s.error??"Type failed")}async handleLoadall(e,t){let{targetId:n,wsUrl:r}=await this.resolveTarget(e.target),s=e.selector,i=e.interval??500;if(!s)return this.formatError("Missing required 'selector' parameter");let a=await this.sendDaemonCommand(n,r,"loadall",{selector:s,interval:i,timeout:3e5});return a.ok?this.formatResult({ok:!0,selector:s,clickCount:a.result?.clickCount,timedOut:a.result?.timedOut,message:a.result?.message}):this.formatError(a.error??"Loadall failed")}async handleEvalraw(e){let{targetId:t,wsUrl:n}=await this.resolveTarget(e.target),r=e.method,s=e.params??{};if(!r)return this.formatError("Missing required 'method' parameter");let i=await this.sendDaemonCommand(t,n,"evalraw",{method:r,params:s});return i.ok?this.formatResult({ok:!0,method:r,result:i.result?.result}):this.formatError(i.error??"Raw CDP command failed")}async resolveTarget(e){if(!e)throw new Error("Missing required 'target' parameter. Use 'chrome_session list' to see available targets.");let t=pn();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 Et(t)}catch{n=await Et(t)}let r=n.filter(l=>l.type==="page"&&!l.url.startsWith("chrome://")),s=e.toUpperCase(),i=r.filter(l=>l.id.toUpperCase().startsWith(s));if(i.length===0)throw new Error(`No target found matching prefix '${e}'`);if(i.length>1){let l=i.map(c=>c.id.slice(0,this.config.targetPrefixLength)).join(", ");throw new Error(`Ambiguous prefix '${e}' matches ${i.length} targets: ${l}`)}let a=i[0];return{targetId:a.id,wsUrl:a.webSocketDebuggerUrl}}async sendDaemonCommand(e,t,n,r){return await this.daemonManager.getOrCreateDaemon(e,t,{idleTimeoutMs:this.config.daemonIdleTimeoutS*1e3}),this.daemonManager.sendCommand(e,n,r)}resolveScreenshotPath(e){if(!e)return;let t;if(e.startsWith("/")?t=e:e.startsWith("./")||e.startsWith("../")?this.restrictToWorkspace&&this.workspace?t=bn(this.workspace,e):t=bn(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=bn(this.workspace,e):t=bn(ki(),`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=Si(e);wi(n)||vi(n,{recursive:!0});let r=Buffer.from(t,"base64");bi(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var It=class extends D{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 z from"node:fs";import _t from"node:path";import{randomUUID as xi}from"node:crypto";var Ci="automations",Ti="index.json";function Ai(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function br(o){return _t.join(o,Ci)}function wo(o){return _t.join(br(o),Ti)}function vn(o,e){return _t.join(br(o),e)}function vr(o,e){return _t.join(vn(o,e),"rule.json")}function wr(o,e){return _t.join(vn(o,e),"script.js")}function Sr(o){let e=br(o);z.existsSync(e)||z.mkdirSync(e,{recursive:!0})}function wn(o){Sr(o);let e=wo(o);if(!z.existsSync(e))return{rules:[]};try{let t=z.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=de(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=de(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&Sn(o,n),n}catch{return{rules:[]}}}function Sn(o,e){Sr(o);let t=wo(o),n=`${t}.tmp`;z.writeFileSync(n,JSON.stringify(e,null,2)),z.renameSync(n,t)}function lt(o){return wn(o).rules}function de(o,e){let t=vr(o,e);if(!z.existsSync(t))return null;try{let n=z.readFileSync(t,"utf-8"),r=JSON.parse(n),s=wr(o,e);return z.existsSync(s)&&(r.scriptContent=z.readFileSync(s,"utf-8")),r}catch{return null}}function kn(o,e){Sr(o);let t=Ai(e.name)||xi().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=vn(o,t);z.existsSync(s)||z.mkdirSync(s,{recursive:!0});let i=vr(o,t);z.writeFileSync(i,JSON.stringify(r,null,2));let a=So(r),l=wr(o,t);z.writeFileSync(l,a);let c=wn(o),u={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(u.toolType=e.toolType),c.rules.push(u),Sn(o,c),r}function xn(o,e,t){let n=de(o,e);if(!n)return null;let r=Date.now(),s={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:r,stepCount:(t.steps||n.steps).length},i=vr(o,e);if(z.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=So(s),u=wr(o,e);z.writeFileSync(u,c)}let a=wn(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,Sn(o,a)}return s}function ct(o,e){let t=vn(o,e);if(!z.existsSync(t))return!1;z.rmSync(t,{recursive:!0,force:!0});let n=wn(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(Sn(o,n),!0):!1}function So(o){let e=new Date().toISOString();return`// Automation: ${o.name}
192
+ - chrome_session evalraw --target "ABC123" --method "Page.getTitle" --params '{}'`;parameters={type:"object",properties:{command:{type:"string",description:"The command to execute",enum:["status","list","open","stop","snap","shot","eval","html","nav","net","click","clickxy","type","loadall","evalraw"]},target:{type:"string",description:"Target ID prefix (required for page interaction commands)"},url:{type:"string",description:"URL to open (for 'open' and 'nav' commands)"},path:{type:"string",description:"File path to save screenshot (for 'shot' command)"},selector:{type:"string",description:"CSS selector for element-specific operations (for 'shot', 'html', 'click', 'loadall' commands)"},expression:{type:"string",description:"JavaScript expression to evaluate (for 'eval' command)"},depth:{type:"number",description:"Maximum depth for accessibility tree (for 'snap' command)"},timeout:{type:"number",description:"Timeout in milliseconds (for 'nav' command)"},outer:{type:"boolean",description:"Return outer HTML (default true, for 'html' command)"},x:{type:"number",description:"X coordinate in CSS pixels (for 'clickxy' command)"},y:{type:"number",description:"Y coordinate in CSS pixels (for 'clickxy' command)"},text:{type:"string",description:"Text to type at focused element (for 'type' command)"},interval:{type:"number",description:"Interval in milliseconds between clicks (for 'loadall' command, default 500)"},method:{type:"string",description:"CDP method name (for 'evalraw' command)"},params:{type:"object",description:"CDP method parameters as JSON object (for 'evalraw' command)"}},required:["command"]};config;daemonManager;commands;workspace;restrictToWorkspace;constructor(e={},t,n=!1){super(),this.config={minChromeVersion:e.minChromeVersion??136,daemonIdleTimeoutS:e.daemonIdleTimeoutS??1200,targetPrefixLength:e.targetPrefixLength??8},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=At.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 Tt();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=$n();if(!e)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let t;try{let i=await fetch(`http://127.0.0.1:${e}/json/list`);i.ok?t=await i.json():t=await zt(e)}catch{t=await zt(e)}let n=t.filter(i=>i.type==="page"&&!i.url.startsWith("chrome://"));if(n.length===0)return this.formatResult({tabs:[],message:"No open tabs found"});let r=this.config.targetPrefixLength,s=n.map(i=>({id:i.id.slice(0,r),fullId:i.id,title:i.title,url:i.url}));return this.formatResult({tabs:s,count:s.length})}async handleOpen(e){let t=$n();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 Fo(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=$n();if(!t)throw new Error("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n;try{let l=await fetch(`http://127.0.0.1:${t}/json/list`);l.ok?n=await l.json():n=await zt(t)}catch{n=await zt(t)}let r=n.filter(l=>l.type==="page"&&!l.url.startsWith("chrome://")),s=e.toUpperCase(),i=r.filter(l=>l.id.toUpperCase().startsWith(s));if(i.length===0)throw new Error(`No target found matching prefix '${e}'`);if(i.length>1){let l=i.map(c=>c.id.slice(0,this.config.targetPrefixLength)).join(", ");throw new Error(`Ambiguous prefix '${e}' matches ${i.length} targets: ${l}`)}let a=i[0];return{targetId:a.id,wsUrl:a.webSocketDebuggerUrl}}async sendDaemonCommand(e,t,n,r){return await this.daemonManager.getOrCreateDaemon(e,t,{idleTimeoutMs:this.config.daemonIdleTimeoutS*1e3}),this.daemonManager.sendCommand(e,n,r)}resolveScreenshotPath(e){if(!e)return;let t;if(e.startsWith("/")?t=e:e.startsWith("./")||e.startsWith("../")?this.restrictToWorkspace&&this.workspace?t=Dn(this.workspace,e):t=Dn(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=Dn(this.workspace,e):t=Dn(Yi(),`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=Xi(e);Vi(n)||zi(n,{recursive:!0});let r=Buffer.from(t,"base64");Hi(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var Xt=class extends G{constructor(t){super();this.relay=t}name="chrome_relay";description="Control Chrome browser through the relay extension. Commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach.";parameters={type:"object",properties:{command:{type:"string",enum:["list_tabs","navigate","click","type","screenshot","read","evaluate","attach","detach"],description:"The command to execute"},tabId:{type:"number",description:"Tab ID for tab-specific commands"},url:{type:"string",description:"URL to navigate to"},selector:{type:"string",description:"CSS selector for click command"},text:{type:"string",description:"Text to type"},expression:{type:"string",description:"JavaScript expression to evaluate"},format:{type:"string",description:"Screenshot format (png or jpeg)"}},required:["command"]};async execute(t){let n=String(t.command??"");try{switch(n){case"list_tabs":{let r=await this.relay.listTabs();return JSON.stringify(r,null,2)}case"navigate":{let r=Number(t.tabId),s=String(t.url??"");return r?s?(await this.relay.navigate(r,s),`Navigated tab ${r} to ${s}`):"Error: url is required":"Error: tabId is required"}case"click":{let r=Number(t.tabId),s=String(t.selector??"");return r?s?(await this.relay.click(r,s),`Clicked "${s}" in tab ${r}`):"Error: selector is required":"Error: tabId is required"}case"type":{let r=Number(t.tabId),s=String(t.text??""),i=t.selector?String(t.selector):void 0;return r?s?(await this.relay.type(r,s,i),`Typed "${s}" in tab ${r}${i?` (selector: ${i})`:""}`):"Error: text is required":"Error: tabId is required"}case"screenshot":{let r=Number(t.tabId),s=String(t.format??"png");return r?`Screenshot captured: ${(await this.relay.screenshot(r,s)).slice(0,100)}...`:"Error: tabId is required"}case"read":{let r=Number(t.tabId);if(!r)return"Error: tabId is required";let s=await this.relay.evaluate(r,"document.body.innerText");return JSON.stringify(s,null,2)}case"evaluate":{let r=Number(t.tabId),s=String(t.expression??"");if(!r)return"Error: tabId is required";if(!s)return"Error: expression is required";let i=await this.relay.evaluate(r,s);return JSON.stringify(i,null,2)}case"attach":{let r=Number(t.tabId);return r?(await this.relay.attachTab(r),`Attached to tab ${r}`):"Error: tabId is required"}case"detach":{let r=Number(t.tabId);return r?(await this.relay.detachTab(r),`Detached from tab ${r}`):"Error: tabId is required"}default:return`Unknown command: ${n}. Available commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach`}}catch(r){return`Error: ${r instanceof Error?r.message:String(r)}`}}};import oe from"node:fs";import Yt from"node:path";import{randomUUID as Qi}from"node:crypto";var Zi="automations",ea="index.json";function ta(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function Dr(o){return Yt.join(o,Zi)}function Uo(o){return Yt.join(Dr(o),ea)}function jn(o,e){return Yt.join(Dr(o),e)}function jr(o,e){return Yt.join(jn(o,e),"rule.json")}function Fr(o,e){return Yt.join(jn(o,e),"script.js")}function Br(o){let e=Dr(o);oe.existsSync(e)||oe.mkdirSync(e,{recursive:!0})}function Fn(o){Br(o);let e=Uo(o);if(!oe.existsSync(e))return{rules:[]};try{let t=oe.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=ye(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=ye(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&Bn(o,n),n}catch{return{rules:[]}}}function Bn(o,e){Br(o);let t=Uo(o),n=`${t}.tmp`;oe.writeFileSync(n,JSON.stringify(e,null,2)),oe.renameSync(n,t)}function Et(o){return Fn(o).rules}function ye(o,e){let t=jr(o,e);if(!oe.existsSync(t))return null;try{let n=oe.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Fr(o,e);return oe.existsSync(s)&&(r.scriptContent=oe.readFileSync(s,"utf-8")),r}catch{return null}}function Gn(o,e){Br(o);let t=ta(e.name)||Qi().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=jn(o,t);oe.existsSync(s)||oe.mkdirSync(s,{recursive:!0});let i=jr(o,t);oe.writeFileSync(i,JSON.stringify(r,null,2));let a=Wo(r),l=Fr(o,t);oe.writeFileSync(l,a);let c=Fn(o),u={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(u.toolType=e.toolType),c.rules.push(u),Bn(o,c),r}function Un(o,e,t){let n=ye(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=jr(o,e);if(oe.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=Wo(s),u=Fr(o,e);oe.writeFileSync(u,c)}let a=Fn(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,Bn(o,a)}return s}function Pt(o,e){let t=jn(o,e);if(!oe.existsSync(t))return!1;oe.rmSync(t,{recursive:!0,force:!0});let n=Fn(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(Bn(o,n),!0):!1}function Wo(o){let e=new Date().toISOString();return`// Automation: ${o.name}
191
193
  // Tool: ${o.toolType??"auto-detect"}
192
194
  // Generated: ${e}
193
195
  // Description: ${o.description}
@@ -208,24 +210,24 @@ fetch(URL, { method: 'POST' })
208
210
  else console.error('Failed:', r.error);
209
211
  })
210
212
  .catch(e => console.error('Could not reach everclaw:', e.message));
211
- `}Ce();var ko={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"}},kr=o=>new Promise(e=>setTimeout(e,o)),dt=class extends D{constructor(t,n){super();this.browserTool=n;this.workspace=Y(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=lt(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=de(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let u=this.browserTool?.name,p;if(s){let y={name:i,description:a,steps:l,tags:c};return u&&(y.toolType=u),p=xn(this.workspace,s,y),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let y={name:i,description:a,steps:l,tags:c,source:"conversation"};return u&&(y.toolType=u),p=kn(this.workspace,y),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?ct(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=de(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),u=await this.executeStepWithRetries(c,n,i),p=this.maskSensitiveValues(u,t.variables);s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`)}catch(c){let u=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${u}`);else return s.push(` -> FAILED: ${u}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
213
+ `}Ae();var Ko={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"}},Gr=o=>new Promise(e=>setTimeout(e,o)),It=class extends G{constructor(t,n){super();this.browserTool=n;this.workspace=V(t)}name="automation";description="Manage browser automation workflows. Commands: list, get, save, delete, run.";parameters={type:"object",properties:{command:{type:"string",enum:["list","get","save","delete","run"],description:"The command to execute"},id:{type:"string",description:"Automation ID (for get, delete, run)"},name:{type:"string",description:"Automation name (for save)"},description:{type:"string",description:"Brief description (for save)"},steps:{type:"array",items:{type:"object",properties:{order:{type:"number"},action:{type:"string"},target:{type:"string"},value:{type:"string"},description:{type:"string"},optional:{type:"boolean"},assert:{type:"object",properties:{check:{type:"string",enum:["selector_exists","selector_text","url_contains","eval_truthy"]},value:{type:"string"},expected:{type:"string"},timeoutMs:{type:"number"}}},retries:{type:"number"},retryDelayMs:{type:"number"}}},description:"Automation steps (for save)"},tags:{type:"array",items:{type:"string"},description:"Optional tags (for save)"},enabled:{type:"boolean",description:"Enable/disable (for save)"},variables:{type:"object",description:'Variable overrides for run command (e.g., {"USERNAME": "user"})'}},required:["command"]};workspace;async execute(t,n){let r=String(t.command??"");try{switch(r){case"list":{let s=Et(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=ye(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let u=this.browserTool?.name,p;if(s){let h={name:i,description:a,steps:l,tags:c};return u&&(h.toolType=u),p=Un(this.workspace,s,h),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let h={name:i,description:a,steps:l,tags:c,source:"conversation"};return u&&(h.toolType=u),p=Gn(this.workspace,h),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?Pt(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=ye(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),u=await this.executeStepWithRetries(c,n,i),p=this.maskSensitiveValues(u,t.variables);s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`)}catch(c){let u=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${u}`);else return s.push(` -> FAILED: ${u}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
212
214
  `)}}return s.push(`Automation '${t.name}' completed successfully.`),s.join(`
213
- `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,u)=>{if(r&&r[u]!==void 0)return r[u];if(n&&n[u]?.defaultValue!==void 0)return n[u].defaultValue;if(n&&n[u]?.required)throw new Error(`Required variable '${u}' not provided`);return`\${${u}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await kr(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=ko[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"";break;case"read":break;case"screenshot":t.target&&(l.selector=t.target);break;case"eval":l.expression=t.value??"";break;case"wait":let c=parseInt(t.value??"1000",10);return await kr(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=ko[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let y={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(y.tabId=r.tabId),c==="chrome_session"&&r.target&&(y.target=r.target);let C=await this.browserTool.execute(y);if(this.isAssertionPassing(C,c))return}catch{}if(Date.now()-l>=s)break;await kr(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var Cn=class o{tools=new Map;guardEngine=null;register(e){this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}clear(){this.tools.clear()}get(e){return this.tools.get(e)}getDefinitions(){return[...this.tools.values()].map(e=>e.toSchema())}get toolNames(){return[...this.tools.keys()]}setGuardEngine(e){this.guardEngine=e}getGuardEngine(){return this.guardEngine}filterByNames(e){let t=new o;t.guardEngine=this.guardEngine;for(let n of e){let r=this.tools.get(n);r&&t.register(r)}return t}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{kind:"error",content:`Error: Tool '${e}' not found. Available: ${this.toolNames.join(", ")}`,retryable:!1};try{if(U(n?.signal),this.guardEngine){let a=this.guardEngine.guard(e,t);if(a&&!a.isSafe){let l=a.findings.map(c=>` - [${c.severity}] ${c.title}: ${c.description}`).join(`
215
+ `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,u)=>{if(r&&r[u]!==void 0)return r[u];if(n&&n[u]?.defaultValue!==void 0)return n[u].defaultValue;if(n&&n[u]?.required)throw new Error(`Required variable '${u}' not provided`);return`\${${u}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await Gr(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=Ko[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"";break;case"read":break;case"screenshot":t.target&&(l.selector=t.target);break;case"eval":l.expression=t.value??"";break;case"wait":let c=parseInt(t.value??"1000",10);return await Gr(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=Ko[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let h={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(h.tabId=r.tabId),c==="chrome_session"&&r.target&&(h.target=r.target);let T=await this.browserTool.execute(h);if(this.isAssertionPassing(T,c))return}catch{}if(Date.now()-l>=s)break;await Gr(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var Wn=class o{tools=new Map;guardEngine=null;register(e){this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}clear(){this.tools.clear()}get(e){return this.tools.get(e)}getDefinitions(){return[...this.tools.values()].map(e=>e.toSchema())}get toolNames(){return[...this.tools.keys()]}setGuardEngine(e){this.guardEngine=e}getGuardEngine(){return this.guardEngine}filterByNames(e){let t=new o;t.guardEngine=this.guardEngine;for(let n of e){let r=this.tools.get(n);r&&t.register(r)}return t}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{kind:"error",content:`Error: Tool '${e}' not found. Available: ${this.toolNames.join(", ")}`,retryable:!1};try{if(X(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(`
214
216
  `);return{kind:"error",content:`Security: Tool call blocked. The tool '${e}' was denied by the security guard.
215
217
 
216
218
  Findings:
217
219
  ${l}`,retryable:!1}}}let s=r.validateParams(t);if(s.length)return{kind:"error",content:`Error: Invalid parameters for tool '${e}': ${s.join("; ")}
218
220
 
219
- [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return U(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(J(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
221
+ [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return X(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(ee(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
220
222
 
221
- [Analyze the error above and try a different approach.]`,retryable:!0}}}};function xo(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Ri(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
223
+ [Analyze the error above and try a different approach.]`,retryable:!0}}}};function Jo(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function na(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
222
224
 
223
- `).trim()}function Ei(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 Tn=class extends D{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{U(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let u=(await l.json()).web?.results??[];if(!u.length)return`No results for: ${r}`;let p=[`Results for: ${r}`,""];return u.slice(0,s).forEach((y,C)=>{p.push(`${C+1}. ${y.title??""}`),p.push(` ${y.url??""}`),y.description&&p.push(` ${y.description}`)}),p.join(`
224
- `)}catch(a){if(J(a))throw a;return`Error: ${String(a)}`}}},An=class extends D{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]=Ei(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{U(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),u=c.headers.get("content-type")||"",p="",y="raw";if(u.includes("application/json"))p=JSON.stringify(await c.json(),null,2),y="json";else{let d=await c.text();u.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(d.slice(0,256))?(p=s==="text"?xo(d):Ri(xo(d)),y="html"):p=d}let C=p.length>i,w=C?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:y,truncated:C,length:w.length,text:w})}catch(c){if(J(c))throw c;return JSON.stringify({error:String(c),url:r})}}};function Re(o){return Pi.resolve(o.workspace)}function Rn(o){let e=Re(o);return o.restrictToWorkspace?e:void 0}function Ii(o){let e=[oe({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new tn(Re(t),Rn(t))},{name:"write_file",create:t=>new nn(Re(t),Rn(t))},{name:"edit_file",create:t=>new rn(Re(t),Rn(t))},{name:"list_dir",create:t=>new on(Re(t),Rn(t))}]}),oe({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new ln(t.execConfig?.timeout??60,Re(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new ce,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),oe({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new Tn(t.braveApiKey??null)},{name:"web_fetch",create:()=>new An}]})];return o.bus&&e.push(oe({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 an(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(oe({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 cn(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey),n}}]})),o.cronService&&e.push(oe({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 en(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(oe({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 un;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 mn;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 dn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(oe({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new qe(t.chromeSessionConfig,Re(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(oe({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 It(t.browserRelay)}}]})),e.push(oe({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new It(t.browserRelay):t.chromeSessionConfig?.enabled?new qe(t.chromeSessionConfig,Re(t),!!t.restrictToWorkspace):void 0;return new dt(Re(t),n)}}]})),e}function _i(o){return hr(Ii(o))}function En(o){let e=new Cn,t=_i(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function Mi(o){let e=[oe({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new At({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??Oe())}]})];return o.heartbeat&&e.push(oe({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new Rt(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 Oi(o){return hr(Mi(o))}function Ee(o){let e=Oi(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 At))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 Rt))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}var Co="EVERCLAW_SUBAGENT_RESULT ";function $i(){return`# Subagent
225
+ `).trim()}function ra(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 Kn=class extends G{constructor(t,n=5){super();this.apiKey=t;this.maxResults=n}name="web_search";description="Search the web. Returns titles, URLs, and snippets.";parameters={type:"object",properties:{query:{type:"string",description:"Search query"},count:{type:"integer",minimum:1,maximum:10,description:"Results (1-10)"}},required:["query"]};async execute(t,n){let r=String(t.query??""),s=Math.min(Math.max(Number(t.count??this.maxResults),1),10),i=this.apiKey||process.env.BRAVE_API_KEY||"";if(!i)return"Error: Brave Search API key not configured. Set tools.web.search.apiKey or BRAVE_API_KEY.";try{X(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let u=(await l.json()).web?.results??[];if(!u.length)return`No results for: ${r}`;let p=[`Results for: ${r}`,""];return u.slice(0,s).forEach((h,T)=>{p.push(`${T+1}. ${h.title??""}`),p.push(` ${h.url??""}`),h.description&&p.push(` ${h.description}`)}),p.join(`
226
+ `)}catch(a){if(ee(a))throw a;return`Error: ${String(a)}`}}},Jn=class extends G{constructor(t=5e4){super();this.maxChars=t}name="web_fetch";description="Fetch URL and extract readable content (HTML to markdown/text).";parameters={type:"object",properties:{url:{type:"string",description:"URL to fetch"},extractMode:{type:"string",enum:["markdown","text"]},maxChars:{type:"integer",minimum:100}},required:["url"]};async execute(t,n){let r=String(t.url??""),s=String(t.extractMode??"markdown"),i=Number(t.maxChars??this.maxChars),[a,l]=ra(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{X(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),u=c.headers.get("content-type")||"",p="",h="raw";if(u.includes("application/json"))p=JSON.stringify(await c.json(),null,2),h="json";else{let d=await c.text();u.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(d.slice(0,256))?(p=s==="text"?Jo(d):na(Jo(d)),h="html"):p=d}let T=p.length>i,v=T?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:h,truncated:T,length:v.length,text:v})}catch(c){if(ee(c))throw c;return JSON.stringify({error:String(c),url:r})}}};ct();function Fe(o){return oa.resolve(o.workspace)}function qn(o){let e=Fe(o);return o.restrictToWorkspace?e:void 0}function sa(o){let e=[ge({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new kn(Fe(t),qn(t))},{name:"write_file",create:t=>new xn(Fe(t),qn(t))},{name:"edit_file",create:t=>new Cn(Fe(t),qn(t))},{name:"list_dir",create:t=>new Tn(Fe(t),qn(t))}]}),ge({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new En(t.execConfig?.timeout??60,Fe(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new me,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),ge({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new Kn(t.braveApiKey??null)},{name:"web_fetch",create:()=>new Jn}]})];return o.bus&&e.push(ge({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 An(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(ge({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 Pn(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey),n}}]})),o.cronService&&e.push(ge({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 Sn(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(ge({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 Mn;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 _n;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 In;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(ge({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new ut(t.chromeSessionConfig,Fe(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(ge({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 Xt(t.browserRelay)}}]})),e.push(ge({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new Xt(t.browserRelay):t.chromeSessionConfig?.enabled?new ut(t.chromeSessionConfig,Fe(t),!!t.restrictToWorkspace):void 0;return new It(Fe(t),n)}}]})),e}function ia(o){return Lr(sa(o))}function Hn(o){let e=new Wn,t=ia(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function aa(o){let e=[ge({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new qt({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??qe())}]})];return o.heartbeat&&e.push(ge({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new Ht(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 la(o){return Lr(aa(o))}function Be(o){let e=la(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 qt))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 Ht))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}ct();var qo="EVERCLAW_SUBAGENT_RESULT ";function da(){return`# Subagent
225
227
 
226
228
  Current Time: ${new Date().toLocaleString()}
227
229
 
228
- You are a subagent spawned by the main agent to complete a specific task. Stay focused and concise.`}async function xr(o){let e=En({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig});o.allowedTools&&o.allowedTools.length>0&&(e=e.filterByNames(o.allowedTools));let t=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:$i()},{role:"user",content:o.task}],n="Task completed but no final response was generated.";for(let r=0;r<15;r++){U(o.signal);let s=await o.provider.chat({messages:t,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(U(o.signal),s.toolCalls.length){t.push({role:"assistant",content:s.content??"",tool_calls:s.toolCalls.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.arguments)}}))});for(let i of s.toolCalls){U(o.signal);let a=await e.execute(i.name,i.arguments,o.signal?{signal:o.signal}:{});U(o.signal);let l=typeof a=="object"&&"kind"in a?a.content??String(a):String(a);t.push({role:"tool",tool_call_id:i.id,name:i.name,content:l})}continue}n=s.content??n;break}return n}function Di(){let o=process.argv[1]??"";return it(o)}function Ni(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 ji(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(Co));if(e)try{return JSON.parse(e.slice(Co.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:Ni(o),failureAttribution:o.failureAttribution}}var Pn=class{constructor(e=new ce,t=Di){this.runner=e;this.resolveCommand=t}async execute(e){if(ot("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 ji(s)}},In=class{sessionManager;constructor(e){this.sessionManager=e}async execute(e){if(!e.provider)return{status:"failed",errorMessage:"Inline subagent execution requires a provider to be provided.",failureAttribution:"protocol"};try{let t;if(e.sessionKey&&!this.sessionManager&&console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`),e.sessionKey&&this.sessionManager){let r=this.sessionManager.getOrCreate(e.sessionKey);r&&(t=r.fork().getHistory())}return{status:"completed",finalResult:await xr({...e,provider:e.provider,existingMessages:t})}}catch(t){return J(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},_n=class{constructor(e,t,n,r){this.bus=e;this.processExecutor=t;this.inlineExecutor=n;this.settings=r}running=new Map;controllers=new Map;sessionTasks=new Map;sessionGenerations=new Map;async spawn(e){let t=Li().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s);let i=e.mode??"process",a=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName).finally(()=>{this.running.delete(t),this.controllers.delete(t);let l=this.sessionTasks.get(e.sessionKey);l&&(l.delete(t),l.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,a),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l){let c=this.controllers.get(e)?.signal,u=s==="inline"?this.inlineExecutor:this.processExecutor;try{let p={...this.settings,task:t};c&&(p.signal=c),i&&(p.provider=i),a&&(p.model=a),l&&(p.providerName=l);let y=await u.execute(p);if(y.status==="aborted"||!this.isSessionCurrent(r.sessionKey,r.generation))return;await this.publishOutcome(r,t,n,y)}catch(p){if(J(p)||!this.isSessionCurrent(r.sessionKey,r.generation))return;try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:p instanceof Error?p.message:String(p),failureAttribution:"exception"})}catch{}}}async publishOutcome(e,t,n,r){let s=r.status==="completed"?`[Subagent '${n}' completed successfully]
230
+ You are a subagent spawned by the main agent to complete a specific task. Stay focused and concise.`}async function Ur(o){let e=Hn({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig});o.allowedTools&&o.allowedTools.length>0&&(e=e.filterByNames(o.allowedTools));let t=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:da()},{role:"user",content:o.task}],n="Task completed but no final response was generated.";for(let r=0;r<15;r++){X(o.signal);let s=await o.provider.chat({messages:t,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(X(o.signal),s.toolCalls.length){t.push({role:"assistant",content:s.content??"",tool_calls:s.toolCalls.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.arguments)}}))});for(let i of s.toolCalls){X(o.signal);let a=await e.execute(i.name,i.arguments,o.signal?{signal:o.signal}:{});X(o.signal);let l=typeof a=="object"&&"kind"in a?a.content??String(a):String(a);t.push({role:"tool",tool_call_id:i.id,name:i.name,content:l})}continue}n=s.content??n;break}return n}function ua(){let o=process.argv[1]??"";return Rt(o)}function ga(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 ma(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(qo));if(e)try{return JSON.parse(e.slice(qo.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:ga(o),failureAttribution:o.failureAttribution}}var zn=class{constructor(e=new me,t=ua){this.runner=e;this.resolveCommand=t}async execute(e){if(lt("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 ma(s)}},Vn=class{sessionManager;constructor(e){this.sessionManager=e}async execute(e){if(!e.provider)return{status:"failed",errorMessage:"Inline subagent execution requires a provider to be provided.",failureAttribution:"protocol"};try{let t;if(e.sessionKey&&!this.sessionManager&&console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`),e.sessionKey&&this.sessionManager){let r=this.sessionManager.getOrCreate(e.sessionKey);r&&(t=r.fork().getHistory())}return{status:"completed",finalResult:await Ur({...e,provider:e.provider,existingMessages:t})}}catch(t){return ee(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},Xn=class{constructor(e,t,n,r){this.bus=e;this.processExecutor=t;this.inlineExecutor=n;this.settings=r}running=new Map;controllers=new Map;sessionTasks=new Map;sessionGenerations=new Map;async spawn(e){let t=ca().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s);let i=e.mode??"process",a=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName).finally(()=>{this.running.delete(t),this.controllers.delete(t);let l=this.sessionTasks.get(e.sessionKey);l&&(l.delete(t),l.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,a),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l){let c=this.controllers.get(e)?.signal,u=s==="inline"?this.inlineExecutor:this.processExecutor;try{let p={...this.settings,task:t};c&&(p.signal=c),i&&(p.provider=i),a&&(p.model=a),l&&(p.providerName=l);let h=await u.execute(p);if(h.status==="aborted"||!this.isSessionCurrent(r.sessionKey,r.generation))return;await this.publishOutcome(r,t,n,h)}catch(p){if(ee(p)||!this.isSessionCurrent(r.sessionKey,r.generation))return;try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:p instanceof Error?p.message:String(p),failureAttribution:"exception"})}catch{}}}async publishOutcome(e,t,n,r){let s=r.status==="completed"?`[Subagent '${n}' completed successfully]
229
231
 
230
232
  Task: ${t}
231
233
 
@@ -239,7 +241,7 @@ Task: ${t}
239
241
  Error:
240
242
  ${r.errorMessage??"The isolated subagent failed before producing a result."}
241
243
 
242
- Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:s};await this.bus.publishInbound(i)}async cancelBySession(e){this.sessionGenerations.set(e,this.getSessionGeneration(e)+1);let t=[...this.sessionTasks.get(e)??[]],n=0;for(let r of t){let s=this.controllers.get(r);!s||s.signal.aborted||(s.abort(),n+=1)}return n}async cancelAll(){let e=[...this.sessionTasks.keys()],t=0;for(let n of e)t+=await this.cancelBySession(n);return t}getRunningCount(){return this.running.size}getSessionGeneration(e){return this.sessionGenerations.get(e)??0}isSessionCurrent(e,t){return this.getSessionGeneration(e)===t}};var Mn=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 Cr(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import he from"node:fs";import On from"node:path";Ce();function ut(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function To(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Bi(o){try{let e=JSON.parse(o);return ut(e)?"metadata"in e||"last_consolidated"in e?{metadata:ut(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 Ln=class o{key;messages=[];createdAt=X();updatedAt=X();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let u=this.messages[c];if(u?._type==="anchor"){n=u,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(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 u={role:c.role,content:c.content??""};for(let p of["tool_calls","tool_call_id","name"])p in c&&(u[p]=c[p]);l.push(u)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=X()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:X()};return this.messages.push(n),this.updatedAt=X(),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=X(),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)}}},Le=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=Me(On.join(e,"sessions")),this.workspaceKey=t.workspaceKey??On.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return On.join(this.sessionsDir,`${Jr(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=we({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=ut(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=Bi(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=To(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
244
+ Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:s};await this.bus.publishInbound(i)}async cancelBySession(e){this.sessionGenerations.set(e,this.getSessionGeneration(e)+1);let t=[...this.sessionTasks.get(e)??[]],n=0;for(let r of t){let s=this.controllers.get(r);!s||s.signal.aborted||(s.abort(),n+=1)}return n}async cancelAll(){let e=[...this.sessionTasks.keys()],t=0;for(let n of e)t+=await this.cancelBySession(n);return t}getRunningCount(){return this.running.size}getSessionGeneration(e){return this.sessionGenerations.get(e)??0}isSessionCurrent(e,t){return this.getSessionGeneration(e)===t}};var Yn=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 Wr(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import Ce from"node:fs";import Qn from"node:path";Ae();function Mt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Ho(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function pa(o){try{let e=JSON.parse(o);return Mt(e)?"metadata"in e||"last_consolidated"in e?{metadata:Mt(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 Zn=class o{key;messages=[];createdAt=se();updatedAt=se();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let u=this.messages[c];if(u?._type==="anchor"){n=u,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(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 u={role:c.role,content:c.content??""};for(let p of["tool_calls","tool_call_id","name"])p in c&&(u[p]=c[p]);l.push(u)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=se()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:se()};return this.messages.push(n),this.updatedAt=se(),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=se(),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)}}},He=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=Ke(Qn.join(e,"sessions")),this.workspaceKey=t.workspaceKey??Qn.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return Qn.join(this.sessionsDir,`${uo(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Ee({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=Mt(t.metadata)?t.metadata:{},e.lastConsolidated=typeof t.last_consolidated=="number"?t.last_consolidated:0}applyPersistedRow(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt;let n=pa(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=Ho(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
243
245
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
244
246
  ) VALUES (?, ?, ?, ?, ?, ?, ?)
245
247
  ON CONFLICT(workspace, session_key) DO UPDATE SET
@@ -247,68 +249,66 @@ Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channe
247
249
  chat_id = excluded.chat_id,
248
250
  created_at = excluded.created_at,
249
251
  updated_at = excluded.updated_at,
250
- 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(!he.existsSync(e))return null;try{let t=he.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return ut(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!he.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
252
+ metadata_json = excluded.metadata_json`).run(this.workspaceKey,e.key,t,n,e.createdAt,e.updatedAt,JSON.stringify({metadata:e.metadata,last_consolidated:e.lastConsolidated}))}readLegacySessionMetadata(e){if(!Ce.existsSync(e))return null;try{let t=Ce.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return Mt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!Ce.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
251
253
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
252
- ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of he.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=On.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=To(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??X(),r.updated_at??r.created_at??X(),JSON.stringify({metadata:ut(r.metadata)?r.metadata:{},last_consolidated:typeof r.last_consolidated=="number"?r.last_consolidated:0}))}}readPersistedRow(e){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT created_at, updated_at, metadata_json
254
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of Ce.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=Qn.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=Ho(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??se(),r.updated_at??r.created_at??se(),JSON.stringify({metadata:Mt(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
253
255
  FROM session_metadata
254
- WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!he.existsSync(t))return null;try{let r=he.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let u=JSON.parse(c);if(!i&&ut(u)&&u._type==="metadata"){i=u;continue}s.push(u)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new Ln(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{he.writeFileSync(n,`${s.join(`
256
+ WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!Ce.existsSync(t))return null;try{let r=Ce.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let u=JSON.parse(c);if(!i&&Mt(u)&&u._type==="metadata"){i=u;continue}s.push(u)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new Zn(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{Ce.writeFileSync(n,`${s.join(`
255
257
  `)}
256
- `,"utf8"),he.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{he.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return he.existsSync(t)&&(he.unlinkSync(t),n=!0),this.getStorage().prepare("DELETE FROM session_metadata WHERE workspace = ? AND session_key = ?").run(this.workspaceKey,e),this.cache.delete(e),n}listSessions(){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT session_key, created_at, updated_at
258
+ `,"utf8"),Ce.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{Ce.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return Ce.existsSync(t)&&(Ce.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
257
259
  FROM session_metadata
258
260
  WHERE workspace = ?
259
- 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 Ln(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};bt();var Fi=[{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"}],Ui=/<\/?[a-zA-Z][^>]*\/?>/g,$n=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(Ui,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of Fi)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};bt();se();function Mt(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 Ao(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function Ro(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var Dn=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",Ao(this.options.providerLabel??"")]).has(Ao(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:Mt(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning_effort:"medium"}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=n.choices?.[0];if(!r?.message)return{content:`Error calling LLM: ${JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=(r.message.tool_calls??[]).map(i=>({id:i.id,name:i.function.name,arguments:Ro(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 Mt(e)){let r=String(n.role??"");if(r==="tool"){t.push({type:"function_call_output",call_id:String(n.tool_call_id??""),output:typeof n.content=="string"?n.content:JSON.stringify(n.content??null)});continue}if(r==="assistant"&&Array.isArray(n.tool_calls))for(let s of n.tool_calls)t.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:typeof s.arguments=="string"?s.arguments:JSON.stringify(s.arguments??{})});(r==="system"||r==="user"||r==="assistant")&&t.push({role:r,content:n.content??""})}return t}async responses(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/responses`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),input:this.toResponsesInput(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_output_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning:{effort:"medium"}}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=Array.isArray(n.output)?n.output:[],s=r.filter(a=>a?.type==="function_call").map(a=>({id:String(a.call_id??a.id??""),name:String(a.name??""),arguments:Ro(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(`
260
- `).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 U(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(J(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Gi}from"nanoid";var Nn=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let u=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let p of u){let y=p.function;y?.name&&l.push({functionCall:{name:y.name,args:this.parseToolArgs(y.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
261
+ ORDER BY updated_at DESC, session_key`).all(this.workspaceKey).map(t=>({key:t.session_key,created_at:t.created_at,updated_at:t.updated_at,path:this.getSessionPath(t.session_key)}))}load(e){let t=this.readPersistedRow(e),n=this.readTranscript(e);if(!t&&!n)return null;let r=new Zn(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};wt();var fa=[{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"}],ha=/<\/?[a-zA-Z][^>]*\/?>/g,er=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(ha,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of fa)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};wt();ue();function Qt(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 zo(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function Vo(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var tr=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",zo(this.options.providerLabel??"")]).has(zo(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:Qt(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning_effort:"medium"}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=n.choices?.[0];if(!r?.message)return{content:`Error calling LLM: ${JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=(r.message.tool_calls??[]).map(i=>({id:i.id,name:i.function.name,arguments:Vo(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 Qt(e)){let r=String(n.role??"");if(r==="tool"){t.push({type:"function_call_output",call_id:String(n.tool_call_id??""),output:typeof n.content=="string"?n.content:JSON.stringify(n.content??null)});continue}if(r==="assistant"&&Array.isArray(n.tool_calls))for(let s of n.tool_calls)t.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:typeof s.arguments=="string"?s.arguments:JSON.stringify(s.arguments??{})});(r==="system"||r==="user"||r==="assistant")&&t.push({role:r,content:n.content??""})}return t}async responses(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/responses`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),input:this.toResponsesInput(e.messages),tools:e.tools,tool_choice:e.tools?.length?"auto":void 0,max_output_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7,...e.reasoning?{reasoning:{effort:"medium"}}:{},...e.imageOutput?{include_image_output:!0}:{}}),...e.signal?{signal:e.signal}:{}}),n=await this.readJson(t);if(!t.ok)return{content:`Error calling LLM: ${n?.error?.message??JSON.stringify(n)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let r=Array.isArray(n.output)?n.output:[],s=r.filter(a=>a?.type==="function_call").map(a=>({id:String(a.call_id??a.id??""),name:String(a.name??""),arguments:Vo(a.arguments)}));return{content:r.filter(a=>a?.type==="message").flatMap(a=>Array.isArray(a?.content)?a.content:[]).filter(a=>a?.type==="output_text").map(a=>String(a.text??"")).join(`
262
+ `).trim()||null,toolCalls:s,finishReason:s.length?"tool_calls":n.status??"stop",usage:{prompt_tokens:n.usage?.input_tokens??0,completion_tokens:n.usage?.output_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:null}}async chat(e){try{return X(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(ee(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as ya}from"nanoid";var nr=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let u=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let p of u){let h=p.function;h?.name&&l.push({functionCall:{name:h.name,args:this.parseToolArgs(h.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
261
263
 
262
- `)}]});let s=(e.tools??[]).map(i=>i).filter(i=>i.type==="function"&&i.function?.name).map(i=>({name:i.function.name,description:i.function?.description??"",parameters:i.function?.parameters??{type:"object",properties:{}}}));return s.length&&(r.tools=[{functionDeclarations:s}],r.toolConfig={functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{U(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],u=c.filter(w=>typeof w?.text=="string").map(w=>String(w.text)),p=c.filter(w=>w?.functionCall?.name).map(w=>({id:Gi(9),name:String(w.functionCall.name),arguments:this.parseToolArgs(w.functionCall.args)})),y={};a?.usageMetadata&&(y.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),y.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),y.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let C=String(l?.finishReason??"STOP").toLowerCase();return{content:u.length?u.join(`
263
- `):null,toolCalls:p,finishReason:C,usage:y,reasoningContent:null}}catch(t){if(J(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Wi}from"nanoid";se();var jn=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",custom:"http://localhost:8000/v1"};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:Mt(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice="auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{U(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 ${Fe} 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??"",y=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${y}
264
- ${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: ${y}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let u=(c.message.tool_calls??[]).map(p=>({id:Wi(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:u,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(J(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function ye(o){let e=o.agents.defaults.model,t=We(o,e),n=Zr(o,e),r=t&&Ge(t)?Ze(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(Ge(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${Fe}.`);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"&&!Ge(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${Fe}.`);return t==="custom"||Ge(t)?new Dn(n?.apiKey||r?.apiKey||"no-key",Ht(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 Nn(n?.apiKey||"",Ht(o,e),e):new jn(n?.apiKey??null,Ht(o,e),e,t)}import{Client as Ji}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as Ki}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as qi}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as Hi}from"@modelcontextprotocol/sdk/client/sse.js";function Eo(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var 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(`
265
- `):String(c.content??"Unknown error")}`:Array.isArray(c.content)?c.content.map(p=>p.type==="text"?p.text:JSON.stringify(p)).filter(Boolean).join(`
266
- `)||"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 Ji({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=Eo(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${Eo(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 Ki({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 qi(s,{requestInit:{headers:a}})}catch{return new Hi(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 Fn=class extends D{constructor(t,n,r,s,i,a){super();this.serverName=t;this.remoteName=n;this.manager=a;this.name=r,this.description=s,this.parameters=i}name;description;parameters;validateParams(t){return[]}async execute(t,n){return this.manager.callTool(this.serverName,this.remoteName,t,n)}};function Tr(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function zi(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function Vi(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 mt=class o{constructor(e){this.input=e;let t=Po.resolve(e.workspace);this.context=new Ke(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new Le(t);this.sessions=n,this.lifecycle=e.lifecycle??Oe();let r=e.model??e.provider.getDefaultModel();this.subagents=new _n(e.bus,e.subagentExecutor??new Pn,e.subagentInlineExecutor??new In(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 Mn(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;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=zt(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=zt(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=zt(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:ye(r)}}getRuntimeState(){let e=this.runtime.snapshot();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(t=>t.queued>0).length,queuedMessages:e.queued,subagents:this.subagents.getRunningCount(),sessions:e.sessions,overload:{maxQueuedPerSession:e.maxQueuedPerKey,maxRequestsPerWindow:this.maxRequestsPerWindow,rateLimitWindowMs:this.rateLimitWindowMs,rateLimited:this.rateLimited,backpressured:e.backpressured,lastRateLimitedAt:this.lastRateLimitedAt,lastBackpressureAt:e.lastBackpressureAt}}}rateLimitMessage(e){return`This session is receiving messages too quickly. Please wait ${Math.max(1,Math.ceil(e/1e3))}s and try again.`}pruneRecentInbound(e,t=Date.now()){let n=(this.recentInboundBySession.get(e)??[]).filter(r=>t-r<this.rateLimitWindowMs);return n.length?this.recentInboundBySession.set(e,n):this.recentInboundBySession.delete(e),n}checkRateLimit(e){let t=Date.now(),n=this.pruneRecentInbound(e,t);if(n.length>=this.maxRequestsPerWindow){this.rateLimited+=1,this.lastRateLimitedAt=new Date(t).toISOString();let r=n[0];return r!=null?Math.max(1,this.rateLimitWindowMs-(t-r)):this.rateLimitWindowMs}return n.push(t),this.recentInboundBySession.set(e,n),null}makeDirectResult(e,t,n){return n==null?{outcome:e,content:t}:{outcome:e,content:t,retryAfterMs:n}}rejectIfOverloaded(e,t){if(e.channel==="system")return null;let n=this.checkRateLimit(t);return n==null?null:this.makeDirectResult("rate_limited",this.rateLimitMessage(n),n)}mapRuntimeResult(e){return e.status==="cancelled"?this.makeDirectResult("cancelled","Task was cancelled."):e.status==="rejected"?this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE):this.makeDirectResult("completed",e.value?.content??"")}async publishDirectResult(e,t,n){let r=t.outcome==="rate_limited"?{...n,_overload:t.outcome,_retry_after_ms:t.retryAfterMs??0}:t.outcome==="backpressure"?{...n,_overload:t.outcome}:n??{};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t.content,metadata:r})}async withAgentTurnLifecycle(e,t,n,r){await Ae(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 Ae(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:Po.resolve(this.input.workspace),restrictToWorkspace:!!this.input.restrictToWorkspace,braveApiKey:this.input.braveApiKey??null,execConfig:this.input.execConfig??{timeout:60,pathAppend:""},bus:this.input.bus,subagents:this.subagents,sessionManager:this.sessions};if(e&&(s.turn=e),this.input.cronService&&(s.cronService=this.input.cronService),this.input.rtkConfig&&(s.rtkConfig=this.input.rtkConfig),this.input.rtkService&&(s.rtkService=this.input.rtkService),this.input.browserRelay&&n&&(s.browserRelay=this.input.browserRelay),r){let a=this.input.chromeSessionConfig??t?.tools?.chromeSession;a&&(s.chromeSessionConfig=a)}let i=En(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i){let a=[...e],l=null,c=[],u=this.input.maxIterations??40,p=i?.model??this.model,y=i?.provider??this.input.provider,C=this.isToolCallingEnabled(p),w=this.isReasoningEnabled(p),d=this.isImageOutputEnabled(p),b=C?t.getDefinitions():void 0,k=AbortSignal.timeout(12e4),$=s?AbortSignal.any([s,k]):k;for(let j=0;j<u;j++){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};U(s);let M;try{M=await y.chat({messages:a,...b?{tools:b}:{},model:p,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...w?{reasoning:!0}:{},...d?{imageOutput:!0}:{},signal:$})}catch(q){if(J(q)){if(s?.aborted)throw q;return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1}}throw q}if(U(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let N=M.reasoningContent||zi(M.content);if(N&&n&&r()&&await n(N,{event:"thinking",thinkingContent:N,toolHint:!1}),M.toolCalls.length){let q=Tr(M.content);n&&q&&r()&&await n(q,{event:"answer",toolHint:!1});let ge=M.toolCalls.map(F=>({id:F.id,type:"function",function:{name:F.name,arguments:JSON.stringify(F.arguments)}}));n&&r()&&await n(this.toolHint(M.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:ge.map(F=>({...F,status:"running"}))}),this.context.addAssistantMessage(a,q,ge,N);for(let F of M.toolCalls){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};U(s),c.push(F.name);let H=await t.execute(F.name,F.arguments,s?{signal:s}:{});if(U(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let ne=H.kind==="cancelled"?"Task was cancelled.":H.content;if(this.context.addToolResult(a,F.id,F.name,ne),n&&r()&&await n(ne,{event:"tool_result",toolHint:!0,tool_call:{id:F.id,type:"function",function:{name:F.name,arguments:JSON.stringify(F.arguments)},status:"completed",resultPreview:Vi(ne,200)??null}}),H.kind==="terminal")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!1,terminal:!0};if(H.kind==="cancelled")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};if(H.kind==="error"&&!H.retryable)break}}else{l=Tr(M.content),l&&n&&r()&&await n(l,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(a,l,void 0,N);break}}return l==null&&(l=`I reached the maximum number of tool call iterations (${u}) without completing the task.`),{finalContent:l,toolsUsed:c,messages:a,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${Cr(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 u=await this.runtime.enqueue(t,({isCurrent:p})=>this.withSessionController(t,y=>this.processMessage(a,t,s,p,y,"direct")));return u.status==="completed"&&u.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(u)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(J(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??Cr(e),channel:e.channel,chatId:e.chatId,...n?{messageId:n}:{}}}memoryNamespace(e){return e.includes(":")&&e.replace(/:/g,"_")||void 0}async consolidateMemory(e,t=!1,n=this.input.provider,r=this.model){return this.context.getMemoryStore(this.memoryNamespace(e.key)).consolidate(e,n,r,{archiveAll:t,memoryWindow:this.input.memoryWindow??100})}saveTurn(e,t,n,r){let s=t.slice(n);for(let i=0;i<s.length;i++){let l={...s[i]};l.role==="assistant"&&typeof l.content=="string"&&(l.content=Tr(l.content)),l.role==="tool"&&typeof l.content=="string"&&l.content.length>o.TOOL_RESULT_MAX_CHARS&&(l._full_content=l.content,l.content=`${l.content.slice(0,o.TOOL_RESULT_MAX_CHARS)}
267
- ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(Ke.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 $n(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){return e==="/new"?t.messages.length&&!await this.consolidateMemory(t,!0,r.provider,r.model)?{response:{channel:n.channel,chatId:n.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(t.clear(),this.sessions.save(t),this.sessions.invalidate(t.key),{response:{channel:n.channel,chatId:n.chatId,content:"New session started."},cancelled:!1}):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
264
+ `)}]});let s=(e.tools??[]).map(i=>i).filter(i=>i.type==="function"&&i.function?.name).map(i=>({name:i.function.name,description:i.function?.description??"",parameters:i.function?.parameters??{type:"object",properties:{}}}));return s.length&&(r.tools=[{functionDeclarations:s}],r.toolConfig={functionCallingConfig:{mode:"AUTO"}}),e.imageOutput&&(r.responseModalities=["TEXT","IMAGE"]),r}async chat(e){try{X(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],u=c.filter(v=>typeof v?.text=="string").map(v=>String(v.text)),p=c.filter(v=>v?.functionCall?.name).map(v=>({id:ya(9),name:String(v.functionCall.name),arguments:this.parseToolArgs(v.functionCall.args)})),h={};a?.usageMetadata&&(h.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),h.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),h.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let T=String(l?.finishReason??"STOP").toLowerCase();return{content:u.length?u.join(`
265
+ `):null,toolCalls:p,finishReason:T,usage:h,reasoningContent:null}}catch(t){if(ee(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as ba}from"nanoid";ue();var rr=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:Qt(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice="auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{X(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 ${nt} or run everclaw onboard.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(`${s.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(n),...e.signal?{signal:e.signal}:{}}),l=await a.json();if(!a.ok){let p=l?.error?.code??"",h=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${h}
266
+ ${r==="groq"?"Try a Groq-supported model like llama-3.3-70b-versatile or openai/gpt-oss-120b. You can run `everclaw doctor`.":"Check your model id and provider access. You can run `everclaw doctor`."}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}:{content:`Error calling LLM: ${h}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let u=(c.message.tool_calls??[]).map(p=>({id:ba(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:u,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(ee(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function Te(o){let e=o.agents.defaults.model,t=Je(o,e),n=vo(o,e),r=t&&ot(t)?vt(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(ot(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${nt}.`);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"&&!ot(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${nt}.`);return t==="custom"||ot(t)?new tr(n?.apiKey||r?.apiKey||"no-key",pn(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 nr(n?.apiKey||"",pn(o,e),e):new rr(n?.apiKey??null,pn(o,e),e,t)}en();var sr=class extends G{constructor(t,n,r,s,i,a){super();this.serverName=t;this.remoteName=n;this.manager=a;this.name=r,this.description=s,this.parameters=i}name;description;parameters;validateParams(t){return[]}async execute(t,n){return this.manager.callTool(this.serverName,this.remoteName,t,n)}};function Kr(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function xa(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function Ca(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 _t=class o{constructor(e){this.input=e;let t=Yo.resolve(e.workspace);this.context=new at(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new He(t);this.sessions=n,this.lifecycle=e.lifecycle??qe();let r=e.model??e.provider.getDefaultModel();this.subagents=new Xn(e.bus,e.subagentExecutor??new zn,e.subagentInlineExecutor??new Vn(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 Yn(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 Zt;recentInboundBySession=new Map;static CANCELLED_SENTINEL=Symbol("cancelled");static TOOL_RESULT_MAX_CHARS=500;static SHUTDOWN_MESSAGE="Gateway is shutting down. Please try again later.";static SESSION_BUSY_MESSAGE="This session is busy right now. Please wait for the current response before sending more messages.";static DEFAULT_MAX_QUEUED_PER_SESSION=1;static DEFAULT_MAX_REQUESTS_PER_WINDOW=6;static DEFAULT_RATE_LIMIT_WINDOW_MS=3e4;maxRequestsPerWindow;rateLimitWindowMs;rateLimited=0;lastRateLimitedAt=null;get model(){return this.input.model??this.input.provider.getDefaultModel()}get channelsConfig(){return this.input.channelsConfig}isToolCallingEnabled(e=this.model){if(!this.input.loadConfig)return!0;let t=this.input.loadConfig(),n=fn(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=fn(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=fn(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:Te(r)}}getRuntimeState(){let e=this.runtime.snapshot();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(t=>t.queued>0).length,queuedMessages:e.queued,subagents:this.subagents.getRunningCount(),sessions:e.sessions,overload:{maxQueuedPerSession:e.maxQueuedPerKey,maxRequestsPerWindow:this.maxRequestsPerWindow,rateLimitWindowMs:this.rateLimitWindowMs,rateLimited:this.rateLimited,backpressured:e.backpressured,lastRateLimitedAt:this.lastRateLimitedAt,lastBackpressureAt:e.lastBackpressureAt}}}rateLimitMessage(e){return`This session is receiving messages too quickly. Please wait ${Math.max(1,Math.ceil(e/1e3))}s and try again.`}pruneRecentInbound(e,t=Date.now()){let n=(this.recentInboundBySession.get(e)??[]).filter(r=>t-r<this.rateLimitWindowMs);return n.length?this.recentInboundBySession.set(e,n):this.recentInboundBySession.delete(e),n}checkRateLimit(e){let t=Date.now(),n=this.pruneRecentInbound(e,t);if(n.length>=this.maxRequestsPerWindow){this.rateLimited+=1,this.lastRateLimitedAt=new Date(t).toISOString();let r=n[0];return r!=null?Math.max(1,this.rateLimitWindowMs-(t-r)):this.rateLimitWindowMs}return n.push(t),this.recentInboundBySession.set(e,n),null}makeDirectResult(e,t,n){return n==null?{outcome:e,content:t}:{outcome:e,content:t,retryAfterMs:n}}rejectIfOverloaded(e,t){if(e.channel==="system")return null;let n=this.checkRateLimit(t);return n==null?null:this.makeDirectResult("rate_limited",this.rateLimitMessage(n),n)}mapRuntimeResult(e){return e.status==="cancelled"?this.makeDirectResult("cancelled","Task was cancelled."):e.status==="rejected"?this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE):this.makeDirectResult("completed",e.value?.content??"")}async publishDirectResult(e,t,n){let r=t.outcome==="rate_limited"?{...n,_overload:t.outcome,_retry_after_ms:t.retryAfterMs??0}:t.outcome==="backpressure"?{...n,_overload:t.outcome}:n??{};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t.content,metadata:r})}async withAgentTurnLifecycle(e,t,n,r){await je(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 je(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:Yo.resolve(this.input.workspace),restrictToWorkspace:!!this.input.restrictToWorkspace,braveApiKey:this.input.braveApiKey??null,execConfig:this.input.execConfig??{timeout:60,pathAppend:""},bus:this.input.bus,subagents:this.subagents,sessionManager:this.sessions};if(e&&(s.turn=e),this.input.cronService&&(s.cronService=this.input.cronService),this.input.rtkConfig&&(s.rtkConfig=this.input.rtkConfig),this.input.rtkService&&(s.rtkService=this.input.rtkService),this.input.browserRelay&&n&&(s.browserRelay=this.input.browserRelay),r){let a=this.input.chromeSessionConfig??t?.tools?.chromeSession;a&&(s.chromeSessionConfig=a)}let i=Hn(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i){let a=[...e],l=null,c=[],u=this.input.maxIterations??40,p=i?.model??this.model,h=i?.provider??this.input.provider,T=this.isToolCallingEnabled(p),v=this.isReasoningEnabled(p),d=this.isImageOutputEnabled(p),b=T?t.getDefinitions():void 0,w=AbortSignal.timeout(12e4),F=s?AbortSignal.any([s,w]):w;for(let A=0;A<u;A++){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};X(s);let N;try{N=await h.chat({messages:a,...b?{tools:b}:{},model:p,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...v?{reasoning:!0}:{},...d?{imageOutput:!0}:{},signal:F})}catch(D){if(ee(D)){if(s?.aborted)throw D;return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1}}throw D}if(X(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let U=N.reasoningContent||xa(N.content);if(U&&n&&r()&&await n(U,{event:"thinking",thinkingContent:U,toolHint:!1}),N.toolCalls.length){let D=Kr(N.content);n&&D&&r()&&await n(D,{event:"answer",toolHint:!1});let ie=N.toolCalls.map(W=>({id:W.id,type:"function",function:{name:W.name,arguments:JSON.stringify(W.arguments)}}));n&&r()&&await n(this.toolHint(N.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:ie.map(W=>({...W,status:"running"}))}),this.context.addAssistantMessage(a,D,ie,U);for(let W of N.toolCalls){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};X(s),c.push(W.name);let Q=await t.execute(W.name,W.arguments,s?{signal:s}:{});if(X(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let E=Q.kind==="cancelled"?"Task was cancelled.":Q.content;if(this.context.addToolResult(a,W.id,W.name,E),n&&r()&&await n(E,{event:"tool_result",toolHint:!0,tool_call:{id:W.id,type:"function",function:{name:W.name,arguments:JSON.stringify(W.arguments)},status:"completed",resultPreview:Ca(E,200)??null}}),Q.kind==="terminal")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!1,terminal:!0};if(Q.kind==="cancelled")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};if(Q.kind==="error"&&!Q.retryable)break}}else{l=Kr(N.content),l&&n&&r()&&await n(l,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(a,l,void 0,U);break}}return l==null&&(l=`I reached the maximum number of tool call iterations (${u}) without completing the task.`),{finalContent:l,toolsUsed:c,messages:a,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${Wr(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 u=await this.runtime.enqueue(t,({isCurrent:p})=>this.withSessionController(t,h=>this.processMessage(a,t,s,p,h,"direct")));return u.status==="completed"&&u.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(u)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(ee(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??Wr(e),channel:e.channel,chatId:e.chatId,...n?{messageId:n}:{}}}memoryNamespace(e){return e.includes(":")&&e.replace(/:/g,"_")||void 0}async consolidateMemory(e,t=!1,n=this.input.provider,r=this.model){return this.context.getMemoryStore(this.memoryNamespace(e.key)).consolidate(e,n,r,{archiveAll:t,memoryWindow:this.input.memoryWindow??100})}saveTurn(e,t,n,r){let s=t.slice(n);for(let i=0;i<s.length;i++){let l={...s[i]};l.role==="assistant"&&typeof l.content=="string"&&(l.content=Kr(l.content)),l.role==="tool"&&typeof l.content=="string"&&l.content.length>o.TOOL_RESULT_MAX_CHARS&&(l._full_content=l.content,l.content=`${l.content.slice(0,o.TOOL_RESULT_MAX_CHARS)}
267
+ ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(at.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 er(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){return e==="/new"?t.messages.length&&!await this.consolidateMemory(t,!0,r.provider,r.model)?{response:{channel:n.channel,chatId:n.chatId,content:"Memory archival failed, session not cleared. Please try again."},cancelled:!1}:(t.clear(),this.sessions.save(t),this.sessions.invalidate(t.key),{response:{channel:n.channel,chatId:n.chatId,content:"New session started."},cancelled:!1}):e==="/help"?{response:{channel:n.channel,chatId:n.chatId,content:`everclaw commands:
268
268
  /new - Start a new conversation
269
269
  /stop - Stop the current task
270
- /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n){let r=this.createToolRegistry(t);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let s of n)try{let i=await this.mcpManager.getServerTools(s);for(let a of i)r.register(new Fn(a.serverName,a.remoteName,a.proxyName,a.description,a.inputSchema,this.mcpManager))}catch(i){console.warn(`MCP: failed to connect to '${s}': ${String(i)}`)}}return r}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(Se);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),u=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let{messages:W,newMessageStartIndex:Z}=this.buildTurnPrompt(c,e,l,[]),g=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[]),{finalContent:m,messages:f,toolsUsed:v,cancelled:S,terminal:A}=await this.runAgentLoop(W,g,void 0,r,s,u);return S||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,f,Z,v),{response:{channel:a.channel,chatId:a.chatId,content:m??"Background task completed."},cancelled:!1})}let y=(typeof e.content=="string"?e.content:e.content.find(W=>W.type==="text")?.text??"").trim().toLowerCase(),C=await this.resolveCommand(y,c,e,u);if(C)return C;let d=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],I=new Set(Object.keys(l?.tools?.mcpServers??{})),k=b.filter(W=>I.has(W)),$=b.filter(W=>!I.has(W)),j=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},k),{messages:M,newMessageStartIndex:N}=this.buildTurnPrompt(c,e,l,$),q=async(W,Z)=>{if(!r())return;let g={...e.metadata,_progress:!0,_tool_hint:!!Z?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:W,metadata:g})},{finalContent:ge,messages:F,toolsUsed:H,cancelled:ne,terminal:L}=await this.runAgentLoop(M,j,n??q,r,s,u);if(ne||!r())return{response:null,cancelled:!0};let Q=ge??"I've completed processing but have no response to give.";if(this.commitTurn(c,F,N,H),d){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,u.provider,u.model)}finally{this.consolidating.delete(c.key)}}return L?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:Q,metadata:e.metadata??{}},cancelled:!1}})}};ur();var Xi=1024*1024,Yi=300*1e3;function Io(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function Qi(o,e,t){let n=Io(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
270
+ /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n){let r=this.createToolRegistry(t);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let s of n)try{let i=await this.mcpManager.getServerTools(s);for(let a of i)r.register(new sr(a.serverName,a.remoteName,a.proxyName,a.description,a.inputSchema,this.mcpManager))}catch(i){console.warn(`MCP: failed to connect to '${s}': ${String(i)}`)}}return r}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(pe);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),u=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let{messages:K,newMessageStartIndex:ne}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[]),{finalContent:g,messages:f,toolsUsed:S,cancelled:x,terminal:P}=await this.runAgentLoop(K,m,void 0,r,s,u);return x||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,f,ne,S),{response:{channel:a.channel,chatId:a.chatId,content:g??"Background task completed."},cancelled:!1})}let h=(typeof e.content=="string"?e.content:e.content.find(K=>K.type==="text")?.text??"").trim().toLowerCase(),T=await this.resolveCommand(h,c,e,u);if(T)return T;let d=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],_=new Set(Object.keys(l?.tools?.mcpServers??{})),w=b.filter(K=>_.has(K)),F=b.filter(K=>!_.has(K)),A=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},w),{messages:N,newMessageStartIndex:U}=this.buildTurnPrompt(c,e,l,F),D=async(K,ne)=>{if(!r())return;let m={...e.metadata,_progress:!0,_tool_hint:!!ne?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:K,metadata:m})},{finalContent:ie,messages:W,toolsUsed:Q,cancelled:E,terminal:M}=await this.runAgentLoop(N,A,n??D,r,s,u);if(E||!r())return{response:null,cancelled:!0};let j=ie??"I've completed processing but have no response to give.";if(this.commitTurn(c,W,U,Q),d){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,u.provider,u.model)}finally{this.consolidating.delete(c.key)}}return M?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:j,metadata:e.metadata??{}},cancelled:!1}})}};Er();ct();var Ta=1024*1024,Ra=300*1e3;function Qo(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function Aa(o,e,t){let n=Qo(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
271
271
  ${t.stdout.trim()}`:"",t.stderr.trim()?`STDERR:
272
272
  ${t.stderr.trim()}`:"",typeof t.exitCode=="number"?`Exit code: ${t.exitCode}`:"",t.signal?`Signal: ${t.signal}`:"",t.errorMessage?`Error: ${t.errorMessage}`:""].filter(Boolean).join(`
273
273
  `);return r?`${n} failed
274
- ${r}`:`${n} failed`}function Zi(){let o=process.argv[1]??"";return it(o)}function Un(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(Yi,e)}var Ar=class{constructor(e,t,n,r=new ce,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(ot(this.target).mode!=="local-process")throw new Error(`${Io(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??Xi});if(n.status==="aborted")throw Tt();if(n.status==="ok")return n.stdout;throw new Error(Qi(this.target,this.timeoutMs,n))}};function Ot(o){let e=Zi();return new Ar(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 gt=class o{constructor(e,t,n){this.config=e;this.bus=t;this.debounce=n}running=!1;isAllowed(e){let t=this.config?.allowFrom??[];return!t.length||t.includes(String(e))?!0:String(e).includes("|")?String(e).split("|").some(n=>t.includes(n)):!1}static channelColors={telegram:"\x1B[36m",discord:"\x1B[35m"};async handleMessage(e){let t=typeof e.content=="string"?e.content:JSON.stringify(e.content),n=o.channelColors[this.name]??"\x1B[0m",r=t.length>80?t.slice(0,80)+"\u2026":t;if(!this.isAllowed(e.senderId)){console.log(`[${n}${this.name}\x1B[0m] \x1B[31mBLOCKED\x1B[0m from=${e.senderId}`);return}console.log(`[${n}${this.name}\x1B[0m] from=${e.senderId} chat=${e.chatId} "${r}"`);let s={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(s.media=e.media),e.metadata&&Object.keys(e.metadata).length>0&&(s.metadata=e.metadata),e.sessionKey&&(s.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(s)}get isRunning(){return this.running}};var pt=class{buffers=new Map;config;onEmit;constructor(e,t){this.config=e,this.onEmit=t}submit(e){if(!this.config.enabled){this.onEmit(e);return}let t=`${e.channel}:${e.chatId}`,n=this.buffers.get(t);if(n){clearTimeout(n.quietTimer),n.messages.push(e),n.quietTimer=setTimeout(()=>this.emit(t),this.config.quietMs);return}let r=setTimeout(()=>this.emit(t),this.config.quietMs),s=setTimeout(()=>this.emit(t),this.config.maxWaitMs);this.buffers.set(t,{messages:[e],quietTimer:r,maxTimer:s})}emit(e){let t=this.buffers.get(e);if(!t)return;clearTimeout(t.quietTimer),clearTimeout(t.maxTimer),this.buffers.delete(e);let n=t.messages[0];if(!n)return;let r=t.messages.map(a=>typeof a.content=="string"?a.content:a.content.find(c=>c.type==="text")?.text??JSON.stringify(a.content)).join(`
275
- `),s=t.messages.flatMap(a=>a.media??[]),i=t.messages.reduce((a,l)=>({...a,...l.metadata??{}}),{});this.onEmit({...n,content:r,media:s.length>0?s:void 0,metadata:Object.keys(i).length>0?i:void 0})}flush(){for(let e of this.buffers.keys())this.emit(e)}get size(){return this.buffers.size}};function ea(o,e=4e3){if(o.length<=e)return[o];let t=[],n=o;for(;n.length>e;){let r=n.slice(0,e),s=Math.max(r.lastIndexOf(`
276
- `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}var Gn=class extends gt{name="telegram";offset=0;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new pt(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=s.text??s.caption??"[Unsupported message]";this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:{message_id:s.message_id}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;let t=ea(e.content||"");for(let n of t){let r={chat_id:e.chatId,text:n},s=e.metadata?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s}),await fetch(this.api("sendMessage"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}).catch(()=>{})}}};import _o from"ws";var Wn=class extends gt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new pt(e.debounce,n=>this.handleMessage(n))}async start(){if(!this.config.token){console.error("Discord token not configured");return}for(this.running=!0;this.running;){try{await this.connectOnce()}catch{}this.running&&await new Promise(e=>setTimeout(e,2e3))}}async stop(){if(this.running=!1,this.hb&&(clearInterval(this.hb),this.hb=null),this.ws){try{this.ws.close()}catch{}this.ws=null}}async send(e){this.config.token&&await fetch(`https://discord.com/api/v10/channels/${e.chatId}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify({content:e.content||""})}).catch(()=>{})}async connectOnce(){await new Promise(e=>{let t=new _o(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!==_o.OPEN||this.ws.send(JSON.stringify(e))}};var Mo="_shutdown",Jn=class{constructor(e,t,n){this.config=e;this.bus=t;this.lifecycle=n??Oe(),this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new Gn(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new Wn(this.config.channels.discord,this.bus))}async startAll(){this.channels.size&&(this.stopping=!1,this.dispatchLoop=this.dispatchOutbound(),await Promise.all([...this.channels.values()].map(e=>e.start().catch(()=>{}))))}async stopAll(){this.stopping=!0,await Promise.all([...this.channels.values()].map(e=>e.stop().catch(()=>{}))),this.dispatchLoop&&(await this.bus.publishOutbound({channel:"system",chatId:"gateway:shutdown",content:"",metadata:{[Mo]:!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?.[Mo])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await Ae(this.lifecycle.beforeOutbound,"beforeOutbound",{message:e,hasChannel:t,skippedReason:n})}catch(i){s=i,console.warn(String(i))}if(!s&&!n){let i=this.channels.get(e.channel);if(i)try{await i.send(e),r=!0}catch(a){s=a}}try{await Ae(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}]))}};et();import{randomUUID as ta}from"node:crypto";import na from"node:path";function ra(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 oa(o){return na.resolve(o)}function Oo(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:ra(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var ft=class{storage;workspace;constructor(e,t,n){this.workspace=oa(e),this.storage=n??we({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
274
+ ${r}`:`${n} failed`}function Ea(){let o=process.argv[1]??"";return Rt(o)}function ir(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(Ra,e)}var Jr=class{constructor(e,t,n,r=new me,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(lt(this.target).mode!=="local-process")throw new Error(`${Qo(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??Ta});if(n.status==="aborted")throw Jt();if(n.status==="ok")return n.stdout;throw new Error(Aa(this.target,this.timeoutMs,n))}};function tn(o){let e=Ea();return new Jr(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 Ot=class o{constructor(e,t,n){this.config=e;this.bus=t;this.debounce=n}running=!1;isAllowed(e){let t=this.config?.allowFrom??[];return!t.length||t.includes(String(e))?!0:String(e).includes("|")?String(e).split("|").some(n=>t.includes(n)):!1}static channelColors={telegram:"\x1B[36m",discord:"\x1B[35m"};async handleMessage(e){let t=typeof e.content=="string"?e.content:JSON.stringify(e.content),n=o.channelColors[this.name]??"\x1B[0m",r=t.length>80?t.slice(0,80)+"\u2026":t;if(!this.isAllowed(e.senderId)){console.log(`[${n}${this.name}\x1B[0m] \x1B[31mBLOCKED\x1B[0m from=${e.senderId}`);return}console.log(`[${n}${this.name}\x1B[0m] from=${e.senderId} chat=${e.chatId} "${r}"`);let s={channel:this.name,senderId:String(e.senderId),chatId:String(e.chatId),content:e.content};e.media&&e.media.length>0&&(s.media=e.media),e.metadata&&Object.keys(e.metadata).length>0&&(s.metadata=e.metadata),e.sessionKey&&(s.sessionKeyOverride=e.sessionKey),await this.bus.publishInbound(s)}get isRunning(){return this.running}};var $t=class{buffers=new Map;config;onEmit;constructor(e,t){this.config=e,this.onEmit=t}submit(e){if(!this.config.enabled){this.onEmit(e);return}let t=`${e.channel}:${e.chatId}`,n=this.buffers.get(t);if(n){clearTimeout(n.quietTimer),n.messages.push(e),n.quietTimer=setTimeout(()=>this.emit(t),this.config.quietMs);return}let r=setTimeout(()=>this.emit(t),this.config.quietMs),s=setTimeout(()=>this.emit(t),this.config.maxWaitMs);this.buffers.set(t,{messages:[e],quietTimer:r,maxTimer:s})}emit(e){let t=this.buffers.get(e);if(!t)return;clearTimeout(t.quietTimer),clearTimeout(t.maxTimer),this.buffers.delete(e);let n=t.messages[0];if(!n)return;let r=t.messages.map(a=>typeof a.content=="string"?a.content:a.content.find(c=>c.type==="text")?.text??JSON.stringify(a.content)).join(`
275
+ `),s=t.messages.flatMap(a=>a.media??[]),i=t.messages.reduce((a,l)=>({...a,...l.metadata??{}}),{});this.onEmit({...n,content:r,media:s.length>0?s:void 0,metadata:Object.keys(i).length>0?i:void 0})}flush(){for(let e of this.buffers.keys())this.emit(e)}get size(){return this.buffers.size}};function Pa(o,e=4e3){if(o.length<=e)return[o];let t=[],n=o;for(;n.length>e;){let r=n.slice(0,e),s=Math.max(r.lastIndexOf(`
276
+ `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}var ar=class extends Ot{name="telegram";offset=0;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new $t(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=s.text??s.caption??"[Unsupported message]";this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:{message_id:s.message_id}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;let t=Pa(e.content||"");for(let n of t){let r={chat_id:e.chatId,text:n},s=e.metadata?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s}),await fetch(this.api("sendMessage"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}).catch(()=>{})}}};import Zo from"ws";var lr=class extends Ot{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new $t(e.debounce,n=>this.handleMessage(n))}async start(){if(!this.config.token){console.error("Discord token not configured");return}for(this.running=!0;this.running;){try{await this.connectOnce()}catch{}this.running&&await new Promise(e=>setTimeout(e,2e3))}}async stop(){if(this.running=!1,this.hb&&(clearInterval(this.hb),this.hb=null),this.ws){try{this.ws.close()}catch{}this.ws=null}}async send(e){this.config.token&&await fetch(`https://discord.com/api/v10/channels/${e.chatId}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.config.token}`,"Content-Type":"application/json"},body:JSON.stringify({content:e.content||""})}).catch(()=>{})}async connectOnce(){await new Promise(e=>{let t=new Zo(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!==Zo.OPEN||this.ws.send(JSON.stringify(e))}};var es="_shutdown",cr=class{constructor(e,t,n){this.config=e;this.bus=t;this.lifecycle=n??qe(),this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new ar(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new lr(this.config.channels.discord,this.bus))}async startAll(){this.channels.size&&(this.stopping=!1,this.dispatchLoop=this.dispatchOutbound(),await Promise.all([...this.channels.values()].map(e=>e.start().catch(()=>{}))))}async stopAll(){this.stopping=!0,await Promise.all([...this.channels.values()].map(e=>e.stop().catch(()=>{}))),this.dispatchLoop&&(await this.bus.publishOutbound({channel:"system",chatId:"gateway:shutdown",content:"",metadata:{[es]:!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?.[es])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await je(this.lifecycle.beforeOutbound,"beforeOutbound",{message:e,hasChannel:t,skippedReason:n})}catch(i){s=i,console.warn(String(i))}if(!s&&!n){let i=this.channels.get(e.channel);if(i)try{await i.send(e),r=!0}catch(a){s=a}}try{await je(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}]))}};Ie();import{randomUUID as Ia}from"node:crypto";import Ma from"node:path";function _a(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 Oa(o){return Ma.resolve(o)}function ts(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:_a(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Lt=class{storage;workspace;constructor(e,t,n){this.workspace=Oa(e),this.storage=n??Ee({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
277
277
  FROM inbox_deliveries
278
278
  WHERE workspace = ?
279
279
  AND (? = 1 OR cleared_at IS NULL)
280
- ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>Oo(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
280
+ ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>ts(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
281
281
  FROM inbox_deliveries
282
- WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return Oo(t)}record(e){let t=String(e.deliveredAt??X()),n=ta();return this.storage.prepare(`INSERT INTO inbox_deliveries (
282
+ WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return ts(t)}record(e){let t=String(e.deliveredAt??se()),n=Ia();return this.storage.prepare(`INSERT INTO inbox_deliveries (
283
283
  workspace, delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
284
- ) 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=X()){return this.storage.prepare(`UPDATE inbox_deliveries
284
+ ) 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=se()){return this.storage.prepare(`UPDATE inbox_deliveries
285
285
  SET cleared_at = COALESCE(cleared_at, ?)
286
- WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};Ce();et();import te,{existsSync as ze,unlinkSync as Ta}from"node:fs";import ue,{join as Aa}from"node:path";import{createServer as Ra}from"node:http";import{spawn as Ho}from"node:child_process";function Kn(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function He(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function Lo(o){let e="local_process",t=He(o.runtime.overload?.rateLimited)+He(o.runtime.overload?.backpressured),n=He(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,He(o.config.tools.exec.timeout)),runningSubagents:He(o.runtime.subagents),queuedMessages:He(o.runtime.queuedMessages),queuedSessions:He(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:Kn("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:Kn(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:Kn("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:Kn("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 be from"node:fs";import $e from"node:path";import{randomUUID as sa}from"node:crypto";function ia(o){return o.split($e.sep).join("/")}function aa(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 la=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),ca={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function da(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":la.has(e)?"image":"binary"}function Lt(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return ca[e]||"image"}function ua(o,e=!1,t=128*1024){if(!be.existsSync(o)||!be.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=be.statSync(o),r=da(o);if(r==="image"){let C=Math.min(n.size,5242881),w=Buffer.alloc(C),d=be.openSync(o,"r");try{C>0&&be.readSync(d,w,0,C,0)}finally{be.closeSync(d)}let b=Lt(o)==="image-jpeg"?"image/jpeg":Lt(o)==="image-png"?"image/png":Lt(o)==="image-gif"?"image/gif":Lt(o)==="image-webp"?"image/webp":Lt(o)==="image-svg"?"image/svg+xml":"image/png",I=w.toString("base64"),k=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:k?"Image preview truncated.":"Image preview available.",content:null,truncated:k,imageDataUrl:`data:${b};base64,${I}`}}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=be.openSync(o,"r");try{s>0&&be.readSync(a,i,0,s,0)}finally{be.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let u=c.toString("utf8");if(u.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let p=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:p,preview:aa(u),content:e?u:null,truncated:l}}var qn=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=$e.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=we({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return $e.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=$e.isAbsolute(t)?$e.resolve(t):$e.resolve(this.workspacePath,t);try{ke(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!be.existsSync(n))throw new Error(`File not found: ${t}`);if(!be.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=ia($e.relative(this.workspacePath,n));return{relativePath:r,displayName:$e.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
286
+ WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};Ae();Ie();import le,{existsSync as mt,unlinkSync as el}from"node:fs";import be,{join as tl}from"node:path";import{createServer as nl}from"node:http";import{spawn as fs}from"node:child_process";function dr(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function gt(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function ns(o){let e="local_process",t=gt(o.runtime.overload?.rateLimited)+gt(o.runtime.overload?.backpressured),n=gt(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,gt(o.config.tools.exec.timeout)),runningSubagents:gt(o.runtime.subagents),queuedMessages:gt(o.runtime.queuedMessages),queuedSessions:gt(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:dr("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:dr(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:dr("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:dr("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 Re from"node:fs";import ze from"node:path";import{randomUUID as $a}from"node:crypto";function La(o){return o.split(ze.sep).join("/")}function Na(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 Da=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),ja={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function Fa(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":Da.has(e)?"image":"binary"}function nn(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return ja[e]||"image"}function Ba(o,e=!1,t=128*1024){if(!Re.existsSync(o)||!Re.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=Re.statSync(o),r=Fa(o);if(r==="image"){let T=Math.min(n.size,5242881),v=Buffer.alloc(T),d=Re.openSync(o,"r");try{T>0&&Re.readSync(d,v,0,T,0)}finally{Re.closeSync(d)}let b=nn(o)==="image-jpeg"?"image/jpeg":nn(o)==="image-png"?"image/png":nn(o)==="image-gif"?"image/gif":nn(o)==="image-webp"?"image/webp":nn(o)==="image-svg"?"image/svg+xml":"image/png",_=v.toString("base64"),w=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:w?"Image preview truncated.":"Image preview available.",content:null,truncated:w,imageDataUrl:`data:${b};base64,${_}`}}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=Re.openSync(o,"r");try{s>0&&Re.readSync(a,i,0,s,0)}finally{Re.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let u=c.toString("utf8");if(u.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let p=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:p,preview:Na(u),content:e?u:null,truncated:l}}var ur=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=ze.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Ee({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return ze.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=ze.isAbsolute(t)?ze.resolve(t):ze.resolve(this.workspacePath,t);try{_e(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!Re.existsSync(n))throw new Error(`File not found: ${t}`);if(!Re.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=La(ze.relative(this.workspacePath,n));return{relativePath:r,displayName:ze.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
287
287
  FROM session_files
288
- 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=ua(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
288
+ 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=Ba(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
289
289
  FROM session_files
290
290
  WHERE workspace = ? AND session_key = ?
291
291
  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
292
292
  FROM session_files
293
- WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:u,...p}=this.summarizeRow(r,!1);return{created:!1,file:p}}let s={session_key:e,file_id:sa(),relative_path:n.relativePath,display_name:n.displayName,created_at:X(),updated_at:X()};this.getStorage().prepare(`INSERT INTO session_files (
293
+ WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:u,...p}=this.summarizeRow(r,!1);return{created:!1,file:p}}let s={session_key:e,file_id:$a(),relative_path:n.relativePath,display_name:n.displayName,created_at:se(),updated_at:se()};this.getStorage().prepare(`INSERT INTO session_files (
294
294
  workspace, session_key, file_id, relative_path, display_name, created_at, updated_at
295
295
  ) 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
296
- 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 ma from"node:os";import $o from"node:path";et();Ce();var Rr="clawhub@latest",Do=12e4;function No(o){let e=o?.runner??new ce,t=()=>{let n=O(),r=Y(n.agents.defaults.workspace);return Ue(r,!0),r};return{getSnapshot(){let n=t(),r=$o.join(n,"skills"),s=$o.join(ma.homedir(),".agents","skills"),i=new tt(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${Rr} search <query> --limit 5`,installTemplate:Hn(["install","<slug>"],n),list:Hn(["list"],n),update:Hn(["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(!no(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",Rr,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:Do,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(pa(i));return{slug:r,workspacePath:s,command:Hn(["install",r],s),output:jo(i),restartRequired:!0}}}}function Hn(o,e){return["npx","--yes",Rr,...o,"--workdir",e].map(ga).join(" ")}function ga(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function jo(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
296
+ 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 Ga from"node:os";import rs from"node:path";Ie();ct();Ae();var qr="clawhub@latest",os=12e4;function ss(o){let e=o?.runner??new me,t=()=>{let n=$(),r=V(n.agents.defaults.workspace);return rt(r,!0),r};return{getSnapshot(){let n=t(),r=rs.join(n,"skills"),s=rs.join(Ga.homedir(),".agents","skills"),i=new De(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${qr} search <query> --limit 5`,installTemplate:gr(["install","<slug>"],n),list:gr(["list"],n),update:gr(["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(!bn(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",qr,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:os,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(Wa(i));return{slug:r,workspacePath:s,command:gr(["install",r],s),output:is(i),restartRequired:!0}}}}function gr(o,e){return["npx","--yes",qr,...o,"--workdir",e].map(Ua).join(" ")}function Ua(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function is(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
297
297
 
298
- `).trim()||"Skill installed."}function pa(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(Do/1e3)} seconds.`;let e=jo(o),t=typeof o.exitCode=="number"?`
298
+ `).trim()||"Skill installed."}function Wa(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(os/1e3)} seconds.`;let e=is(o),t=typeof o.exitCode=="number"?`
299
299
  Exit code: ${o.exitCode}`:"",n=o.signal?`
300
- Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}Ce();se();import{scrypt as fa,randomBytes as Fo,timingSafeEqual as ha}from"node:crypto";var Uo=64,Go=16384,Wo=8,Jo=1,ya=5,Bo=300*1e3;function ba(){let o=Fo(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 Ko(o,e,t,n){let r=n??{};return new Promise((s,i)=>{fa(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function va(o,e){let t=e??Fo(16),n=await Ko(o,t,Uo,{N:Go,r:Wo,p:Jo});return`${t.toString("hex")}:${n.toString("hex")}`}async function wa(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 Ko(o,n,Uo,{N:Go,r:Wo,p:Jo});return s.length!==r.length?!1:ha(s,r)}var zn=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 va(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?wa(e,this.config.pinHash):!1}createSession(){let e=ba(),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)>=ya}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+Bo-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()-Bo;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function zo(o){let e=ue.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 Vo(o){return o.startsWith("text/")||o==="application/json"}function Ea(){let o=_e("dashboard");if(!o)return null;let e=ue.join(o,"index.html");return te.existsSync(e)?o:null}function K(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 h(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function Pa(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Yn(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function Qn(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 Ia(o){let e=Yn(o),t=[...e].reverse().find(n=>Qn(n.content));return{messageCount:e.length,lastMessagePreview:t?Qn(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function _a(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function _r(o){return typeof o=="string"?o.trim():""}function ns(o){return _r(o?.metadata?.displayName)||null}function Ma(o){let e=new Set;for(let n of o){let r=ns(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 Oa(o,e){let t=_a(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function Ir(o){let e=new Set,t=[];for(let n of[...Yn(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:Qn(r,56)??r}),t.length>=3))break}return t}function Xn(o,e,t,n){let{channel:r,chatId:s}=Pa(o.key),i=Ia(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:ns(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 Xo(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 Yo(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function Qo(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 Zo(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function La(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 De(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Mr(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function $a(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function es(o,e,t){return $a(o.socket.remoteAddress)?!0:(h(e,403,{error:t}),!1)}function Bt(o){return o.map(e=>String(e)).join(".")}function Or(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!De(t))return;t=t[n]}return t}function me(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 ${Bt(e)}`);let c=n[i],u=e[s+1];c===void 0&&(n[i]=typeof u=="number"?[]:{}),n=n[i];continue}if(!De(n))throw new Error(`Expected object while writing ${Bt(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 ${Bt(e)}`);n[r]=t;return}if(!De(n))throw new Error(`Expected object while writing ${Bt(e)}`);n[r]=t}function Pe(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??Mr(o):null}}function Da(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))me(t,["providers",n,"apiKey"],Pe(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{me(t,["customLlmProviders",r,"apiKey"],Pe(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),me(t,["channels","telegram","token"],Pe(o.channels.telegram.token)),me(t,["channels","discord","token"],Pe(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",me(t,["security","auth","pinHash"],Pe(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",me(t,["tools","browserRelay","authToken"],Pe(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",me(t,["tools","web","search","apiKey"],Pe(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??{}))me(t,["tools","mcpServers",n,"env",s],Pe(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))me(t,["tools","mcpServers",n,"headers",s],Pe(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function rs(o,e,t,n){let r=Or(o,e),s=Bt(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(!De(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 Ve(o,e,t,n){let r=String(Or(e,n)??""),s=String(Or(o,n)??""),i=rs(t,n,r,s);if(i){if(i.action==="keep"){me(o,n,r);return}if(i.action==="clear"){me(o,n,"");return}me(o,n,i.value??s)}}function ts(o){return De(o)&&Object.values(o).every(e=>typeof e=="string")}function Na(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function ja(o){if(!De(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),!De(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",u=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!Na(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&&!ts(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!ts(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(u)||u<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function Ba(o){if(Array.isArray(o.customAcpProviders))return o;let e=O();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var Fa=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),Ua={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function os(o){let e=Ea(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??No(),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 zn(o.config.security.auth),c=()=>(r||(r=new qn(o.workspacePath??process.cwd(),o.dataDir)),r),u=()=>(s||(s=new ft(o.workspacePath??process.cwd(),o.dataDir)),s),p=w=>typeof o.sessionManager.listSessions!="function"?w===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===w)||w===o.sessionKey,y=(w,d)=>{let b=w||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:d,session:b}}},C=Ra(async(w,d)=>{let b=w.method||"GET",I=new URL(w.url||"/",`http://${w.headers.host||"localhost"}`),k=I.pathname;d.setHeader("X-Content-Type-Options","nosniff"),d.setHeader("X-Frame-Options","DENY"),d.setHeader("Referrer-Policy","no-referrer"),d.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let $=Ua[b]??"\x1B[0m";if(console.log(`[gateway] ${$}${b}\x1B[0m ${k}`),l.isEnabled&&k.startsWith("/api/")&&!Fa.has(k)){let g=w.headers["x-auth-token"];if(!g||typeof g!="string"||!l.validateSession(g))return h(d,401,{error:"Authentication required"});l.touchSession(g)}if(!l.isEnabled&&k==="/api/config"&&(b==="GET"||b==="PUT")&&!es(w,d,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&k==="/api/auth/login"){let g=await K(w),m=String(g.pin??"");if(!m)return h(d,400,{error:"PIN is required"});let f=w.socket.remoteAddress??"unknown";if(l.isRateLimited(f)){let A=l.getRateLimitRemainingMs(f);return h(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:A})}if(!l.hasPin)return h(d,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(m))return l.recordFailedAttempt(f),h(d,401,{error:"Invalid PIN"});l.clearFailedAttempts(f);let S=l.createSession();return h(d,200,{token:S})}if(b==="GET"&&k==="/api/auth/status")return h(d,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&k==="/api/auth/logout"){let g=w.headers["x-auth-token"];return!g||typeof g!="string"?h(d,200,{ok:!0}):(l.invalidateSession(g),h(d,200,{ok:!0}))}if(b==="POST"&&k==="/api/auth/set-pin"){let g=await K(w),m=String(g.newPin??""),f=g.currentPin!==void 0?String(g.currentPin):void 0;if(!m)return h(d,400,{error:"newPin is required"});if(m.length!==6)return h(d,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(m))return h(d,400,{error:"PIN must contain only digits"});if(l.hasPin){let x=w.headers["x-auth-token"];if(!(x&&typeof x=="string"&&l.validateSession(x))){let E=w.socket.remoteAddress??"unknown";if(l.isRateLimited(E)){let B=l.getRateLimitRemainingMs(E);return h(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:B})}if(!f)return h(d,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(f))return l.recordFailedAttempt(E),h(d,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(E)}}else{let x=process.env.EVERCLAW_BOOTSTRAP_PIN;if(x&&String(g.bootstrapSecret??"")!==x)return h(d,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let v=!l.hasPin,S=await l.setPin(m);v||l.reset();let A=O();return A.security?.auth&&(A.security.auth.pinHash=S,ie(A)),h(d,200,{ok:!0,message:v?"PIN set successfully":"PIN changed successfully"})}let j=()=>h(d,503,{error:"Gateway is shutting down. Please try again later."}),M=k.match(/^\/api\/cron\/jobs\/([^/]+)$/),N=k.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),q=k.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),ge=k.match(/^\/api\/inbox-deliveries\/([^/]+)$/),F=k.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),H=k.match(/^\/api\/sessions\/([^/]+)$/),ne=k.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&k==="/api/chat"||b==="POST"&&k==="/api/sessions"||b==="PUT"&&!!H||b==="PUT"&&k==="/api/config"||b==="POST"&&k==="/api/skills/install"||b==="POST"&&!!F||b==="POST"&&k==="/api/session-files"||b==="POST"&&k==="/api/cron/jobs"||b==="DELETE"&&!!ne||b==="DELETE"&&!!M||b==="POST"&&!!N||b==="POST"&&!!q))return j();if(b==="GET"&&k==="/api/status"){let g=O(),m=o.agent.getRuntimeState(),f=o.cron.status(),v=Lo({config:g,runtime:m,cron:f}),S=structuredClone(g.channels);return S.telegram?.token&&(S.telegram.token=Mr(S.telegram.token)),S.discord?.token&&(S.discord.token=Mr(S.discord.token)),h(d,200,{provider:g.agents.defaults.provider,model:g.agents.defaults.model,cron:f,channels:S,gateway:{...g.gateway,port:t},runtime:m,isolation:v,shutdown:{active:i||!m.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&k==="/api/chrome-session/status"){let g=O(),m=I.searchParams.get("port"),f=m?parseInt(m,10):g.tools.chromeSession?.debugPort??9222,v=g.tools.chromeSession?.minChromeVersion??136,S=await st(f);if(!S)return h(d,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:f});if(S.pendingApproval)return h(d,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${S.port} --user-data-dir=/tmp/chrome-debug-profile`,port:S.port,debugPort:f});let{port:A,versionInfo:x}=S,T=x.Browser.match(/(\w+)\/(\d+)/),E=T?.[1]??"Chrome",R=T?parseInt(T[2],10):0;return R>0&&R<v?h(d,200,{available:!1,reason:`Chrome version ${R} is below minimum required version ${v}`,hint:`Update Chrome to version ${v} or higher`,version:x.Browser,port:A,browser:E,debugPort:f}):h(d,200,{available:!0,version:x.Browser,remoteDebugging:!0,port:A,browser:E,debugPort:f})}if(b==="POST"&&k==="/api/chrome-session/launch"){let g=await K(w),m=O(),f=g.port??m.tools.chromeSession?.debugPort??9222,v=await st(f);if(v&&!v.pendingApproval){let R=v.versionInfo.Browser.match(/(\w+)\/(\d+)/);return h(d,200,{ok:!0,launched:!1,alreadyRunning:!0,port:v.port,version:v.versionInfo.Browser,browser:R?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${v.port}. No need to launch.`})}if(v?.pendingApproval)return h(d,200,{ok:!1,launched:!1,pendingApproval:!0,port:v.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 S="/tmp/chrome-debug-profile",A=Aa(S,"DevToolsActivePort");try{Ta(A)}catch{}let x=process.platform,T,E=[`--remote-debugging-port=${f}`,`--user-data-dir=${S}`];if(x==="darwin"){let R=["/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"],B=R.find(_=>ze(_));if(!B)return h(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:R,hint:"Install Google Chrome or specify the path manually."});T=B}else if(x==="win32"){T="cmd.exe";let R=process.env.ProgramFiles??"C:\\Program Files",B=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",_=[`${R}\\Google\\Chrome\\Application\\chrome.exe`,`${B}\\Google\\Chrome\\Application\\chrome.exe`,`${R}\\Microsoft\\Edge\\Application\\msedge.exe`,`${B}\\Microsoft\\Edge\\Application\\msedge.exe`],re=_.find(pe=>ze(pe));if(!re)return h(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:_,hint:"Install Google Chrome or Microsoft Edge."});E=["/c","start","",re,`--remote-debugging-port=${f}`]}else{let R=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],B=R.find(_=>ze(_));if(!B)return h(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:R,hint:"Install Google Chrome or Chromium."});T=B}try{let R=Ho(T,E,{detached:!0,stdio:"ignore"}),B=await Promise.race([new Promise(pe=>R.once("error",pe)),new Promise(pe=>setTimeout(()=>pe(null),500))]);if(B)return h(d,500,{ok:!1,error:B.message,chromePath:T,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});R.unref();let _;for(let pe=0;pe<5&&(await new Promise(je=>setTimeout(je,1e3)),_=await st(f),!_);pe++);if(!_)return h(d,200,{ok:!1,launched:!0,port:f,chromePath:T,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(_.pendingApproval)return h(d,200,{ok:!1,launched:!0,pendingApproval:!0,port:_.port,chromePath:T,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 re=_.versionInfo.Browser.match(/(\w+)\/(\d+)/);return h(d,200,{ok:!0,launched:!0,port:_.port,chromePath:T,version:_.versionInfo.Browser,browser:re?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${_.port}`})}catch(R){return h(d,500,{ok:!1,error:R instanceof Error?R.message:String(R),chromePath:T,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&k==="/api/browser-relay/status"){let m=O().tools.browserRelay;if(!m.enabled)return h(d,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:m.extensionPath});if(o.browserRelay){let f=o.browserRelay.getStatus();return h(d,200,{enabled:!0,connected:f.connected,attachedTabs:f.attachedTabs,lastPing:f.lastPing,extensionPath:m.extensionPath})}return h(d,200,{enabled:m.enabled,connected:!1,attachedTabs:[],extensionPath:m.extensionPath})}if(b==="GET"&&k==="/api/browser-relay/config"){if(!es(w,d,"Browser Relay bootstrap is only available from localhost."))return;let g=O(),m=g.tools.browserRelay;return h(d,200,{enabled:m.enabled,port:g.gateway.port,token:m.enabled&&m.authToken||""})}if(b==="POST"&&k==="/api/browser-relay/launch"){let g=await K(w),m=O(),f=g.extensionPath??m.tools.browserRelay.extensionPath;if(!f)return h(d,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let v=process.platform,S,A=[`--load-extension=${f}`,"--no-first-run","--no-default-browser-check"];if(v==="darwin")S=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(ze)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(v==="win32"){let x=process.env.ProgramFiles??"C:\\Program Files",T=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";S=[`${x}\\Google\\Chrome\\Application\\chrome.exe`,`${T}\\Google\\Chrome\\Application\\chrome.exe`].find(ze)??`${x}\\Google\\Chrome\\Application\\chrome.exe`}else S="google-chrome";try{return Ho(S,A,{detached:!0,stdio:"ignore"}).unref(),h(d,200,{ok:!0,launched:!0,extensionPath:f,message:`Chrome launched with extension from ${f}`})}catch(x){return h(d,500,{ok:!1,error:x instanceof Error?x.message:String(x),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let L=k.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),Q=Y(o.config.agents.defaults.workspace);if(b==="GET"&&k==="/api/automations"){let g=lt(Q);return h(d,200,g)}if(b==="GET"&&L&&L[1]&&!L[2]){let g=L[1],m=de(Q,g);return m?h(d,200,m):h(d,404,{error:"Automation not found"})}if(b==="POST"&&k==="/api/automations"){let g=await K(w);try{let m={name:String(g.name??"Untitled"),description:String(g.description??""),steps:g.steps||[],tags:g.tags||[],source:g.source||"manual"};g.toolType!==void 0&&(m.toolType=g.toolType),g.variables!==void 0&&(m.variables=g.variables);let f=kn(Q,m);return h(d,201,f)}catch(m){return h(d,400,{error:String(m)})}}if(b==="PUT"&&L&&L[1]&&!L[2]){let g=L[1],m=await K(w),f={};m.name!==void 0&&(f.name=String(m.name)),m.description!==void 0&&(f.description=String(m.description)),m.enabled!==void 0&&(f.enabled=!!m.enabled),m.steps!==void 0&&(f.steps=m.steps),m.tags!==void 0&&(f.tags=m.tags),m.toolType!==void 0&&(f.toolType=m.toolType),m.variables!==void 0&&(f.variables=m.variables);let v=xn(Q,g,f);return v?h(d,200,v):h(d,404,{error:"Automation not found"})}if(b==="DELETE"&&L&&L[1]){let g=L[1];return ct(Q,g)?h(d,200,{ok:!0}):h(d,404,{error:"Automation not found"})}if(b==="POST"&&L&&L[1]&&L[2]==="/run"){let g=L[1],m=de(Q,g);return m?m.enabled?(o.agent.tools.execute("automation",{command:"run",id:g}).then(f=>{console.log(`[automation] Execution of '${m.name}' finished`,{logs:f.kind==="ok"?f.content:f})}).catch(f=>{console.error(`[automation] Execution of '${m.name}' failed`,{err:f})}),h(d,200,{ok:!0,message:`Automation '${m.name}' execution started in background.`})):h(d,400,{error:"Automation is disabled"}):h(d,404,{error:"Automation not found"})}if(b==="GET"&&k==="/api/history"){let g=String(I.searchParams.get("session")??"").trim(),m=y(g,"Session history not found.");if(m.error)return h(d,404,m.error);let f=m.sessionKey,v=o.sessionManager.getOrCreate(f);return h(d,200,{session:f,messages:Yn(v.messages)})}if(b==="GET"&&k==="/api/sessions"){let g=o.agent.getRuntimeState(),m=new Set((g.sessions||[]).filter(S=>S.running||S.queued>0).map(S=>S.key)),f=o.sessionManager.getOrCreate(o.sessionKey),v=o.sessionManager.listSessions().filter(S=>String(S.key??"")!==o.sessionKey).map(S=>{let A=String(S.key??"");return Xn({key:A,created_at:String(S.created_at??f.createdAt),updated_at:String(S.updated_at??f.updatedAt)},o.sessionKey,m.has(A),o.sessionManager.getOrCreate(A))});return h(d,200,{currentSession:o.sessionKey,sessions:[Xn({key:f.key,created_at:f.createdAt,updated_at:f.updatedAt},o.sessionKey,m.has(f.key),f),...v]})}if(b==="GET"&&k==="/api/files/preview"){let g=String(I.searchParams.get("path")??"").trim(),m=parseInt(I.searchParams.get("maxLines")??"100",10),f=o.workspacePath??process.cwd();if(!g)return h(d,400,{error:"path required"});try{ke(g,f)}catch{return h(d,403,{error:"Access denied: path outside workspace"})}if(!ze(g))return h(d,404,{error:"file not found"});try{let v=te.statSync(g);if(v.isDirectory())return h(d,400,{error:"path is a directory"});let S=zo(g),A=te.readFileSync(g),x=null,T=!1;if(Vo(S)){let _=A.toString("utf-8").split(`
301
- `);T=_.length>m,x=_.slice(0,m).join(`
302
- `)}let E=ue.extname(g).toLowerCase(),R=S.startsWith("image/")?"image":S==="application/pdf"?"pdf":S==="text/csv"||S==="text/tab-separated-values"?"table":Vo(S)?E===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(E)?"code":"text":"binary";return h(d,200,{name:ue.basename(g),path:g,size:v.size,content:x,truncated:T,mimeType:S,previewType:R,extension:E})}catch(v){return h(d,500,{error:String(v)})}}if(b==="GET"&&k==="/api/files/content"){let g=String(I.searchParams.get("path")??"").trim(),m=o.workspacePath??process.cwd();if(!g)return h(d,400,{error:"path required"});try{ke(g,m)}catch{return h(d,403,{error:"Access denied: path outside workspace"})}if(!ze(g))return h(d,404,{error:"file not found"});try{let f=te.statSync(g);if(f.isDirectory())return h(d,400,{error:"path is a directory"});d.statusCode=200,d.setHeader("Content-Type",zo(g)),d.setHeader("Content-Length",String(f.size)),te.createReadStream(g).pipe(d);return}catch(f){return h(d,500,{error:String(f)})}}if(b==="POST"&&k==="/api/sessions"){let g=await K(w),m=new Set(o.sessionManager.listSessions().map(R=>String(R.key??"")));m.add(o.sessionKey);let f=String(g.key??"").trim(),v=[...m].map(R=>o.sessionManager.getOrCreate(R)),S=_r(g.label),A=S||Ma(v),x=f||Oa(m,S),T=m.has(x),E=o.sessionManager.getOrCreate(x);return T||(E.metadata={...E.metadata,displayName:A},o.sessionManager.save(E)),h(d,200,{created:!T,session:Xn({key:E.key,created_at:E.createdAt,updated_at:E.updatedAt},o.sessionKey,!1,E)})}if(H&&b==="PUT"){let g=H[1]?decodeURIComponent(H[1]):void 0;if(!g)return h(d,400,"Invalid session key");let m=y(g,"Session not found.");if(m.error)return h(d,404,m.error);let f=await K(w),v=_r(f.label),S=Number(f.pinnedOrder),A=Number(f.recentOrder);if(v===void 0&&f.isPinned===void 0&&f.pinnedOrder===void 0&&f.recentOrder===void 0)return h(d,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:g});let x=o.sessionManager.getOrCreate(m.sessionKey);if(x.metadata={...x.metadata},v!==void 0&&(x.metadata.displayName=v),f.isPinned!==void 0&&(x.metadata.isPinned=!!f.isPinned),x.metadata.isPinned===!0){delete x.metadata.recentOrder;let E=[...Xo(o.sessionManager,x.key)],R=Number.isFinite(S)?Math.max(0,Math.min(Math.trunc(S),E.length)):E.length;E.splice(R,0,x),Yo(o.sessionManager,E),Zo(o.sessionManager,Qo(o.sessionManager,x.key))}else{delete x.metadata.pinnedOrder,Yo(o.sessionManager,Xo(o.sessionManager,x.key));let E=[...Qo(o.sessionManager,x.key)],R=Number.isFinite(A)?Math.max(0,Math.min(Math.trunc(A),E.length)):E.length;E.splice(R,0,x),Zo(o.sessionManager,E)}return o.sessionManager.save(x),h(d,200,{ok:!0,session:Xn({key:x.key,created_at:x.createdAt,updated_at:x.updatedAt},o.sessionKey,!1,x)})}if(H&&b==="DELETE"){let g=H[1]?decodeURIComponent(H[1]):void 0;if(!g)return h(d,400,"Invalid session key");let m=y(g,"Session not found.");if(m.error)return h(d,404,m.error);if(m.sessionKey===o.sessionKey)return h(d,400,{error:"The primary session cannot be deleted."});let f=o.sessionManager.delete(m.sessionKey);return h(d,200,{ok:f,session:g})}if(b==="GET"&&k==="/api/suggestions"){let g=String(I.searchParams.get("session")??"").trim(),m=y(g,"Session suggestions not found.");if(m.error)return h(d,404,m.error);let f=m.sessionKey,v=o.sessionManager.getOrCreate(f),S=O(),A=S.subagents?.find(T=>T.id==="advisor"),x=A?A.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let T=ye(S),E=await xr({task:x+`
303
- Return ONLY a JSON array of strings, nothing else.`,provider:T,workspace:o.workspacePath??process.cwd(),model:S.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:S.tools.exec,restrictToWorkspace:S.tools.restrictToWorkspace,existingMessages:Yn(v.messages)}),R=[];try{let _=E.replace(/```json/g,"").replace(/```/g,"").trim();R=JSON.parse(_)}catch{R=Ir(v.messages).map(_=>_.text)}let B=Array.isArray(R)?R.slice(0,3).map((_,re)=>({id:`suggestion-${re+1}`,text:String(_),label:Qn(String(_),56)??String(_)})):Ir(v.messages);return h(d,200,{session:f,suggestions:B})}catch{return h(d,200,{session:f,suggestions:Ir(v.messages)})}}if(b==="GET"&&k==="/api/session-files"){let g=String(I.searchParams.get("session")??"").trim(),m=y(g,"Session files not found.");return m.error?h(d,404,m.error):h(d,200,{session:m.sessionKey,files:c().list(m.sessionKey)})}if(b==="GET"&&k==="/api/inbox-deliveries"){let g=I.searchParams.get("all")==="1",m=u();if(m.list({includeCleared:!0}).filter(S=>!S.clearedAt).length===0){let S=[{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.
300
+ Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}Ae();ue();import{scrypt as Ka,randomBytes as ls,timingSafeEqual as Ja}from"node:crypto";var cs=64,ds=16384,us=8,gs=1,qa=5,as=300*1e3;function Ha(){let o=ls(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 ms(o,e,t,n){let r=n??{};return new Promise((s,i)=>{Ka(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function za(o,e){let t=e??ls(16),n=await ms(o,t,cs,{N:ds,r:us,p:gs});return`${t.toString("hex")}:${n.toString("hex")}`}async function Va(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 ms(o,n,cs,{N:ds,r:us,p:gs});return s.length!==r.length?!1:Ja(s,r)}var mr=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 za(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?Va(e,this.config.pinHash):!1}createSession(){let e=Ha(),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)>=qa}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+as-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()-as;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function hs(o){let e=be.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 ys(o){return o.startsWith("text/")||o==="application/json"}function rl(){let o=We("dashboard");if(!o)return null;let e=be.join(o,"index.html");return le.existsSync(e)?o:null}function te(o){return new Promise(e=>{let t="";o.on("data",n=>{t+=n.toString(),t.length>2e6&&o.destroy()}),o.on("end",()=>{try{e(t?JSON.parse(t):{})}catch{e({})}}),o.on("error",()=>e({}))})}function y(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function ol(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function hr(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 sl(o){let e=hr(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 il(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Xr(o){return typeof o=="string"?o.trim():""}function Cs(o){return Xr(o?.metadata?.displayName)||null}function al(o){let e=new Set;for(let n of o){let r=Cs(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 ll(o,e){let t=il(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function Vr(o){let e=new Set,t=[];for(let n of[...hr(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 fr(o,e,t,n){let{channel:r,chatId:s}=ol(o.key),i=sl(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Cs(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 bs(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 vs(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function ws(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 Ss(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function cl(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 Ve(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Yr(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function dl(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function ks(o,e,t){return dl(o.socket.remoteAddress)?!0:(y(e,403,{error:t}),!1)}function ln(o){return o.map(e=>String(e)).join(".")}function Qr(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!Ve(t))return;t=t[n]}return t}function ve(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 ${ln(e)}`);let c=n[i],u=e[s+1];c===void 0&&(n[i]=typeof u=="number"?[]:{}),n=n[i];continue}if(!Ve(n))throw new Error(`Expected object while writing ${ln(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 ${ln(e)}`);n[r]=t;return}if(!Ve(n))throw new Error(`Expected object while writing ${ln(e)}`);n[r]=t}function Ge(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??Yr(o):null}}function ul(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))ve(t,["providers",n,"apiKey"],Ge(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{ve(t,["customLlmProviders",r,"apiKey"],Ge(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),ve(t,["channels","telegram","token"],Ge(o.channels.telegram.token)),ve(t,["channels","discord","token"],Ge(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",ve(t,["security","auth","pinHash"],Ge(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",ve(t,["tools","browserRelay","authToken"],Ge(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",ve(t,["tools","web","search","apiKey"],Ge(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??{}))ve(t,["tools","mcpServers",n,"env",s],Ge(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))ve(t,["tools","mcpServers",n,"headers",s],Ge(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function Ts(o,e,t,n){let r=Qr(o,e),s=ln(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(!Ve(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 pt(o,e,t,n){let r=String(Qr(e,n)??""),s=String(Qr(o,n)??""),i=Ts(t,n,r,s);if(i){if(i.action==="keep"){ve(o,n,r);return}if(i.action==="clear"){ve(o,n,"");return}ve(o,n,i.value??s)}}function xs(o){return Ve(o)&&Object.values(o).every(e=>typeof e=="string")}function gl(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function ml(o){if(!Ve(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),!Ve(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",u=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!gl(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&&!xs(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!xs(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(u)||u<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function pl(o){if(Array.isArray(o.customAcpProviders))return o;let e=$();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var fl=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),hl={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Rs(o){let e=rl(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??ss(),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 mr(o.config.security.auth),c=()=>(r||(r=new ur(o.workspacePath??process.cwd(),o.dataDir)),r),u=()=>(s||(s=new Lt(o.workspacePath??process.cwd(),o.dataDir)),s),p=v=>typeof o.sessionManager.listSessions!="function"?v===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===v)||v===o.sessionKey,h=(v,d)=>{let b=v||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:d,session:b}}},T=nl(async(v,d)=>{let b=v.method||"GET",_=new URL(v.url||"/",`http://${v.headers.host||"localhost"}`),w=_.pathname;d.setHeader("X-Content-Type-Options","nosniff"),d.setHeader("X-Frame-Options","DENY"),d.setHeader("Referrer-Policy","no-referrer"),d.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let F=hl[b]??"\x1B[0m";if(console.log(`[gateway] ${F}${b}\x1B[0m ${w}`),l.isEnabled&&w.startsWith("/api/")&&!fl.has(w)){let m=v.headers["x-auth-token"];if(!m||typeof m!="string"||!l.validateSession(m))return y(d,401,{error:"Authentication required"});l.touchSession(m)}if(!l.isEnabled&&w==="/api/config"&&(b==="GET"||b==="PUT")&&!ks(v,d,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&w==="/api/auth/login"){let m=await te(v),g=String(m.pin??"");if(!g)return y(d,400,{error:"PIN is required"});let f=v.socket.remoteAddress??"unknown";if(l.isRateLimited(f)){let P=l.getRateLimitRemainingMs(f);return y(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:P})}if(!l.hasPin)return y(d,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(g))return l.recordFailedAttempt(f),y(d,401,{error:"Invalid PIN"});l.clearFailedAttempts(f);let x=l.createSession();return y(d,200,{token:x})}if(b==="GET"&&w==="/api/auth/status")return y(d,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&w==="/api/auth/logout"){let m=v.headers["x-auth-token"];return!m||typeof m!="string"?y(d,200,{ok:!0}):(l.invalidateSession(m),y(d,200,{ok:!0}))}if(b==="POST"&&w==="/api/auth/set-pin"){let m=await te(v),g=String(m.newPin??""),f=m.currentPin!==void 0?String(m.currentPin):void 0;if(!g)return y(d,400,{error:"newPin is required"});if(g.length!==6)return y(d,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(g))return y(d,400,{error:"PIN must contain only digits"});if(l.hasPin){let C=v.headers["x-auth-token"];if(!(C&&typeof C=="string"&&l.validateSession(C))){let O=v.socket.remoteAddress??"unknown";if(l.isRateLimited(O)){let z=l.getRateLimitRemainingMs(O);return y(d,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:z})}if(!f)return y(d,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(f))return l.recordFailedAttempt(O),y(d,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(O)}}else{let C=process.env.EVERCLAW_BOOTSTRAP_PIN;if(C&&String(m.bootstrapSecret??"")!==C)return y(d,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let S=!l.hasPin,x=await l.setPin(g);S||l.reset();let P=$();return P.security?.auth&&(P.security.auth.pinHash=x,re(P)),y(d,200,{ok:!0,message:S?"PIN set successfully":"PIN changed successfully"})}let A=()=>y(d,503,{error:"Gateway is shutting down. Please try again later."}),N=w.match(/^\/api\/cron\/jobs\/([^/]+)$/),U=w.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),D=w.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),ie=w.match(/^\/api\/inbox-deliveries\/([^/]+)$/),W=w.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),Q=w.match(/^\/api\/sessions\/([^/]+)$/),E=w.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&w==="/api/chat"||b==="POST"&&w==="/api/sessions"||b==="PUT"&&!!Q||b==="PUT"&&w==="/api/config"||b==="POST"&&w==="/api/skills/install"||b==="POST"&&!!W||b==="POST"&&w==="/api/session-files"||b==="POST"&&w==="/api/cron/jobs"||b==="DELETE"&&!!E||b==="DELETE"&&!!N||b==="POST"&&!!U||b==="POST"&&!!D))return A();if(b==="GET"&&w==="/api/status"){let m=$(),g=o.agent.getRuntimeState(),f=o.cron.status(),S=ns({config:m,runtime:g,cron:f}),x=structuredClone(m.channels);x.telegram?.token&&(x.telegram.token=Yr(x.telegram.token)),x.discord?.token&&(x.discord.token=Yr(x.discord.token));let P=o.channelManager?.getStatus()??{};return y(d,200,{provider:m.agents.defaults.provider,model:m.agents.defaults.model,cron:f,channels:x,channelStatus:P,gateway:{...m.gateway,port:t},runtime:g,isolation:S,shutdown:{active:i||!g.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&w==="/api/chrome-session/status"){let m=$(),g=_.searchParams.get("port"),f=g?parseInt(g,10):m.tools.chromeSession?.debugPort??9222,S=m.tools.chromeSession?.minChromeVersion??136,x=await Tt(f);if(!x)return y(d,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:f});if(x.pendingApproval)return y(d,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${x.port} --user-data-dir=/tmp/chrome-debug-profile`,port:x.port,debugPort:f});let{port:P,versionInfo:C}=x,R=C.Browser.match(/(\w+)\/(\d+)/),O=R?.[1]??"Chrome",I=R?parseInt(R[2],10):0;return I>0&&I<S?y(d,200,{available:!1,reason:`Chrome version ${I} is below minimum required version ${S}`,hint:`Update Chrome to version ${S} or higher`,version:C.Browser,port:P,browser:O,debugPort:f}):y(d,200,{available:!0,version:C.Browser,remoteDebugging:!0,port:P,browser:O,debugPort:f})}if(b==="POST"&&w==="/api/chrome-session/launch"){let m=await te(v),g=$(),f=m.port??g.tools.chromeSession?.debugPort??9222,S=await Tt(f);if(S&&!S.pendingApproval){let I=S.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(d,200,{ok:!0,launched:!1,alreadyRunning:!0,port:S.port,version:S.versionInfo.Browser,browser:I?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${S.port}. No need to launch.`})}if(S?.pendingApproval)return y(d,200,{ok:!1,launched:!1,pendingApproval:!0,port:S.port,message:"Chrome is running on this port but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow'."});let x="/tmp/chrome-debug-profile",P=tl(x,"DevToolsActivePort");try{el(P)}catch{}let C=process.platform,R,O=[`--remote-debugging-port=${f}`,`--user-data-dir=${x}`];if(C==="darwin"){let I=["/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"],z=I.find(L=>mt(L));if(!z)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:I,hint:"Install Google Chrome or specify the path manually."});R=z}else if(C==="win32"){R="cmd.exe";let I=process.env.ProgramFiles??"C:\\Program Files",z=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",L=[`${I}\\Google\\Chrome\\Application\\chrome.exe`,`${z}\\Google\\Chrome\\Application\\chrome.exe`,`${I}\\Microsoft\\Edge\\Application\\msedge.exe`,`${z}\\Microsoft\\Edge\\Application\\msedge.exe`],de=L.find(ke=>mt(ke));if(!de)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:L,hint:"Install Google Chrome or Microsoft Edge."});O=["/c","start","",de,`--remote-debugging-port=${f}`]}else{let I=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],z=I.find(L=>mt(L));if(!z)return y(d,500,{ok:!1,error:"No supported Chromium-based browser found",searched:I,hint:"Install Google Chrome or Chromium."});R=z}try{let I=fs(R,O,{detached:!0,stdio:"ignore"}),z=await Promise.race([new Promise(ke=>I.once("error",ke)),new Promise(ke=>setTimeout(()=>ke(null),500))]);if(z)return y(d,500,{ok:!1,error:z.message,chromePath:R,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});I.unref();let L;for(let ke=0;ke<5&&(await new Promise(tt=>setTimeout(tt,1e3)),L=await Tt(f),!L);ke++);if(!L)return y(d,200,{ok:!1,launched:!0,port:f,chromePath:R,message:"Chrome was launched but CDP is not fully active. You may need to click 'Allow' in Chrome's remote debugging prompt, or try closing all existing Chrome windows first, then retry."});if(L.pendingApproval)return y(d,200,{ok:!1,launched:!0,pendingApproval:!0,port:L.port,chromePath:R,message:"Chrome was launched but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to enable agent control."});let de=L.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(d,200,{ok:!0,launched:!0,port:L.port,chromePath:R,version:L.versionInfo.Browser,browser:de?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${L.port}`})}catch(I){return y(d,500,{ok:!1,error:I instanceof Error?I.message:String(I),chromePath:R,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&w==="/api/browser-relay/status"){let g=$().tools.browserRelay;if(!g.enabled)return y(d,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:g.extensionPath});if(o.browserRelay){let f=o.browserRelay.getStatus();return y(d,200,{enabled:!0,connected:f.connected,attachedTabs:f.attachedTabs,lastPing:f.lastPing,extensionPath:g.extensionPath})}return y(d,200,{enabled:g.enabled,connected:!1,attachedTabs:[],extensionPath:g.extensionPath})}if(b==="GET"&&w==="/api/browser-relay/config"){if(!ks(v,d,"Browser Relay bootstrap is only available from localhost."))return;let m=$(),g=m.tools.browserRelay;return y(d,200,{enabled:g.enabled,port:m.gateway.port,token:g.enabled&&g.authToken||""})}if(b==="POST"&&w==="/api/browser-relay/launch"){let m=await te(v),g=$(),f=m.extensionPath??g.tools.browserRelay.extensionPath;if(!f)return y(d,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let S=process.platform,x,P=[`--load-extension=${f}`,"--no-first-run","--no-default-browser-check"];if(S==="darwin")x=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(mt)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(S==="win32"){let C=process.env.ProgramFiles??"C:\\Program Files",R=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";x=[`${C}\\Google\\Chrome\\Application\\chrome.exe`,`${R}\\Google\\Chrome\\Application\\chrome.exe`].find(mt)??`${C}\\Google\\Chrome\\Application\\chrome.exe`}else x="google-chrome";try{return fs(x,P,{detached:!0,stdio:"ignore"}).unref(),y(d,200,{ok:!0,launched:!0,extensionPath:f,message:`Chrome launched with extension from ${f}`})}catch(C){return y(d,500,{ok:!1,error:C instanceof Error?C.message:String(C),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let M=w.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),j=V(o.config.agents.defaults.workspace);if(b==="GET"&&w==="/api/automations"){let m=Et(j);return y(d,200,m)}if(b==="GET"&&M&&M[1]&&!M[2]){let m=M[1],g=ye(j,m);return g?y(d,200,g):y(d,404,{error:"Automation not found"})}if(b==="POST"&&w==="/api/automations"){let m=await te(v);try{let g={name:String(m.name??"Untitled"),description:String(m.description??""),steps:m.steps||[],tags:m.tags||[],source:m.source||"manual"};m.toolType!==void 0&&(g.toolType=m.toolType),m.variables!==void 0&&(g.variables=m.variables);let f=Gn(j,g);return y(d,201,f)}catch(g){return y(d,400,{error:String(g)})}}if(b==="PUT"&&M&&M[1]&&!M[2]){let m=M[1],g=await te(v),f={};g.name!==void 0&&(f.name=String(g.name)),g.description!==void 0&&(f.description=String(g.description)),g.enabled!==void 0&&(f.enabled=!!g.enabled),g.steps!==void 0&&(f.steps=g.steps),g.tags!==void 0&&(f.tags=g.tags),g.toolType!==void 0&&(f.toolType=g.toolType),g.variables!==void 0&&(f.variables=g.variables);let S=Un(j,m,f);return S?y(d,200,S):y(d,404,{error:"Automation not found"})}if(b==="DELETE"&&M&&M[1]){let m=M[1];return Pt(j,m)?y(d,200,{ok:!0}):y(d,404,{error:"Automation not found"})}if(b==="POST"&&M&&M[1]&&M[2]==="/run"){let m=M[1],g=ye(j,m);return g?g.enabled?(o.agent.tools.execute("automation",{command:"run",id:m}).then(f=>{console.log(`[automation] Execution of '${g.name}' finished`,{logs:f.kind==="ok"?f.content:f})}).catch(f=>{console.error(`[automation] Execution of '${g.name}' failed`,{err:f})}),y(d,200,{ok:!0,message:`Automation '${g.name}' execution started in background.`})):y(d,400,{error:"Automation is disabled"}):y(d,404,{error:"Automation not found"})}if(b==="GET"&&w==="/api/history"){let m=String(_.searchParams.get("session")??"").trim(),g=h(m,"Session history not found.");if(g.error)return y(d,404,g.error);let f=g.sessionKey,S=o.sessionManager.getOrCreate(f);return y(d,200,{session:f,messages:hr(S.messages)})}if(b==="GET"&&w==="/api/sessions"){let m=o.agent.getRuntimeState(),g=new Set((m.sessions||[]).filter(x=>x.running||x.queued>0).map(x=>x.key)),f=o.sessionManager.getOrCreate(o.sessionKey),S=o.sessionManager.listSessions().filter(x=>String(x.key??"")!==o.sessionKey).map(x=>{let P=String(x.key??"");return fr({key:P,created_at:String(x.created_at??f.createdAt),updated_at:String(x.updated_at??f.updatedAt)},o.sessionKey,g.has(P),o.sessionManager.getOrCreate(P))});return y(d,200,{currentSession:o.sessionKey,sessions:[fr({key:f.key,created_at:f.createdAt,updated_at:f.updatedAt},o.sessionKey,g.has(f.key),f),...S]})}if(b==="GET"&&w==="/api/files/preview"){let m=String(_.searchParams.get("path")??"").trim(),g=parseInt(_.searchParams.get("maxLines")??"100",10),f=o.workspacePath??process.cwd();if(!m)return y(d,400,{error:"path required"});try{_e(m,f)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!mt(m))return y(d,404,{error:"file not found"});try{let S=le.statSync(m);if(S.isDirectory())return y(d,400,{error:"path is a directory"});let x=hs(m),P=le.readFileSync(m),C=null,R=!1;if(ys(x)){let L=P.toString("utf-8").split(`
301
+ `);R=L.length>g,C=L.slice(0,g).join(`
302
+ `)}let O=be.extname(m).toLowerCase(),I=x.startsWith("image/")?"image":x==="application/pdf"?"pdf":x==="text/csv"||x==="text/tab-separated-values"?"table":ys(x)?O===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(O)?"code":"text":"binary";return y(d,200,{name:be.basename(m),path:m,size:S.size,content:C,truncated:R,mimeType:x,previewType:I,extension:O})}catch(S){return y(d,500,{error:String(S)})}}if(b==="GET"&&w==="/api/files/content"){let m=String(_.searchParams.get("path")??"").trim(),g=o.workspacePath??process.cwd();if(!m)return y(d,400,{error:"path required"});try{_e(m,g)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!mt(m))return y(d,404,{error:"file not found"});try{let f=le.statSync(m);if(f.isDirectory())return y(d,400,{error:"path is a directory"});d.statusCode=200,d.setHeader("Content-Type",hs(m)),d.setHeader("Content-Length",String(f.size)),le.createReadStream(m).pipe(d);return}catch(f){return y(d,500,{error:String(f)})}}if(b==="POST"&&w==="/api/sessions"){let m=await te(v),g=new Set(o.sessionManager.listSessions().map(I=>String(I.key??"")));g.add(o.sessionKey);let f=String(m.key??"").trim(),S=[...g].map(I=>o.sessionManager.getOrCreate(I)),x=Xr(m.label),P=x||al(S),C=f||ll(g,x),R=g.has(C),O=o.sessionManager.getOrCreate(C);return R||(O.metadata={...O.metadata,displayName:P},o.sessionManager.save(O)),y(d,200,{created:!R,session:fr({key:O.key,created_at:O.createdAt,updated_at:O.updatedAt},o.sessionKey,!1,O)})}if(Q&&b==="PUT"){let m=Q[1]?decodeURIComponent(Q[1]):void 0;if(!m)return y(d,400,"Invalid session key");let g=h(m,"Session not found.");if(g.error)return y(d,404,g.error);let f=await te(v),S=Xr(f.label),x=Number(f.pinnedOrder),P=Number(f.recentOrder);if(S===void 0&&f.isPinned===void 0&&f.pinnedOrder===void 0&&f.recentOrder===void 0)return y(d,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:m});let C=o.sessionManager.getOrCreate(g.sessionKey);if(C.metadata={...C.metadata},S!==void 0&&(C.metadata.displayName=S),f.isPinned!==void 0&&(C.metadata.isPinned=!!f.isPinned),C.metadata.isPinned===!0){delete C.metadata.recentOrder;let O=[...bs(o.sessionManager,C.key)],I=Number.isFinite(x)?Math.max(0,Math.min(Math.trunc(x),O.length)):O.length;O.splice(I,0,C),vs(o.sessionManager,O),Ss(o.sessionManager,ws(o.sessionManager,C.key))}else{delete C.metadata.pinnedOrder,vs(o.sessionManager,bs(o.sessionManager,C.key));let O=[...ws(o.sessionManager,C.key)],I=Number.isFinite(P)?Math.max(0,Math.min(Math.trunc(P),O.length)):O.length;O.splice(I,0,C),Ss(o.sessionManager,O)}return o.sessionManager.save(C),y(d,200,{ok:!0,session:fr({key:C.key,created_at:C.createdAt,updated_at:C.updatedAt},o.sessionKey,!1,C)})}if(Q&&b==="DELETE"){let m=Q[1]?decodeURIComponent(Q[1]):void 0;if(!m)return y(d,400,"Invalid session key");let g=h(m,"Session not found.");if(g.error)return y(d,404,g.error);if(g.sessionKey===o.sessionKey)return y(d,400,{error:"The primary session cannot be deleted."});let f=o.sessionManager.delete(g.sessionKey);return y(d,200,{ok:f,session:m})}if(b==="GET"&&w==="/api/suggestions"){let m=String(_.searchParams.get("session")??"").trim(),g=h(m,"Session suggestions not found.");if(g.error)return y(d,404,g.error);let f=g.sessionKey,S=o.sessionManager.getOrCreate(f),x=$(),P=x.subagents?.find(R=>R.id==="advisor"),C=P?P.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let R=Te(x),O=await Ur({task:C+`
303
+ Return ONLY a JSON array of strings, nothing else.`,provider:R,workspace:o.workspacePath??process.cwd(),model:x.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:x.tools.exec,restrictToWorkspace:x.tools.restrictToWorkspace,existingMessages:hr(S.messages)}),I=[];try{let L=O.replace(/```json/g,"").replace(/```/g,"").trim();I=JSON.parse(L)}catch{I=Vr(S.messages).map(L=>L.text)}let z=Array.isArray(I)?I.slice(0,3).map((L,de)=>({id:`suggestion-${de+1}`,text:String(L),label:yr(String(L),56)??String(L)})):Vr(S.messages);return y(d,200,{session:f,suggestions:z})}catch{return y(d,200,{session:f,suggestions:Vr(S.messages)})}}if(b==="GET"&&w==="/api/session-files"){let m=String(_.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");return g.error?y(d,404,g.error):y(d,200,{session:g.sessionKey,files:c().list(g.sessionKey)})}if(b==="GET"&&w==="/api/inbox-deliveries"){let m=_.searchParams.get("all")==="1",g=u();if(g.list({includeCleared:!0}).filter(x=>!x.clearedAt).length===0){let x=[{jobId:"demo-cron-daily-standup",jobName:"Daily standup reminder",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:`This is a sample cron notification to demonstrate the Inbox functionality. When real cron jobs run and deliver messages, they will appear here.
304
304
 
305
- 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 x=0;x<S.length;x++){let T=S[x],E=new Date(A.getTime()-x*36e5).toISOString();m.record({jobId:T.jobId,jobName:T.jobName,sessionKey:T.sessionKey,channel:T.channel,recipient:T.recipient,content:T.content,deliveredAt:E})}}return h(d,200,{deliveries:m.list({includeCleared:g})})}if(ge&&b==="GET"){let g=ge[1];if(!g)return h(d,400,"Invalid delivery ID");let m=u().get(decodeURIComponent(g));return m?h(d,200,{delivery:m}):h(d,404,{error:"Inbox delivery not found."})}if(F&&b==="POST"){let g=F[1];if(!g)return h(d,400,"Invalid delivery ID");let m=u().markCleared(decodeURIComponent(g));return m?h(d,200,{ok:!0,delivery:m}):h(d,404,{error:"Inbox delivery not found."})}if(b==="POST"&&k==="/api/session-files"){let g=await K(w),m=String(g.session??"").trim(),f=y(m,"Session files not found.");if(f.error)return h(d,404,f.error);try{return h(d,200,c().associate(f.sessionKey,String(g.path??"")))}catch(v){return h(d,400,{error:v instanceof Error?v.message:String(v)})}}if(b==="POST"&&k==="/api/session-files/upload"){let g=await K(w),m=String(g.session??"").trim(),f=y(m,"Session files not found.");if(f.error)return h(d,404,f.error);let v=String(g.filename??"").trim(),S=String(g.content??"").trim();if(!v)return h(d,400,{error:"Filename is required."});if(!S)return h(d,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"],x=v.toLowerCase().slice(v.lastIndexOf("."));if(!x||!A.includes(x))return h(d,400,{error:`Unsupported file type. Allowed: ${A.join(", ")}`});try{let T=Buffer.from(S,"base64"),E=ue.join(o.workspacePath??process.cwd(),".session-uploads");te.existsSync(E)||te.mkdirSync(E,{recursive:!0});let R=v.replace(/[^a-zA-Z0-9._-]/g,"_"),B=ue.join(E,`${Date.now()}-${R}`);return te.writeFileSync(B,T),h(d,200,c().associate(f.sessionKey,B))}catch(T){return h(d,400,{error:T instanceof Error?T.message:String(T)})}}if(b==="POST"&&k==="/api/session-files/copy-local"){let g=await K(w),m=String(g.session??"").trim(),f=y(m,"Session files not found.");if(f.error)return h(d,404,f.error);let v=String(g.path??"").trim(),S=o.workspacePath??process.cwd();if(!v)return h(d,400,{error:"Path is required."});try{ke(v,S)}catch{return h(d,403,{error:"Access denied: path outside workspace"})}if(!te.existsSync(v))return h(d,404,{error:"File not found."});try{return te.statSync(v).isDirectory()?h(d,400,{error:"Path is a directory."}):h(d,200,c().associate(f.sessionKey,v))}catch(A){return h(d,400,{error:A instanceof Error?A.message:String(A)})}}if(ne&&b==="GET"){let g=String(I.searchParams.get("session")??"").trim(),m=y(g,"Session files not found.");if(m.error)return h(d,404,m.error);let f=ne[1];if(!f)return h(d,400,"Invalid file ID");let v=c().get(m.sessionKey,decodeURIComponent(f));return v?h(d,200,{session:m.sessionKey,file:v}):h(d,404,{error:"Session file not found.",session:m.sessionKey})}if(ne&&b==="DELETE"){let g=String(I.searchParams.get("session")??"").trim(),m=y(g,"Session files not found.");if(m.error)return h(d,404,m.error);let f=ne[1];return f?h(d,200,{ok:c().remove(m.sessionKey,decodeURIComponent(f))}):h(d,400,"Invalid file ID")}if(b==="POST"&&k==="/api/chat/stream"){let g=await K(w),m=g.message,f=String(g.session??"default:everclaw"),v=String(g.model??"").trim(),S=String(g._provider??"").trim(),A=Array.isArray(m)?m:String(m??"").trim();if(typeof A=="string"&&!A)return h(d,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return h(d,400,{error:"message required"});d.setHeader("Content-Type","text/event-stream"),d.setHeader("Cache-Control","no-cache"),d.setHeader("Connection","keep-alive"),d.flushHeaders();let x=R=>{d.write(`data: ${JSON.stringify(R)}
305
+ 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."}],P=new Date;for(let C=0;C<x.length;C++){let R=x[C],O=new Date(P.getTime()-C*36e5).toISOString();g.record({jobId:R.jobId,jobName:R.jobName,sessionKey:R.sessionKey,channel:R.channel,recipient:R.recipient,content:R.content,deliveredAt:O})}}return y(d,200,{deliveries:g.list({includeCleared:m})})}if(ie&&b==="GET"){let m=ie[1];if(!m)return y(d,400,"Invalid delivery ID");let g=u().get(decodeURIComponent(m));return g?y(d,200,{delivery:g}):y(d,404,{error:"Inbox delivery not found."})}if(W&&b==="POST"){let m=W[1];if(!m)return y(d,400,"Invalid delivery ID");let g=u().markCleared(decodeURIComponent(m));return g?y(d,200,{ok:!0,delivery:g}):y(d,404,{error:"Inbox delivery not found."})}if(b==="POST"&&w==="/api/session-files"){let m=await te(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(d,404,f.error);try{return y(d,200,c().associate(f.sessionKey,String(m.path??"")))}catch(S){return y(d,400,{error:S instanceof Error?S.message:String(S)})}}if(b==="POST"&&w==="/api/session-files/upload"){let m=await te(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(d,404,f.error);let S=String(m.filename??"").trim(),x=String(m.content??"").trim();if(!S)return y(d,400,{error:"Filename is required."});if(!x)return y(d,400,{error:"File content is required."});let P=[".md",".txt",".pdf",".jpg",".jpeg",".png",".gif",".webp",".json",".js",".jsx",".ts",".tsx",".css",".html",".xml",".yml",".yaml",".py",".rb",".go",".rs",".java",".c",".cc",".cpp",".h",".hpp",".sh"],C=S.toLowerCase().slice(S.lastIndexOf("."));if(!C||!P.includes(C))return y(d,400,{error:`Unsupported file type. Allowed: ${P.join(", ")}`});try{let R=Buffer.from(x,"base64"),O=be.join(o.workspacePath??process.cwd(),".session-uploads");le.existsSync(O)||le.mkdirSync(O,{recursive:!0});let I=S.replace(/[^a-zA-Z0-9._-]/g,"_"),z=be.join(O,`${Date.now()}-${I}`);return le.writeFileSync(z,R),y(d,200,c().associate(f.sessionKey,z))}catch(R){return y(d,400,{error:R instanceof Error?R.message:String(R)})}}if(b==="POST"&&w==="/api/session-files/copy-local"){let m=await te(v),g=String(m.session??"").trim(),f=h(g,"Session files not found.");if(f.error)return y(d,404,f.error);let S=String(m.path??"").trim(),x=o.workspacePath??process.cwd();if(!S)return y(d,400,{error:"Path is required."});try{_e(S,x)}catch{return y(d,403,{error:"Access denied: path outside workspace"})}if(!le.existsSync(S))return y(d,404,{error:"File not found."});try{return le.statSync(S).isDirectory()?y(d,400,{error:"Path is a directory."}):y(d,200,c().associate(f.sessionKey,S))}catch(P){return y(d,400,{error:P instanceof Error?P.message:String(P)})}}if(E&&b==="GET"){let m=String(_.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");if(g.error)return y(d,404,g.error);let f=E[1];if(!f)return y(d,400,"Invalid file ID");let S=c().get(g.sessionKey,decodeURIComponent(f));return S?y(d,200,{session:g.sessionKey,file:S}):y(d,404,{error:"Session file not found.",session:g.sessionKey})}if(E&&b==="DELETE"){let m=String(_.searchParams.get("session")??"").trim(),g=h(m,"Session files not found.");if(g.error)return y(d,404,g.error);let f=E[1];return f?y(d,200,{ok:c().remove(g.sessionKey,decodeURIComponent(f))}):y(d,400,"Invalid file ID")}if(b==="POST"&&w==="/api/chat/stream"){let m=await te(v),g=m.message,f=String(m.session??"default:everclaw"),S=String(m.model??"").trim(),x=String(m._provider??"").trim(),P=Array.isArray(g)?g:String(g??"").trim();if(typeof P=="string"&&!P)return y(d,400,{error:"message required"});if(Array.isArray(P)&&P.length===0)return y(d,400,{error:"message required"});d.setHeader("Content-Type","text/event-stream"),d.setHeader("Cache-Control","no-cache"),d.setHeader("Connection","keep-alive"),d.flushHeaders();let C=I=>{d.write(`data: ${JSON.stringify(I)}
306
306
 
307
- `)},T="",E=[];try{let R=await o.agent.processDirectResult(A,f,"cli","dashboard",async(B,_)=>{if(_?.thinkingContent&&(T=_.thinkingContent),Array.isArray(_?.tool_calls)&&(E=_.tool_calls),_?.tool_call&&typeof _.tool_call=="object"){let re=_.tool_call,pe=typeof re.id=="string"?re.id:"";E=E.some(je=>je.id===pe)?E.map(je=>je.id===pe?{...je,...re}:je):[...E,re]}switch(_?.event){case"thinking":x({type:"thinking",content:_.thinkingContent??B});break;case"tool_calls":x({type:"tool_calls",tool_calls:E});break;case"tool_result":x({type:"tool_result",tool_call:_.tool_call,tool_calls:E});break;case"answer":x({type:"answer",content:B});break;default:x({type:"progress",content:B,toolHint:!!_?.toolHint,..._?.tool_calls?{tool_calls:_.tool_calls}:{}});break}},{...v?{_model:v}:{},...S?{_provider:S}:{},...Array.isArray(g.skillNames)&&g.skillNames.length?{skillNames:g.skillNames}:{}});R.outcome==="rate_limited"?x({type:"error",error:R.content,outcome:R.outcome,retryAfterMs:R.retryAfterMs??0}):R.outcome==="backpressure"||R.outcome==="shutdown"?x({type:"error",error:R.content,outcome:R.outcome}):x({type:"done",response:R.content,thinkingContent:T,tool_calls:E})}catch(R){x({type:"error",error:String(R)})}finally{d.end()}return}if(b==="POST"&&k==="/api/chat"){let g=await K(w),m=g.message,f=String(g.session??"default:everclaw"),v=String(g.model??"").trim(),S=String(g._provider??"").trim(),A=Array.isArray(m)?m:String(m??"").trim();if(typeof A=="string"&&!A)return h(d,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return h(d,400,{error:"message required"});let x=[];try{let T=await o.agent.processDirectResult(A,f,"cli","dashboard",async(E,R)=>{x.push({content:E,toolHint:!!R?.toolHint,...R?.tool_calls?{tool_calls:R.tool_calls}:{}})},{...v?{_model:v}:{},...S?{_provider:S}:{}});return T.outcome==="rate_limited"?(d.setHeader("Retry-After",String(Math.max(1,Math.ceil((T.retryAfterMs??0)/1e3)))),h(d,429,{error:T.content,outcome:T.outcome,retryAfterMs:T.retryAfterMs??0,progress:x})):T.outcome==="backpressure"||T.outcome==="shutdown"?h(d,503,{error:T.content,outcome:T.outcome,progress:x}):h(d,200,{response:T.content,progress:x})}catch(T){return h(d,500,{error:String(T)})}}if(b==="GET"&&k==="/api/config")return h(d,200,Da(O()));if(b==="GET"&&k==="/api/security/status"){let{ToolGuardEngine:g}=await Promise.resolve().then(()=>(Pr(),qo)),f=g.getInstance().getRules(),v=f.filter(A=>A.enabled),S=O();return h(d,200,{toolGuard:{enabled:S.security?.toolGuard?.enabled??!1,totalRules:f.length,enabledRules:v.length,defaultRules:f.filter(A=>!A.id.startsWith("user-")).length,userRules:S.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:S.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&k==="/api/config"){let g=await K(w),m=De(g.config)?g.config:null;if(!m)return h(d,400,{error:"Request body must include a config object."});let f=Ba(m),v=O(),S=g.secretChanges;v.security?.auth&&f.security?.auth&&"pinHash"in v.security.auth&&(f.security.auth.pinHash=v.security.auth.pinHash);try{if(f.providers&&v.providers)for(let x of Object.keys(f.providers))f.providers[x]&&v.providers[x]&&Ve(f,v,S,["providers",x,"apiKey"]);if(Array.isArray(f.customLlmProviders)&&Array.isArray(v.customLlmProviders))for(let x=0;x<f.customLlmProviders.length;x++){let T=f.customLlmProviders[x];if(!T)continue;let R=v.customLlmProviders.find(re=>re?.name===T.name)?.apiKey??"",B=T.apiKey??"",_=rs(S,["customLlmProviders",x,"apiKey"],R,B);_&&(T.apiKey=_.action==="keep"?R:_.action==="clear"?"":_.value??B)}if(f.channels&&v.channels&&(Ve(f,v,S,["channels","telegram","token"]),Ve(f,v,S,["channels","discord","token"])),f.tools?.browserRelay&&v.tools?.browserRelay&&Ve(f,v,S,["tools","browserRelay","authToken"]),f.tools?.web?.search&&v.tools?.web?.search&&Ve(f,v,S,["tools","web","search","apiKey"]),f.tools?.mcpServers&&v.tools?.mcpServers)for(let x of Object.keys(f.tools.mcpServers)){let T=f.tools.mcpServers[x];if(T?.env)for(let E of Object.keys(T.env))Ve(f,v,S,["tools","mcpServers",x,"env",E]);if(T?.headers)for(let E of Object.keys(T.headers))Ve(f,v,S,["tools","mcpServers",x,"headers",E])}}catch(x){return h(d,400,{error:x instanceof Error?x.message:String(x)})}if(f.security?.auth?.enabled&&!f.security?.auth?.pinHash?.length)return h(d,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let A=ja(f.tools?.mcpServers??{});return A.length?h(d,400,{error:`Invalid MCP server configuration. ${A[0]}`,details:A}):(ie(f),l.updateConfig(f.security.auth),h(d,200,{ok:!0}))}if(b==="GET"&&k==="/api/subagents"){let g=O();return h(d,200,{subagents:g.subagents||[]})}if(b==="POST"&&k==="/api/subagents"){let g=await K(w),m=O();m.subagents||(m.subagents=[]);let f=m.subagents.length,v={id:`subagent-${Date.now()}`,name:g.name||`SubAgent ${f+1}`,task:g.task||"",createdAt:Date.now()};return m.subagents.push(v),ie(m),h(d,200,v)}let W=k.match(/^\/api\/subagents\/([^/]+)$/);if(W&&b==="PUT"){let g=W[1];if(!g)return h(d,400,"Invalid subagent ID");let m=await K(w),f=O();f.subagents||(f.subagents=[]);let v=f.subagents.findIndex(x=>x.id===g);if(v===-1)return h(d,404,{error:"Subagent not found"});let S=f.subagents[v];if(!S)return h(d,404,{error:"Subagent not found"});let A={id:m.id??S.id,name:m.name??S.name,task:m.task??S.task,createdAt:m.createdAt??S.createdAt};return f.subagents[v]=A,ie(f),h(d,200,A)}if(W&&b==="DELETE"){let g=W[1],m=O();m.subagents||(m.subagents=[]);let f=m.subagents.findIndex(v=>v.id===g);return f===-1?h(d,404,{error:"Subagent not found"}):(m.subagents.splice(f,1),ie(m),h(d,200,{ok:!0}))}if(b==="GET"&&k==="/api/skills")try{return h(d,200,n.getSnapshot())}catch(g){return h(d,500,{error:String(g)})}if(b==="POST"&&k==="/api/skills/install"){let g=await K(w);try{let m=await n.install(String(g.slug??""));return h(d,200,m)}catch(m){return h(d,400,{error:m instanceof Error?m.message:String(m)})}}if(b==="GET"&&k==="/api/cron/jobs"){let g=I.searchParams.get("all")==="1";return h(d,200,o.cron.listJobs(g))}if(b==="POST"&&k==="/api/cron/jobs"){let g=await K(w);try{let m={name:String(g.name??"job"),schedule:g.schedule,message:String(g.message??""),deliver:!!g.deliver,deleteAfterRun:!!g.deleteAfterRun};g.channel&&(m.channel=String(g.channel)),g.to&&(m.to=String(g.to));let f=o.cron.addJob(m);return h(d,200,f)}catch(m){return h(d,400,{error:String(m)})}}if(M&&b==="DELETE"){let g=M[1];return g?h(d,200,{ok:o.cron.removeJob(g)}):h(d,400,"Invalid job ID")}if(M&&b==="PUT"){let g=M[1];if(!g)return h(d,400,"Invalid job ID");let m=await K(w),f={};m.name!==void 0&&(f.name=String(m.name)),m.schedule!==void 0&&(f.schedule=m.schedule),m.message!==void 0&&(f.message=String(m.message)),m.deliver!==void 0&&(f.deliver=!!m.deliver),m.channel!==void 0&&(f.channel=String(m.channel)),m.to!==void 0&&(f.to=String(m.to)),m.deleteAfterRun!==void 0&&(f.deleteAfterRun=!!m.deleteAfterRun);let v=o.cron.updateJob(g,f);return v?h(d,200,v):h(d,404,{error:"not found"})}if(N&&b==="POST"){let m=(await K(w)).enabled!==!1,f=N[1];if(!f)return h(d,400,"Invalid job ID");let v=o.cron.enableJob(f,m);return v?h(d,200,v):h(d,404,{error:"not found"})}if(q&&b==="POST"){let g=await K(w),m=q[1];if(!m)return h(d,400,"Invalid job ID");let f=await o.cron.runJob(m,!!g.force);return h(d,200,{ok:f})}let Z=o.config.gateway.dashboard?.enabled!==!1;if(Z&&e){let g=ue.resolve(e,k==="/"?"index.html":k.slice(1));if(!g.startsWith(ue.resolve(e)+ue.sep)&&g!==ue.resolve(e)&&(g=ue.join(e,"index.html")),(!te.existsSync(g)||te.statSync(g).isDirectory())&&(g=ue.join(e,"index.html")),!te.existsSync(g)){d.statusCode=404,d.end("Dashboard assets not found. Run npm run build.");return}d.statusCode=200,d.setHeader("Content-Type",La(g)),te.createReadStream(g).pipe(d);return}if(!k.startsWith("/api/")){d.statusCode=404,d.end(Z?"Dashboard assets not found. Install the full package or run `npm run build:dashboard`.":"Dashboard is disabled. API endpoints are still available.");return}d.statusCode=404,d.end("Dashboard is disabled. API endpoints are still available.")});return C.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(C),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((w,d)=>C.close(b=>{try{r?.close(),s?.close()}catch{}b?d(b):w()})))}}se();import{spawn as Zn}from"node:child_process";import{createWriteStream as Ga,existsSync as ht,lstatSync as Wa,mkdirSync as Ja,readdirSync as Ka,rmSync as Ft}from"node:fs";import er from"node:path";import{pipeline as qa}from"node:stream/promises";var Xe="0.28.0",ss="https://github.com/rtk-ai/rtk/releases",is=3e4,tr={"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"},Ha=200,za=5e3;function as(o){return Math.ceil(o.length/4)}function nr(o,e){let t=c=>c.split(".").map(u=>parseInt(u,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var ve=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return er.join(Wt(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(ht(t)){let n=await this.getVersion(t);if(n&&nr(n,Xe))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 ${Xe}). 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=tr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(tr).join(", ")}`);let s=o.binaryPath(),i=er.dirname(s);if(!e?.force&&ht(s)){let c=await this.getVersion(s);if(c&&nr(c,Xe))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${ss}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${ss}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),ht(i)||Ja(i,{recursive:!0});let l=er.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:u}=await import("node:fs");u(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{ht(l)&&Ft(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),is);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 qa(n.fromWeb(i.body),Ga(t))}catch(i){throw Ft(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${is}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=Zn("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((u,p)=>{l.on("close",y=>{y===0?u():p(new Error(`tar extraction failed with code ${y}`))}),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{Ft(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of Ka(e)){let s=er.join(e,r),i=Wa(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=Zn("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((u,p)=>{l.on("close",y=>{y===0?u():p(new Error(`PowerShell extraction failed with code ${y}`))}),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{Ft(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();ht(e)&&Ft(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return ht(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=Zn(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<Ha)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=as(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=as(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=Zn(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},za);i.stdout?.on("data",u=>{a+=u.toString()}),i.stderr?.on("data",u=>{l+=u.toString()}),i.stdin?.end(e,"utf8"),i.on("close",u=>{clearTimeout(c),u===0?n(a):r(new Error(`rtk exited with code ${u}: ${l}`))}),i.on("error",u=>{clearTimeout(c),r(u)})})}};import{randomUUID as Va}from"node:crypto";import Lr,{WebSocketServer as Xa}from"ws";var $r=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
307
+ `)},R="",O=[];try{let I=await o.agent.processDirectResult(P,f,"cli","dashboard",async(z,L)=>{if(L?.thinkingContent&&(R=L.thinkingContent),Array.isArray(L?.tool_calls)&&(O=L.tool_calls),L?.tool_call&&typeof L.tool_call=="object"){let de=L.tool_call,ke=typeof de.id=="string"?de.id:"";O=O.some(tt=>tt.id===ke)?O.map(tt=>tt.id===ke?{...tt,...de}:tt):[...O,de]}switch(L?.event){case"thinking":C({type:"thinking",content:L.thinkingContent??z});break;case"tool_calls":C({type:"tool_calls",tool_calls:O});break;case"tool_result":C({type:"tool_result",tool_call:L.tool_call,tool_calls:O});break;case"answer":C({type:"answer",content:z});break;default:C({type:"progress",content:z,toolHint:!!L?.toolHint,...L?.tool_calls?{tool_calls:L.tool_calls}:{}});break}},{...S?{_model:S}:{},...x?{_provider:x}:{},...Array.isArray(m.skillNames)&&m.skillNames.length?{skillNames:m.skillNames}:{}});I.outcome==="rate_limited"?C({type:"error",error:I.content,outcome:I.outcome,retryAfterMs:I.retryAfterMs??0}):I.outcome==="backpressure"||I.outcome==="shutdown"?C({type:"error",error:I.content,outcome:I.outcome}):C({type:"done",response:I.content,thinkingContent:R,tool_calls:O})}catch(I){C({type:"error",error:String(I)})}finally{d.end()}return}if(b==="POST"&&w==="/api/chat"){let m=await te(v),g=m.message,f=String(m.session??"default:everclaw"),S=String(m.model??"").trim(),x=String(m._provider??"").trim(),P=Array.isArray(g)?g:String(g??"").trim();if(typeof P=="string"&&!P)return y(d,400,{error:"message required"});if(Array.isArray(P)&&P.length===0)return y(d,400,{error:"message required"});let C=[];try{let R=await o.agent.processDirectResult(P,f,"cli","dashboard",async(O,I)=>{C.push({content:O,toolHint:!!I?.toolHint,...I?.tool_calls?{tool_calls:I.tool_calls}:{}})},{...S?{_model:S}:{},...x?{_provider:x}:{}});return R.outcome==="rate_limited"?(d.setHeader("Retry-After",String(Math.max(1,Math.ceil((R.retryAfterMs??0)/1e3)))),y(d,429,{error:R.content,outcome:R.outcome,retryAfterMs:R.retryAfterMs??0,progress:C})):R.outcome==="backpressure"||R.outcome==="shutdown"?y(d,503,{error:R.content,outcome:R.outcome,progress:C}):y(d,200,{response:R.content,progress:C})}catch(R){return y(d,500,{error:String(R)})}}if(b==="GET"&&w==="/api/config")return y(d,200,ul($()));if(b==="GET"&&w==="/api/security/status"){let{ToolGuardEngine:m}=await Promise.resolve().then(()=>(zr(),ps)),f=m.getInstance().getRules(),S=f.filter(P=>P.enabled),x=$();return y(d,200,{toolGuard:{enabled:x.security?.toolGuard?.enabled??!1,totalRules:f.length,enabledRules:S.length,defaultRules:f.filter(P=>!P.id.startsWith("user-")).length,userRules:x.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:x.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&w==="/api/config"){let m=await te(v),g=Ve(m.config)?m.config:null;if(!g)return y(d,400,{error:"Request body must include a config object."});let f=pl(g),S=$(),x=m.secretChanges;S.security?.auth&&f.security?.auth&&"pinHash"in S.security.auth&&(f.security.auth.pinHash=S.security.auth.pinHash);try{if(f.providers&&S.providers)for(let C of Object.keys(f.providers))f.providers[C]&&S.providers[C]&&pt(f,S,x,["providers",C,"apiKey"]);if(Array.isArray(f.customLlmProviders)&&Array.isArray(S.customLlmProviders))for(let C=0;C<f.customLlmProviders.length;C++){let R=f.customLlmProviders[C];if(!R)continue;let I=S.customLlmProviders.find(de=>de?.name===R.name)?.apiKey??"",z=R.apiKey??"",L=Ts(x,["customLlmProviders",C,"apiKey"],I,z);L&&(R.apiKey=L.action==="keep"?I:L.action==="clear"?"":L.value??z)}if(f.channels&&S.channels&&(pt(f,S,x,["channels","telegram","token"]),pt(f,S,x,["channels","discord","token"])),f.tools?.browserRelay&&S.tools?.browserRelay&&pt(f,S,x,["tools","browserRelay","authToken"]),f.tools?.web?.search&&S.tools?.web?.search&&pt(f,S,x,["tools","web","search","apiKey"]),f.tools?.mcpServers&&S.tools?.mcpServers)for(let C of Object.keys(f.tools.mcpServers)){let R=f.tools.mcpServers[C];if(R?.env)for(let O of Object.keys(R.env))pt(f,S,x,["tools","mcpServers",C,"env",O]);if(R?.headers)for(let O of Object.keys(R.headers))pt(f,S,x,["tools","mcpServers",C,"headers",O])}}catch(C){return y(d,400,{error:C instanceof Error?C.message:String(C)})}if(f.security?.auth?.enabled&&!f.security?.auth?.pinHash?.length)return y(d,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let P=ml(f.tools?.mcpServers??{});return P.length?y(d,400,{error:`Invalid MCP server configuration. ${P[0]}`,details:P}):(re(f),l.updateConfig(f.security.auth),y(d,200,{ok:!0}))}if(b==="GET"&&w==="/api/subagents"){let m=$();return y(d,200,{subagents:m.subagents||[]})}if(b==="POST"&&w==="/api/subagents"){let m=await te(v),g=$();g.subagents||(g.subagents=[]);let f=g.subagents.length,S={id:`subagent-${Date.now()}`,name:m.name||`SubAgent ${f+1}`,task:m.task||"",createdAt:Date.now()};return g.subagents.push(S),re(g),y(d,200,S)}let K=w.match(/^\/api\/subagents\/([^/]+)$/);if(K&&b==="PUT"){let m=K[1];if(!m)return y(d,400,"Invalid subagent ID");let g=await te(v),f=$();f.subagents||(f.subagents=[]);let S=f.subagents.findIndex(C=>C.id===m);if(S===-1)return y(d,404,{error:"Subagent not found"});let x=f.subagents[S];if(!x)return y(d,404,{error:"Subagent not found"});let P={id:g.id??x.id,name:g.name??x.name,task:g.task??x.task,createdAt:g.createdAt??x.createdAt};return f.subagents[S]=P,re(f),y(d,200,P)}if(K&&b==="DELETE"){let m=K[1],g=$();g.subagents||(g.subagents=[]);let f=g.subagents.findIndex(S=>S.id===m);return f===-1?y(d,404,{error:"Subagent not found"}):(g.subagents.splice(f,1),re(g),y(d,200,{ok:!0}))}if(b==="GET"&&w==="/api/skills")try{return y(d,200,n.getSnapshot())}catch(m){return y(d,500,{error:String(m)})}if(b==="POST"&&w==="/api/skills/install"){let m=await te(v);try{let g=await n.install(String(m.slug??""));return y(d,200,g)}catch(g){return y(d,400,{error:g instanceof Error?g.message:String(g)})}}if(b==="GET"&&w==="/api/cron/jobs"){let m=_.searchParams.get("all")==="1";return y(d,200,o.cron.listJobs(m))}if(b==="POST"&&w==="/api/cron/jobs"){let m=await te(v);try{let g={name:String(m.name??"job"),schedule:m.schedule,message:String(m.message??""),deliver:!!m.deliver,deleteAfterRun:!!m.deleteAfterRun};m.channel&&(g.channel=String(m.channel)),m.to&&(g.to=String(m.to));let f=o.cron.addJob(g);return y(d,200,f)}catch(g){return y(d,400,{error:String(g)})}}if(N&&b==="DELETE"){let m=N[1];return m?y(d,200,{ok:o.cron.removeJob(m)}):y(d,400,"Invalid job ID")}if(N&&b==="PUT"){let m=N[1];if(!m)return y(d,400,"Invalid job ID");let g=await te(v),f={};g.name!==void 0&&(f.name=String(g.name)),g.schedule!==void 0&&(f.schedule=g.schedule),g.message!==void 0&&(f.message=String(g.message)),g.deliver!==void 0&&(f.deliver=!!g.deliver),g.channel!==void 0&&(f.channel=String(g.channel)),g.to!==void 0&&(f.to=String(g.to)),g.deleteAfterRun!==void 0&&(f.deleteAfterRun=!!g.deleteAfterRun);let S=o.cron.updateJob(m,f);return S?y(d,200,S):y(d,404,{error:"not found"})}if(U&&b==="POST"){let g=(await te(v)).enabled!==!1,f=U[1];if(!f)return y(d,400,"Invalid job ID");let S=o.cron.enableJob(f,g);return S?y(d,200,S):y(d,404,{error:"not found"})}if(D&&b==="POST"){let m=await te(v),g=D[1];if(!g)return y(d,400,"Invalid job ID");let f=await o.cron.runJob(g,!!m.force);return y(d,200,{ok:f})}let ne=o.config.gateway.dashboard?.enabled!==!1;if(ne&&e){let m=be.resolve(e,w==="/"?"index.html":w.slice(1));if(!m.startsWith(be.resolve(e)+be.sep)&&m!==be.resolve(e)&&(m=be.join(e,"index.html")),(!le.existsSync(m)||le.statSync(m).isDirectory())&&(m=be.join(e,"index.html")),!le.existsSync(m)){d.statusCode=404,d.end("Dashboard assets not found. Run npm run build.");return}d.statusCode=200,d.setHeader("Content-Type",cl(m)),le.createReadStream(m).pipe(d);return}if(!w.startsWith("/api/")){d.statusCode=404,d.end(ne?"Dashboard assets not found. Install the full package or run `npm run build:dashboard`.":"Dashboard is disabled. API endpoints are still available.");return}d.statusCode=404,d.end("Dashboard is disabled. API endpoints are still available.")});return T.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(T),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((v,d)=>T.close(b=>{try{r?.close(),s?.close()}catch{}b?d(b):v()})))}}ue();import{spawn as br}from"node:child_process";import{createWriteStream as yl,existsSync as Nt,lstatSync as bl,mkdirSync as vl,readdirSync as wl,rmSync as cn}from"node:fs";import vr from"node:path";import{pipeline as Sl}from"node:stream/promises";var we="0.28.0",As="https://github.com/rtk-ai/rtk/releases",Es=3e4,wr={"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"},kl=200,xl=5e3;function Ps(o){return Math.ceil(o.length/4)}function ft(o,e){let t=c=>c.split(".").map(u=>parseInt(u,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var Se=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return vr.join(dn(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Nt(t)){let n=await this.getVersion(t);if(n&&ft(n,we))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 ${we}). 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=wr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(wr).join(", ")}`);let s=o.binaryPath(),i=vr.dirname(s);if(!e?.force&&Nt(s)){let c=await this.getVersion(s);if(c&&ft(c,we))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${As}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${As}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Nt(i)||vl(i,{recursive:!0});let l=vr.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:u}=await import("node:fs");u(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{Nt(l)&&cn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),Es);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 Sl(n.fromWeb(i.body),yl(t))}catch(i){throw cn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${Es}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=br("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((u,p)=>{l.on("close",h=>{h===0?u():p(new Error(`tar extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{cn(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of wl(e)){let s=vr.join(e,r),i=bl(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=br("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((u,p)=>{l.on("close",h=>{h===0?u():p(new Error(`PowerShell extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{cn(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Nt(e)&&cn(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Nt(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=br(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<kl)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=Ps(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=Ps(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=br(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},xl);i.stdout?.on("data",u=>{a+=u.toString()}),i.stderr?.on("data",u=>{l+=u.toString()}),i.stdin?.end(e,"utf8"),i.on("close",u=>{clearTimeout(c),u===0?n(a):r(new Error(`rtk exited with code ${u}: ${l}`))}),i.on("error",u=>{clearTimeout(c),r(u)})})}};import{randomUUID as Cl}from"node:crypto";import Zr,{WebSocketServer as Tl}from"ws";var eo=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
308
308
  \r
309
309
  Browser relay is disabled`),t.destroy();return}if(s!==this.config.authToken){t.write(`HTTP/1.1 401 Unauthorized\r
310
310
  \r
311
- Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new Xa({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===Lr.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===Lr.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!==Lr.OPEN)throw new Error("Extension not connected");let r=Va(),s={id:r,method:e,params:t};return new Promise((i,a)=>{let l=setTimeout(()=>{this.extension?.pendingCommands.delete(r),a(new Error("Command timeout"))},n);this.extension.pendingCommands.set(r,{resolve:i,reject:a,timeout:l}),this.extension.ws.send(JSON.stringify(s))})}async listTabs(){return await this.sendCommand("tabs.list")}async navigate(e,t){await this.sendCommand("tabs.navigate",{tabId:e,url:t})}async click(e,t){await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
311
+ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new Tl({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===Zr.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===Zr.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!==Zr.OPEN)throw new Error("Extension not connected");let r=Cl(),s={id:r,method:e,params:t};return new Promise((i,a)=>{let l=setTimeout(()=>{this.extension?.pendingCommands.delete(r),a(new Error("Command timeout"))},n);this.extension.pendingCommands.set(r,{resolve:i,reject:a,timeout:l}),this.extension.ws.send(JSON.stringify(s))})}async listTabs(){return await this.sendCommand("tabs.list")}async navigate(e,t){await this.sendCommand("tabs.navigate",{tabId:e,url:t})}async click(e,t){await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
312
312
  const el = document.querySelector(${JSON.stringify(t)});
313
313
  if (!el) throw new Error('Element not found: ' + ${JSON.stringify(t)});
314
314
  el.scrollIntoView({ block: 'center' });
@@ -321,32 +321,105 @@ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.ha
321
321
  el.focus();
322
322
  if (el.value !== undefined) el.value = '';
323
323
  return 'focused';
324
- })()`,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 ls(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new $r(t,e)}Pr();function Ya(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function Qa(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var rr=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:Ya(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=Qa(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})}};Nt();import Za from"node:path";import el from"node:os";var cs=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],ds=["command","cmd"],tl=[{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."}],us=el.homedir();function nl(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,us),e=e.replace(/\$HOME(?=[/\\])/,us),e}function rl(o,e){let t=[];for(let n of cs){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 ds){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!cs.includes(n)&&!ds.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var or=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=rl(r,n);for(let i of s){let a=nl(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let u=this.checkWorkspaceEscape(a,n);u&&t.push(u)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of tl)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(!Za.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"}};Nt();import Dr from"node:fs";import ms from"node:path";var ol=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"]),sl=8192,il=.01;function al(o){let e=Math.min(o.length,sl);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=il}var sr=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(ol.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let y;try{y=Dr.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(al(y)){i.skippedFiles++;continue}let C=y.toString("utf8"),w={filePath:p.absPath,extension:p.ext,size:p.size,content:C};for(let d of this.analyzers){let b=d.analyze(w);a.push(...b)}i.scannedFiles++}let c=ll(a),u=!a.some(p=>p.severity==="CRITICAL"||p.severity==="HIGH");return{skillName:t,findings:a,isSafe:u,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=Dr.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=ms.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=Dr.lstatSync(i),l=ms.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function ll(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"}Nt();se();import cl from"node:fs";var dl=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"]),ul=8192,ml=.01,ir=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=_e("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=cl.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,ul);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=ml}isSkippedExtension(e){return dl.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:Dt[i.category]??"COMMAND_INJECTION",severity:$t[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};async function gs(o){let e=structuredClone(o?.config??O()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=Y(e.agents.defaults.workspace);Ue(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:
324
+ })()`,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 Is(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new eo(t,e)}zr();function Rl(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function Al(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Sr=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:Rl(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=Al(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})}};sn();import El from"node:path";import Pl from"node:os";var Ms=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],_s=["command","cmd"],Il=[{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."}],Os=Pl.homedir();function Ml(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,Os),e=e.replace(/\$HOME(?=[/\\])/,Os),e}function _l(o,e){let t=[];for(let n of Ms){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 _s){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!Ms.includes(n)&&!_s.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var kr=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=_l(r,n);for(let i of s){let a=Ml(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let u=this.checkWorkspaceEscape(a,n);u&&t.push(u)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of Il)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(!El.isAbsolute(e))return null;try{_e(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"}};sn();import to from"node:fs";import $s from"node:path";var Ol=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"]),$l=8192,Ll=.01;function Nl(o){let e=Math.min(o.length,$l);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=Ll}var Xe=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(Ol.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let h;try{h=to.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(Nl(h)){i.skippedFiles++;continue}let T=h.toString("utf8"),v={filePath:p.absPath,extension:p.ext,size:p.size,content:T};for(let d of this.analyzers){let b=d.analyze(v);a.push(...b)}i.scannedFiles++}let c=Dl(a),u=!a.some(p=>p.severity==="CRITICAL"||p.severity==="HIGH");return{skillName:t,findings:a,isSafe:u,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=to.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=$s.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=to.lstatSync(i),l=$s.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function Dl(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"}sn();ue();import jl from"node:fs";var Fl=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"]),Bl=8192,Gl=.01,Ye=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=We("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=jl.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,Bl);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=Gl}isSkippedExtension(e){return Fl.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:on[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}};async function Ls(o){let e=structuredClone(o?.config??$()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=V(e.agents.defaults.workspace);rt(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:
325
325
  1. Set security.auth.enabled = true and configure a PIN
326
326
  2. Set gateway.host = 127.0.0.1 (loopback only)
327
- 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new Je,c=o?.provider??ye(e),u=new Le(n),p=Te(),y=new ft(n,p),C=Un(e.tools.exec.timeout),w=Ot({target:"scheduled-job",timeoutMs:C}),d=Ot({target:"background-job",timeoutMs:C}),{cron:b,heartbeat:I,lifecycle:k}=Ee({cron:{dataDir:p,onJob:async(L,Q)=>{let W=await w.run({payload:{message:L.payload.message,session:`cron:${L.id}`,channel:L.payload.channel??"cli",chatId:L.payload.to??"direct"},cwd:process.cwd(),signal:Q?.signal});if(L.payload.deliver&&L.payload.to){let Z=L.payload.channel??"cli",g=L.payload.to;await l.publishOutbound({channel:Z,chatId:g,content:W});try{y.record({jobId:L.id,jobName:L.name,sessionKey:`cron:${L.id}`,channel:Z,recipient:g,content:W})}catch(m){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${L.id}: ${m instanceof Error?m.message:String(m)}`)}}return W}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(L,Q)=>{let Z=u.listSessions().find(f=>(f.key??"").includes(":"))?.key??"cli:direct",[g,m]=Z.split(/:(.*)/s,2);return d.run({payload:{message:L,session:"heartbeat",channel:g||"cli",chatId:m||"direct"},cwd:process.cwd(),signal:Q?.signal})},onNotify:async L=>{let W=u.listSessions().find(m=>(m.key??"").includes(":"))?.key??"",[Z,g]=W?W.split(/:(.*)/s,2):["cli","direct"];Z!=="cli"&&Z&&await l.publishOutbound({channel:Z,chatId:g??"direct",content:L})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!I)throw new Error("Builtin heartbeat job registration is missing");let $,j;e.security.enabled&&(e.security.toolGuard.enabled&&($=jt.getInstance(e),$.registerGuardian(new rr($.getRules())),$.registerGuardian(new or(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(j=new sr([new ir]),console.log("[security] Skill scanner initialized")));let M=new ve,N=await M.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 q=null;if(e.tools.browserRelay.enabled&&e.tools.browserRelay.authToken){let L=ls(e,Q=>{Q.connected&&console.log(`[browser-relay] Extension connected, ${Q.attachedTabs.length} tabs attached`)});L&&(q=L,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let ge=new mt({bus:l,provider:c,workspace:n,sessionManager:u,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:k,loadConfig:O,rtkConfig:e.tools.rtk,rtkService:M,...$?{guardEngine:$}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...j?{skillScanner:j}:{},...q?{browserRelay:q}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),F=new Jn(e,l,k),H=os({agent:ge,cron:b,config:e,dataDir:p,port:t,sessionManager:u,sessionKey:o?.sessionKey??"default:everclaw",inboxService:y,workspacePath:n,...q?{browserRelay:q}:{}});await b.start(),await I.start();let ne=ge.run();return await F.startAll(),{config:e,workspace:n,port:H.port,loop:ge,heartbeat:I,cron:b,channels:F,dashboard:H,enabledChannels:F.enabledChannels,runPromise:ne,browserRelay:q}}async function ps(o){o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),at.getInstance().stopAll(),await o.dashboard.close(),e}import V from"chalk";import{Command as gl}from"commander";function fs(){let o=new gl("rtk").description("Manage rtk token compression binary");return 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 ve;try{let n=await t.install({version:e.version,force:e.force});console.log(V.green(`
328
- rtk v${n.version} installed to ${n.binaryPath}`)),console.log(V.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(V.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=1}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new ve,t=await e.getStatus();if(!t.installed){console.log(V.yellow("rtk is not installed."));return}await e.uninstall(),console.log(V.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new ve().getStatus();console.log(V.cyan(`
327
+ 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new it,c=o?.provider??Te(e),u=new He(n),p=Pe(),h=new Lt(n,p),T=ir(e.tools.exec.timeout),v=tn({target:"scheduled-job",timeoutMs:T}),d=tn({target:"background-job",timeoutMs:T}),{cron:b,heartbeat:_,lifecycle:w}=Be({cron:{dataDir:p,onJob:async(M,j)=>{let K=await v.run({payload:{message:M.payload.message,session:`cron:${M.id}`,channel:M.payload.channel??"cli",chatId:M.payload.to??"direct"},cwd:process.cwd(),signal:j?.signal});if(M.payload.deliver&&M.payload.to){let ne=M.payload.channel??"cli",m=M.payload.to;await l.publishOutbound({channel:ne,chatId:m,content:K});try{h.record({jobId:M.id,jobName:M.name,sessionKey:`cron:${M.id}`,channel:ne,recipient:m,content:K})}catch(g){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${M.id}: ${g instanceof Error?g.message:String(g)}`)}}return K}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(M,j)=>{let ne=u.listSessions().find(f=>(f.key??"").includes(":"))?.key??"cli:direct",[m,g]=ne.split(/:(.*)/s,2);return d.run({payload:{message:M,session:"heartbeat",channel:m||"cli",chatId:g||"direct"},cwd:process.cwd(),signal:j?.signal})},onNotify:async M=>{let K=u.listSessions().find(g=>(g.key??"").includes(":"))?.key??"",[ne,m]=K?K.split(/:(.*)/s,2):["cli","direct"];ne!=="cli"&&ne&&await l.publishOutbound({channel:ne,chatId:m??"direct",content:M})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!_)throw new Error("Builtin heartbeat job registration is missing");let F,A;e.security.enabled&&(e.security.toolGuard.enabled&&(F=an.getInstance(e),F.registerGuardian(new Sr(F.getRules())),F.registerGuardian(new kr(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(A=new Xe([new Ye]),console.log("[security] Skill scanner initialized")));let N=new Se,U=await N.resolve(e.tools.rtk);U.available?console.log(`rtk ${U.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 M=Is(e,j=>{j.connected&&console.log(`[browser-relay] Extension connected, ${j.attachedTabs.length} tabs attached`)});M&&(D=M,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let ie=new _t({bus:l,provider:c,workspace:n,sessionManager:u,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:w,loadConfig:$,rtkConfig:e.tools.rtk,rtkService:N,...F?{guardEngine:F}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...A?{skillScanner:A}:{},...D?{browserRelay:D}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),W=new cr(e,l,w),Q=Rs({agent:ie,cron:b,config:e,dataDir:p,port:t,sessionManager:u,sessionKey:o?.sessionKey??"default:everclaw",inboxService:h,workspacePath:n,channelManager:W,...D?{browserRelay:D}:{}});await b.start(),await _.start();let E=ie.run();return await W.startAll(),{config:e,workspace:n,port:Q.port,loop:ie,heartbeat:_,cron:b,channels:W,dashboard:Q,enabledChannels:W.enabledChannels,runPromise:E,browserRelay:D}}async function no(o){o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),At.getInstance().stopAll(),await o.dashboard.close(),e}import B from"chalk";import{Command as Ul}from"commander";Ie();var q={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function Ns(){let o=new Ul("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
328
+ Examples:
329
+ everclaw rtk install Install the latest rtk binary
330
+ everclaw rtk update Update to the latest version
331
+ 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 Se;try{let n=await t.install({version:e.version,force:e.force});console.log(B.green(`
332
+ rtk v${n.version} installed to ${n.binaryPath}`)),console.log(B.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(B.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=q.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Se,t=await e.getStatus();if(!t.installed){console.log(B.yellow("rtk is not installed."));return}await e.uninstall(),console.log(B.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new Se().getStatus(),n=$();console.log(B.cyan(`
329
333
  RTK Token Compression
330
- `)),t.installed&&t.version?(console.log(` Status: ${V.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),nr(t.version,Xe)||(console.log(V.yellow(` Warning: Version ${t.version} is below minimum ${Xe}`)),console.log(V.gray(` Run ${V.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${V.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(V.gray(` Run ${V.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${V.gray("Not installed")}`),console.log(V.gray(` Fix: Run ${V.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(V.gray(`
331
- Minimum version: ${Xe}`)),console.log(V.gray(` Supported platforms: ${Object.keys(tr).join(", ")}`))}),o}var fl=Xr(),hl="0.3.0";function yl(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 vs(o){let e=new pl;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(hl,"-v, --version","show version"),e.addCommand(fs()),o?.commands)for(let i of o.commands.values()){let a=e.command(i.contribution.name).description(i.contribution.description??"");i.contribution.builder&&i.contribution.builder(a),a.action(async l=>{await i.contribution.handler({},l)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").action(async i=>{let a=vt(),l=O();if(Ut.existsSync(a)){console.log(`Config already exists at ${a}`);let p=hs.createInterface({input:ys,output:bs}),y=(await p.question("Overwrite? [y/N] ")).trim().toLowerCase();p.close(),y==="y"?(l=structuredClone(Se),ie(l),console.log(`Config reset to defaults at ${a}`)):(ie(l),console.log(`Config refreshed at ${a} (existing values preserved)`))}else ie(l),console.log(`Created config at ${a}`);let c=Y(l.agents.defaults.workspace);if(Ut.existsSync(c)||(Ut.mkdirSync(c,{recursive:!0}),console.log(`Created workspace at ${c}`)),Ue(c),i.provider||i.model||i.apiKey||i.apiBase||i.channel||i.channelToken||i.noChannel){if(i.provider&&(l.agents.defaults.provider=i.provider),i.model&&(l.agents.defaults.model=i.model),i.apiKey){let p=l.agents.defaults.provider;if(p in l.providers){let y=l.providers[p];y&&(y.apiKey=i.apiKey)}}if(i.apiBase){let p=l.agents.defaults.provider;if(p in l.providers){let y=l.providers[p];y&&(y.apiBase=i.apiBase)}}if(i.noChannel||(i.channel==="telegram"&&i.channelToken?(l.channels.telegram.enabled=!0,l.channels.telegram.token=i.channelToken):i.channel==="discord"&&i.channelToken&&(l.channels.discord.enabled=!0,l.channels.discord.token=i.channelToken)),ie(l),console.log(P.green(`
332
- Config created via non-interactive mode.`)),!i.noTest){console.log(P.cyan(`
333
- Running connectivity test...`));try{let y=await ye(l).chat({messages:[{role:"user",content:"Reply with: OK"}],model:l.agents.defaults.model,maxTokens:16,temperature:0});(y.content||"").toLowerCase().includes("error")?console.log(P.red(`Connectivity test failed: ${y.content}`)):console.log(P.green(`Connectivity test passed: ${y.content??"(empty response)"}`))}catch(p){console.log(P.red(`Connectivity test failed: ${String(p)}`))}}console.log(P.yellow(`
334
- Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){console.log(P.cyan(`
335
- everclaw Setup Wizard`)),console.log(P.gray(`Use arrow keys to pick options.
336
- `));let p=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(p=!0)}catch{}p&&console.log(P.green(" Ollama detected on localhost:11434"));let y=await Ne({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:"Custom OpenAI-compatible provider",value:"custom"}]}),C=String(y.provider||"openrouter"),w=fl[C]??[l.agents.defaults.model],d=await Ne({type:"select",name:"model",message:"Choose your model",choices:w.map($=>({title:$,value:$}))}),b=String(d.model||w[0]),I="";if(C!=="vllm"&&C!=="ollama"){let $=await Ne({type:"password",name:"apiKey",message:"Enter API key",validate:j=>j&&j.trim().length>0?!0:"API key cannot be empty"});I=String($.apiKey||"")}if(l.agents.defaults.provider=C,l.agents.defaults.model=b,C in l.providers){let $=l.providers[C];$&&($.apiKey=I)}if(C==="custom"||C==="vllm"||C==="ollama"){let $=await Ne({type:"text",name:"apiBase",message:"Enter API base URL",initial:C==="ollama"?"http://localhost:11434/v1":C==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"}),j=String($.apiBase||"");if(C in l.providers){let M=l.providers[C];M&&(M.apiBase=j.trim())}}if((await Ne({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let $=await Ne({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),j=String($.channel||"telegram");if(j==="telegram"){let M=await Ne({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:N=>N&&N.trim().length>0?!0:"Token cannot be empty"});l.channels.telegram.enabled=!0,l.channels.telegram.token=String(M.token||"").trim()}else if(j==="discord"){let M=await Ne({type:"password",name:"token",message:"Enter Discord Bot Token",validate:N=>N&&N.trim().length>0?!0:"Token cannot be empty"});l.channels.discord.enabled=!0,l.channels.discord.token=String(M.token||"").trim()}}ie(l),console.log(P.green(`
337
- Configs created.`)),console.log(P.yellow("Run everclaw gateway")),console.log(P.yellow("or chat with agent: everclaw agent"));return}console.log(`
338
- everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${Fe}, then run everclaw gateway or everclaw agent.`)}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new Nr("--channel <channel>").default("cli").hideHelp()).addOption(new Nr("--chat-id <chatId>").default("direct").hideHelp()).addOption(new Nr("--raw-output").default(!1).hideHelp()).action(async i=>{let a=O(),l=Xt(a,process.env),c=Y(l.agents.defaults.workspace);Ue(c,!0);let u=new Je,p;try{p=ye(l)}catch(d){console.log(P.red(String(d))),process.exitCode=1;return}let y=new Le(c),{cron:C}=Ee({cron:{dataDir:Te()}}),w=new mt({bus:u,provider:p,workspace:c,model:l.agents.defaults.model,temperature:l.agents.defaults.temperature,maxTokens:l.agents.defaults.maxTokens,maxIterations:l.agents.defaults.maxToolIterations,memoryWindow:l.agents.defaults.memoryWindow,braveApiKey:l.tools.web.search.apiKey||null,execConfig:l.tools.exec,cronService:C,restrictToWorkspace:l.tools.restrictToWorkspace,channelsConfig:l.channels,loadConfig:O});if(i.message){let d=await w.processDirect(String(i.message),String(i.session),String(i.channel),String(i.chatId));i.rawOutput?process.stdout.write(d):console.log(`
334
+ `)),t.installed&&t.version?(console.log(` Status: ${B.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),ft(t.version,we)||(console.log(B.yellow(` Warning: Version ${t.version} is below minimum ${we}`)),console.log(B.gray(` Run ${B.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${B.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(B.gray(` Run ${B.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${B.gray("Not installed")}`),console.log(B.gray(` Fix: Run ${B.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?B.green("yes"):B.gray("no")}`),console.log(B.gray(`
335
+ Minimum version: ${we}`)),console.log(B.gray(` Supported platforms: ${Object.keys(wr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Se,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?B.cyan(`Current: v${n}`):B.gray("rtk is not installed."));try{console.log(B.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(B.green(`Already at latest version (v${r.version})`)):console.log(B.green(`
336
+ rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(B.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=q.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=$();if(e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,re(e),console.log(B.green("RTK token compression enabled.")),console.log(B.gray("Restart the gateway for changes to take effect."))}),o.command("disable").description("Disable rtk token compression in config").action(()=>{let e=$();if(!e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,re(e),console.log(B.yellow("RTK token compression disabled.")),console.log(B.gray("Restart the gateway for changes to take effect.")),console.log(B.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}wt();Ie();import H from"chalk";import{Command as Wl}from"commander";async function Kl(){let o=Me();if(!o)return!0;if(!Le(o.pid))return Ne(),!0;console.log(H.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(H.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await Ir(o.pid,1e4)){console.log(H.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return Ne(),console.log(H.green("Gateway stopped.")),!0}async function Ds(o){let e=$(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=Fs(o.port,e.gateway.port));let n=Ft(e,process.env,t),r=n.gateway.port,s=Me();if(s&&Le(s.pid)){console.error(H.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(H.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=q.PROCESS_CONFLICT;return}s&&Ne();let i;try{i=await Ls({config:n,port:r,sessionKey:"default:everclaw"})}catch(p){console.log(H.red(String(p))),process.exitCode=q.GENERAL_ERROR;return}Co({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(H.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(H.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(H.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(H.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(H.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async p=>a||(console.log(H.yellow(`
337
+ Received ${p}. Shutting down gateway...`)),Ne(process.pid),a=no(i).then(h=>{h>0&&console.log(H.gray(`Cancelled ${h} task(s) during shutdown.`))}).catch(h=>{process.exitCode=1,console.log(H.red(`Gateway shutdown failed: ${String(h)}`))}),a),c=()=>{l("SIGINT")},u=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",u);try{await i.runPromise,a&&await a}finally{Ne(process.pid),process.off("SIGINT",c),process.off("SIGTERM",u)}}function js(){let o=new Wl("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
338
+ Examples:
339
+ everclaw gateway Start the gateway (default)
340
+ everclaw gateway status Check if gateway is running
341
+ everclaw gateway restart Restart the gateway
342
+ everclaw gateway stop Stop a running gateway`),o.command("start",{isDefault:!0}).description("Start the everclaw gateway (default when no subcommand given)").option("-p, --port <port>","Gateway port",String(pe.gateway.port)).option("-H, --host <host>","Gateway bind address").action(async e=>{await Ds({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Me();if(!e){console.log(H.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=q.GENERAL_ERROR;return}if(!Le(e.pid)){console.log(H.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),Ne();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(H.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=q.GENERAL_ERROR;return}if(await Ir(e.pid,1e4))Ne(),console.log(H.green("Gateway stopped."));else{console.log(H.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}Ne(),console.log(H.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(pe.gateway.port)).option("-H, --host <host>","Gateway bind address").option("--force","Start even if stop fails",!1).action(async e=>{if(!await Kl()){if(!e.force){console.error(H.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=q.GENERAL_ERROR;return}console.log(H.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(H.cyan("Starting gateway...")),await Ds({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Me();if(!e){console.log(H.yellow("Gateway is not running (no PID file found)."));return}if(!Le(e.pid)){console.log(H.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=st(e.startedAt);console.log(H.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`),console.log(` Started: ${e.startedAt}`)}),o}import J from"chalk";import{Command as Jl}from"commander";import Qe from"node:fs";import Ze from"node:path";Ie();Ae();function Bs(){let o=new Jl("skills").description("Manage skills");return o.addHelpText("after",`
343
+ Examples:
344
+ everclaw skills list List all available skills
345
+ everclaw skills show browser Show details for a skill
346
+ everclaw skills create my-skill Create a new skill in workspace
347
+ 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=V(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new Xe([new Ye]):null,a=new De(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(J.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(J.gray("No available skills. Use --all to see all skills."));return}console.log(J.cyan(`
348
+ Skills
349
+ `)),console.log("Name".padEnd(28)+"Source".padEnd(12)+"Status".padEnd(12)+"Description"),console.log("-".repeat(80));for(let c of l){let u=c.status==="available"?J.green("available"):c.status==="blocked"?J.red("blocked"):J.yellow(c.status),p=c.description?.slice(0,40)??"";console.log(c.name.padEnd(28)+c.source.padEnd(12)+u.padEnd(20)+p)}console.log("")}),o.command("show <name>").description("Show skill details").action(e=>{let t=$(),n=V(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new Xe([new Ye]):null,l=new De(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(J.red(`Skill '${e}' not found.`)),console.log(J.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=q.GENERAL_ERROR;return}console.log(J.cyan(`
350
+ Skill: ${l.name}
351
+ `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?J.green("available"):J.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
352
+ Description: ${l.description}
353
+ `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=$(),n=V(t.agents.defaults.workspace),r=Ze.join(n,"skills"),s=Ze.join(r,e);if(!Qe.existsSync(s)){console.log(J.red(`Skill '${e}' not found in workspace skills.`)),console.log(J.gray("Only workspace-scoped skills can be removed.")),process.exitCode=q.GENERAL_ERROR;return}Qe.rmSync(s,{recursive:!0,force:!0}),console.log(J.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=$(),n=V(t.agents.defaults.workspace),r=Ze.join(n,"skills");if(!Qe.existsSync(r)){console.log(J.gray("No workspace skills directory found."));return}let s=new Xe([new Ye]),i=e?[e]:Qe.readdirSync(r).filter(a=>Qe.statSync(Ze.join(r,a)).isDirectory());if(i.length===0){console.log(J.gray("No skills to scan."));return}console.log(J.cyan(`
354
+ Skill Security Scan
355
+ `));for(let a of i){let l=Ze.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${J.green("passed")}`);else{console.log(`${a.padEnd(28)} ${J.red("blocked")}`);for(let u of c.findings)console.log(J.gray(` - ${u.severity}: ${u.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=$(),n=V(t.agents.defaults.workspace),r=Ze.join(n,"skills"),s=Ze.join(r,e);if(Qe.existsSync(s)){console.log(J.red(`Skill '${e}' already exists.`)),process.exitCode=q.GENERAL_ERROR;return}Qe.mkdirSync(s,{recursive:!0});let i=`---
356
+ name: ${e}
357
+ description: A custom skill
358
+ always_on: false
359
+ ---
360
+
361
+ # ${e}
362
+
363
+ TODO: Add skill instructions here.
364
+ `;Qe.writeFileSync(Ze.join(s,"SKILL.md"),i),console.log(J.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(!bn(e)){console.log(J.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=q.GENERAL_ERROR;return}let t=$(),n=V(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(ct(),Lo)),s=new r,i="clawhub@latest",a=12e4;console.log(J.cyan(`Installing skill '${e}'...`));try{let l=await s.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",i,"install",e,"--workdir",n]},cwd:n,env:{...process.env},timeoutMs:a,maxCaptureBytes:1048576});if(l.status!=="ok"){let u=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
365
+ `),p=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(J.red(`Failed to install skill '${e}'${p}: ${u||"unknown error"}`)),process.exitCode=q.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
366
+ `);console.log(J.green(`Skill '${e}' installed successfully.`)),c&&console.log(J.gray(c)),console.log(J.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(J.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=q.CONNECTIVITY_ERROR}}),o}Ie();import Z from"chalk";import{Command as ql}from"commander";function Hl(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function Gs(){let o=new ql("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
367
+ Examples:
368
+ everclaw mcp list List configured servers
369
+ everclaw mcp add fs --command npx --args "-y @anthropic/mcp-server-filesystem /path"
370
+ everclaw mcp test fs Test connectivity
371
+ 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(Z.gray("No MCP servers configured.")),console.log(Z.gray(`Run ${Z.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(Z.cyan(`
372
+ MCP Servers
373
+ `)),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)+Hl(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(Z.red("Error: Either --command or --url is required.")),process.exitCode=q.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(Z.red("Error: --timeout must be a positive integer.")),process.exitCode=q.GENERAL_ERROR;return}n=i}let r=$(),s=r.tools.mcpServers;if(s[e]){console.log(Z.yellow(`MCP server '${e}' already exists.`)),process.exitCode=q.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},re(r),console.log(Z.green(`Added MCP server '${e}'.`)),console.log(Z.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(Z.red(`MCP server '${e}' not found.`)),process.exitCode=q.GENERAL_ERROR;return}delete n[e],re(t),console.log(Z.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(Z.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(Z.cyan(`
374
+ MCP Server: ${e}
375
+ `)),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(Z.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(Z.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(Z.cyan(`
376
+ MCP Connectivity Test
377
+ `));let{McpClientManager:s}=await Promise.resolve().then(()=>(en(),or)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${Z.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${Z.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=q.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(Z.red(`MCP server '${e}' not found.`)),process.exitCode=q.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(en(),or)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(Z.gray(`No tools exposed by '${e}'.`));else{console.log(Z.cyan(`
378
+ Tools from ${e} (${i.length})
379
+ `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(Z.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=q.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}var Vl=yo(),Xl="0.3.0";function Fs(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 Js(){if(process.env.DOCKER==="true"||ce.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(ce.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function Yl(o){if(process.platform==="win32")return null;try{let{execSync:e}=zs("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
380
+ `);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}}function qs(o){let e=new zl;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(Xl,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
381
+ Examples:
382
+ everclaw onboard Interactive setup wizard
383
+ everclaw gateway Start the gateway server
384
+ everclaw agent -m "Hello" Send a single message to the agent
385
+ everclaw doctor Check system health and connectivity
386
+ everclaw status Show gateway status
387
+
388
+ Documentation: https://docs.everclaw.ai`),e.addCommand(Ns()),e.addCommand(Bs()),e.addCommand(Gs()),e.addCommand(js()),o?.commands)for(let i of o.commands.values()){let a=e.command(i.contribution.name).description(i.contribution.description??"");i.contribution.builder&&i.contribution.builder(a),a.action(async l=>{await i.contribution.handler({},l)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").action(async i=>{let a=St(),l=$();if(ce.existsSync(a)){console.log(`Config already exists at ${a}`);let p=Us.createInterface({input:Ws,output:Ks}),h=(await p.question("Overwrite? [y/N] ")).trim().toLowerCase();p.close(),h==="y"?(l=structuredClone(pe),re(l),console.log(`Config reset to defaults at ${a}`)):(re(l),console.log(`Config refreshed at ${a} (existing values preserved)`))}else re(l),console.log(`Created config at ${a}`);let c=V(l.agents.defaults.workspace);if(ce.existsSync(c)||(ce.mkdirSync(c,{recursive:!0}),console.log(`Created workspace at ${c}`)),rt(c),i.provider||i.model||i.apiKey||i.apiBase||i.channel||i.channelToken||i.noChannel){if((i.provider??l.agents.defaults.provider)==="custom"&&i.apiKey&&i.apiBase){let h;try{h=new URL(i.apiBase).hostname.replace(/\./g,"-")}catch{h="custom-provider"}l.customLlmProviders.push({name:h,baseUrl:i.apiBase,apiKey:i.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),l.agents.defaults.provider=jt(h)}else{if(i.provider&&(l.agents.defaults.provider=i.provider),i.apiKey){let h=l.agents.defaults.provider;if(h in l.providers){let T=l.providers[h];T&&(T.apiKey=i.apiKey)}}if(i.apiBase){let h=l.agents.defaults.provider;if(h in l.providers){let T=l.providers[h];T&&(T.apiBase=i.apiBase)}}}if(i.model&&(l.agents.defaults.model=i.model),i.noChannel||(i.channel==="telegram"&&i.channelToken?(l.channels.telegram.enabled=!0,l.channels.telegram.token=i.channelToken):i.channel==="discord"&&i.channelToken&&(l.channels.discord.enabled=!0,l.channels.discord.token=i.channelToken)),re(l),console.log(k.green(`
389
+ Config created via non-interactive mode.`)),!i.noTest){console.log(k.cyan(`
390
+ Running connectivity test...`));try{let T=await Te(l).chat({messages:[{role:"user",content:"Reply with: OK"}],model:l.agents.defaults.model,maxTokens:16,temperature:0});(T.content||"").toLowerCase().includes("error")?console.log(k.red(`Connectivity test failed: ${T.content}`)):console.log(k.green(`Connectivity test passed: ${T.content??"(empty response)"}`))}catch(h){console.log(k.red(`Connectivity test failed: ${String(h)}`))}}console.log(k.yellow(`
391
+ Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){console.log(k.cyan(`
392
+ everclaw Setup Wizard`)),console.log(k.gray(`Use arrow keys to pick options.
393
+ `));let p=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(p=!0)}catch{}p&&console.log(k.green(" Ollama detected on localhost:11434"));let h=await et({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"}]}),T=String(h.provider||"openrouter"),v=Vl[T]??[l.agents.defaults.model],d=await et({type:"select",name:"model",message:"Choose your model",choices:v.map(A=>({title:A,value:A}))}),b=String(d.model||v[0]),_="";if(T!=="vllm"&&T!=="ollama"){let A=await et({type:"password",name:"apiKey",message:"Enter API key",validate:N=>N&&N.trim().length>0?!0:"API key cannot be empty"});_=String(A.apiKey||"")}let w="";if(T==="custom"||T==="vllm"||T==="ollama"){let A=await et({type:"text",name:"apiBase",message:"Enter API base URL",initial:T==="ollama"?"http://localhost:11434/v1":T==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"});w=String(A.apiBase||"").trim()}if(T==="custom"){let A;try{A=new URL(w).hostname.replace(/\./g,"-")}catch{A="custom-provider"}l.customLlmProviders.push({name:A,baseUrl:w,apiKey:_,apiFormat:"v1/chat/completions",models:[{id:b,displayName:b}],extraHeaders:null}),l.agents.defaults.provider=jt(A),l.agents.defaults.model=b}else{if(l.agents.defaults.provider=T,l.agents.defaults.model=b,T in l.providers){let A=l.providers[T];A&&(A.apiKey=_)}if((T==="vllm"||T==="ollama")&&w&&T in l.providers){let A=l.providers[T];A&&(A.apiBase=w)}}if((await et({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let A=await et({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),N=String(A.channel||"telegram");if(N==="telegram"){let U=await et({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:D=>D&&D.trim().length>0?!0:"Token cannot be empty"});l.channels.telegram.enabled=!0,l.channels.telegram.token=String(U.token||"").trim()}else if(N==="discord"){let U=await et({type:"password",name:"token",message:"Enter Discord Bot Token",validate:D=>D&&D.trim().length>0?!0:"Token cannot be empty"});l.channels.discord.enabled=!0,l.channels.discord.token=String(U.token||"").trim()}}re(l),console.log(k.green(`
394
+ Configs created.`)),console.log(k.yellow("Run everclaw gateway")),console.log(k.yellow("or chat with agent: everclaw agent"));return}console.log(`
395
+ everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${nt}, then run everclaw gateway or everclaw agent.`)}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new ro("--channel <channel>").default("cli").hideHelp()).addOption(new ro("--chat-id <chatId>").default("direct").hideHelp()).addOption(new ro("--raw-output").default(!1).hideHelp()).action(async i=>{let a=$(),l=Ft(a,process.env),c=V(l.agents.defaults.workspace);rt(c,!0);let u=new it,p;try{p=Te(l)}catch(d){console.log(k.red(String(d))),process.exitCode=1;return}let h=new He(c),{cron:T}=Be({cron:{dataDir:Pe()}}),v=new _t({bus:u,provider:p,workspace:c,model:l.agents.defaults.model,temperature:l.agents.defaults.temperature,maxTokens:l.agents.defaults.maxTokens,maxIterations:l.agents.defaults.maxToolIterations,memoryWindow:l.agents.defaults.memoryWindow,braveApiKey:l.tools.web.search.apiKey||null,execConfig:l.tools.exec,cronService:T,restrictToWorkspace:l.tools.restrictToWorkspace,channelsConfig:l.channels,loadConfig:$});if(i.message){let d=await v.processDirect(String(i.message),String(i.session),String(i.channel),String(i.chatId));i.rawOutput?process.stdout.write(d):console.log(`
339
396
  everclaw
340
397
  ${d}
341
- `)}else{console.log("Interactive mode (type exit to quit)");let d=hs.createInterface({input:ys,output:bs});for(;;){let b=await d.question("You: "),I=b.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(I))break;let k=await w.processDirect(b,String(i.session));console.log(`
398
+ `)}else{console.log("Interactive mode (type exit to quit)");let d=Us.createInterface({input:Ws,output:Ks});for(;;){let b=await d.question("You: "),_=b.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(_))break;let w=await v.processDirect(b,String(i.session));console.log(`
342
399
  everclaw
343
- ${k}
344
- `)}d.close()}}),e.command("gateway").description("Start the everclaw gateway").option("-p, --port <port>","Gateway port",String(Se.gateway.port)).option("-H, --host <host>","Gateway bind address").action(async i=>{let a=O(),l={};i.host&&(l.gatewayHost=i.host),i.port&&(l.gatewayPort=yl(i.port,a.gateway.port));let c=Xt(a,process.env,l),u=c.gateway.port,p;try{p=await gs({config:c,port:u,sessionKey:"default:everclaw"})}catch(b){console.log(P.red(String(b)));return}console.log(P.cyan(`Starting everclaw gateway on port ${p.port}...`)),p.enabledChannels.length?console.log(P.green(`Channels enabled: ${p.enabledChannels.join(", ")}`)):console.log(P.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(P.green(`Dashboard: http://localhost:${p.port}/chat`)),console.log(P.gray("Gateway running. Press Ctrl+C to stop."));let y=null,C=async b=>y||(console.log(P.yellow(`
345
- Received ${b}. Shutting down gateway...`)),y=ps(p).then(I=>{I>0&&console.log(P.gray(`Cancelled ${I} task(s) during shutdown.`))}).catch(I=>{process.exitCode=1,console.log(P.red(`Gateway shutdown failed: ${String(I)}`))}),y),w=()=>{C("SIGINT")},d=()=>{C("SIGTERM")};process.once("SIGINT",w),process.once("SIGTERM",d);try{await p.runPromise,y&&await y}finally{process.off("SIGINT",w),process.off("SIGTERM",d)}});let t=e.command("channels").description("Manage channels");t.command("status").action(()=>{let i=O(),a=[["Telegram",i.channels.telegram.enabled?"yes":"no",i.channels.telegram.token?`token: ${i.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",i.channels.discord.enabled?"yes":"no",i.channels.discord.gatewayUrl]];for(let l of a){let c=l[0]??"",u=l[1]??"",p=l[2]??"";console.log(`${c.padEnd(12)} ${u.padEnd(3)} ${p}`)}}),t.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let n=e.command("auto").alias("automation").description("Manage browser automations");n.command("list").action(()=>{let i=O(),a=Y(i.agents.defaults.workspace),l=lt(a);if(!l.length)return console.log("No automations found.");console.log(P.cyan(`
346
- Saved Automations:`));for(let c of l)console.log(`${P.bold(c.id)} | ${c.name} | ${c.stepCount||0} steps | ${c.enabled?P.green("enabled"):P.gray("disabled")}`),c.description&&console.log(P.gray(` ${c.description}`));console.log("")}),n.command("show <id>").action(i=>{let a=O(),l=Y(a.agents.defaults.workspace),c=de(l,i);if(!c)return console.log(P.red(`Automation '${i}' not found.`));console.log(P.cyan(`
347
- Automation: ${c.name} (${c.id})`)),console.log(P.gray(c.description||"No description")),console.log(`
348
- Steps (${c.steps.length}):`);for(let u of c.steps)console.log(` ${u.order}. ${u.description} (${u.action})`);c.scriptContent&&(console.log(P.yellow(`
349
- Generated Script:`)),console.log(P.gray("----------------------------------------")),console.log(c.scriptContent),console.log(P.gray("----------------------------------------"))),console.log("")}),n.command("run <id>").action(async i=>{let a=O(),l=Y(a.agents.defaults.workspace),c=de(l,i);if(!c)return console.log(P.red(`Automation '${i}' not found.`));let u;if(a.tools.chromeSession?.enabled&&(u=new qe(a.tools.chromeSession,l,!!a.tools.restrictToWorkspace)),!u)return console.log(P.red("No browser tool available. Enable chrome_session in config."));let p=new dt(l,u);console.log(P.cyan(`Running automation: ${c.name}...`));let y=await p.execute({command:"run",id:i});console.log(y)}),n.command("remove").alias("delete").argument("<id>").action(i=>{let a=O(),l=Y(a.agents.defaults.workspace);ct(l,i)?console.log(P.green(`Removed automation '${i}'`)):console.log(P.red(`Automation '${i}' not found.`))});let r=e.command("cron").description("Manage scheduled tasks");return r.command("list").option("-a, --all","Include disabled jobs",!1).action(i=>{let{cron:a}=Ee({cron:{dataDir:Te()}}),l=a.listJobs(!!i.all);if(!l.length)return console.log("No scheduled jobs.");for(let c of l){let u=c.schedule.kind==="every"?`every ${c.schedule.everyMs/1e3}s`:c.schedule.kind==="cron"?`${c.schedule.expr} (${c.schedule.tz??"local"})`:"one-time",p=c.state.nextRunAtMs?new Date(c.state.nextRunAtMs).toISOString():"";console.log(`${c.id} | ${c.name} | ${u} | ${c.enabled?"enabled":"disabled"} | ${p}`)}}),r.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(i=>{if(i.tz&&!i.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let a;if(i.every)a={kind:"every",everyMs:Number(i.every)*1e3};else if(i.cron){let c={kind:"cron",expr:String(i.cron)};i.tz&&(c.tz=String(i.tz)),a=c}else if(i.at){let c=new Date(String(i.at));if(Number.isNaN(c.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}a={kind:"at",atMs:c.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:l}=Ee({cron:{dataDir:Te()}});try{let c={name:String(i.name),schedule:a,message:String(i.message),deliver:!!i.deliver};i.to&&(c.to=String(i.to)),i.channel&&(c.channel=String(i.channel));let u=l.addJob(c);console.log(`Added job '${u.name}' (${u.id})`)}catch(c){console.log(`Error: ${String(c).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),r.command("remove").argument("<jobId>").action(i=>{let{cron:a}=Ee({cron:{dataDir:Te()}});a.removeJob(i)?console.log(`Removed job ${i}`):console.log(`Job ${i} not found`)}),r.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((i,a)=>{let{cron:l}=Ee({cron:{dataDir:Te()}}),c=l.enableJob(i,!a.disable);if(!c)return console.log(`Job ${i} not found`);console.log(`Job '${c.name}' ${a.disable?"disabled":"enabled"}`)}),r.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(i,a)=>{let l=O(),c=Y(l.agents.defaults.workspace),u;try{u=ye(l)}catch(b){console.log(P.red(String(b))),process.exitCode=1;return}let p=new Je,y=Un(l.tools.exec.timeout),C=Ot({target:"scheduled-job",timeoutMs:y}),{cron:w}=Ee({cron:{dataDir:Te(),onJob:async(b,I)=>{let k=await C.run({payload:{message:b.payload.message,session:`cron:${b.id}`,channel:b.payload.channel??"cli",chatId:b.payload.to??"direct"},cwd:process.cwd(),signal:I?.signal});return d.push(k),k}}}),d=[];await w.runJob(i,!!a.force)?(console.log("Job executed"),d.length&&console.log(d[0])):(console.log(`Failed to run job ${i}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let i=vt(),a=O(),l=Y(a.agents.defaults.workspace);console.log(`everclaw Status
350
- `),console.log(`Config: ${i} ${Ut.existsSync(i)?"yes":"no"}`),console.log(`Workspace: ${l} ${Ut.existsSync(l)?"yes":"no"}`),console.log(`Model: ${a.agents.defaults.model}`);let c=Object.keys(a.providers);for(let y of c){let C=a.providers[y];if(!C)continue;["openai_codex","github_copilot"].includes(y)?console.log(`${y}: OAuth`):C.apiBase&&!C.apiKey?console.log(`${y}: ${C.apiBase}`):console.log(`${y}: ${C.apiKey?"set":"not set"}`)}console.log(`Resolved provider: ${We(a)??"none"}`);let p=await new ve().getStatus();console.log(`
351
- RTK Token Compression:`),p.installed&&p.version?(console.log(` Status: ${P.green("Available")} (v${p.version})`),console.log(` Binary: ${p.binaryPath}`)):p.installed?(console.log(` Status: ${P.yellow("Installed but broken")}`),console.log(` Binary: ${p.binaryPath}`),console.log(P.gray(` Run ${P.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${P.gray("Not installed")}`),a.tools.rtk.autoInstall?console.log(P.gray(" Auto-install is enabled and will download on first gateway start")):console.log(P.gray(` Run ${P.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let i=O(),a=Xt(i,process.env),l=We(a);console.log(P.cyan(`everclaw doctor
352
- `)),console.log(`Resolved provider: ${l??"none"}`),console.log(`Model: ${a.agents.defaults.model}`);let u=await new ve().getStatus();u.installed&&u.version?console.log(`RTK: ${P.green("Available")} (v${u.version})`):console.log(`RTK: ${P.gray("Not installed (token compression disabled)")}`);let p;try{p=ye(a)}catch(y){console.log(P.red(String(y))),process.exitCode=1;return}try{let y=await p.chat({messages:[{role:"user",content:"Reply with: OK"}],model:a.agents.defaults.model,maxTokens:16,temperature:0});if((y.content||"").toLowerCase().includes("error")){console.log(P.red(`LLM check failed: ${y.content}`)),process.exitCode=1;return}console.log(P.green(`LLM check passed: ${y.content??"(empty response)"}`)),console.log(P.green("Config looks good."))}catch(y){console.log(P.red(`LLM check failed: ${String(y)}`)),process.exitCode=1}}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(i=>{let a=i.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(a)){console.log(`Unknown OAuth provider: ${i}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${i} is not yet implemented in TypeScript port.`)}),e}zr(process.argv);var bl=vs();bl.parseAsync(process.argv);
400
+ ${w}
401
+ `)}d.close()}});let t=e.command("channels").description("Manage channels");t.addHelpText("after",`
402
+ Examples:
403
+ everclaw channels status Show channel configuration`),t.command("status").action(()=>{let i=$(),a=[["Telegram",i.channels.telegram.enabled?"yes":"no",i.channels.telegram.token?`token: ${i.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",i.channels.discord.enabled?"yes":"no",i.channels.discord.gatewayUrl]];for(let l of a){let c=l[0]??"",u=l[1]??"",p=l[2]??"";console.log(`${c.padEnd(12)} ${u.padEnd(3)} ${p}`)}}),t.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let n=e.command("auto").alias("automation").description("Manage browser automations");n.command("list").action(()=>{let i=$(),a=V(i.agents.defaults.workspace),l=Et(a);if(!l.length)return console.log("No automations found.");console.log(k.cyan(`
404
+ Saved Automations:`));for(let c of l)console.log(`${k.bold(c.id)} | ${c.name} | ${c.stepCount||0} steps | ${c.enabled?k.green("enabled"):k.gray("disabled")}`),c.description&&console.log(k.gray(` ${c.description}`));console.log("")}),n.command("show <id>").action(i=>{let a=$(),l=V(a.agents.defaults.workspace),c=ye(l,i);if(!c)return console.log(k.red(`Automation '${i}' not found.`));console.log(k.cyan(`
405
+ Automation: ${c.name} (${c.id})`)),console.log(k.gray(c.description||"No description")),console.log(`
406
+ Steps (${c.steps.length}):`);for(let u of c.steps)console.log(` ${u.order}. ${u.description} (${u.action})`);c.scriptContent&&(console.log(k.yellow(`
407
+ Generated Script:`)),console.log(k.gray("----------------------------------------")),console.log(c.scriptContent),console.log(k.gray("----------------------------------------"))),console.log("")}),n.command("run <id>").action(async i=>{let a=$(),l=V(a.agents.defaults.workspace),c=ye(l,i);if(!c)return console.log(k.red(`Automation '${i}' not found.`));let u;if(a.tools.chromeSession?.enabled&&(u=new ut(a.tools.chromeSession,l,!!a.tools.restrictToWorkspace)),!u)return console.log(k.red("No browser tool available. Enable chrome_session in config."));let p=new It(l,u);console.log(k.cyan(`Running automation: ${c.name}...`));let h=await p.execute({command:"run",id:i});console.log(h)}),n.command("remove").alias("delete").argument("<id>").action(i=>{let a=$(),l=V(a.agents.defaults.workspace);Pt(l,i)?console.log(k.green(`Removed automation '${i}'`)):console.log(k.red(`Automation '${i}' not found.`))});let r=e.command("cron").description("Manage scheduled tasks");return r.addHelpText("after",`
408
+ Examples:
409
+ everclaw cron list List all scheduled jobs
410
+ everclaw cron add -n "daily" --cron "0 9 * * *" -m "Good morning!"
411
+ everclaw cron add -n "reminder" --at "2024-12-25T09:00:00" -m "Merry Christmas!" -d --to "12345" --channel "telegram"
412
+ everclaw cron run abc123 Run a job immediately`),r.command("list").option("-a, --all","Include disabled jobs",!1).action(i=>{let{cron:a}=Be({cron:{dataDir:Pe()}}),l=a.listJobs(!!i.all);if(!l.length)return console.log("No scheduled jobs.");for(let c of l){let u=c.schedule.kind==="every"?`every ${c.schedule.everyMs/1e3}s`:c.schedule.kind==="cron"?`${c.schedule.expr} (${c.schedule.tz??"local"})`:"one-time",p=c.state.nextRunAtMs?new Date(c.state.nextRunAtMs).toISOString():"";console.log(`${c.id} | ${c.name} | ${u} | ${c.enabled?"enabled":"disabled"} | ${p}`)}}),r.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(i=>{if(i.tz&&!i.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let a;if(i.every)a={kind:"every",everyMs:Number(i.every)*1e3};else if(i.cron){let c={kind:"cron",expr:String(i.cron)};i.tz&&(c.tz=String(i.tz)),a=c}else if(i.at){let c=new Date(String(i.at));if(Number.isNaN(c.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}a={kind:"at",atMs:c.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:l}=Be({cron:{dataDir:Pe()}});try{let c={name:String(i.name),schedule:a,message:String(i.message),deliver:!!i.deliver};i.to&&(c.to=String(i.to)),i.channel&&(c.channel=String(i.channel));let u=l.addJob(c);console.log(`Added job '${u.name}' (${u.id})`)}catch(c){console.log(`Error: ${String(c).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),r.command("remove").argument("<jobId>").action(i=>{let{cron:a}=Be({cron:{dataDir:Pe()}});a.removeJob(i)?console.log(`Removed job ${i}`):console.log(`Job ${i} not found`)}),r.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((i,a)=>{let{cron:l}=Be({cron:{dataDir:Pe()}}),c=l.enableJob(i,!a.disable);if(!c)return console.log(`Job ${i} not found`);console.log(`Job '${c.name}' ${a.disable?"disabled":"enabled"}`)}),r.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(i,a)=>{let l=$(),c=V(l.agents.defaults.workspace),u;try{u=Te(l)}catch(b){console.log(k.red(String(b))),process.exitCode=1;return}let p=new it,h=ir(l.tools.exec.timeout),T=tn({target:"scheduled-job",timeoutMs:h}),{cron:v}=Be({cron:{dataDir:Pe(),onJob:async(b,_)=>{let w=await T.run({payload:{message:b.payload.message,session:`cron:${b.id}`,channel:b.payload.channel??"cli",chatId:b.payload.to??"direct"},cwd:process.cwd(),signal:_?.signal});return d.push(w),w}}}),d=[];await v.runJob(i,!!a.force)?(console.log("Job executed"),d.length&&console.log(d[0])):(console.log(`Failed to run job ${i}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let a=!!e.opts().json,l=St(),c=$(),u=V(c.agents.defaults.workspace),p=c.gateway.port,h=null;try{let d=await fetch(`http://127.0.0.1:${p}/api/status`,{signal:AbortSignal.timeout(2e3)});d.ok&&(h=await d.json())}catch{}let v=await new Se().getStatus();if(a){let d={gateway:{running:!!h,port:h?h.gateway?.port??p:null},model:c.agents.defaults.model,provider:Je(c)??null,config:{path:l,exists:ce.existsSync(l)},workspace:{path:u,exists:ce.existsSync(u)},rtk:{installed:v.installed,version:v.version??null,binaryPath:v.binaryPath}};if(h){let b=h.runtime,_=h.channelStatus,w=Me();d.gateway={running:!0,port:h.gateway?.port??p,pid:w?.pid??null,uptime:w?st(w.startedAt):null},d.agent={acceptingWork:b?.acceptingWork??!0,activeSessions:b?.activeSessions??0,queuedMessages:b?.queuedMessages??0,subagents:b?.subagents??0},d.channels=_??{}}console.log(JSON.stringify(d,null,2));return}if(console.log(k.cyan(`everclaw Status
413
+ `)),h){let d=h.runtime,b=h.gateway,_=h.channelStatus,w=Me(),F=w?st(w.startedAt):"unknown";console.log(`Gateway: ${k.green("running")} (port ${b?.port??p}, uptime ${F})`),console.log(`Agent: ${d?.acceptingWork?k.green("idle (accepting work)"):k.yellow("busy")}`),console.log(` Active sessions: ${d?.activeSessions??0}`),console.log(` Queued messages: ${d?.queuedMessages??0}`),console.log(` Subagents: ${d?.subagents??0}`);let A=d?.overload;if(A&&typeof A.rateLimited=="number"&&A.rateLimited>0&&console.log(` Rate limited: ${k.yellow(String(A.rateLimited))} (window: ${A.rateLimitWindowMs??0}ms)`),_&&Object.keys(_).length>0){console.log(`
414
+ Channels:`);for(let[N,U]of Object.entries(_)){let ie=U?.running?k.green("connected"):k.gray("disconnected");console.log(` ${N.padEnd(12)} ${ie}`)}}}else console.log(`Gateway: ${k.gray("not running")}`);console.log(`
415
+ Model: ${c.agents.defaults.model}`),console.log(`Provider: ${Je(c)??"none"}`),console.log(`Config: ${l} ${ce.existsSync(l)?"yes":"no"}`),console.log(`Workspace: ${u} ${ce.existsSync(u)?"yes":"no"}`),console.log(`
416
+ RTK Token Compression:`),v.installed&&v.version?(console.log(` Status: ${k.green("Available")} (v${v.version})`),console.log(` Binary: ${v.binaryPath}`)):v.installed?(console.log(` Status: ${k.yellow("Installed but broken")}`),console.log(` Binary: ${v.binaryPath}`),console.log(k.gray(` Run ${k.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${k.gray("Not installed")}`),c.tools.rtk.autoInstall?console.log(k.gray(" Auto-install is enabled and will download on first gateway start")):console.log(k.gray(` Run ${k.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let a=!!e.opts().json,l=$(),c=Ft(l,process.env),u=Je(c),p=[],h={ok:!0,warnings:[]},T=Me(),v=T&&Le(T.pid);h.system={gateway:v?{running:!0,pid:T.pid,port:T.port,uptime:st(T.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:Js()??"standalone"},a||(console.log(k.cyan(`everclaw doctor
417
+ `)),console.log(k.bold("System:")),console.log(v?` Gateway: ${k.green("running")} (PID ${T.pid}, port ${T.port}, uptime ${st(T.startedAt)})`:` Gateway: ${k.gray("not running")}`));let d=process.versions.node,b=parseInt(d.split(".")[0]??"0",10);b<20&&p.push("Node.js version below 20 may have compatibility issues");let _=process.getuid?.()===0;if(_&&p.push("Running as root is not recommended for security"),!a){b>=20?console.log(` Node.js: ${k.green(d)}`):console.log(` Node.js: ${k.yellow(d)} (recommend v20+)`),console.log(_?` Running as: ${k.red("root")} (not recommended)`:` Running as: ${k.green("non-root")}`);let E=Js();console.log(E?` Supervisor: ${k.green(E)}`:` Supervisor: ${k.gray("standalone")}`)}let w=St();if(ce.existsSync(w))try{let j=!!(ce.statSync(w).mode&511&7);h.system.configPermissions={ok:!j,path:w},j&&p.push("Config file is world-readable \u2014 contains API keys"),a||console.log(j?` Config: ${k.yellow("world-readable")} (${w})`:` Config: ${k.green("ok")} (${w})`)}catch{a||console.log(` Config: ${k.gray("unable to check")}`)}try{let E=Pe();ce.statSync(E);let M=Yl(E);if(M!==null){let j=Math.round(M/1048576);h.system.diskSpace={freeMB:j,path:E,ok:M>=100*1024*1024},M<100*1024*1024&&p.push(`Low disk space: ${j}MB free in ${E}`),a||(M<100*1024*1024?console.log(` Disk space: ${k.yellow(`${j}MB free`)} (${E})`):console.log(` Disk space: ${k.green(`${j}MB free`)} (${E})`))}}catch{}let F=V(c.agents.defaults.workspace);if(ce.existsSync(F))try{let j=!!(ce.statSync(F).mode&511&2);h.system.workspace={ok:!j,path:F},j&&p.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),a||console.log(j?` Workspace: ${k.yellow("world-writable")} (${F})`:` Workspace: ${k.green("ok")} (${F})`)}catch{a||console.log(` Workspace: ${k.gray("unable to check")}`)}else h.system.workspace={ok:!0,path:F,created:!1},a||console.log(` Workspace: ${k.gray("not created")} (${F})`);let A=c.security;if(h.security={enabled:A.enabled,auth:A.auth.enabled,toolGuard:A.toolGuard.enabled,skillScanner:A.skillScanner.enabled,inputSanitizer:A.inputSanitizer.enabled,pathBoundary:c.tools.restrictToWorkspace},a)A.toolGuard.enabled&&A.toolGuard.failOpen&&p.push("Tool guard is fail-open \u2014 consider fail-closed for production"),A.skillScanner.enabled||p.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),c.tools.restrictToWorkspace||p.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!A.auth.enabled&&c.gateway.host!=="127.0.0.1"&&c.gateway.host!=="localhost"&&p.push("Dashboard exposed on non-loopback without auth");else{if(console.log(k.bold(`
418
+ Security:`)),console.log(` Master switch: ${A.enabled?k.green("enabled"):k.gray("disabled")}`),A.auth.enabled){let E=A.auth.sessionTtlS?`${Math.floor(A.auth.sessionTtlS/60)}min`:"default",M=A.auth.idleTimeoutS?`${Math.floor(A.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${k.green("enabled")} (PIN, session TTL: ${E}, idle lock: ${M})`)}else console.log(` Authentication: ${k.gray("disabled")}`),c.gateway.host!=="127.0.0.1"&&c.gateway.host!=="localhost"&&p.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${A.toolGuard.enabled?k.green("enabled"):k.gray("disabled")}`),A.toolGuard.enabled&&A.toolGuard.failOpen&&p.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${A.skillScanner.enabled?k.green("enabled"):k.gray("disabled")}`),A.skillScanner.enabled||p.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${A.inputSanitizer.enabled?k.green("enabled"):k.gray("disabled")}`),console.log(` Path Boundary: ${c.tools.restrictToWorkspace?k.green("workspace-restricted"):k.yellow("unrestricted")}`),c.tools.restrictToWorkspace||p.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let N=So(c);for(let E of N)p.includes(E)||p.push(E);h.provider={name:u??null,model:c.agents.defaults.model},a||(console.log(k.bold(`
419
+ Provider:`)),console.log(` Resolved: ${u??"none"}`),console.log(` Model: ${c.agents.defaults.model}`));let D=await new Se().getStatus();h.rtk={installed:D.installed,version:D.version??null,binaryPath:D.binaryPath},D.installed&&D.version&&!ft(D.version,we)&&p.push(`RTK version ${D.version} is below minimum ${we}`),a||(console.log(k.bold(`
420
+ RTK Token Compression:`)),D.installed&&D.version?ft(D.version,we)?console.log(` Status: ${k.green("Available")} (v${D.version})`):console.log(` Status: ${k.yellow("Outdated")} (v${D.version}, min: ${we})`):console.log(` Status: ${k.gray("Not installed")}`));let ie=Object.keys(c.tools.mcpServers);if(ie.length>0){let E={};a||console.log(k.bold(`
421
+ MCP Servers:`));for(let M of ie)try{let{McpClientManager:j}=await Promise.resolve().then(()=>(en(),or)),K=new j;K.updateConfig(c.tools.mcpServers);let ne=await K.getServerTools(M);await K.closeAll(),E[M]={connected:!0,tools:ne.length},a||console.log(` ${M.padEnd(20)} ${k.green("\u2713 connected")} (${ne.length} tools)`)}catch(j){let K=j instanceof Error?j.message:String(j);E[M]={connected:!1,error:K},a||console.log(` ${M.padEnd(20)} ${k.red("\u2717 "+K)}`)}h.mcp=E}let W={};if(c.channels.telegram.enabled){let E=c.channels.telegram.token,M=E?/^\d+:[A-Za-z0-9_-]{30,}$/.test(E):!1;W.telegram={enabled:!0,configured:!!E,validFormat:M},E?M||p.push("Telegram token format does not match expected pattern"):p.push("Telegram channel enabled but no token configured")}if(c.channels.discord.enabled){let E=c.channels.discord.token,M=E?E.length>=50&&/^[A-Za-z0-9._-]+$/.test(E):!1;W.discord={enabled:!0,configured:!!E,validFormat:M},E?M||p.push("Discord token format does not match expected pattern"):p.push("Discord channel enabled but no token configured")}if(Object.keys(W).length>0&&(h.channels=W,!a)){if(console.log(k.bold(`
422
+ Channel Tokens:`)),c.channels.telegram.enabled){let E=c.channels.telegram.token;E&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(E)?console.log(` Telegram: ${k.green("valid format")}`):console.log(E?` Telegram: ${k.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${k.red("not configured")}`)}if(c.channels.discord.enabled){let E=c.channels.discord.token;E&&E.length>=50&&/^[A-Za-z0-9._-]+$/.test(E)?console.log(` Discord: ${k.green("valid format")}`):console.log(E?` Discord: ${k.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${k.red("not configured")}`)}}a||console.log(k.bold(`
423
+ LLM Connectivity:`));let Q;try{Q=Te(c)}catch(E){h.llm={connected:!1,error:String(E)},h.ok=!1,h.warnings=p,console.log(a?JSON.stringify(h,null,2):` ${k.red("Failed to create provider: "+String(E))}`),process.exitCode=q.GENERAL_ERROR;return}try{let E=await Q.chat({messages:[{role:"user",content:"Reply with: OK"}],model:c.agents.defaults.model,maxTokens:16,temperature:0});if((E.content||"").toLowerCase().includes("error")){h.llm={connected:!1,error:E.content},h.ok=!1,h.warnings=p,console.log(a?JSON.stringify(h,null,2):` ${k.red("Failed: "+E.content)}`),process.exitCode=q.CONNECTIVITY_ERROR;return}h.llm={connected:!0},a||console.log(` ${k.green("Passed")}: ${E.content??"(empty response)"}`)}catch(E){h.llm={connected:!1,error:String(E)},h.ok=!1,h.warnings=p,console.log(a?JSON.stringify(h,null,2):` ${k.red("Failed: "+String(E))}`),process.exitCode=q.CONNECTIVITY_ERROR;return}if(h.warnings=p,a){console.log(JSON.stringify(h,null,2));return}if(p.length>0){console.log(k.bold(`
424
+ Warnings:`));for(let E of p)console.log(` ${k.yellow("\u26A0")} ${E}`)}console.log(k.green(`
425
+ Doctor check complete.`))}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(i=>{let a=i.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(a)){console.log(`Unknown OAuth provider: ${i}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${i} is not yet implemented in TypeScript port.`)}),e}fo(process.argv);var Ql=qs();Ql.parseAsync(process.argv);