everclaw 0.3.9 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var Ii=Object.defineProperty;var _i=(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 Ge=(o,e)=>()=>(o&&(e=o(o=0)),e);var Gr=(o,e)=>{for(var t in e)Ii(o,t,{get:e[t],enumerable:!0})};import Mo from"node:fs";import Ve from"node:os";import he from"node:path";import{fileURLToPath as Mi}from"node:url";function Sn(o=Ve.homedir()){return he.join(o,ct)}function Lo(o=Ve.homedir()){return he.join(o,ct,"workspace")}function Oo(o=Ve.homedir()){return he.join(o,ct,"config.json")}function Ue(o=Ve.homedir()){return he.join(o,ct,"logs")}function Ur(o=Ve.homedir()){return he.join(o,".config","systemd","user")}function Wr(o=Ve.homedir()){return he.join(o,"Library","LaunchAgents")}function kn(o=Ve.homedir()){return he.join(Ur(o),"everclaw.service")}function Cn(o=Ve.homedir()){return he.join(Wr(o),"ai.everclaw.gateway.plist")}function $i(){let o=Mi(import.meta.url),e=he.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:he.resolve(e,"..")}function No(...o){let e=he.resolve(Do,...o);if(!Mo.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function Ye(...o){let e=he.resolve(Do,...o);return Mo.existsSync(e)?e:null}var ct,dt,$o,Do,le=Ge(()=>{"use strict";ct=".everclaw",dt="~/.everclaw/config.json",$o=he.join("~",ct,"workspace");Do=$i()});import xn from"node:fs";import We from"node:path";import Kr from"node:os";function Xe(o){return xn.mkdirSync(o,{recursive:!0}),o}function Tn(){return Xe(Sn(Kr.homedir()))}function X(o){let e=o?o.replace(/^~(?=$|[\\/])/,Kr.homedir()):Lo(Kr.homedir());return Xe(We.resolve(e))}function jo(o){return o.replace(Li,"_").trim()}function ut(o,e=!1){let t=Ye("templates");if(!t)return[];let n=[],r=(i,a)=>{xn.existsSync(a)||(Xe(We.dirname(a)),i?xn.copyFileSync(i,a):xn.writeFileSync(a,"","utf8"),n.push(We.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(We.join(t,i),We.join(o,i));if(r(We.join(t,"memory","MEMORY.md"),We.join(o,"memory","MEMORY.md")),r(null,We.join(o,"memory","HISTORY.md")),Xe(We.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var Li,De=Ge(()=>{"use strict";le();Li=/[<>:"/\\|?*]/g});function Ko(){let o={};for(let e of Wo)e.models.length>0&&(o[e.spec.name]=e.models);return o}function Jr(){return Wo.map(o=>o.spec)}var Wo,qr=Ge(()=>{"use strict";Wo=[{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 Et(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function zt(o){return`${At}${Et(o)}`}function Ho(o,e){let t=Et(e.startsWith(At)?e.slice(At.length):e);return o.customLlmProviders.find(n=>Et(n.name)===t)??null}function Ki(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?Ho(o,n):null}function gt(o){return!!o&&o.startsWith(At)}function Pt(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return Ho(o,n);let r=Ki(o,t??o.agents.defaults.model);if(r)return r;let s=o.customLlmProviders.filter(i=>i.name.trim()&&i.baseUrl.trim());return s.length===1?s[0]??null:null}function Qe(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Pt(o,t,e);return a?zt(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=Et(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of qt){let l=o.providers[a.name];if(s&&Et(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of qt){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(Et(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of qt){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Pt(o,t,e);return i?zt(i.name):null}function Jo(o,e){let t=Qe(o,e);if(t&&gt(t)){let n=Pt(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function En(o,e){let t=Qe(o,e);if(!t)return null;if(gt(t))return Pt(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=qt.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function An(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(At)){let s=n.slice(At.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 qt,Wi,At,de,It=Ge(()=>{"use strict";le();qr();qt=Jr(),Wi=Object.fromEntries(Jr().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),At="custom:",de={agents:{defaults:{workspace:$o,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3},groups:{requireMention:!0,allowedGroupIds:null},commands:{native:!0,custom:[]}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:Wi,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}},logging:{enabled:!0,level:"info",retentionHours:4,maxFileSizeMb:10,purgeIntervalMs:6e5}}});import Pn from"node:fs";import Hi from"node:path";function mt(){return Oo()}function je(){return Tn()}function qo(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]=qo(t[n],r):t[n]=r;return t}function In(o,e){if(o===e)return!0;if(o===null||e===null)return o===e;if(typeof o!="object"||typeof e!="object"||Array.isArray(o)!==Array.isArray(e))return!1;if(Array.isArray(o)&&Array.isArray(e))return o.length!==e.length?!1:o.every((i,a)=>In(i,e[a]));let t=o,n=e,r=Object.keys(t).sort(),s=Object.keys(n).sort();return r.length!==s.length?!1:r.every((i,a)=>i===s[a]&&In(t[i],n[i]))}function qi(o){return o.apiKey===""&&o.apiBase===null&&o.extraHeaders===null&&(o.models===void 0||o.models.length===0)}function zo(o,e,t=""){if(Ji.has(t))return o;if(o===null||e===null||typeof o!="object"||typeof e!="object")return o===e?void 0:o;if(Array.isArray(o)!==Array.isArray(e))return o;if(Array.isArray(o)&&Array.isArray(e))return In(o,e)?void 0:o;if(t==="providers"){let a=o,l=e,c={},d=!1;for(let[p,h]of Object.entries(a)){let v=l[p];v?In(h,v)||(c[p]=h,d=!0):qi(h)||(c[p]=h,d=!0)}return d?c:void 0}let n=o,r=e,s={},i=!1;for(let a of Object.keys(n)){let l=t?`${t}.${a}`:a,c=n[a],d=r[a];if(d===void 0)s[a]=c,i=!0;else{let p=zo(c,d,l);p!==void 0&&(s[a]=p,i=!0)}}return i?s:void 0}function zi(o,e=de){return zo(o,e)??{}}function M(o){let e=o??mt();if(!Pn.existsSync(e))return structuredClone(de);try{let t=Pn.readFileSync(e,"utf8"),n=JSON.parse(t),r=qo(structuredClone(de),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=de.subagents.find(l=>l.id===i);a&&r.subagents.push(structuredClone(a))}return r}catch(t){return console.warn(`Warning: Failed to load config from ${e}: ${String(t)}`),structuredClone(de)}}function oe(o,e){let t=e??mt();Pn.mkdirSync(Hi.dirname(t),{recursive:!0});let n=zi(o);Pn.writeFileSync(t,JSON.stringify(n,null,2),"utf8")}function Vo(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(r=>r.name===t)&&e.push(`Provider '${t}' is not in the provider catalog and no matching customLlmProvider exists`),o.gateway.host!=="127.0.0.1"&&o.gateway.host!=="localhost"&&o.gateway.host!=="::1"&&o.gateway.dashboard?.enabled!==!1&&!o.security?.auth?.enabled&&e.push("Dashboard exposed on non-loopback address without authentication"),o.security?.toolGuard?.enabled&&o.security?.toolGuard?.failOpen&&e.push("Tool guard is fail-open \u2014 consider fail-closed for production"),o.channels?.telegram?.enabled&&!o.channels.telegram.token&&e.push("Telegram channel enabled but no token configured"),o.channels?.discord?.enabled&&!o.channels.discord.token&&e.push("Discord channel enabled but no token configured");let n=o.channels?.telegram?.groups?.allowedGroupIds;n!=null&&!Array.isArray(n)&&e.push(`Telegram groups.allowedGroupIds should be an array (e.g. ["${n}"]), got ${typeof n}`);for(let[r,s]of Object.entries(o.tools?.mcpServers??{}))!s.command&&!s.url&&e.push(`MCP server '${r}' has neither command nor URL configured`),s.command&&s.url&&e.push(`MCP server '${r}' has both command and URL \u2014 must use one`),s.toolTimeout!==void 0&&(!Number.isFinite(s.toolTimeout)||s.toolTimeout<=0)&&e.push(`MCP server '${r}' has invalid toolTimeout`);return e}var Ji,Fe=Ge(()=>{"use strict";It();le();De();Ji=new Set(["agents.defaults.model","agents.defaults.provider","gateway.port"])});var ls={};Gr(ls,{LocalProcessIsolationRunner:()=>be,selectExecutionIsolationPolicy:()=>yt});import{spawn as as}from"node:child_process";function yt(o){return{...sa[o]}}var sa,be,bt=Ge(()=>{"use strict";sa={"agent-turn":{target:"agent-turn",mode:"in-process",risk:"safe",cleanup:"none",observation:"basic",reason:"Normal agent turns stay in-process unless a later surface explicitly routes them through isolation."},"tool.exec":{target:"tool.exec",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Shell execution already crosses the local OS boundary and needs explicit launch, timeout, output capture, and cleanup semantics."},subagent:{target:"subagent",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Spawned subagents are a high-risk local execution path that later Wave D routing can move onto this process boundary."},"scheduled-job":{target:"scheduled-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Scheduled jobs can run unattended and should share the same local-process isolation contract when routed in later Wave D work."},"background-job":{target:"background-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Long-running background work needs the same local process cleanup and attribution boundary as other risky execution paths."}};be=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,d=null,p=!1,h=(S,N)=>{let U=typeof S=="string"?S:S.toString("utf8"),I=t-Buffer.byteLength(N);return I<=0?N:N+U.slice(0,I)};s.stdout?.on("data",S=>{a=h(S,a)}),s.stderr?.on("data",S=>{l=h(S,l)});let v=null,w=S=>{c||(c=!0,d=S,p=S==="timeout",this.killChild(s,"SIGTERM"),v=setTimeout(()=>this.killChild(s,"SIGKILL"),250),v.unref?.())},u=()=>w("abort");e.signal?.aborted?u():e.signal?.addEventListener("abort",u,{once:!0});let b=n!=null?setTimeout(()=>w("timeout"),n):null;b?.unref?.();let E=await new Promise(S=>{let N=!1,U=I=>{N||(N=!0,S(I))};s.once("error",I=>{i.current=I,U({code:null,signal:null})}),s.once("close",(I,J)=>U({code:I,signal:J}))});return b&&clearTimeout(b),v&&clearTimeout(v),e.signal?.removeEventListener("abort",u),d==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:E.code,signal:E.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:E.code,signal:E.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:E.code,signal:E.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:d,errorMessage:i.current.message}:E.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:E.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:E.code,signal:E.signal,failureAttribution:E.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:d,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?as(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):as(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 br={};Gr(br,{McpClientManager:()=>dn});import{Client as sl}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as il}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as al}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as ll}from"@modelcontextprotocol/sdk/client/sse.js";function Cs(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var dn,un=Ge(()=>{"use strict";dn=class{connections=new Map;servers={};updateConfig(e){this.servers=e}async getServerTools(e){return(await this.ensureConnected(e)).tools}async callTool(e,t,n,r){let s=await this.ensureConnected(e),i=(s.timeout||60)*1e3,a=new AbortController,l=setTimeout(()=>a.abort(),i);r?.signal&&r.signal.addEventListener("abort",()=>a.abort(),{once:!0});try{let c=await s.client.callTool({name:t,arguments:n},void 0,{signal:a.signal});return c.isError?`Error: ${Array.isArray(c.content)?c.content.map(p=>p.text??JSON.stringify(p)).join(`
2
+ var ha=Object.defineProperty;var ya=(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 _e=(o,e)=>()=>(o&&(e=o(o=0)),e);var $n=(o,e)=>{for(var t in e)ha(o,t,{get:e[t],enumerable:!0})};import rs from"node:fs";import Ze from"node:os";import be from"node:path";import{fileURLToPath as ba}from"node:url";function On(o=Ze.homedir()){return be.join(o,mt)}function ss(o=Ze.homedir()){return be.join(o,mt,"workspace")}function is(o=Ze.homedir()){return be.join(o,mt,"config.json")}function We(o=Ze.homedir()){return be.join(o,mt,"logs")}function oo(o=Ze.homedir()){return be.join(o,".config","systemd","user")}function so(o=Ze.homedir()){return be.join(o,"Library","LaunchAgents")}function Ln(o=Ze.homedir()){return be.join(oo(o),"everclaw.service")}function Nn(o=Ze.homedir()){return be.join(so(o),"ai.everclaw.gateway.plist")}function wa(){let o=ba(import.meta.url),e=be.dirname(o);return o.endsWith("/index.js")||o.endsWith("\\index.js")?e:be.resolve(e,"..")}function ls(...o){let e=be.resolve(as,...o);if(!rs.existsSync(e))throw new Error(`Runtime asset not found: ${e}`);return e}function et(...o){let e=be.resolve(as,...o);return rs.existsSync(e)?e:null}var mt,pt,os,as,de=_e(()=>{"use strict";mt=".everclaw",pt="~/.everclaw/config.json",os=be.join("~",mt,"workspace");as=wa()});import Dn from"node:fs";import Ke from"node:path";import io from"node:os";function tt(o){return Dn.mkdirSync(o,{recursive:!0}),o}function jn(){return tt(On(io.homedir()))}function Z(o){let e=o?o.replace(/^~(?=$|[\\/])/,io.homedir()):ss(io.homedir());return tt(Ke.resolve(e))}function cs(o){return o.replace(va,"_").trim()}function ft(o,e=!1){let t=et("templates");if(!t)return[];let n=[],r=(i,a)=>{Dn.existsSync(a)||(tt(Ke.dirname(a)),i?Dn.copyFileSync(i,a):Dn.writeFileSync(a,"","utf8"),n.push(Ke.relative(o,a)))},s=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","HEARTBEAT.md"];for(let i of s)r(Ke.join(t,i),Ke.join(o,i));if(r(Ke.join(t,"memory","MEMORY.md"),Ke.join(o,"memory","MEMORY.md")),r(null,Ke.join(o,"memory","HISTORY.md")),tt(Ke.join(o,"skills")),!e)for(let i of n)console.log(` Created ${i}`);return n}var va,je=_e(()=>{"use strict";de();va=/[<>:"/\\|?*]/g});function fs(){let o={};for(let e of ps)e.models.length>0&&(o[e.spec.name]=e.models);return o}function lo(){return ps.map(o=>o.spec)}var ps,co=_e(()=>{"use strict";ps=[{spec:{name:"zai",keywords:["zai"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.z.ai/api/coding/paas/v4"},models:["glm-5-turbo"]},{spec:{name:"openrouter",displayName:"OpenRouter",keywords:["openrouter"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://openrouter.ai/api/v1",detectByKeyPrefix:"sk-or-",detectByBaseKeyword:"openrouter"},models:["anthropic/claude-opus-4-1","anthropic/claude-sonnet-4","openai/gpt-4.1","google/gemini-2.5-pro"]},{spec:{name:"aihubmix",displayName:"AIHubMix",keywords:["aihubmix"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://aihubmix.com/v1",detectByBaseKeyword:"aihubmix"},models:[]},{spec:{name:"siliconflow",displayName:"SiliconFlow",keywords:["siliconflow"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://api.siliconflow.cn/v1",detectByBaseKeyword:"siliconflow"},models:["openai/deepseek-ai/DeepSeek-R1"]},{spec:{name:"volcengine",displayName:"VolcEngine",keywords:["volcengine","volces","ark"],isOauth:!1,isGateway:!0,isLocal:!1,defaultApiBase:"https://ark.cn-beijing.volces.com/api/v3",detectByBaseKeyword:"volces"},models:["volcengine/deepseek-r1-250120"]},{spec:{name:"anthropic",displayName:"Anthropic",keywords:["anthropic","claude"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["anthropic/claude-opus-4-5","anthropic/claude-sonnet-4"]},{spec:{name:"openai",displayName:"OpenAI",keywords:["openai","gpt"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gpt-5.2","gpt-5.2-pro","gpt-5.3-codex","gpt-5.2-codex","gpt-5.1","gpt-5.1-codex","gpt-5-mini","gpt-5-nano","gpt-4.1","gpt-4.1-mini","gpt-4.1-nano","gpt-4o","gpt-4o-mini"]},{spec:{name:"openai_codex",displayName:"OpenAI Codex",keywords:["openai-codex","codex"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:"https://chatgpt.com/backend-api"},models:[]},{spec:{name:"github_copilot",displayName:"GitHub Copilot",keywords:["github_copilot","copilot"],isOauth:!0,isGateway:!1,isLocal:!1,defaultApiBase:""},models:[]},{spec:{name:"deepseek",displayName:"DeepSeek",keywords:["deepseek"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["deepseek/deepseek-chat","deepseek/deepseek-reasoner"]},{spec:{name:"gemini",displayName:"Google Gemini",keywords:["gemini"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["gemini/gemini-3-flash-preview","gemini/gemini-2.5-pro","gemini/gemini-2.5-flash"]},{spec:{name:"zhipu",displayName:"Zhipu AI",keywords:["zhipu","glm","zai"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["zai/glm-4.5"]},{spec:{name:"dashscope",displayName:"DashScope",keywords:["qwen","dashscope"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["dashscope/qwen-max"]},{spec:{name:"moonshot",displayName:"Moonshot AI",keywords:["moonshot","kimi"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.moonshot.ai/v1"},models:["moonshot/kimi-k2.5"]},{spec:{name:"minimax",displayName:"MiniMax",keywords:["minimax"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:"https://api.minimax.io/v1"},models:["minimax/MiniMax-M2.1"]},{spec:{name:"vllm",displayName:"vLLM",keywords:["vllm"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:""},models:["hosted_vllm/llama-3.1-8b-instruct"]},{spec:{name:"groq",displayName:"Groq",keywords:["groq"],isOauth:!1,isGateway:!1,isLocal:!1,defaultApiBase:""},models:["openai/gpt-oss-120b","openai/gpt-oss-20b","meta-llama/llama-4-maverick-17b-128e-instruct","groq/compound","groq/compound-mini"]},{spec:{name:"ollama",displayName:"Ollama",keywords:["ollama"],isOauth:!1,isGateway:!1,isLocal:!0,defaultApiBase:"http://localhost:11434/v1"},models:["ollama/llama3.3","ollama/qwen2.5","ollama/deepseek-r1"]}]});function It(o){return o.toLowerCase().replace(/[\s-]+/g,"_")}function tn(o){return`${$t}${It(o)}`}function hs(o,e){let t=It(e.startsWith($t)?e.slice($t.length):e);return o.customLlmProviders.find(n=>It(n.name)===t)??null}function _a(o,e){if(!e.includes("/"))return null;let n=e.split("/",1)[0];return n?hs(o,n):null}function ht(o){return!!o&&o.startsWith($t)}function Ot(o,e,t){let n=(e??o.agents.defaults.provider).trim();if(n&&n!=="auto"&&!o.providers[n])return hs(o,n);let r=_a(o,t??o.agents.defaults.model);if(r)return r;let s=o.customLlmProviders.filter(i=>i.name.trim()&&i.baseUrl.trim());return s.length===1?s[0]??null:null}function nt(o,e){let t=o.agents.defaults.provider;if(t!=="auto"){if(o.providers[t])return t;let a=Ot(o,t,e);return a?tn(a.name):null}let n=(e??o.agents.defaults.model).toLowerCase(),r=It(n),s=n.includes("/")?n.split("/",1)[0]:"";for(let a of en){let l=o.providers[a.name];if(s&&It(s)===a.name&&(a.isOauth||l?.apiKey))return a.name}for(let a of en){let l=o.providers[a.name];if(a.keywords.some(c=>n.includes(c)||r.includes(It(c)))&&(a.isOauth||l?.apiKey))return a.name}for(let a of en){if(a.isOauth)continue;if(o.providers[a.name]?.apiKey)return a.name}let i=Ot(o,t,e);return i?tn(i.name):null}function ys(o,e){let t=nt(o,e);if(t&&ht(t)){let n=Ot(o,t,e);return n?{apiKey:n.apiKey,apiBase:n.baseUrl,extraHeaders:n.extraHeaders}:null}return t?o.providers[t]??null:null}function Bn(o,e){let t=nt(o,e);if(!t)return null;if(ht(t))return Ot(o,t,e)?.baseUrl??null;let n=o.providers[t];if(n?.apiBase)return n.apiBase;let r=en.find(s=>s.name===t);return r?.isGateway?r.defaultApiBase:null}function Un(o,e){let t=e??o.agents.defaults.model,n=o.agents.defaults.provider;if(n==="auto"&&!t.includes("/"))return null;let r;if(n==="auto"&&t.includes("/")){let s=t.split("/")[0],i=s.toLowerCase(),a=o.customLlmProviders.find(l=>l.name.toLowerCase()===i);if(a){let l=t.slice(s.length+1).toLowerCase();r=a.models.find(c=>c.id.toLowerCase()===l)}}else if(n.startsWith($t)){let s=n.slice($t.length).toLowerCase(),i=o.customLlmProviders.find(a=>a.name.toLowerCase()===s);i&&(r=i.models.find(a=>a.id.toLowerCase()===t.toLowerCase()))}else{let s=o.providers[n];s?.models&&(r=s.models.find(i=>i.id.toLowerCase()===t.toLowerCase()))}return r?.capabilities??null}var en,Pa,$t,me,Lt=_e(()=>{"use strict";de();co();en=lo(),Pa=Object.fromEntries(lo().map(o=>[o.name,{apiKey:"",apiBase:null,extraHeaders:null,models:[]}])),$t="custom:",me={agents:{defaults:{workspace:os,model:"gpt-4.1",provider:"auto",maxTokens:8192,temperature:.1,maxToolIterations:40,memoryWindow:100}},subagents:[{id:"researcher",name:"Researcher",task:"Research the given topic thoroughly and provide detailed findings.",createdAt:0},{id:"advisor",name:"Advisor",task:"Analyze the current conversation context and provide exactly 3 concise suggestion options for the user's next logical message. Reply with a JSON array of 3 strings.",createdAt:0}],channels:{sendProgress:!0,sendToolHints:!1,telegram:{enabled:!1,token:"",allowFrom:[],proxy:null,replyToMessage:!1,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3},groups:{requireMention:!0,allowedGroupIds:null},commands:{native:!0,custom:[]}},discord:{enabled:!1,token:"",allowFrom:[],gatewayUrl:"wss://gateway.discord.gg/?v=10&encoding=json",intents:37377,debounce:{enabled:!0,quietMs:500,maxWaitMs:3e3}}},providers:Pa,customLlmProviders:[],customAcpProviders:[],gateway:{host:"127.0.0.1",port:6767,dashboard:{enabled:!0},heartbeat:{enabled:!0,intervalS:1800}},tools:{web:{search:{apiKey:"",maxResults:5}},exec:{timeout:60,pathAppend:""},restrictToWorkspace:!1,mcpServers:{},chromeSession:{enabled:!1,debugPort:9222,minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8,stealth:{enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}},browserRelay:{enabled:!1,authToken:"",extensionPath:""},rtk:{enabled:!0,autoInstall:!0,ultraCompact:!1,version:"latest"}},security:{enabled:!1,auth:{enabled:!1,pinHash:"",sessionTtlS:3600,lockOnIdle:!1,idleTimeoutS:900},toolGuard:{enabled:!1,guardedTools:null,deniedTools:[],rules:[],failOpen:!0},skillScanner:{enabled:!1,scanOnLoad:!1,blockUnsafe:!0,maxFileCount:1e3,maxFileSizeBytes:5242880},inputSanitizer:{enabled:!1,maxInputLength:5e4,stripHtmlTags:!1,blockPromptInjection:!1}},logging:{enabled:!0,level:"info",retentionHours:4,maxFileSizeMb:10,purgeIntervalMs:6e5},compaction:{enabled:!0,microCompactThresholdRatio:.6,autoCompactThresholdRatio:.8,keepRecentMessages:10,maxConsecutiveFailures:3}}});import Gn from"node:fs";import Ma from"node:path";function yt(){return is()}function Be(){return jn()}function bs(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]=bs(t[n],r):t[n]=r;return t}function Wn(o,e){if(o===e)return!0;if(o===null||e===null)return o===e;if(typeof o!="object"||typeof e!="object"||Array.isArray(o)!==Array.isArray(e))return!1;if(Array.isArray(o)&&Array.isArray(e))return o.length!==e.length?!1:o.every((i,a)=>Wn(i,e[a]));let t=o,n=e,r=Object.keys(t).sort(),s=Object.keys(n).sort();return r.length!==s.length?!1:r.every((i,a)=>i===s[a]&&Wn(t[i],n[i]))}function $a(o){return o.apiKey===""&&o.apiBase===null&&o.extraHeaders===null&&(o.models===void 0||o.models.length===0)}function ws(o,e,t=""){if(Ia.has(t))return o;if(o===null||e===null||typeof o!="object"||typeof e!="object")return o===e?void 0:o;if(Array.isArray(o)!==Array.isArray(e))return o;if(Array.isArray(o)&&Array.isArray(e))return Wn(o,e)?void 0:o;if(t==="providers"){let a=o,l=e,c={},d=!1;for(let[p,g]of Object.entries(a)){let x=l[p];x?Wn(g,x)||(c[p]=g,d=!0):$a(g)||(c[p]=g,d=!0)}return d?c:void 0}let n=o,r=e,s={},i=!1;for(let a of Object.keys(n)){let l=t?`${t}.${a}`:a,c=n[a],d=r[a];if(d===void 0)s[a]=c,i=!0;else{let p=ws(c,d,l);p!==void 0&&(s[a]=p,i=!0)}}return i?s:void 0}function Oa(o,e=me){return ws(o,e)??{}}function P(o){let e=o??yt();if(!Gn.existsSync(e))return structuredClone(me);try{let t=Gn.readFileSync(e,"utf8"),n=JSON.parse(t),r=bs(structuredClone(me),n),s=["advisor"];for(let i of s)if(!r.subagents.find(a=>a.id===i)){let a=me.subagents.find(l=>l.id===i);a&&r.subagents.push(structuredClone(a))}return r}catch(t){return console.warn(`Warning: Failed to load config from ${e}: ${String(t)}`),structuredClone(me)}}function oe(o,e){let t=e??yt();Gn.mkdirSync(Ma.dirname(t),{recursive:!0});let n=Oa(o);Gn.writeFileSync(t,JSON.stringify(n,null,2),"utf8")}function vs(o){let e=[],t=o.agents.defaults.provider;t!=="auto"&&t!=="custom"&&!o.providers[t]&&!o.customLlmProviders.some(r=>r.name===t)&&e.push(`Provider '${t}' is not in the provider catalog and no matching customLlmProvider exists`),o.gateway.host!=="127.0.0.1"&&o.gateway.host!=="localhost"&&o.gateway.host!=="::1"&&o.gateway.dashboard?.enabled!==!1&&!o.security?.auth?.enabled&&e.push("Dashboard exposed on non-loopback address without authentication"),o.security?.toolGuard?.enabled&&o.security?.toolGuard?.failOpen&&e.push("Tool guard is fail-open \u2014 consider fail-closed for production"),o.channels?.telegram?.enabled&&!o.channels.telegram.token&&e.push("Telegram channel enabled but no token configured"),o.channels?.discord?.enabled&&!o.channels.discord.token&&e.push("Discord channel enabled but no token configured");let n=o.channels?.telegram?.groups?.allowedGroupIds;n!=null&&!Array.isArray(n)&&e.push(`Telegram groups.allowedGroupIds should be an array (e.g. ["${n}"]), got ${typeof n}`);for(let[r,s]of Object.entries(o.tools?.mcpServers??{}))!s.command&&!s.url&&e.push(`MCP server '${r}' has neither command nor URL configured`),s.command&&s.url&&e.push(`MCP server '${r}' has both command and URL \u2014 must use one`),s.toolTimeout!==void 0&&(!Number.isFinite(s.toolTimeout)||s.toolTimeout<=0)&&e.push(`MCP server '${r}' has invalid toolTimeout`);return e}var Ia,Ue=_e(()=>{"use strict";Lt();de();je();Ia=new Set(["agents.defaults.model","agents.defaults.provider","gateway.port"])});function ce(o){if(!o)return 0;let e=typeof o=="string"?o:JSON.stringify(o);return Math.ceil(e.length/4)}function Cs(o){let e=4;if(typeof o.content=="string")e+=ce(o.content);else if(Array.isArray(o.content))for(let t of o.content)t&&typeof t=="object"&&("text"in t&&typeof t.text=="string"&&(e+=ce(t.text)),"image_url"in t&&(e+=85));if(Array.isArray(o.tool_calls))for(let t of o.tool_calls)e+=ce(t);return o.tool_call_id&&(e+=10),o.name&&(e+=ce(o.name)),o.reasoning_content&&(e+=ce(o.reasoning_content)),e}function He(o){let e=0;for(let t of o)e+=Cs(t);return e+=o.length*3,e+3}function Kn(o,e){if(e){let n=e.providers?.[e.agents.defaults.provider]?.models?.find(r=>r.id.toLowerCase()===o.toLowerCase())?.capabilities;if(n?.contextWindow)return n.contextWindow;for(let r of e.customLlmProviders??[]){let s=r.models.find(i=>i.id.toLowerCase()===o.toLowerCase());if(s?.capabilities?.contextWindow)return s.capabilities.contextWindow}}let t=o.toLowerCase();for(let[n,r]of Object.entries(ja))if(n.toLowerCase()===t||t.includes(n.toLowerCase()))return r;return Fa}function Dt(o,e){return Kn(o,e)-Ba}function po(o,e,t,n){let r=He(o),s=Dt(t,n);return r>=s*e}var ja,Fa,Ba,jt=_e(()=>{"use strict";ja={"gpt-4.1":1047576,"gpt-4.1-mini":1047576,"gpt-4.1-nano":1047576,"gpt-4o":128e3,"gpt-4o-mini":128e3,"gpt-4-turbo":128e3,"gpt-4":8192,"gpt-3.5-turbo":16385,"claude-sonnet-4":2e5,"claude-sonnet-4-20250514":2e5,"claude-3-5-sonnet":2e5,"claude-3-5-sonnet-20241022":2e5,"claude-3-5-haiku":2e5,"claude-3-opus":2e5,"claude-3-sonnet":2e5,"claude-3-haiku":2e5,"gemini-2.5-pro":1e6,"gemini-2.0-flash":1e6,"gemini-1.5-pro":1e6,"gemini-1.5-flash":1e6,"deepseek-chat":64e3,"deepseek-reasoner":64e3,"grok-2":131072,"grok-2-mini":131072},Fa=128e3,Ba=16384});var Os={};$n(Os,{LocalProcessIsolationRunner:()=>ve,selectExecutionIsolationPolicy:()=>St});import{spawn as $s}from"node:child_process";function St(o){return{...za[o]}}var za,ve,kt=_e(()=>{"use strict";za={"agent-turn":{target:"agent-turn",mode:"in-process",risk:"safe",cleanup:"none",observation:"basic",reason:"Normal agent turns stay in-process unless a later surface explicitly routes them through isolation."},"tool.exec":{target:"tool.exec",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Shell execution already crosses the local OS boundary and needs explicit launch, timeout, output capture, and cleanup semantics."},subagent:{target:"subagent",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Spawned subagents are a high-risk local execution path that later Wave D routing can move onto this process boundary."},"scheduled-job":{target:"scheduled-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Scheduled jobs can run unattended and should share the same local-process isolation contract when routed in later Wave D work."},"background-job":{target:"background-job",mode:"local-process",risk:"risky-local",cleanup:"terminate-process",observation:"stdio",reason:"Long-running background work needs the same local process cleanup and attribution boundary as other risky execution paths."}};ve=class{async run(e){let t=Math.max(1,e.maxCaptureBytes??1048576),n=typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:null,r=this.launch(e);if(r instanceof Error)return{status:"failed",pid:null,stdout:"",stderr:"",exitCode:null,signal:null,failureAttribution:"spawn_error",cleanupTriggered:!1,cleanupReason:null,errorMessage:r.message};let{child:s,spawnError:i}=r;e.stdinText!=null?s.stdin?.end(e.stdinText,"utf8"):s.stdin?.end();let a="",l="",c=!1,d=null,p=!1,g=(S,D)=>{let $=typeof S=="string"?S:S.toString("utf8"),I=t-Buffer.byteLength(D);return I<=0?D:D+$.slice(0,I)};s.stdout?.on("data",S=>{a=g(S,a)}),s.stderr?.on("data",S=>{l=g(S,l)});let x=null,y=S=>{c||(c=!0,d=S,p=S==="timeout",this.killChild(s,"SIGTERM"),x=setTimeout(()=>this.killChild(s,"SIGKILL"),250),x.unref?.())},u=()=>y("abort");e.signal?.aborted?u():e.signal?.addEventListener("abort",u,{once:!0});let b=n!=null?setTimeout(()=>y("timeout"),n):null;b?.unref?.();let R=await new Promise(S=>{let D=!1,$=I=>{D||(D=!0,S(I))};s.once("error",I=>{i.current=I,$({code:null,signal:null})}),s.once("close",(I,H)=>$({code:I,signal:H}))});return b&&clearTimeout(b),x&&clearTimeout(x),e.signal?.removeEventListener("abort",u),d==="abort"?{status:"aborted",pid:s.pid??null,stdout:a,stderr:l,exitCode:R.code,signal:R.signal,failureAttribution:"aborted",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:p?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:R.code,signal:R.signal,failureAttribution:"timeout",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:i.current?{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:R.code,signal:R.signal,failureAttribution:"spawn_error",cleanupTriggered:c,cleanupReason:d,errorMessage:i.current.message}:R.code===0?{status:"ok",pid:s.pid??null,stdout:a,stderr:l,exitCode:0,signal:R.signal,failureAttribution:"none",cleanupTriggered:c,cleanupReason:d,errorMessage:null}:{status:"failed",pid:s.pid??null,stdout:a,stderr:l,exitCode:R.code,signal:R.signal,failureAttribution:R.signal?"signal":"exit_code",cleanupTriggered:c,cleanupReason:d,errorMessage:null}}launch(e){try{return{child:e.command.kind==="shell"?$s(e.command.command,{cwd:e.cwd,env:e.env,shell:!0,detached:process.platform!=="win32",stdio:["pipe","pipe","pipe"]}):$s(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 $r={};$n($r,{McpClientManager:()=>bn});import{Client as ql}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as zl}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Vl}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{SSEClientTransport as Xl}from"@modelcontextprotocol/sdk/client/sse.js";function Qs(o){return o.replace(/[^a-zA-Z0-9_-]/g,"_")}var bn,wn=_e(()=>{"use strict";bn=class{connections=new Map;servers={};updateConfig(e){this.servers=e}async getServerTools(e){return(await this.ensureConnected(e)).tools}async callTool(e,t,n,r){let s=await this.ensureConnected(e),i=(s.timeout||60)*1e3,a=new AbortController,l=setTimeout(()=>a.abort(),i);r?.signal&&r.signal.addEventListener("abort",()=>a.abort(),{once:!0});try{let c=await s.client.callTool({name:t,arguments:n},void 0,{signal:a.signal});return c.isError?`Error: ${Array.isArray(c.content)?c.content.map(p=>p.text??JSON.stringify(p)).join(`
3
3
  `):String(c.content??"Unknown error")}`:Array.isArray(c.content)?c.content.map(p=>p.type==="text"?p.text:JSON.stringify(p)).filter(Boolean).join(`
4
- `)||"OK":c.content?String(c.content):"OK"}finally{clearTimeout(l)}}async closeAll(){let e=[...this.connections.entries()];this.connections.clear();for(let[,t]of e)try{await(await t).client.close()}catch{}}async closeServer(e){let t=this.connections.get(e);if(t){this.connections.delete(e);try{await(await t).client.close()}catch{}}}ensureConnected(e){let t=this.connections.get(e);return t||(t=this.connectServer(e),this.connections.set(e,t),t.catch(()=>this.connections.delete(e)),t)}async connectServer(e){let t=this.servers[e];if(!t)throw new Error(`MCP server '${e}' is not configured.`);let n=this.createTransport(e,t),r=new sl({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=Cs(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${Cs(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 il({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 al(s,{requestInit:{headers:a}})}catch{return new ll(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 pn,fn,hn=Ge(()=>{"use strict";pn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(pn||{}),fn=(d=>(d.COMMAND_INJECTION="COMMAND_INJECTION",d.DATA_EXFILTRATION="DATA_EXFILTRATION",d.PATH_TRAVERSAL="PATH_TRAVERSAL",d.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",d.NETWORK_ABUSE="NETWORK_ABUSE",d.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",d.RESOURCE_ABUSE="RESOURCE_ABUSE",d.PROMPT_INJECTION="PROMPT_INJECTION",d.CODE_EXECUTION="CODE_EXECUTION",d.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",d))(fn||{})});var Gs={};Gr(Gs,{ToolGuardEngine:()=>yn});import Gl from"node:fs";function Ul(){if(Ar)return Ar;try{let o=Ye("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=Gl.readFileSync(o,"utf8"),t=JSON.parse(e);return Ar=t,t}catch{return[]}}function Kl(o){if(o.length===0)return"SAFE";let e=po.SAFE;for(let t of o){let n=po[t.severity]??po.SAFE;n<e&&(e=n)}return Wl[e]??"SAFE"}var Ar,po,Wl,yn,fo=Ge(()=>{"use strict";Fe();hn();le();Ar=null;po={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Wl={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};yn=class o{static instance=null;config;guardians=[];mergedRules=[];loadFromDisk;constructor(e){this.loadFromDisk=e===void 0,this.config=e??M(),this.reloadRules()}static getInstance(e){return o.instance||(o.instance=new o(e)),o.instance}static resetInstance(){o.instance=null,Ar=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 v={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(v)}}let l=performance.now()-n,c=Kl(r);return{toolName:e,params:t,findings:r,guardDurationMs:l,guardiansUsed:s,guardiansFailed:i,isSafe:c!=="CRITICAL"&&c!=="HIGH",maxSeverity:c}}registerGuardian(e){this.guardians.some(t=>t.name===e.name)||this.guardians.push(e)}unregisterGuardian(e){this.guardians=this.guardians.filter(t=>t.name!==e)}getRegisteredGuardians(){return this.guardians.map(e=>e.name)}getRules(){return this.mergedRules}getConfig(){return this.config}reloadRules(){this.loadFromDisk&&(this.config=M());let e=Ul(),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 Bo from"node:path";import{createRequire as Oi}from"node:module";function ae(){return new Date().toISOString()}De();var Di=Oi(import.meta.url),Rn=null;function Ni(){return Rn||(Rn=Di("node:sqlite").DatabaseSync,Rn)}function Go(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 Fo=[{version:1,name:"create-operational-state-tables",sql:`
4
+ `)||"OK":c.content?String(c.content):"OK"}finally{clearTimeout(l)}}async closeAll(){let e=[...this.connections.entries()];this.connections.clear();for(let[,t]of e)try{await(await t).client.close()}catch{}}async closeServer(e){let t=this.connections.get(e);if(t){this.connections.delete(e);try{await(await t).client.close()}catch{}}}ensureConnected(e){let t=this.connections.get(e);return t||(t=this.connectServer(e),this.connections.set(e,t),t.catch(()=>this.connections.delete(e)),t)}async connectServer(e){let t=this.servers[e];if(!t)throw new Error(`MCP server '${e}' is not configured.`);let n=this.createTransport(e,t),r=new ql({name:"everclaw",version:"1.0.0"});await r.connect(n);let{tools:s}=await r.listTools(),i=Qs(e),a=s.map(l=>({serverName:e,remoteName:l.name,proxyName:`mcp__${i}__${Qs(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 zl({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 Vl(s,{requestInit:{headers:a}})}catch{return new Xl(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 ti={};$n(ti,{aggressiveMicroCompact:()=>Nr,estimateMicroCompactSavings:()=>ei,microCompact:()=>Lr,wouldMicroCompactHelp:()=>Zs});function Lr(o,e=10){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=typeof a.name=="string"?a.name:"";if(!Po.has(l))continue;let c=a.content;if(typeof c!="string"||c===Xe)continue;let d=ce(c);t[i]={...a,content:Xe},n+=d-ce(Xe),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function Nr(o,e=4){let t=o.map(i=>({...i})),n=0,r=0,s=Math.max(0,t.length-e);for(let i=0;i<s;i++){let a=t[i];if(!a||a.role!=="tool")continue;let l=a.content;if(typeof l!="string"||l===Xe)continue;let c=ce(l);t[i]={...a,content:Xe},n+=c-ce(Xe),r++}return{messages:t,tokensFreed:n,messagesCleared:r}}function Zs(o,e=10){let t=Math.max(0,o.length-e);for(let n=0;n<t;n++){let r=o[n];if(!r||r.role!=="tool")continue;let s=typeof r.name=="string"?r.name:"";if(!Po.has(s))continue;let i=r.content;if(typeof i=="string"&&i!==Xe&&i.length>100)return!0}return!1}function ei(o,e=10){let t=0,n=Math.max(0,o.length-e);for(let r=0;r<n;r++){let s=o[r];if(!s||s.role!=="tool")continue;let i=typeof s.name=="string"?s.name:"";if(!Po.has(i))continue;let a=s.content;typeof a=="string"&&a!==Xe&&(t+=ce(a)-ce(Xe))}return t}var Po,Xe,vn=_e(()=>{"use strict";jt();Po=new Set(["read_file","exec","grep_search","list_dir","web_search","web_fetch","write_file","edit_file","glob_search","list_directory","Read","Execute","Grep","Glob","LS","FetchUrl","WebSearch","exa___web_search_exa","exa___web_fetch_exa","context7___resolve-library-id","context7___query-docs","deepwiki___read_wiki_structure","deepwiki___read_wiki_contents","deepwiki___ask_question"]),Xe="[Tool result cleared to save context]"});var Tn,Rn,An=_e(()=>{"use strict";Tn=(i=>(i.CRITICAL="CRITICAL",i.HIGH="HIGH",i.MEDIUM="MEDIUM",i.LOW="LOW",i.INFO="INFO",i.SAFE="SAFE",i))(Tn||{}),Rn=(d=>(d.COMMAND_INJECTION="COMMAND_INJECTION",d.DATA_EXFILTRATION="DATA_EXFILTRATION",d.PATH_TRAVERSAL="PATH_TRAVERSAL",d.SENSITIVE_FILE_ACCESS="SENSITIVE_FILE_ACCESS",d.NETWORK_ABUSE="NETWORK_ABUSE",d.CREDENTIAL_EXPOSURE="CREDENTIAL_EXPOSURE",d.RESOURCE_ABUSE="RESOURCE_ABUSE",d.PROMPT_INJECTION="PROMPT_INJECTION",d.CODE_EXECUTION="CODE_EXECUTION",d.PRIVILEGE_ESCALATION="PRIVILEGE_ESCALATION",d))(Rn||{})});var Ai={};$n(Ai,{ToolGuardEngine:()=>En});import _c from"node:fs";function Mc(){if(Hr)return Hr;try{let o=et("security","tool-guard","rules","default-rules.json");if(!o)return[];let e=_c.readFileSync(o,"utf8"),t=JSON.parse(e);return Hr=t,t}catch{return[]}}function $c(o){if(o.length===0)return"SAFE";let e=Fo.SAFE;for(let t of o){let n=Fo[t.severity]??Fo.SAFE;n<e&&(e=n)}return Ic[e]??"SAFE"}var Hr,Fo,Ic,En,Bo=_e(()=>{"use strict";Ue();An();de();Hr=null;Fo={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3,INFO:4,SAFE:5},Ic={0:"CRITICAL",1:"HIGH",2:"MEDIUM",3:"LOW",4:"INFO",5:"SAFE"};En=class o{static instance=null;config;guardians=[];mergedRules=[];loadFromDisk;constructor(e){this.loadFromDisk=e===void 0,this.config=e??P(),this.reloadRules()}static getInstance(e){return o.instance||(o.instance=new o(e)),o.instance}static resetInstance(){o.instance=null,Hr=null}isDenied(e){return!this.config.security.enabled||!this.config.security.toolGuard.enabled?!1:this.config.security.toolGuard.deniedTools.includes(e)}isGuarded(e){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return!1;let t=this.config.security.toolGuard.guardedTools;return t===null?!0:t.includes(e)}guard(e,t){if(!this.config.security.enabled||!this.config.security.toolGuard.enabled)return null;if(this.isDenied(e)){let p={id:`denied-${e}-${Date.now()}`,ruleId:"denied-tools-list",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Tool '${e}' is denied`,description:`The tool '${e}' is in the denied tools list and cannot be executed.`,toolName:e,guardian:"ToolGuardEngine"};return{toolName:e,params:t,findings:[p],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!1,maxSeverity:"CRITICAL"}}if(!this.isGuarded(e))return{toolName:e,params:t,findings:[],guardDurationMs:0,guardiansUsed:[],guardiansFailed:[],isSafe:!0,maxSeverity:"SAFE"};let n=performance.now(),r=[],s=[],i=[],a=this.config.security.toolGuard.failOpen!==!1;for(let p of this.guardians)try{let g=p.guard({toolName:e,params:t});g.length>0&&r.push(...g),s.push(p.name)}catch(g){if(i.push(p.name),console.error(`ToolGuardEngine: guardian '${p.name}' failed: ${String(g)}`),!a){let x={id:`guardian-error-${p.name}-${Date.now()}`,ruleId:"guardian-error",category:"PRIVILEGE_ESCALATION",severity:"CRITICAL",title:`Guardian '${p.name}' failed`,description:`Security guardian encountered an error and failOpen is disabled: ${String(g)}`,toolName:e,guardian:"ToolGuardEngine"};r.push(x)}}let l=performance.now()-n,c=$c(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=P());let e=Mc(),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 us from"node:path";import{createRequire as Sa}from"node:module";function le(){return new Date().toISOString()}je();var ka=Sa(import.meta.url),Fn=null;function Ca(){return Fn||(Fn=ka("node:sqlite").DatabaseSync,Fn)}function gs(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 ds=[{version:1,name:"create-operational-state-tables",sql:`
5
5
  CREATE TABLE IF NOT EXISTS session_metadata (
6
6
  workspace TEXT NOT NULL,
7
7
  session_key TEXT NOT NULL,
@@ -68,36 +68,50 @@ var Ii=Object.defineProperty;var _i=(o=>typeof require<"u"?require:typeof Proxy<
68
68
 
69
69
  CREATE INDEX IF NOT EXISTS idx_inbox_deliveries_workspace_cleared_at
70
70
  ON inbox_deliveries (workspace, cleared_at, delivered_at DESC);
71
- `}];function ji(o=Tn()){return Bo.join(o,"runtime","operations.sqlite")}var Hr=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 Go(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
71
+ `}];function xa(o=jn()){return us.join(o,"runtime","operations.sqlite")}var ao=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 gs(this.db,e)}getAppliedMigrations(){return this.db.prepare(`SELECT version, name, applied_at
72
72
  FROM schema_migrations
73
- ORDER BY version`).all().map(t=>({version:Number(t.version),name:String(t.name),applied_at:String(t.applied_at)}))}getCurrentVersion(){return this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations").get().version}};function Fi(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 Ta(o){o.exec(`
74
74
  CREATE TABLE IF NOT EXISTS schema_migrations (
75
75
  version INTEGER PRIMARY KEY,
76
76
  name TEXT NOT NULL,
77
77
  applied_at TEXT NOT NULL
78
78
  );
79
- `)}function Ne(o={}){let e=o.dbPath??ji(o.dataDir);Xe(Bo.dirname(e));let t=Ni(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),Fi(n);let r=Fo.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 Fo)i.has(a.version)||Go(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,ae())});return new Hr(n,e)}var Bi=new Set(["agent","gateway"]);function Gi(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function Ui(o){let e=Gi(o);return!!e&&Bi.has(e)}function Uo(o,e={}){if(!Ui(o))return!1;let t=e.openStorage??Ne,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}}Fe();It();import ce from"node:fs";import Ci from"node:readline/promises";import{stdin as xi,stdout as Ti}from"node:process";import{Command as pd,Option as _o}from"commander";import pe from"prompts";import C from"chalk";function Vi(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 Yo(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 Vt(o,e,t){let n=Vi(e),r=Yo(o,n);return t?Yo(r,t):r}le();le();import _t from"node:fs";import Xo from"node:path";import Yi from"node:os";var Xi="gateway.pid";function zr(){return Xo.join(Yi.homedir(),ct,Xi)}function Vr(o){let e=zr();_t.mkdirSync(Xo.dirname(e),{recursive:!0}),_t.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Ie(){let o=zr();if(!_t.existsSync(o))return null;try{let e=_t.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function _e(o){let e=zr();try{if(!_t.existsSync(e))return;if(o!==void 0){let t=Ie();if(t&&t.pid!==o)return}_t.unlinkSync(e)}catch{}}function Pe(o){try{return process.kill(o,0),!0}catch{return!1}}async function Yr(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Pe(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Pe(o)}function pt(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(" ")}De();var Yt=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 ft=class{inbound=new Yt;outbound=new Yt;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 xs from"node:path";import Qo from"node:fs";import $n from"node:path";import Zo from"node:os";import Xt from"node:fs";import _n from"node:path";var Qi=[{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"]}}}],Qt=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=_n.join(e,"memory");this.memoryDir=t?_n.join(n,t):n,Xt.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=_n.join(this.memoryDir,"MEMORY.md"),this.historyFile=_n.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return Xt.existsSync(this.memoryFile)?Xt.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){Xt.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){Xt.appendFileSync(this.historyFile,`${e.trim()}
79
+ `)}function Fe(o={}){let e=o.dbPath??xa(o.dataDir);tt(us.dirname(e));let t=Ca(),n=new t(e);n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;"),n.exec("PRAGMA busy_timeout = 5000;"),Ta(n);let r=ds.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 ds)i.has(a.version)||gs(n,()=>{n.exec(a.sql),n.prepare("INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)").run(a.version,a.name,le())});return new ao(n,e)}var Ra=new Set(["agent","gateway"]);function Aa(o){for(let e of o.slice(2))if(!e.startsWith("-"))return e;return null}function Ea(o){let e=Aa(o);return!!e&&Ra.has(e)}function ms(o,e={}){if(!Ea(o))return!1;let t=e.openStorage??Fe,n=e.onError??(s=>console.error(s)),r=e.exit??(s=>process.exit(s));try{return t().close(),!0}catch(s){let i=s instanceof Error?s.message:String(s);return n(`Failed to initialize operational storage: ${i}`),r(1),!1}}Ue();Lt();import ue from"node:fs";import ca from"node:readline/promises";import{stdin as da,stdout as ua}from"node:process";import{Command as ru,Option as ns}from"commander";import ye from"prompts";import v from"chalk";function La(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 Ss(o,e){let t=structuredClone(o);if(e.provider!==void 0&&(t.agents.defaults.provider=e.provider),e.model!==void 0&&(t.agents.defaults.model=e.model),e.gatewayHost!==void 0&&(t.gateway.host=e.gatewayHost),e.gatewayPort!==void 0&&(t.gateway.port=e.gatewayPort),e.dashboardEnabled!==void 0){let n=t.gateway;n.dashboard&&typeof n.dashboard=="object"&&(n.dashboard.enabled=e.dashboardEnabled)}if(e.apiKey!==void 0||e.apiBase!==void 0){let n=t.agents.defaults.provider;n&&n!=="auto"&&(t.providers[n]||(t.providers[n]={apiKey:"",apiBase:null,extraHeaders:null}),e.apiKey!==void 0&&(t.providers[n].apiKey=e.apiKey),e.apiBase!==void 0&&(t.providers[n].apiBase=e.apiBase))}return t}function nn(o,e,t){let n=La(e),r=Ss(o,n);return t?Ss(r,t):r}de();de();import Nt from"node:fs";import ks from"node:path";import Na from"node:os";var Da="gateway.pid";function uo(){return ks.join(Na.homedir(),mt,Da)}function go(o){let e=uo();Nt.mkdirSync(ks.dirname(e),{recursive:!0}),Nt.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}function Ie(){let o=uo();if(!Nt.existsSync(o))return null;try{let e=Nt.readFileSync(o,"utf8");return JSON.parse(e)}catch{return null}}function $e(o){let e=uo();try{if(!Nt.existsSync(e))return;if(o!==void 0){let t=Ie();if(t&&t.pid!==o)return}Nt.unlinkSync(e)}catch{}}function Me(o){try{return process.kill(o,0),!0}catch{return!1}}async function mo(o,e){let t=Date.now();for(;Date.now()-t<e;){if(!Me(o))return!0;await new Promise(n=>setTimeout(n,200))}return!Me(o)}function bt(o){let e=new Date(o).getTime();if(Number.isNaN(e))return"unknown";let t=Date.now()-e;if(t<0)return"unknown";let n=Math.floor(t/1e3),r=Math.floor(n/86400),s=Math.floor(n%86400/3600),i=Math.floor(n%3600/60),a=[];return r>0&&a.push(`${r}d`),s>0&&a.push(`${s}h`),a.push(`${i}m`),a.join(" ")}je();var rn=class{items=[];waiters=[];push(e){let t=this.waiters.shift();t?t(e):this.items.push(e)}async pop(){let e=this.items.shift();return e!==void 0?e:new Promise(t=>this.waiters.push(t))}size(){return this.items.length}};var wt=class{inbound=new rn;outbound=new rn;async publishInbound(e){this.inbound.push(e)}async consumeInbound(){return this.inbound.pop()}async publishOutbound(e){this.outbound.push(e)}async consumeOutbound(){return this.outbound.pop()}get inboundSize(){return this.inbound.size()}get outboundSize(){return this.outbound.size()}};import di from"node:path";import xs from"node:fs";import qn from"node:path";import Ts from"node:os";jt();import on from"node:fs";import Hn from"node:path";var Ua=[{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"]}}}],sn=class{memoryDir;memoryFile;historyFile;constructor(e,t){let n=Hn.join(e,"memory");this.memoryDir=t?Hn.join(n,t):n,on.mkdirSync(this.memoryDir,{recursive:!0}),this.memoryFile=Hn.join(this.memoryDir,"MEMORY.md"),this.historyFile=Hn.join(this.memoryDir,"HISTORY.md")}readLongTerm(){return on.existsSync(this.memoryFile)?on.readFileSync(this.memoryFile,"utf8"):""}writeLongTerm(e){on.writeFileSync(this.memoryFile,e,"utf8")}appendHistory(e){on.appendFileSync(this.historyFile,`${e.trim()}
80
80
 
81
81
  `,"utf8")}getMemoryContext(){let e=this.readLongTerm();return e?`## Long-term Memory
82
- ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],d=[];for(let w of a)w._type==="anchor"?c.push(w):d.push(w);let p=[];for(let w of c)p.push(`[ANCHOR] ${w.name}: ${w.summary??"(no summary)"}`);for(let w of d){if(!w.content&&!w._full_content)continue;let u=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()}${u}: ${String(b)}`)}let h=this.readLongTerm(),v=`Process this conversation and call the save_memory tool with your consolidation.
82
+ ${e}`:""}async consolidate(e,t,n,r){let s=r?.archiveAll??!1,i=r?.memoryWindow??50,a=[],l=0;if(s)a=e.messages,l=0;else if(l=Math.floor(i/2),e.messages.length<=l||e.messages.length-e.lastConsolidated<=0||(a=e.messages.slice(e.lastConsolidated,e.messages.length-l),!a.length))return!0;let c=[],d=[];for(let $ of a)$._type==="anchor"?c.push($):d.push($);let p=[];for(let $ of c)p.push(`[ANCHOR] ${$.name}: ${$.summary??"(no summary)"}`);for(let $ of d){if(!$.content&&!$._full_content)continue;let I=Array.isArray($.tools_used)&&$.tools_used.length?` [tools: ${$.tools_used.join(", ")}]`:"",H=$._full_content??$.content;p.push(`[${String($.timestamp??"?").slice(0,16)}] ${String($.role).toUpperCase()}${I}: ${String(H)}`)}let g=this.readLongTerm(),x=`Process this conversation and call the save_memory tool with your consolidation.
83
83
 
84
84
  ## Current Long-term Memory
85
- ${h||"(empty)"}
85
+ ${g||"(empty)"}
86
86
 
87
87
  ## Conversation to Process
88
88
  ${p.join(`
89
- `)}`;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:v}],tools:Qi});if(!w.toolCalls.length)return!1;let u=w.toolCalls[0];if(!u)return!1;let b=u.arguments??{},E=b.history_entry,S=b.memory_update;if(E!=null&&this.appendHistory(typeof E=="string"?E:JSON.stringify(E)),S!=null){let J=typeof S=="string"?S:JSON.stringify(S);J!==h&&this.writeLongTerm(J)}let N=s?0:e.messages.length-l,U=e.messages.slice(0,N),I=-1;for(let J=U.length-1;J>=0;J--)if(U[J]?._type==="anchor"){I=J;break}return I!==-1?e.lastConsolidated=I+1:e.lastConsolidated=N,!0}catch{return!1}}};le();import Zt from"node:fs";import en from"node:path";var Xr=/^[a-z0-9][a-z0-9-]*$/;function Mn(o){return Xr.test(o)}var Ke=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=en.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??No("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
+ `)}`,y=ce(`Process this conversation and call the save_memory tool with your consolidation.
90
+
91
+ ## Current Long-term Memory
92
+
93
+
94
+ ## Conversation to Process
95
+ `),u=ce(g||"(empty)"),b=ce(p.join(`
96
+ `)),R=y+u+b,S=Kn(n),D=Math.floor(S*.9);if(R>D){let $=Math.max(1e3,D-y-u),I=Math.floor($*4),L=p.join(`
97
+ `).slice(-I);x=`Process this conversation and call the save_memory tool with your consolidation.
98
+
99
+ ## Current Long-term Memory
100
+ ${g||"(empty)"}
101
+
102
+ ## Conversation to Process (truncated, most recent)
103
+ ${L}`}try{let $=await t.chat({model:n,messages:[{role:"system",content:"You are a memory consolidation agent. Call the save_memory tool."},{role:"user",content:x}],tools:Ua});if(!$.toolCalls.length)return!1;let I=$.toolCalls[0];if(!I)return!1;let H=I.arguments??{},L=H.history_entry,Q=H.memory_update;if(L!=null&&this.appendHistory(typeof L=="string"?L:JSON.stringify(L)),Q!=null){let B=typeof Q=="string"?Q:JSON.stringify(Q);B!==g&&this.writeLongTerm(B)}let Y=s?0:e.messages.length-l,F=e.messages.slice(0,Y),z=-1;for(let B=F.length-1;B>=0;B--)if(F[B]?._type==="anchor"){z=B;break}return z!==-1?e.lastConsolidated=z+1:e.lastConsolidated=Y,!0}catch{return!1}}};de();import an from"node:fs";import ln from"node:path";var fo=/^[a-z0-9][a-z0-9-]*$/;function Jn(o){return fo.test(o)}var Je=class{workspaceSkills;userSkills;builtinSkills;scannerConfig;scanner;constructor(e,t,n,r,s){this.workspaceSkills=ln.join(e,"skills"),this.userSkills=t??null,this.builtinSkills=n??ls("skills"),this.scannerConfig=r??null,this.scanner=s??null}listSkills(e=!0){return(e?this.getResolvedSkills().filter(n=>n.status==="available"):this.getResolvedSkills()).map(({name:n,path:r,source:s})=>({name:n,path:r,source:s}))}listResolvedSkills(){return this.getResolvedSkills().map(({content:e,metadata:t,runtimeMeta:n,...r})=>r)}loadSkill(e){let t=this.getSkillByName(e);return t?.status==="available"?t.content:null}loadSkillsForContext(e){let t=[];for(let n of e){let r=this.getSkillByName(n);if(!r){t.push(this.renderLoadFailure(n,`Skill '${n}' is not installed. ${this.getAvailableSkillsHint()}`));continue}if(r.status!=="available"){let s=r.status==="malformed"?`Skill '${n}' is malformed: ${r.reason}.`:r.status==="blocked"?`Skill '${n}' is blocked by security scanner: ${r.reason}.`:`Skill '${n}' is unavailable: ${r.reason}.`;t.push(this.renderLoadFailure(n,s));continue}t.push(`### Skill: ${n}
90
104
 
91
105
  ${this.stripFrontmatter(r.content)}`)}return t.join(`
92
106
 
93
107
  ---
94
108
 
95
109
  `)}buildSkillsSummary(){let e=this.getResolvedSkills();if(!e.length)return"";let t=r=>r.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;"),n=["<skills>"];for(let r of e)n.push(` <skill available="${r.status==="available"}" source="${t(r.source)}">`),n.push(` <name>${t(r.name)}</name>`),n.push(` <description>${t(r.description)}</description>`),n.push(` <location>${t(r.path)}</location>`),n.push(` <status>${t(r.status)}</status>`),r.reason&&n.push(` <reason>${t(r.reason)}</reason>`),n.push(" </skill>");return n.push("</skills>"),n.join(`
96
- `)}getAlwaysSkills(){return this.getResolvedSkills().filter(e=>e.status==="available"&&e.always).map(e=>e.name)}getSkillMetadata(e){return this.getSkillByName(e)?.metadata??null}stripFrontmatter(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length).trim():e}getResolvedSkills(){let e=new Map;for(let{root:t,source:n}of this.getSkillRoots()){if(!Zt.existsSync(t))continue;let r=Zt.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,i)=>s.name.localeCompare(i.name));for(let s of r){if(e.has(s.name))continue;let i=en.join(t,s.name,"SKILL.md");Zt.existsSync(i)&&e.set(s.name,this.readSkill(s.name,i,n))}}return[...e.values()].sort((t,n)=>t.name.localeCompare(n.name))}getSkillByName(e){return this.getResolvedSkills().find(t=>t.name===e)??null}getSkillRoots(){let e=[{root:this.workspaceSkills,source:"workspace"}];return this.userSkills&&e.push({root:this.userSkills,source:"user"}),e.push({root:this.builtinSkills,source:"builtin"}),e}readSkill(e,t,n){let r=Zt.readFileSync(t,"utf8"),s=this.parseSkill(e,r);if(s.errors.length)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:{},description:s.description,status:"malformed",reason:s.errors.join("; "),always:!1};let i=this.getRequirementErrors(s.runtimeMeta),a=this.runSecurityScan(t,e);if(a&&!a.isSafe&&this.scannerConfig?.blockUnsafe)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:"blocked",reason:this.formatBlockedReason(a),always:s.always};if(a&&a.findings.length>0){let l=a.findings.map(c=>`[${c.severity}] ${c.title} (${c.category})`);console.warn(`SkillScanner: skill '${e}' has ${a.findings.length} finding(s): ${l.join("; ")}`)}return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:i.length?"unavailable":"available",reason:i.length?i.join("; "):null,always:s.always}}runSecurityScan(e,t){if(!this.scannerConfig?.enabled||!this.scannerConfig.scanOnLoad||!this.scanner)return null;let n=en.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}'`):Xr.test(l)||a.push(`frontmatter name '${l}' must match ${Xr}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let d=s.always;return d!==void 0&&typeof d!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:d??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
110
+ `)}getAlwaysSkills(){return this.getResolvedSkills().filter(e=>e.status==="available"&&e.always).map(e=>e.name)}getSkillMetadata(e){return this.getSkillByName(e)?.metadata??null}stripFrontmatter(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return t?e.slice(t[0].length).trim():e}getResolvedSkills(){let e=new Map;for(let{root:t,source:n}of this.getSkillRoots()){if(!an.existsSync(t))continue;let r=an.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,i)=>s.name.localeCompare(i.name));for(let s of r){if(e.has(s.name))continue;let i=ln.join(t,s.name,"SKILL.md");an.existsSync(i)&&e.set(s.name,this.readSkill(s.name,i,n))}}return[...e.values()].sort((t,n)=>t.name.localeCompare(n.name))}getSkillByName(e){return this.getResolvedSkills().find(t=>t.name===e)??null}getSkillRoots(){let e=[{root:this.workspaceSkills,source:"workspace"}];return this.userSkills&&e.push({root:this.userSkills,source:"user"}),e.push({root:this.builtinSkills,source:"builtin"}),e}readSkill(e,t,n){let r=an.readFileSync(t,"utf8"),s=this.parseSkill(e,r);if(s.errors.length)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:{},description:s.description,status:"malformed",reason:s.errors.join("; "),always:!1};let i=this.getRequirementErrors(s.runtimeMeta),a=this.runSecurityScan(t,e);if(a&&!a.isSafe&&this.scannerConfig?.blockUnsafe)return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:"blocked",reason:this.formatBlockedReason(a),always:s.always};if(a&&a.findings.length>0){let l=a.findings.map(c=>`[${c.severity}] ${c.title} (${c.category})`);console.warn(`SkillScanner: skill '${e}' has ${a.findings.length} finding(s): ${l.join("; ")}`)}return{name:e,path:t,source:n,content:r,metadata:s.metadata,runtimeMeta:s.runtimeMeta,description:s.description,status:i.length?"unavailable":"available",reason:i.length?i.join("; "):null,always:s.always}}runSecurityScan(e,t){if(!this.scannerConfig?.enabled||!this.scannerConfig.scanOnLoad||!this.scanner)return null;let n=ln.dirname(e);return this.scanner.scanSkill(n,t,{maxFileCount:this.scannerConfig.maxFileCount,maxFileSizeBytes:this.scannerConfig.maxFileSizeBytes})}formatBlockedReason(e){let t=e.findings.filter(r=>r.severity==="CRITICAL");return t.length===0?"Security scan failed":`Blocked by security scanner: ${t.map(r=>`[${r.severity}] ${r.title} (${r.category})`).join("; ")}`}parseSkill(e,t){let n=this.extractFrontmatter(t);if(!n.frontmatter)return{metadata:null,runtimeMeta:{},description:e,always:!1,errors:[n.error??"missing YAML frontmatter"]};let r=this.parseFrontmatter(n.frontmatter),s=r.metadata,i=typeof s.description=="string"&&s.description.trim()?s.description.trim():e,a=[...r.errors],l=typeof s.name=="string"?s.name.trim():"";l?l!==e?a.push(`frontmatter name '${l}' does not match directory '${e}'`):fo.test(l)||a.push(`frontmatter name '${l}' must match ${fo}`):a.push("missing required frontmatter field 'name'"),typeof s.description=="string"&&s.description.trim()||a.push("missing required frontmatter field 'description'");let c=this.parseRuntimeMetadata(s.metadata);a.push(...c.errors);let d=s.always;return d!==void 0&&typeof d!="boolean"&&a.push("frontmatter field 'always' must be a boolean"),{metadata:s,runtimeMeta:c.runtimeMeta,description:i,always:d??c.runtimeMeta.always??!1,errors:a}}extractFrontmatter(e){if(!(e.startsWith(`---
97
111
  `)||e.startsWith(`---\r
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(en.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>Zt.existsSync(en.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}
112
+ `)))return{frontmatter:null,error:"missing YAML frontmatter"};let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);return t?{frontmatter:t[1]??null,error:null}:{frontmatter:null,error:"unterminated YAML frontmatter"}}parseFrontmatter(e){let t={},n=[];for(let r of e.split(/\r?\n/)){let s=r.trim();if(!s)continue;let i=s.indexOf(":");if(i<=0){n.push(`invalid frontmatter line '${s}'`);continue}let a=s.slice(0,i).trim(),l=s.slice(i+1).trim();t[a]=this.parseFrontmatterValue(l)}return{metadata:t,errors:n}}parseFrontmatterValue(e){let t=e.replace(/^['"]|['"]$/g,"");return t==="true"?!0:t==="false"?!1:t}parseRuntimeMetadata(e){if(e===void 0||e==="")return{runtimeMeta:{},errors:[]};if(typeof e!="string")return{runtimeMeta:{},errors:["frontmatter field 'metadata' must be a JSON object string"]};let t;try{t=JSON.parse(e)}catch{return{runtimeMeta:{},errors:["frontmatter field 'metadata' must contain valid JSON"]}}if(!this.isRecord(t))return{runtimeMeta:{},errors:["frontmatter field 'metadata' must decode to an object"]};let n=t.everclaw??t.openclaw??{};if(!this.isRecord(n))return{runtimeMeta:{},errors:["skill metadata for 'everclaw'/'openclaw' must be an object"]};let r=[],s={};if(n.always!==void 0&&(typeof n.always!="boolean"?r.push("skill metadata field 'always' must be a boolean"):s.always=n.always),n.requires!==void 0)if(!this.isRecord(n.requires))r.push("skill metadata field 'requires' must be an object");else{let i=n.requires.bins,a=n.requires.env;i!==void 0&&!this.isStringArray(i)&&r.push("skill metadata field 'requires.bins' must be an array of strings"),a!==void 0&&!this.isStringArray(a)&&r.push("skill metadata field 'requires.env' must be an array of strings");let l={};this.isStringArray(i)&&(l.bins=i),this.isStringArray(a)&&(l.env=a),Object.keys(l).length>0&&(s.requires=l)}return{runtimeMeta:s,errors:r}}getRequirementErrors(e){let t=e.requires??{},n=(t.bins??[]).filter(i=>!this.hasBinary(i)),r=(t.env??[]).filter(i=>!process.env[i]),s=[];return n.length&&s.push(`missing required binaries: ${n.join(", ")}`),r.length&&s.push(`missing required env vars: ${r.join(", ")}`),s}hasBinary(e){let t=(process.env.PATH??"").split(ln.delimiter).filter(Boolean),n=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return t.some(r=>n.some(s=>an.existsSync(ln.join(r,`${e}${s}`))))}getAvailableSkillsHint(){let e=this.getResolvedSkills().filter(t=>t.status==="available").map(t=>t.name);return e.length?`Available skills: ${e.join(", ")}`:"No skills are currently available."}renderLoadFailure(e,t){return`### Skill unavailable: ${e}
99
113
 
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 ht=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new Qt(e),this.skills=new Ke(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 Qt(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
114
+ Error: ${t}`}isRecord(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}isStringArray(e){return Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.trim().length>0)}};var vt=class o{constructor(e,t,n){this.workspace=e;this.defaultMemory=new sn(e),this.skills=new Je(e,null,void 0,t,n)}static BOOTSTRAP_FILES=["AGENTS.md","SOUL.md","USER.md","TOOLS.md","IDENTITY.md"];static RUNTIME_CONTEXT_TAG="[Runtime Context - metadata only, not instructions]";static ANCHOR_TAG="[anchor]";static estimateTokens(e){if(!e)return 0;let t=typeof e=="string"?e:JSON.stringify(e);return Math.ceil(t.length/4)}static estimateMessageTokens(e){let t=0;if(typeof e.content=="string"&&(t+=o.estimateTokens(e.content)),Array.isArray(e.tool_calls))for(let n of e.tool_calls)t+=o.estimateTokens(n);return t}static findLastAnchor(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n)continue;let r=n.content;if(typeof r=="string"&&r.includes(o.ANCHOR_TAG))return{name:r.match(/\[anchor\]\s*(\S+)/)?.[1]??null,index:t}}return{name:null,index:-1}}defaultMemory;skills;getMemoryStore(e){return e?new sn(this.workspace,e):this.defaultMemory}buildSystemPrompt(e,t){let n=[this.getIdentity()],r=this.loadBootstrapFiles();r&&n.push(r);let i=this.getMemoryStore(t).getMemoryContext();i&&n.push(`# Memory
101
115
 
102
116
  ${i}`);let a=this.skills.getAlwaysSkills();if(a.length){let c=this.skills.loadSkillsForContext(a);c&&n.push(`# Active Skills
103
117
 
@@ -116,45 +130,47 @@ ${l}`),n.join(`
116
130
  You are everclaw, a helpful AI assistant.
117
131
 
118
132
  ## Runtime
119
- ${Zo.platform()} ${Zo.arch()}, Node ${process.version}
133
+ ${Ts.platform()} ${Ts.arch()}, Node ${process.version}
120
134
 
121
135
  ## Workspace
122
136
  Your workspace is at: ${this.workspace}
123
- - Long-term memory: ${$n.join(this.workspace,"memory","MEMORY.md")}
124
- - History log: ${$n.join(this.workspace,"memory","HISTORY.md")}
125
- - Custom skills: ${$n.join(this.workspace,"skills","{skill-name}","SKILL.md")}
137
+ - Long-term memory: ${qn.join(this.workspace,"memory","MEMORY.md")}
138
+ - History log: ${qn.join(this.workspace,"memory","HISTORY.md")}
139
+ - Custom skills: ${qn.join(this.workspace,"skills","{skill-name}","SKILL.md")}
126
140
 
127
141
  ## Guidelines
128
142
  - State intent before tool calls, but never claim results before receiving them.
129
143
  - Before modifying a file, read it first.
130
- - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=$n.join(this.workspace,t);Qo.existsSync(n)&&e.push(`## ${t}
144
+ - Ask for clarification when the request is ambiguous.`}loadBootstrapFiles(){let e=[];for(let t of o.BOOTSTRAP_FILES){let n=qn.join(this.workspace,t);xs.existsSync(n)&&e.push(`## ${t}
131
145
 
132
- ${Qo.readFileSync(n,"utf8")}`)}return e.join(`
146
+ ${xs.readFileSync(n,"utf8")}`)}return e.join(`
133
147
 
134
148
  `)}static buildRuntimeContext(e,t,n){let s=[`Current Time: ${new Date().toISOString()}`];return e&&t&&(s.push(`Channel: ${e}`),s.push(`Chat ID: ${t}`)),n?.chat_type&&s.push(`Chat Type: ${n.chat_type}`),n?.bot_mentioned&&s.push("Bot Mentioned: yes"),`${o.RUNTIME_CONTEXT_TAG}
135
149
  ${s.join(`
136
- `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId,e.metadata)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}};import{randomUUID as Va}from"node:crypto";import Ka from"node:path";import{randomUUID as ts}from"node:crypto";import ta from"cron-parser";function eo(o){return o??"builtin"}function es(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function Ze(){return es()}function Ln(o,e,t,n){let r=eo(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 Zi(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:eo(e.source),contribution:s})};switch(t.slot){case"beforeAgentTurn":n(o.beforeAgentTurn,t);return;case"afterAgentTurn":n(o.afterAgentTurn,t);return;case"beforeOutbound":n(o.beforeOutbound,t);return;case"afterOutbound":n(o.afterOutbound,t);return;case"beforeScheduledJob":n(o.beforeScheduledJob,t);return;case"afterScheduledJob":n(o.afterScheduledJob,t);return;case"shutdown":n(o.shutdown,t);return}}function ye(o){return{...o,source:"builtin"}}var Qr=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:eo(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=es();for(let i of this.extensions.values()){for(let a of i.tools??[])Ln("tool",e,i,a);for(let a of i.channels??[])Ln("channel",t,i,a);for(let a of i.jobs??[])Ln("job",n,i,a);for(let a of i.commands??[])Ln("command",r,i,a);for(let a of i.lifecycle??[])Zi(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 ea(o){return o instanceof Error?o.message:String(o)}var Zr=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${ea(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function He(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new Zr(e,n.extension,n.source,n.contribution.name,r)}}function to(o){let e=new Qr;for(let t of o)e.register(t);return e.compose()}function tn(){let o=new Error("Operation aborted");return o.name="AbortError",o}function te(o){return o instanceof Error&&o.name==="AbortError"}function Q(o){if(o?.aborted)throw tn()}function Se(){return Date.now()}var na="default";function Mt(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 ta.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function ns(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 nn=class{constructor(e={},t,n=Ze()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??na}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Ne({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,
150
+ `)}`}buildMessages(e){return[{role:"system",content:this.buildSystemPrompt(e.skillNames,e.memoryNamespace)},...e.history,{role:"user",content:o.buildRuntimeContext(e.channel,e.chatId,e.metadata)},{role:"user",content:e.currentMessage}]}addToolResult(e,t,n,r){return e.push({role:"tool",tool_call_id:t,name:n,content:r}),e}addAssistantMessage(e,t,n,r){let s={role:"assistant",content:t};return n?.length&&(s.tool_calls=n),r!=null&&(s.reasoning_content=r),e.push(s),e}buildNotificationContext(e){let t=e.status==="completed"?"\u2713":"\u2717";if(e.kind==="cron_completed"||e.kind==="subagent_completed"||e.kind==="subagent_failed"){let n=[`[${t}] ${e.kind==="cron_completed"?"Cron Job":"Subagent"}: ${e.label}`,`Task: ${e.originalTask}`,`Status: ${e.status}`];e.result&&n.push(`Result: ${e.result}`),e.error&&n.push(`Error: ${e.error}`);let r=e.kind==="cron_completed"?"cron job":"subagent";return n.push("",`The ${r} has finished. Acknowledge this result briefly and continue with any follow-up work if needed.`),n.join(`
151
+ `)}return`[${t}] Task: ${e.label}
152
+ Status: ${e.status}`}};import{randomUUID as jl}from"node:crypto";import $l from"node:path";import{randomUUID as As}from"node:crypto";import Ka from"cron-parser";function bo(o){return o??"builtin"}function Rs(){return{beforeAgentTurn:[],afterAgentTurn:[],beforeOutbound:[],afterOutbound:[],beforeScheduledJob:[],afterScheduledJob:[],shutdown:[]}}function rt(){return Rs()}function zn(o,e,t,n){let r=bo(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 Ga(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:bo(e.source),contribution:s})};switch(t.slot){case"beforeAgentTurn":n(o.beforeAgentTurn,t);return;case"afterAgentTurn":n(o.afterAgentTurn,t);return;case"beforeOutbound":n(o.beforeOutbound,t);return;case"afterOutbound":n(o.afterOutbound,t);return;case"beforeScheduledJob":n(o.beforeScheduledJob,t);return;case"afterScheduledJob":n(o.afterScheduledJob,t);return;case"shutdown":n(o.shutdown,t);return}}function we(o){return{...o,source:"builtin"}}var ho=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:bo(e.source)}),this}list(){return[...this.extensions.values()]}compose(){let e=new Map,t=new Map,n=new Map,r=new Map,s=Rs();for(let i of this.extensions.values()){for(let a of i.tools??[])zn("tool",e,i,a);for(let a of i.channels??[])zn("channel",t,i,a);for(let a of i.jobs??[])zn("job",n,i,a);for(let a of i.commands??[])zn("command",r,i,a);for(let a of i.lifecycle??[])Ga(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 Wa(o){return o instanceof Error?o.message:String(o)}var yo=class extends Error{constructor(t,n,r,s,i){super(`Lifecycle hook '${t}:${s}' from extension '${n}' failed: ${Wa(i)}`);this.slot=t;this.extension=n;this.source=r;this.hookName=s;this.name="LifecycleHookError",this.originalError=i}originalError};async function qe(o,e,t){for(let n of o)try{await n.contribution.run(t)}catch(r){throw new yo(e,n.extension,n.source,n.contribution.name,r)}}function wo(o){let e=new ho;for(let t of o)e.register(t);return e.compose()}function cn(){let o=new Error("Operation aborted");return o.name="AbortError",o}function se(o){return o instanceof Error&&o.name==="AbortError"}function te(o){if(o?.aborted)throw cn()}function Ce(){return Date.now()}var Ha="default";function Ft(o,e){if(o.kind==="at")return o.atMs>e?o.atMs:null;if(o.kind==="every")return o.everyMs>0?e+o.everyMs:null;if(o.kind==="cron")try{let t=o.tz?{currentDate:new Date(e),tz:o.tz}:{currentDate:new Date(e)};return Ka.parseExpression(o.expr,t).next().toDate().getTime()}catch{return null}return null}function Es(o){if("tz"in o&&o.tz&&o.kind!=="cron")throw new Error("tz can only be used with cron schedules");if(o.kind==="cron"&&o.tz)try{new Intl.DateTimeFormat("en-US",{timeZone:o.tz})}catch{throw new Error(`unknown timezone '${o.tz}'`)}}var dn=class{constructor(e={},t,n=rt()){this.onJob=t;this.lifecycle=n;this.dataDir=e.dataDir??void 0,this.workspaceKey=e.workspace??Ha}store=null;storage=null;timer=null;running=!1;activeControllers=new Set;workspaceKey;dataDir;getStorage(){return this.storage||(this.storage=Fe({dataDir:this.dataDir})),this.storage}rowToJob(e){let t=JSON.parse(e.state_json);return{id:e.job_id,name:e.name,enabled:!!e.enabled,schedule:JSON.parse(e.schedule_json),payload:JSON.parse(e.payload_json),state:{...t,nextRunAtMs:e.next_run_at_ms},createdAtMs:e.created_at_ms,updatedAtMs:e.updated_at_ms,deleteAfterRun:!!e.delete_after_run}}readStoreFromStorage(){return{version:1,jobs:this.getStorage().prepare(`SELECT job_id, name, enabled, schedule_json, payload_json, state_json,
137
153
  next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
138
154
  FROM cron_jobs
139
155
  WHERE workspace = ?
140
156
  ORDER BY created_at_ms, job_id`).all(this.workspaceKey).map(t=>this.rowToJob(t))}}loadStore(){return this.store?this.store:(this.store=this.readStoreFromStorage(),this.store)}saveStore(){if(!this.store)return;let e=this.getStorage();e.transaction(()=>{e.prepare("DELETE FROM cron_jobs WHERE workspace = ?").run(this.workspaceKey);let t=e.prepare(`INSERT INTO cron_jobs (
141
157
  workspace, job_id, name, enabled, schedule_json, payload_json,
142
158
  state_json, next_run_at_ms, delete_after_run, created_at_ms, updated_at_ms
143
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let n of this.store.jobs)t.run(this.workspaceKey,n.id,n.name,n.enabled?1:0,JSON.stringify(n.schedule),JSON.stringify(n.payload),JSON.stringify(n.state),n.state.nextRunAtMs,n.deleteAfterRun?1:0,n.createdAtMs,n.updatedAtMs)})}getNextWakeMs(){let t=this.loadStore().jobs.filter(n=>n.enabled&&n.state.nextRunAtMs).map(n=>n.state.nextRunAtMs);return t.length?Math.min(...t):null}armTimer(){this.timer&&clearTimeout(this.timer);let e=this.getNextWakeMs();!this.running||!e||(this.timer=setTimeout(()=>{this.onTimer()},Math.max(0,e-Se())))}async onTimer(){let e=this.loadStore(),t=Se(),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=Se(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await He(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 He(this.lifecycle.afterScheduledJob,"afterScheduledJob",{job:e,result:n,error:r})}catch(i){r=r==null?i:new Error(`${String(r)}; ${String(i)}`)}e.state.lastStatus=r==null?"ok":te(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=Se(),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=Mt(e.schedule,Se())}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:Mt(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=Se(),n={id:ts().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:Mt({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=Se();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();ns(e.schedule);let n=Se(),r={id:ts().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:Mt(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=Se(),r.state.nextRunAtMs=t?Mt(r.schedule,Se()):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&&(ns(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Mt(t.schedule,Se()):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=Se(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import rs from"node:fs";import ra from"node:path";var oa=[{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"]}}}],rn=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 ra.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!rs.existsSync(this.heartbeatFile))return null;let e=rs.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.
159
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let n of this.store.jobs)t.run(this.workspaceKey,n.id,n.name,n.enabled?1:0,JSON.stringify(n.schedule),JSON.stringify(n.payload),JSON.stringify(n.state),n.state.nextRunAtMs,n.deleteAfterRun?1:0,n.createdAtMs,n.updatedAtMs)})}getNextWakeMs(){let t=this.loadStore().jobs.filter(n=>n.enabled&&n.state.nextRunAtMs).map(n=>n.state.nextRunAtMs);return t.length?Math.min(...t):null}armTimer(){this.timer&&clearTimeout(this.timer);let e=this.getNextWakeMs();!this.running||!e||(this.timer=setTimeout(()=>{this.onTimer()},Math.max(0,e-Ce())))}async onTimer(){let e=this.loadStore(),t=Ce(),n=e.jobs.filter(r=>r.enabled&&r.state.nextRunAtMs&&t>=r.state.nextRunAtMs);for(let r of n)await this.executeJob(r);this.saveStore(),this.armTimer()}async executeJob(e){let t=Ce(),n=null,r=null,s=new AbortController;this.activeControllers.add(s);try{await qe(this.lifecycle.beforeScheduledJob,"beforeScheduledJob",{job:e}),this.onJob&&(n=await this.onJob(e,{signal:s.signal}))}catch(i){r=i}finally{this.activeControllers.delete(s)}try{await qe(this.lifecycle.afterScheduledJob,"afterScheduledJob",{job:e,result:n,error:r})}catch(i){r=r==null?i:new Error(`${String(r)}; ${String(i)}`)}e.state.lastStatus=r==null?"ok":se(r)?"skipped":"error",e.state.lastError=r==null?null:String(r),e.state.lastRunAtMs=t,e.updatedAtMs=Ce(),e.schedule.kind==="at"?e.deleteAfterRun?this.store.jobs=this.store.jobs.filter(i=>i.id!==e.id):(e.enabled=!1,e.state.nextRunAtMs=null):e.state.nextRunAtMs=Ft(e.schedule,Ce())}reconcileRecoveredJobs(e){let t=this.loadStore(),n=!1;for(let r of t.jobs){if(!r.enabled){r.state.nextRunAtMs!==null&&(r.state.nextRunAtMs=null,r.updatedAtMs=e,n=!0);continue}if(r.state.nextRunAtMs!==null)continue;let s=r.schedule.kind==="at"&&r.schedule.atMs<=e?e:Ft(r.schedule,e);s!==r.state.nextRunAtMs&&(r.state.nextRunAtMs=s,r.updatedAtMs=e,n=!0)}return n}seedDefaultJobs(){let e=this.loadStore();if(e.jobs.length>0)return;let t=Ce(),n={id:As().slice(0,8),name:"Example: Daily reminder",enabled:!0,schedule:{kind:"every",everyMs:1440*60*1e3},payload:{kind:"agent_turn",message:"This is an example cron job. Edit or delete it.",deliver:!1},state:{nextRunAtMs:Ft({kind:"every",everyMs:1440*60*1e3},t),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:t,updatedAtMs:t,deleteAfterRun:!1};e.jobs.push(n),this.saveStore()}async start(){this.running=!0,this.seedDefaultJobs();let e=Ce();this.reconcileRecoveredJobs(e)&&this.saveStore(),this.armTimer()}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null;for(let e of this.activeControllers)e.abort()}listJobs(e=!1){let t=this.loadStore();return[...e?t.jobs:t.jobs.filter(r=>r.enabled)].sort((r,s)=>(r.state.nextRunAtMs??Number.MAX_SAFE_INTEGER)-(s.state.nextRunAtMs??Number.MAX_SAFE_INTEGER))}addJob(e){let t=this.loadStore();Es(e.schedule);let n=Ce(),r={id:As().slice(0,8),name:e.name,enabled:!0,schedule:e.schedule,payload:{kind:"agent_turn",message:e.message,deliver:!!e.deliver,channel:e.channel,to:e.to},state:{nextRunAtMs:Ft(e.schedule,n),lastRunAtMs:null,lastStatus:null,lastError:null},createdAtMs:n,updatedAtMs:n,deleteAfterRun:!!e.deleteAfterRun};return t.jobs.push(r),this.saveStore(),this.armTimer(),r}removeJob(e){let t=this.loadStore(),n=t.jobs.length;t.jobs=t.jobs.filter(s=>s.id!==e);let r=t.jobs.length<n;return r&&(this.saveStore(),this.armTimer()),r}enableJob(e,t=!0){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(r.enabled=t,r.updatedAtMs=Ce(),r.state.nextRunAtMs=t?Ft(r.schedule,Ce()):null,this.saveStore(),this.armTimer(),r):null}async runJob(e,t=!1){let r=this.loadStore().jobs.find(s=>s.id===e);return!r||!t&&!r.enabled?!1:(await this.executeJob(r),this.saveStore(),this.armTimer(),!0)}updateJob(e,t){let r=this.loadStore().jobs.find(s=>s.id===e);return r?(t.name!==void 0&&(r.name=t.name),t.schedule!==void 0&&(Es(t.schedule),r.schedule=t.schedule,r.state.nextRunAtMs=r.enabled?Ft(t.schedule,Ce()):null),t.message!==void 0&&(r.payload.message=t.message),t.deliver!==void 0&&(r.payload.deliver=t.deliver),t.channel!==void 0&&(r.payload.channel=t.channel),t.to!==void 0&&(r.payload.to=t.to),t.deleteAfterRun!==void 0&&(r.deleteAfterRun=t.deleteAfterRun),r.updatedAtMs=Ce(),this.saveStore(),this.armTimer(),r):null}status(){let e=this.loadStore();return{enabled:this.running,jobs:e.jobs.length,nextWakeAtMs:this.getNextWakeMs()}}};import Ps from"node:fs";import Ja from"node:path";var qa=[{type:"function",function:{name:"heartbeat",description:"Report heartbeat decision after reviewing tasks.",parameters:{type:"object",properties:{action:{type:"string",enum:["skip","run"]},tasks:{type:"string"}},required:["action"]}}}],un=class{constructor(e,t,n,r,s,i=1800,a=!0){this.workspace=e;this.provider=t;this.model=n;this.onExecute=r;this.onNotify=s;this.intervalS=i;this.enabled=a}running=!1;timer=null;activeController=null;get heartbeatFile(){return Ja.join(this.workspace,"HEARTBEAT.md")}readHeartbeat(){if(!Ps.existsSync(this.heartbeatFile))return null;let e=Ps.readFileSync(this.heartbeatFile,"utf8");return e.trim()?e:null}async decide(e){let t=await this.provider.chat({model:this.model,messages:[{role:"system",content:"You are a heartbeat agent. Call the heartbeat tool to report your decision."},{role:"user",content:`Review the following HEARTBEAT.md and decide whether there are active tasks.
144
160
 
145
- ${e}`}],tools:oa});if(!t.toolCalls.length)return{action:"skip",tasks:""};let n=t.toolCalls[0];if(!n)return{action:"skip",tasks:""};let r=n.arguments,s=r.action==="run"?"run":"skip",i=typeof r.tasks=="string"?r.tasks:"";return{action:s,tasks:i}}async start(){!this.enabled||this.running||(this.running=!0,this.schedule())}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null,this.activeController?.abort(),this.activeController=null}schedule(){this.running&&(this.timer=setTimeout(()=>{this.tick().catch(e=>{te(e)||console.warn(String(e))}).finally(()=>this.schedule())},this.intervalS*1e3))}async executeTasks(e){if(!this.onExecute)throw new Error("Heartbeat execution callback is not configured");let t=new AbortController;this.activeController=t;try{return await this.onExecute(e,{signal:t.signal})}finally{this.activeController===t&&(this.activeController=null)}}async tick(){let e=this.readHeartbeat();if(!e)return;let{action:t,tasks:n}=await this.decide(e);if(t!=="run"||!this.onExecute)return;let r=await this.executeTasks(n);r&&this.onNotify&&await this.onNotify(r)}async triggerNow(){let e=this.readHeartbeat();if(!e)return null;let{action:t,tasks:n}=await this.decide(e);return t!=="run"||!this.onExecute?null:this.executeTasks(n)}};var 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 On=class extends G{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let d={kind:"cron",expr:s};i&&(d.tz=i),l=d}else if(a){let d=new Date(a);if(Number.isNaN(d.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:d.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let d=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${d.name}' (id: ${d.id})`}catch(d){return`Error: ${String(d).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
161
+ ${e}`}],tools:qa});if(!t.toolCalls.length)return{action:"skip",tasks:""};let n=t.toolCalls[0];if(!n)return{action:"skip",tasks:""};let r=n.arguments,s=r.action==="run"?"run":"skip",i=typeof r.tasks=="string"?r.tasks:"";return{action:s,tasks:i}}async start(){!this.enabled||this.running||(this.running=!0,this.schedule())}stop(){this.running=!1,this.timer&&clearTimeout(this.timer),this.timer=null,this.activeController?.abort(),this.activeController=null}schedule(){this.running&&(this.timer=setTimeout(()=>{this.tick().catch(e=>{se(e)||console.warn(String(e))}).finally(()=>this.schedule())},this.intervalS*1e3))}async executeTasks(e){if(!this.onExecute)throw new Error("Heartbeat execution callback is not configured");let t=new AbortController;this.activeController=t;try{return await this.onExecute(e,{signal:t.signal})}finally{this.activeController===t&&(this.activeController=null)}}async tick(){let e=this.readHeartbeat();if(!e)return;let{action:t,tasks:n}=await this.decide(e);if(t!=="run"||!this.onExecute)return;let r=await this.executeTasks(n);r&&this.onNotify&&await this.onNotify(r)}async triggerNow(){let e=this.readHeartbeat();if(!e)return null;let{action:t,tasks:n}=await this.decide(e);return t!=="run"||!this.onExecute?null:this.executeTasks(n)}};var q=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 Vn=class extends q{constructor(t){super();this.cron=t}name="cron";description="Schedule reminders and recurring tasks. Actions: add, list, remove.";parameters={type:"object",properties:{action:{type:"string",enum:["add","list","remove"]},message:{type:"string"},every_seconds:{type:"integer"},cron_expr:{type:"string"},tz:{type:"string"},at:{type:"string"},job_id:{type:"string"}},required:["action"]};channel="";chatId="";setContext(t,n){this.channel=t,this.chatId=n}async execute(t,n){let r=String(t.action??"");return r==="add"?this.addJob(t):r==="list"?this.listJobs():r==="remove"?this.removeJob(String(t.job_id??"")):`Unknown action: ${r}`}addJob(t){let n=String(t.message??"");if(!n)return"Error: message is required for add";if(!this.channel||!this.chatId)return"Error: no session context (channel/chat_id)";let r=t.every_seconds!=null?Number(t.every_seconds):null,s=t.cron_expr!=null?String(t.cron_expr):null,i=t.tz!=null?String(t.tz):null,a=t.at!=null?String(t.at):null,l,c=!1;if(r)l={kind:"every",everyMs:r*1e3};else if(s){let d={kind:"cron",expr:s};i&&(d.tz=i),l=d}else if(a){let d=new Date(a);if(Number.isNaN(d.getTime()))return"Error: invalid ISO datetime in at";l={kind:"at",atMs:d.getTime()},c=!0}else return"Error: either every_seconds, cron_expr, or at is required";try{let d=this.cron.addJob({name:n.slice(0,30),schedule:l,message:n,deliver:!0,channel:this.channel,to:this.chatId,deleteAfterRun:c});return`Created job '${d.name}' (id: ${d.id})`}catch(d){return`Error: ${String(d).replace(/^Error:\s*/,"")}`}}listJobs(){let t=this.cron.listJobs();return t.length?`Scheduled jobs:
146
162
  ${t.map(n=>`- ${n.name} (id: ${n.id}, ${n.schedule.kind})`).join(`
147
- `)}`:"No scheduled jobs."}removeJob(t){return t?this.cron.removeJob(t)?`Removed job ${t}`:`Job ${t} not found`:"Error: job_id is required for remove"}};import ke from"node:fs";import $t from"node:path";import Me from"node:fs";import ue from"node:path";function os(o){let e=ue.resolve(o);for(;e!=="/"&&e!==".";)try{return Me.lstatSync(e),e}catch{let t=ue.dirname(e);if(t===e)break;e=t}return e||"/"}function ss(o,e){let t=ue.resolve(o),n=ue.resolve(e),r=n.endsWith(ue.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+ue.sep);if(!Me.existsSync(r))return s;try{let i=r;try{i=Me.realpathSync.native(r)}catch{}if(Me.existsSync(t)){let c=Me.realpathSync.native(t);return c===i||c.startsWith(i+ue.sep)}let a=os(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=Me.realpathSync.native(a);if(c===i||c.startsWith(i+ue.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=ue.dirname(l);if(c===l)break;try{if(Me.lstatSync(c).isSymbolicLink()){let p=Me.realpathSync.native(c);if(p!==i&&!p.startsWith(i+ue.sep))return!1}}catch{}l=c}return s}catch{return!1}}function is(o,e){let t=ue.resolve(o),n=ue.resolve(e);if(!ss(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=ue.dirname(t),s=os(r),i=n;try{Me.existsSync(n)&&(i=Me.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=Me.realpathSync.native(s);if(a!==i&&!a.startsWith(i+ue.sep))throw new Error(`Path '${o}' would be created outside workspace via symlinked parent directory`)}catch(a){throw a instanceof Error&&a.message.includes("symlinked parent")?a:new Error(`Could not validate path '${o}' is within workspace`)}}function Be(o,e){if(!ss(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function Bn(o,e,t,n=!1){let r=o.startsWith("~")?$t.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=$t.isAbsolute(r)?r:e?$t.join(e,r):r,i=$t.resolve(s);if(t)try{n?is(i,t):Be(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var Dn=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=Bn(String(t.path),this.workspace,this.allowedDir);return ke.existsSync(r)?ke.statSync(r).isFile()?ke.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 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=Bn(String(t.path),this.workspace,this.allowedDir,!0);ke.mkdirSync($t.dirname(r),{recursive:!0});let s=String(t.content??"");return ke.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},jn=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=Bn(String(t.path),this.workspace,this.allowedDir,!0);if(!ke.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=ke.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.`:(ke.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)}`}}},Fn=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=Bn(String(t.path),this.workspace,this.allowedDir);if(!ke.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!ke.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=ke.readdirSync(r).sort().map(i=>{let a=$t.join(r,i);return`${ke.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 Gn=class extends G{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,d=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${d}`:d}catch(c){return`Error sending message: ${String(c)}`}}};import no from"node:path";bt();var Un=class extends G{constructor(t=60,n,r=!1,s="",i=new be,a,l=!1){super();this.timeout=t;this.workingDir=n;this.restrictToWorkspace=r;this.pathAppend=s;this.runner=i;this.rtkService=a;this.rtkUltraCompact=l}name="exec";description="Execute a shell command and return its output. Use with caution.";parameters={type:"object",properties:{command:{type:"string",description:"The shell command to execute"},working_dir:{type:"string",description:"Optional working directory for the command"}},required:["command"]};guard(t,n){let r=t.toLowerCase();if([/\brm\s+-[rf]{1,2}\b/,/\bdel\s+\/[fq]\b/,/\brmdir\s+\/s\b/,/(?:^|[;&|]\s*)format\b/,/\b(mkfs|diskpart)\b/,/\bdd\s+if=/,/>\s*\/dev\/sd/,/\b(shutdown|reboot|poweroff)\b/,/:\(\)\s*\{.*\};\s*:/].some(i=>i.test(r)))return"Error: Command blocked by safety guard (dangerous pattern detected)";if(this.restrictToWorkspace){if(t.includes("../")||t.includes("..\\"))return"Error: Command blocked by safety guard (path traversal detected)";let i=t.match(/[A-Za-z]:\\[^\s"']+/g)??[];for(let a of i){let l=no.resolve(a),c=no.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;Q(n?.signal);let a=yt("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${no.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let d=await this.runner.run(c);if(d.status==="aborted")throw tn();if(d.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=d.stdout?`${d.stdout}${d.status==="failed"?`
149
- `:""}`:"";if(this.rtkService?.getRuntime().available&&p)try{let b=await this.rtkService.compress({command:r,stdout:p,stderr:d.stderr,exitCode:d.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(p=b.stdout)}catch{}let h=d.stderr.trim()?`STDERR:
163
+ `)}`:"No scheduled jobs."}removeJob(t){return t?this.cron.removeJob(t)?`Removed job ${t}`:`Job ${t} not found`:"Error: job_id is required for remove"}};import xe from"node:fs";import Bt from"node:path";import Oe from"node:fs";import pe from"node:path";function _s(o){let e=pe.resolve(o);for(;e!=="/"&&e!==".";)try{return Oe.lstatSync(e),e}catch{let t=pe.dirname(e);if(t===e)break;e=t}return e||"/"}function Ms(o,e){let t=pe.resolve(o),n=pe.resolve(e),r=n.endsWith(pe.sep)?n.slice(0,-1):n,s=t===r||t.startsWith(r+pe.sep);if(!Oe.existsSync(r))return s;try{let i=r;try{i=Oe.realpathSync.native(r)}catch{}if(Oe.existsSync(t)){let c=Oe.realpathSync.native(t);return c===i||c.startsWith(i+pe.sep)}let a=_s(t);if(a===i||a===r)return!0;if(a!=="/")try{let c=Oe.realpathSync.native(a);if(c===i||c.startsWith(i+pe.sep))return!0;if(!s)return!1}catch{return s}let l=t;for(;l!=="/"&&l!==".";){let c=pe.dirname(l);if(c===l)break;try{if(Oe.lstatSync(c).isSymbolicLink()){let p=Oe.realpathSync.native(c);if(p!==i&&!p.startsWith(i+pe.sep))return!1}}catch{}l=c}return s}catch{return!1}}function Is(o,e){let t=pe.resolve(o),n=pe.resolve(e);if(!Ms(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`);let r=pe.dirname(t),s=_s(r),i=n;try{Oe.existsSync(n)&&(i=Oe.realpathSync.native(n))}catch{}if(s!=="/"&&s!==i)try{let a=Oe.realpathSync.native(s);if(a!==i&&!a.startsWith(i+pe.sep))throw new Error(`Path '${o}' would be created outside workspace via symlinked parent directory`)}catch(a){throw a instanceof Error&&a.message.includes("symlinked parent")?a:new Error(`Could not validate path '${o}' is within workspace`)}}function Ge(o,e){if(!Ms(o,e))throw new Error(`Path '${o}' is outside allowed workspace '${e}'`)}function er(o,e,t,n=!1){let r=o.startsWith("~")?Bt.join(process.env.USERPROFILE||process.env.HOME||"",o.slice(1)):o,s=Bt.isAbsolute(r)?r:e?Bt.join(e,r):r,i=Bt.resolve(s);if(t)try{n?Is(i,t):Ge(i,t)}catch(a){throw new Error(a instanceof Error?a.message:`Path ${o} validation failed`)}return i}var Xn=class extends q{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=er(String(t.path),this.workspace,this.allowedDir);return xe.existsSync(r)?xe.statSync(r).isFile()?xe.readFileSync(r,"utf8"):`Error: Not a file: ${String(t.path)}`:`Error: File not found: ${String(t.path)}`}catch(r){return`Error reading file: ${String(r)}`}}},Yn=class extends q{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=er(String(t.path),this.workspace,this.allowedDir,!0);xe.mkdirSync(Bt.dirname(r),{recursive:!0});let s=String(t.content??"");return xe.writeFileSync(r,s,"utf8"),`Successfully wrote ${s.length} bytes to ${r}`}catch(r){return`Error writing file: ${String(r)}`}}},Qn=class extends q{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=er(String(t.path),this.workspace,this.allowedDir,!0);if(!xe.existsSync(r))return`Error: File not found: ${String(t.path)}`;let s=xe.readFileSync(r,"utf8"),i=String(t.old_text??""),a=String(t.new_text??"");return s.includes(i)?s.split(i).length-1>1?`Warning: old_text appears ${s.split(i).length-1} times. Please provide more context to make it unique.`:(xe.writeFileSync(r,s.replace(i,a),"utf8"),`Successfully edited ${r}`):`Error: old_text not found in ${String(t.path)}. Verify the file content.`}catch(r){return`Error editing file: ${String(r)}`}}},Zn=class extends q{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=er(String(t.path),this.workspace,this.allowedDir);if(!xe.existsSync(r))return`Error: Directory not found: ${String(t.path)}`;if(!xe.statSync(r).isDirectory())return`Error: Not a directory: ${String(t.path)}`;let s=xe.readdirSync(r).sort().map(i=>{let a=Bt.join(r,i);return`${xe.statSync(a).isDirectory()?"[DIR]":"[FILE]"} ${i}`});return s.length?s.join(`
164
+ `):`Directory ${String(t.path)} is empty`}catch(r){return`Error listing directory: ${String(r)}`}}};var tr=class extends q{constructor(t){super();this.sendCallback=t}name="message";description="Send a message to the user. Use this when you want to communicate something.";parameters={type:"object",properties:{content:{type:"string",description:"The message content to send"},channel:{type:"string",description:"Optional target channel"},chat_id:{type:"string",description:"Optional target chat/user ID"},media:{type:"array",items:{type:"string"},description:"Optional file attachments"}},required:["content"]};defaultChannel="";defaultChatId="";defaultMessageId=null;setContext(t,n,r){this.defaultChannel=t,this.defaultChatId=n,this.defaultMessageId=r??null}setSendCallback(t){this.sendCallback=t}async execute(t,n){let r=String(t.content??""),s=String(t.channel??this.defaultChannel),i=String(t.chat_id??this.defaultChatId),a=String(t.message_id??this.defaultMessageId??""),l=Array.isArray(t.media)?t.media:[];if(!s||!i)return"Error: No target channel/chat specified";if(!this.sendCallback)return"Error: Message sending not configured";try{await this.sendCallback({channel:s,chatId:i,content:r,media:l,metadata:{message_id:a}});let c=s===this.defaultChannel&&i===this.defaultChatId,d=`Message sent to ${s}:${i}${l.length?` with ${l.length} attachments`:""}`;return c?`__TERMINAL__${d}`:d}catch(c){return`Error sending message: ${String(c)}`}}};import vo from"node:path";kt();var nr=class extends q{constructor(t=60,n,r=!1,s="",i=new ve,a,l=!1){super();this.timeout=t;this.workingDir=n;this.restrictToWorkspace=r;this.pathAppend=s;this.runner=i;this.rtkService=a;this.rtkUltraCompact=l}name="exec";description="Execute a shell command and return its output. Use with caution.";parameters={type:"object",properties:{command:{type:"string",description:"The shell command to execute"},working_dir:{type:"string",description:"Optional working directory for the command"}},required:["command"]};guard(t,n){let r=t.toLowerCase();if([/\brm\s+-[rf]{1,2}\b/,/\bdel\s+\/[fq]\b/,/\brmdir\s+\/s\b/,/(?:^|[;&|]\s*)format\b/,/\b(mkfs|diskpart)\b/,/\bdd\s+if=/,/>\s*\/dev\/sd/,/\b(shutdown|reboot|poweroff)\b/,/:\(\)\s*\{.*\};\s*:/].some(i=>i.test(r)))return"Error: Command blocked by safety guard (dangerous pattern detected)";if(this.restrictToWorkspace){if(t.includes("../")||t.includes("..\\"))return"Error: Command blocked by safety guard (path traversal detected)";let i=t.match(/[A-Za-z]:\\[^\s"']+/g)??[];for(let a of i){let l=vo.resolve(a),c=vo.resolve(n);if(!l.startsWith(c))return"Error: Command blocked by safety guard (path outside working dir)"}}return null}async execute(t,n){let r=String(t.command??""),s=String(t.working_dir??this.workingDir??process.cwd()),i=this.guard(r,s);if(i)return i;te(n?.signal);let a=St("tool.exec"),l={...process.env};if(this.pathAppend&&(l.PATH=`${l.PATH??""}${vo.delimiter}${this.pathAppend}`),a.mode!=="local-process")return"Error: exec tool requires local-process isolation";let c={command:{kind:"shell",command:r},cwd:s,env:l,timeoutMs:this.timeout*1e3,maxCaptureBytes:1024*1024};n?.signal&&(c.signal=n.signal);let d=await this.runner.run(c);if(d.status==="aborted")throw cn();if(d.failureAttribution==="timeout")return`Error: Command timed out after ${this.timeout} seconds`;let p=d.stdout?`${d.stdout}${d.status==="failed"?`
165
+ `:""}`:"";if(this.rtkService?.getRuntime().available&&p)try{let b=await this.rtkService.compress({command:r,stdout:p,stderr:d.stderr,exitCode:d.exitCode,ultraCompact:this.rtkUltraCompact});b.compressed&&(p=b.stdout)}catch{}let g=d.stderr.trim()?`STDERR:
150
166
  ${d.stderr}
151
- `:"",v=d.status==="failed"&&typeof d.exitCode=="number"?`
152
- Exit code: ${d.exitCode}`:"",w=d.status==="failed"&&d.signal?`
153
- Signal: ${d.signal}`:"",u=`${p}${h}${v}${w}`.trim();return u?u.length>1e4?`${u.slice(0,1e4)}
154
- ... (truncated, ${u.length-1e4} more chars)`:u:d.status==="failed"?d.errorMessage?`Error executing command: ${d.errorMessage}`:"Error executing command":"(no output)"}};var Wn=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 Kn=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 Hn=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+=ht.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 Jn=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 ia,existsSync as aa}from"node:fs";import{join as Z}from"node:path";import la from"node:http";import{homedir as ca}from"node:os";import da from"node:net";import ds from"ws";var ua={existsSync:aa,readFileSync:ia},cs=ua;var ga=la,us=ga;var ma=1;var pa="/tmp/chrome-debug-profile";function fa(o){let e=o??process.platform,t=ca(),n=Z(pa,"DevToolsActivePort");switch(e){case"darwin":return[n,Z(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),Z(t,"Library/Application Support/Chromium/DevToolsActivePort"),Z(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),Z(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),Z(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||Z(t,".config");return[n,Z(r,"google-chrome","DevToolsActivePort"),Z(r,"chromium","DevToolsActivePort"),Z(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),Z(r,"microsoft-edge","DevToolsActivePort"),Z(r,"vivaldi","DevToolsActivePort"),Z(t,".config","google-chrome","DevToolsActivePort"),Z(t,".config","chromium","DevToolsActivePort"),Z(t,"snap","chromium","common","chromium","DevToolsActivePort"),Z(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),Z(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||Z(t,"AppData","Local");return[n,Z(r,"Google","Chrome","User Data","DevToolsActivePort"),Z(r,"Chromium","User Data","DevToolsActivePort"),Z(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),Z(r,"Microsoft","Edge","User Data","DevToolsActivePort"),Z(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function zn(o){return Vn(o)?.port}function Vn(o){let e=fa(o);for(let t of e)try{if(!cs.existsSync(t))continue;let r=cs.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 ha(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=us.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 ya(o,e="127.0.0.1"){return new Promise(t=>{let n=new da.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 ba(o){return new Promise(e=>{try{let t=new ds(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 Lt(o=9222){let e=Vn(),t=e?.port??o;if(await ya(t)){for(let r=0;r<2;r++){try{let s=await ha(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 ba(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=us.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 on(o){let t=Vn()?.browserWsPath;if(!t)return[];let n=await qn.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 gs(o,e){let n=Vn()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await qn.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 qn=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 ds(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!==ma)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 wa}from"node:child_process";import{createConnection as va}from"node:net";import{tmpdir as Sa}from"node:os";import{join as ps,dirname as ka}from"node:path";import{unlink as Ca,unlinkSync as xa,mkdirSync as Ta,existsSync as Yn}from"node:fs";import wt from"node:fs";function Ot(o){let e="electron"in process.versions,t=o;try{t=wt.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!wt.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!wt.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(wt.existsSync(a)){try{n=wt.realpathSync(a)}catch{n=a}r=!1}else if(wt.existsSync(l)){try{n=wt.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 Ra=null,Ea=null,Aa=null,Pa=!1;function sn(){return Ea??process.platform}function Ia(){return Ra??wa}function _a(){return Aa??va}function Ma(o,e){let t=sn(),n=e??Sa(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:ps(n,`airclaw-daemon-${r}.sock`)}function ms(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 Dt=class o{static instance=null;daemons=new Map;constructor(){}static getInstance(){return o.instance||(o.instance=new o),o.instance}async getOrCreateDaemon(e,t,n){if(this.daemons.has(e))return;let r=Ma(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(sn()==="win32"||Yn(r)){let v={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,v);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),sn()!=="win32"&&Yn(r))try{xa(r)}catch{}}}let i=ka(r);if(!Yn(i)&&sn()!=="win32")try{Ta(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),Pa)return;let l=ps(import.meta.dirname,"daemon-worker"),{file:c,args:d,env:p}=Ot(l),h=Ia()(c,[...d,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=h,h.on("exit",()=>{this.cleanupDaemon(e)}),h.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((v,w)=>{let u=setTimeout(()=>{w(new Error("Daemon startup timeout"))},1e4),b=E=>{E.toString("utf8").includes("READY")&&(clearTimeout(u),h.stdout?.off("data",b),v())};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=_a()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=ms(t.ndjsonBuffer+i.toString("utf8"),a=>{let l=t.pendingCommands.get(a.id);l&&(t.pendingCommands.delete(a.id),l.resolve(a))})}),s.on("close",()=>{t.clientSocket=null;for(let[,i]of t.pendingCommands)i.reject(new Error("Daemon socket closed"));t.pendingCommands.clear()}),s.on("error",()=>{}),n()}),s.on("error",i=>{r(new Error(`Failed to connect to daemon: ${i.message}`))}),setTimeout(()=>{t.clientSocket||(s.destroy(),r(new Error("Daemon connection timeout")))},5e3)})}async sendCommand(e,t,n={}){let r=this.daemons.get(e);if(!r)throw new Error(`No daemon for target ${e}`);if(!r.clientSocket)throw new Error(`Daemon socket not connected for ${e}`);let s=r.commandId++,a=JSON.stringify({id:s,cmd:t,args:n})+`
157
- `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(d){r.pendingCommands.delete(s),c(d)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=ms(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"));sn()!=="win32"&&Yn(t.socketPath)&&Ca(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as $a,mkdirSync as La,existsSync as Oa}from"node:fs";import{dirname as Da,join as Xn}from"node:path";import{tmpdir as Na}from"node:os";var vt=class extends G{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
167
+ `:"",x=d.status==="failed"&&typeof d.exitCode=="number"?`
168
+ Exit code: ${d.exitCode}`:"",y=d.status==="failed"&&d.signal?`
169
+ Signal: ${d.signal}`:"",u=`${p}${g}${x}${y}`.trim();return u?u.length>1e4?`${u.slice(0,1e4)}
170
+ ... (truncated, ${u.length-1e4} more chars)`:u:d.status==="failed"?d.errorMessage?`Error executing command: ${d.errorMessage}`:"Error executing command":"(no output)"}};var Ls={general:{name:"general",description:"General-purpose subagent with full tool access",systemPromptSuffix:"Complete the assigned task using all available tools."},researcher:{name:"researcher",description:"Read-only researcher \u2014 no file modifications",systemPromptSuffix:"Research and report findings. Do NOT modify any files.",allowedTools:["read_file","list_files","search","web_search","web_fetch","session.info","session.search"]},coder:{name:"coder",description:"Code modification specialist",systemPromptSuffix:"Implement the requested code changes.",deniedTools:["web_search","web_fetch"]}};function So(o){return Ls[o]}function Ns(){return Object.values(Ls)}var rr=class extends q{constructor(t){super();this.manager=t}name="spawn";description="Spawn a subagent to handle a task in the background.";parameters={type:"object",properties:{task:{type:"string",description:"The task for the subagent to complete"},label:{type:"string",description:"Optional short label"},model:{type:"string",description:"Optional model override (e.g. 'anthropic/claude-sonnet-4'). Falls back to subagent config or global default if omitted."},provider:{type:"string",description:"Optional provider override (e.g. 'openai'). Falls back to subagent config or global default if omitted."},context:{type:"string",enum:["fresh","fork"],description:"Context mode: 'fresh' (default) starts with minimal context, 'fork' inherits parent conversation for prompt cache reuse."},type:{type:"string",description:`Agent type defining available tools and behavior. Available types: ${Ns().map(t=>`'${t.name}'`).join(", ")}. Defaults to 'general'.`}},required:["task"]};originChannel="cli";originChatId="direct";sessionKey="cli:direct";parentSystemPrompt;setContext(t,n,r=`${t}:${n}`,s){this.originChannel=t,this.originChatId=n,this.sessionKey=r,this.parentSystemPrompt=s}async execute(t,n){let r=t.context??"fresh",s=t.type??"general",i={task:String(t.task??""),label:t.label!=null?String(t.label):null,originChannel:this.originChannel,originChatId:this.originChatId,sessionKey:this.sessionKey,contextMode:r,agentType:s};return t.model!=null&&(i.model=String(t.model)),t.provider!=null&&(i.providerName=String(t.provider)),r==="fork"&&this.parentSystemPrompt&&(i.parentSystemPrompt=this.parentSystemPrompt),this.manager.spawn(i)}};var or=class extends q{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 sr=class extends q{name="session.info";description="Returns information about the current session: message count, token estimate, last anchor name, and messages since last anchor.";parameters={type:"object",properties:{},required:[]};sessionManager=null;sessionKey="cli:direct";setSessionManager(e){this.sessionManager=e}setContext(e){this.sessionKey=e}async execute(e){if(!this.sessionManager)return"Error: Session manager not available";let t=this.sessionManager.getOrCreate(this.sessionKey),n=t.getHistory(1e3),r=0;for(let l of n)r+=vt.estimateMessageTokens(l);let s=t.getLastAnchor(),i=t.getMessagesSinceLastAnchor().length,a={messageCount:t.messages.length,tokenEstimate:r,lastAnchor:s?.name??null,messagesSinceAnchor:i};return JSON.stringify(a,null,2)}};var ir=class extends q{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 Va,existsSync as Xa}from"node:fs";import{join as ne}from"node:path";import Ya from"node:http";import{homedir as Qa}from"node:os";import Za from"node:net";import js from"ws";var el={existsSync:Xa,readFileSync:Va},Ds=el;var tl=Ya,Fs=tl;var nl=1;var rl="/tmp/chrome-debug-profile";function ol(o){let e=o??process.platform,t=Qa(),n=ne(rl,"DevToolsActivePort");switch(e){case"darwin":return[n,ne(t,"Library/Application Support/Google/Chrome/DevToolsActivePort"),ne(t,"Library/Application Support/Chromium/DevToolsActivePort"),ne(t,"Library/Application Support/BraveSoftware/Brave-Browser/DevToolsActivePort"),ne(t,"Library/Application Support/Microsoft Edge/DevToolsActivePort"),ne(t,"Library/Application Support/Vivaldi/DevToolsActivePort")];case"linux":{let r=process.env.XDG_CONFIG_HOME||ne(t,".config");return[n,ne(r,"google-chrome","DevToolsActivePort"),ne(r,"chromium","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","DevToolsActivePort"),ne(r,"microsoft-edge","DevToolsActivePort"),ne(r,"vivaldi","DevToolsActivePort"),ne(t,".config","google-chrome","DevToolsActivePort"),ne(t,".config","chromium","DevToolsActivePort"),ne(t,"snap","chromium","common","chromium","DevToolsActivePort"),ne(t,".var","app","com.google.Chrome","config","google-chrome","DevToolsActivePort"),ne(t,".var","app","org.chromium.Chromium","config","chromium","DevToolsActivePort")]}case"win32":{let r=process.env.LOCALAPPDATA||ne(t,"AppData","Local");return[n,ne(r,"Google","Chrome","User Data","DevToolsActivePort"),ne(r,"Chromium","User Data","DevToolsActivePort"),ne(r,"BraveSoftware","Brave-Browser","User Data","DevToolsActivePort"),ne(r,"Microsoft","Edge","User Data","DevToolsActivePort"),ne(r,"Vivaldi","User Data","DevToolsActivePort")]}default:return[]}}function lr(o){return cr(o)?.port}function cr(o){let e=ol(o);for(let t of e)try{if(!Ds.existsSync(t))continue;let r=Ds.readFileSync(t,"utf-8").split(`
171
+ `),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 sl(o=9222){return new Promise(e=>{let t=`http://127.0.0.1:${o}/json/version`,n=Fs.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 il(o,e="127.0.0.1"){return new Promise(t=>{let n=new Za.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 al(o){return new Promise(e=>{try{let t=new js(o),n=setTimeout(()=>{t.close(),e(!1)},3e3);t.on("open",()=>{clearTimeout(n),t.close(),e(!0)}),t.on("error",()=>{clearTimeout(n),e(!1)})}catch{e(!1)}})}async function Ut(o=9222){let e=cr(),t=e?.port??o;if(await il(t)){for(let r=0;r<2;r++){try{let s=await sl(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 al(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=Fs.get(`http://127.0.0.1:${t}/json/version`,{timeout:3e3},i=>{i.resume(),i.statusCode===404||i.statusCode===403?r({port:t,versionInfo:{},pendingApproval:!0}):r(void 0)});s.on("error",()=>r(void 0)),s.on("timeout",()=>{s.destroy(),r(void 0)})})}}async function gn(o){let t=cr()?.browserWsPath;if(!t)return[];let n=await ar.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 Bs(o,e){let n=cr()?.browserWsPath;if(!n)throw new Error("No browser WebSocket path found in DevToolsActivePort");let r=await ar.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 ar=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 js(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!==nl)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 ll}from"node:child_process";import{createConnection as cl}from"node:net";import{tmpdir as dl}from"node:os";import{join as Gs,dirname as ul}from"node:path";import{unlink as gl,unlinkSync as ml,mkdirSync as pl,existsSync as dr}from"node:fs";import Ct from"node:fs";function Gt(o){let e="electron"in process.versions,t=o;try{t=Ct.realpathSync(o)}catch{}let n,r;if(t.endsWith(".js")){if(!Ct.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!1}else if(t.endsWith(".ts")){if(!Ct.existsSync(t))throw new Error(`No executable found: ${t} does not exist.`);n=t,r=!0}else{let a=t+".js",l=t+".ts";if(Ct.existsSync(a)){try{n=Ct.realpathSync(a)}catch{n=a}r=!1}else if(Ct.existsSync(l)){try{n=Ct.realpathSync(l)}catch{n=l}r=!0}else throw new Error(`No executable found: neither ${a} nor ${l} exists.`)}let s=process.execPath,i=r?["--import","tsx",n]:[n];return e?{file:s,args:i,env:{...process.env,ELECTRON_RUN_AS_NODE:"1"}}:{file:s,args:i,env:process.env}}var fl=null,hl=null,yl=null,bl=!1;function mn(){return hl??process.platform}function wl(){return fl??ll}function vl(){return yl??cl}function Sl(o,e){let t=mn(),n=e??dl(),r=o.replace(/[^a-zA-Z0-9]/g,"_").slice(0,32);return t==="win32"?`\\\\.\\pipe\\airclaw-daemon-${r}`:Gs(n,`airclaw-daemon-${r}.sock`)}function Us(o,e){let t=o.split(`
172
+ `),n=t.pop()??"";for(let r of t){let s=r.trim();if(s)try{let i=JSON.parse(s);e(i)}catch{}}return n}var Wt=class o{static instance=null;daemons=new Map;constructor(){}static getInstance(){return o.instance||(o.instance=new o),o.instance}async getOrCreateDaemon(e,t,n){if(this.daemons.has(e))return;let r=Sl(e,n?.socketDir),s=n?.idleTimeoutMs??12e5;if(mn()==="win32"||dr(r)){let x={targetId:e,child:null,socketPath:r,clientSocket:null,commandId:1,pendingCommands:new Map,ndjsonBuffer:""};this.daemons.set(e,x);try{await this.connectToDaemon(e);return}catch{if(this.daemons.delete(e),mn()!=="win32"&&dr(r))try{ml(r)}catch{}}}let i=ul(r);if(!dr(i)&&mn()!=="win32")try{pl(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),bl)return;let l=Gs(import.meta.dirname,"daemon-worker"),{file:c,args:d,env:p}=Gt(l),g=wl()(c,[...d,"--target",e,"--ws-url",t,"--socket",r,"--idle-timeout",String(s)],{stdio:["ignore","pipe","pipe"],detached:!1,env:p});a.child=g,g.on("exit",()=>{this.cleanupDaemon(e)}),g.on("error",()=>{this.cleanupDaemon(e)}),await new Promise((x,y)=>{let u=setTimeout(()=>{y(new Error("Daemon startup timeout"))},1e4),b=R=>{R.toString("utf8").includes("READY")&&(clearTimeout(u),g.stdout?.off("data",b),x())};g.stdout?.on("data",b)}),await this.connectToDaemon(e)}async connectToDaemon(e){let t=this.daemons.get(e);if(!t)throw new Error(`No daemon for target ${e}`);return new Promise((n,r)=>{let s=vl()(t.socketPath);s.on("connect",()=>{t.clientSocket=s,s.on("data",i=>{t.ndjsonBuffer=Us(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})+`
173
+ `;return new Promise((l,c)=>{r.pendingCommands.set(s,{resolve:l,reject:c});try{r.clientSocket.write(a)}catch(d){r.pendingCommands.delete(s),c(d)}setTimeout(()=>{r.pendingCommands.has(s)&&(r.pendingCommands.delete(s),c(new Error(`Command ${s} timed out`)))},3e4)})}hasDaemon(e){return this.daemons.has(e)}getSocketPath(e){return this.daemons.get(e)?.socketPath}stopDaemon(e){let t=this.daemons.get(e);t&&(t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM"),this.cleanupDaemon(e))}stopAll(){for(let e of this.daemons.keys())this.stopDaemon(e)}getActiveTargets(){return Array.from(this.daemons.keys())}__setClientSocket(e,t){let n=this.daemons.get(e);n&&(n.clientSocket=t,t&&(t.on("data",r=>{n.ndjsonBuffer=Us(n.ndjsonBuffer+r.toString("utf8"),s=>{let i=n.pendingCommands.get(s.id);i&&(n.pendingCommands.delete(s.id),i.resolve(s))})}),t.on("close",()=>{n.clientSocket=null;for(let[,r]of n.pendingCommands)r.reject(new Error("Daemon socket closed"));n.pendingCommands.clear()})))}cleanupDaemon(e){let t=this.daemons.get(e);if(t){t.clientSocket&&t.clientSocket.destroy(),t.child&&t.child.kill("SIGTERM");for(let[,n]of t.pendingCommands)n.reject(new Error("Daemon stopped"));mn()!=="win32"&&dr(t.socketPath)&&gl(t.socketPath,()=>{}),this.daemons.delete(e)}}};import{writeFileSync as kl,mkdirSync as Cl,existsSync as xl}from"node:fs";import{dirname as Tl,join as ur}from"node:path";import{tmpdir as Rl}from"node:os";var ko={minChromeVersion:136,daemonIdleTimeoutS:1200,targetPrefixLength:8},xt=class extends q{name="chrome_session";description=`Interact with Chrome browser via Chrome DevTools Protocol (CDP).
158
174
 
159
175
  Core Commands:
160
176
  - status: Check Chrome connectivity, version, and remote debugging status
@@ -189,7 +205,7 @@ Examples:
189
205
  - chrome_session clickxy --target "ABC123" --x 100 --y 200
190
206
  - chrome_session type --target "ABC123" --text "Hello World"
191
207
  - chrome_session loadall --target "ABC123" --selector "button.load-more" --interval 500
192
- - chrome_session evalraw --target "ABC123" --method "Page.getTitle" --params '{}'`;parameters={type:"object",properties:{command:{type:"string",description:"The command to execute",enum:["status","list","open","stop","snap","shot","eval","html","nav","net","click","clickxy","type","loadall","evalraw"]},target:{type:"string",description:"Target ID prefix (required for page interaction commands)"},url:{type:"string",description:"URL to open (for 'open' and 'nav' commands)"},path:{type:"string",description:"File path to save screenshot (for 'shot' command)"},selector:{type:"string",description:"CSS selector for element-specific operations (for 'shot', 'html', 'click', 'loadall' commands)"},expression:{type:"string",description:"JavaScript expression to evaluate (for 'eval' command)"},depth:{type:"number",description:"Maximum depth for accessibility tree (for 'snap' command)"},timeout:{type:"number",description:"Timeout in milliseconds (for 'nav' command)"},outer:{type:"boolean",description:"Return outer HTML (default true, for 'html' command)"},x:{type:"number",description:"X coordinate in CSS pixels (for 'clickxy' command)"},y:{type:"number",description:"Y coordinate in CSS pixels (for 'clickxy' command)"},text:{type:"string",description:"Text to type at focused element (for 'type' command)"},interval:{type:"number",description:"Interval in milliseconds between clicks (for 'loadall' command, default 500)"},method:{type:"string",description:"CDP method name (for 'evalraw' command)"},params:{type:"object",description:"CDP method parameters as JSON object (for 'evalraw' command)"}},required:["command"]};config;daemonManager;commands;workspace;restrictToWorkspace;constructor(e={},t,n=!1){super(),this.config={minChromeVersion:e.minChromeVersion??136,daemonIdleTimeoutS:e.daemonIdleTimeoutS??1200,targetPrefixLength:e.targetPrefixLength??8},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Dt.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 Lt();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=zn();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 on(e)}catch{t=await on(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=zn();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 gs(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=zn();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 on(t)}catch{n=await on(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=Xn(this.workspace,e):t=Xn(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=Xn(this.workspace,e):t=Xn(Na(),`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=Da(e);Oa(n)||La(n,{recursive:!0});let r=Buffer.from(t,"base64");$a(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var an=class extends G{constructor(t){super();this.relay=t}name="chrome_relay";description="Control Chrome browser through the relay extension. Commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach.";parameters={type:"object",properties:{command:{type:"string",enum:["list_tabs","navigate","click","type","screenshot","read","evaluate","attach","detach"],description:"The command to execute"},tabId:{type:"number",description:"Tab ID for tab-specific commands"},url:{type:"string",description:"URL to navigate to"},selector:{type:"string",description:"CSS selector for click command"},text:{type:"string",description:"Text to type"},expression:{type:"string",description:"JavaScript expression to evaluate"},format:{type:"string",description:"Screenshot format (png or jpeg)"}},required:["command"]};async execute(t){let n=String(t.command??"");try{switch(n){case"list_tabs":{let r=await this.relay.listTabs();return JSON.stringify(r,null,2)}case"navigate":{let r=Number(t.tabId),s=String(t.url??"");return r?s?(await this.relay.navigate(r,s),`Navigated tab ${r} to ${s}`):"Error: url is required":"Error: tabId is required"}case"click":{let r=Number(t.tabId),s=String(t.selector??"");return r?s?(await this.relay.click(r,s),`Clicked "${s}" in tab ${r}`):"Error: selector is required":"Error: tabId is required"}case"type":{let r=Number(t.tabId),s=String(t.text??""),i=t.selector?String(t.selector):void 0;return r?s?(await this.relay.type(r,s,i),`Typed "${s}" in tab ${r}${i?` (selector: ${i})`:""}`):"Error: text is required":"Error: tabId is required"}case"screenshot":{let r=Number(t.tabId),s=String(t.format??"png");return r?`Screenshot captured: ${(await this.relay.screenshot(r,s)).slice(0,100)}...`:"Error: tabId is required"}case"read":{let r=Number(t.tabId);if(!r)return"Error: tabId is required";let s=await this.relay.evaluate(r,"document.body.innerText");return JSON.stringify(s,null,2)}case"evaluate":{let r=Number(t.tabId),s=String(t.expression??"");if(!r)return"Error: tabId is required";if(!s)return"Error: expression is required";let i=await this.relay.evaluate(r,s);return JSON.stringify(i,null,2)}case"attach":{let r=Number(t.tabId);return r?(await this.relay.attachTab(r),`Attached to tab ${r}`):"Error: tabId is required"}case"detach":{let r=Number(t.tabId);return r?(await this.relay.detachTab(r),`Detached from tab ${r}`):"Error: tabId is required"}default:return`Unknown command: ${n}. Available commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach`}}catch(r){return`Error: ${r instanceof Error?r.message:String(r)}`}}};import se from"node:fs";import ln from"node:path";import{randomUUID as ja}from"node:crypto";var Fa="automations",Ba="index.json";function Ga(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function ro(o){return ln.join(o,Fa)}function fs(o){return ln.join(ro(o),Ba)}function Qn(o,e){return ln.join(ro(o),e)}function oo(o,e){return ln.join(Qn(o,e),"rule.json")}function so(o,e){return ln.join(Qn(o,e),"script.js")}function io(o){let e=ro(o);se.existsSync(e)||se.mkdirSync(e,{recursive:!0})}function Zn(o){io(o);let e=fs(o);if(!se.existsSync(e))return{rules:[]};try{let t=se.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=Ce(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=Ce(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&er(o,n),n}catch{return{rules:[]}}}function er(o,e){io(o);let t=fs(o),n=`${t}.tmp`;se.writeFileSync(n,JSON.stringify(e,null,2)),se.renameSync(n,t)}function Nt(o){return Zn(o).rules}function Ce(o,e){let t=oo(o,e);if(!se.existsSync(t))return null;try{let n=se.readFileSync(t,"utf-8"),r=JSON.parse(n),s=so(o,e);return se.existsSync(s)&&(r.scriptContent=se.readFileSync(s,"utf-8")),r}catch{return null}}function tr(o,e){io(o);let t=Ga(e.name)||ja().slice(0,8),n=Date.now(),r={id:t,name:e.name,description:e.description,createdAt:n,updatedAt:n,enabled:!0,stepCount:e.steps.length,steps:e.steps,scriptPath:`automations/${t}/script.js`,tags:e.tags||[],source:e.source||"manual",...e.toolType?{toolType:e.toolType}:{},...e.variables?{variables:e.variables}:{}},s=Qn(o,t);se.existsSync(s)||se.mkdirSync(s,{recursive:!0});let i=oo(o,t);se.writeFileSync(i,JSON.stringify(r,null,2));let a=hs(r),l=so(o,t);se.writeFileSync(l,a);let c=Zn(o),d={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(d.toolType=e.toolType),c.rules.push(d),er(o,c),r}function nr(o,e,t){let n=Ce(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=oo(o,e);if(se.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=hs(s),d=so(o,e);se.writeFileSync(d,c)}let a=Zn(o),l=a.rules.findIndex(c=>c.id===e);if(l>=0){let c={id:s.id,name:s.name,description:s.description,enabled:s.enabled,updatedAt:s.updatedAt,stepCount:s.steps.length};s.toolType&&(c.toolType=s.toolType),a.rules[l]=c,er(o,a)}return s}function jt(o,e){let t=Qn(o,e);if(!se.existsSync(t))return!1;se.rmSync(t,{recursive:!0,force:!0});let n=Zn(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(er(o,n),!0):!1}function hs(o){let e=new Date().toISOString();return`// Automation: ${o.name}
208
+ - 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??ko.minChromeVersion,daemonIdleTimeoutS:e.daemonIdleTimeoutS??ko.daemonIdleTimeoutS,targetPrefixLength:e.targetPrefixLength??ko.targetPrefixLength,...e.stealth?{stealth:e.stealth}:{}},this.workspace=t,this.restrictToWorkspace=n,this.daemonManager=Wt.getInstance(),this.commands=new Map([["status",this.handleStatus.bind(this)],["list",this.handleList.bind(this)],["open",this.handleOpen.bind(this)],["stop",this.handleStop.bind(this)],["snap",this.handleSnap.bind(this)],["shot",this.handleShot.bind(this)],["eval",this.handleEval.bind(this)],["html",this.handleHtml.bind(this)],["nav",this.handleNav.bind(this)],["net",this.handleNet.bind(this)],["click",this.handleClick.bind(this)],["clickxy",this.handleClickxy.bind(this)],["type",this.handleType.bind(this)],["loadall",this.handleLoadall.bind(this)],["evalraw",this.handleEvalraw.bind(this)]])}async execute(e,t){let n=e.command;if(!n)return this.formatError("Missing required 'command' parameter. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw");let r=this.commands.get(n);if(!r)return this.formatError(`Unknown command '${n}'. Available commands: status, list, open, stop, snap, shot, eval, html, nav, net, click, clickxy, type, loadall, evalraw`);try{return await r(e,t)}catch(s){let i=s instanceof Error?s.message:String(s);return this.formatError(`Command '${n}' failed: ${i}`)}}async handleStatus(){let e=this.config,t=await Ut();if(!t)return this.formatResult({available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or launch Chrome with --remote-debugging-port=9222"});if(t.pendingApproval)return this.formatResult({available:!1,pendingApproval:!0,reason:`Chrome is listening on port ${t.port} but remote debugging approval may be required`,hint:"Look for a remote debugging approval prompt in Chrome, or quit Chrome and relaunch with: open -a 'Google Chrome' --args --remote-debugging-port=9222",port:t.port});let{port:n,versionInfo:r}=t,s=r.Browser.match(/(\w+)\/(\d+)/),i=s?.[1]??"Chrome",a=s?parseInt(s[2],10):0;return a>0&&a<e.minChromeVersion?this.formatResult({available:!1,reason:`Chrome version ${a} is below minimum required version ${e.minChromeVersion}`,hint:`Update Chrome to version ${e.minChromeVersion} or higher`,version:r.Browser,port:n,browser:i}):this.formatResult({available:!0,version:r.Browser,protocolVersion:r["Protocol-Version"],userAgent:r["User-Agent"],webSocketDebuggerUrl:r.webSocketDebuggerUrl,port:n,browser:i})}async handleList(){let e=lr();if(!e)return this.formatError("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let t;try{let i=await fetch(`http://127.0.0.1:${e}/json/list`);i.ok?t=await i.json():t=await gn(e)}catch{t=await gn(e)}let n=t.filter(i=>i.type==="page"&&!i.url.startsWith("chrome://"));if(n.length===0)return this.formatResult({tabs:[],message:"No open tabs found"});let r=this.config.targetPrefixLength,s=n.map(i=>({id:i.id.slice(0,r),fullId:i.id,title:i.title,url:i.url}));return this.formatResult({tabs:s,count:s.length})}async handleOpen(e){let t=lr();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 Bs(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=lr();if(!t)throw new Error("Chrome remote debugging not detected. Run 'chrome_session status' for details.");let n;try{let l=await fetch(`http://127.0.0.1:${t}/json/list`);l.ok?n=await l.json():n=await gn(t)}catch{n=await gn(t)}let r=n.filter(l=>l.type==="page"&&!l.url.startsWith("chrome://")),s=e.toUpperCase(),i=r.filter(l=>l.id.toUpperCase().startsWith(s));if(i.length===0)throw new Error(`No target found matching prefix '${e}'`);if(i.length>1){let l=i.map(c=>c.id.slice(0,this.config.targetPrefixLength)).join(", ");throw new Error(`Ambiguous prefix '${e}' matches ${i.length} targets: ${l}`)}let a=i[0];return{targetId:a.id,wsUrl:a.webSocketDebuggerUrl}}async sendDaemonCommand(e,t,n,r){return await this.daemonManager.getOrCreateDaemon(e,t,{idleTimeoutMs:this.config.daemonIdleTimeoutS*1e3}),this.config.stealth?.enabled&&await this.daemonManager.sendCommand(e,"setStealthConfig",{stealth:this.config.stealth}),this.daemonManager.sendCommand(e,n,r)}resolveScreenshotPath(e){if(!e)return;let t;if(e.startsWith("/")?t=e:e.startsWith("./")||e.startsWith("../")?this.restrictToWorkspace&&this.workspace?t=ur(this.workspace,e):t=ur(process.cwd(),e):this.restrictToWorkspace&&this.workspace?t=ur(this.workspace,e):t=ur(Rl(),`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=Tl(e);xl(n)||Cl(n,{recursive:!0});let r=Buffer.from(t,"base64");kl(e,r)}formatResult(e){return JSON.stringify(e,null,2)}formatError(e){return JSON.stringify({error:e},null,2)}};var pn=class extends q{constructor(t){super();this.relay=t}name="chrome_relay";description="Control Chrome browser through the relay extension. Commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach.";parameters={type:"object",properties:{command:{type:"string",enum:["list_tabs","navigate","click","type","screenshot","read","evaluate","attach","detach"],description:"The command to execute"},tabId:{type:"number",description:"Tab ID for tab-specific commands"},url:{type:"string",description:"URL to navigate to"},selector:{type:"string",description:"CSS selector for click command"},text:{type:"string",description:"Text to type"},expression:{type:"string",description:"JavaScript expression to evaluate"},format:{type:"string",description:"Screenshot format (png or jpeg)"}},required:["command"]};async execute(t){let n=String(t.command??"");try{switch(n){case"list_tabs":{let r=await this.relay.listTabs();return JSON.stringify(r,null,2)}case"navigate":{let r=Number(t.tabId),s=String(t.url??"");return r?s?(await this.relay.navigate(r,s),`Navigated tab ${r} to ${s}`):"Error: url is required":"Error: tabId is required"}case"click":{let r=Number(t.tabId),s=String(t.selector??"");return r?s?(await this.relay.click(r,s),`Clicked "${s}" in tab ${r}`):"Error: selector is required":"Error: tabId is required"}case"type":{let r=Number(t.tabId),s=String(t.text??""),i=t.selector?String(t.selector):void 0;return r?s?(await this.relay.type(r,s,i),`Typed "${s}" in tab ${r}${i?` (selector: ${i})`:""}`):"Error: text is required":"Error: tabId is required"}case"screenshot":{let r=Number(t.tabId),s=String(t.format??"png");return r?`Screenshot captured: ${(await this.relay.screenshot(r,s)).slice(0,100)}...`:"Error: tabId is required"}case"read":{let r=Number(t.tabId);if(!r)return"Error: tabId is required";let s=await this.relay.evaluate(r,"document.body.innerText");return JSON.stringify(s,null,2)}case"evaluate":{let r=Number(t.tabId),s=String(t.expression??"");if(!r)return"Error: tabId is required";if(!s)return"Error: expression is required";let i=await this.relay.evaluate(r,s);return JSON.stringify(i,null,2)}case"attach":{let r=Number(t.tabId);return r?(await this.relay.attachTab(r),`Attached to tab ${r}`):"Error: tabId is required"}case"detach":{let r=Number(t.tabId);return r?(await this.relay.detachTab(r),`Detached from tab ${r}`):"Error: tabId is required"}default:return`Unknown command: ${n}. Available commands: list_tabs, navigate, click, type, screenshot, read, evaluate, attach, detach`}}catch(r){return`Error: ${r instanceof Error?r.message:String(r)}`}}};import ae from"node:fs";import fn from"node:path";import{randomUUID as Al}from"node:crypto";var El="automations",Pl="index.json";function _l(o){return o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,50)}function Co(o){return fn.join(o,El)}function Ws(o){return fn.join(Co(o),Pl)}function gr(o,e){return fn.join(Co(o),e)}function xo(o,e){return fn.join(gr(o,e),"rule.json")}function To(o,e){return fn.join(gr(o,e),"script.js")}function Ro(o){let e=Co(o);ae.existsSync(e)||ae.mkdirSync(e,{recursive:!0})}function mr(o){Ro(o);let e=Ws(o);if(!ae.existsSync(e))return{rules:[]};try{let t=ae.readFileSync(e,"utf-8"),n=JSON.parse(t),r=!1;for(let s of n.rules){if(s.stepCount===void 0){let i=Te(o,s.id);s.stepCount=i?.steps?.length||0,r=!0}if(s.toolType===void 0){let i=Te(o,s.id);i?.toolType&&(s.toolType=i.toolType,r=!0)}}return r&&pr(o,n),n}catch{return{rules:[]}}}function pr(o,e){Ro(o);let t=Ws(o),n=`${t}.tmp`;ae.writeFileSync(n,JSON.stringify(e,null,2)),ae.renameSync(n,t)}function Kt(o){return mr(o).rules}function Te(o,e){let t=xo(o,e);if(!ae.existsSync(t))return null;try{let n=ae.readFileSync(t,"utf-8"),r=JSON.parse(n),s=To(o,e);return ae.existsSync(s)&&(r.scriptContent=ae.readFileSync(s,"utf-8")),r}catch{return null}}function fr(o,e){Ro(o);let t=_l(e.name)||Al().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=gr(o,t);ae.existsSync(s)||ae.mkdirSync(s,{recursive:!0});let i=xo(o,t);ae.writeFileSync(i,JSON.stringify(r,null,2));let a=Ks(r),l=To(o,t);ae.writeFileSync(l,a);let c=mr(o),d={id:r.id,name:r.name,description:r.description,enabled:r.enabled,updatedAt:r.updatedAt,stepCount:r.steps.length};return e.toolType&&(d.toolType=e.toolType),c.rules.push(d),pr(o,c),r}function hr(o,e,t){let n=Te(o,e);if(!n)return null;let r=Date.now(),s={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:r,stepCount:(t.steps||n.steps).length},i=xo(o,e);if(ae.writeFileSync(i,JSON.stringify(s,null,2)),t.steps){let c=Ks(s),d=To(o,e);ae.writeFileSync(d,c)}let a=mr(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,pr(o,a)}return s}function Ht(o,e){let t=gr(o,e);if(!ae.existsSync(t))return!1;ae.rmSync(t,{recursive:!0,force:!0});let n=mr(o),r=n.rules.length;return n.rules=n.rules.filter(s=>s.id!==e),n.rules.length!==r?(pr(o,n),!0):!1}function Ks(o){let e=new Date().toISOString();return`// Automation: ${o.name}
193
209
  // Tool: ${o.toolType??"auto-detect"}
194
210
  // Generated: ${e}
195
211
  // Description: ${o.description}
@@ -210,38 +226,40 @@ fetch(URL, { method: 'POST' })
210
226
  else console.error('Failed:', r.error);
211
227
  })
212
228
  .catch(e => console.error('Could not reach everclaw:', e.message));
213
- `}De();var ys={chrome_session:{navigate:"nav",click:"click",type:"type",screenshot:"shot",read:"snap",eval:"eval"},chrome_relay:{navigate:"navigate",click:"click",type:"type",screenshot:"screenshot",read:"read",eval:"evaluate"}},ao=o=>new Promise(e=>setTimeout(e,o)),Ft=class extends G{constructor(t,n){super();this.browserTool=n;this.workspace=X(t)}name="automation";description="Manage browser automation workflows. Commands: list, get, save, delete, run.";parameters={type:"object",properties:{command:{type:"string",enum:["list","get","save","delete","run"],description:"The command to execute"},id:{type:"string",description:"Automation ID (for get, delete, run)"},name:{type:"string",description:"Automation name (for save)"},description:{type:"string",description:"Brief description (for save)"},steps:{type:"array",items:{type:"object",properties:{order:{type:"number"},action:{type:"string"},target:{type:"string"},value:{type:"string"},description:{type:"string"},optional:{type:"boolean"},assert:{type:"object",properties:{check:{type:"string",enum:["selector_exists","selector_text","url_contains","eval_truthy"]},value:{type:"string"},expected:{type:"string"},timeoutMs:{type:"number"}}},retries:{type:"number"},retryDelayMs:{type:"number"}}},description:"Automation steps (for save)"},tags:{type:"array",items:{type:"string"},description:"Optional tags (for save)"},enabled:{type:"boolean",description:"Enable/disable (for save)"},variables:{type:"object",description:'Variable overrides for run command (e.g., {"USERNAME": "user"})'}},required:["command"]};workspace;async execute(t,n){let r=String(t.command??"");try{switch(r){case"list":{let s=Nt(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=Ce(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let d=this.browserTool?.name,p;if(s){let h={name:i,description:a,steps:l,tags:c};return d&&(h.toolType=d),p=nr(this.workspace,s,h),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let h={name:i,description:a,steps:l,tags:c,source:"conversation"};return d&&(h.toolType=d),p=tr(this.workspace,h),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?jt(this.workspace,s)?`Deleted automation '${s}'`:`Error: Automation '${s}' not found or could not be deleted`:"Error: id is required for delete command"}case"run":{let s=String(t.id??"");if(!s)return"Error: id is required for run command";let i=Ce(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),d=await this.executeStepWithRetries(c,n,i),p=this.maskSensitiveValues(d,t.variables);s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`)}catch(c){let d=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${d}`);else return s.push(` -> FAILED: ${d}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
229
+ `}je();var Hs={chrome_session:{navigate:"nav",click:"click",type:"type",screenshot:"shot",read:"snap",eval:"eval"},chrome_relay:{navigate:"navigate",click:"click",type:"type",screenshot:"screenshot",read:"read",eval:"evaluate"}},hn=o=>new Promise(e=>setTimeout(e,o)),Jt=class extends q{constructor(t,n,r){super();this.browserTool=n;this.stealthConfig=r;this.workspace=Z(t)}name="automation";description="Manage browser automation workflows. Commands: list, get, save, delete, run.";parameters={type:"object",properties:{command:{type:"string",enum:["list","get","save","delete","run"],description:"The command to execute"},id:{type:"string",description:"Automation ID (for get, delete, run)"},name:{type:"string",description:"Automation name (for save)"},description:{type:"string",description:"Brief description (for save)"},steps:{type:"array",items:{type:"object",properties:{order:{type:"number"},action:{type:"string"},target:{type:"string"},value:{type:"string"},description:{type:"string"},optional:{type:"boolean"},assert:{type:"object",properties:{check:{type:"string",enum:["selector_exists","selector_text","url_contains","eval_truthy"]},value:{type:"string"},expected:{type:"string"},timeoutMs:{type:"number"}}},retries:{type:"number"},retryDelayMs:{type:"number"}}},description:"Automation steps (for save)"},tags:{type:"array",items:{type:"string"},description:"Optional tags (for save)"},enabled:{type:"boolean",description:"Enable/disable (for save)"},variables:{type:"object",description:'Variable overrides for run command (e.g., {"USERNAME": "user"})'}},required:["command"]};workspace;async execute(t,n){let r=String(t.command??"");try{switch(r){case"list":{let s=Kt(this.workspace);return JSON.stringify(s,null,2)}case"get":{let s=String(t.id??"");if(!s)return"Error: id is required for get command";let i=Te(this.workspace,s);return i?JSON.stringify(i,null,2):`Error: Automation '${s}' not found`}case"save":{let s=t.id?String(t.id):void 0,i=String(t.name??"Untitled Automation"),a=String(t.description??""),l=t.steps||[],c=t.tags||[];if(l.length===0)return"Error: At least one step is required";let d=this.browserTool?.name,p;if(s){let g={name:i,description:a,steps:l,tags:c};return d&&(g.toolType=d),p=hr(this.workspace,s,g),p?`Updated automation '${p.name}' (${p.id})`:`Error: Automation '${s}' not found for update`}else{let g={name:i,description:a,steps:l,tags:c,source:"conversation"};return d&&(g.toolType=d),p=fr(this.workspace,g),`Created automation '${p.name}' (${p.id})`}}case"delete":{let s=String(t.id??"");return s?Ht(this.workspace,s)?`Deleted automation '${s}'`:`Error: Automation '${s}' not found or could not be deleted`:"Error: id is required for delete command"}case"run":{let s=String(t.id??"");if(!s)return"Error: id is required for run command";let i=Te(this.workspace,s);if(!i)return`Error: Automation '${s}' not found`;if(!i.enabled)return`Error: Automation '${i.name}' is disabled`;let a=t.variables;return this.executeAutomation(i,n?.signal,a)}default:return`Unknown command: ${r}. Available commands: list, get, save, delete, run`}}catch(s){return`Error: ${s instanceof Error?s.message:String(s)}`}}async executeAutomation(t,n,r){if(!this.browserTool)return"Error: No browser tool available. Enable chrome_session or chrome_relay to run automations.";if(t.toolType&&t.toolType!==this.browserTool.name)return`Error: Automation '${t.name}' requires ${t.toolType} but ${this.browserTool.name} is active. Change browser tool or update the automation.`;let s=[];s.push(`Running automation: ${t.name}`),s.push(`Tool: ${this.browserTool.name}`),s.push(`Steps: ${t.steps.length}`);let i=await this.resolveTabContext();if(!i.tabId&&!i.target)return"Error: Could not resolve tab context. Open a browser tab first.";let a=[...t.steps].sort((l,c)=>l.order-c.order);for(let l of a){if(n?.aborted){s.push(`Aborted at step ${l.order}`);break}l.stealth?.preDelay&&await hn(l.stealth.preDelay),s.push(`[Step ${l.order}] ${l.description}`);try{let c=this.resolveStep(l,t.variables,r),d=await this.executeStepWithRetries(c,n,i),p=this.maskSensitiveValues(d,t.variables);if(s.push(` -> ${p.slice(0,200)}${p.length>200?"...":""}`),this.stealthConfig?.enabled){let[g,x]=this.stealthConfig.interStepDelay;await hn(g+Math.random()*(x-g))}}catch(c){let d=c instanceof Error?c.message:String(c);if(l.optional)s.push(` -> Optional step failed (continuing): ${d}`);else return s.push(` -> FAILED: ${d}`),s.push(`Automation '${t.name}' stopped due to error.`),s.join(`
214
230
  `)}}return s.push(`Automation '${t.name}' completed successfully.`),s.join(`
215
- `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,d)=>{if(r&&r[d]!==void 0)return r[d];if(n&&n[d]?.defaultValue!==void 0)return n[d].defaultValue;if(n&&n[d]?.required)throw new Error(`Required variable '${d}' not provided`);return`\${${d}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await ao(i)}throw a??new Error("Unknown error")}async executeStepOnce(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=this.browserTool.name,i=ys[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"";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 ao(c),`Waited ${c}ms`;default:throw new Error(`Unknown action: ${t.action}`)}return this.browserTool.execute(l,n?{signal:n}:void 0)}toExpression(t){switch(t.check){case"selector_exists":return`!!document.querySelector(${JSON.stringify(t.value)})`;case"selector_text":return`(document.querySelector(${JSON.stringify(t.value)})?.textContent?.trim() ?? "") === ${JSON.stringify(t.expected??"")}`;case"url_contains":return`window.location.href.includes(${JSON.stringify(t.value)})`;case"eval_truthy":return`!!(${t.value})`}}isAssertionPassing(t,n){try{let r=JSON.parse(t);if(n==="chrome_session"){let s=r.result;return s&&typeof s.value=="boolean"?s.value:s&&typeof s.value=="string"?s.value.length>0:s&&typeof s.value=="number"?s.value!==0:r.result===!0}return n==="chrome_relay"?r===!0:!1}catch{return!1}}async pollAssertion(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=t.timeoutMs??5e3,i=500,a=this.toExpression(t),l=Date.now();do{if(n?.aborted)throw new Error("Aborted during assertion");try{let c=this.browserTool.name,p=ys[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let h={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(h.tabId=r.tabId),c==="chrome_session"&&r.target&&(h.target=r.target);let v=await this.browserTool.execute(h);if(this.isAssertionPassing(v,c))return}catch{}if(Date.now()-l>=s)break;await ao(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var rr=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(Q(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(`
231
+ `)}async resolveTabContext(){if(!this.browserTool)return{};let t=this.browserTool.name;if(t==="chrome_relay"){try{let n=await this.browserTool.execute({command:"list_tabs"}),r=JSON.parse(n);if(Array.isArray(r)&&r.length>0)return{tabId:(r.find(i=>i.active)||r[0]).id}}catch{}return{}}if(t==="chrome_session"){try{let n=await this.browserTool.execute({command:"list"}),r=JSON.parse(n);if(r.tabs&&Array.isArray(r.tabs)&&r.tabs.length>0)return{target:r.tabs[0].id}}catch{}return{}}return{}}resolveStep(t,n,r){let s=l=>l&&l.replace(/\$\{(\w+)\}/g,(c,d)=>{if(r&&r[d]!==void 0)return r[d];if(n&&n[d]?.defaultValue!==void 0)return n[d].defaultValue;if(n&&n[d]?.required)throw new Error(`Required variable '${d}' not provided`);return`\${${d}}`}),i=s(t.target),a=s(t.value);return{...t,...i!==void 0?{target:i}:{},...a!==void 0?{value:a}:{}}}maskSensitiveValues(t,n){if(!n)return t;let r=t;for(let[s,i]of Object.entries(n))i.sensitive&&(r=r.replaceAll(`\${${s}}`,`[REDACTED:${s}]`));return r}async executeStepWithRetries(t,n,r){let s=1+(t.retries??0),i=t.retryDelayMs??1e3,a;for(let l=1;l<=s;l++)try{let c=await this.executeStepOnce(t,n,r);return t.assert&&await this.pollAssertion(t.assert,n,r),c}catch(c){a=c instanceof Error?c:new Error(String(c)),l<s&&await hn(i)}throw a??new Error("Unknown error")}async executeStepOnce(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=this.browserTool.name,i=Hs[s];if(!i)throw new Error(`Unsupported browser tool: ${s}`);let a=i[t.action];if(!a)throw new Error(`Action '${t.action}' not supported by ${s}`);let l={command:a};switch(s==="chrome_relay"&&r.tabId&&(l.tabId=r.tabId),s==="chrome_session"&&r.target&&(l.target=r.target),t.action){case"navigate":l.url=t.value??t.target??"";break;case"click":l.selector=t.target??"";break;case"type":l.text=t.value??"",t.stealth?.typingSpeed&&(l.typingSpeed=t.stealth.typingSpeed);break;case"read":break;case"screenshot":t.target&&(l.selector=t.target);break;case"eval":l.expression=t.value??"";break;case"wait":let c=parseInt(t.value??"1000",10);return await hn(c),`Waited ${c}ms`;default:throw new Error(`Unknown action: ${t.action}`)}return this.browserTool.execute(l,n?{signal:n}:void 0)}toExpression(t){switch(t.check){case"selector_exists":return`!!document.querySelector(${JSON.stringify(t.value)})`;case"selector_text":return`(document.querySelector(${JSON.stringify(t.value)})?.textContent?.trim() ?? "") === ${JSON.stringify(t.expected??"")}`;case"url_contains":return`window.location.href.includes(${JSON.stringify(t.value)})`;case"eval_truthy":return`!!(${t.value})`}}isAssertionPassing(t,n){try{let r=JSON.parse(t);if(n==="chrome_session"){let s=r.result;return s&&typeof s.value=="boolean"?s.value:s&&typeof s.value=="string"?s.value.length>0:s&&typeof s.value=="number"?s.value!==0:r.result===!0}return n==="chrome_relay"?r===!0:!1}catch{return!1}}async pollAssertion(t,n,r){if(!this.browserTool)throw new Error("No browser tool available");let s=t.timeoutMs??5e3,i=500,a=this.toExpression(t),l=Date.now();do{if(n?.aborted)throw new Error("Aborted during assertion");try{let c=this.browserTool.name,p=Hs[c]?.eval;if(!p)throw new Error(`Evaluation not supported by ${c}`);let g={command:p,expression:a};c==="chrome_relay"&&r.tabId&&(g.tabId=r.tabId),c==="chrome_session"&&r.target&&(g.target=r.target);let x=await this.browserTool.execute(g);if(this.isAssertionPassing(x,c))return}catch{}if(Date.now()-l>=s)break;await hn(i)}while(Date.now()-l<s);throw new Error(`Assertion failed after ${s}ms: ${t.check} (${t.value})`)}};var yr=class o{tools=new Map;guardEngine=null;register(e){this.tools.set(e.name,e)}unregister(e){return this.tools.delete(e)}clear(){this.tools.clear()}get(e){return this.tools.get(e)}getDefinitions(){return[...this.tools.values()].map(e=>e.toSchema())}get toolNames(){return[...this.tools.keys()]}setGuardEngine(e){this.guardEngine=e}getGuardEngine(){return this.guardEngine}filterByNames(e){let t=new o;t.guardEngine=this.guardEngine;for(let n of e){let r=this.tools.get(n);r&&t.register(r)}return t}excludeByNames(e){let t=new Set(e),n=new o;n.guardEngine=this.guardEngine;for(let[r,s]of this.tools)t.has(r)||n.register(s);return n}async execute(e,t,n){let r=this.tools.get(e);if(!r)return{kind:"error",content:`Error: Tool '${e}' not found. Available: ${this.toolNames.join(", ")}`,retryable:!1};try{if(te(n?.signal),this.guardEngine){let a=this.guardEngine.guard(e,t);if(a&&!a.isSafe){let l=a.findings.map(c=>` - [${c.severity}] ${c.title}: ${c.description}`).join(`
216
232
  `);return{kind:"error",content:`Security: Tool call blocked. The tool '${e}' was denied by the security guard.
217
233
 
218
234
  Findings:
219
235
  ${l}`,retryable:!1}}}let s=r.validateParams(t);if(s.length)return{kind:"error",content:`Error: Invalid parameters for tool '${e}': ${s.join("; ")}
220
236
 
221
- [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return Q(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(te(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
237
+ [Analyze the error above and try a different approach.]`,retryable:!0};let i=await r.execute(t,n);return te(n?.signal),i.startsWith("__TERMINAL__")?{kind:"terminal",content:i.slice(12)}:{kind:"ok",content:i}}catch(s){if(se(s))throw s;return{kind:"error",content:`Error executing ${e}: ${String(s)}
222
238
 
223
- [Analyze the error above and try a different approach.]`,retryable:!0}}}};function bs(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Ua(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
239
+ [Analyze the error above and try a different approach.]`,retryable:!0}}}};function Js(o){return o.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").trim()}function Ml(o){return o.replace(/[ \t]+/g," ").replace(/\n{3,}/g,`
224
240
 
225
- `).trim()}function Wa(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 or=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{Q(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let d=(await l.json()).web?.results??[];if(!d.length)return`No results for: ${r}`;let p=[`Results for: ${r}`,""];return d.slice(0,s).forEach((h,v)=>{p.push(`${v+1}. ${h.title??""}`),p.push(` ${h.url??""}`),h.description&&p.push(` ${h.description}`)}),p.join(`
226
- `)}catch(a){if(te(a))throw a;return`Error: ${String(a)}`}}},sr=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]=Wa(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{Q(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),d=c.headers.get("content-type")||"",p="",h="raw";if(d.includes("application/json"))p=JSON.stringify(await c.json(),null,2),h="json";else{let u=await c.text();d.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(u.slice(0,256))?(p=s==="text"?bs(u):Ua(bs(u)),h="html"):p=u}let v=p.length>i,w=v?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:h,truncated:v,length:w.length,text:w})}catch(c){if(te(c))throw c;return JSON.stringify({error:String(c),url:r})}}};bt();function Je(o){return Ka.resolve(o.workspace)}function ir(o){let e=Je(o);return o.restrictToWorkspace?e:void 0}function Ha(o){let e=[ye({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new Dn(Je(t),ir(t))},{name:"write_file",create:t=>new Nn(Je(t),ir(t))},{name:"edit_file",create:t=>new jn(Je(t),ir(t))},{name:"list_dir",create:t=>new Fn(Je(t),ir(t))}]}),ye({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new Un(t.execConfig?.timeout??60,Je(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new be,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),ye({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new or(t.braveApiKey??null)},{name:"web_fetch",create:()=>new sr}]})];return o.bus&&e.push(ye({name:"builtin-messaging-tools",tools:[{name:"message",create:t=>{if(!t.bus)throw new Error("Builtin message tool requires a message bus");let n=new Gn(async r=>{t.turn?.isCurrent&&!t.turn.isCurrent()||await t.bus.publishOutbound(r)});return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.messageId),n}}]})),o.subagents&&e.push(ye({name:"builtin-subagent-tools",tools:[{name:"spawn",create:t=>{if(!t.subagents)throw new Error("Builtin spawn tool requires a subagent manager");let n=new Wn(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey),n}}]})),o.cronService&&e.push(ye({name:"builtin-scheduler-tools",tools:[{name:"cron",create:t=>{if(!t.cronService)throw new Error("Builtin cron tool requires a cron service");let n=new On(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(ye({name:"builtin-session-tools",tools:[{name:"session.info",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.info tool requires a session manager");let n=new Hn;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 Jn;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 Kn;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(ye({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new vt(t.chromeSessionConfig,Je(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(ye({name:"builtin-browser-relay-tools",tools:[{name:"chrome_relay",create:t=>{if(!t.browserRelay)throw new Error("Builtin chrome_relay tool requires a browser relay server");return new an(t.browserRelay)}}]})),e.push(ye({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new an(t.browserRelay):t.chromeSessionConfig?.enabled?new vt(t.chromeSessionConfig,Je(t),!!t.restrictToWorkspace):void 0;return new Ft(Je(t),n)}}]})),e}function Ja(o){return to(Ha(o))}function ar(o){let e=new rr,t=Ja(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function qa(o){let e=[ye({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new nn({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??Ze())}]})];return o.heartbeat&&e.push(ye({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new rn(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 za(o){return to(qa(o))}function qe(o){let e=za(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 nn))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 rn))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}bt();var ws="EVERCLAW_SUBAGENT_RESULT ";function Ya(){return`# Subagent
241
+ `).trim()}function Il(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 br=class extends q{constructor(t,n=5){super();this.apiKey=t;this.maxResults=n}name="web_search";description="Search the web. Returns titles, URLs, and snippets.";parameters={type:"object",properties:{query:{type:"string",description:"Search query"},count:{type:"integer",minimum:1,maximum:10,description:"Results (1-10)"}},required:["query"]};async execute(t,n){let r=String(t.query??""),s=Math.min(Math.max(Number(t.count??this.maxResults),1),10),i=this.apiKey||process.env.BRAVE_API_KEY||"";if(!i)return"Error: Brave Search API key not configured. Set tools.web.search.apiKey or BRAVE_API_KEY.";try{te(n?.signal);let a=new URL("https://api.search.brave.com/res/v1/web/search");a.searchParams.set("q",r),a.searchParams.set("count",String(s));let l=await fetch(a,{headers:{Accept:"application/json","X-Subscription-Token":i},...n?.signal?{signal:n.signal}:{}});if(!l.ok)return`Error: ${l.status} ${l.statusText}`;let d=(await l.json()).web?.results??[];if(!d.length)return`No results for: ${r}`;let p=[`Results for: ${r}`,""];return d.slice(0,s).forEach((g,x)=>{p.push(`${x+1}. ${g.title??""}`),p.push(` ${g.url??""}`),g.description&&p.push(` ${g.description}`)}),p.join(`
242
+ `)}catch(a){if(se(a))throw a;return`Error: ${String(a)}`}}},wr=class extends q{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]=Il(r);if(!a)return JSON.stringify({error:`URL validation failed: ${l}`,url:r});try{te(n?.signal);let c=await fetch(r,{redirect:"follow",headers:{"User-Agent":"Mozilla/5.0"},...n?.signal?{signal:n.signal}:{}}),d=c.headers.get("content-type")||"",p="",g="raw";if(d.includes("application/json"))p=JSON.stringify(await c.json(),null,2),g="json";else{let u=await c.text();d.includes("text/html")||/^\s*<!doctype|^\s*<html/i.test(u.slice(0,256))?(p=s==="text"?Js(u):Ml(Js(u)),g="html"):p=u}let x=p.length>i,y=x?p.slice(0,i):p;return JSON.stringify({url:r,finalUrl:c.url,status:c.status,extractor:g,truncated:x,length:y.length,text:y})}catch(c){if(se(c))throw c;return JSON.stringify({error:String(c),url:r})}}};kt();function ze(o){return $l.resolve(o.workspace)}function vr(o){let e=ze(o);return o.restrictToWorkspace?e:void 0}function Ol(o){let e=[we({name:"builtin-filesystem-tools",tools:[{name:"read_file",create:t=>new Xn(ze(t),vr(t))},{name:"write_file",create:t=>new Yn(ze(t),vr(t))},{name:"edit_file",create:t=>new Qn(ze(t),vr(t))},{name:"list_dir",create:t=>new Zn(ze(t),vr(t))}]}),we({name:"builtin-shell-tools",tools:[{name:"exec",create:t=>new nr(t.execConfig?.timeout??60,ze(t),!!t.restrictToWorkspace,t.execConfig?.pathAppend??"",new ve,t.rtkService,t.rtkConfig?.ultraCompact??!1)}]}),we({name:"builtin-web-tools",tools:[{name:"web_search",create:t=>new br(t.braveApiKey??null)},{name:"web_fetch",create:()=>new wr}]})];return o.bus&&e.push(we({name:"builtin-messaging-tools",tools:[{name:"message",create:t=>{if(!t.bus)throw new Error("Builtin message tool requires a message bus");let n=new tr(async r=>{t.turn?.isCurrent&&!t.turn.isCurrent()||await t.bus.publishOutbound(r)});return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.messageId),n}}]})),o.subagents&&e.push(we({name:"builtin-subagent-tools",tools:[{name:"spawn",create:t=>{if(!t.subagents)throw new Error("Builtin spawn tool requires a subagent manager");let n=new rr(t.subagents);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId,t.turn.sessionKey,t.turn.systemPrompt),n}}]})),o.cronService&&e.push(we({name:"builtin-scheduler-tools",tools:[{name:"cron",create:t=>{if(!t.cronService)throw new Error("Builtin cron tool requires a cron service");let n=new Vn(t.cronService);return t.turn&&n.setContext(t.turn.channel,t.turn.chatId),n}}]})),o.sessionManager&&e.push(we({name:"builtin-session-tools",tools:[{name:"session.info",create:t=>{if(!t.sessionManager)throw new Error("Builtin session.info tool requires a session manager");let n=new sr;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 ir;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 or;return n.setSessionManager(t.sessionManager),t.turn&&n.setContext(t.turn.sessionKey),n}}]})),o.chromeSessionConfig?.enabled&&e.push(we({name:"builtin-chrome-session-tools",tools:[{name:"chrome_session",create:t=>new xt(t.chromeSessionConfig,ze(t),!!t.restrictToWorkspace)}]})),o.browserRelay&&e.push(we({name:"builtin-browser-relay-tools",tools:[{name:"chrome_relay",create:t=>{if(!t.browserRelay)throw new Error("Builtin chrome_relay tool requires a browser relay server");return new pn(t.browserRelay)}}]})),e.push(we({name:"builtin-automation-tools",tools:[{name:"automation",create:t=>{let n=t.browserRelay?new pn(t.browserRelay):t.chromeSessionConfig?.enabled?new xt(t.chromeSessionConfig,ze(t),!!t.restrictToWorkspace):void 0;return new Jt(ze(t),n,t.chromeSessionConfig?.stealth)}}]})),e}function Ll(o){return wo(Ol(o))}function Sr(o){let e=new yr,t=Ll(o);for(let n of t.tools.values())e.register(n.contribution.create(o));return e}function Nl(o){let e=[we({name:"builtin-scheduled-jobs",jobs:[{name:"cron",create:t=>new dn({dataDir:t.cron.dataDir},t.cron.onJob,t.lifecycle??rt())}]})];return o.heartbeat&&e.push(we({name:"builtin-background-jobs",jobs:[{name:"heartbeat",create:t=>{if(!t.heartbeat)throw new Error("Builtin heartbeat job requires heartbeat configuration");return new un(t.heartbeat.workspace,t.heartbeat.provider,t.heartbeat.model,t.heartbeat.onExecute,t.heartbeat.onNotify,t.heartbeat.intervalS??1800,t.heartbeat.enabled??!0)}}]})),e}function Dl(o){return wo(Nl(o))}function Ve(o){let e=Dl(o),t=o.lifecycle??e.lifecycle,n={...o,lifecycle:t},r=e.jobs.get("cron")?.contribution;if(!r)throw new Error("Builtin cron job registration is missing");let s=r.create(n);if(!(s instanceof dn))throw new Error("Builtin cron job registration produced an invalid service");let i=e.jobs.get("heartbeat")?.contribution,a;if(i){let l=i.create(n);if(!(l instanceof un))throw new Error("Builtin heartbeat job registration produced an invalid service");a=l}return{composed:e,lifecycle:t,cron:s,heartbeat:a}}var kr=class{tasks=new Map;order=[];register(e,t,n,r){let s=new Date().toISOString(),i={id:e,type:t,label:n,sessionKey:r,createdAt:s,status:"pending",startedAt:null,completedAt:null,result:null,error:null};return this.tasks.set(e,i),this.order.push(e),this.enforceLimit(),i}transition(e,t,n,r){let s=this.tasks.get(e);if(!s)return;let i=new Date().toISOString(),a={status:t};t==="running"&&s.startedAt===null&&(a.startedAt=i),this.isTerminal(t)&&(a.completedAt=i,n!==void 0&&(a.result=n),r!==void 0&&(a.error=r)),Object.assign(s,a)}get(e){return this.tasks.get(e)}getBySession(e){return[...this.tasks.values()].filter(t=>t.sessionKey===e)}getRunning(){return[...this.tasks.values()].filter(e=>e.status==="running")}getPending(){return[...this.tasks.values()].filter(e=>e.status==="pending")}getAll(){return[...this.tasks.values()].map(e=>({...e}))}isTerminal(e){return e==="completed"||e==="failed"||e==="killed"}prune(e=36e5){let t=Date.now(),n=[];for(let r of this.tasks.values())if(this.isTerminal(r.status)&&r.completedAt){let s=new Date(r.completedAt).getTime();t-s>e&&n.push(r.id)}for(let r of n){this.tasks.delete(r);let s=this.order.indexOf(r);s!==-1&&this.order.splice(s,1)}return n.length}enforceLimit(){for(;this.order.length>100;){let e=this.order.shift();if(!e)continue;let t=this.tasks.get(e);if(t)if(this.isTerminal(t.status))this.tasks.delete(e);else{this.order.unshift(e);break}}}count(){return this.tasks.size}countByStatus(){let e={pending:0,running:0,completed:0,failed:0,killed:0};for(let t of this.tasks.values())e[t.status]++;return e}};kt();var qs="EVERCLAW_SUBAGENT_RESULT ";function zs(o,e){let t=new Date().toLocaleString(),n=e??"You are operating as a subagent spawned by the main agent to complete a specific task. Stay focused and concise. Complete the assigned task and report your findings.";return o?`${o}
243
+
244
+ ---
227
245
 
228
- Current Time: ${new Date().toLocaleString()}
246
+ # Subagent Mode
229
247
 
230
- You are a subagent spawned by the main agent to complete a specific task. Stay focused and concise.`}async function lo(o){let e=ar({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:Ya()},{role:"user",content:o.task}],n="Task completed but no final response was generated.";for(let r=0;r<15;r++){Q(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(Q(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){Q(o.signal);let a=await e.execute(i.name,i.arguments,o.signal?{signal:o.signal}:{});Q(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 Xa(){let o=process.argv[1]??"";return Ot(o)}function Qa(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 Za(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(ws));if(e)try{return JSON.parse(e.slice(ws.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:Qa(o),failureAttribution:o.failureAttribution}}var lr=class{constructor(e=new be,t=Xa){this.runner=e;this.resolveCommand=t}async execute(e){if(yt("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 Za(s)}},cr=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 lo({...e,provider:e.provider,existingMessages:t})}}catch(t){return te(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},dr=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=Va().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s);let i=e.mode??"process",a=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName).finally(()=>{this.running.delete(t),this.controllers.delete(t);let l=this.sessionTasks.get(e.sessionKey);l&&(l.delete(t),l.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,a),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l){let c=this.controllers.get(e)?.signal,d=s==="inline"?this.inlineExecutor:this.processExecutor;try{let p={...this.settings,task:t};c&&(p.signal=c),i&&(p.provider=i),a&&(p.model=a),l&&(p.providerName=l);let h=await d.execute(p);if(h.status==="aborted"||!this.isSessionCurrent(r.sessionKey,r.generation))return;await this.publishOutcome(r,t,n,h)}catch(p){if(te(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]
248
+ Current Time: ${t}
231
249
 
232
- Task: ${t}
250
+ ${n}`:`# Subagent
233
251
 
234
- Result:
235
- ${r.finalResult??"Task completed but no final response was generated."}
252
+ Current Time: ${t}
236
253
 
237
- Summarize this naturally for the user. Keep it brief (1-2 sentences).`:`[Subagent '${n}' failed]
254
+ ${n}`}async function Ao(o){let e=Sr({workspace:o.workspace,restrictToWorkspace:o.restrictToWorkspace,braveApiKey:o.braveApiKey,execConfig:o.execConfig}),t=o.definition;t?.allowedTools&&t.allowedTools.length>0?e=e.filterByNames(t.allowedTools):t?.deniedTools&&t.deniedTools.length>0&&(e=e.excludeByNames(t.deniedTools));let n=t?.systemPromptSuffix,r;if(o.contextMode==="fork"&&o.existingMessages?.length){let i=n?`# Subagent Mode
238
255
 
239
- Task: ${t}
256
+ ${n}`:`# Subagent Mode
240
257
 
241
- Error:
242
- ${r.errorMessage??"The isolated subagent failed before producing a result."}
258
+ You are operating as a subagent spawned by the main agent to complete a specific task. Stay focused and concise. Complete the assigned task and report your findings.`;r=o.existingMessages.map((a,l)=>l===0&&a.role==="system"&&typeof a.content=="string"?{...a,content:`${a.content}
243
259
 
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 ur=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 co(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import $e from"node:fs";import gr from"node:path";De();function Bt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function vs(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function el(o){try{let e=JSON.parse(o);return Bt(e)?"metadata"in e||"last_consolidated"in e?{metadata:Bt(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 mr=class o{key;messages=[];createdAt=ae();updatedAt=ae();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let d=this.messages[c];if(d?._type==="anchor"){n=d,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(p=>p.role==="tool"||p.tool_calls&&Array.isArray(p.tool_calls))||(i=i.slice(a)));let l=[];n&&l.push({role:"system",content:`[Context anchor: ${n.name}${n.summary?` \u2014 ${n.summary}`:""}]`,_type:"anchor_marker"});for(let c of i){let d={role:c.role,content:c.content??""};for(let p of["tool_calls","tool_call_id","name"])p in c&&(d[p]=c[p]);l.push(d)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=ae()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:ae()};return this.messages.push(n),this.updatedAt=ae(),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=ae(),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)}}},et=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=Xe(gr.join(e,"sessions")),this.workspaceKey=t.workspaceKey??gr.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return gr.join(this.sessionsDir,`${jo(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Ne({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=Bt(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=el(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=vs(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
260
+ ---
261
+
262
+ ${i}`}:a),r.push({role:"user",content:o.task})}else o.contextMode==="inherit-system"&&o.parentSystemPrompt?r=[{role:"system",content:zs(o.parentSystemPrompt,n)},{role:"user",content:o.task}]:r=o.existingMessages?[...o.existingMessages,{role:"user",content:o.task}]:[{role:"system",content:zs(void 0,n)},{role:"user",content:o.task}];let s="Task completed but no final response was generated.";for(let i=0;i<15;i++){te(o.signal);let a=await o.provider.chat({messages:r,tools:e.getDefinitions(),model:o.model,temperature:o.temperature,maxTokens:o.maxTokens,...o.signal?{signal:o.signal}:{}});if(te(o.signal),a.toolCalls.length){r.push({role:"assistant",content:a.content??"",tool_calls:a.toolCalls.map(l=>({id:l.id,type:"function",function:{name:l.name,arguments:JSON.stringify(l.arguments)}}))});for(let l of a.toolCalls){te(o.signal);let c=await e.execute(l.name,l.arguments,o.signal?{signal:o.signal}:{});te(o.signal);let d=typeof c=="object"&&"kind"in c?c.content??String(c):String(c);r.push({role:"tool",tool_call_id:l.id,name:l.name,content:d})}continue}s=a.content??s;break}return s}function Fl(){let o=process.argv[1]??"";return Gt(o)}function Bl(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 Ul(o){let e=o.stdout.split(/\r?\n/).reverse().find(t=>t.startsWith(qs));if(e)try{return JSON.parse(e.slice(qs.length))}catch{return{status:"failed",errorMessage:"Isolated subagent returned an invalid result payload.",failureAttribution:"protocol"}}return o.status==="aborted"?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:Bl(o),failureAttribution:o.failureAttribution}}var Cr=class{constructor(e=new ve,t=Fl){this.runner=e;this.resolveCommand=t}async execute(e){if(St("subagent").mode!=="local-process")return{status:"failed",errorMessage:"Subagent isolation policy did not resolve to local-process execution.",failureAttribution:"protocol"};let n=this.resolveCommand(),r={command:{kind:"argv",file:n.file,args:n.args},cwd:e.workspace,env:{...n.env},stdinText:JSON.stringify({task:e.task,workspace:e.workspace,model:e.model,temperature:e.temperature,maxTokens:e.maxTokens,braveApiKey:e.braveApiKey,execConfig:e.execConfig,restrictToWorkspace:e.restrictToWorkspace,allowedTools:e.allowedTools,providerName:e.providerName}),maxCaptureBytes:1024*1024};e.signal&&(r.signal=e.signal);let s=await this.runner.run(r);return Ul(s)}},xr=class{sessionManager;constructor(e){this.sessionManager=e}async execute(e){if(!e.provider)return{status:"failed",errorMessage:"Inline subagent execution requires a provider to be provided.",failureAttribution:"protocol"};try{let t,n=e.contextMode??"fresh";if(n==="fork"&&e.sessionKey)if(!this.sessionManager)console.error(`[subagent] sessionKey "${e.sessionKey}" provided but no sessionManager available \u2014 subagent will run without parent context`);else{let a=this.sessionManager.getOrCreate(e.sessionKey);a&&(t=a.fork().getHistory())}let r=e.agentType?So(e.agentType):void 0,s={...e,provider:e.provider,existingMessages:t,contextMode:n,...e.parentSystemPrompt?{parentSystemPrompt:e.parentSystemPrompt}:{},...r?{definition:r}:{}};return{status:"completed",finalResult:await Ao(s)}}catch(t){return se(t)?{status:"aborted",errorMessage:null,failureAttribution:"aborted"}:{status:"failed",errorMessage:t instanceof Error?t.message:String(t),failureAttribution:"exception"}}}},Tr=class{constructor(e,t,n,r){this.bus=e;this.processExecutor=t;this.inlineExecutor=n;this.settings=r}running=new Map;controllers=new Map;sessionTasks=new Map;sessionGenerations=new Map;taskTracker=new kr;getTaskTracker(){return this.taskTracker}getTaskSnapshot(){return this.taskTracker.prune(),this.taskTracker.getAll()}async spawn(e){let t=jl().slice(0,8),n=e.label??(e.task.length>30?`${e.task.slice(0,30)}...`:e.task),r=this.getSessionGeneration(e.sessionKey),s=new AbortController;this.controllers.set(t,s),this.taskTracker.register(t,"subagent",n,e.sessionKey);let i=e.mode??"process",a=e.agentType?So(e.agentType):void 0,l=this.runSubagent(t,e.task,n,{channel:e.originChannel,chatId:e.originChatId,sessionKey:e.sessionKey,generation:r},i,e.provider,e.model,e.providerName,e.contextMode,e.parentSystemPrompt,a).finally(()=>{this.running.delete(t),this.controllers.delete(t);let c=this.sessionTasks.get(e.sessionKey);c&&(c.delete(t),c.size||this.sessionTasks.delete(e.sessionKey))});return this.running.set(t,l),this.sessionTasks.has(e.sessionKey)||this.sessionTasks.set(e.sessionKey,new Set),this.sessionTasks.get(e.sessionKey).add(t),`Subagent [${n}] started (id: ${t}). I'll notify you when it completes.`}async runSubagent(e,t,n,r,s="process",i,a,l,c,d,p){let g=this.controllers.get(e)?.signal,x=s==="inline"?this.inlineExecutor:this.processExecutor;this.taskTracker.transition(e,"running");try{let y={...this.settings,task:t};g&&(y.signal=g),i&&(y.provider=i),a&&(y.model=a),l&&(y.providerName=l),c&&(y.contextMode=c),d&&(y.parentSystemPrompt=d),p&&(y.agentType=p.name);let u=await x.execute(y);if(u.status==="aborted"){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}u.status==="completed"?this.taskTracker.transition(e,"completed",u.finalResult??void 0):this.taskTracker.transition(e,"failed",void 0,u.errorMessage??void 0),await this.publishOutcome(r,t,n,u,e)}catch(y){if(se(y)){this.taskTracker.transition(e,"killed");return}if(!this.isSessionCurrent(r.sessionKey,r.generation)){this.taskTracker.transition(e,"killed");return}let u=y instanceof Error?y.message:String(y);this.taskTracker.transition(e,"failed",void 0,u);try{await this.publishOutcome(r,t,n,{status:"failed",errorMessage:u,failureAttribution:"exception"},e)}catch{}}}async publishOutcome(e,t,n,r,s){let i={kind:r.status==="completed"?"subagent_completed":"subagent_failed",taskId:s,label:n,status:r.status==="completed"?"completed":"failed",originalTask:t,...r.finalResult?{result:r.finalResult}:{},...r.errorMessage?{error:r.errorMessage}:{}},a=r.status==="completed"?r.finalResult??"Task completed.":r.errorMessage??"Subagent failed.",l={channel:"system",senderId:"subagent",chatId:`${e.channel}:${e.chatId}`,content:a,metadata:{_notification:i}};await this.bus.publishInbound(l)}async cancelBySession(e){this.sessionGenerations.set(e,this.getSessionGeneration(e)+1);let t=[...this.sessionTasks.get(e)??[]],n=0;for(let r of t){let s=this.controllers.get(r);!s||s.signal.aborted||(s.abort(),n+=1)}return n}async cancelAll(){let e=[...this.sessionTasks.keys()],t=0;for(let n of e)t+=await this.cancelBySession(n);return t}getRunningCount(){return this.running.size}getSessionGeneration(e){return this.sessionGenerations.get(e)??0}isSessionCurrent(e,t){return this.getSessionGeneration(e)===t}};var Rr=class{constructor(e=4,t=1){this.maxConcurrency=e;this.maxQueuedPerKey=t}states=new Map;readyKeys=[];readySet=new Set;inFlight=0;backpressured=0;lastBackpressureAt=null;enqueue(e,t,n={}){let r=this.getOrCreateState(e),s=r.generation;return!n.bypassCapacity&&r.queued.length>=this.maxQueuedPerKey?(this.backpressured+=1,this.lastBackpressureAt=new Date().toISOString(),this.cleanup(e),Promise.resolve({status:"rejected",reason:"backpressure"})):new Promise((i,a)=>{r.queued.push({generation:s,execute:t,resolve:i,reject:a}),r.running||this.queueKey(e),this.pump()})}cancel(e){let t=this.states.get(e);if(!t)return{running:!1,queued:0};t.generation+=1;let n=t.queued.length;for(let r of t.queued)r.resolve({status:"cancelled"});return t.queued=[],this.removeReadyKey(e),this.cleanup(e),{running:t.running,queued:n}}snapshot(){let e=[...this.states.entries()].map(([t,n])=>({key:t,running:n.running,queued:n.queued.length})).filter(t=>t.running||t.queued>0).sort((t,n)=>t.key.localeCompare(n.key));return{maxConcurrency:this.maxConcurrency,maxQueuedPerKey:this.maxQueuedPerKey,running:e.filter(t=>t.running).length,queued:e.reduce((t,n)=>t+n.queued,0),backpressured:this.backpressured,lastBackpressureAt:this.lastBackpressureAt,sessions:e}}getOrCreateState(e){let t=this.states.get(e);return t||(t={generation:0,running:!1,queued:[]},this.states.set(e,t)),t}isCurrent(e,t){return this.states.get(e)?.generation===t}queueKey(e){this.readySet.has(e)||(this.readySet.add(e),this.readyKeys.push(e))}removeReadyKey(e){if(!this.readySet.delete(e))return;let t=this.readyKeys.indexOf(e);t>=0&&this.readyKeys.splice(t,1)}cleanup(e){let t=this.states.get(e);!t||t.running||t.queued.length||this.states.delete(e)}pump(){for(;this.inFlight<this.maxConcurrency&&this.readyKeys.length;){let e=this.readyKeys.shift();this.readySet.delete(e);let t=this.states.get(e);if(!t||t.running||!t.queued.length){this.cleanup(e);continue}let n=t.queued.shift();t.running=!0,this.inFlight+=1,(async()=>{try{if(!this.isCurrent(e,n.generation)){n.resolve({status:"cancelled"});return}let r=await n.execute({isCurrent:()=>this.isCurrent(e,n.generation)});this.isCurrent(e,n.generation)?n.resolve({status:"completed",value:r}):n.resolve({status:"cancelled"})}catch(r){n.reject(r)}finally{let r=this.states.get(e);r&&(r.running=!1,r.queued.length&&this.queueKey(e),this.cleanup(e)),this.inFlight-=1,this.pump()}})()}}};function Eo(o){return o.sessionKeyOverride??`${o.channel}:${o.chatId}`}import Le from"node:fs";import Ar from"node:path";je();function qt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Vs(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Gl(o){try{let e=JSON.parse(o);return qt(e)?"metadata"in e||"last_consolidated"in e?{metadata:qt(e.metadata)?e.metadata:{},lastConsolidated:typeof e.last_consolidated=="number"?e.last_consolidated:0}:{metadata:e,lastConsolidated:0}:{metadata:{},lastConsolidated:0}}catch{return{metadata:{},lastConsolidated:0}}}var Er=class o{key;messages=[];createdAt=le();updatedAt=le();metadata={};lastConsolidated=0;constructor(e){this.key=e}getHistory(e=500){let t=0,n=null;for(let c=this.messages.length-1;c>=0;c--){let d=this.messages[c];if(d?._type==="anchor"){n=d,t=c;break}}let i=this.messages.slice(t).filter(c=>c._type!=="anchor").slice(-e),a=i.findIndex(c=>c.role==="user");a>0&&(i.slice(0,a).some(p=>p.role==="tool"||p.tool_calls&&Array.isArray(p.tool_calls))||(i=i.slice(a)));let l=[];n&&l.push({role:"system",content:`[Context anchor: ${n.name}${n.summary?` \u2014 ${n.summary}`:""}]`,_type:"anchor_marker"});for(let c of i){let d={role:c.role,content:c.content??""};for(let p of["tool_calls","tool_call_id","name"])p in c&&(d[p]=c[p]);l.push(d)}return l}clear(){this.messages=[],this.lastConsolidated=0,this.updatedAt=le()}anchor(e,t){let n={_type:"anchor",name:e,summary:t,timestamp:le()};return this.messages.push(n),this.updatedAt=le(),n}getLastAnchor(){for(let e=this.messages.length-1;e>=0;e--){let t=this.messages[e];if(t&&t._type==="anchor")return t}return null}fork(){let e=new o(this.key);return e.messages=[...this.messages],e.createdAt=this.createdAt,e.updatedAt=this.updatedAt,e.metadata={...this.metadata},e.lastConsolidated=this.lastConsolidated,e}merge(e){if(e.key!==this.key)throw new Error("Cannot merge sessions with different keys");let t=e.messages.slice(this.messages.length);this.messages.push(...t),this.updatedAt=le(),this.metadata={...this.metadata,...e.metadata}}getMessagesSinceLastAnchor(){let e=-1;for(let t=this.messages.length-1;t>=0;t--)if(this.messages[t]?._type==="anchor"){e=t;break}return e===-1?this.messages:this.messages.slice(e+1)}search(e,t=10){let n=e.toLowerCase(),r=[];for(let s of this.messages){if(s._type==="anchor")continue;let i=typeof s.content=="string"?s.content:JSON.stringify(s.content),a=i.toLowerCase(),l=a.indexOf(n);if(l!==-1){let c={role:String(s.role??"unknown"),content:i,score:a.length-n.length+l};typeof s.timestamp=="string"&&(c.timestamp=s.timestamp),r.push(c)}}return r.sort((s,i)=>s.score-i.score),{query:e,results:r.slice(0,t)}}},ot=class{sessionsDir;cache=new Map;storage=null;workspaceKey;dataDir;legacyIndexHydrated=!1;constructor(e,t={}){this.sessionsDir=tt(Ar.join(e,"sessions")),this.workspaceKey=t.workspaceKey??Ar.resolve(e),t.dataDir&&(this.dataDir=t.dataDir)}getSessionPath(e){return Ar.join(this.sessionsDir,`${cs(e.replace(":","_"))}.jsonl`)}getStorage(){return this.storage||(this.storage=Fe({dataDir:this.dataDir})),this.storage}applyMetadata(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt,e.metadata=qt(t.metadata)?t.metadata:{},e.lastConsolidated=typeof t.last_consolidated=="number"?t.last_consolidated:0}applyPersistedRow(e,t){e.createdAt=t.created_at??e.createdAt,e.updatedAt=t.updated_at??e.updatedAt;let n=Gl(t.metadata_json);e.metadata=n.metadata,e.lastConsolidated=n.lastConsolidated}persistSessionIndex(e){let{channel:t,chatId:n}=Vs(e.key);this.getStorage().prepare(`INSERT INTO session_metadata (
245
263
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
246
264
  ) VALUES (?, ?, ?, ?, ?, ?, ?)
247
265
  ON CONFLICT(workspace, session_key) DO UPDATE SET
@@ -249,116 +267,142 @@ Summarize this naturally for the user. Keep it brief (1-2 sentences).`,i={channe
249
267
  chat_id = excluded.chat_id,
250
268
  created_at = excluded.created_at,
251
269
  updated_at = excluded.updated_at,
252
- metadata_json = excluded.metadata_json`).run(this.workspaceKey,e.key,t,n,e.createdAt,e.updatedAt,JSON.stringify({metadata:e.metadata,last_consolidated:e.lastConsolidated}))}readLegacySessionMetadata(e){if(!$e.existsSync(e))return null;try{let t=$e.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return Bt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!$e.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
270
+ 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(!Le.existsSync(e))return null;try{let t=Le.readFileSync(e,"utf8").split(/\r?\n/,1)[0];if(!t)return null;let n=JSON.parse(t);return qt(n)&&n._type==="metadata"?n:null}catch{return null}}hydrateLegacyIndex(){if(this.legacyIndexHydrated||(this.legacyIndexHydrated=!0,!Le.existsSync(this.sessionsDir)))return;let e=this.getStorage().prepare(`INSERT OR IGNORE INTO session_metadata (
253
271
  workspace, session_key, channel, chat_id, created_at, updated_at, metadata_json
254
- ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of $e.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=gr.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=vs(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??ae(),r.updated_at??r.created_at??ae(),JSON.stringify({metadata:Bt(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
272
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)`);for(let t of Le.readdirSync(this.sessionsDir)){if(!t.endsWith(".jsonl"))continue;let n=Ar.join(this.sessionsDir,t),r=this.readLegacySessionMetadata(n);if(!r?.key)continue;let{channel:s,chatId:i}=Vs(r.key);e.run(this.workspaceKey,r.key,s,i,r.created_at??le(),r.updated_at??r.created_at??le(),JSON.stringify({metadata:qt(r.metadata)?r.metadata:{},last_consolidated:typeof r.last_consolidated=="number"?r.last_consolidated:0}))}}readPersistedRow(e){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT created_at, updated_at, metadata_json
255
273
  FROM session_metadata
256
- WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!$e.existsSync(t))return null;try{let r=$e.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let d=JSON.parse(c);if(!i&&Bt(d)&&d._type==="metadata"){i=d;continue}s.push(d)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new mr(e);return this.cache.set(e,n),n}save(e){let t=this.getSessionPath(e.key),n=`${t}.tmp`,r={_type:"metadata",key:e.key,created_at:e.createdAt,updated_at:e.updatedAt,metadata:e.metadata,last_consolidated:e.lastConsolidated},s=[JSON.stringify(r),...e.messages.map(i=>JSON.stringify(i))];try{$e.writeFileSync(n,`${s.join(`
274
+ WHERE workspace = ? AND session_key = ?`).get(this.workspaceKey,e)??null}readTranscript(e){let t=this.getSessionPath(e);if(!Le.existsSync(t))return null;try{let r=Le.readFileSync(t,"utf8").split(/\r?\n/).filter(Boolean),s=[],i=null,a=0;for(let l=0;l<r.length;l++){let c=r[l];try{let d=JSON.parse(c);if(!i&&qt(d)&&d._type==="metadata"){i=d;continue}s.push(d)}catch{a++,console.warn(`[session] Skipping corrupt line ${l+1} in ${t}`)}}return{metadata:i,messages:s,skipped:a}}catch{return null}}getOrCreate(e){let t=this.cache.get(e);if(t)return t;let n=this.load(e)??new Er(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{Le.writeFileSync(n,`${s.join(`
257
275
  `)}
258
- `,"utf8"),$e.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{$e.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return $e.existsSync(t)&&($e.unlinkSync(t),n=!0),this.getStorage().prepare("DELETE FROM session_metadata WHERE workspace = ? AND session_key = ?").run(this.workspaceKey,e),this.cache.delete(e),n}listSessions(){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT session_key, created_at, updated_at
276
+ `,"utf8"),Le.renameSync(n,t),this.persistSessionIndex(e),this.cache.set(e.key,e)}catch(i){try{Le.unlinkSync(n)}catch{}throw i}}invalidate(e){this.cache.delete(e)}delete(e){let t=this.getSessionPath(e),n=!1;return Le.existsSync(t)&&(Le.unlinkSync(t),n=!0),this.getStorage().prepare("DELETE FROM session_metadata WHERE workspace = ? AND session_key = ?").run(this.workspaceKey,e),this.cache.delete(e),n}listSessions(){return this.hydrateLegacyIndex(),this.getStorage().prepare(`SELECT session_key, created_at, updated_at
259
277
  FROM session_metadata
260
278
  WHERE workspace = ?
261
- ORDER BY updated_at DESC, session_key`).all(this.workspaceKey).map(t=>({key:t.session_key,created_at:t.created_at,updated_at:t.updated_at,path:this.getSessionPath(t.session_key)}))}load(e){let t=this.readPersistedRow(e),n=this.readTranscript(e);if(!t&&!n)return null;let r=new mr(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};It();var tl=[{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"}],nl=/<\/?[a-zA-Z][^>]*\/?>/g,pr=class{config;constructor(e){this.config=e}sanitize(e){if(!this.config.enabled)return{safe:!1,sanitized:String(e??""),warnings:[]};let t=typeof e=="string"?e:String(e??""),n=[];if(t.length>this.config.maxInputLength&&(t=t.slice(0,this.config.maxInputLength),n.push(`Input truncated from ${typeof e=="string"?e.length:0} to ${this.config.maxInputLength} characters (maxInputLength).`)),this.config.stripHtmlTags){let r=t;t=t.replace(nl,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of tl)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};It();le();function cn(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 Ss(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function ks(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var fr=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",Ss(this.options.providerLabel??"")]).has(Ss(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:cn(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:ks(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 cn(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:ks(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 Q(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(te(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as rl}from"nanoid";var hr=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let d=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let p of d){let h=p.function;h?.name&&l.push({functionCall:{name:h.name,args:this.parseToolArgs(h.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
279
+ 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 Er(e);return t?this.applyPersistedRow(r,t):n?.metadata&&(this.applyMetadata(r,n.metadata),this.persistSessionIndex(r)),n&&(r.messages=n.messages),r}};Lt();var Wl=[{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"}],Kl=/<\/?[a-zA-Z][^>]*\/?>/g,Pr=class{config;constructor(e){this.config=e}sanitize(e){if(!this.config.enabled)return{safe:!1,sanitized:String(e??""),warnings:[]};let t=typeof e=="string"?e:String(e??""),n=[];if(t.length>this.config.maxInputLength&&(t=t.slice(0,this.config.maxInputLength),n.push(`Input truncated from ${typeof e=="string"?e.length:0} to ${this.config.maxInputLength} characters (maxInputLength).`)),this.config.stripHtmlTags){let r=t;t=t.replace(Kl,""),t!==r&&n.push("HTML tags were stripped from input.")}if(this.config.blockPromptInjection)for(let{pattern:r,label:s}of Wl)r.test(t)&&(n.push(`Potential prompt injection detected: ${s}`),r.lastIndex=0);return{safe:!0,sanitized:t,warnings:n}}};Lt();de();function yn(o){return o.map(e=>{let t=e.content;if(typeof t=="string"&&t.length===0)return e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"};if(Array.isArray(t)){let n=t.filter(r=>!(typeof r=="object"&&r&&["text","input_text","output_text"].includes(r.type)&&!r.text));if(n.length!==t.length)return n.length>0?{...e,content:n}:e.role==="assistant"&&e.tool_calls?{...e,content:null}:{...e,content:"(empty)"}}return e})}function Xs(o){return o.trim().toLowerCase().replace(/[\s-]+/g,"_")}function Ys(o){if(typeof o!="string")return o&&typeof o=="object"?o:{};try{return JSON.parse(o)}catch{return{}}}var _r=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",Xs(this.options.providerLabel??"")]).has(Xs(r))?s:t}buildHeaders(){let e={"Content-Type":"application/json",...this.options.extraHeaders??{}};return this.apiKey.trim()&&(e.Authorization=`Bearer ${this.apiKey}`),e}async readJson(e){try{return await e.json()}catch{return{}}}async chatCompletions(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),messages:yn(e.messages),tools:e.tools,tool_choice:e.tools?.length?"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:Ys(i.function.arguments)}));return{content:r.message.content??null,toolCalls:s,finishReason:r.finish_reason??"stop",usage:{prompt_tokens:n.usage?.prompt_tokens??0,completion_tokens:n.usage?.completion_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:r.message.reasoning_content??null}}toResponsesInput(e){let t=[];for(let n of yn(e)){let r=String(n.role??"");if(r==="tool"){t.push({type:"function_call_output",call_id:String(n.tool_call_id??""),output:typeof n.content=="string"?n.content:JSON.stringify(n.content??null)});continue}if(r==="assistant"&&Array.isArray(n.tool_calls))for(let s of n.tool_calls)t.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:typeof s.arguments=="string"?s.arguments:JSON.stringify(s.arguments??{})});(r==="system"||r==="user"||r==="assistant")&&t.push({role:r,content:n.content??""})}return t}async responses(e){let t=await fetch(`${this.apiBase.replace(/\/$/,"")}/responses`,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:this.resolveModel(e.model??this.defaultModel),input:this.toResponsesInput(e.messages),tools:e.tools,tool_choice:e.tools?.length?"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:Ys(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(`
280
+ `).trim()||null,toolCalls:s,finishReason:s.length?"tool_calls":n.status??"stop",usage:{prompt_tokens:n.usage?.input_tokens??0,completion_tokens:n.usage?.output_tokens??0,total_tokens:n.usage?.total_tokens??0},reasoningContent:null}}async chat(e){try{return te(e.signal),this.requestFormat==="v1/responses"?await this.responses(e):await this.chatCompletions(e)}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Hl}from"nanoid";var Mr=class o{constructor(e,t,n){this.apiKey=e;this.apiBase=t;this.defaultModel=n}static DEFAULT_BASE="https://generativelanguage.googleapis.com/v1beta";getDefaultModel(){return this.defaultModel}resolveModel(e){let t=e.trim();if(t.includes("/")){let n=t.split("/",2),r=n[0],s=n[1];if(!r||!s)return t;let i=r.toLowerCase();(i==="gemini"||i==="google")&&(t=s)}return t.startsWith("models/")?t.slice(7):t}asText(e){if(typeof e=="string")return e;if(e==null)return"";try{return JSON.stringify(e)}catch{return String(e)}}parseToolArgs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t))return t}catch{}return{}}toGemini(e){let t=[],n=[];for(let i of e.messages){let a=String(i.role??"");if(a==="system"){let l=this.asText(i.content).trim();l&&t.push(l);continue}if(a==="user"){let l=this.asText(i.content).trim();if(!l)continue;n.push({role:"user",parts:[{text:l}]});continue}if(a==="assistant"||a==="model"){let l=[],c=this.asText(i.content).trim();c&&l.push({text:c});let d=Array.isArray(i.tool_calls)?i.tool_calls:[];for(let p of d){let g=p.function;g?.name&&l.push({functionCall:{name:g.name,args:this.parseToolArgs(g.arguments)}})}l.length&&n.push({role:"model",parts:l});continue}if(a==="tool"){let l=typeof i.name=="string"?i.name:"";if(!l)continue;let c=this.asText(i.content);n.push({role:"user",parts:[{functionResponse:{name:l,response:{result:c}}}]})}}n.length||n.push({role:"user",parts:[{text:"Hello"}]});let r={contents:n,generationConfig:{temperature:e.temperature??.1,maxOutputTokens:Math.max(1,e.maxTokens??4096),...e.reasoning?{thinkingConfig:{thinkingBudget:Math.max(1,e.maxTokens??4096)}}:{}}};t.length&&(r.systemInstruction={parts:[{text:t.join(`
281
+
282
+ `)}]});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{te(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],d=c.filter(y=>typeof y?.text=="string").map(y=>String(y.text)),p=c.filter(y=>y?.functionCall?.name).map(y=>({id:Hl(9),name:String(y.functionCall.name),arguments:this.parseToolArgs(y.functionCall.args)})),g={};a?.usageMetadata&&(g.prompt_tokens=Number(a.usageMetadata.promptTokenCount??0),g.completion_tokens=Number(a.usageMetadata.candidatesTokenCount??0),g.total_tokens=Number(a.usageMetadata.totalTokenCount??0));let x=String(l?.finishReason??"STOP").toLowerCase();return{content:d.length?d.join(`
283
+ `):null,toolCalls:p,finishReason:x,usage:g,reasoningContent:null}}catch(t){if(se(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as Jl}from"nanoid";de();var Ir=class o{constructor(e,t,n,r){this.apiKey=e;this.apiBase=t;this.defaultModel=n;this.providerName=r}static DEFAULT_BASE_BY_PROVIDER={openrouter:"https://openrouter.ai/api/v1",openai:"https://api.openai.com/v1",deepseek:"https://api.deepseek.com/v1",groq:"https://api.groq.com/openai/v1",moonshot:"https://api.moonshot.ai/v1",minimax:"https://api.minimax.io/v1",dashscope:"https://dashscope.aliyuncs.com/compatible-mode/v1",zhipu:"https://open.bigmodel.cn/api/paas/v4",siliconflow:"https://api.siliconflow.cn/v1",volcengine:"https://ark.cn-beijing.volces.com/api/v3",vllm:"http://localhost:8000/v1",ollama:"http://localhost:11434/v1",zai:"https://api.z.ai/api/coding/paas/v4"};static UNSUPPORTED_PROVIDERS=new Set(["anthropic","gemini","openai_codex","github_copilot"]);getDefaultModel(){return this.defaultModel}resolveModel(e){let t=n=>n.toLowerCase().replace(/-/g,"_");if(e.includes("/")){let n=e.split("/",2),r=n[0],s=n[1];if(!r||!s)return e;if(t(r)==="github_copilot")return`github_copilot/${s}`;if(t(r)==="openai_codex")return`openai_codex/${s}`;if(t(r)==="groq")return s==="compound"||s==="compound-mini"?`groq/${s}`:s;if(t(r)==="ollama")return s}return e}async chat(e){let n={model:this.resolveModel(e.model??this.defaultModel),messages:yn(e.messages),max_tokens:Math.max(1,e.maxTokens??4096),temperature:e.temperature??.7};e.tools?.length&&(n.tools=e.tools,n.tool_choice="auto"),e.reasoning&&(n.reasoning_effort="medium"),e.imageOutput&&(n.include_image_output=!0);try{te(e.signal);let r=(this.providerName??"").trim();if(r&&o.UNSUPPORTED_PROVIDERS.has(r))return{content:`Error calling LLM: provider '${r}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let s=this.apiBase??(r?o.DEFAULT_BASE_BY_PROVIDER[r]:void 0)??(this.apiKey?.startsWith("sk-or-")?o.DEFAULT_BASE_BY_PROVIDER.openrouter:void 0);if(!s)return{content:`Error calling LLM: api_base not configured. Set provider/api_base in ${pt} or run everclaw onboard.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(`${s.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(n),...e.signal?{signal:e.signal}:{}}),l=await a.json();if(!a.ok){let p=l?.error?.code??"",g=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${g}
284
+ ${r==="groq"?"Try a Groq-supported model like llama-3.3-70b-versatile or openai/gpt-oss-120b. You can run `everclaw doctor`.":"Check your model id and provider access. You can run `everclaw doctor`."}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}:{content:`Error calling LLM: ${g}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let d=(c.message.tool_calls??[]).map(p=>({id:Jl(9),name:p.function.name,arguments:typeof p.function.arguments=="string"?JSON.parse(p.function.arguments||"{}"):p.function.arguments}));return{content:c.message.content??null,toolCalls:d,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(se(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function Ne(o){let e=o.agents.defaults.model,t=nt(o,e),n=ys(o,e),r=t&&ht(t)?Ot(o,t,e):null,s=new Set(["openai_codex","github_copilot"]),i=new Set(["anthropic"]);if(!t)throw new Error("No provider could be resolved from config. Run `everclaw onboard` and set provider/model/API key.");if(ht(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${pt}.`);if(i.has(t))throw new Error(`Provider '${t}' is not supported in this TypeScript port yet. Use openrouter/openai/deepseek/groq/custom.`);if(!s.has(t)&&t!=="vllm"&&t!=="custom"&&!ht(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${pt}.`);return t==="custom"||ht(t)?new _r(n?.apiKey||r?.apiKey||"no-key",Bn(o,e)||r?.baseUrl||"http://localhost:8000/v1",e,{providerLabel:r?.name??t,apiFormat:r?.apiFormat,extraHeaders:r?.extraHeaders??n?.extraHeaders??null}):t==="gemini"?new Mr(n?.apiKey||"",Bn(o,e),e):new Ir(n?.apiKey??null,Bn(o,e),e,t)}wn();var Or=class extends q{constructor(t,n,r,s,i,a){super();this.serverName=t;this.remoteName=n;this.manager=a;this.name=r,this.description=s,this.parameters=i}name;description;parameters;validateParams(t){return[]}async execute(t,n){return this.manager.callTool(this.serverName,this.remoteName,t,n)}};jt();vn();jt();vn();function Tt(o,e){let t=Math.max(0,o.length-e);for(;t>0&&o[t]?.role==="tool";)t--;return o.slice(t)}function ni(){return`Your task is to create a detailed summary of the conversation so far.
285
+ This summary should capture all technical details essential for continuing work.
286
+
287
+ Respond with TEXT ONLY. Do NOT call any tools.
288
+
289
+ Your summary should include:
290
+
291
+ 1. Primary Request and Intent: The user's explicit requests
292
+ 2. Key Technical Context: Important concepts, technologies, decisions
293
+ 3. Files and Code: Files examined/modified with relevant snippets
294
+ 4. Errors and Fixes: Problems encountered and solutions
295
+ 5. Tool Results: Key outputs from tool calls that informed decisions
296
+ 6. Pending Tasks: Outstanding work items
297
+ 7. Current Work: What was being worked on immediately before this summary
298
+ 8. Next Step: The immediate next action to take
299
+
300
+ Wrap your analysis in <analysis> tags, then provide the summary in <summary> tags.`}function ri(o){let e=o.match(/<summary>([\s\S]*?)<\/summary>/);return e?.[1]?e[1].trim():o.match(/<analysis>([\s\S]*?)<\/analysis>/)?o.slice(o.indexOf("</analysis>")+11).trim()||o:o.trim()}function oi(o){let e=[`## Conversation to Summarize
301
+ `];for(let t of o){let n=String(t.role??"unknown").toUpperCase();if(n!=="SYSTEM"){if(n==="USER"){let r=typeof t.content=="string"?t.content:Array.isArray(t.content)?t.content.map(s=>s.type==="text"?s.text:"[non-text content]").join(`
302
+ `):String(t.content);e.push(`[USER]: ${r}`)}else if(n==="ASSISTANT"){let r=typeof t.content=="string"?t.content:"",s=Array.isArray(t.tool_calls)?t.tool_calls.map(i=>{let a=i.function?.name??i.name??"unknown",l=i.function?.arguments??i.arguments??"{}";return`Tool: ${a}(${typeof l=="string"?l:JSON.stringify(l)})`}).join(`
303
+ `):"";e.push(`[ASSISTANT]: ${r}${s?`
304
+ ${s}`:""}`)}else if(n==="TOOL"){let r=String(t.name??"unknown"),s=typeof t.content=="string"?t.content.length>500?`${t.content.slice(0,500)}... (truncated)`:t.content:"[non-text content]";e.push(`[TOOL ${r}]: ${s}`)}}}return e.join(`
305
+
306
+ `)}function Sn(o){return{role:"user",content:`[Compacted Summary]
307
+
308
+ This session continues from a compacted conversation. Here's a summary of what happened:
263
309
 
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{Q(e.signal);let t=this.resolveModel(e.model??this.defaultModel),r=`${(this.apiBase??o.DEFAULT_BASE).replace(/\/$/,"")}/models/${encodeURIComponent(t)}:generateContent`,s=this.toGemini(e),i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":this.apiKey},body:JSON.stringify(s),...e.signal?{signal:e.signal}:{}}),a=await i.json();if(!i.ok)return{content:`Error calling LLM: ${a?.error?.message??JSON.stringify(a)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let l=a?.candidates?.[0],c=l?.content?.parts??[],d=c.filter(w=>typeof w?.text=="string").map(w=>String(w.text)),p=c.filter(w=>w?.functionCall?.name).map(w=>({id:rl(9),name:String(w.functionCall.name),arguments:this.parseToolArgs(w.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 v=String(l?.finishReason??"STOP").toLowerCase();return{content:d.length?d.join(`
265
- `):null,toolCalls:p,finishReason:v,usage:h,reasoningContent:null}}catch(t){if(te(t))throw t;return{content:`Error calling LLM: ${String(t)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};import{nanoid as ol}from"nanoid";le();var yr=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:cn(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{Q(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 ${dt} or run everclaw onboard.`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(`${s.replace(/\/$/,"")}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(n),...e.signal?{signal:e.signal}:{}}),l=await a.json();if(!a.ok){let p=l?.error?.code??"",h=l?.error?.message??JSON.stringify(l);return p==="model_not_found"?{content:`Error calling LLM: ${h}
266
- ${r==="groq"?"Try a Groq-supported model like llama-3.3-70b-versatile or openai/gpt-oss-120b. You can run `everclaw doctor`.":"Check your model id and provider access. You can run `everclaw doctor`."}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}:{content:`Error calling LLM: ${h}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}let c=l.choices?.[0]?.message?l.choices[0]:null;if(!c)return{content:`Error calling LLM: ${JSON.stringify(l)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null};let d=(c.message.tool_calls??[]).map(p=>({id:ol(9),name:p.function.name,arguments:typeof p.function.arguments=="string"?JSON.parse(p.function.arguments||"{}"):p.function.arguments}));return{content:c.message.content??null,toolCalls:d,finishReason:c.finish_reason??"stop",usage:l.usage??{},reasoningContent:c.message.reasoning_content??null}}catch(r){if(te(r))throw r;return{content:`Error calling LLM: ${String(r)}`,toolCalls:[],finishReason:"error",usage:{},reasoningContent:null}}}};function Le(o){let e=o.agents.defaults.model,t=Qe(o,e),n=Jo(o,e),r=t&&gt(t)?Pt(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(gt(t)&&!r)throw new Error(`Custom provider '${t}' could not be found. Check ${dt}.`);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"&&!gt(t)&&!(n?.apiKey||"").trim())throw new Error(`No API key configured for provider '${t}'. Run 'everclaw onboard' or edit ${dt}.`);return t==="custom"||gt(t)?new fr(n?.apiKey||r?.apiKey||"no-key",En(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 hr(n?.apiKey||"",En(o,e),e):new yr(n?.apiKey??null,En(o,e),e,t)}un();var wr=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 uo(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function cl(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function dl(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 Gt=class o{constructor(e){this.input=e;let t=xs.resolve(e.workspace);this.context=new ht(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new et(t);this.sessions=n,this.lifecycle=e.lifecycle??Ze();let r=e.model??e.provider.getDefaultModel();this.subagents=new dr(e.bus,e.subagentExecutor??new lr,e.subagentInlineExecutor??new cr(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 ur(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 dn;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=An(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=An(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=An(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:Le(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 He(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 He(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:xs.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=ar(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i){let a=[...e],l=null,c=[],d=this.input.maxIterations??40,p=i?.model??this.model,h=i?.provider??this.input.provider,v=this.isToolCallingEnabled(p),w=this.isReasoningEnabled(p),u=this.isImageOutputEnabled(p),b=v?t.getDefinitions():void 0,S=AbortSignal.timeout(12e4),N=s?AbortSignal.any([s,S]):S;for(let U=0;U<d;U++){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Q(s);let I;try{I=await h.chat({messages:a,...b?{tools:b}:{},model:p,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...w?{reasoning:!0}:{},...u?{imageOutput:!0}:{},signal:N})}catch(re){if(te(re)){if(s?.aborted)throw re;return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1}}throw re}if(Q(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let J=I.reasoningContent||cl(I.content);if(J&&n&&r()&&await n(J,{event:"thinking",thinkingContent:J,toolHint:!1}),I.toolCalls.length){let re=uo(I.content);n&&re&&r()&&await n(re,{event:"answer",toolHint:!1});let q=I.toolCalls.map(K=>({id:K.id,type:"function",function:{name:K.name,arguments:JSON.stringify(K.arguments)}}));n&&r()&&await n(this.toolHint(I.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:q.map(K=>({...K,status:"running"}))}),this.context.addAssistantMessage(a,re,q,J);for(let K of I.toolCalls){if(!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};Q(s),c.push(K.name);let V=await t.execute(K.name,K.arguments,s?{signal:s}:{});if(Q(s),!r())return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};let ie=V.kind==="cancelled"?"Task was cancelled.":V.content;if(this.context.addToolResult(a,K.id,K.name,ie),n&&r()&&await n(ie,{event:"tool_result",toolHint:!0,tool_call:{id:K.id,type:"function",function:{name:K.name,arguments:JSON.stringify(K.arguments)},status:"completed",resultPreview:dl(ie,200)??null}}),V.kind==="terminal")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!1,terminal:!0};if(V.kind==="cancelled")return{finalContent:null,toolsUsed:c,messages:a,cancelled:!0,terminal:!1};if(V.kind==="error"&&!V.retryable)break}}else{l=uo(I.content),l&&n&&r()&&await n(l,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(a,l,void 0,J);break}}return l==null&&(l=`I reached the maximum number of tool call iterations (${d}) without completing the task.`),{finalContent:l,toolsUsed:c,messages:a,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${co(e)}:`,r));this.activeDispatches.add(n),n.finally(()=>this.activeDispatches.delete(n))}}stop(){this.running=!1}beginShutdown(){this.acceptingWork=!1}async shutdown(){this.beginShutdown(),this.running=!1;let e=await this.stopAllSessions();return this.activeDispatches.size>0&&await Promise.race([Promise.allSettled(this.activeDispatches),new Promise(n=>setTimeout(n,1e4))]),await this.mcpManager.closeAll(),await this.input.bus.publishInbound({channel:"system",senderId:"system",chatId:"gateway:shutdown",content:"",metadata:{_shutdown:!0}}),e}async processDirect(e,t="cli:direct",n="cli",r="direct",s){return(await this.processDirectResult(e,t,n,r,s)).content}async processDirectResult(e,t="cli:direct",n="cli",r="direct",s,i){let a={channel:n,senderId:"user",chatId:r,content:e,sessionKeyOverride:t,...i?{metadata:i}:{}};if((typeof e=="string"?e:e.find(p=>p.type==="text")?.text??"").trim().toLowerCase()==="/stop"){let p=await this.stopSession(t);return this.makeDirectResult("completed",p?`Stopped ${p} task(s).`:"No active task to stop.")}if(!this.acceptingWork)return this.makeDirectResult("shutdown",o.SHUTDOWN_MESSAGE);let c=this.rejectIfOverloaded(a,t);if(c)return c;let d=await this.runtime.enqueue(t,({isCurrent:p})=>this.withSessionController(t,h=>this.processMessage(a,t,s,p,h,"direct")));return d.status==="completed"&&d.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(d)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(te(r))return o.CANCELLED_SENTINEL;throw r}finally{this.activeControllers.get(e)===n&&this.activeControllers.delete(e)}}resolveSessionContext(e,t){let n=e.metadata?.message_id;if(e.channel==="system"){let r=String(e.chatId),s=r.includes(":"),i=s?r.split(/:(.*)/s,2)[0]:"cli",a=s?r.split(/:(.*)/s,2)[1]:r,l={key:`${i}:${a}`,channel:i,chatId:a};return n&&(l.messageId=n),l}return{key:t??co(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=uo(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(ht.RUNTIME_CONTEXT_TAG))&&(l.timestamp||(l.timestamp=new Date().toISOString()),l.role==="assistant"&&r?.length&&i===s.length-1&&(l.tools_used=r),e.messages.push(l))}e.updatedAt=new Date().toISOString()}sanitizeInput(e,t){if(!t.security?.enabled||!t.security.inputSanitizer?.enabled)return e;let n=new pr(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){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:
310
+ ${o}`}}async function kn(o,e,t){let n=ni(),r=oi(o),i=(await e.chat({model:t,messages:[{role:"system",content:n},{role:"user",content:r}],maxTokens:16384})).content||"";return ri(i)}var si=.8,ii=.6,ai=3,li=10,_o={consecutiveFailures:0,lastCompactAt:null,totalCompactions:0};async function Mo(o,e,t,n,r){let s=n?.compaction?.autoCompactThresholdRatio??si,i=n?.compaction?.keepRecentMessages??li,a=n?.compaction?.maxConsecutiveFailures??ai,l=He(o),c=Dt(t,n);if(l<c*s)return{compacted:!1,messages:o,method:"none",tokensBefore:l,tokensAfter:l,tokensFreed:0};if(r.consecutiveFailures>=a)return{compacted:!1,messages:o,method:"failed",tokensBefore:l,tokensAfter:l,tokensFreed:0};let d=Lr(o,i),p=He(d.messages);if(p<c*s)return{compacted:!0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p};try{let g=await kn(o,e,t),x=Sn(g),y=o.find(S=>S.role==="system"),u=Tt(o,i),b=[];y&&b.push(y),b.push(x),b.push(...u);let R=He(b);return r.consecutiveFailures=0,r.lastCompactAt=new Date().toISOString(),r.totalCompactions++,{compacted:!0,messages:b,method:"auto",tokensBefore:l,tokensAfter:R,tokensFreed:l-R}}catch{return r.consecutiveFailures++,{compacted:d.messagesCleared>0,messages:d.messages,method:"micro",tokensBefore:l,tokensAfter:p,tokensFreed:l-p}}}function Io(o,e,t){let n=t?.compaction?.microCompactThresholdRatio??ii;return po(o,n,e,t)}jt();vn();var ci=3,$o=10,Yl=.3;function Oo(o){if(!o)return!1;let e=String(o).toLowerCase();return["context length","context window","too long","maximum context","token limit","input is longer than","exceeds maximum","413","prompt is too long","request too large"].some(n=>e.includes(n))}async function Lo(o,e,t,n){let r=Nr(o,$o).messages,s=He(r),i=Dt(t,n);if(s<i*.9)return{messages:r,retries:1,method:"aggressive_micro"};for(let c=1;c<=ci;c++){let d=Math.max($o,Math.floor(r.length*Yl*(1/c))),p=r.find(x=>x.role==="system"),g=Tt(r,d);if(r=p?[p,...g]:g,s=He(r),s<i*.7)try{let x=await kn(r,e,t),y=Sn(x),u=[];return p&&u.push(p),u.push(y),u.push(...Tt(r,Math.floor(d/2))),{messages:u,retries:c,method:"llm"}}catch{continue}}let a=r.find(c=>c.role==="system"),l=Tt(r,$o);return r=a?[a,...l]:l,{messages:r,retries:ci,method:"truncate"}}function No(o){return o&&o.replace(/<think>[\s\S]*?<\/think>/g,"").trim()||null}function Ql(o){if(!o)return null;let e=o.match(/<think>([\s\S]*?)<\/think>/);return e?(e[1]||"").trim():null}function Zl(o,e=200){let t=typeof o=="string"?o.trim().replace(/\s+/g," "):"";return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var zt=class o{constructor(e){this.input=e;let t=di.resolve(e.workspace);this.context=new vt(t,e.skillScannerConfig,e.skillScanner);let n=e.sessionManager??new ot(t);this.sessions=n,this.lifecycle=e.lifecycle??rt();let r=e.model??e.provider.getDefaultModel();this.subagents=new Tr(e.bus,e.subagentExecutor??new Cr,e.subagentInlineExecutor??new xr(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 Rr(Math.max(1,e.maxConcurrentSessions??4),s)}context;sessions;tools;subagents;runtime;lifecycle;running=!1;acceptingWork=!0;consolidating=new Set;activeControllers=new Map;activeDispatches=new Set;mcpManager=new bn;recentInboundBySession=new Map;static CANCELLED_SENTINEL=Symbol("cancelled");static TOOL_RESULT_MAX_CHARS=500;static SHUTDOWN_MESSAGE="Gateway is shutting down. Please try again later.";static SESSION_BUSY_MESSAGE="This session is busy right now. Please wait for the current response before sending more messages.";static DEFAULT_MAX_QUEUED_PER_SESSION=1;static DEFAULT_MAX_REQUESTS_PER_WINDOW=6;static DEFAULT_RATE_LIMIT_WINDOW_MS=3e4;maxRequestsPerWindow;rateLimitWindowMs;rateLimited=0;lastRateLimitedAt=null;compactionStats={microCompactions:0,autoCompactions:0,reactiveCompactions:0,tokensFreed:0,consecutiveFailures:0};get model(){return this.input.model??this.input.provider.getDefaultModel()}get channelsConfig(){return this.input.channelsConfig}isToolCallingEnabled(e=this.model){if(!this.input.loadConfig)return!0;let t=this.input.loadConfig(),n=Un(t,e);return n&&typeof n.toolCalling=="boolean"?n.toolCalling:!0}isReasoningEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=Un(t,e);return n&&typeof n.reasoning=="boolean"?n.reasoning:!1}isImageOutputEnabled(e=this.model){if(!this.input.loadConfig)return!1;let t=this.input.loadConfig(),n=Un(t,e);return n&&typeof n.imageOutput=="boolean"?n.imageOutput:!1}resolveTurnModel(e){let t=String(e?._model??"").trim(),n=String(e?._provider??"").trim();if(!t||!this.input.loadConfig)return{model:this.model,provider:this.input.provider};let r=structuredClone(this.input.loadConfig());return r.agents.defaults.model=t,r.agents.defaults.provider=n||"auto",{model:t,provider:Ne(r)}}getRuntimeState(){let e=this.runtime.snapshot(),t=this.input.loadConfig?.();return{running:this.running,acceptingWork:this.acceptingWork,maxConcurrentSessions:e.maxConcurrency,activeSessions:e.running,queuedSessions:e.sessions.filter(n=>n.queued>0).length,queuedMessages:e.queued,subagents:this.subagents.getRunningCount(),sessions:e.sessions,overload:{maxQueuedPerSession:e.maxQueuedPerKey,maxRequestsPerWindow:this.maxRequestsPerWindow,rateLimitWindowMs:this.rateLimitWindowMs,rateLimited:this.rateLimited,backpressured:e.backpressured,lastRateLimitedAt:this.lastRateLimitedAt,lastBackpressureAt:e.lastBackpressureAt},tasks:this.subagents.getTaskSnapshot(),compaction:{enabled:t?.compaction?.enabled??!0,microCompactions:this.compactionStats.microCompactions,autoCompactions:this.compactionStats.autoCompactions,reactiveCompactions:this.compactionStats.reactiveCompactions,tokensFreed:this.compactionStats.tokensFreed,circuitBreakerTripped:this.compactionStats.consecutiveFailures>=(t?.compaction?.maxConsecutiveFailures??3)}}}rateLimitMessage(e){return`This session is receiving messages too quickly. Please wait ${Math.max(1,Math.ceil(e/1e3))}s and try again.`}pruneRecentInbound(e,t=Date.now()){let n=(this.recentInboundBySession.get(e)??[]).filter(r=>t-r<this.rateLimitWindowMs);return n.length?this.recentInboundBySession.set(e,n):this.recentInboundBySession.delete(e),n}checkRateLimit(e){let t=Date.now(),n=this.pruneRecentInbound(e,t);if(n.length>=this.maxRequestsPerWindow){this.rateLimited+=1,this.lastRateLimitedAt=new Date(t).toISOString();let r=n[0];return r!=null?Math.max(1,this.rateLimitWindowMs-(t-r)):this.rateLimitWindowMs}return n.push(t),this.recentInboundBySession.set(e,n),null}makeDirectResult(e,t,n){return n==null?{outcome:e,content:t}:{outcome:e,content:t,retryAfterMs:n}}rejectIfOverloaded(e,t){if(e.channel==="system")return null;let n=this.checkRateLimit(t);return n==null?null:this.makeDirectResult("rate_limited",this.rateLimitMessage(n),n)}mapRuntimeResult(e){return e.status==="cancelled"?this.makeDirectResult("cancelled","Task was cancelled."):e.status==="rejected"?this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE):this.makeDirectResult("completed",e.value?.content??"")}async publishDirectResult(e,t,n){let r=t.outcome==="rate_limited"?{...n,_overload:t.outcome,_retry_after_ms:t.retryAfterMs??0}:t.outcome==="backpressure"?{...n,_overload:t.outcome}:n??{};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t.content,metadata:r})}async withAgentTurnLifecycle(e,t,n,r){await qe(this.lifecycle.beforeAgentTurn,"beforeAgentTurn",{message:e,sessionKey:t,trigger:n});let s=null,i=!1,a=null;try{let l=await r();return s=l.response,i=l.cancelled,s}catch(l){a=l;try{let c=this.sessions.getOrCreate(t);c.messages.push({role:"assistant",content:null,_error:String(l),timestamp:new Date().toISOString()}),c.updatedAt=new Date().toISOString(),this.sessions.save(c)}catch(c){console.error(`[agent] failed to persist error turn for ${t}:`,c)}throw l}finally{await qe(this.lifecycle.afterAgentTurn,"afterAgentTurn",{message:e,sessionKey:t,trigger:n,response:s,cancelled:i,error:a})}}createToolRegistry(e){let t=this.input.loadConfig?.(),n=t?.tools?.browserRelay?.enabled??!1,r=t?.tools?.chromeSession?.enabled??!1,s={workspace:di.resolve(this.input.workspace),restrictToWorkspace:!!this.input.restrictToWorkspace,braveApiKey:this.input.braveApiKey??null,execConfig:this.input.execConfig??{timeout:60,pathAppend:""},bus:this.input.bus,subagents:this.subagents,sessionManager:this.sessions};if(e){let a=this.context.buildSystemPrompt(e.skillNames,e.memoryNamespace);s.turn={...e,systemPrompt:a}}if(this.input.cronService&&(s.cronService=this.input.cronService),this.input.rtkConfig&&(s.rtkConfig=this.input.rtkConfig),this.input.rtkService&&(s.rtkService=this.input.rtkService),this.input.browserRelay&&n&&(s.browserRelay=this.input.browserRelay),r){let a=this.input.chromeSessionConfig??t?.tools?.chromeSession;a&&(s.chromeSessionConfig=a)}let i=Sr(s);return this.input.guardEngine&&i.setGuardEngine(this.input.guardEngine),i}toolHint(e){return e.map(t=>{let n=Object.values(t.arguments??{})[0];return typeof n!="string"?t.name:n.length>40?`${t.name}("${n.slice(0,40)}...")`:`${t.name}("${n}")`}).join(", ")}async runAgentLoop(e,t,n,r=()=>!0,s,i,a={..._o}){let l=[...e],c=null,d=[],p=this.input.maxIterations??40,g=i?.model??this.model,x=i?.provider??this.input.provider,y=this.isToolCallingEnabled(g),u=this.isReasoningEnabled(g),b=this.isImageOutputEnabled(g),R=y?t.getDefinitions():void 0,D=AbortSignal.timeout(12e4),$=s?AbortSignal.any([s,D]):D,I=0;for(let H=0;H<p;H++){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s);let L=this.input.loadConfig?.(),Q=await Mo(l,x,g,L,a);Q.compacted&&(l.length=0,l.push(...Q.messages));let Y;try{Y=await x.chat({messages:l,...R?{tools:R}:{},model:g,temperature:this.input.temperature??.1,maxTokens:this.input.maxTokens??4096,...u?{reasoning:!0}:{},...b?{imageOutput:!0}:{},signal:$})}catch(z){if(Oo(z)){if(I++,this.compactionStats.consecutiveFailures++,I>2)throw z;console.error(`[compact] reactive: triggered by context_overflow (attempt ${I})`);let B=await Lo(l,x,g,L);this.compactionStats.reactiveCompactions++,this.compactionStats.consecutiveFailures=0,l.length=0,l.push(...B.messages),H--;continue}if(se(z)){if(s?.aborted)throw z;return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1}}throw z}if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let F=Y.reasoningContent||Ql(Y.content);if(F&&n&&r()&&await n(F,{event:"thinking",thinkingContent:F,toolHint:!1}),Y.toolCalls.length){let z=No(Y.content);n&&z&&r()&&await n(z,{event:"answer",toolHint:!1});let B=Y.toolCalls.map(N=>({id:N.id,type:"function",function:{name:N.name,arguments:JSON.stringify(N.arguments)}}));n&&r()&&await n(this.toolHint(Y.toolCalls),{event:"tool_calls",toolHint:!0,tool_calls:B.map(N=>({...N,status:"running"}))}),this.context.addAssistantMessage(l,z,B,F);for(let N of Y.toolCalls){if(!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};te(s),d.push(N.name);let J=await t.execute(N.name,N.arguments,s?{signal:s}:{});if(te(s),!r())return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};let G=J.kind==="cancelled"?"Task was cancelled.":J.content;if(this.context.addToolResult(l,N.id,N.name,G),n&&r()&&await n(G,{event:"tool_result",toolHint:!0,tool_call:{id:N.id,type:"function",function:{name:N.name,arguments:JSON.stringify(N.arguments)},status:"completed",resultPreview:Zl(G,200)??null}}),J.kind==="terminal")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!1,terminal:!0};if(J.kind==="cancelled")return{finalContent:null,toolsUsed:d,messages:l,cancelled:!0,terminal:!1};if(J.kind==="error"&&!J.retryable)break}if(Io(l,g,L)){let{microCompact:N}=await Promise.resolve().then(()=>(vn(),ti)),J=N(l,L?.compaction?.keepRecentMessages??10);J.messagesCleared>0&&(l.length=0,l.push(...J.messages))}}else{c=No(Y.content),c&&n&&r()&&await n(c,{event:"answer",toolHint:!1}),this.context.addAssistantMessage(l,c,void 0,F);break}}return c==null&&(c=`I reached the maximum number of tool call iterations (${p}) without completing the task.`),{finalContent:c,toolsUsed:d,messages:l,cancelled:!1,terminal:!1}}async run(){for(this.running=!0,this.acceptingWork=!0;this.running;){let e=await this.input.bus.consumeInbound();if(!this.running||e.metadata?._shutdown)break;if(!this.acceptingWork){await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:o.SHUTDOWN_MESSAGE,metadata:{_shutdown:!0}});continue}if((typeof e.content=="string"?e.content.trim():(e.content.find(r=>r.type==="text")?.text??"").trim()).toLowerCase()==="/stop"){await this.handleStop(e);continue}let n=this.dispatch(e).catch(r=>console.error(`[agent] dispatch error for ${Eo(e)}:`,r));this.activeDispatches.add(n),n.finally(()=>this.activeDispatches.delete(n))}}stop(){this.running=!1}beginShutdown(){this.acceptingWork=!1}async shutdown(){this.beginShutdown(),this.running=!1;let e=await this.stopAllSessions();return this.activeDispatches.size>0&&await Promise.race([Promise.allSettled(this.activeDispatches),new Promise(n=>setTimeout(n,1e4))]),await this.mcpManager.closeAll(),await this.input.bus.publishInbound({channel:"system",senderId:"system",chatId:"gateway:shutdown",content:"",metadata:{_shutdown:!0}}),e}async processDirect(e,t="cli:direct",n="cli",r="direct",s){return(await this.processDirectResult(e,t,n,r,s)).content}async processDirectResult(e,t="cli:direct",n="cli",r="direct",s,i){let a={channel:n,senderId:"user",chatId:r,content:e,sessionKeyOverride:t,...i?{metadata:i}:{}};if((typeof e=="string"?e:e.find(p=>p.type==="text")?.text??"").trim().toLowerCase()==="/stop"){let p=await this.stopSession(t);return this.makeDirectResult("completed",p?`Stopped ${p} task(s).`:"No active task to stop.")}if(!this.acceptingWork)return this.makeDirectResult("shutdown",o.SHUTDOWN_MESSAGE);let c=this.rejectIfOverloaded(a,t);if(c)return c;let d=await this.runtime.enqueue(t,({isCurrent:p})=>this.withSessionController(t,g=>this.processMessage(a,t,s,p,g,"direct")));return d.status==="completed"&&d.value===o.CANCELLED_SENTINEL?this.makeDirectResult("cancelled","Task was cancelled."):this.mapRuntimeResult(d)}async dispatch(e){try{if(!this.acceptingWork)return;let t=this.resolveSessionContext(e),n=this.rejectIfOverloaded(e,t.key);if(n){await this.publishDirectResult(t,n,e.metadata);return}let r=await this.runtime.enqueue(t.key,async({isCurrent:s})=>{try{let i=await this.withSessionController(t.key,a=>this.processMessage(e,t.key,void 0,s,a,"queued"));return i===o.CANCELLED_SENTINEL?s()?{channel:t.channel,chatId:t.chatId,content:"Task was cancelled.",metadata:{_cancelled:!0}}:null:i}catch{return s()?{channel:t.channel,chatId:t.chatId,content:"Sorry, I encountered an error."}:null}},{bypassCapacity:e.channel==="system"});if(r.status==="rejected"){await this.publishDirectResult(t,this.makeDirectResult("backpressure",o.SESSION_BUSY_MESSAGE),e.metadata);return}if(r.status==="cancelled")return;r.value?await this.input.bus.publishOutbound(r.value):e.channel==="cli"&&await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:"",metadata:e.metadata??{}})}catch(t){console.error(`[agent] dispatch error (channel=${e.channel}, chatId=${e.chatId}):`,t)}}async handleStop(e){let t=await this.stopSession(this.resolveSessionContext(e).key);await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:t?`Stopped ${t} task(s).`:"No active task to stop."})}async stopSession(e){let t=this.runtime.cancel(e);t.running&&this.abortSession(e);let n=await this.subagents.cancelBySession(e);return Number(t.running)+t.queued+n}async stopAllSessions(){let e=0;for(let t of this.runtime.snapshot().sessions){let n=this.runtime.cancel(t.key);n.running&&this.abortSession(t.key),e+=Number(n.running)+n.queued}return e+await this.subagents.cancelAll()}abortSession(e){this.activeControllers.get(e)?.abort()}async withSessionController(e,t){let n=new AbortController;this.activeControllers.set(e,n);try{return await t(n.signal)}catch(r){if(se(r))return o.CANCELLED_SENTINEL;throw r}finally{this.activeControllers.get(e)===n&&this.activeControllers.delete(e)}}resolveSessionContext(e,t){let n=e.metadata?.message_id;if(e.channel==="system"){let r=String(e.chatId),s=r.includes(":"),i=s?r.split(/:(.*)/s,2)[0]:"cli",a=s?r.split(/:(.*)/s,2)[1]:r,l={key:`${i}:${a}`,channel:i,chatId:a};return n&&(l.messageId=n),l}return{key:t??Eo(e),channel:e.channel,chatId:e.chatId,...n?{messageId:n}:{}}}memoryNamespace(e){return e.includes(":")&&e.replace(/:/g,"_")||void 0}async consolidateMemory(e,t=!1,n=this.input.provider,r=this.model){return this.context.getMemoryStore(this.memoryNamespace(e.key)).consolidate(e,n,r,{archiveAll:t,memoryWindow:this.input.memoryWindow??100})}saveTurn(e,t,n,r){let s=t.slice(n);for(let i=0;i<s.length;i++){let l={...s[i]};l.role==="assistant"&&typeof l.content=="string"&&(l.content=No(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)}
311
+ ... (truncated)`),!(l.role==="user"&&typeof l.content=="string"&&l.content.startsWith(vt.RUNTIME_CONTEXT_TAG))&&(l.timestamp||(l.timestamp=new Date().toISOString()),l.role==="assistant"&&r?.length&&i===s.length-1&&(l.tools_used=r),e.messages.push(l))}e.updatedAt=new Date().toISOString()}sanitizeInput(e,t){if(!t.security?.enabled||!t.security.inputSanitizer?.enabled)return e;let n=new Pr(t.security.inputSanitizer);return typeof e=="string"?n.sanitize(e).sanitized:e.map(r=>{if(r.type==="text"){let s=n.sanitize(r.text);return{...r,text:s.sanitized}}return r})}async resolveCommand(e,t,n,r){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
312
  /new - Start a new conversation
269
313
  /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 wr(a.serverName,a.remoteName,a.proxyName,a.description,a.inputSchema,this.mcpManager))}catch(i){console.warn(`MCP: failed to connect to '${s}': ${String(i)}`)}}return r}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),t.metadata&&(l.metadata=t.metadata),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(de);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),d=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let{messages:z,newMessageStartIndex:g}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[]),{finalContent:f,messages:k,toolsUsed:x,cancelled:P,terminal:T}=await this.runAgentLoop(z,m,void 0,r,s,d);return P||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,k,g,x),{response:{channel:a.channel,chatId:a.chatId,content:f??"Background task completed."},cancelled:!1})}let h=(typeof e.content=="string"?e.content:e.content.find(z=>z.type==="text")?.text??"").trim().toLowerCase(),v=await this.resolveCommand(h,c,e,d);if(v)return v;let u=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],E=Object.keys(l?.tools?.mcpServers??{}),S=new Set(E),N=b.length?b.filter(z=>S.has(z)):E,U=b.filter(z=>!S.has(z)),I=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},N),{messages:J,newMessageStartIndex:re}=this.buildTurnPrompt(c,e,l,U),q=async(z,g)=>{if(!r())return;let m={...e.metadata,_progress:!0,_tool_hint:!!g?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:z,metadata:m})},{finalContent:K,messages:V,toolsUsed:ie,cancelled:R,terminal:O}=await this.runAgentLoop(J,I,n??q,r,s,d);if(R||!r())return{response:null,cancelled:!0};let F=K??"I've completed processing but have no response to give.";if(this.commitTurn(c,V,re,ie),u){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,d.provider,d.model)}finally{this.consolidating.delete(c.key)}}return O?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:F,metadata:e.metadata??{}},cancelled:!1}})}};qr();bt();var ul=1024*1024,gl=300*1e3;function Ts(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function ml(o,e,t){let n=Ts(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
314
+ /help - Show available commands`},cancelled:!1}:null}async prepareTurnTools(e,t,n,r){let s=this.memoryNamespace(t.sessionKey),i={...t};r&&(i.skillNames=r),s&&(i.memoryNamespace=s);let a=this.createToolRegistry(i);if(n.length&&e?.tools?.mcpServers){this.mcpManager.updateConfig(e.tools.mcpServers);for(let l of n)try{let c=await this.mcpManager.getServerTools(l);for(let d of c)a.register(new Or(d.serverName,d.remoteName,d.proxyName,d.description,d.inputSchema,this.mcpManager))}catch(c){console.warn(`MCP: failed to connect to '${l}': ${String(c)}`)}}return a}buildTurnPrompt(e,t,n,r){let s=e.getHistory(this.input.memoryWindow??100),i=this.sanitizeInput(t.content,n),a=this.memoryNamespace(e.key),l={history:s,currentMessage:i,channel:t.channel,chatId:t.chatId};return a&&(l.memoryNamespace=a),t.media&&(l.media=t.media),r.length&&(l.skillNames=r),t.metadata&&(l.metadata=t.metadata),{messages:this.context.buildMessages(l),newMessageStartIndex:1+s.length}}commitTurn(e,t,n,r){this.saveTurn(e,t,n,r),this.sessions.save(e)}async processMessage(e,t,n,r=()=>!0,s,i="queued"){let a=this.resolveSessionContext(e,t),l=this.input.loadConfig?.()??structuredClone(me);return this.withAgentTurnLifecycle(e,a.key,i,async()=>{let c=this.sessions.getOrCreate(a.key),d=this.resolveTurnModel(e.metadata);if(e.channel==="system"){let G=e.metadata?._notification;if(G){let _=this.context.buildNotificationContext(G),M={...e,content:_},{messages:X,newMessageStartIndex:j}=this.buildTurnPrompt(c,M,l,[]),ge=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:ee,messages:Qe,toolsUsed:In,cancelled:gt,terminal:lu}=await this.runAgentLoop(X,ge,void 0,r,s,d);return gt||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,Qe,j,In),{response:{channel:a.channel,chatId:a.chatId,content:ee??"Task notification processed."},cancelled:!1})}let{messages:h,newMessageStartIndex:f}=this.buildTurnPrompt(c,e,l,[]),m=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},[],[]),{finalContent:k,messages:C,toolsUsed:A,cancelled:T,terminal:E}=await this.runAgentLoop(h,m,void 0,r,s,d);return T||!r()?{response:null,cancelled:!0}:(this.commitTurn(c,C,f,A),{response:{channel:a.channel,chatId:a.chatId,content:k??"Background task completed."},cancelled:!1})}let g=(typeof e.content=="string"?e.content:e.content.find(G=>G.type==="text")?.text??"").trim().toLowerCase(),x=await this.resolveCommand(g,c,e,d);if(x)return x;let u=c.messages.length-c.lastConsolidated>=(this.input.memoryWindow??100)&&!this.consolidating.has(c.key),b=Array.isArray(e.metadata?.skillNames)?e.metadata.skillNames:[],R=Object.keys(l?.tools?.mcpServers??{}),S=new Set(R),D=b.length?b.filter(G=>S.has(G)):R,$=b.filter(G=>!S.has(G)),I=await this.prepareTurnTools(l,{...a,sessionKey:a.key,isCurrent:r},D,$),{messages:H,newMessageStartIndex:L}=this.buildTurnPrompt(c,e,l,$),Q=async(G,h)=>{if(!r())return;let f={...e.metadata,_progress:!0,_tool_hint:!!h?.toolHint};await this.input.bus.publishOutbound({channel:e.channel,chatId:e.chatId,content:G,metadata:f})},{finalContent:Y,messages:F,toolsUsed:z,cancelled:B,terminal:N}=await this.runAgentLoop(H,I,n??Q,r,s,d);if(B||!r())return{response:null,cancelled:!0};let J=Y??"I've completed processing but have no response to give.";if(this.commitTurn(c,F,L,z),u){this.consolidating.add(c.key);try{await this.consolidateMemory(c,!1,d.provider,d.model)}finally{this.consolidating.delete(c.key)}}return N?{response:null,cancelled:!1}:{response:{channel:e.channel,chatId:e.chatId,content:J,metadata:e.metadata??{}},cancelled:!1}})}};co();kt();var ec=1024*1024,tc=300*1e3;function ui(o){return o==="scheduled-job"?"Scheduled job":"Background job"}function nc(o,e,t){let n=ui(o);if(t.failureAttribution==="timeout")return`${n} timed out after ${Math.ceil(e/1e3)} seconds`;let r=[t.stdout.trim()?`STDOUT:
271
315
  ${t.stdout.trim()}`:"",t.stderr.trim()?`STDERR:
272
316
  ${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
317
  `);return r?`${n} failed
274
- ${r}`:`${n} failed`}function pl(){let o=process.argv[1]??"";return Ot(o)}function vr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(gl,e)}var go=class{constructor(e,t,n,r=new be,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(yt(this.target).mode!=="local-process")throw new Error(`${Ts(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??ul});if(n.status==="aborted")throw tn();if(n.status==="ok")return n.stdout;throw new Error(ml(this.target,this.timeoutMs,n))}};function gn(o){let e=pl();return new go(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 Ut=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 Wt=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 fl(o,e=4e3){if(o.length<=e)return[o];let t=[],n=o;for(;n.length>e;){let r=n.slice(0,e),s=Math.max(r.lastIndexOf(`
276
- `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function hl(o){if(!o)return"[Unsupported message]";if(o.text)return o.text;let e=o.caption?` ${o.caption}`:"";return o.photo?`[Photo]${e}`:o.video?`[Video]${e}`:o.voice?`[Voice message]${e}`:o.audio?`[Audio]${e}`:o.document?`[Document: ${o.document.file_name??"file"}]${e}`:o.sticker?`[Sticker ${o.sticker.emoji??""}]${e}`:o.location?`[Location]${e}`:o.contact?`[Contact]${e}`:`[Unsupported message]${e}`}function yl(o){return o.toLowerCase().replace(/[^a-z0-9_]/g,"_").slice(0,32)}var bl=new Set(["chatid","ping"]);function wl(o){let e=o.match(/^\/([a-zA-Z0-9_]+)(?:@([a-zA-Z0-9_]+))?(?:\s|$)/);return e?{name:e[1].toLowerCase(),target:e[2]?.toLowerCase()??null}:null}var vl=3e3,Sr=class extends Ut{name="telegram";offset=0;inbox;botUsername=null;botId=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t){super(e,t,e.debounce),this.inbox=new Wt(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}if(!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result&&(t.result.id&&(this.botId=String(t.result.id)),t.result.username&&(this.botUsername=t.result.username.toLowerCase(),this.config.commands?.native!==!1&&await this.registerCommands()))}}catch{}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=hl(s),c=s.text?wl(l):null,d=c?.target!=null&&this.botUsername!=null&&c.target!==this.botUsername;if(c&&!d&&bl.has(c.name)){await this.handleBotCommand(c.name,s);continue}let p={message_id:s.message_id};s.chat.type&&(p.chat_type=s.chat.type);let h=!1;if(this.botUsername&&s.text&&s.entities&&(h=s.entities.some(w=>w.type==="mention"?s.text.substring(w.offset,w.offset+w.length).toLowerCase().trim()===`@${this.botUsername}`:w.type==="text_mention"?!0:w.type==="bot_command"?s.text.substring(w.offset,w.offset+w.length).toLowerCase().includes(`@${this.botUsername}`):!1)),s.chat.type==="group"||s.chat.type==="supergroup"){let w=this.config.groups?.allowedGroupIds,u=w==null?null:Array.isArray(w)?w:[String(w)];if(u!==null&&!u.includes(String(s.chat.id)))continue;if(this.config.groups?.requireMention!==!1){let E=!!c&&!d,S=!!(s.reply_to_message?.from?.is_bot&&(!this.botId||String(s.reply_to_message.from.id)===this.botId));if(!h&&!E&&!S)continue}}h&&this.botUsername&&(p.bot_mentioned=!0,s.text&&(l=l.replace(new RegExp(`@${this.botUsername}`,"gi"),"").trim())),s.message_thread_id&&(p.thread_id=s.message_thread_id),this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:p,...s.message_thread_id&&{sessionKey:`telegram:${s.chat.id}:${s.message_thread_id}`}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async registerCommands(){let e=[{command:"chatid",description:"Show this chat's ID for configuration"},{command:"ping",description:"Check if the bot is online"},{command:"new",description:"Start a new conversation session"},{command:"stop",description:"Stop the current task"},{command:"help",description:"Show available commands"}],t=(this.config.commands?.custom??[]).map(r=>({command:yl(r.command),description:r.description})),n=[...e,...t].slice(0,100);try{let r=await fetch(this.api("setMyCommands"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commands:n})});if(!r.ok){let s=await r.json().catch(()=>({}));console.warn(`[telegram] setMyCommands failed: ${s?.description??r.status}`)}}catch{console.warn("[telegram] setMyCommands request failed")}}async handleBotCommand(e,t){let n=String(t.chat.id);if(e==="chatid"){let r=t.chat.type??"private",s=r==="private"?t.from?.first_name??t.from?.username??"Private":t.chat.title??"Unknown";await this.sendChunk(n,`Chat ID: \`telegram:${n}\`
318
+ ${r}`:`${n} failed`}function rc(){let o=process.argv[1]??"";return Gt(o)}function Dr(o){let e=Math.max(1,Number(o??0))*1e3;return Math.max(tc,e)}var Do=class{constructor(e,t,n,r=new ve,s){this.target=e;this.timeoutMs=t;this.buildCommand=n;this.runner=r;this.defaultEnv=s}async run(e){if(St(this.target).mode!=="local-process")throw new Error(`${ui(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??ec});if(n.status==="aborted")throw cn();if(n.status==="ok")return n.stdout;throw new Error(nc(this.target,this.timeoutMs,n))}};function Cn(o){let e=rc();return new Do(o.target,o.timeoutMs,t=>({kind:"argv",file:e.file,args:[...e.args,"agent","--message",t.message,"--session",t.session,"--channel",t.channel,"--chat-id",t.chatId,"--raw-output"]}),o.runner,e.env)}var Vt=class o{constructor(e,t,n){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 Xt=class{buffers=new Map;config;onEmit;constructor(e,t){this.config=e,this.onEmit=t}submit(e){if(!this.config.enabled){this.onEmit(e);return}let t=`${e.channel}:${e.chatId}`,n=this.buffers.get(t);if(n){clearTimeout(n.quietTimer),n.messages.push(e),n.quietTimer=setTimeout(()=>this.emit(t),this.config.quietMs);return}let r=setTimeout(()=>this.emit(t),this.config.quietMs),s=setTimeout(()=>this.emit(t),this.config.maxWaitMs);this.buffers.set(t,{messages:[e],quietTimer:r,maxTimer:s})}emit(e){let t=this.buffers.get(e);if(!t)return;clearTimeout(t.quietTimer),clearTimeout(t.maxTimer),this.buffers.delete(e);let n=t.messages[0];if(!n)return;let r=t.messages.map(a=>typeof a.content=="string"?a.content:a.content.find(c=>c.type==="text")?.text??JSON.stringify(a.content)).join(`
319
+ `),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 oc(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(`
320
+ `),r.lastIndexOf(" "));s<=0&&(s=e),t.push(n.slice(0,s)),n=n.slice(s).trimStart()}return n&&t.push(n),t}function sc(o){if(!o)return"[Unsupported message]";if(o.text)return o.text;let e=o.caption?` ${o.caption}`:"";return o.photo?`[Photo]${e}`:o.video?`[Video]${e}`:o.voice?`[Voice message]${e}`:o.audio?`[Audio]${e}`:o.document?`[Document: ${o.document.file_name??"file"}]${e}`:o.sticker?`[Sticker ${o.sticker.emoji??""}]${e}`:o.location?`[Location]${e}`:o.contact?`[Contact]${e}`:`[Unsupported message]${e}`}function ic(o){return o.toLowerCase().replace(/[^a-z0-9_]/g,"_").slice(0,32)}var ac=new Set(["chatid","ping"]);function lc(o){let e=o.match(/^\/([a-zA-Z0-9_]+)(?:@([a-zA-Z0-9_]+))?(?:\s|$)/);return e?{name:e[1].toLowerCase(),target:e[2]?.toLowerCase()??null}:null}var cc=3e3,jr=class extends Vt{name="telegram";offset=0;inbox;botUsername=null;botId=null;startTime=Date.now();lastTypingAt=new Map;constructor(e,t){super(e,t,e.debounce),this.inbox=new Xt(e.debounce,n=>this.handleMessage(n))}api(e){return`https://api.telegram.org/bot${this.config.token}/${e}`}async start(){if(!this.config.token){console.error("Telegram token not configured");return}if(!this.botUsername)try{let e=await fetch(this.api("getMe"));if(e.ok){let t=await e.json();t.ok&&t.result&&(t.result.id&&(this.botId=String(t.result.id)),t.result.username&&(this.botUsername=t.result.username.toLowerCase(),this.config.commands?.native!==!1&&await this.registerCommands()))}}catch{}for(this.running=!0;this.running;)try{let e=new URL(this.api("getUpdates"));e.searchParams.set("timeout","25"),e.searchParams.set("offset",String(this.offset)),e.searchParams.set("allowed_updates",JSON.stringify(["message"]));let t=await fetch(e);if(!t.ok){await new Promise(r=>setTimeout(r,1500));continue}let n=await t.json();if(!n.ok)continue;for(let r of n.result){this.offset=r.update_id+1;let s=r.message;if(!s||s.from?.is_bot)continue;let i=String(s.from?.id??"unknown"),a=s.from?.username?`${i}|@${s.from.username}`:i,l=sc(s),c=s.text?lc(l):null,d=c?.target!=null&&this.botUsername!=null&&c.target!==this.botUsername;if(c&&!d&&ac.has(c.name)){await this.handleBotCommand(c.name,s);continue}let p={message_id:s.message_id};s.chat.type&&(p.chat_type=s.chat.type);let g=!1;if(this.botUsername&&s.text&&s.entities&&(g=s.entities.some(y=>y.type==="mention"?s.text.substring(y.offset,y.offset+y.length).toLowerCase().trim()===`@${this.botUsername}`:y.type==="text_mention"?!0:y.type==="bot_command"?s.text.substring(y.offset,y.offset+y.length).toLowerCase().includes(`@${this.botUsername}`):!1)),s.chat.type==="group"||s.chat.type==="supergroup"){let y=this.config.groups?.allowedGroupIds,u=y==null?null:Array.isArray(y)?y:[String(y)];if(u!==null&&!u.includes(String(s.chat.id)))continue;if(this.config.groups?.requireMention!==!1){let R=!!c&&!d,S=!!(s.reply_to_message?.from?.is_bot&&(!this.botId||String(s.reply_to_message.from.id)===this.botId));if(!g&&!R&&!S)continue}}g&&this.botUsername&&(p.bot_mentioned=!0,s.text&&(l=l.replace(new RegExp(`@${this.botUsername}`,"gi"),"").trim())),s.message_thread_id&&(p.thread_id=s.message_thread_id),this.inbox.submit({channel:this.name,senderId:a,chatId:String(s.chat.id),content:l,metadata:p,...s.message_thread_id&&{sessionKey:`telegram:${s.chat.id}:${s.message_thread_id}`}})}}catch{await new Promise(e=>setTimeout(e,1500))}}async registerCommands(){let e=[{command:"chatid",description:"Show this chat's ID for configuration"},{command:"ping",description:"Check if the bot is online"},{command:"new",description:"Start a new conversation session"},{command:"stop",description:"Stop the current task"},{command:"help",description:"Show available commands"}],t=(this.config.commands?.custom??[]).map(r=>({command:ic(r.command),description:r.description})),n=[...e,...t].slice(0,100);try{let r=await fetch(this.api("setMyCommands"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({commands:n})});if(!r.ok){let s=await r.json().catch(()=>({}));console.warn(`[telegram] setMyCommands failed: ${s?.description??r.status}`)}}catch{console.warn("[telegram] setMyCommands request failed")}}async handleBotCommand(e,t){let n=String(t.chat.id);if(e==="chatid"){let r=t.chat.type??"private",s=r==="private"?t.from?.first_name??t.from?.username??"Private":t.chat.title??"Unknown";await this.sendChunk(n,`Chat ID: \`telegram:${n}\`
277
321
  Name: ${s}
278
- Type: ${r}`,{message_id:t.message_id,thread_id:t.message_thread_id})}else if(e==="ping"){let r=Math.floor((Date.now()-this.startTime)/1e3);await this.sendChunk(n,`Pong! Uptime: ${r}s`,{message_id:t.message_id,thread_id:t.message_thread_id})}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;if(e.metadata?._progress){await this.sendTyping(e.chatId);return}let t=fl(e.content||"");for(let n of t)await this.sendChunk(e.chatId,n,e.metadata)}async sendTyping(e){let t=Date.now(),n=this.lastTypingAt.get(e)??0;t-n<vl||(this.lastTypingAt.set(e,t),await fetch(this.api("sendChatAction"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:e,action:"typing"})}).catch(()=>{}))}async sendChunk(e,t,n){let r={chat_id:e,text:t,parse_mode:"Markdown"},s=n?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s});let i=n?.thread_id;i&&(r.message_thread_id=i);let a=await this.fetchWithRetry(this.api("sendMessage"),r);if(a&&!a.ok&&a.status===400)try{if((await a.json()).description?.toLowerCase().includes("parse")){let c={...r};delete c.parse_mode,await this.fetchWithRetry(this.api("sendMessage"),c)}}catch{}}async fetchWithRetry(e,t,n=1){for(let r=0;r<=n;r++)try{return await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(s){r<n?await new Promise(i=>setTimeout(i,1e3)):console.error(`[telegram] send failed after ${n+1} attempts:`,s instanceof Error?s.message:String(s))}}};import Rs from"ws";var kr=class extends Ut{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new Wt(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 Rs(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!==Rs.OPEN||this.ws.send(JSON.stringify(e))}};var Es="_shutdown",Cr=class{constructor(e,t,n,r){this.config=e;this.bus=t;this.lifecycle=n??Ze(),this.logger=r,this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;logger;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new Sr(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new kr(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 He(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 He(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}]))}};Fe();import{randomUUID as Sl}from"node:crypto";import kl from"node:path";function Cl(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 xl(o){return kl.resolve(o)}function As(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:Cl(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Kt=class{storage;workspace;constructor(e,t,n){this.workspace=xl(e),this.storage=n??Ne({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
322
+ Type: ${r}`,{message_id:t.message_id,thread_id:t.message_thread_id})}else if(e==="ping"){let r=Math.floor((Date.now()-this.startTime)/1e3);await this.sendChunk(n,`Pong! Uptime: ${r}s`,{message_id:t.message_id,thread_id:t.message_thread_id})}}async stop(){this.running=!1}async send(e){if(!this.config.token)return;if(e.metadata?._progress){await this.sendTyping(e.chatId);return}let t=oc(e.content||"");for(let n of t)await this.sendChunk(e.chatId,n,e.metadata)}async sendTyping(e){let t=Date.now(),n=this.lastTypingAt.get(e)??0;t-n<cc||(this.lastTypingAt.set(e,t),await fetch(this.api("sendChatAction"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chat_id:e,action:"typing"})}).catch(()=>{}))}async sendChunk(e,t,n){let r={chat_id:e,text:t,parse_mode:"Markdown"},s=n?.message_id;this.config.replyToMessage&&s&&(r.reply_parameters={message_id:s});let i=n?.thread_id;i&&(r.message_thread_id=i);let a=await this.fetchWithRetry(this.api("sendMessage"),r);if(a&&!a.ok&&a.status===400)try{if((await a.json()).description?.toLowerCase().includes("parse")){let c={...r};delete c.parse_mode,await this.fetchWithRetry(this.api("sendMessage"),c)}}catch{}}async fetchWithRetry(e,t,n=1){for(let r=0;r<=n;r++)try{return await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(s){r<n?await new Promise(i=>setTimeout(i,1e3)):console.error(`[telegram] send failed after ${n+1} attempts:`,s instanceof Error?s.message:String(s))}}};import gi from"ws";var Fr=class extends Vt{name="discord";ws=null;hb=null;seq=null;inbox;constructor(e,t){super(e,t,e.debounce),this.inbox=new Xt(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 gi(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!==gi.OPEN||this.ws.send(JSON.stringify(e))}};var mi="_shutdown",Br=class{constructor(e,t,n,r){this.config=e;this.bus=t;this.lifecycle=n??rt(),this.logger=r,this.initChannels()}channels=new Map;dispatchLoop=null;stopping=!1;lifecycle;logger;initChannels(){this.config.channels.telegram.enabled&&this.channels.set("telegram",new jr(this.config.channels.telegram,this.bus)),this.config.channels.discord.enabled&&this.channels.set("discord",new Fr(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:{[mi]:!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?.[mi])break;let t=this.channels.has(e.channel),n=this.getSkipReason(e),r=!1,s=null;try{await qe(this.lifecycle.beforeOutbound,"beforeOutbound",{message:e,hasChannel:t,skippedReason:n})}catch(i){s=i,console.warn(String(i))}if(!s&&!n){let i=this.channels.get(e.channel);if(i)try{await i.send(e),r=!0}catch(a){s=a}}try{await qe(this.lifecycle.afterOutbound,"afterOutbound",{message:e,hasChannel:t,skippedReason:n,dispatched:r,error:s})}catch(i){console.warn(String(i))}}}get enabledChannels(){return[...this.channels.keys()]}getStatus(){return Object.fromEntries([...this.channels].map(([e,t])=>[e,{enabled:!0,running:t.isRunning}]))}};Ue();import{randomUUID as dc}from"node:crypto";import uc from"node:path";function gc(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 mc(o){return uc.resolve(o)}function pi(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:gc(e),deliveredAt:String(o.delivered_at??""),clearedAt:o.cleared_at?String(o.cleared_at):null}}var Yt=class{storage;workspace;constructor(e,t,n){this.workspace=mc(e),this.storage=n??Fe({dataDir:t})}list(e={}){return this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
279
323
  FROM inbox_deliveries
280
324
  WHERE workspace = ?
281
325
  AND (? = 1 OR cleared_at IS NULL)
282
- ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>As(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
326
+ ORDER BY delivered_at DESC`).all(this.workspace,e.includeCleared?1:0).map(n=>pi(n)).filter(n=>n!==null)}get(e){let t=this.storage.prepare(`SELECT delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
283
327
  FROM inbox_deliveries
284
- WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return As(t)}record(e){let t=String(e.deliveredAt??ae()),n=Sl();return this.storage.prepare(`INSERT INTO inbox_deliveries (
328
+ WHERE workspace = ? AND delivery_id = ?`).get(this.workspace,e);return pi(t)}record(e){let t=String(e.deliveredAt??le()),n=dc();return this.storage.prepare(`INSERT INTO inbox_deliveries (
285
329
  workspace, delivery_id, job_id, job_name, session_key, channel, recipient, content, delivered_at, cleared_at
286
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(this.workspace,n,String(e.jobId??""),String(e.jobName??"Delivery"),String(e.sessionKey??""),String(e.channel??"cli"),String(e.recipient??"direct"),String(e.content??""),t),this.get(n)}markCleared(e,t=ae()){return this.storage.prepare(`UPDATE inbox_deliveries
330
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(this.workspace,n,String(e.jobId??""),String(e.jobName??"Delivery"),String(e.sessionKey??""),String(e.channel??"cli"),String(e.recipient??"direct"),String(e.content??""),t),this.get(n)}markCleared(e,t=le()){return this.storage.prepare(`UPDATE inbox_deliveries
287
331
  SET cleared_at = COALESCE(cleared_at, ?)
288
- WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};De();Fe();import ge,{existsSync as kt,unlinkSync as Hl}from"node:fs";import xe,{join as Jl}from"node:path";import{createServer as ql}from"node:http";import{spawn as Us}from"node:child_process";function xr(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function St(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function Ps(o){let e="local_process",t=St(o.runtime.overload?.rateLimited)+St(o.runtime.overload?.backpressured),n=St(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,St(o.config.tools.exec.timeout)),runningSubagents:St(o.runtime.subagents),queuedMessages:St(o.runtime.queuedMessages),queuedSessions:St(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:xr("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:xr(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:xr("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:xr("mixed_same_host"),boundary:"Scheduling state remains durable in the main runtime. This subagent-focused view keeps job-isolation reporting conservative rather than asserting a separate operator-facing boundary here.",evidence:[`Configured jobs: ${r.scheduledJobs}`,`Heartbeat: ${r.heartbeatEnabled?"enabled":"disabled"}`,`Queued messages now: ${r.queuedMessages}`]}],decisionEvidence:{recommendation:"Keep first-wave isolation lightweight until interference, cleanup failures, or sustained shared-process pressure show that heavier isolation is worth the added complexity.",signals:r,observedSignals:[`${r.runningSubagents} subagent(s) running right now`,`${r.queuedMessages} queued message(s) across ${r.queuedSessions} session(s)`,`${r.deniedTurns} denied turn(s) since process start`,`${r.scheduledJobs} scheduled job(s) configured`],justifyHeavierIsolationWhen:["subagents interfere with unrelated turns or cannot be cleaned up reliably","shell guardrails prove insufficient for required operator workflows","shared-process queueing/backpressure becomes a recurring containment problem"]}}}import Oe from"node:fs";import tt from"node:path";import{randomUUID as Tl}from"node:crypto";function Rl(o){return o.split(tt.sep).join("/")}function El(o,e=120){let t=o.trim().replace(/\s+/g," ");return t?t.length>e?`${t.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`:t:null}var Al=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),Pl={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function Il(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":Al.has(e)?"image":"binary"}function mn(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return Pl[e]||"image"}function _l(o,e=!1,t=128*1024){if(!Oe.existsSync(o)||!Oe.statSync(o).isFile())return{exists:!1,sizeBytes:null,modifiedAt:null,kind:"missing",preview:"File no longer exists in the workspace.",content:null,truncated:!1};let n=Oe.statSync(o),r=Il(o);if(r==="image"){let v=Math.min(n.size,5242881),w=Buffer.alloc(v),u=Oe.openSync(o,"r");try{v>0&&Oe.readSync(u,w,0,v,0)}finally{Oe.closeSync(u)}let b=mn(o)==="image-jpeg"?"image/jpeg":mn(o)==="image-png"?"image/png":mn(o)==="image-gif"?"image/gif":mn(o)==="image-webp"?"image/webp":mn(o)==="image-svg"?"image/svg+xml":"image/png",E=w.toString("base64"),S=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:S?"Image preview truncated.":"Image preview available.",content:null,truncated:S,imageDataUrl:`data:${b};base64,${E}`}}if(r==="pdf")return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"pdf",preview:"PDF document. Use the preview to view.",content:null,truncated:!1};let s=Math.min(n.size,t+1),i=Buffer.alloc(s),a=Oe.openSync(o,"r");try{s>0&&Oe.readSync(a,i,0,s,0)}finally{Oe.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let d=c.toString("utf8");if(d.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let p=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:p,preview:El(d),content:e?d:null,truncated:l}}var Tr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=tt.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Ne({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return tt.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=tt.isAbsolute(t)?tt.resolve(t):tt.resolve(this.workspacePath,t);try{Be(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!Oe.existsSync(n))throw new Error(`File not found: ${t}`);if(!Oe.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=Rl(tt.relative(this.workspacePath,n));return{relativePath:r,displayName:tt.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
332
+ WHERE workspace = ? AND delivery_id = ?`).run(t,this.workspace,e),this.get(e)}close(){this.storage.close()}};je();Ue();import fe,{existsSync as At,unlinkSync as Oc}from"node:fs";import Re,{join as Lc}from"node:path";import{createServer as Nc}from"node:http";import{spawn as Ei}from"node:child_process";function Ur(o){return o==="local_process"?"Local process":o==="mixed_same_host"?"Mixed same-host boundary":"Shared process"}function Rt(o){return typeof o=="number"&&Number.isFinite(o)?o:0}function fi(o){let e="local_process",t=Rt(o.runtime.overload?.rateLimited)+Rt(o.runtime.overload?.backpressured),n=Rt(o.cron.jobs),r={shellWorkspaceRestrictionEnabled:!!o.config.tools.restrictToWorkspace,execTimeoutSeconds:Math.max(1,Rt(o.config.tools.exec.timeout)),runningSubagents:Rt(o.runtime.subagents),queuedMessages:Rt(o.runtime.queuedMessages),queuedSessions:Rt(o.runtime.queuedSessions),deniedTurns:t,scheduledJobs:n,heartbeatEnabled:!!o.config.gateway.heartbeat.enabled};return{mode:"mixed_same_host",modeLabel:Ur("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:Ur(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:Ur("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:Ur("mixed_same_host"),boundary:"Scheduling state remains durable in the main runtime. This subagent-focused view keeps job-isolation reporting conservative rather than asserting a separate operator-facing boundary here.",evidence:[`Configured jobs: ${r.scheduledJobs}`,`Heartbeat: ${r.heartbeatEnabled?"enabled":"disabled"}`,`Queued messages now: ${r.queuedMessages}`]}],decisionEvidence:{recommendation:"Keep first-wave isolation lightweight until interference, cleanup failures, or sustained shared-process pressure show that heavier isolation is worth the added complexity.",signals:r,observedSignals:[`${r.runningSubagents} subagent(s) running right now`,`${r.queuedMessages} queued message(s) across ${r.queuedSessions} session(s)`,`${r.deniedTurns} denied turn(s) since process start`,`${r.scheduledJobs} scheduled job(s) configured`],justifyHeavierIsolationWhen:["subagents interfere with unrelated turns or cannot be cleaned up reliably","shell guardrails prove insufficient for required operator workflows","shared-process queueing/backpressure becomes a recurring containment problem"]}}}import De from"node:fs";import st from"node:path";import{randomUUID as pc}from"node:crypto";function fc(o){return o.split(st.sep).join("/")}function hc(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 yc=new Set([".jpg",".jpeg",".png",".gif",".webp",".svg",".ico"]),bc={".jpg":"image-jpeg",".jpeg":"image-jpeg",".png":"image-png",".gif":"image-gif",".webp":"image-webp",".svg":"image-svg",".ico":"image-icon"};function wc(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return e===".pdf"?"pdf":e===".md"||e===".markdown"?"markdown":yc.has(e)?"image":"binary"}function xn(o){let e=(o.includes(".")?o.slice(o.lastIndexOf(".")):"").toLowerCase();return bc[e]||"image"}function vc(o,e=!1,t=128*1024){if(!De.existsSync(o)||!De.statSync(o).isFile())return{exists:!1,sizeBytes:null,modifiedAt:null,kind:"missing",preview:"File no longer exists in the workspace.",content:null,truncated:!1};let n=De.statSync(o),r=wc(o);if(r==="image"){let x=Math.min(n.size,5242881),y=Buffer.alloc(x),u=De.openSync(o,"r");try{x>0&&De.readSync(u,y,0,x,0)}finally{De.closeSync(u)}let b=xn(o)==="image-jpeg"?"image/jpeg":xn(o)==="image-png"?"image/png":xn(o)==="image-gif"?"image/gif":xn(o)==="image-webp"?"image/webp":xn(o)==="image-svg"?"image/svg+xml":"image/png",R=y.toString("base64"),S=n.size>5242880;return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"image",preview:S?"Image preview truncated.":"Image preview available.",content:null,truncated:S,imageDataUrl:`data:${b};base64,${R}`}}if(r==="pdf")return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"pdf",preview:"PDF document. Use the preview to view.",content:null,truncated:!1};let s=Math.min(n.size,t+1),i=Buffer.alloc(s),a=De.openSync(o,"r");try{s>0&&De.readSync(a,i,0,s,0)}finally{De.closeSync(a)}let l=n.size>t,c=l?i.subarray(0,t):i;if(c.includes(0))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let d=c.toString("utf8");if(d.includes("\0"))return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:"binary",preview:"Binary file preview unavailable.",content:null,truncated:!1};let p=r==="markdown"?"markdown":"text";return{exists:!0,sizeBytes:n.size,modifiedAt:n.mtime.toISOString(),kind:p,preview:hc(d),content:e?d:null,truncated:l}}var Gr=class{constructor(e,t){this.workspacePath=e;this.dataDir=t;this.workspaceKey=st.resolve(e)}storage=null;workspaceKey;getStorage(){return this.storage||(this.storage=Fe({dataDir:this.dataDir})),this.storage}resolveAbsolutePath(e){return st.resolve(this.workspacePath,e)}resolveAssociationPath(e){let t=String(e??"").trim();if(!t)throw new Error("File path is required.");let n=st.isAbsolute(t)?st.resolve(t):st.resolve(this.workspacePath,t);try{Ge(n,this.workspacePath)}catch{throw new Error("Files must be inside the configured workspace.")}if(!De.existsSync(n))throw new Error(`File not found: ${t}`);if(!De.statSync(n).isFile())throw new Error(`Only files can be associated: ${t}`);let r=fc(st.relative(this.workspacePath,n));return{relativePath:r,displayName:st.basename(r||n)}}getRowById(e,t){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
289
333
  FROM session_files
290
- WHERE workspace = ? AND session_key = ? AND file_id = ?`).get(this.workspaceKey,e,t)??null}summarizeRow(e,t=!1){let n=this.resolveAbsolutePath(e.relative_path),r=_l(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
334
+ 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=vc(n,t);return{id:e.file_id,sessionKey:e.session_key,name:e.display_name,relativePath:e.relative_path,absolutePath:n,createdAt:e.created_at,updatedAt:e.updated_at,exists:r.exists,sizeBytes:r.sizeBytes,modifiedAt:r.modifiedAt,kind:r.kind,preview:r.preview,content:r.content,truncated:r.truncated,imageDataUrl:r.imageDataUrl||null}}list(e){return this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
291
335
  FROM session_files
292
336
  WHERE workspace = ? AND session_key = ?
293
337
  ORDER BY updated_at DESC, display_name COLLATE NOCASE ASC`).all(this.workspaceKey,e).map(n=>{let{content:r,truncated:s,...i}=this.summarizeRow(n,!1);return i})}associate(e,t){let n=this.resolveAssociationPath(t),r=this.getStorage().prepare(`SELECT session_key, file_id, relative_path, display_name, created_at, updated_at
294
338
  FROM session_files
295
- WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:d,...p}=this.summarizeRow(r,!1);return{created:!1,file:p}}let s={session_key:e,file_id:Tl(),relative_path:n.relativePath,display_name:n.displayName,created_at:ae(),updated_at:ae()};this.getStorage().prepare(`INSERT INTO session_files (
339
+ WHERE workspace = ? AND session_key = ? AND relative_path = ?`).get(this.workspaceKey,e,n.relativePath);if(r){let{content:c,truncated:d,...p}=this.summarizeRow(r,!1);return{created:!1,file:p}}let s={session_key:e,file_id:pc(),relative_path:n.relativePath,display_name:n.displayName,created_at:le(),updated_at:le()};this.getStorage().prepare(`INSERT INTO session_files (
296
340
  workspace, session_key, file_id, relative_path, display_name, created_at, updated_at
297
341
  ) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(this.workspaceKey,s.session_key,s.file_id,s.relative_path,s.display_name,s.created_at,s.updated_at);let{content:i,truncated:a,...l}=this.summarizeRow(s,!1);return{created:!0,file:l}}get(e,t){let n=this.getRowById(e,t);return n?this.summarizeRow(n,!0):null}remove(e,t){let n=this.getStorage().prepare(`DELETE FROM session_files
298
- WHERE workspace = ? AND session_key = ? AND file_id = ?`).run(this.workspaceKey,e,t);return Number(n?.changes??0)>0}close(){this.storage?.close(),this.storage=null}};import Ml from"node:os";import Is from"node:path";Fe();bt();De();var mo="clawhub@latest",_s=12e4;function Ms(o){let e=o?.runner??new be,t=()=>{let n=M(),r=X(n.agents.defaults.workspace);return ut(r,!0),r};return{getSnapshot(){let n=t(),r=Is.join(n,"skills"),s=Is.join(Ml.homedir(),".agents","skills"),i=new Ke(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${mo} search <query> --limit 5`,installTemplate:Rr(["install","<slug>"],n),list:Rr(["list"],n),update:Rr(["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(!Mn(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",mo,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:_s,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(Ll(i));return{slug:r,workspacePath:s,command:Rr(["install",r],s),output:$s(i),restartRequired:!0}}}}function Rr(o,e){return["npx","--yes",mo,...o,"--workdir",e].map($l).join(" ")}function $l(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function $s(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
342
+ 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 Sc from"node:os";import hi from"node:path";Ue();kt();je();var jo="clawhub@latest",yi=12e4;function bi(o){let e=o?.runner??new ve,t=()=>{let n=P(),r=Z(n.agents.defaults.workspace);return ft(r,!0),r};return{getSnapshot(){let n=t(),r=hi.join(n,"skills"),s=hi.join(Sc.homedir(),".agents","skills"),i=new Je(n,s);return{workspacePath:n,skillsDir:r,commands:{search:`npx --yes ${jo} search <query> --limit 5`,installTemplate:Wr(["install","<slug>"],n),list:Wr(["list"],n),update:Wr(["update","--all"],n)},restartHint:"Start a new session after installing a skill so the agent can load it.",skills:i.listResolvedSkills()}},async install(n){let r=String(n??"").trim();if(!Jn(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",jo,"install",r,"--workdir",s]},cwd:s,env:{...process.env},timeoutMs:yi,maxCaptureBytes:1024*1024});if(i.status!=="ok")throw new Error(Cc(i));return{slug:r,workspacePath:s,command:Wr(["install",r],s),output:wi(i),restartRequired:!0}}}}function Wr(o,e){return["npx","--yes",jo,...o,"--workdir",e].map(kc).join(" ")}function kc(o){return/^[a-z0-9_./:@=-]+$/i.test(o)?o:JSON.stringify(o)}function wi(o){return[o.stdout.trim(),o.stderr.trim()].filter(Boolean).join(`
299
343
 
300
- `).trim()||"Skill installed."}function Ll(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(_s/1e3)} seconds.`;let e=$s(o),t=typeof o.exitCode=="number"?`
344
+ `).trim()||"Skill installed."}function Cc(o){if(o.failureAttribution==="timeout")return`Skill install timed out after ${Math.round(yi/1e3)} seconds.`;let e=wi(o),t=typeof o.exitCode=="number"?`
301
345
  Exit code: ${o.exitCode}`:"",n=o.signal?`
302
- Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}De();le();import{scrypt as Ol,randomBytes as Os,timingSafeEqual as Dl}from"node:crypto";var Ds=64,Ns=16384,js=8,Fs=1,Nl=5,Ls=300*1e3;function jl(){let o=Os(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 Bs(o,e,t,n){let r=n??{};return new Promise((s,i)=>{Ol(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function Fl(o,e){let t=e??Os(16),n=await Bs(o,t,Ds,{N:Ns,r:js,p:Fs});return`${t.toString("hex")}:${n.toString("hex")}`}async function Bl(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 Bs(o,n,Ds,{N:Ns,r:js,p:Fs});return s.length!==r.length?!1:Dl(s,r)}var Er=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 Fl(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?Bl(e,this.config.pinHash):!1}createSession(){let e=jl(),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)>=Nl}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+Ls-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()-Ls;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function Ws(o){let e=xe.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 Ks(o){return o.startsWith("text/")||o==="application/json"}function zl(){let o=Ye("dashboard");if(!o)return null;let e=xe.join(o,"index.html");return ge.existsSync(e)?o:null}function ne(o){return new Promise(e=>{let t="";o.on("data",n=>{t+=n.toString(),t.length>2e6&&o.destroy()}),o.on("end",()=>{try{e(t?JSON.parse(t):{})}catch{e({})}}),o.on("error",()=>e({}))})}function y(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function Vl(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function Ir(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function _r(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 Yl(o){let e=Ir(o),t=[...e].reverse().find(n=>_r(n.content));return{messageCount:e.length,lastMessagePreview:t?_r(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function Xl(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function yo(o){return typeof o=="string"?o.trim():""}function Xs(o){return yo(o?.metadata?.displayName)||null}function Ql(o){let e=new Set;for(let n of o){let r=Xs(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 Zl(o,e){let t=Xl(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function ho(o){let e=new Set,t=[];for(let n of[...Ir(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:_r(r,56)??r}),t.length>=3))break}return t}function Pr(o,e,t,n){let{channel:r,chatId:s}=Vl(o.key),i=Yl(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Xs(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 Hs(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 Js(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function qs(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 zs(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function ec(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 nt(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function bo(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function tc(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Vs(o,e,t){return tc(o.socket.remoteAddress)?!0:(y(e,403,{error:t}),!1)}function bn(o){return o.map(e=>String(e)).join(".")}function wo(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!nt(t))return;t=t[n]}return t}function Te(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 ${bn(e)}`);let c=n[i],d=e[s+1];c===void 0&&(n[i]=typeof d=="number"?[]:{}),n=n[i];continue}if(!nt(n))throw new Error(`Expected object while writing ${bn(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 ${bn(e)}`);n[r]=t;return}if(!nt(n))throw new Error(`Expected object while writing ${bn(e)}`);n[r]=t}function ze(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??bo(o):null}}function nc(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))Te(t,["providers",n,"apiKey"],ze(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{Te(t,["customLlmProviders",r,"apiKey"],ze(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),Te(t,["channels","telegram","token"],ze(o.channels.telegram.token)),Te(t,["channels","discord","token"],ze(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",Te(t,["security","auth","pinHash"],ze(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",Te(t,["tools","browserRelay","authToken"],ze(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",Te(t,["tools","web","search","apiKey"],ze(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??{}))Te(t,["tools","mcpServers",n,"env",s],ze(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))Te(t,["tools","mcpServers",n,"headers",s],ze(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function Qs(o,e,t,n){let r=wo(o,e),s=bn(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(!nt(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 Ct(o,e,t,n){let r=String(wo(e,n)??""),s=String(wo(o,n)??""),i=Qs(t,n,r,s);if(i){if(i.action==="keep"){Te(o,n,r);return}if(i.action==="clear"){Te(o,n,"");return}Te(o,n,i.value??s)}}function Ys(o){return nt(o)&&Object.values(o).every(e=>typeof e=="string")}function rc(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function oc(o){if(!nt(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),!nt(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",d=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!rc(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&&!Ys(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!Ys(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(d)||d<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function sc(o){if(Array.isArray(o.customAcpProviders))return o;let e=M();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var ic=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),ac={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Zs(o){let e=zl(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??Ms(),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 Er(o.config.security.auth),c=()=>(r||(r=new Tr(o.workspacePath??process.cwd(),o.dataDir)),r),d=()=>(s||(s=new Kt(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,h=(w,u)=>{let b=w||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:u,session:b}}},v=ql(async(w,u)=>{let b=w.method||"GET",E=new URL(w.url||"/",`http://${w.headers.host||"localhost"}`),S=E.pathname;u.setHeader("X-Content-Type-Options","nosniff"),u.setHeader("X-Frame-Options","DENY"),u.setHeader("Referrer-Policy","no-referrer"),u.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let N=ac[b]??"\x1B[0m";if(console.log(`[gateway] ${N}${b}\x1B[0m ${S}`),l.isEnabled&&S.startsWith("/api/")&&!ic.has(S)){let g=w.headers["x-auth-token"];if(!g||typeof g!="string"||!l.validateSession(g))return y(u,401,{error:"Authentication required"});l.touchSession(g)}if(!l.isEnabled&&S==="/api/config"&&(b==="GET"||b==="PUT")&&!Vs(w,u,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&S==="/api/auth/login"){let g=await ne(w),m=String(g.pin??"");if(!m)return y(u,400,{error:"PIN is required"});let f=w.socket.remoteAddress??"unknown";if(l.isRateLimited(f)){let P=l.getRateLimitRemainingMs(f);return y(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:P})}if(!l.hasPin)return y(u,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(m))return l.recordFailedAttempt(f),y(u,401,{error:"Invalid PIN"});l.clearFailedAttempts(f);let x=l.createSession();return y(u,200,{token:x})}if(b==="GET"&&S==="/api/auth/status")return y(u,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&S==="/api/auth/logout"){let g=w.headers["x-auth-token"];return!g||typeof g!="string"?y(u,200,{ok:!0}):(l.invalidateSession(g),y(u,200,{ok:!0}))}if(b==="POST"&&S==="/api/auth/set-pin"){let g=await ne(w),m=String(g.newPin??""),f=g.currentPin!==void 0?String(g.currentPin):void 0;if(!m)return y(u,400,{error:"newPin is required"});if(m.length!==6)return y(u,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(m))return y(u,400,{error:"PIN must contain only digits"});if(l.hasPin){let T=w.headers["x-auth-token"];if(!(T&&typeof T=="string"&&l.validateSession(T))){let $=w.socket.remoteAddress??"unknown";if(l.isRateLimited($)){let Y=l.getRateLimitRemainingMs($);return y(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:Y})}if(!f)return y(u,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(f))return l.recordFailedAttempt($),y(u,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts($)}}else{let T=process.env.EVERCLAW_BOOTSTRAP_PIN;if(T&&String(g.bootstrapSecret??"")!==T)return y(u,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let k=!l.hasPin,x=await l.setPin(m);k||l.reset();let P=M();return P.security?.auth&&(P.security.auth.pinHash=x,oe(P)),y(u,200,{ok:!0,message:k?"PIN set successfully":"PIN changed successfully"})}let U=()=>y(u,503,{error:"Gateway is shutting down. Please try again later."}),I=S.match(/^\/api\/cron\/jobs\/([^/]+)$/),J=S.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),re=S.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),q=S.match(/^\/api\/inbox-deliveries\/([^/]+)$/),K=S.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),V=S.match(/^\/api\/sessions\/([^/]+)$/),ie=S.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&S==="/api/chat"||b==="POST"&&S==="/api/sessions"||b==="PUT"&&!!V||b==="PUT"&&S==="/api/config"||b==="POST"&&S==="/api/skills/install"||b==="POST"&&!!K||b==="POST"&&S==="/api/session-files"||b==="POST"&&S==="/api/cron/jobs"||b==="DELETE"&&!!ie||b==="DELETE"&&!!I||b==="POST"&&!!J||b==="POST"&&!!re))return U();if(b==="GET"&&S==="/api/status"){let g=M(),m=o.agent.getRuntimeState(),f=o.cron.status(),k=Ps({config:g,runtime:m,cron:f}),x=structuredClone(g.channels);x.telegram?.token&&(x.telegram.token=bo(x.telegram.token)),x.discord?.token&&(x.discord.token=bo(x.discord.token));let P=o.channelManager?.getStatus()??{};return y(u,200,{provider:g.agents.defaults.provider,model:g.agents.defaults.model,cron:f,channels:x,channelStatus:P,gateway:{...g.gateway,port:t},runtime:m,isolation:k,shutdown:{active:i||!m.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&S==="/api/chrome-session/status"){let g=M(),m=E.searchParams.get("port"),f=m?parseInt(m,10):g.tools.chromeSession?.debugPort??9222,k=g.tools.chromeSession?.minChromeVersion??136,x=await Lt(f);if(!x)return y(u,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:f});if(x.pendingApproval)return y(u,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${x.port} --user-data-dir=/tmp/chrome-debug-profile`,port:x.port,debugPort:f});let{port:P,versionInfo:T}=x,A=T.Browser.match(/(\w+)\/(\d+)/),$=A?.[1]??"Chrome",_=A?parseInt(A[2],10):0;return _>0&&_<k?y(u,200,{available:!1,reason:`Chrome version ${_} is below minimum required version ${k}`,hint:`Update Chrome to version ${k} or higher`,version:T.Browser,port:P,browser:$,debugPort:f}):y(u,200,{available:!0,version:T.Browser,remoteDebugging:!0,port:P,browser:$,debugPort:f})}if(b==="POST"&&S==="/api/chrome-session/launch"){let g=await ne(w),m=M(),f=g.port??m.tools.chromeSession?.debugPort??9222,k=await Lt(f);if(k&&!k.pendingApproval){let _=k.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(u,200,{ok:!0,launched:!1,alreadyRunning:!0,port:k.port,version:k.versionInfo.Browser,browser:_?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${k.port}. No need to launch.`})}if(k?.pendingApproval)return y(u,200,{ok:!1,launched:!1,pendingApproval:!0,port:k.port,message:"Chrome is running on this port but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow'."});let x="/tmp/chrome-debug-profile",P=Jl(x,"DevToolsActivePort");try{Hl(P)}catch{}let T=process.platform,A,$=[`--remote-debugging-port=${f}`,`--user-data-dir=${x}`];if(T==="darwin"){let _=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",`${process.env.HOME}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,"/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"],Y=_.find(D=>kt(D));if(!Y)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:_,hint:"Install Google Chrome or specify the path manually."});A=Y}else if(T==="win32"){A="cmd.exe";let _=process.env.ProgramFiles??"C:\\Program Files",Y=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",D=[`${_}\\Google\\Chrome\\Application\\chrome.exe`,`${Y}\\Google\\Chrome\\Application\\chrome.exe`,`${_}\\Microsoft\\Edge\\Application\\msedge.exe`,`${Y}\\Microsoft\\Edge\\Application\\msedge.exe`],fe=D.find(Ae=>kt(Ae));if(!fe)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:D,hint:"Install Google Chrome or Microsoft Edge."});$=["/c","start","",fe,`--remote-debugging-port=${f}`]}else{let _=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],Y=_.find(D=>kt(D));if(!Y)return y(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:_,hint:"Install Google Chrome or Chromium."});A=Y}try{let _=Us(A,$,{detached:!0,stdio:"ignore"}),Y=await Promise.race([new Promise(Ae=>_.once("error",Ae)),new Promise(Ae=>setTimeout(()=>Ae(null),500))]);if(Y)return y(u,500,{ok:!1,error:Y.message,chromePath:A,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});_.unref();let D;for(let Ae=0;Ae<5&&(await new Promise(lt=>setTimeout(lt,1e3)),D=await Lt(f),!D);Ae++);if(!D)return y(u,200,{ok:!1,launched:!0,port:f,chromePath:A,message:"Chrome was launched but CDP is not fully active. You may need to click 'Allow' in Chrome's remote debugging prompt, or try closing all existing Chrome windows first, then retry."});if(D.pendingApproval)return y(u,200,{ok:!1,launched:!0,pendingApproval:!0,port:D.port,chromePath:A,message:"Chrome was launched but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to enable agent control."});let fe=D.versionInfo.Browser.match(/(\w+)\/(\d+)/);return y(u,200,{ok:!0,launched:!0,port:D.port,chromePath:A,version:D.versionInfo.Browser,browser:fe?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${D.port}`})}catch(_){return y(u,500,{ok:!1,error:_ instanceof Error?_.message:String(_),chromePath:A,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&S==="/api/browser-relay/status"){let m=M().tools.browserRelay;if(!m.enabled)return y(u,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:m.extensionPath});if(o.browserRelay){let f=o.browserRelay.getStatus();return y(u,200,{enabled:!0,connected:f.connected,attachedTabs:f.attachedTabs,lastPing:f.lastPing,extensionPath:m.extensionPath})}return y(u,200,{enabled:m.enabled,connected:!1,attachedTabs:[],extensionPath:m.extensionPath})}if(b==="GET"&&S==="/api/browser-relay/config"){if(!Vs(w,u,"Browser Relay bootstrap is only available from localhost."))return;let g=M(),m=g.tools.browserRelay;return y(u,200,{enabled:m.enabled,port:g.gateway.port,token:m.enabled&&m.authToken||""})}if(b==="POST"&&S==="/api/browser-relay/launch"){let g=await ne(w),m=M(),f=g.extensionPath??m.tools.browserRelay.extensionPath;if(!f)return y(u,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let k=process.platform,x,P=[`--load-extension=${f}`,"--no-first-run","--no-default-browser-check"];if(k==="darwin")x=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(kt)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(k==="win32"){let T=process.env.ProgramFiles??"C:\\Program Files",A=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";x=[`${T}\\Google\\Chrome\\Application\\chrome.exe`,`${A}\\Google\\Chrome\\Application\\chrome.exe`].find(kt)??`${T}\\Google\\Chrome\\Application\\chrome.exe`}else x="google-chrome";try{return Us(x,P,{detached:!0,stdio:"ignore"}).unref(),y(u,200,{ok:!0,launched:!0,extensionPath:f,message:`Chrome launched with extension from ${f}`})}catch(T){return y(u,500,{ok:!1,error:T instanceof Error?T.message:String(T),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let R=S.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),O=X(o.config.agents.defaults.workspace);if(b==="GET"&&S==="/api/automations"){let g=Nt(O);return y(u,200,g)}if(b==="GET"&&R&&R[1]&&!R[2]){let g=R[1],m=Ce(O,g);return m?y(u,200,m):y(u,404,{error:"Automation not found"})}if(b==="POST"&&S==="/api/automations"){let g=await ne(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=tr(O,m);return y(u,201,f)}catch(m){return y(u,400,{error:String(m)})}}if(b==="PUT"&&R&&R[1]&&!R[2]){let g=R[1],m=await ne(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 k=nr(O,g,f);return k?y(u,200,k):y(u,404,{error:"Automation not found"})}if(b==="DELETE"&&R&&R[1]){let g=R[1];return jt(O,g)?y(u,200,{ok:!0}):y(u,404,{error:"Automation not found"})}if(b==="POST"&&R&&R[1]&&R[2]==="/run"){let g=R[1],m=Ce(O,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})}),y(u,200,{ok:!0,message:`Automation '${m.name}' execution started in background.`})):y(u,400,{error:"Automation is disabled"}):y(u,404,{error:"Automation not found"})}if(b==="GET"&&S==="/api/history"){let g=String(E.searchParams.get("session")??"").trim(),m=h(g,"Session history not found.");if(m.error)return y(u,404,m.error);let f=m.sessionKey,k=o.sessionManager.getOrCreate(f);return y(u,200,{session:f,messages:Ir(k.messages)})}if(b==="GET"&&S==="/api/sessions"){let g=o.agent.getRuntimeState(),m=new Set((g.sessions||[]).filter(x=>x.running||x.queued>0).map(x=>x.key)),f=o.sessionManager.getOrCreate(o.sessionKey),k=o.sessionManager.listSessions().filter(x=>String(x.key??"")!==o.sessionKey).map(x=>{let P=String(x.key??"");return Pr({key:P,created_at:String(x.created_at??f.createdAt),updated_at:String(x.updated_at??f.updatedAt)},o.sessionKey,m.has(P),o.sessionManager.getOrCreate(P))});return y(u,200,{currentSession:o.sessionKey,sessions:[Pr({key:f.key,created_at:f.createdAt,updated_at:f.updatedAt},o.sessionKey,m.has(f.key),f),...k]})}if(b==="GET"&&S==="/api/files/preview"){let g=String(E.searchParams.get("path")??"").trim(),m=parseInt(E.searchParams.get("maxLines")??"100",10),f=o.workspacePath??process.cwd();if(!g)return y(u,400,{error:"path required"});try{Be(g,f)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!kt(g))return y(u,404,{error:"file not found"});try{let k=ge.statSync(g);if(k.isDirectory())return y(u,400,{error:"path is a directory"});let x=Ws(g),P=ge.readFileSync(g),T=null,A=!1;if(Ks(x)){let D=P.toString("utf-8").split(`
303
- `);A=D.length>m,T=D.slice(0,m).join(`
304
- `)}let $=xe.extname(g).toLowerCase(),_=x.startsWith("image/")?"image":x==="application/pdf"?"pdf":x==="text/csv"||x==="text/tab-separated-values"?"table":Ks(x)?$===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes($)?"code":"text":"binary";return y(u,200,{name:xe.basename(g),path:g,size:k.size,content:T,truncated:A,mimeType:x,previewType:_,extension:$})}catch(k){return y(u,500,{error:String(k)})}}if(b==="GET"&&S==="/api/files/content"){let g=String(E.searchParams.get("path")??"").trim(),m=o.workspacePath??process.cwd();if(!g)return y(u,400,{error:"path required"});try{Be(g,m)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!kt(g))return y(u,404,{error:"file not found"});try{let f=ge.statSync(g);if(f.isDirectory())return y(u,400,{error:"path is a directory"});u.statusCode=200,u.setHeader("Content-Type",Ws(g)),u.setHeader("Content-Length",String(f.size)),ge.createReadStream(g).pipe(u);return}catch(f){return y(u,500,{error:String(f)})}}if(b==="POST"&&S==="/api/sessions"){let g=await ne(w),m=new Set(o.sessionManager.listSessions().map(_=>String(_.key??"")));m.add(o.sessionKey);let f=String(g.key??"").trim(),k=[...m].map(_=>o.sessionManager.getOrCreate(_)),x=yo(g.label),P=x||Ql(k),T=f||Zl(m,x),A=m.has(T),$=o.sessionManager.getOrCreate(T);return A||($.metadata={...$.metadata,displayName:P},o.sessionManager.save($)),y(u,200,{created:!A,session:Pr({key:$.key,created_at:$.createdAt,updated_at:$.updatedAt},o.sessionKey,!1,$)})}if(V&&b==="PUT"){let g=V[1]?decodeURIComponent(V[1]):void 0;if(!g)return y(u,400,"Invalid session key");let m=h(g,"Session not found.");if(m.error)return y(u,404,m.error);let f=await ne(w),k=yo(f.label),x=Number(f.pinnedOrder),P=Number(f.recentOrder);if(k===void 0&&f.isPinned===void 0&&f.pinnedOrder===void 0&&f.recentOrder===void 0)return y(u,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:g});let T=o.sessionManager.getOrCreate(m.sessionKey);if(T.metadata={...T.metadata},k!==void 0&&(T.metadata.displayName=k),f.isPinned!==void 0&&(T.metadata.isPinned=!!f.isPinned),T.metadata.isPinned===!0){delete T.metadata.recentOrder;let $=[...Hs(o.sessionManager,T.key)],_=Number.isFinite(x)?Math.max(0,Math.min(Math.trunc(x),$.length)):$.length;$.splice(_,0,T),Js(o.sessionManager,$),zs(o.sessionManager,qs(o.sessionManager,T.key))}else{delete T.metadata.pinnedOrder,Js(o.sessionManager,Hs(o.sessionManager,T.key));let $=[...qs(o.sessionManager,T.key)],_=Number.isFinite(P)?Math.max(0,Math.min(Math.trunc(P),$.length)):$.length;$.splice(_,0,T),zs(o.sessionManager,$)}return o.sessionManager.save(T),y(u,200,{ok:!0,session:Pr({key:T.key,created_at:T.createdAt,updated_at:T.updatedAt},o.sessionKey,!1,T)})}if(V&&b==="DELETE"){let g=V[1]?decodeURIComponent(V[1]):void 0;if(!g)return y(u,400,"Invalid session key");let m=h(g,"Session not found.");if(m.error)return y(u,404,m.error);if(m.sessionKey===o.sessionKey)return y(u,400,{error:"The primary session cannot be deleted."});let f=o.sessionManager.delete(m.sessionKey);return y(u,200,{ok:f,session:g})}if(b==="GET"&&S==="/api/suggestions"){let g=String(E.searchParams.get("session")??"").trim(),m=h(g,"Session suggestions not found.");if(m.error)return y(u,404,m.error);let f=m.sessionKey,k=o.sessionManager.getOrCreate(f),x=M(),P=x.subagents?.find(A=>A.id==="advisor"),T=P?P.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let A=Le(x),$=await lo({task:T+`
305
- Return ONLY a JSON array of strings, nothing else.`,provider:A,workspace:o.workspacePath??process.cwd(),model:x.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:x.tools.exec,restrictToWorkspace:x.tools.restrictToWorkspace,existingMessages:Ir(k.messages)}),_=[];try{let D=$.replace(/```json/g,"").replace(/```/g,"").trim();_=JSON.parse(D)}catch{_=ho(k.messages).map(D=>D.text)}let Y=Array.isArray(_)?_.slice(0,3).map((D,fe)=>({id:`suggestion-${fe+1}`,text:String(D),label:_r(String(D),56)??String(D)})):ho(k.messages);return y(u,200,{session:f,suggestions:Y})}catch{return y(u,200,{session:f,suggestions:ho(k.messages)})}}if(b==="GET"&&S==="/api/session-files"){let g=String(E.searchParams.get("session")??"").trim(),m=h(g,"Session files not found.");return m.error?y(u,404,m.error):y(u,200,{session:m.sessionKey,files:c().list(m.sessionKey)})}if(b==="GET"&&S==="/api/inbox-deliveries"){let g=E.searchParams.get("all")==="1",m=d();if(m.list({includeCleared:!0}).filter(x=>!x.clearedAt).length===0){let x=[{jobId:"demo-cron-daily-standup",jobName:"Daily standup reminder",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:`This is a sample cron notification to demonstrate the Inbox functionality. When real cron jobs run and deliver messages, they will appear here.
346
+ Signal: ${o.signal}`:"";return`${e||"Skill install failed."}${t}${n}`.trim()}je();de();import{scrypt as xc,randomBytes as Si,timingSafeEqual as Tc}from"node:crypto";var ki=64,Ci=16384,xi=8,Ti=1,Rc=5,vi=300*1e3;function Ac(){let o=Si(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 Ri(o,e,t,n){let r=n??{};return new Promise((s,i)=>{xc(o,e,t,r,(a,l)=>{a?i(a):s(l)})})}async function Ec(o,e){let t=e??Si(16),n=await Ri(o,t,ki,{N:Ci,r:xi,p:Ti});return`${t.toString("hex")}:${n.toString("hex")}`}async function Pc(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 Ri(o,n,ki,{N:Ci,r:xi,p:Ti});return s.length!==r.length?!1:Tc(s,r)}var Kr=class{config;sessions=new Map;failedAttempts=new Map;constructor(e){this.config=e}updateConfig(e){this.config=e}get isEnabled(){return this.config.enabled}get hasPin(){return this.config.pinHash.length>0}async setPin(e){let t=await Ec(e);return this.config.pinHash=t,t}async verifyPin(e){return this.hasPin?Pc(e,this.config.pinHash):!1}createSession(){let e=Ac(),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)>=Rc}getRateLimitRemainingMs(e){let t=this.failedAttempts.get(e);if(!t||t.timestamps.length===0)return 0;let s=t.timestamps[0]+vi-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()-vi;t.timestamps=t.timestamps.filter(r=>r>n),t.timestamps.length===0&&this.failedAttempts.delete(e)}};function Pi(o){let e=Re.extname(o).toLowerCase();return[".png",".jpg",".jpeg",".gif",".webp",".svg"].includes(e)?`image/${e===".svg"?"svg+xml":e.slice(1)}`:e===".pdf"?"application/pdf":e===".json"?"application/json":e===".md"?"text/markdown":e===".js"||e===".mjs"||e===".cjs"?"text/javascript":e===".ts"||e===".tsx"?"text/typescript":e===".jsx"?"text/jsx":e===".html"?"text/html":e===".css"?"text/css":e===".csv"?"text/csv":e===".tsv"?"text/tab-separated-values":[".txt",".log",".yml",".yaml",".xml",".sh",".py",".rb",".java",".go",".rs"].includes(e)?"text/plain":"application/octet-stream"}function _i(o){return o.startsWith("text/")||o==="application/json"}function Dc(){let o=et("dashboard");if(!o)return null;let e=Re.join(o,"index.html");return fe.existsSync(e)?o:null}function ie(o){return new Promise(e=>{let t="";o.on("data",n=>{t+=n.toString(),t.length>2e6&&o.destroy()}),o.on("end",()=>{try{e(t?JSON.parse(t):{})}catch{e({})}}),o.on("error",()=>e({}))})}function w(o,e,t){o.statusCode=e,o.setHeader("Content-Type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}function jc(o){if(!o.includes(":"))return{channel:null,chatId:null};let[e,t]=o.split(/:(.*)/s,2);return{channel:e||null,chatId:t||null}}function qr(o){return o.map(e=>{let t={...e};return e.reasoning_content&&!e.thinkingContent&&(t.thinkingContent=e.reasoning_content),t})}function zr(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 Fc(o){let e=qr(o),t=[...e].reverse().find(n=>zr(n.content));return{messageCount:e.length,lastMessagePreview:t?zr(t.content,120):null,lastMessageRole:t&&typeof t.role=="string"?t.role:null}}function Bc(o){return o.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Go(o){return typeof o=="string"?o.trim():""}function Di(o){return Go(o?.metadata?.displayName)||null}function Uc(o){let e=new Set;for(let n of o){let r=Di(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 Gc(o,e){let t=Bc(e)||"dashboard",n=t,r=2;for(;o.has(`web:${n}`);)n=`${t}-${r}`,r+=1;return`web:${n}`}function Uo(o){let e=new Set,t=[];for(let n of[...qr(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:zr(r,56)??r}),t.length>=3))break}return t}function Jr(o,e,t,n){let{channel:r,chatId:s}=jc(o.key),i=Fc(n?.messages??[]),a=Number(n?.metadata?.pinnedOrder),l=Number(n?.metadata?.recentOrder);return{key:o.key,channel:r,chatId:s,displayName:Di(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 Mi(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 Ii(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,isPinned:!0,pinnedOrder:n},o.save(t)})}function $i(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 Oi(o,e){e.forEach((t,n)=>{t.metadata={...t.metadata,recentOrder:n},o.save(t)})}function Wc(o){return o.endsWith(".html")?"text/html; charset=utf-8":o.endsWith(".js")?"text/javascript; charset=utf-8":o.endsWith(".css")?"text/css; charset=utf-8":o.endsWith(".json")?"application/json; charset=utf-8":o.endsWith(".svg")?"image/svg+xml":"application/octet-stream"}function it(o){return!!o&&typeof o=="object"&&!Array.isArray(o)}function Wo(o){return!o||o.length<=4?"***":`***${o.slice(-4)}`}function Kc(o){return o==="127.0.0.1"||o==="::1"||o==="::ffff:127.0.0.1"}function Li(o,e,t){return Kc(o.socket.remoteAddress)?!0:(w(e,403,{error:t}),!1)}function Pn(o){return o.map(e=>String(e)).join(".")}function Ko(o,e){let t=o;for(let n of e){if(typeof n=="number"){if(!Array.isArray(t))return;t=t[n];continue}if(!it(t))return;t=t[n]}return t}function Ae(o,e,t){if(e.length===0)return;let n=o;for(let s=0;s<e.length-1;s+=1){let i=e[s];if(typeof i=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${Pn(e)}`);let c=n[i],d=e[s+1];c===void 0&&(n[i]=typeof d=="number"?[]:{}),n=n[i];continue}if(!it(n))throw new Error(`Expected object while writing ${Pn(e)}`);let a=n[i],l=e[s+1];a===void 0&&(n[i]=typeof l=="number"?[]:{}),n=n[i]}let r=e[e.length-1];if(typeof r=="number"){if(!Array.isArray(n))throw new Error(`Expected array while writing ${Pn(e)}`);n[r]=t;return}if(!it(n))throw new Error(`Expected object while writing ${Pn(e)}`);n[r]=t}function Ye(o,e){let t=o.length>0;return{configured:t,preview:t?e?.preview??Wo(o):null}}function Hc(o){let e=structuredClone(o),t={};for(let[n,r]of Object.entries(o.providers??{}))Ae(t,["providers",n,"apiKey"],Ye(r?.apiKey??"")),e.providers[n]&&(e.providers[n].apiKey="");e.customLlmProviders.forEach((n,r)=>{Ae(t,["customLlmProviders",r,"apiKey"],Ye(n?.apiKey??"")),e.customLlmProviders[r]&&(e.customLlmProviders[r].apiKey="")}),Ae(t,["channels","telegram","token"],Ye(o.channels.telegram.token)),Ae(t,["channels","discord","token"],Ye(o.channels.discord.token)),e.channels.telegram.token="",e.channels.discord.token="",Ae(t,["security","auth","pinHash"],Ye(o.security.auth.pinHash,{preview:o.security.auth.pinHash?"[set]":null})),e.security.auth.pinHash="",Ae(t,["tools","browserRelay","authToken"],Ye(o.tools.browserRelay.authToken)),e.tools.browserRelay.authToken="",Ae(t,["tools","web","search","apiKey"],Ye(o.tools.web.search.apiKey)),e.tools.web.search.apiKey="";for(let[n,r]of Object.entries(o.tools.mcpServers??{})){for(let[s,i]of Object.entries(r.env??{}))Ae(t,["tools","mcpServers",n,"env",s],Ye(i)),e.tools.mcpServers[n]?.env?.[s]!==void 0&&(e.tools.mcpServers[n].env[s]="");for(let[s,i]of Object.entries(r.headers??{}))Ae(t,["tools","mcpServers",n,"headers",s],Ye(i)),e.tools.mcpServers[n]?.headers?.[s]!==void 0&&(e.tools.mcpServers[n].headers[s]="")}return{config:e,secretState:t}}function ji(o,e,t,n){let r=Ko(o,e),s=Pn(e);if(r==null){if(!t&&!n)return null;if(!t&&n)return{action:"set",value:n};throw new Error(`Missing secretChanges action for '${s}'.`)}if(!it(r))throw new Error(`Invalid secretChanges entry for '${s}'.`);let i=r.action;if(i!=="keep"&&i!=="clear"&&i!=="set")throw new Error(`Invalid secretChanges action for '${s}'.`);if(i==="set"){let a=typeof r.value=="string"?r.value:n;if(!a)throw new Error(`secretChanges '${s}' must include a non-empty value when action is 'set'.`);return{action:i,value:a}}return{action:i}}function Et(o,e,t,n){let r=String(Ko(e,n)??""),s=String(Ko(o,n)??""),i=ji(t,n,r,s);if(i){if(i.action==="keep"){Ae(o,n,r);return}if(i.action==="clear"){Ae(o,n,"");return}Ae(o,n,i.value??s)}}function Ni(o){return it(o)&&Object.values(o).every(e=>typeof e=="string")}function Jc(o){try{let e=new URL(o);return["http:","https:","ws:","wss:"].includes(e.protocol)}catch{return!1}}function qc(o){if(!it(o))return["tools.mcpServers must be an object."];let e=[],t=new Set;for(let[n,r]of Object.entries(o)){let s=n.trim(),i=s||"(unnamed server)";if(!s){e.push("MCP server names cannot be empty.");continue}let a=s.toLowerCase();if(t.has(a)){e.push(`MCP server '${s}' is duplicated.`);continue}if(t.add(a),!it(r)){e.push(`MCP server '${i}' must be an object.`);continue}let l=typeof r.command=="string"?r.command.trim():"",c=typeof r.url=="string"?r.url.trim():"",d=Number(r.toolTimeout);!l&&!c&&e.push(`MCP server '${i}' requires either a command or a URL.`),l&&c&&e.push(`MCP server '${i}' must use either a command or a URL, not both.`),c&&!Jc(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&&!Ni(r.env)&&e.push(`MCP server '${i}' env must be a string map.`),r.headers!==void 0&&!Ni(r.headers)&&e.push(`MCP server '${i}' headers must be a string map.`),(!Number.isFinite(d)||d<=0)&&e.push(`MCP server '${i}' must have a positive tool timeout.`)}return e}function zc(o){if(Array.isArray(o.customAcpProviders))return o;let e=P();return{...o,customAcpProviders:structuredClone(e.customAcpProviders)}}var Vc=new Set(["/api/auth/login","/api/auth/status","/api/auth/set-pin","/api/browser-relay/config"]),Xc={GET:"\x1B[32m",POST:"\x1B[34m",PUT:"\x1B[33m",DELETE:"\x1B[31m"};function Fi(o){let e=Dc(),t=o.port??o.config.gateway.port??6767,n=o.skillsService??bi(),r=null,s=o.inboxService??null,i=!1;o.config.gateway.dashboard?.enabled!==!1&&!e&&(console.log("[gateway] Dashboard assets not found. The gateway is running in API-only mode."),console.log("[gateway] Install the full package or run `npm run build:dashboard` to enable the web UI."));let l=new Kr(o.config.security.auth),c=()=>(r||(r=new Gr(o.workspacePath??process.cwd(),o.dataDir)),r),d=()=>(s||(s=new Yt(o.workspacePath??process.cwd(),o.dataDir)),s),p=y=>typeof o.sessionManager.listSessions!="function"?y===o.sessionKey:o.sessionManager.listSessions().some(b=>String(b.key??"")===y)||y===o.sessionKey,g=(y,u)=>{let b=y||o.sessionKey;return p(b)?{sessionKey:b}:{error:{error:u,session:b}}},x=Nc(async(y,u)=>{let b=y.method||"GET",R=new URL(y.url||"/",`http://${y.headers.host||"localhost"}`),S=R.pathname;u.setHeader("X-Content-Type-Options","nosniff"),u.setHeader("X-Frame-Options","DENY"),u.setHeader("Referrer-Policy","no-referrer"),u.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:;");let D=Xc[b]??"\x1B[0m";if(console.log(`[gateway] ${D}${b}\x1B[0m ${S}`),l.isEnabled&&S.startsWith("/api/")&&!Vc.has(S)){let h=y.headers["x-auth-token"];if(!h||typeof h!="string"||!l.validateSession(h))return w(u,401,{error:"Authentication required"});l.touchSession(h)}if(!l.isEnabled&&S==="/api/config"&&(b==="GET"||b==="PUT")&&!Li(y,u,"Config access is only available from localhost when dashboard auth is disabled."))return;if(b==="POST"&&S==="/api/auth/login"){let h=await ie(y),f=String(h.pin??"");if(!f)return w(u,400,{error:"PIN is required"});let m=y.socket.remoteAddress??"unknown";if(l.isRateLimited(m)){let A=l.getRateLimitRemainingMs(m);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:A})}if(!l.hasPin)return w(u,400,{error:"No PIN has been set. Use /api/auth/set-pin to set one."});if(!await l.verifyPin(f))return l.recordFailedAttempt(m),w(u,401,{error:"Invalid PIN"});l.clearFailedAttempts(m);let C=l.createSession();return w(u,200,{token:C})}if(b==="GET"&&S==="/api/auth/status")return w(u,200,{authenticated:!1,authEnabled:l.isEnabled,hasPin:l.hasPin});if(b==="POST"&&S==="/api/auth/logout"){let h=y.headers["x-auth-token"];return!h||typeof h!="string"?w(u,200,{ok:!0}):(l.invalidateSession(h),w(u,200,{ok:!0}))}if(b==="POST"&&S==="/api/auth/set-pin"){let h=await ie(y),f=String(h.newPin??""),m=h.currentPin!==void 0?String(h.currentPin):void 0;if(!f)return w(u,400,{error:"newPin is required"});if(f.length!==6)return w(u,400,{error:"PIN must be 6 digits"});if(!/^\d+$/.test(f))return w(u,400,{error:"PIN must contain only digits"});if(l.hasPin){let T=y.headers["x-auth-token"];if(!(T&&typeof T=="string"&&l.validateSession(T))){let _=y.socket.remoteAddress??"unknown";if(l.isRateLimited(_)){let X=l.getRateLimitRemainingMs(_);return w(u,429,{error:"Too many failed attempts. Please try again later.",retryAfterMs:X})}if(!m)return w(u,401,{error:"Current PIN is required to change PIN"});if(!await l.verifyPin(m))return l.recordFailedAttempt(_),w(u,401,{error:"Current PIN is incorrect"});l.clearFailedAttempts(_)}}else{let T=process.env.EVERCLAW_BOOTSTRAP_PIN;if(T&&String(h.bootstrapSecret??"")!==T)return w(u,403,{error:"Bootstrap secret required for first-time PIN setup. Set EVERCLAW_BOOTSTRAP_PIN env var and provide it in the request."})}let k=!l.hasPin,C=await l.setPin(f);k||l.reset();let A=P();return A.security?.auth&&(A.security.auth.pinHash=C,oe(A)),w(u,200,{ok:!0,message:k?"PIN set successfully":"PIN changed successfully"})}let $=()=>w(u,503,{error:"Gateway is shutting down. Please try again later."}),I=S.match(/^\/api\/cron\/jobs\/([^/]+)$/),H=S.match(/^\/api\/cron\/jobs\/([^/]+)\/enable$/),L=S.match(/^\/api\/cron\/jobs\/([^/]+)\/run$/),Q=S.match(/^\/api\/inbox-deliveries\/([^/]+)$/),Y=S.match(/^\/api\/inbox-deliveries\/([^/]+)\/clear$/),F=S.match(/^\/api\/sessions\/([^/]+)$/),z=S.match(/^\/api\/session-files\/([^/]+)$/);if(i&&(b==="POST"&&S==="/api/chat"||b==="POST"&&S==="/api/sessions"||b==="PUT"&&!!F||b==="PUT"&&S==="/api/config"||b==="POST"&&S==="/api/skills/install"||b==="POST"&&!!Y||b==="POST"&&S==="/api/session-files"||b==="POST"&&S==="/api/cron/jobs"||b==="DELETE"&&!!z||b==="DELETE"&&!!I||b==="POST"&&!!H||b==="POST"&&!!L))return $();if(b==="GET"&&S==="/api/status"){let h=P(),f=o.agent.getRuntimeState(),m=o.cron.status(),k=fi({config:h,runtime:f,cron:m}),C=structuredClone(h.channels);C.telegram?.token&&(C.telegram.token=Wo(C.telegram.token)),C.discord?.token&&(C.discord.token=Wo(C.discord.token));let A=o.channelManager?.getStatus()??{};return w(u,200,{provider:h.agents.defaults.provider,model:h.agents.defaults.model,cron:m,channels:C,channelStatus:A,gateway:{...h.gateway,port:t},runtime:f,isolation:k,shutdown:{active:i||!f.acceptingWork,rejectingMutations:i}})}if(b==="GET"&&S==="/api/chrome-session/status"){let h=P(),f=R.searchParams.get("port"),m=f?parseInt(f,10):h.tools.chromeSession?.debugPort??9222,k=h.tools.chromeSession?.minChromeVersion??136,C=await Ut(m);if(!C)return w(u,200,{available:!1,reason:"Chrome remote debugging not detected",hint:"Enable remote debugging in Chrome at chrome://inspect/#remote-debugging or use the Launch Chrome button.",debugPort:m});if(C.pendingApproval)return w(u,200,{available:!1,pendingApproval:!0,reason:"Chrome is running but remote debugging has not been approved yet",hint:"Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to approve the remote debugging connection.",fixCommand:`open -a 'Google Chrome' --args --remote-debugging-port=${C.port} --user-data-dir=/tmp/chrome-debug-profile`,port:C.port,debugPort:m});let{port:A,versionInfo:T}=C,E=T.Browser.match(/(\w+)\/(\d+)/),_=E?.[1]??"Chrome",M=E?parseInt(E[2],10):0;return M>0&&M<k?w(u,200,{available:!1,reason:`Chrome version ${M} is below minimum required version ${k}`,hint:`Update Chrome to version ${k} or higher`,version:T.Browser,port:A,browser:_,debugPort:m}):w(u,200,{available:!0,version:T.Browser,remoteDebugging:!0,port:A,browser:_,debugPort:m})}if(b==="POST"&&S==="/api/chrome-session/launch"){let h=await ie(y),f=P(),m=h.port??f.tools.chromeSession?.debugPort??9222,k=await Ut(m);if(k&&!k.pendingApproval){let M=k.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!1,alreadyRunning:!0,port:k.port,version:k.versionInfo.Browser,browser:M?.[1]??"Chrome",message:`Chrome remote debugging is already active on port ${k.port}. No need to launch.`})}if(k?.pendingApproval)return w(u,200,{ok:!1,launched:!1,pendingApproval:!0,port:k.port,message:"Chrome is running on this port but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow'."});let C="/tmp/chrome-debug-profile",A=Lc(C,"DevToolsActivePort");try{Oc(A)}catch{}let T=process.platform,E,_=[`--remote-debugging-port=${m}`,`--user-data-dir=${C}`];if(T==="darwin"){let M=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",`${process.env.HOME}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,"/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"],X=M.find(j=>At(j));if(!X)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or specify the path manually."});E=X}else if(T==="win32"){E="cmd.exe";let M=process.env.ProgramFiles??"C:\\Program Files",X=process.env.LOCALAPPDATA??"C:\\Users\\Default\\AppData\\Local",j=[`${M}\\Google\\Chrome\\Application\\chrome.exe`,`${X}\\Google\\Chrome\\Application\\chrome.exe`,`${M}\\Microsoft\\Edge\\Application\\msedge.exe`,`${X}\\Microsoft\\Edge\\Application\\msedge.exe`],ge=j.find(ee=>At(ee));if(!ge)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:j,hint:"Install Google Chrome or Microsoft Edge."});_=["/c","start","",ge,`--remote-debugging-port=${m}`]}else{let M=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"],X=M.find(j=>At(j));if(!X)return w(u,500,{ok:!1,error:"No supported Chromium-based browser found",searched:M,hint:"Install Google Chrome or Chromium."});E=X}try{let M=Ei(E,_,{detached:!0,stdio:"ignore"}),X=await Promise.race([new Promise(ee=>M.once("error",ee)),new Promise(ee=>setTimeout(()=>ee(null),500))]);if(X)return w(u,500,{ok:!1,error:X.message,chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"});M.unref();let j;for(let ee=0;ee<5&&(await new Promise(Qe=>setTimeout(Qe,1e3)),j=await Ut(m),!j);ee++);if(!j)return w(u,200,{ok:!1,launched:!0,port:m,chromePath:E,message:"Chrome was launched but CDP is not fully active. You may need to click 'Allow' in Chrome's remote debugging prompt, or try closing all existing Chrome windows first, then retry."});if(j.pendingApproval)return w(u,200,{ok:!1,launched:!0,pendingApproval:!0,port:j.port,chromePath:E,message:"Chrome was launched but remote debugging has not been approved yet. Open chrome://inspect/#remote-debugging in Chrome and click 'Allow' to enable agent control."});let ge=j.versionInfo.Browser.match(/(\w+)\/(\d+)/);return w(u,200,{ok:!0,launched:!0,port:j.port,chromePath:E,version:j.versionInfo.Browser,browser:ge?.[1]??"Chrome",message:`Chrome launched successfully with remote debugging on port ${j.port}`})}catch(M){return w(u,500,{ok:!1,error:M instanceof Error?M.message:String(M),chromePath:E,hint:"Could not launch Chrome. Please start Chrome manually with --remote-debugging-port=9222"})}}if(b==="GET"&&S==="/api/browser-relay/status"){let f=P().tools.browserRelay;if(!f.enabled)return w(u,200,{enabled:!1,connected:!1,attachedTabs:[],extensionPath:f.extensionPath});if(o.browserRelay){let m=o.browserRelay.getStatus();return w(u,200,{enabled:!0,connected:m.connected,attachedTabs:m.attachedTabs,lastPing:m.lastPing,extensionPath:f.extensionPath})}return w(u,200,{enabled:f.enabled,connected:!1,attachedTabs:[],extensionPath:f.extensionPath})}if(b==="GET"&&S==="/api/browser-relay/config"){if(!Li(y,u,"Browser Relay bootstrap is only available from localhost."))return;let h=P(),f=h.tools.browserRelay;return w(u,200,{enabled:f.enabled,port:h.gateway.port,token:f.enabled&&f.authToken||""})}if(b==="POST"&&S==="/api/browser-relay/launch"){let h=await ie(y),f=P(),m=h.extensionPath??f.tools.browserRelay.extensionPath;if(!m)return w(u,400,{ok:!1,error:"No extension path configured",hint:"Set the extension path in Settings > Tools > Browser Relay"});let k=process.platform,C,A=[`--load-extension=${m}`,"--no-first-run","--no-default-browser-check"];if(k==="darwin")C=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"].find(At)??"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";else if(k==="win32"){let T=process.env.ProgramFiles??"C:\\Program Files",E=process.env["ProgramFiles(x86)"]??"C:\\Program Files (x86)";C=[`${T}\\Google\\Chrome\\Application\\chrome.exe`,`${E}\\Google\\Chrome\\Application\\chrome.exe`].find(At)??`${T}\\Google\\Chrome\\Application\\chrome.exe`}else C="google-chrome";try{return Ei(C,A,{detached:!0,stdio:"ignore"}).unref(),w(u,200,{ok:!0,launched:!0,extensionPath:m,message:`Chrome launched with extension from ${m}`})}catch(T){return w(u,500,{ok:!1,error:T instanceof Error?T.message:String(T),hint:"Could not launch Chrome. Please load the extension manually via chrome://extensions"})}}let B=S.match(/^\/api\/automations(?:\/([^/]+))?(\/run)?$/),N=Z(o.config.agents.defaults.workspace);if(b==="GET"&&S==="/api/automations"){let h=Kt(N);return w(u,200,h)}if(b==="GET"&&B&&B[1]&&!B[2]){let h=B[1],f=Te(N,h);return f?w(u,200,f):w(u,404,{error:"Automation not found"})}if(b==="POST"&&S==="/api/automations"){let h=await ie(y);try{let f={name:String(h.name??"Untitled"),description:String(h.description??""),steps:h.steps||[],tags:h.tags||[],source:h.source||"manual"};h.toolType!==void 0&&(f.toolType=h.toolType),h.variables!==void 0&&(f.variables=h.variables);let m=fr(N,f);return w(u,201,m)}catch(f){return w(u,400,{error:String(f)})}}if(b==="PUT"&&B&&B[1]&&!B[2]){let h=B[1],f=await ie(y),m={};f.name!==void 0&&(m.name=String(f.name)),f.description!==void 0&&(m.description=String(f.description)),f.enabled!==void 0&&(m.enabled=!!f.enabled),f.steps!==void 0&&(m.steps=f.steps),f.tags!==void 0&&(m.tags=f.tags),f.toolType!==void 0&&(m.toolType=f.toolType),f.variables!==void 0&&(m.variables=f.variables);let k=hr(N,h,m);return k?w(u,200,k):w(u,404,{error:"Automation not found"})}if(b==="DELETE"&&B&&B[1]){let h=B[1];return Ht(N,h)?w(u,200,{ok:!0}):w(u,404,{error:"Automation not found"})}if(b==="POST"&&B&&B[1]&&B[2]==="/run"){let h=B[1],f=Te(N,h);return f?f.enabled?(o.agent.tools.execute("automation",{command:"run",id:h}).then(m=>{console.log(`[automation] Execution of '${f.name}' finished`,{logs:m.kind==="ok"?m.content:m})}).catch(m=>{console.error(`[automation] Execution of '${f.name}' failed`,{err:m})}),w(u,200,{ok:!0,message:`Automation '${f.name}' execution started in background.`})):w(u,400,{error:"Automation is disabled"}):w(u,404,{error:"Automation not found"})}if(b==="GET"&&S==="/api/history"){let h=String(R.searchParams.get("session")??"").trim(),f=g(h,"Session history not found.");if(f.error)return w(u,404,f.error);let m=f.sessionKey,k=o.sessionManager.getOrCreate(m);return w(u,200,{session:m,messages:qr(k.messages)})}if(b==="GET"&&S==="/api/sessions"){let h=o.agent.getRuntimeState(),f=new Set((h.sessions||[]).filter(C=>C.running||C.queued>0).map(C=>C.key)),m=o.sessionManager.getOrCreate(o.sessionKey),k=o.sessionManager.listSessions().filter(C=>String(C.key??"")!==o.sessionKey).map(C=>{let A=String(C.key??"");return Jr({key:A,created_at:String(C.created_at??m.createdAt),updated_at:String(C.updated_at??m.updatedAt)},o.sessionKey,f.has(A),o.sessionManager.getOrCreate(A))});return w(u,200,{currentSession:o.sessionKey,sessions:[Jr({key:m.key,created_at:m.createdAt,updated_at:m.updatedAt},o.sessionKey,f.has(m.key),m),...k]})}if(b==="GET"&&S==="/api/files/preview"){let h=String(R.searchParams.get("path")??"").trim(),f=parseInt(R.searchParams.get("maxLines")??"100",10),m=o.workspacePath??process.cwd();if(!h)return w(u,400,{error:"path required"});try{Ge(h,m)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!At(h))return w(u,404,{error:"file not found"});try{let k=fe.statSync(h);if(k.isDirectory())return w(u,400,{error:"path is a directory"});let C=Pi(h),A=fe.readFileSync(h),T=null,E=!1;if(_i(C)){let j=A.toString("utf-8").split(`
347
+ `);E=j.length>f,T=j.slice(0,f).join(`
348
+ `)}let _=Re.extname(h).toLowerCase(),M=C.startsWith("image/")?"image":C==="application/pdf"?"pdf":C==="text/csv"||C==="text/tab-separated-values"?"table":_i(C)?_===".md"?"markdown":[".js",".mjs",".cjs",".ts",".tsx",".jsx",".py",".rb",".java",".go",".rs",".sh",".css",".html",".xml",".yml",".yaml"].includes(_)?"code":"text":"binary";return w(u,200,{name:Re.basename(h),path:h,size:k.size,content:T,truncated:E,mimeType:C,previewType:M,extension:_})}catch(k){return w(u,500,{error:String(k)})}}if(b==="GET"&&S==="/api/files/content"){let h=String(R.searchParams.get("path")??"").trim(),f=o.workspacePath??process.cwd();if(!h)return w(u,400,{error:"path required"});try{Ge(h,f)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!At(h))return w(u,404,{error:"file not found"});try{let m=fe.statSync(h);if(m.isDirectory())return w(u,400,{error:"path is a directory"});u.statusCode=200,u.setHeader("Content-Type",Pi(h)),u.setHeader("Content-Length",String(m.size)),fe.createReadStream(h).pipe(u);return}catch(m){return w(u,500,{error:String(m)})}}if(b==="POST"&&S==="/api/sessions"){let h=await ie(y),f=new Set(o.sessionManager.listSessions().map(M=>String(M.key??"")));f.add(o.sessionKey);let m=String(h.key??"").trim(),k=[...f].map(M=>o.sessionManager.getOrCreate(M)),C=Go(h.label),A=C||Uc(k),T=m||Gc(f,C),E=f.has(T),_=o.sessionManager.getOrCreate(T);return E||(_.metadata={..._.metadata,displayName:A},o.sessionManager.save(_)),w(u,200,{created:!E,session:Jr({key:_.key,created_at:_.createdAt,updated_at:_.updatedAt},o.sessionKey,!1,_)})}if(F&&b==="PUT"){let h=F[1]?decodeURIComponent(F[1]):void 0;if(!h)return w(u,400,"Invalid session key");let f=g(h,"Session not found.");if(f.error)return w(u,404,f.error);let m=await ie(y),k=Go(m.label),C=Number(m.pinnedOrder),A=Number(m.recentOrder);if(k===void 0&&m.isPinned===void 0&&m.pinnedOrder===void 0&&m.recentOrder===void 0)return w(u,400,{error:"Session name, isPinned, pinnedOrder, or recentOrder is required.",session:h});let T=o.sessionManager.getOrCreate(f.sessionKey);if(T.metadata={...T.metadata},k!==void 0&&(T.metadata.displayName=k),m.isPinned!==void 0&&(T.metadata.isPinned=!!m.isPinned),T.metadata.isPinned===!0){delete T.metadata.recentOrder;let _=[...Mi(o.sessionManager,T.key)],M=Number.isFinite(C)?Math.max(0,Math.min(Math.trunc(C),_.length)):_.length;_.splice(M,0,T),Ii(o.sessionManager,_),Oi(o.sessionManager,$i(o.sessionManager,T.key))}else{delete T.metadata.pinnedOrder,Ii(o.sessionManager,Mi(o.sessionManager,T.key));let _=[...$i(o.sessionManager,T.key)],M=Number.isFinite(A)?Math.max(0,Math.min(Math.trunc(A),_.length)):_.length;_.splice(M,0,T),Oi(o.sessionManager,_)}return o.sessionManager.save(T),w(u,200,{ok:!0,session:Jr({key:T.key,created_at:T.createdAt,updated_at:T.updatedAt},o.sessionKey,!1,T)})}if(F&&b==="DELETE"){let h=F[1]?decodeURIComponent(F[1]):void 0;if(!h)return w(u,400,"Invalid session key");let f=g(h,"Session not found.");if(f.error)return w(u,404,f.error);if(f.sessionKey===o.sessionKey)return w(u,400,{error:"The primary session cannot be deleted."});let m=o.sessionManager.delete(f.sessionKey);return w(u,200,{ok:m,session:h})}if(b==="GET"&&S==="/api/suggestions"){let h=String(R.searchParams.get("session")??"").trim(),f=g(h,"Session suggestions not found.");if(f.error)return w(u,404,f.error);let m=f.sessionKey,k=o.sessionManager.getOrCreate(m),C=P(),A=C.subagents?.find(E=>E.id==="advisor"),T=A?A.task:"Analyze the conversation and suggest 3 possible next messages the user could send. Return a JSON array of strings.";try{let E=Ne(C),_=await Ao({task:T+`
349
+ Return ONLY a JSON array of strings, nothing else.`,provider:E,workspace:o.workspacePath??process.cwd(),model:C.agents.defaults.model,temperature:.3,maxTokens:500,braveApiKey:null,execConfig:C.tools.exec,restrictToWorkspace:C.tools.restrictToWorkspace,existingMessages:qr(k.messages)}),M=[];try{let j=_.replace(/```json/g,"").replace(/```/g,"").trim();M=JSON.parse(j)}catch{M=Uo(k.messages).map(j=>j.text)}let X=Array.isArray(M)?M.slice(0,3).map((j,ge)=>({id:`suggestion-${ge+1}`,text:String(j),label:zr(String(j),56)??String(j)})):Uo(k.messages);return w(u,200,{session:m,suggestions:X})}catch{return w(u,200,{session:m,suggestions:Uo(k.messages)})}}if(b==="GET"&&S==="/api/session-files"){let h=String(R.searchParams.get("session")??"").trim(),f=g(h,"Session files not found.");return f.error?w(u,404,f.error):w(u,200,{session:f.sessionKey,files:c().list(f.sessionKey)})}if(b==="GET"&&S==="/api/inbox-deliveries"){let h=R.searchParams.get("all")==="1",f=d();if(f.list({includeCleared:!0}).filter(C=>!C.clearedAt).length===0){let C=[{jobId:"demo-cron-daily-standup",jobName:"Daily standup reminder",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:`This is a sample cron notification to demonstrate the Inbox functionality. When real cron jobs run and deliver messages, they will appear here.
306
350
 
307
- This delivery is from a demo cron job that runs daily to remind the team about the standup meeting.`},{jobId:"demo-cron-weekly-report",jobName:"Weekly progress report",sessionKey:"telegram:8281248569",channel:"telegram",recipient:"8281248569",content:"Your weekly progress report is ready. This demo delivery shows how proactive notifications from cron jobs appear in your inbox. You can clear this delivery once reviewed."},{jobId:"demo-cron-backup",jobName:"Backup completed",sessionKey:"default:everclaw",channel:"cli",recipient:"direct",content:"Automated backup completed successfully at 3:00 AM. All project files have been archived to the backup location. This is a demo delivery for testing the inbox clear functionality."}],P=new Date;for(let T=0;T<x.length;T++){let A=x[T],$=new Date(P.getTime()-T*36e5).toISOString();m.record({jobId:A.jobId,jobName:A.jobName,sessionKey:A.sessionKey,channel:A.channel,recipient:A.recipient,content:A.content,deliveredAt:$})}}return y(u,200,{deliveries:m.list({includeCleared:g})})}if(q&&b==="GET"){let g=q[1];if(!g)return y(u,400,"Invalid delivery ID");let m=d().get(decodeURIComponent(g));return m?y(u,200,{delivery:m}):y(u,404,{error:"Inbox delivery not found."})}if(K&&b==="POST"){let g=K[1];if(!g)return y(u,400,"Invalid delivery ID");let m=d().markCleared(decodeURIComponent(g));return m?y(u,200,{ok:!0,delivery:m}):y(u,404,{error:"Inbox delivery not found."})}if(b==="POST"&&S==="/api/session-files"){let g=await ne(w),m=String(g.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(u,404,f.error);try{return y(u,200,c().associate(f.sessionKey,String(g.path??"")))}catch(k){return y(u,400,{error:k instanceof Error?k.message:String(k)})}}if(b==="POST"&&S==="/api/session-files/upload"){let g=await ne(w),m=String(g.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(u,404,f.error);let k=String(g.filename??"").trim(),x=String(g.content??"").trim();if(!k)return y(u,400,{error:"Filename is required."});if(!x)return y(u,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"],T=k.toLowerCase().slice(k.lastIndexOf("."));if(!T||!P.includes(T))return y(u,400,{error:`Unsupported file type. Allowed: ${P.join(", ")}`});try{let A=Buffer.from(x,"base64"),$=xe.join(o.workspacePath??process.cwd(),".session-uploads");ge.existsSync($)||ge.mkdirSync($,{recursive:!0});let _=k.replace(/[^a-zA-Z0-9._-]/g,"_"),Y=xe.join($,`${Date.now()}-${_}`);return ge.writeFileSync(Y,A),y(u,200,c().associate(f.sessionKey,Y))}catch(A){return y(u,400,{error:A instanceof Error?A.message:String(A)})}}if(b==="POST"&&S==="/api/session-files/copy-local"){let g=await ne(w),m=String(g.session??"").trim(),f=h(m,"Session files not found.");if(f.error)return y(u,404,f.error);let k=String(g.path??"").trim(),x=o.workspacePath??process.cwd();if(!k)return y(u,400,{error:"Path is required."});try{Be(k,x)}catch{return y(u,403,{error:"Access denied: path outside workspace"})}if(!ge.existsSync(k))return y(u,404,{error:"File not found."});try{return ge.statSync(k).isDirectory()?y(u,400,{error:"Path is a directory."}):y(u,200,c().associate(f.sessionKey,k))}catch(P){return y(u,400,{error:P instanceof Error?P.message:String(P)})}}if(ie&&b==="GET"){let g=String(E.searchParams.get("session")??"").trim(),m=h(g,"Session files not found.");if(m.error)return y(u,404,m.error);let f=ie[1];if(!f)return y(u,400,"Invalid file ID");let k=c().get(m.sessionKey,decodeURIComponent(f));return k?y(u,200,{session:m.sessionKey,file:k}):y(u,404,{error:"Session file not found.",session:m.sessionKey})}if(ie&&b==="DELETE"){let g=String(E.searchParams.get("session")??"").trim(),m=h(g,"Session files not found.");if(m.error)return y(u,404,m.error);let f=ie[1];return f?y(u,200,{ok:c().remove(m.sessionKey,decodeURIComponent(f))}):y(u,400,"Invalid file ID")}if(b==="POST"&&S==="/api/chat/stream"){let g=await ne(w),m=g.message,f=String(g.session??"default:everclaw"),k=String(g.model??"").trim(),x=String(g._provider??"").trim(),P=Array.isArray(m)?m:String(m??"").trim();if(typeof P=="string"&&!P)return y(u,400,{error:"message required"});if(Array.isArray(P)&&P.length===0)return y(u,400,{error:"message required"});u.setHeader("Content-Type","text/event-stream"),u.setHeader("Cache-Control","no-cache"),u.setHeader("Connection","keep-alive"),u.flushHeaders();let T=_=>{u.write(`data: ${JSON.stringify(_)}
351
+ 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 T=0;T<C.length;T++){let E=C[T],_=new Date(A.getTime()-T*36e5).toISOString();f.record({jobId:E.jobId,jobName:E.jobName,sessionKey:E.sessionKey,channel:E.channel,recipient:E.recipient,content:E.content,deliveredAt:_})}}return w(u,200,{deliveries:f.list({includeCleared:h})})}if(Q&&b==="GET"){let h=Q[1];if(!h)return w(u,400,"Invalid delivery ID");let f=d().get(decodeURIComponent(h));return f?w(u,200,{delivery:f}):w(u,404,{error:"Inbox delivery not found."})}if(Y&&b==="POST"){let h=Y[1];if(!h)return w(u,400,"Invalid delivery ID");let f=d().markCleared(decodeURIComponent(h));return f?w(u,200,{ok:!0,delivery:f}):w(u,404,{error:"Inbox delivery not found."})}if(b==="POST"&&S==="/api/session-files"){let h=await ie(y),f=String(h.session??"").trim(),m=g(f,"Session files not found.");if(m.error)return w(u,404,m.error);try{return w(u,200,c().associate(m.sessionKey,String(h.path??"")))}catch(k){return w(u,400,{error:k instanceof Error?k.message:String(k)})}}if(b==="POST"&&S==="/api/session-files/upload"){let h=await ie(y),f=String(h.session??"").trim(),m=g(f,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(h.filename??"").trim(),C=String(h.content??"").trim();if(!k)return w(u,400,{error:"Filename is required."});if(!C)return w(u,400,{error:"File content is required."});let A=[".md",".txt",".pdf",".jpg",".jpeg",".png",".gif",".webp",".json",".js",".jsx",".ts",".tsx",".css",".html",".xml",".yml",".yaml",".py",".rb",".go",".rs",".java",".c",".cc",".cpp",".h",".hpp",".sh"],T=k.toLowerCase().slice(k.lastIndexOf("."));if(!T||!A.includes(T))return w(u,400,{error:`Unsupported file type. Allowed: ${A.join(", ")}`});try{let E=Buffer.from(C,"base64"),_=Re.join(o.workspacePath??process.cwd(),".session-uploads");fe.existsSync(_)||fe.mkdirSync(_,{recursive:!0});let M=k.replace(/[^a-zA-Z0-9._-]/g,"_"),X=Re.join(_,`${Date.now()}-${M}`);return fe.writeFileSync(X,E),w(u,200,c().associate(m.sessionKey,X))}catch(E){return w(u,400,{error:E instanceof Error?E.message:String(E)})}}if(b==="POST"&&S==="/api/session-files/copy-local"){let h=await ie(y),f=String(h.session??"").trim(),m=g(f,"Session files not found.");if(m.error)return w(u,404,m.error);let k=String(h.path??"").trim(),C=o.workspacePath??process.cwd();if(!k)return w(u,400,{error:"Path is required."});try{Ge(k,C)}catch{return w(u,403,{error:"Access denied: path outside workspace"})}if(!fe.existsSync(k))return w(u,404,{error:"File not found."});try{return fe.statSync(k).isDirectory()?w(u,400,{error:"Path is a directory."}):w(u,200,c().associate(m.sessionKey,k))}catch(A){return w(u,400,{error:A instanceof Error?A.message:String(A)})}}if(z&&b==="GET"){let h=String(R.searchParams.get("session")??"").trim(),f=g(h,"Session files not found.");if(f.error)return w(u,404,f.error);let m=z[1];if(!m)return w(u,400,"Invalid file ID");let k=c().get(f.sessionKey,decodeURIComponent(m));return k?w(u,200,{session:f.sessionKey,file:k}):w(u,404,{error:"Session file not found.",session:f.sessionKey})}if(z&&b==="DELETE"){let h=String(R.searchParams.get("session")??"").trim(),f=g(h,"Session files not found.");if(f.error)return w(u,404,f.error);let m=z[1];return m?w(u,200,{ok:c().remove(f.sessionKey,decodeURIComponent(m))}):w(u,400,"Invalid file ID")}if(b==="POST"&&S==="/api/chat/stream"){let h=await ie(y),f=h.message,m=String(h.session??"default:everclaw"),k=String(h.model??"").trim(),C=String(h._provider??"").trim(),A=Array.isArray(f)?f:String(f??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(u,400,{error:"message required"});u.setHeader("Content-Type","text/event-stream"),u.setHeader("Cache-Control","no-cache"),u.setHeader("Connection","keep-alive"),u.flushHeaders();let T=M=>{u.write(`data: ${JSON.stringify(M)}
308
352
 
309
- `)},A="",$=[];try{let _=await o.agent.processDirectResult(P,f,"cli","dashboard",async(Y,D)=>{if(D?.thinkingContent&&(A=D.thinkingContent),Array.isArray(D?.tool_calls)&&($=D.tool_calls),D?.tool_call&&typeof D.tool_call=="object"){let fe=D.tool_call,Ae=typeof fe.id=="string"?fe.id:"";$=$.some(lt=>lt.id===Ae)?$.map(lt=>lt.id===Ae?{...lt,...fe}:lt):[...$,fe]}switch(D?.event){case"thinking":T({type:"thinking",content:D.thinkingContent??Y});break;case"tool_calls":T({type:"tool_calls",tool_calls:$});break;case"tool_result":T({type:"tool_result",tool_call:D.tool_call,tool_calls:$});break;case"answer":T({type:"answer",content:Y});break;default:T({type:"progress",content:Y,toolHint:!!D?.toolHint,...D?.tool_calls?{tool_calls:D.tool_calls}:{}});break}},{...k?{_model:k}:{},...x?{_provider:x}:{},...Array.isArray(g.skillNames)&&g.skillNames.length?{skillNames:g.skillNames}:{}});_.outcome==="rate_limited"?T({type:"error",error:_.content,outcome:_.outcome,retryAfterMs:_.retryAfterMs??0}):_.outcome==="backpressure"||_.outcome==="shutdown"?T({type:"error",error:_.content,outcome:_.outcome}):T({type:"done",response:_.content,thinkingContent:A,tool_calls:$})}catch(_){T({type:"error",error:String(_)})}finally{u.end()}return}if(b==="POST"&&S==="/api/chat"){let g=await ne(w),m=g.message,f=String(g.session??"default:everclaw"),k=String(g.model??"").trim(),x=String(g._provider??"").trim(),P=Array.isArray(m)?m:String(m??"").trim();if(typeof P=="string"&&!P)return y(u,400,{error:"message required"});if(Array.isArray(P)&&P.length===0)return y(u,400,{error:"message required"});let T=[];try{let A=await o.agent.processDirectResult(P,f,"cli","dashboard",async($,_)=>{T.push({content:$,toolHint:!!_?.toolHint,..._?.tool_calls?{tool_calls:_.tool_calls}:{}})},{...k?{_model:k}:{},...x?{_provider:x}:{}});return A.outcome==="rate_limited"?(u.setHeader("Retry-After",String(Math.max(1,Math.ceil((A.retryAfterMs??0)/1e3)))),y(u,429,{error:A.content,outcome:A.outcome,retryAfterMs:A.retryAfterMs??0,progress:T})):A.outcome==="backpressure"||A.outcome==="shutdown"?y(u,503,{error:A.content,outcome:A.outcome,progress:T}):y(u,200,{response:A.content,progress:T})}catch(A){return y(u,500,{error:String(A)})}}if(b==="GET"&&S==="/api/config")return y(u,200,nc(M()));if(b==="GET"&&S==="/api/security/status"){let{ToolGuardEngine:g}=await Promise.resolve().then(()=>(fo(),Gs)),f=g.getInstance().getRules(),k=f.filter(P=>P.enabled),x=M();return y(u,200,{toolGuard:{enabled:x.security?.toolGuard?.enabled??!1,totalRules:f.length,enabledRules:k.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"&&S==="/api/config"){let g=await ne(w),m=nt(g.config)?g.config:null;if(!m)return y(u,400,{error:"Request body must include a config object."});let f=sc(m),k=M(),x=g.secretChanges;k.security?.auth&&f.security?.auth&&"pinHash"in k.security.auth&&(f.security.auth.pinHash=k.security.auth.pinHash);try{if(f.providers&&k.providers)for(let T of Object.keys(f.providers))f.providers[T]&&k.providers[T]&&Ct(f,k,x,["providers",T,"apiKey"]);if(Array.isArray(f.customLlmProviders)&&Array.isArray(k.customLlmProviders))for(let T=0;T<f.customLlmProviders.length;T++){let A=f.customLlmProviders[T];if(!A)continue;let _=k.customLlmProviders.find(fe=>fe?.name===A.name)?.apiKey??"",Y=A.apiKey??"",D=Qs(x,["customLlmProviders",T,"apiKey"],_,Y);D&&(A.apiKey=D.action==="keep"?_:D.action==="clear"?"":D.value??Y)}if(f.channels&&k.channels&&(Ct(f,k,x,["channels","telegram","token"]),Ct(f,k,x,["channels","discord","token"])),f.tools?.browserRelay&&k.tools?.browserRelay&&Ct(f,k,x,["tools","browserRelay","authToken"]),f.tools?.web?.search&&k.tools?.web?.search&&Ct(f,k,x,["tools","web","search","apiKey"]),f.tools?.mcpServers&&k.tools?.mcpServers)for(let T of Object.keys(f.tools.mcpServers)){let A=f.tools.mcpServers[T];if(A?.env)for(let $ of Object.keys(A.env))Ct(f,k,x,["tools","mcpServers",T,"env",$]);if(A?.headers)for(let $ of Object.keys(A.headers))Ct(f,k,x,["tools","mcpServers",T,"headers",$])}}catch(T){return y(u,400,{error:T instanceof Error?T.message:String(T)})}if(f.security?.auth?.enabled&&!f.security?.auth?.pinHash?.length)return y(u,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let P=oc(f.tools?.mcpServers??{});return P.length?y(u,400,{error:`Invalid MCP server configuration. ${P[0]}`,details:P}):(oe(f),l.updateConfig(f.security.auth),y(u,200,{ok:!0}))}if(b==="GET"&&S==="/api/subagents"){let g=M();return y(u,200,{subagents:g.subagents||[]})}if(b==="POST"&&S==="/api/subagents"){let g=await ne(w),m=M();m.subagents||(m.subagents=[]);let f=m.subagents.length,k={id:`subagent-${Date.now()}`,name:g.name||`SubAgent ${f+1}`,task:g.task||"",createdAt:Date.now()};return m.subagents.push(k),oe(m),y(u,200,k)}let F=S.match(/^\/api\/subagents\/([^/]+)$/);if(F&&b==="PUT"){let g=F[1];if(!g)return y(u,400,"Invalid subagent ID");let m=await ne(w),f=M();f.subagents||(f.subagents=[]);let k=f.subagents.findIndex(T=>T.id===g);if(k===-1)return y(u,404,{error:"Subagent not found"});let x=f.subagents[k];if(!x)return y(u,404,{error:"Subagent not found"});let P={id:m.id??x.id,name:m.name??x.name,task:m.task??x.task,createdAt:m.createdAt??x.createdAt};return f.subagents[k]=P,oe(f),y(u,200,P)}if(F&&b==="DELETE"){let g=F[1],m=M();m.subagents||(m.subagents=[]);let f=m.subagents.findIndex(k=>k.id===g);return f===-1?y(u,404,{error:"Subagent not found"}):(m.subagents.splice(f,1),oe(m),y(u,200,{ok:!0}))}if(b==="GET"&&S==="/api/skills")try{return y(u,200,n.getSnapshot())}catch(g){return y(u,500,{error:String(g)})}if(b==="POST"&&S==="/api/skills/install"){let g=await ne(w);try{let m=await n.install(String(g.slug??""));return y(u,200,m)}catch(m){return y(u,400,{error:m instanceof Error?m.message:String(m)})}}if(b==="GET"&&S==="/api/cron/jobs"){let g=E.searchParams.get("all")==="1";return y(u,200,o.cron.listJobs(g))}if(b==="POST"&&S==="/api/cron/jobs"){let g=await ne(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 y(u,200,f)}catch(m){return y(u,400,{error:String(m)})}}if(I&&b==="DELETE"){let g=I[1];return g?y(u,200,{ok:o.cron.removeJob(g)}):y(u,400,"Invalid job ID")}if(I&&b==="PUT"){let g=I[1];if(!g)return y(u,400,"Invalid job ID");let m=await ne(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 k=o.cron.updateJob(g,f);return k?y(u,200,k):y(u,404,{error:"not found"})}if(J&&b==="POST"){let m=(await ne(w)).enabled!==!1,f=J[1];if(!f)return y(u,400,"Invalid job ID");let k=o.cron.enableJob(f,m);return k?y(u,200,k):y(u,404,{error:"not found"})}if(re&&b==="POST"){let g=await ne(w),m=re[1];if(!m)return y(u,400,"Invalid job ID");let f=await o.cron.runJob(m,!!g.force);return y(u,200,{ok:f})}let z=o.config.gateway.dashboard?.enabled!==!1;if(z&&e){let g=xe.resolve(e,S==="/"?"index.html":S.slice(1));if(!g.startsWith(xe.resolve(e)+xe.sep)&&g!==xe.resolve(e)&&(g=xe.join(e,"index.html")),(!ge.existsSync(g)||ge.statSync(g).isDirectory())&&(g=xe.join(e,"index.html")),!ge.existsSync(g)){u.statusCode=404,u.end("Dashboard assets not found. Run npm run build.");return}u.statusCode=200,u.setHeader("Content-Type",ec(g)),ge.createReadStream(g).pipe(u);return}if(!S.startsWith("/api/")){u.statusCode=404,u.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}u.statusCode=404,u.end("Dashboard is disabled. API endpoints are still available.")});return v.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(v),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((w,u)=>v.close(b=>{try{r?.close(),s?.close()}catch{}b?u(b):w()})))}}le();import{spawn as Mr}from"node:child_process";import{createWriteStream as lc,existsSync as Ht,lstatSync as cc,mkdirSync as dc,readdirSync as uc,rmSync as wn}from"node:fs";import $r from"node:path";import{pipeline as gc}from"node:stream/promises";var Re="0.28.0",ei="https://github.com/rtk-ai/rtk/releases",ti=3e4,Lr={"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"},mc=200,pc=5e3;function ni(o){return Math.ceil(o.length/4)}function xt(o,e){let t=c=>c.split(".").map(d=>parseInt(d,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var Ee=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return $r.join(Sn(),"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&&xt(n,Re))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 ${Re}). 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=Lr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Lr).join(", ")}`);let s=o.binaryPath(),i=$r.dirname(s);if(!e?.force&&Ht(s)){let c=await this.getVersion(s);if(c&&xt(c,Re))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${ei}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${ei}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Ht(i)||dc(i,{recursive:!0});let l=$r.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:d}=await import("node:fs");d(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{Ht(l)&&wn(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),ti);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 gc(n.fromWeb(i.body),lc(t))}catch(i){throw wn(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${ti}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=Mr("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((d,p)=>{l.on("close",h=>{h===0?d():p(new Error(`tar extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{wn(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of uc(e)){let s=$r.join(e,r),i=cc(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=Mr("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((d,p)=>{l.on("close",h=>{h===0?d():p(new Error(`PowerShell extraction failed with code ${h}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{wn(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Ht(e)&&wn(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=Mr(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<mc)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=ni(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=ni(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=Mr(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},pc);i.stdout?.on("data",d=>{a+=d.toString()}),i.stderr?.on("data",d=>{l+=d.toString()}),i.stdin?.end(e,"utf8"),i.on("close",d=>{clearTimeout(c),d===0?n(a):r(new Error(`rtk exited with code ${d}: ${l}`))}),i.on("error",d=>{clearTimeout(c),r(d)})})}};import{randomUUID as fc}from"node:crypto";import vo,{WebSocketServer as hc}from"ws";var So=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
353
+ `)},E="",_=[];try{let M,X={...k?{_model:k}:{},...C?{_provider:C}:{},...Array.isArray(h.skillNames)&&h.skillNames.length?{skillNames:h.skillNames}:{},...h._notification?{_notification:h._notification}:{}};h._notification&&(M=h._notification);let j=await o.agent.processDirectResult(A,m,"cli","dashboard",async(ge,ee)=>{if(ee?.thinkingContent&&(E=ee.thinkingContent),Array.isArray(ee?.tool_calls)&&(_=ee.tool_calls),ee?.tool_call&&typeof ee.tool_call=="object"){let Qe=ee.tool_call,In=typeof Qe.id=="string"?Qe.id:"";_=_.some(gt=>gt.id===In)?_.map(gt=>gt.id===In?{...gt,...Qe}:gt):[..._,Qe]}switch(ee?.event){case"thinking":T({type:"thinking",content:ee.thinkingContent??ge});break;case"tool_calls":T({type:"tool_calls",tool_calls:_});break;case"tool_result":T({type:"tool_result",tool_call:ee.tool_call,tool_calls:_});break;case"answer":T({type:"answer",content:ge});break;default:T({type:"progress",content:ge,toolHint:!!ee?.toolHint,...ee?.tool_calls?{tool_calls:ee.tool_calls}:{}});break}},X);j.outcome==="rate_limited"?T({type:"error",error:j.content,outcome:j.outcome,retryAfterMs:j.retryAfterMs??0}):j.outcome==="backpressure"||j.outcome==="shutdown"?T({type:"error",error:j.content,outcome:j.outcome}):(M&&T({type:"notification",notification:M}),T({type:"done",response:j.content,thinkingContent:E,tool_calls:_,...M?{_notification:M}:{}}))}catch(M){T({type:"error",error:String(M)})}finally{u.end()}return}if(b==="POST"&&S==="/api/chat"){let h=await ie(y),f=h.message,m=String(h.session??"default:everclaw"),k=String(h.model??"").trim(),C=String(h._provider??"").trim(),A=Array.isArray(f)?f:String(f??"").trim();if(typeof A=="string"&&!A)return w(u,400,{error:"message required"});if(Array.isArray(A)&&A.length===0)return w(u,400,{error:"message required"});let T=[];try{let E=await o.agent.processDirectResult(A,m,"cli","dashboard",async(_,M)=>{T.push({content:_,toolHint:!!M?.toolHint,...M?.tool_calls?{tool_calls:M.tool_calls}:{}})},{...k?{_model:k}:{},...C?{_provider:C}:{}});return E.outcome==="rate_limited"?(u.setHeader("Retry-After",String(Math.max(1,Math.ceil((E.retryAfterMs??0)/1e3)))),w(u,429,{error:E.content,outcome:E.outcome,retryAfterMs:E.retryAfterMs??0,progress:T})):E.outcome==="backpressure"||E.outcome==="shutdown"?w(u,503,{error:E.content,outcome:E.outcome,progress:T}):w(u,200,{response:E.content,progress:T})}catch(E){return w(u,500,{error:String(E)})}}if(b==="GET"&&S==="/api/config")return w(u,200,Hc(P()));if(b==="GET"&&S==="/api/security/status"){let{ToolGuardEngine:h}=await Promise.resolve().then(()=>(Bo(),Ai)),m=h.getInstance().getRules(),k=m.filter(A=>A.enabled),C=P();return w(u,200,{toolGuard:{enabled:C.security?.toolGuard?.enabled??!1,totalRules:m.length,enabledRules:k.length,defaultRules:m.filter(A=>!A.id.startsWith("user-")).length,userRules:C.security?.toolGuard?.rules?.length??0},skillScanner:{enabled:C.security?.skillScanner?.enabled??!1}})}if(b==="PUT"&&S==="/api/config"){let h=await ie(y),f=it(h.config)?h.config:null;if(!f)return w(u,400,{error:"Request body must include a config object."});let m=zc(f),k=P(),C=h.secretChanges;k.security?.auth&&m.security?.auth&&"pinHash"in k.security.auth&&(m.security.auth.pinHash=k.security.auth.pinHash);try{if(m.providers&&k.providers)for(let T of Object.keys(m.providers))m.providers[T]&&k.providers[T]&&Et(m,k,C,["providers",T,"apiKey"]);if(Array.isArray(m.customLlmProviders)&&Array.isArray(k.customLlmProviders))for(let T=0;T<m.customLlmProviders.length;T++){let E=m.customLlmProviders[T];if(!E)continue;let M=k.customLlmProviders.find(ge=>ge?.name===E.name)?.apiKey??"",X=E.apiKey??"",j=ji(C,["customLlmProviders",T,"apiKey"],M,X);j&&(E.apiKey=j.action==="keep"?M:j.action==="clear"?"":j.value??X)}if(m.channels&&k.channels&&(Et(m,k,C,["channels","telegram","token"]),Et(m,k,C,["channels","discord","token"])),m.tools?.browserRelay&&k.tools?.browserRelay&&Et(m,k,C,["tools","browserRelay","authToken"]),m.tools?.web?.search&&k.tools?.web?.search&&Et(m,k,C,["tools","web","search","apiKey"]),m.tools?.mcpServers&&k.tools?.mcpServers)for(let T of Object.keys(m.tools.mcpServers)){let E=m.tools.mcpServers[T];if(E?.env)for(let _ of Object.keys(E.env))Et(m,k,C,["tools","mcpServers",T,"env",_]);if(E?.headers)for(let _ of Object.keys(E.headers))Et(m,k,C,["tools","mcpServers",T,"headers",_])}}catch(T){return w(u,400,{error:T instanceof Error?T.message:String(T)})}if(m.security?.auth?.enabled&&!m.security?.auth?.pinHash?.length)return w(u,400,{error:"Cannot enable PIN authentication without setting a PIN. Use the 'Set PIN' button first.",field:"security.auth.enabled"});let A=qc(m.tools?.mcpServers??{});return A.length?w(u,400,{error:`Invalid MCP server configuration. ${A[0]}`,details:A}):(oe(m),l.updateConfig(m.security.auth),w(u,200,{ok:!0}))}if(b==="GET"&&S==="/api/subagents"){let h=P();return w(u,200,{subagents:h.subagents||[]})}if(b==="POST"&&S==="/api/subagents"){let h=await ie(y),f=P();f.subagents||(f.subagents=[]);let m=f.subagents.length,k={id:`subagent-${Date.now()}`,name:h.name||`SubAgent ${m+1}`,task:h.task||"",createdAt:Date.now(),...h.type?{type:h.type}:{},...h.contextMode?{contextMode:h.contextMode}:{}};return f.subagents.push(k),oe(f),w(u,200,k)}let J=S.match(/^\/api\/subagents\/([^/]+)$/);if(J&&b==="PUT"){let h=J[1];if(!h)return w(u,400,"Invalid subagent ID");let f=await ie(y),m=P();m.subagents||(m.subagents=[]);let k=m.subagents.findIndex(X=>X.id===h);if(k===-1)return w(u,404,{error:"Subagent not found"});let C=m.subagents[k];if(!C)return w(u,404,{error:"Subagent not found"});let A={id:f.id??C.id,name:f.name??C.name,task:f.task??C.task,createdAt:f.createdAt??C.createdAt},T=f.provider!==void 0?f.provider:C.provider,E=f.model!==void 0?f.model:C.model,_=f.type!==void 0?f.type:C.type,M=f.contextMode!==void 0?f.contextMode:C.contextMode;return T&&(A.provider=T),E&&(A.model=E),_&&(A.type=_),M&&(A.contextMode=M),m.subagents[k]=A,oe(m),w(u,200,A)}if(J&&b==="DELETE"){let h=J[1],f=P();f.subagents||(f.subagents=[]);let m=f.subagents.findIndex(k=>k.id===h);return m===-1?w(u,404,{error:"Subagent not found"}):(f.subagents.splice(m,1),oe(f),w(u,200,{ok:!0}))}if(b==="GET"&&S==="/api/skills")try{return w(u,200,n.getSnapshot())}catch(h){return w(u,500,{error:String(h)})}if(b==="POST"&&S==="/api/skills/install"){let h=await ie(y);try{let f=await n.install(String(h.slug??""));return w(u,200,f)}catch(f){return w(u,400,{error:f instanceof Error?f.message:String(f)})}}if(b==="GET"&&S==="/api/cron/jobs"){let h=R.searchParams.get("all")==="1";return w(u,200,o.cron.listJobs(h))}if(b==="POST"&&S==="/api/cron/jobs"){let h=await ie(y);try{let f={name:String(h.name??"job"),schedule:h.schedule,message:String(h.message??""),deliver:!!h.deliver,deleteAfterRun:!!h.deleteAfterRun};h.channel&&(f.channel=String(h.channel)),h.to&&(f.to=String(h.to));let m=o.cron.addJob(f);return w(u,200,m)}catch(f){return w(u,400,{error:String(f)})}}if(I&&b==="DELETE"){let h=I[1];return h?w(u,200,{ok:o.cron.removeJob(h)}):w(u,400,"Invalid job ID")}if(I&&b==="PUT"){let h=I[1];if(!h)return w(u,400,"Invalid job ID");let f=await ie(y),m={};f.name!==void 0&&(m.name=String(f.name)),f.schedule!==void 0&&(m.schedule=f.schedule),f.message!==void 0&&(m.message=String(f.message)),f.deliver!==void 0&&(m.deliver=!!f.deliver),f.channel!==void 0&&(m.channel=String(f.channel)),f.to!==void 0&&(m.to=String(f.to)),f.deleteAfterRun!==void 0&&(m.deleteAfterRun=!!f.deleteAfterRun);let k=o.cron.updateJob(h,m);return k?w(u,200,k):w(u,404,{error:"not found"})}if(H&&b==="POST"){let f=(await ie(y)).enabled!==!1,m=H[1];if(!m)return w(u,400,"Invalid job ID");let k=o.cron.enableJob(m,f);return k?w(u,200,k):w(u,404,{error:"not found"})}if(L&&b==="POST"){let h=await ie(y),f=L[1];if(!f)return w(u,400,"Invalid job ID");let m=await o.cron.runJob(f,!!h.force);return w(u,200,{ok:m})}let G=o.config.gateway.dashboard?.enabled!==!1;if(G&&e){let h=Re.resolve(e,S==="/"?"index.html":S.slice(1));if(!h.startsWith(Re.resolve(e)+Re.sep)&&h!==Re.resolve(e)&&(h=Re.join(e,"index.html")),(!fe.existsSync(h)||fe.statSync(h).isDirectory())&&(h=Re.join(e,"index.html")),!fe.existsSync(h)){u.statusCode=404,u.end("Dashboard assets not found. Run npm run build.");return}u.statusCode=200,u.setHeader("Content-Type",Wc(h)),fe.createReadStream(h).pipe(u);return}if(!S.startsWith("/api/")){u.statusCode=404,u.end(G?"Dashboard assets not found. Install the full package or run `npm run build:dashboard`.":"Dashboard is disabled. API endpoints are still available.");return}u.statusCode=404,u.end("Dashboard is disabled. API endpoints are still available.")});return x.listen(t,o.config.gateway.host),o.browserRelay&&(o.browserRelay.attachToServer(x),console.log("[gateway] Browser relay WebSocket endpoint mounted at /ws/browser-relay")),{beginShutdown:()=>{i=!0},port:t,close:()=>(i=!0,new Promise((y,u)=>x.close(b=>{try{r?.close(),s?.close()}catch{}b?u(b):y()})))}}de();import{spawn as Vr}from"node:child_process";import{createWriteStream as Yc,existsSync as Qt,lstatSync as Qc,mkdirSync as Zc,readdirSync as ed,rmSync as _n}from"node:fs";import Xr from"node:path";import{pipeline as td}from"node:stream/promises";var Ee="0.28.0",Bi="https://github.com/rtk-ai/rtk/releases",Ui=3e4,Yr={"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"},nd=200,rd=5e3;function Gi(o){return Math.ceil(o.length/4)}function Pt(o,e){let t=c=>c.split(".").map(d=>parseInt(d,10)||0),[n=0,r=0,s=0]=t(o),[i=0,a=0,l=0]=t(e);return n!==i?n>=i:r!==a?r>=a:s>=l}var Pe=class o{runtime={available:!1,binaryPath:"",version:null};static binaryPath(){let e=process.platform==="win32"?"rtk.exe":"rtk";return Xr.join(On(),"bin",e)}async resolve(e){if(!e.enabled)return this.runtime={available:!1,binaryPath:"",version:null},this.runtime;let t=o.binaryPath();if(Qt(t)){let n=await this.getVersion(t);if(n&&Pt(n,Ee))return this.runtime={available:!0,binaryPath:t,version:n},this.runtime;if(e.autoInstall&&process.env.CI!=="true"){console.error(`[rtk] Binary outdated (${n}, need ${Ee}). Re-downloading...`);try{return await this.install({version:e.version,force:!0})}catch(r){return console.error(`[rtk] Failed to re-download: ${r instanceof Error?r.message:String(r)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}if(e.autoInstall&&process.env.CI!=="true")try{return await this.install({version:e.version})}catch(n){return console.error(`[rtk] Auto-download failed: ${n instanceof Error?n.message:String(n)}`),this.runtime={available:!1,binaryPath:"",version:null},this.runtime}return this.runtime={available:!1,binaryPath:"",version:null},this.runtime}async install(e){let t=e?.version??"latest",n=`${process.platform}-${process.arch}`,r=Yr[n];if(!r)throw new Error(`Unsupported platform: ${n}. Supported platforms: ${Object.keys(Yr).join(", ")}`);let s=o.binaryPath(),i=Xr.dirname(s);if(!e?.force&&Qt(s)){let c=await this.getVersion(s);if(c&&Pt(c,Ee))return this.runtime={available:!0,binaryPath:s,version:c},this.runtime}let a;if(t==="latest")a=`${Bi}/latest/download/${r}`;else{let c=`v${t.replace(/^v/,"")}`;a=`${Bi}/download/${c}/${r}`}console.error(`[rtk] Downloading from ${a}...`),Qt(i)||Zc(i,{recursive:!0});let l=Xr.join(i,`.rtk-download-${Date.now()}.${r.endsWith(".zip")?"zip":"tar.gz"}`);try{if(await this.downloadFile(a,l),r.endsWith(".zip")?await this.extractZip(l,s):await this.extractTarGz(l,s),process.platform!=="win32"){let{chmodSync:d}=await import("node:fs");d(s,493)}let c=await this.getVersion(s);if(!c)throw new Error("Downloaded binary failed version check");return console.error(`[rtk] Installed v${c} to ${s}`),this.runtime={available:!0,binaryPath:s,version:c},this.runtime}finally{Qt(l)&&_n(l,{force:!0})}}async downloadFile(e,t){let{Readable:n}=await import("node:stream"),r=new AbortController,s=setTimeout(()=>r.abort(),Ui);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 td(n.fromWeb(i.body),Yc(t))}catch(i){throw _n(t,{force:!0}),i instanceof Error&&i.name==="AbortError"?new Error(`Download timed out after ${Ui}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=Vr("tar",["-xzf",e,"-C",a],{stdio:["ignore","pipe","pipe"]});await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`tar extraction failed with code ${g}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{_n(a,{recursive:!0,force:!0})}}findBinaryInDir(e,t){let n=process.platform==="win32"?[`${t}.exe`,t]:[t];for(let r of ed(e)){let s=Xr.join(e,r),i=Qc(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=Vr("powershell",["-Command",`Expand-Archive -LiteralPath '${e.replace(/'/g,"''")}' -DestinationPath '${a.replace(/'/g,"''")}' -Force`]);await new Promise((d,p)=>{l.on("close",g=>{g===0?d():p(new Error(`PowerShell extraction failed with code ${g}`))}),l.on("error",p)});let c=this.findBinaryInDir(a,"rtk");if(!c)throw new Error("Could not find rtk binary in extracted archive");n(c,t)}finally{_n(a,{recursive:!0,force:!0})}}async uninstall(){let e=o.binaryPath();Qt(e)&&_n(e,{force:!0}),this.runtime={available:!1,binaryPath:"",version:null}}getRuntime(){return this.runtime}async getStatus(){let e=o.binaryPath();return Qt(e)?{installed:!0,version:await this.getVersion(e),binaryPath:e}:{installed:!1,version:null,binaryPath:e}}async getVersion(e){return new Promise(t=>{let n=Vr(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<nd)return{stdout:e.stdout,stderr:e.stderr,compressed:!1,originalTokens:0,compressedTokens:0};let t=Gi(e.stdout);try{let n=await this.runRtkSummary(e.stdout,e.ultraCompact),r=Gi(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=Vr(this.runtime.binaryPath,s),a="",l="",c=setTimeout(()=>{i.kill("SIGKILL"),r(new Error("rtk compression timed out"))},rd);i.stdout?.on("data",d=>{a+=d.toString()}),i.stderr?.on("data",d=>{l+=d.toString()}),i.stdin?.end(e,"utf8"),i.on("close",d=>{clearTimeout(c),d===0?n(a):r(new Error(`rtk exited with code ${d}: ${l}`))}),i.on("error",d=>{clearTimeout(c),r(d)})})}};import{randomUUID as od}from"node:crypto";import Ho,{WebSocketServer as sd}from"ws";var Jo=class{wss=null;extension=null;config;onStatusChange;constructor(e,t){this.config=e,this.onStatusChange=t}handleUpgrade(e,t,n){if(!this.wss){t.destroy();return}let s=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`).searchParams.get("token");if(!this.config.enabled){t.write(`HTTP/1.1 503 Service Unavailable\r
310
354
  \r
311
355
  Browser relay is disabled`),t.destroy();return}if(s!==this.config.authToken){t.write(`HTTP/1.1 401 Unauthorized\r
312
356
  \r
313
- Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new hc({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===vo.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===vo.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!==vo.OPEN)throw new Error("Extension not connected");let r=fc(),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() {
357
+ Invalid auth token`),t.destroy();return}this.wss.handleUpgrade(e,t,n,i=>{this.handleConnection(i)})}attachToServer(e){this.wss=new sd({noServer:!0}),e.on("upgrade",(t,n,r)=>{new URL(t.url||"/",`http://${t.headers.host||"localhost"}`).pathname==="/ws/browser-relay"&&this.handleUpgrade(t,n,r)})}handleConnection(e){this.extension&&this.extension.ws.close();let t={ws:e,attachedTabs:new Set,lastPing:Date.now(),pendingCommands:new Map};this.extension=t,this.notifyStatusChange(),e.on("message",r=>{try{let s=JSON.parse(r.toString());this.handleMessage(t,s)}catch{}}),e.on("close",()=>{if(this.extension===t){for(let[,{reject:r,timeout:s}]of t.pendingCommands)clearTimeout(s),r(new Error("Extension disconnected"));this.extension=null,this.notifyStatusChange()}});let n=setInterval(()=>{e.readyState===Ho.OPEN&&e.send(JSON.stringify({type:"ping"}))},2e4);e.on("close",()=>clearInterval(n))}handleMessage(e,t){if(t.type==="pong"){e.lastPing=Date.now();return}if(t.type!=="cdp_event"){if(t.id&&e.pendingCommands.has(String(t.id))){let n=e.pendingCommands.get(String(t.id));e.pendingCommands.delete(String(t.id)),clearTimeout(n.timeout),t.error?n.reject(new Error(String(t.error))):n.resolve(t.result);return}t.type==="status"&&Array.isArray(t.attachedTabs)&&(e.attachedTabs=new Set(t.attachedTabs.map(Number)),this.notifyStatusChange())}}notifyStatusChange(){this.onStatusChange&&this.onStatusChange(this.getStatus())}getStatus(){return this.extension?{connected:this.extension.ws.readyState===Ho.OPEN,attachedTabs:[...this.extension.attachedTabs],lastPing:this.extension.lastPing}:{connected:!1,attachedTabs:[]}}async sendCommand(e,t={},n=3e4){if(!this.extension||this.extension.ws.readyState!==Ho.OPEN)throw new Error("Extension not connected");let r=od(),s={id:r,method:e,params:t};return new Promise((i,a)=>{let l=setTimeout(()=>{this.extension?.pendingCommands.delete(r),a(new Error("Command timeout"))},n);this.extension.pendingCommands.set(r,{resolve:i,reject:a,timeout:l}),this.extension.ws.send(JSON.stringify(s))})}async listTabs(){return await this.sendCommand("tabs.list")}async navigate(e,t){await this.sendCommand("tabs.navigate",{tabId:e,url:t})}async click(e,t){let r=(await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
314
358
  const el = document.querySelector(${JSON.stringify(t)});
315
359
  if (!el) throw new Error('Element not found: ' + ${JSON.stringify(t)});
316
360
  el.scrollIntoView({ block: 'center' });
317
- el.click();
318
- return 'clicked';
319
- })()`,returnByValue:!0}})}async type(e,t,n){n&&await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
361
+ const rect = el.getBoundingClientRect();
362
+ return JSON.stringify({ x: rect.x, y: rect.y, width: rect.width, height: rect.height });
363
+ })()`,returnByValue:!0}}))?.result,s=JSON.parse(r?.value??"{}"),i=s.x+s.width/2,a=s.y+s.height/2;await this.sendCommand("cdp.send",{tabId:e,method:"Input.dispatchMouseEvent",params:{type:"mousePressed",x:i,y:a,button:"left",clickCount:1}}),await this.sendCommand("cdp.send",{tabId:e,method:"Input.dispatchMouseEvent",params:{type:"mouseReleased",x:i,y:a,button:"left",clickCount:1}})}async type(e,t,n){n&&await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:`(function() {
320
364
  const el = document.querySelector(${JSON.stringify(n)});
321
365
  if (!el) throw new Error('Element not found: ' + ${JSON.stringify(n)});
322
366
  el.scrollIntoView({ block: 'center' });
323
367
  el.focus();
324
368
  if (el.value !== undefined) el.value = '';
325
369
  return 'focused';
326
- })()`,returnByValue:!0}}),await this.sendCommand("cdp.send",{tabId:e,method:"Input.insertText",params:{text:t}})}async screenshot(e,t="png"){let n=await this.sendCommand("tabs.screenshot",{tabId:e,format:t});return n?.dataUrl??String(n)}async evaluate(e,t){let n=await this.sendCommand("cdp.send",{tabId:e,method:"Runtime.evaluate",params:{expression:t,returnByValue:!0}}),r=n?.result;return r?.type==="string"||r?.type==="number"||r?.type==="boolean"||r?.value!==void 0?r.value:n}async attachTab(e){await this.sendCommand("debugger.attach",{tabId:e}),this.extension?.attachedTabs.add(e),this.notifyStatusChange()}async detachTab(e){await this.sendCommand("debugger.detach",{tabId:e}),this.extension?.attachedTabs.delete(e),this.notifyStatusChange()}close(){this.extension&&(this.extension.ws.close(),this.extension=null),this.wss&&(this.wss.close(),this.wss=null)}};function ri(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new So(t,e)}fo();function yc(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function bc(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Or=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:yc(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=bc(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})}};hn();import wc from"node:path";import vc from"node:os";var oi=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],si=["command","cmd"],Sc=[{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."}],ii=vc.homedir();function kc(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,ii),e=e.replace(/\$HOME(?=[/\\])/,ii),e}function Cc(o,e){let t=[];for(let n of oi){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 si){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!oi.includes(n)&&!si.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var Dr=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=Cc(r,n);for(let i of s){let a=kc(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let d=this.checkWorkspaceEscape(a,n);d&&t.push(d)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of Sc)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(!wc.isAbsolute(e))return null;try{Be(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"}};hn();import ko from"node:fs";import ai from"node:path";var xc=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"]),Tc=8192,Rc=.01;function Ec(o){let e=Math.min(o.length,Tc);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=Rc}var rt=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(xc.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let h;try{h=ko.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(Ec(h)){i.skippedFiles++;continue}let v=h.toString("utf8"),w={filePath:p.absPath,extension:p.ext,size:p.size,content:v};for(let u of this.analyzers){let b=u.analyze(w);a.push(...b)}i.scannedFiles++}let c=Ac(a),d=!a.some(p=>p.severity==="CRITICAL"||p.severity==="HIGH");return{skillName:t,findings:a,isSafe:d,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=ko.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=ai.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=ko.lstatSync(i),l=ai.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function Ac(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"}hn();le();import Pc from"node:fs";var Ic=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"]),_c=8192,Mc=.01,ot=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=Ye("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=Pc.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,_c);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=Mc}isSkippedExtension(e){return Ic.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:fn[i.category]??"COMMAND_INJECTION",severity:pn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};var Tt={debug:0,info:1,warn:2,error:3};function li(o,e){return Tt[o]>=Tt[e]}var ci=[/api[_-]?key/i,/apikey/i,/secret/i,/token/i,/password/i,/pin/i,/credential/i,/credentials/i,/private[_-]?key/i,/privatekey/i,/auth/i,/session[_-]?id/i],di=[/^[A-Za-z0-9_-]{20,}$/,/^\d+:[A-Za-z0-9_-]{30,}$/,/^sk-[A-Za-z0-9]{20,}$/,/^sk-or-v1-[A-Za-z0-9]{20,}$/,/^Bearer\s+/i],Co=200;import vn from"node:fs";import $c from"node:path";var Nr=class{constructor(e,t){this.logsDir=e;this.maxFileSizeBytes=t;this.ensureLogsDir()}currentHour=null;currentFilePath=null;writeError=!1;ensureLogsDir(){try{vn.existsSync(this.logsDir)||vn.mkdirSync(this.logsDir,{recursive:!0,mode:448})}catch(e){console.error(`[logging] Failed to create logs directory: ${e instanceof Error?e.message:String(e)}`),this.writeError=!0}}getCurrentHourKey(){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return`${t}-${n}-${r}-${s}`}resolveCurrentFile(){let e=this.getCurrentHourKey();return(this.currentHour!==e||this.currentFilePath===null)&&(this.currentHour=e,this.currentFilePath=$c.join(this.logsDir,`gateway-${e}.jsonl`)),this.currentFilePath}checkFileSize(e){try{return vn.statSync(e).size<this.maxFileSizeBytes}catch{return!0}}append(e){if(!this.writeError)try{let t=this.resolveCurrentFile();if(vn.existsSync(t)&&!this.checkFileSize(t)){console.warn(`[logging] Log file ${t} exceeded max size, skipping write`);return}let n=JSON.stringify(e)+`
327
- `;vn.appendFileSync(t,n,"utf8")}catch(t){if(t instanceof Error){let n=t;if(n.code==="ENOSPC"){console.warn("[logging] Disk full, disabling file logging"),this.writeError=!0;return}if(n.code==="EACCES"){console.warn("[logging] Permission denied, disabling file logging"),this.writeError=!0;return}}console.error(`[logging] Failed to write log entry: ${t instanceof Error?t.message:String(t)}`)}}hasWriteError(){return this.writeError}resetWriteError(){this.writeError=!1}};import ui from"node:fs";import Lc from"node:path";var jr=class{constructor(e,t){this.logsDir=e;this.retentionHours=t}timer=null;purge(){let e=Date.now(),t=this.retentionHours*60*60*1e3,n=e-t;try{let r=ui.readdirSync(this.logsDir);for(let s of r){if(!s.startsWith("gateway-")||!s.endsWith(".jsonl"))continue;let i=s.slice(8,-6),a=this.parseHourTimestamp(i);if(a!==null&&a<n){let l=Lc.join(this.logsDir,s);try{ui.unlinkSync(l)}catch(c){console.warn(`[logging] Failed to purge ${s}: ${c instanceof Error?c.message:String(c)}`)}}}}catch(r){console.warn(`[logging] Purge scan failed: ${r instanceof Error?r.message:String(r)}`)}}parseHourTimestamp(e){let t=/^(\d{4})-(\d{2})-(\d{2})-(\d{2})$/.exec(e);if(!t)return null;let n=parseInt(t[1],10),r=parseInt(t[2],10)-1,s=parseInt(t[3],10),i=parseInt(t[4],10),a=new Date(n,r,s,i,0,0,0);return Number.isNaN(a.getTime())?null:a.getTime()}startTimer(e){this.timer===null&&(this.timer=setInterval(()=>{this.purge()},e),this.timer.unref())}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};function Oc(o){return ci.some(e=>e.test(o))}function Dc(o){return typeof o!="string"||o.length<10?!1:di.some(e=>e.test(o))}function xo(o,e){return o.length<=e?o:o.slice(0,e-1)+"\u2026"}function To(o,e,t=0){if(t>5)return"[max depth reached]";if(Oc(o))return typeof e=="string"&&e.length>0?e.length>8?`${e.slice(0,4)}****${e.slice(-4)}`:"****":"[REDACTED]";if(Dc(e))return"[REDACTED]";if(typeof e=="string")return o.toLowerCase().includes("content")||o.toLowerCase().includes("message")?xo(e,Co):e;if(Array.isArray(e))return e.length>20?[`[array of ${e.length} items]`]:e.map((n,r)=>To(`[${r}]`,n,t+1));if(e instanceof Error)return{name:e.name,message:xo(e.message,Co),stack:e.stack?xo(e.stack,500):void 0};if(e!==null&&typeof e=="object"){let n={},r=Object.entries(e);if(r.length>50)return`[object with ${r.length} keys]`;for(let[s,i]of r)n[s]=To(s,i,t+1);return n}return e}function gi(o){let e={};for(let[t,n]of Object.entries(o))e[t]=To(t,n,0);return e}var Fr=class o{static instance=null;writer;purger;level;enabled;started=!1;constructor(e,t){this.enabled=e.enabled,this.level=e.level,this.writer=new Nr(t,e.maxFileSizeMb*1024*1024),this.purger=new jr(t,e.retentionHours)}static getInstance(e,t){return o.instance||(o.instance=new o(e,t)),o.instance}static resetInstance(){o.instance&&(o.instance.stop(),o.instance=null)}start(){this.started||(this.started=!0,this.purger.purge(),this.purger.startTimer(6e5))}stop(){this.started&&(this.started=!1,this.purger.stopTimer())}log(e,t,n,r){let s=r?gi(r):{};if(this.writeToConsole(e,t,n,s),!this.enabled||!li(e,this.level))return;let i={ts:new Date().toISOString(),level:e,category:t,event:n,data:s};this.writer.append(i)}info(e,t,n){this.log("info",e,t,n)}warn(e,t,n){this.log("warn",e,t,n)}error(e,t,n){this.log("error",e,t,n)}debug(e,t,n){this.log("debug",e,t,n)}writeToConsole(e,t,n,r){let s=new Date().toISOString(),i=this.formatConsolePrefix(t),a=this.formatDataPreview(r);switch(e){case"error":console.error(`${s} ${i} ${n} ${a}`);break;case"warn":console.warn(`${s} ${i} ${n} ${a}`);break;default:console.log(`${s} ${i} ${n} ${a}`)}}formatConsolePrefix(e){return`${{"message.inbound":"\x1B[36m","message.outbound":"\x1B[35m","agent.turn":"\x1B[32m","agent.tool":"\x1B[33m",gateway:"\x1B[34m",channel:"\x1B[35m",security:"\x1B[31m"}[e]??"\x1B[0m"}[${e}]\x1B[0m`}formatDataPreview(e){let t=[];for(let[n,r]of Object.entries(e)){if(t.length>=3)break;let s=typeof r=="string"&&r.length>40?`${r.slice(0,39)}\u2026`:String(r);t.push(`${n}=${s}`)}return t.join(" ")}};le();async function mi(o){let e=structuredClone(o?.config??M()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=X(e.agents.defaults.workspace);ut(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:
370
+ })()`,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 Wi(o,e){let t=o.tools.browserRelay;return!t.enabled||!t.authToken?null:new Jo(t,e)}Bo();function id(o){if(o==="*")return/^.*$/;let e=o.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${e}$`)}function ad(o){if(o==null)return"";if(typeof o!="object")return String(o);try{return JSON.stringify(o)}catch{return""}}var Qr=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:id(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=ad(r);for(let i of this.compiledRules){if(!i.toolNameRegex.test(n))continue;let a=i.paramRegex.exec(s);a&&t.push({id:`rule-${i.rule.id}-${Date.now()}-${t.length}`,ruleId:i.rule.id,category:i.rule.category,severity:i.rule.severity.toUpperCase(),title:i.rule.description,description:i.rule.description,toolName:n,matchedValue:a[0],matchedPattern:i.rule.paramPattern,remediation:i.rule.action==="deny"?"This action is blocked by security policy.":"This pattern has been flagged for review.",guardian:this.name})}return t}matchRules(e,t){return this.guard({toolName:e,params:t})}};An();import ld from"node:path";import cd from"node:os";var Ki=["file_path","filepath","filePath","path","directory","dir","filename","target","destination","dest","source","src","output_path","outputPath","input_path","inputPath","log_file","logFile"],Hi=["command","cmd"],dd=[{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."}],Ji=cd.homedir();function ud(o){let e=o.trim();return e=e.replace(/^~(?=[/\\])/,Ji),e=e.replace(/\$HOME(?=[/\\])/,Ji),e}function gd(o,e){let t=[];for(let n of Ki){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 Hi){let r=o[n];typeof r=="string"&&r.length>0&&t.push(r)}for(let[n,r]of Object.entries(o))typeof r=="string"&&!Ki.includes(n)&&!Hi.includes(n)&&/[./\\~$]/.test(r)&&r.length>0&&r.length<4096&&t.push(r);return t}var Zr=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=gd(r,n);for(let i of s){let a=ud(i),l=this.checkPathTraversal(i,a,n);l&&t.push(l);let c=this.checkSensitivePaths(i,a,n);t.push(...c);let d=this.checkWorkspaceEscape(a,n);d&&t.push(d)}return t}checkPathTraversal(e,t,n){return/\.\.\//.test(e)||/\.\.\\/.test(e)?{id:`file-traversal-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-path-traversal",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Path traversal detected",description:`Path traversal pattern '../' detected in path: '${this.truncateForDisplay(e)}'. This could allow access to files outside the intended directory.`,toolName:n,matchedValue:e,matchedPattern:"\\.\\./",remediation:"Avoid using relative paths with '../' sequences.",guardian:this.name}:/%00|%0[dD]/.test(e)?{id:`null-byte-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-null-byte",category:"PATH_TRAVERSAL",severity:"HIGH",title:"Null byte injection detected",description:`Null byte injection pattern detected in path: '${this.truncateForDisplay(e)}'. This could bypass path validation.`,toolName:n,matchedValue:e,matchedPattern:"%00|%0[dD]",remediation:"Do not include null bytes in path strings.",guardian:this.name}:null}checkSensitivePaths(e,t,n){let r=[],s=new Set([e,t]);for(let i of s)for(let a of dd)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(!ld.isAbsolute(e))return null;try{Ge(e,this.workspace)}catch{return{id:`workspace-escape-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ruleId:"file-workspace-escape",category:"PATH_TRAVERSAL",severity:"MEDIUM",title:"Workspace escape detected",description:`Absolute path '${this.truncateForDisplay(e)}' is outside the configured workspace '${this.workspace}'.`,toolName:t,matchedValue:this.truncateForDisplay(e),remediation:"Use paths within the configured workspace directory.",guardian:this.name}}return null}truncateForDisplay(e,t=200){return e.length<=t?e:e.slice(0,t)+"\u2026"}};An();import qo from"node:fs";import qi from"node:path";var md=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"]),pd=8192,fd=.01;function hd(o){let e=Math.min(o.length,pd);if(e===0)return!1;let t=0;for(let n=0;n<e;n++)o[n]===0&&t++;return t/e>=fd}var at=class{analyzers;constructor(e=[]){this.analyzers=e}scanSkill(e,t,n){let r=n?.maxFileCount??1e3,s=n?.maxFileSizeBytes??5242880,i={scannedFiles:0,skippedFiles:0,symlinksSkipped:0,oversizedFiles:0},a=[],l=this.walkDirectory(e,i);for(let p of l){if(i.scannedFiles>=r){i.skippedFiles++;continue}if(md.has(p.ext)){i.skippedFiles++;continue}if(p.size>s){i.oversizedFiles++;continue}let g;try{g=qo.readFileSync(p.absPath)}catch{i.skippedFiles++;continue}if(hd(g)){i.skippedFiles++;continue}let x=g.toString("utf8"),y={filePath:p.absPath,extension:p.ext,size:p.size,content:x};for(let u of this.analyzers){let b=u.analyze(y);a.push(...b)}i.scannedFiles++}let c=yd(a),d=!a.some(p=>p.severity==="CRITICAL"||p.severity==="HIGH");return{skillName:t,findings:a,isSafe:d,maxSeverity:c,stats:i}}walkDirectory(e,t){let n=[],r;try{r=qo.readdirSync(e,{withFileTypes:!0})}catch{return n}for(let s of r){let i=qi.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=qo.lstatSync(i),l=qi.extname(s.name).toLowerCase();n.push({absPath:i,ext:l,size:a.size})}catch{t.skippedFiles++}}return n}};function yd(o){if(o.length===0)return"SAFE";let e={CRITICAL:5,HIGH:4,MEDIUM:3,LOW:2,INFO:1,SAFE:0},t=0;for(let n of o){let r=e[n.severity]??0;r>t&&(t=r)}for(let[n,r]of Object.entries(e))if(r===t)return n;return"SAFE"}An();de();import bd from"node:fs";var wd=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"]),vd=8192,Sd=.01,lt=class{name="PatternAnalyzer";signatures=null;compiledPatterns=new Map;loadSignatures(){if(this.signatures)return this.signatures;try{let e=et("security","skill-scanner","rules","signatures.json");if(!e)return this.signatures=[],[];let t=bd.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,vd);if(t===0)return!1;let n=0;for(let r=0;r<t;r++)e.charCodeAt(r)===0&&n++;return n/t>=Sd}isSkippedExtension(e){return wd.has(e)}analyze(e){let{extension:t,content:n}=e,r=[];if(this.isSkippedExtension(t)||this.isBinaryContent(n))return r;let s=this.loadSignatures();for(let i of s){if(!i.fileTypes.includes(t))continue;let a=this.compilePattern(i.id,i.pattern);if(!a)continue;a.lastIndex=0,a.exec(n)&&r.push({id:i.id,category:Rn[i.category]??"COMMAND_INJECTION",severity:Tn[i.severity]??"MEDIUM",pattern:i.pattern,fileTypes:i.fileTypes,title:i.title,description:i.description,remediation:i.remediation})}return r}};var _t={debug:0,info:1,warn:2,error:3};function zi(o,e){return _t[o]>=_t[e]}var Vi=[/api[_-]?key/i,/apikey/i,/secret/i,/token/i,/password/i,/pin/i,/credential/i,/credentials/i,/private[_-]?key/i,/privatekey/i,/auth/i,/session[_-]?id/i],Xi=[/^[A-Za-z0-9_-]{20,}$/,/^\d+:[A-Za-z0-9_-]{30,}$/,/^sk-[A-Za-z0-9]{20,}$/,/^sk-or-v1-[A-Za-z0-9]{20,}$/,/^Bearer\s+/i],zo=200;import Mn from"node:fs";import kd from"node:path";var eo=class{constructor(e,t){this.logsDir=e;this.maxFileSizeBytes=t;this.ensureLogsDir()}currentHour=null;currentFilePath=null;writeError=!1;ensureLogsDir(){try{Mn.existsSync(this.logsDir)||Mn.mkdirSync(this.logsDir,{recursive:!0,mode:448})}catch(e){console.error(`[logging] Failed to create logs directory: ${e instanceof Error?e.message:String(e)}`),this.writeError=!0}}getCurrentHourKey(){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return`${t}-${n}-${r}-${s}`}resolveCurrentFile(){let e=this.getCurrentHourKey();return(this.currentHour!==e||this.currentFilePath===null)&&(this.currentHour=e,this.currentFilePath=kd.join(this.logsDir,`gateway-${e}.jsonl`)),this.currentFilePath}checkFileSize(e){try{return Mn.statSync(e).size<this.maxFileSizeBytes}catch{return!0}}append(e){if(!this.writeError)try{let t=this.resolveCurrentFile();if(Mn.existsSync(t)&&!this.checkFileSize(t)){console.warn(`[logging] Log file ${t} exceeded max size, skipping write`);return}let n=JSON.stringify(e)+`
371
+ `;Mn.appendFileSync(t,n,"utf8")}catch(t){if(t instanceof Error){let n=t;if(n.code==="ENOSPC"){console.warn("[logging] Disk full, disabling file logging"),this.writeError=!0;return}if(n.code==="EACCES"){console.warn("[logging] Permission denied, disabling file logging"),this.writeError=!0;return}}console.error(`[logging] Failed to write log entry: ${t instanceof Error?t.message:String(t)}`)}}hasWriteError(){return this.writeError}resetWriteError(){this.writeError=!1}};import Yi from"node:fs";import Cd from"node:path";var to=class{constructor(e,t){this.logsDir=e;this.retentionHours=t}timer=null;purge(){let e=Date.now(),t=this.retentionHours*60*60*1e3,n=e-t;try{let r=Yi.readdirSync(this.logsDir);for(let s of r){if(!s.startsWith("gateway-")||!s.endsWith(".jsonl"))continue;let i=s.slice(8,-6),a=this.parseHourTimestamp(i);if(a!==null&&a<n){let l=Cd.join(this.logsDir,s);try{Yi.unlinkSync(l)}catch(c){console.warn(`[logging] Failed to purge ${s}: ${c instanceof Error?c.message:String(c)}`)}}}}catch(r){console.warn(`[logging] Purge scan failed: ${r instanceof Error?r.message:String(r)}`)}}parseHourTimestamp(e){let t=/^(\d{4})-(\d{2})-(\d{2})-(\d{2})$/.exec(e);if(!t)return null;let n=parseInt(t[1],10),r=parseInt(t[2],10)-1,s=parseInt(t[3],10),i=parseInt(t[4],10),a=new Date(n,r,s,i,0,0,0);return Number.isNaN(a.getTime())?null:a.getTime()}startTimer(e){this.timer===null&&(this.timer=setInterval(()=>{this.purge()},e),this.timer.unref())}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};function xd(o){return Vi.some(e=>e.test(o))}function Td(o){return typeof o!="string"||o.length<10?!1:Xi.some(e=>e.test(o))}function Vo(o,e){return o.length<=e?o:o.slice(0,e-1)+"\u2026"}function Xo(o,e,t=0){if(t>5)return"[max depth reached]";if(xd(o))return typeof e=="string"&&e.length>0?e.length>8?`${e.slice(0,4)}****${e.slice(-4)}`:"****":"[REDACTED]";if(Td(e))return"[REDACTED]";if(typeof e=="string")return o.toLowerCase().includes("content")||o.toLowerCase().includes("message")?Vo(e,zo):e;if(Array.isArray(e))return e.length>20?[`[array of ${e.length} items]`]:e.map((n,r)=>Xo(`[${r}]`,n,t+1));if(e instanceof Error)return{name:e.name,message:Vo(e.message,zo),stack:e.stack?Vo(e.stack,500):void 0};if(e!==null&&typeof e=="object"){let n={},r=Object.entries(e);if(r.length>50)return`[object with ${r.length} keys]`;for(let[s,i]of r)n[s]=Xo(s,i,t+1);return n}return e}function Qi(o){let e={};for(let[t,n]of Object.entries(o))e[t]=Xo(t,n,0);return e}var no=class o{static instance=null;writer;purger;level;enabled;started=!1;constructor(e,t){this.enabled=e.enabled,this.level=e.level,this.writer=new eo(t,e.maxFileSizeMb*1024*1024),this.purger=new to(t,e.retentionHours)}static getInstance(e,t){return o.instance||(o.instance=new o(e,t)),o.instance}static resetInstance(){o.instance&&(o.instance.stop(),o.instance=null)}start(){this.started||(this.started=!0,this.purger.purge(),this.purger.startTimer(6e5))}stop(){this.started&&(this.started=!1,this.purger.stopTimer())}log(e,t,n,r){let s=r?Qi(r):{};if(this.writeToConsole(e,t,n,s),!this.enabled||!zi(e,this.level))return;let i={ts:new Date().toISOString(),level:e,category:t,event:n,data:s};this.writer.append(i)}info(e,t,n){this.log("info",e,t,n)}warn(e,t,n){this.log("warn",e,t,n)}error(e,t,n){this.log("error",e,t,n)}debug(e,t,n){this.log("debug",e,t,n)}writeToConsole(e,t,n,r){let s=new Date().toISOString(),i=this.formatConsolePrefix(t),a=this.formatDataPreview(r);switch(e){case"error":console.error(`${s} ${i} ${n} ${a}`);break;case"warn":console.warn(`${s} ${i} ${n} ${a}`);break;default:console.log(`${s} ${i} ${n} ${a}`)}}formatConsolePrefix(e){return`${{"message.inbound":"\x1B[36m","message.outbound":"\x1B[35m","agent.turn":"\x1B[32m","agent.tool":"\x1B[33m",gateway:"\x1B[34m",channel:"\x1B[35m",security:"\x1B[31m"}[e]??"\x1B[0m"}[${e}]\x1B[0m`}formatDataPreview(e){let t=[];for(let[n,r]of Object.entries(e)){if(t.length>=3)break;let s=typeof r=="string"&&r.length>40?`${r.slice(0,39)}\u2026`:String(r);t.push(`${n}=${s}`)}return t.join(" ")}};de();async function Zi(o){let e=structuredClone(o?.config??P()),t=o?.port??e.gateway.port??6767;e.gateway.port=t;let n=Z(e.agents.defaults.workspace);ft(n,!0);let r=e.gateway.host,s=r==="127.0.0.1"||r==="localhost"||r==="::1",i=e.gateway.dashboard?.enabled!==!1,a=e.security?.auth?.enabled===!0;if(!s&&i&&!a)throw new Error("Dashboard is exposed on a non-loopback address ("+r+`) but authentication is not configured. Either:
328
372
  1. Set security.auth.enabled = true and configure a PIN
329
373
  2. Set gateway.host = 127.0.0.1 (loopback only)
330
- 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new ft,c=o?.provider??Le(e),d=new et(n),p=je(),h=new Kt(n,p),v=vr(e.tools.exec.timeout),w=gn({target:"scheduled-job",timeoutMs:v}),u=gn({target:"background-job",timeoutMs:v}),{cron:b,heartbeat:E,lifecycle:S}=qe({cron:{dataDir:p,onJob:async(O,F)=>{let z=await w.run({payload:{message:O.payload.message,session:`cron:${O.id}`,channel:O.payload.channel??"cli",chatId:O.payload.to??"direct"},cwd:process.cwd(),signal:F?.signal});if(O.payload.deliver&&O.payload.to){let g=O.payload.channel??"cli",m=O.payload.to;await l.publishOutbound({channel:g,chatId:m,content:z});try{h.record({jobId:O.id,jobName:O.name,sessionKey:`cron:${O.id}`,channel:g,recipient:m,content:z})}catch(f){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${O.id}: ${f instanceof Error?f.message:String(f)}`)}}return z}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(O,F)=>{let g=d.listSessions().find(k=>(k.key??"").includes(":"))?.key??"cli:direct",[m,f]=g.split(/:(.*)/s,2);return u.run({payload:{message:O,session:"heartbeat",channel:m||"cli",chatId:f||"direct"},cwd:process.cwd(),signal:F?.signal})},onNotify:async O=>{let z=d.listSessions().find(f=>(f.key??"").includes(":"))?.key??"",[g,m]=z?z.split(/:(.*)/s,2):["cli","direct"];g!=="cli"&&g&&await l.publishOutbound({channel:g,chatId:m??"direct",content:O})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!E)throw new Error("Builtin heartbeat job registration is missing");let N=Fr.getInstance(e.logging,Ue());N.start(),N.info("gateway","start",{port:t,host:e.gateway.host,pid:process.pid,channels:e.channels.telegram.enabled||e.channels.discord.enabled?[e.channels.telegram.enabled?"telegram":null,e.channels.discord.enabled?"discord":null].filter(Boolean):[]});let U,I;e.security.enabled&&(e.security.toolGuard.enabled&&(U=yn.getInstance(e),U.registerGuardian(new Or(U.getRules())),U.registerGuardian(new Dr(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(I=new rt([new ot]),console.log("[security] Skill scanner initialized")));let J=new Ee,re=await J.resolve(e.tools.rtk);re.available?console.log(`rtk ${re.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 O=ri(e,F=>{F.connected&&console.log(`[browser-relay] Extension connected, ${F.attachedTabs.length} tabs attached`)});O&&(q=O,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let K=new Gt({bus:l,provider:c,workspace:n,sessionManager:d,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:S,loadConfig:M,rtkConfig:e.tools.rtk,rtkService:J,...U?{guardEngine:U}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...I?{skillScanner:I}:{},...q?{browserRelay:q}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),V=new Cr(e,l,S),ie=Zs({agent:K,cron:b,config:e,dataDir:p,port:t,sessionManager:d,sessionKey:o?.sessionKey??"default:everclaw",inboxService:h,workspacePath:n,channelManager:V,...q?{browserRelay:q}:{}});await b.start(),await E.start();let R=K.run();return await V.startAll(),{config:e,workspace:n,port:ie.port,loop:K,heartbeat:E,cron:b,channels:V,dashboard:ie,enabledChannels:V.enabledChannels,runPromise:R,browserRelay:q,logger:N}}async function Ro(o){o.logger?.info("gateway","stop",{reason:"shutdown"}),o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Dt.getInstance().stopAll(),await o.dashboard.close(),o.logger?.stop(),e}import B from"chalk";import{Command as Nc}from"commander";Fe();var W={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function pi(){let o=new Nc("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
374
+ 3. Set gateway.dashboard.enabled = false (API-only mode)`);let l=new wt,c=o?.provider??Ne(e),d=new ot(n),p=Be(),g=new Yt(n,p),x=Dr(e.tools.exec.timeout),y=Cn({target:"scheduled-job",timeoutMs:x}),u=Cn({target:"background-job",timeoutMs:x}),{cron:b,heartbeat:R,lifecycle:S}=Ve({cron:{dataDir:p,onJob:async(N,J)=>{let G=null,h=null;try{G=await y.run({payload:{message:N.payload.message,session:`cron:${N.id}`,channel:N.payload.channel??"cli",chatId:N.payload.to??"direct"},cwd:process.cwd(),signal:J?.signal})}catch(A){h=A instanceof Error?A.message:String(A)}let f=N.payload.channel??"cli",m=N.payload.to??"direct";if(N.payload.deliver&&N.payload.to&&G){await l.publishOutbound({channel:f,chatId:m,content:G});try{g.record({jobId:N.id,jobName:N.name,sessionKey:`cron:${N.id}`,channel:f,recipient:m,content:G})}catch(A){console.warn(`[dashboard] Failed to record inbox delivery for cron job ${N.id}: ${A instanceof Error?A.message:String(A)}`)}}let k={kind:"cron_completed",taskId:N.id,label:N.name,status:G?"completed":"failed",result:G??"",error:h??"",originalTask:N.payload.message},C={channel:"system",senderId:"cron",chatId:`${f}:${m}`,content:G??h??"Cron job completed",metadata:{_notification:k}};return await l.publishInbound(C),G??h??"Cron job failed"}},heartbeat:{workspace:n,provider:c,model:e.agents.defaults.model,onExecute:async(N,J)=>{let h=d.listSessions().find(k=>(k.key??"").includes(":"))?.key??"cli:direct",[f,m]=h.split(/:(.*)/s,2);return u.run({payload:{message:N,session:"heartbeat",channel:f||"cli",chatId:m||"direct"},cwd:process.cwd(),signal:J?.signal})},onNotify:async N=>{let G=d.listSessions().find(m=>(m.key??"").includes(":"))?.key??"",[h,f]=G?G.split(/:(.*)/s,2):["cli","direct"];h!=="cli"&&h&&await l.publishOutbound({channel:h,chatId:f??"direct",content:N})},intervalS:e.gateway.heartbeat.intervalS,enabled:e.gateway.heartbeat.enabled}});if(!R)throw new Error("Builtin heartbeat job registration is missing");let D=no.getInstance(e.logging,We());D.start(),D.info("gateway","start",{port:t,host:e.gateway.host,pid:process.pid,channels:e.channels.telegram.enabled||e.channels.discord.enabled?[e.channels.telegram.enabled?"telegram":null,e.channels.discord.enabled?"discord":null].filter(Boolean):[]});let $,I;e.security.enabled&&(e.security.toolGuard.enabled&&($=En.getInstance(e),$.registerGuardian(new Qr($.getRules())),$.registerGuardian(new Zr(n)),console.log("[security] Tool guard engine initialized with guardians")),e.security.skillScanner.enabled&&(I=new at([new lt]),console.log("[security] Skill scanner initialized")));let H=new Pe,L=await H.resolve(e.tools.rtk);L.available?console.log(`rtk ${L.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 N=Wi(e,J=>{J.connected&&console.log(`[browser-relay] Extension connected, ${J.attachedTabs.length} tabs attached`)});N&&(Q=N,console.log("[browser-relay] WebSocket endpoint ready at /ws/browser-relay"))}let Y=new zt({bus:l,provider:c,workspace:n,sessionManager:d,model:e.agents.defaults.model,temperature:e.agents.defaults.temperature,maxTokens:e.agents.defaults.maxTokens,maxIterations:e.agents.defaults.maxToolIterations,memoryWindow:e.agents.defaults.memoryWindow,braveApiKey:e.tools.web.search.apiKey||null,execConfig:e.tools.exec,cronService:b,restrictToWorkspace:e.tools.restrictToWorkspace,channelsConfig:e.channels,lifecycle:S,loadConfig:P,rtkConfig:e.tools.rtk,rtkService:H,...$?{guardEngine:$}:{},...e.security.skillScanner.enabled?{skillScannerConfig:e.security.skillScanner}:{},...I?{skillScanner:I}:{},...Q?{browserRelay:Q}:{},...e.tools.chromeSession?.enabled?{chromeSessionConfig:e.tools.chromeSession}:{}}),F=new Br(e,l,S),z=Fi({agent:Y,cron:b,config:e,dataDir:p,port:t,sessionManager:d,sessionKey:o?.sessionKey??"default:everclaw",inboxService:g,workspacePath:n,channelManager:F,...Q?{browserRelay:Q}:{}});await b.start(),await R.start();let B=Y.run();return await F.startAll(),{config:e,workspace:n,port:z.port,loop:Y,heartbeat:R,cron:b,channels:F,dashboard:z,enabledChannels:F.enabledChannels,runPromise:B,browserRelay:Q,logger:D}}async function Yo(o){o.logger?.info("gateway","stop",{reason:"shutdown"}),o.dashboard.beginShutdown?.(),o.loop.beginShutdown(),o.heartbeat.stop(),o.cron.stop();let e=await o.loop.shutdown();return await o.channels.stopAll(),Wt.getInstance().stopAll(),await o.dashboard.close(),o.logger?.stop(),e}import K from"chalk";import{Command as Rd}from"commander";Ue();var W={SUCCESS:0,GENERAL_ERROR:1,CONNECTIVITY_ERROR:2,SECURITY_ERROR:3,PROCESS_CONFLICT:4};function ea(){let o=new Rd("rtk").description("Manage rtk token compression binary");return o.addHelpText("after",`
331
375
  Examples:
332
376
  everclaw rtk install Install the latest rtk binary
333
377
  everclaw rtk update Update to the latest version
334
- 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 Ee;try{let n=await t.install({version:e.version,force:e.force});console.log(B.green(`
335
- 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=W.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Ee,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 Ee().getStatus(),n=M();console.log(B.cyan(`
378
+ 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 Pe;try{let n=await t.install({version:e.version,force:e.force});console.log(K.green(`
379
+ rtk v${n.version} installed to ${n.binaryPath}`)),console.log(K.gray("Token compression is now enabled for shell command outputs."))}catch(n){console.error(K.red(`Failed to install rtk: ${n instanceof Error?n.message:String(n)}`)),process.exitCode=W.CONNECTIVITY_ERROR}}),o.command("uninstall").description("Remove the managed rtk binary").action(async()=>{let e=new Pe,t=await e.getStatus();if(!t.installed){console.log(K.yellow("rtk is not installed."));return}await e.uninstall(),console.log(K.green(`Removed ${t.binaryPath}`))}),o.command("status").description("Show rtk installation status").action(async()=>{let t=await new Pe().getStatus(),n=P();console.log(K.cyan(`
336
380
  RTK Token Compression
337
- `)),t.installed&&t.version?(console.log(` Status: ${B.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),xt(t.version,Re)||(console.log(B.yellow(` Warning: Version ${t.version} is below minimum ${Re}`)),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(`
338
- Minimum version: ${Re}`)),console.log(B.gray(` Supported platforms: ${Object.keys(Lr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Ee,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(`
339
- 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=W.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=M();if(e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(B.green("RTK token compression enabled.")),console.log(B.gray("Restart the gateway for changes to take effect."))}),o.command("disable").description("Disable rtk token compression in config").action(()=>{let e=M();if(!e.tools.rtk.enabled){console.log(B.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(B.yellow("RTK token compression disabled.")),console.log(B.gray("Restart the gateway for changes to take effect.")),console.log(B.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}It();Fe();import{spawn as jc}from"node:child_process";import Fc from"node:fs";import Bc from"node:path";import j from"chalk";import{Command as Gc,Option as Uc}from"commander";function Wc(){let o=process.argv[1];if(o){let e=Bc.resolve(o);if(Fc.existsSync(e))return e}return"everclaw"}async function Kc(){let o=Ie();if(!o)return!0;if(!Pe(o.pid))return _e(),!0;console.log(j.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(j.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await Yr(o.pid,1e4)){console.log(j.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return _e(),console.log(j.green("Gateway stopped.")),!0}async function fi(o){let e=Ie();if(e&&Pe(e.pid)){console.error(j.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(j.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=W.PROCESS_CONFLICT;return}e&&_e();let t=M(),n=Ao(o.port,t.gateway.port),r=Wc(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i="",a=jc(r,s,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env}});if(!a.pid){console.error(j.red("Failed to spawn gateway process.")),process.exitCode=W.GENERAL_ERROR;return}if(a.stderr?.on("data",l=>{i+=l.toString("utf8"),i.length>4096&&(i=i.slice(-4096))}),setTimeout(()=>{a.stderr?.destroy()},3e3).unref(),a.unref(),Vr({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!Pe(a.pid)){_e(),console.error(j.red("Gateway process exited immediately.")),i.trim()?console.error(j.gray(i.trim().split(`
381
+ `)),t.installed&&t.version?(console.log(` Status: ${K.green("Available")} (v${t.version})`),console.log(` Binary: ${t.binaryPath}`),Pt(t.version,Ee)||(console.log(K.yellow(` Warning: Version ${t.version} is below minimum ${Ee}`)),console.log(K.gray(` Run ${K.cyan("everclaw rtk install --force")} to update`)))):t.installed?(console.log(` Status: ${K.yellow("Installed but broken")}`),console.log(` Binary: ${t.binaryPath}`),console.log(K.gray(` Run ${K.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${K.gray("Not installed")}`),console.log(K.gray(` Fix: Run ${K.cyan("everclaw rtk install")} or set tools.rtk.autoInstall=true`))),console.log(` Enabled: ${n.tools.rtk.enabled?K.green("yes"):K.gray("no")}`),console.log(K.gray(`
382
+ Minimum version: ${Ee}`)),console.log(K.gray(` Supported platforms: ${Object.keys(Yr).join(", ")}`))}),o.command("update").description("Update rtk to the latest version").action(async()=>{let e=new Pe,t=await e.getStatus(),n=t.installed&&t.version?t.version:null;console.log(n?K.cyan(`Current: v${n}`):K.gray("rtk is not installed."));try{console.log(K.gray("Fetching latest version..."));let r=await e.install({version:"latest",force:!0});n&&r.version===n?console.log(K.green(`Already at latest version (v${r.version})`)):console.log(K.green(`
383
+ rtk v${r.version} installed to ${r.binaryPath}`))}catch(r){console.error(K.red(`Failed to update rtk: ${r instanceof Error?r.message:String(r)}`)),process.exitCode=W.CONNECTIVITY_ERROR}}),o.command("enable").description("Enable rtk token compression in config").action(()=>{let e=P();if(e.tools.rtk.enabled){console.log(K.gray("RTK token compression is already enabled."));return}e.tools.rtk.enabled=!0,oe(e),console.log(K.green("RTK token compression enabled.")),console.log(K.gray("Restart the gateway for changes to take effect."))}),o.command("disable").description("Disable rtk token compression in config").action(()=>{let e=P();if(!e.tools.rtk.enabled){console.log(K.gray("RTK token compression is already disabled."));return}e.tools.rtk.enabled=!1,oe(e),console.log(K.yellow("RTK token compression disabled.")),console.log(K.gray("Restart the gateway for changes to take effect.")),console.log(K.gray("The binary remains installed \u2014 run `everclaw rtk uninstall` to remove it."))}),o}Lt();Ue();import{spawn as Ad}from"node:child_process";import Ed from"node:fs";import Pd from"node:path";import U from"chalk";import{Command as _d,Option as Md}from"commander";function Id(){let o=process.argv[1];if(o){let e=Pd.resolve(o);if(Ed.existsSync(e))return e}return"everclaw"}async function $d(){let o=Ie();if(!o)return!0;if(!Me(o.pid))return $e(),!0;console.log(U.cyan(`Stopping gateway (PID ${o.pid})...`));try{process.kill(o.pid,"SIGTERM")}catch(t){return console.error(U.red(`Failed to send SIGTERM to PID ${o.pid}: ${String(t)}`)),!1}if(!await mo(o.pid,1e4)){console.log(U.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(o.pid,"SIGKILL")}catch{}}return $e(),console.log(U.green("Gateway stopped.")),!0}async function ta(o){let e=Ie();if(e&&Me(e.pid)){console.error(U.red(`Gateway is already running (PID ${e.pid}, port ${e.port}).`)),console.error(U.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=W.PROCESS_CONFLICT;return}e&&$e();let t=P(),n=Zo(o.port,t.gateway.port),r=Id(),s=["gateway","start","--port",String(n)];o.host&&s.push("--host",o.host),s.push("--_foreground");let i="",a=Ad(r,s,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env}});if(!a.pid){console.error(U.red("Failed to spawn gateway process.")),process.exitCode=W.GENERAL_ERROR;return}if(a.stderr?.on("data",l=>{i+=l.toString("utf8"),i.length>4096&&(i=i.slice(-4096))}),setTimeout(()=>{a.stderr?.destroy()},3e3).unref(),a.unref(),go({pid:a.pid,port:n,startedAt:new Date().toISOString()}),await new Promise(l=>setTimeout(l,1500)),!Me(a.pid)){$e(),console.error(U.red("Gateway process exited immediately.")),i.trim()?console.error(U.gray(i.trim().split(`
340
384
  `).map(l=>` ${l}`).join(`
341
- `))):console.error(j.gray("No error output captured. Try running with -f for details.")),process.exitCode=W.GENERAL_ERROR;return}console.log(j.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(j.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(j.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function Eo(o){let e=M(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=Ao(o.port,e.gateway.port));let n=Vt(e,process.env,t),r=n.gateway.port,s=Ie();if(s&&s.pid!==process.pid&&Pe(s.pid)){console.error(j.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(j.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=W.PROCESS_CONFLICT;return}s&&s.pid!==process.pid&&_e();let i;try{i=await mi({config:n,port:r,sessionKey:"default:everclaw"})}catch(p){console.log(j.red(String(p))),process.exitCode=W.GENERAL_ERROR;return}Vr({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(j.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(j.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(j.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(j.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(j.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async p=>a||(console.log(j.yellow(`
342
- Received ${p}. Shutting down gateway...`)),_e(process.pid),a=Ro(i).then(h=>{h>0&&console.log(j.gray(`Cancelled ${h} task(s) during shutdown.`))}).catch(h=>{process.exitCode=1,console.log(j.red(`Gateway shutdown failed: ${String(h)}`))}),a),c=()=>{l("SIGINT")},d=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",d);try{await i.runPromise,a&&await a}finally{_e(process.pid),process.off("SIGINT",c),process.off("SIGTERM",d)}}function hi(){let o=new Gc("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
385
+ `))):console.error(U.gray("No error output captured. Try running with -f for details.")),process.exitCode=W.GENERAL_ERROR;return}console.log(U.green(`Gateway started in background (PID ${a.pid}, port ${n}).`)),console.log(U.gray(`Dashboard: http://localhost:${n}/chat`)),console.log(U.gray("Use `everclaw gateway status` to check, `everclaw gateway stop` to stop."))}async function Qo(o){let e=P(),t={};o.host&&(t.gatewayHost=o.host),o.port&&(t.gatewayPort=Zo(o.port,e.gateway.port));let n=nn(e,process.env,t),r=n.gateway.port,s=Ie();if(s&&s.pid!==process.pid&&Me(s.pid)){console.error(U.red(`Gateway is already running (PID ${s.pid}, port ${s.port}).`)),console.error(U.gray('Use "everclaw gateway restart" to restart it.')),process.exitCode=W.PROCESS_CONFLICT;return}s&&s.pid!==process.pid&&$e();let i;try{i=await Zi({config:n,port:r,sessionKey:"default:everclaw"})}catch(p){console.log(U.red(String(p))),process.exitCode=W.GENERAL_ERROR;return}go({pid:process.pid,port:i.port,startedAt:new Date().toISOString()}),console.log(U.cyan(`Starting everclaw gateway on port ${i.port}...`)),i.enabledChannels.length?console.log(U.green(`Channels enabled: ${i.enabledChannels.join(", ")}`)):console.log(U.yellow("No channels enabled. Gateway will stay idle until channels are configured.")),console.log(U.green(`Dashboard: http://localhost:${i.port}/chat`)),console.log(U.gray("Gateway running. Press Ctrl+C to stop."));let a=null,l=async p=>a||(console.log(U.yellow(`
386
+ Received ${p}. Shutting down gateway...`)),$e(process.pid),a=Yo(i).then(g=>{g>0&&console.log(U.gray(`Cancelled ${g} task(s) during shutdown.`))}).catch(g=>{process.exitCode=1,console.log(U.red(`Gateway shutdown failed: ${String(g)}`))}),a),c=()=>{l("SIGINT")},d=()=>{l("SIGTERM")};process.once("SIGINT",c),process.once("SIGTERM",d);try{await i.runPromise,a&&await a}finally{$e(process.pid),process.off("SIGINT",c),process.off("SIGTERM",d)}}function na(){let o=new _d("gateway").description("Manage the everclaw gateway");return o.addHelpText("after",`
343
387
  Examples:
344
388
  everclaw gateway Start the gateway in background (default)
345
389
  everclaw gateway start -f Start in foreground
346
390
  everclaw gateway status Check if gateway is running
347
391
  everclaw gateway restart Restart the gateway
348
- everclaw gateway stop Stop a running gateway`),o.command("start",{isDefault:!0}).description("Start the everclaw gateway in background (default when no subcommand given)").option("-p, --port <port>","Gateway port",String(de.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new Uc("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await Eo({port:e.port,host:e.host});return}if(e.foreground){await Eo({port:e.port,host:e.host});return}await fi({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Ie();if(!e){console.log(j.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=W.GENERAL_ERROR;return}if(!Pe(e.pid)){console.log(j.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),_e();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(j.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=W.GENERAL_ERROR;return}if(await Yr(e.pid,1e4))_e(),console.log(j.green("Gateway stopped."));else{console.log(j.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}_e(),console.log(j.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(de.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").option("--force","Start even if stop fails",!1).action(async e=>{if(!await Kc()){if(!e.force){console.error(j.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=W.GENERAL_ERROR;return}console.log(j.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(j.cyan("Starting gateway...")),e.foreground?await Eo({port:e.port,host:e.host}):await fi({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Ie();if(!e){console.log(j.yellow("Gateway is not running (no PID file found)."));return}if(!Pe(e.pid)){console.log(j.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=pt(e.startedAt);console.log(j.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`),console.log(` Started: ${e.startedAt}`)}),o}import H from"chalk";import{Command as Hc}from"commander";import st from"node:fs";import it from"node:path";Fe();De();function yi(){let o=new Hc("skills").description("Manage skills");return o.addHelpText("after",`
392
+ everclaw gateway stop Stop a running gateway`),o.command("start",{isDefault:!0}).description("Start the everclaw gateway in background (default when no subcommand given)").option("-p, --port <port>","Gateway port",String(me.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").addOption(new Md("--_foreground").hideHelp()).action(async e=>{if(e._foreground){await Qo({port:e.port,host:e.host});return}if(e.foreground){await Qo({port:e.port,host:e.host});return}await ta({port:e.port,host:e.host})}),o.command("stop").description("Stop a running gateway").action(async()=>{let e=Ie();if(!e){console.log(U.yellow("No gateway PID file found. Is the gateway running?")),process.exitCode=W.GENERAL_ERROR;return}if(!Me(e.pid)){console.log(U.yellow(`Gateway process (PID ${e.pid}) is not running. Cleaning up stale PID file.`)),$e();return}try{process.kill(e.pid,"SIGTERM")}catch(n){console.error(U.red(`Failed to send SIGTERM to PID ${e.pid}: ${String(n)}`)),process.exitCode=W.GENERAL_ERROR;return}if(await mo(e.pid,1e4))$e(),console.log(U.green("Gateway stopped."));else{console.log(U.yellow("Gateway did not exit within 10s, sending SIGKILL..."));try{process.kill(e.pid,"SIGKILL")}catch{}$e(),console.log(U.green("Gateway killed."))}}),o.command("restart").description("Restart the gateway (stop then start)").option("-p, --port <port>","Gateway port",String(me.gateway.port)).option("-H, --host <host>","Gateway bind address").option("-f, --foreground","Run in the foreground instead of background").option("--force","Start even if stop fails",!1).action(async e=>{if(!await $d()){if(!e.force){console.error(U.red("Failed to stop gateway. Use --force to start anyway.")),process.exitCode=W.GENERAL_ERROR;return}console.log(U.yellow("Warning: stop did not complete cleanly. Starting anyway (--force)."))}console.log(U.cyan("Starting gateway...")),e.foreground?await Qo({port:e.port,host:e.host}):await ta({port:e.port,host:e.host})}),o.command("status").description("Show gateway process status").action(async()=>{let e=Ie();if(!e){console.log(U.yellow("Gateway is not running (no PID file found)."));return}if(!Me(e.pid)){console.log(U.yellow(`Gateway process (PID ${e.pid}) is not running. Stale PID file.`));return}let t=bt(e.startedAt),n=null;try{let d=await fetch(`http://127.0.0.1:${e.port}/api/status`,{signal:AbortSignal.timeout(2e3)});d.ok&&(n=await d.json())}catch{}console.log(U.green("Gateway is running")),console.log(` PID: ${e.pid}`),console.log(` Port: ${e.port}`),console.log(` Uptime: ${t}`);let r=n?.runtime,s=r?.tasks||[],i=r?.compaction,a=s.filter(d=>d.status==="running"),l=s.filter(d=>d.status==="completed"),c=s.filter(d=>d.status==="failed");if(console.log(` Tasks: ${a.length} running, ${l.length} completed, ${c.length} failed`),i){let d=i.tokensFreed,p=g=>g>=1e6?`${(g/1e6).toFixed(1)}M`:g>=1e3?`${(g/1e3).toFixed(1)}K`:String(g);console.log(` Compaction: ${i.microCompactions??0} micro, ${i.autoCompactions??0} auto, ${d?p(d):0} tokens freed`)}}),o}import V from"chalk";import{Command as Od}from"commander";import ct from"node:fs";import dt from"node:path";Ue();je();function ra(){let o=new Od("skills").description("Manage skills");return o.addHelpText("after",`
349
393
  Examples:
350
394
  everclaw skills list List all available skills
351
395
  everclaw skills show browser Show details for a skill
352
396
  everclaw skills create my-skill Create a new skill in workspace
353
- everclaw skills scan Run security scan on all skills`),o.command("list").description("List all available skills").option("-a, --all","Include unavailable and blocked skills",!1).action(e=>{let t=M(),n=X(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new rt([new ot]):null,a=new Ke(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(H.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(H.gray("No available skills. Use --all to see all skills."));return}console.log(H.cyan(`
397
+ 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=P(),n=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new at([new lt]):null,a=new Je(n,null,null,r,s).listResolvedSkills();if(!a.length){console.log(V.gray("No skills found."));return}let l=e.all?a:a.filter(c=>c.status==="available");if(!l.length){console.log(V.gray("No available skills. Use --all to see all skills."));return}console.log(V.cyan(`
354
398
  Skills
355
- `)),console.log("Name".padEnd(28)+"Source".padEnd(12)+"Status".padEnd(12)+"Description"),console.log("-".repeat(80));for(let c of l){let d=c.status==="available"?H.green("available"):c.status==="blocked"?H.red("blocked"):H.yellow(c.status),p=c.description?.slice(0,40)??"";console.log(c.name.padEnd(28)+c.source.padEnd(12)+d.padEnd(20)+p)}console.log("")}),o.command("show <name>").description("Show skill details").action(e=>{let t=M(),n=X(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new rt([new ot]):null,l=new Ke(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(H.red(`Skill '${e}' not found.`)),console.log(H.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=W.GENERAL_ERROR;return}console.log(H.cyan(`
399
+ `)),console.log("Name".padEnd(28)+"Source".padEnd(12)+"Status".padEnd(12)+"Description"),console.log("-".repeat(80));for(let c of l){let d=c.status==="available"?V.green("available"):c.status==="blocked"?V.red("blocked"):V.yellow(c.status),p=c.description?.slice(0,40)??"";console.log(c.name.padEnd(28)+c.source.padEnd(12)+d.padEnd(20)+p)}console.log("")}),o.command("show <name>").description("Show skill details").action(e=>{let t=P(),n=Z(t.agents.defaults.workspace),r=t.security.enabled&&t.security.skillScanner.enabled?t.security.skillScanner:null,s=r?new at([new lt]):null,l=new Je(n,null,null,r,s).listResolvedSkills().find(c=>c.name===e);if(!l){console.log(V.red(`Skill '${e}' not found.`)),console.log(V.gray("Run `everclaw skills list` to see available skills.")),process.exitCode=W.GENERAL_ERROR;return}console.log(V.cyan(`
356
400
  Skill: ${l.name}
357
- `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?H.green("available"):H.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
401
+ `)),console.log(` Source: ${l.source}`),console.log(` Path: ${l.path}`),console.log(` Status: ${l.status==="available"?V.green("available"):V.yellow(l.status)}`),l.reason&&console.log(` Reason: ${l.reason}`),l.description&&console.log(`
358
402
  Description: ${l.description}
359
- `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=M(),n=X(t.agents.defaults.workspace),r=it.join(n,"skills"),s=it.join(r,e);if(!st.existsSync(s)){console.log(H.red(`Skill '${e}' not found in workspace skills.`)),console.log(H.gray("Only workspace-scoped skills can be removed.")),process.exitCode=W.GENERAL_ERROR;return}st.rmSync(s,{recursive:!0,force:!0}),console.log(H.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=M(),n=X(t.agents.defaults.workspace),r=it.join(n,"skills");if(!st.existsSync(r)){console.log(H.gray("No workspace skills directory found."));return}let s=new rt([new ot]),i=e?[e]:st.readdirSync(r).filter(a=>st.statSync(it.join(r,a)).isDirectory());if(i.length===0){console.log(H.gray("No skills to scan."));return}console.log(H.cyan(`
403
+ `)}),o.command("remove <name>").description("Remove a workspace-installed skill").action(e=>{let t=P(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills"),s=dt.join(r,e);if(!ct.existsSync(s)){console.log(V.red(`Skill '${e}' not found in workspace skills.`)),console.log(V.gray("Only workspace-scoped skills can be removed.")),process.exitCode=W.GENERAL_ERROR;return}ct.rmSync(s,{recursive:!0,force:!0}),console.log(V.green(`Removed skill '${e}'.`))}),o.command("scan [name]").description("Run security scanner on skills").action(e=>{let t=P(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills");if(!ct.existsSync(r)){console.log(V.gray("No workspace skills directory found."));return}let s=new at([new lt]),i=e?[e]:ct.readdirSync(r).filter(a=>ct.statSync(dt.join(r,a)).isDirectory());if(i.length===0){console.log(V.gray("No skills to scan."));return}console.log(V.cyan(`
360
404
  Skill Security Scan
361
- `));for(let a of i){let l=it.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${H.green("passed")}`);else{console.log(`${a.padEnd(28)} ${H.red("blocked")}`);for(let d of c.findings)console.log(H.gray(` - ${d.severity}: ${d.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=M(),n=X(t.agents.defaults.workspace),r=it.join(n,"skills"),s=it.join(r,e);if(st.existsSync(s)){console.log(H.red(`Skill '${e}' already exists.`)),process.exitCode=W.GENERAL_ERROR;return}st.mkdirSync(s,{recursive:!0});let i=`---
405
+ `));for(let a of i){let l=dt.join(r,a),c=s.scanSkill(l,a);if(c.findings.length===0)console.log(`${a.padEnd(28)} ${V.green("passed")}`);else{console.log(`${a.padEnd(28)} ${V.red("blocked")}`);for(let d of c.findings)console.log(V.gray(` - ${d.severity}: ${d.title}`))}}console.log("")}),o.command("create <name>").description("Create a new skill in the workspace").action(e=>{let t=P(),n=Z(t.agents.defaults.workspace),r=dt.join(n,"skills"),s=dt.join(r,e);if(ct.existsSync(s)){console.log(V.red(`Skill '${e}' already exists.`)),process.exitCode=W.GENERAL_ERROR;return}ct.mkdirSync(s,{recursive:!0});let i=`---
362
406
  name: ${e}
363
407
  description: A custom skill
364
408
  always_on: false
@@ -367,22 +411,22 @@ always_on: false
367
411
  # ${e}
368
412
 
369
413
  TODO: Add skill instructions here.
370
- `;st.writeFileSync(it.join(s,"SKILL.md"),i),console.log(H.green(`Created skill '${e}' at ${s}/SKILL.md`))}),o.command("install <slug>").description("Install a skill from ClawHub into the workspace").action(async e=>{if(!Mn(e)){console.log(H.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=W.GENERAL_ERROR;return}let t=M(),n=X(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(bt(),ls)),s=new r,i="clawhub@latest",a=12e4;console.log(H.cyan(`Installing skill '${e}'...`));try{let l=await s.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",i,"install",e,"--workdir",n]},cwd:n,env:{...process.env},timeoutMs:a,maxCaptureBytes:1048576});if(l.status!=="ok"){let d=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
371
- `),p=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(H.red(`Failed to install skill '${e}'${p}: ${d||"unknown error"}`)),process.exitCode=W.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
372
- `);console.log(H.green(`Skill '${e}' installed successfully.`)),c&&console.log(H.gray(c)),console.log(H.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(H.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=W.CONNECTIVITY_ERROR}}),o}Fe();import ee from"chalk";import{Command as Jc}from"commander";function qc(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function bi(){let o=new Jc("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
414
+ `;ct.writeFileSync(dt.join(s,"SKILL.md"),i),console.log(V.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(!Jn(e)){console.log(V.red("Invalid skill name. Must start with a lowercase letter or digit and use only lowercase letters, digits, and hyphens.")),process.exitCode=W.GENERAL_ERROR;return}let t=P(),n=Z(t.agents.defaults.workspace),{LocalProcessIsolationRunner:r}=await Promise.resolve().then(()=>(kt(),Os)),s=new r,i="clawhub@latest",a=12e4;console.log(V.cyan(`Installing skill '${e}'...`));try{let l=await s.run({command:{kind:"argv",file:process.platform==="win32"?"npx.cmd":"npx",args:["--yes",i,"install",e,"--workdir",n]},cwd:n,env:{...process.env},timeoutMs:a,maxCaptureBytes:1048576});if(l.status!=="ok"){let d=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
415
+ `),p=typeof l.exitCode=="number"?` (exit code ${l.exitCode})`:"";console.log(V.red(`Failed to install skill '${e}'${p}: ${d||"unknown error"}`)),process.exitCode=W.GENERAL_ERROR;return}let c=[l.stdout?.trim(),l.stderr?.trim()].filter(Boolean).join(`
416
+ `);console.log(V.green(`Skill '${e}' installed successfully.`)),c&&console.log(V.gray(c)),console.log(V.gray("Start a new session so the agent can load the skill."))}catch(l){console.log(V.red(`Failed to install skill '${e}': ${l instanceof Error?l.message:String(l)}`)),process.exitCode=W.CONNECTIVITY_ERROR}}),o}Ue();import re from"chalk";import{Command as Ld}from"commander";function Nd(o,e){return o.length>e?o.slice(0,e-3)+"...":o}function oa(){let o=new Ld("mcp").description("Manage MCP server connections");return o.addHelpText("after",`
373
417
  Examples:
374
418
  everclaw mcp list List configured servers
375
419
  everclaw mcp add fs --command npx --args "-y @anthropic/mcp-server-filesystem /path"
376
420
  everclaw mcp test fs Test connectivity
377
- everclaw mcp tools fs List tools from a server`),o.command("list").description("List configured MCP servers").action(()=>{let t=M().tools.mcpServers,n=Object.keys(t);if(n.length===0){console.log(ee.gray("No MCP servers configured.")),console.log(ee.gray(`Run ${ee.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(ee.cyan(`
421
+ everclaw mcp tools fs List tools from a server`),o.command("list").description("List configured MCP servers").action(()=>{let t=P().tools.mcpServers,n=Object.keys(t);if(n.length===0){console.log(re.gray("No MCP servers configured.")),console.log(re.gray(`Run ${re.cyan("everclaw mcp add <name>")} to add one.`));return}console.log(re.cyan(`
378
422
  MCP Servers
379
- `)),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)+qc(a,45).padEnd(45)+l)}console.log("")}),o.command("add <name>").description("Add a new MCP server").option("--command <command>","Command to run (stdio transport)").option("--args <args...>","Arguments for the command").option("--url <url>","HTTP/SSE endpoint URL").option("--timeout <seconds>","Tool timeout in seconds").action((e,t)=>{if(!t.command&&!t.url){console.log(ee.red("Error: Either --command or --url is required.")),process.exitCode=W.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(ee.red("Error: --timeout must be a positive integer.")),process.exitCode=W.GENERAL_ERROR;return}n=i}let r=M(),s=r.tools.mcpServers;if(s[e]){console.log(ee.yellow(`MCP server '${e}' already exists.`)),process.exitCode=W.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(ee.green(`Added MCP server '${e}'.`)),console.log(ee.gray("Restart the gateway for changes to take effect."))}),o.command("remove <name>").description("Remove an MCP server from config").action(e=>{let t=M(),n=t.tools.mcpServers;if(!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=W.GENERAL_ERROR;return}delete n[e],oe(t),console.log(ee.green(`Removed MCP server '${e}'.`))}),o.command("show <name>").description("Show MCP server details").action(e=>{let r=M().tools.mcpServers[e];if(!r){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(ee.cyan(`
423
+ `)),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)+Nd(a,45).padEnd(45)+l)}console.log("")}),o.command("add <name>").description("Add a new MCP server").option("--command <command>","Command to run (stdio transport)").option("--args <args...>","Arguments for the command").option("--url <url>","HTTP/SSE endpoint URL").option("--timeout <seconds>","Tool timeout in seconds").action((e,t)=>{if(!t.command&&!t.url){console.log(re.red("Error: Either --command or --url is required.")),process.exitCode=W.GENERAL_ERROR;return}let n;if(t.timeout){let i=parseInt(t.timeout,10);if(!Number.isFinite(i)||i<=0){console.log(re.red("Error: --timeout must be a positive integer.")),process.exitCode=W.GENERAL_ERROR;return}n=i}let r=P(),s=r.tools.mcpServers;if(s[e]){console.log(re.yellow(`MCP server '${e}' already exists.`)),process.exitCode=W.GENERAL_ERROR;return}s[e]={command:t.command??"",args:t.args??[],url:t.url??"",toolTimeout:n??60,env:{},headers:{}},oe(r),console.log(re.green(`Added MCP server '${e}'.`)),console.log(re.gray("Restart the gateway for changes to take effect."))}),o.command("remove <name>").description("Remove an MCP server from config").action(e=>{let t=P(),n=t.tools.mcpServers;if(!n[e]){console.log(re.red(`MCP server '${e}' not found.`)),process.exitCode=W.GENERAL_ERROR;return}delete n[e],oe(t),console.log(re.green(`Removed MCP server '${e}'.`))}),o.command("show <name>").description("Show MCP server details").action(e=>{let r=P().tools.mcpServers[e];if(!r){console.log(re.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(re.cyan(`
380
424
  MCP Server: ${e}
381
- `)),console.log(` Transport: ${r.url?"HTTP/SSE":"stdio"}`),r.url?console.log(` URL: ${r.url}`):r.command&&(console.log(` Command: ${r.command}`),r.args?.length&&console.log(` Args: ${r.args.join(" ")}`)),r.toolTimeout&&console.log(` Timeout: ${r.toolTimeout}s`),r.env&&Object.keys(r.env).length>0&&console.log(` Env vars: ${Object.keys(r.env).join(", ")}`),console.log("")}),o.command("test [name]").description("Test connectivity to one or all MCP servers").action(async e=>{let n=M().tools.mcpServers,r=e?[e]:Object.keys(n);if(r.length===0){console.log(ee.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(ee.cyan(`
425
+ `)),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=P().tools.mcpServers,r=e?[e]:Object.keys(n);if(r.length===0){console.log(re.gray("No MCP servers configured."));return}if(e&&!n[e]){console.log(re.red(`MCP server '${e}' not found.`)),process.exitCode=1;return}console.log(re.cyan(`
382
426
  MCP Connectivity Test
383
- `));let{McpClientManager:s}=await Promise.resolve().then(()=>(un(),br)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${ee.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${ee.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=W.CONNECTIVITY_ERROR}await i.closeAll(),console.log("")}),o.command("tools <name>").description("List tools exposed by an MCP server").action(async e=>{let n=M().tools.mcpServers;if(!n[e]){console.log(ee.red(`MCP server '${e}' not found.`)),process.exitCode=W.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(un(),br)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(ee.gray(`No tools exposed by '${e}'.`));else{console.log(ee.cyan(`
427
+ `));let{McpClientManager:s}=await Promise.resolve().then(()=>(wn(),$r)),i=new s;i.updateConfig(n);for(let a of r)try{let l=await i.getServerTools(a);console.log(`${a.padEnd(20)} ${re.green("\u2713 connected")} (${l.length} tools)`)}catch(l){console.log(`${a.padEnd(20)} ${re.red("\u2717 "+(l instanceof Error?l.message:String(l)))}`),process.exitCode=W.CONNECTIVITY_ERROR}await i.closeAll(),console.log("")}),o.command("tools <name>").description("List tools exposed by an MCP server").action(async e=>{let n=P().tools.mcpServers;if(!n[e]){console.log(re.red(`MCP server '${e}' not found.`)),process.exitCode=W.GENERAL_ERROR;return}let{McpClientManager:r}=await Promise.resolve().then(()=>(wn(),$r)),s=new r;s.updateConfig(n);try{let i=await s.getServerTools(e);if(i.length===0)console.log(re.gray(`No tools exposed by '${e}'.`));else{console.log(re.cyan(`
384
428
  Tools from ${e} (${i.length})
385
- `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(ee.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=W.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}le();import we from"node:fs";import Rt from"node:os";import zc from"node:path";import{execSync as wi}from"node:child_process";import L from"chalk";import{Command as Vc}from"commander";function Po(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function Yc(){let o=process.argv[1];if(o){let e=zc.resolve(o);if(we.existsSync(e))return e}try{let e=wi("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&we.existsSync(e))return e}catch{}return"everclaw"}function Xc(o){let e=Ue();return`[Unit]
429
+ `));for(let a of i)console.log(` ${a.remoteName.padEnd(32)} ${a.description.slice(0,60)}`);console.log("")}}catch(i){console.log(re.red(`Failed to connect to '${e}': ${i instanceof Error?i.message:String(i)}`)),process.exitCode=W.CONNECTIVITY_ERROR}finally{await s.closeAll()}}),o}de();import Se from"node:fs";import Mt from"node:os";import Dd from"node:path";import{execSync as sa}from"node:child_process";import O from"chalk";import{Command as jd}from"commander";function es(){return process.platform==="linux"?"linux":process.platform==="darwin"?"macos":"unsupported"}function Fd(){let o=process.argv[1];if(o){let e=Dd.resolve(o);if(Se.existsSync(e))return e}try{let e=sa("which everclaw 2>/dev/null",{encoding:"utf8"}).trim();if(e&&Se.existsSync(e))return e}catch{}return"everclaw"}function Bd(o){let e=We();return`[Unit]
386
430
  Description=Everclaw AI Assistant Gateway
387
431
  After=network-online.target
388
432
  Wants=network-online.target
@@ -398,7 +442,7 @@ StandardError=append:${e}/gateway.stderr.log
398
442
 
399
443
  [Install]
400
444
  WantedBy=default.target
401
- `}function Qc(o){let e=Ue();return`<?xml version="1.0" encoding="UTF-8"?>
445
+ `}function Ud(o){let e=We();return`<?xml version="1.0" encoding="UTF-8"?>
402
446
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
403
447
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
404
448
  <plist version="1.0">
@@ -421,21 +465,21 @@ WantedBy=default.target
421
465
  <string>${e}/gateway.stderr.log</string>
422
466
  </dict>
423
467
  </plist>
424
- `}function me(o){try{return{ok:!0,output:wi(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function Zc(){let o=Po(),e=Rt.homedir(),t=Ue(e),n=Yc();we.mkdirSync(t,{recursive:!0}),o==="linux"?await ed(e,n):o==="macos"?await td(e,n):(console.log(L.red(`Service installation is not supported on '${process.platform}'.`)),console.log(L.gray("Supported: Linux (systemd), macOS (launchd).")),process.exitCode=1)}async function ed(o,e){let t=Ur(o),n=kn(o),r=Xc(e);console.log(L.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),we.mkdirSync(t,{recursive:!0}),we.writeFileSync(n,r,"utf8"),console.log(L.green(" Unit file written."));let s=me("systemctl --user daemon-reload");s.ok||console.log(L.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=me("systemctl --user enable everclaw");i.ok?console.log(L.green(" Service enabled.")):console.log(L.yellow(` Warning: enable failed: ${i.output}`));let a=me("systemctl --user start everclaw");a.ok?console.log(L.green(" Service started.")):console.log(L.yellow(` Warning: start failed: ${a.output}`));let l=me(`loginctl show-user ${Rt.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log(L.yellow(`
425
- Note: Linger is not enabled. The service will stop when you log out.`)),console.log(L.gray(` Run: loginctl enable-linger ${Rt.userInfo().username}`)),console.log(L.gray(" (This may require sudo or admin assistance.)"))),console.log(L.green(`
426
- Service installed successfully.`)),console.log(L.gray("Use: systemctl --user status everclaw")),console.log(L.gray(" systemctl --user stop everclaw")),console.log(L.gray(" journalctl --user -u everclaw -f"))}async function td(o,e){let t=Wr(o),n=Cn(o),r=Qc(e);console.log(L.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),we.mkdirSync(t,{recursive:!0}),we.writeFileSync(n,r,"utf8"),console.log(L.green(" Plist written.")),me(`launchctl unload ${n} 2>/dev/null`);let s=me(`launchctl load ${n}`);s.ok?console.log(L.green(" Agent loaded.")):console.log(L.yellow(` Warning: load failed: ${s.output}`)),console.log(L.green(`
427
- Service installed successfully.`)),console.log(L.gray("Use: launchctl list | grep everclaw")),console.log(L.gray(" launchctl unload "+n)),console.log(L.gray(" launchctl load "+n))}async function nd(){let o=Po(),e=Rt.homedir();o==="linux"?await rd(e):o==="macos"?await od(e):(console.log(L.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function rd(o){let e=kn(o);console.log(L.cyan("Uninstalling systemd user service...")),me("systemctl --user stop everclaw"),me("systemctl --user disable everclaw"),we.existsSync(e)?(we.unlinkSync(e),console.log(L.green(" Unit file removed."))):console.log(L.gray(" No unit file found.")),me("systemctl --user daemon-reload"),console.log(L.green(`
428
- Service uninstalled.`))}async function od(o){let e=Cn(o);console.log(L.cyan("Uninstalling launchd user agent...")),me(`launchctl unload ${e} 2>/dev/null`).ok&&console.log(L.green(" Agent unloaded.")),we.existsSync(e)?(we.unlinkSync(e),console.log(L.green(" Plist removed."))):console.log(L.gray(" No plist found.")),console.log(L.green(`
429
- Service uninstalled.`))}async function sd(){let o=Po(),e=Rt.homedir();console.log(L.cyan(`Service Registration Status
430
- `)),o==="linux"?await id(e):o==="macos"?await ad(e):console.log(L.gray(`Service management not supported on '${process.platform}'.`))}async function id(o){let e=kn(o),t=we.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?L.green(e):L.gray("not found")}`),!t){console.log(L.gray(`
431
- Service is not installed. Run: everclaw service install`));return}let n=me("systemctl --user is-enabled everclaw 2>/dev/null"),r=me("systemctl --user is-active everclaw 2>/dev/null");console.log(`Enabled: ${n.ok&&n.output==="enabled"?L.green("yes"):L.yellow(n.output||"unknown")}`),console.log(`Active: ${r.ok&&r.output==="active"?L.green("running"):r.ok?L.yellow(r.output):L.gray("unknown")}`);let s=me(`loginctl show-user ${Rt.userInfo().username} -p Linger`),i=s.ok&&s.output.includes("yes");console.log(`Linger: ${i?L.green("enabled"):L.yellow("disabled")} (survives logout)`),i||console.log(L.gray(` Run: loginctl enable-linger ${Rt.userInfo().username}`))}async function ad(o){let e=Cn(o),t=we.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?L.green(e):L.gray("not found")}`),!t){console.log(L.gray(`
432
- Service is not installed. Run: everclaw service install`));return}let n=me("launchctl list ai.everclaw.gateway 2>/dev/null");if(n.ok){let r=n.output.match(/"PID"\s*=\s*(\d+)/),s=n.output.match(/"LastExitStatus"\s*=\s*(\d+)/);if(r)console.log(`Status: ${L.green("running")} (PID ${r[1]})`);else if(s){let i=parseInt(s[1],10);console.log(`Status: ${i===0?L.green("exited cleanly"):L.yellow(`exited with code ${i}`)}`)}else console.log(`Status: ${L.green("loaded")}`)}else console.log(`Status: ${L.gray("not loaded")}`)}function vi(){let o=new Vc("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
468
+ `}function he(o){try{return{ok:!0,output:sa(o,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()}}catch(e){return{ok:!1,output:(e?.stderr||e?.message||String(e)).trim()}}}async function Gd(){let o=es(),e=Mt.homedir(),t=We(e),n=Fd();Se.mkdirSync(t,{recursive:!0}),o==="linux"?await Wd(e,n):o==="macos"?await Kd(e,n):(console.log(O.red(`Service installation is not supported on '${process.platform}'.`)),console.log(O.gray("Supported: Linux (systemd), macOS (launchd).")),process.exitCode=1)}async function Wd(o,e){let t=oo(o),n=Ln(o),r=Bd(e);console.log(O.cyan("Installing systemd user service...")),console.log(` Binary: ${e}`),console.log(` Unit: ${n}`),Se.mkdirSync(t,{recursive:!0}),Se.writeFileSync(n,r,"utf8"),console.log(O.green(" Unit file written."));let s=he("systemctl --user daemon-reload");s.ok||console.log(O.yellow(` Warning: daemon-reload failed: ${s.output}`));let i=he("systemctl --user enable everclaw");i.ok?console.log(O.green(" Service enabled.")):console.log(O.yellow(` Warning: enable failed: ${i.output}`));let a=he("systemctl --user start everclaw");a.ok?console.log(O.green(" Service started.")):console.log(O.yellow(` Warning: start failed: ${a.output}`));let l=he(`loginctl show-user ${Mt.userInfo().username} -p Linger`);l.ok&&l.output.includes("yes")||(console.log(O.yellow(`
469
+ Note: Linger is not enabled. The service will stop when you log out.`)),console.log(O.gray(` Run: loginctl enable-linger ${Mt.userInfo().username}`)),console.log(O.gray(" (This may require sudo or admin assistance.)"))),console.log(O.green(`
470
+ Service installed successfully.`)),console.log(O.gray("Use: systemctl --user status everclaw")),console.log(O.gray(" systemctl --user stop everclaw")),console.log(O.gray(" journalctl --user -u everclaw -f"))}async function Kd(o,e){let t=so(o),n=Nn(o),r=Ud(e);console.log(O.cyan("Installing launchd user agent...")),console.log(` Binary: ${e}`),console.log(` Plist: ${n}`),Se.mkdirSync(t,{recursive:!0}),Se.writeFileSync(n,r,"utf8"),console.log(O.green(" Plist written.")),he(`launchctl unload ${n} 2>/dev/null`);let s=he(`launchctl load ${n}`);s.ok?console.log(O.green(" Agent loaded.")):console.log(O.yellow(` Warning: load failed: ${s.output}`)),console.log(O.green(`
471
+ Service installed successfully.`)),console.log(O.gray("Use: launchctl list | grep everclaw")),console.log(O.gray(" launchctl unload "+n)),console.log(O.gray(" launchctl load "+n))}async function Hd(){let o=es(),e=Mt.homedir();o==="linux"?await Jd(e):o==="macos"?await qd(e):(console.log(O.red(`Service uninstall is not supported on '${process.platform}'.`)),process.exitCode=1)}async function Jd(o){let e=Ln(o);console.log(O.cyan("Uninstalling systemd user service...")),he("systemctl --user stop everclaw"),he("systemctl --user disable everclaw"),Se.existsSync(e)?(Se.unlinkSync(e),console.log(O.green(" Unit file removed."))):console.log(O.gray(" No unit file found.")),he("systemctl --user daemon-reload"),console.log(O.green(`
472
+ Service uninstalled.`))}async function qd(o){let e=Nn(o);console.log(O.cyan("Uninstalling launchd user agent...")),he(`launchctl unload ${e} 2>/dev/null`).ok&&console.log(O.green(" Agent unloaded.")),Se.existsSync(e)?(Se.unlinkSync(e),console.log(O.green(" Plist removed."))):console.log(O.gray(" No plist found.")),console.log(O.green(`
473
+ Service uninstalled.`))}async function zd(){let o=es(),e=Mt.homedir();console.log(O.cyan(`Service Registration Status
474
+ `)),o==="linux"?await Vd(e):o==="macos"?await Xd(e):console.log(O.gray(`Service management not supported on '${process.platform}'.`))}async function Vd(o){let e=Ln(o),t=Se.existsSync(e);if(console.log("Platform: Linux (systemd user)"),console.log(`Unit file: ${t?O.green(e):O.gray("not found")}`),!t){console.log(O.gray(`
475
+ Service is not installed. Run: everclaw service install`));return}let n=he("systemctl --user is-enabled everclaw 2>/dev/null"),r=he("systemctl --user is-active everclaw 2>/dev/null");console.log(`Enabled: ${n.ok&&n.output==="enabled"?O.green("yes"):O.yellow(n.output||"unknown")}`),console.log(`Active: ${r.ok&&r.output==="active"?O.green("running"):r.ok?O.yellow(r.output):O.gray("unknown")}`);let s=he(`loginctl show-user ${Mt.userInfo().username} -p Linger`),i=s.ok&&s.output.includes("yes");console.log(`Linger: ${i?O.green("enabled"):O.yellow("disabled")} (survives logout)`),i||console.log(O.gray(` Run: loginctl enable-linger ${Mt.userInfo().username}`))}async function Xd(o){let e=Nn(o),t=Se.existsSync(e);if(console.log("Platform: macOS (launchd)"),console.log(`Plist: ${t?O.green(e):O.gray("not found")}`),!t){console.log(O.gray(`
476
+ Service is not installed. Run: everclaw service install`));return}let n=he("launchctl list ai.everclaw.gateway 2>/dev/null");if(n.ok){let r=n.output.match(/"PID"\s*=\s*(\d+)/),s=n.output.match(/"LastExitStatus"\s*=\s*(\d+)/);if(r)console.log(`Status: ${O.green("running")} (PID ${r[1]})`);else if(s){let i=parseInt(s[1],10);console.log(`Status: ${i===0?O.green("exited cleanly"):O.yellow(`exited with code ${i}`)}`)}else console.log(`Status: ${O.green("loaded")}`)}else console.log(`Status: ${O.gray("not loaded")}`)}function ia(){let o=new jd("service").description("Manage system service registration (auto-start on reboot)");return o.addHelpText("after",`
433
477
  Examples:
434
478
  everclaw service install Register and start the gateway as a system service
435
479
  everclaw service uninstall Remove the system service
436
480
  everclaw service status Show service registration status
437
481
 
438
- Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await Zc()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await nd()}),o.command("status").description("Show service registration status").action(async()=>{await sd()}),o}le();import ve from"node:fs";import Io from"node:path";import{Command as cd}from"commander";import at from"chalk";import Jt from"chalk";var ld={debug:Jt.gray,info:Jt.cyan,warn:Jt.yellow,error:Jt.red},Br=class{format(e){let t=Jt.dim(e.ts),n=this.formatLevel(e.level),r=Jt.bold(`[${e.category}]`),s=e.event,i=this.formatData(e.data);return`${t} ${n} ${r} ${s} ${i}`}formatJson(e){return JSON.stringify(e)}formatLevel(e){let t=ld[e];return t(e.toUpperCase().padEnd(5))}formatData(e){let t=[];for(let[n,r]of Object.entries(e))if(r!=null)if(typeof r=="string")r.length>80?t.push(`${n}="${r.slice(0,77)}\u2026"`):r.includes(" ")||r.includes('"')||r.includes("=")?t.push(`${n}="${r}"`):t.push(`${n}=${r}`);else if(typeof r=="number"||typeof r=="boolean")t.push(`${n}=${r}`);else if(r instanceof Error)t.push(`${n}="${r.message}"`);else try{let s=JSON.stringify(r);s.length>80?t.push(`${n}=${s.slice(0,77)}\u2026`):t.push(`${n}=${s}`)}catch{t.push(`${n}=[circular]`)}return t.join(" ")}};function ki(){let o=new cd("logs").description("View gateway logs").option("-f, --follow","Follow log output (tail -f style)").option("-l, --level <level>","Minimum log level (debug, info, warn, error)","info").option("-c, --category <category>","Filter by category prefix").option("-n, --lines <n>","Number of lines to show","100").option("--json","Output raw JSONL").option("--since <duration>","Show logs from last N minutes/hours (e.g., 30m, 2h)").addHelpText("after",`
482
+ Supported platforms: Linux (systemd user), macOS (launchd LaunchAgent)`),o.command("install").description("Register everclaw gateway as a system service").action(async()=>{await Gd()}),o.command("uninstall").description("Remove the everclaw gateway system service").action(async()=>{await Hd()}),o.command("status").description("Show service registration status").action(async()=>{await zd()}),o}de();import ke from"node:fs";import ts from"node:path";import{Command as Qd}from"commander";import ut from"chalk";import Zt from"chalk";var Yd={debug:Zt.gray,info:Zt.cyan,warn:Zt.yellow,error:Zt.red},ro=class{format(e){let t=Zt.dim(e.ts),n=this.formatLevel(e.level),r=Zt.bold(`[${e.category}]`),s=e.event,i=this.formatData(e.data);return`${t} ${n} ${r} ${s} ${i}`}formatJson(e){return JSON.stringify(e)}formatLevel(e){let t=Yd[e];return t(e.toUpperCase().padEnd(5))}formatData(e){let t=[];for(let[n,r]of Object.entries(e))if(r!=null)if(typeof r=="string")r.length>80?t.push(`${n}="${r.slice(0,77)}\u2026"`):r.includes(" ")||r.includes('"')||r.includes("=")?t.push(`${n}="${r}"`):t.push(`${n}=${r}`);else if(typeof r=="number"||typeof r=="boolean")t.push(`${n}=${r}`);else if(r instanceof Error)t.push(`${n}="${r.message}"`);else try{let s=JSON.stringify(r);s.length>80?t.push(`${n}=${s.slice(0,77)}\u2026`):t.push(`${n}=${s}`)}catch{t.push(`${n}=[circular]`)}return t.join(" ")}};function la(){let o=new Qd("logs").description("View gateway logs").option("-f, --follow","Follow log output (tail -f style)").option("-l, --level <level>","Minimum log level (debug, info, warn, error)","info").option("-c, --category <category>","Filter by category prefix").option("-n, --lines <n>","Number of lines to show","100").option("--json","Output raw JSONL").option("--since <duration>","Show logs from last N minutes/hours (e.g., 30m, 2h)").addHelpText("after",`
439
483
  Examples:
440
484
  everclaw logs Show last 100 log entries
441
485
  everclaw logs -f Follow logs in real-time
@@ -443,10 +487,10 @@ Examples:
443
487
  everclaw logs --category agent Show agent-related logs
444
488
  everclaw logs --since 30m Show logs from last 30 minutes
445
489
  everclaw logs --json Output raw JSONL format
446
- everclaw logs clear Clear all log files`);return o.command("clear").description("Clear all log files").action(()=>{let e=Ue();if(!ve.existsSync(e)){console.log(at.gray("No logs directory found."));return}let t=ve.readdirSync(e).filter(r=>r.startsWith("gateway-")&&r.endsWith(".jsonl"));if(t.length===0){console.log(at.gray("No log files to clear."));return}let n=0;for(let r of t)try{ve.unlinkSync(Io.join(e,r)),n++}catch(s){console.log(at.red(`Failed to delete ${r}: ${s instanceof Error?s.message:String(s)}`))}console.log(at.green(`Cleared ${n} log file(s).`))}),o.action(async e=>{let t=Ue(),n=dd(e.level)||"info",r=e.category,s=e.since?ud(e.since):null,i=parseInt(e.lines,10),a=new Br;if(!ve.existsSync(t)){console.log(at.gray("No logs directory found. Is the gateway running?"));return}let l=ve.readdirSync(t).filter(c=>c.startsWith("gateway-")&&c.endsWith(".jsonl")).sort();if(l.length===0){console.log(at.gray("No log files found."));return}e.follow?await md(t,l,n,r,s,e.json,a):await gd(t,l,n,r,s,i,e.json,a)}),o}function dd(o){let e=o.toLowerCase();return e==="debug"||e==="info"||e==="warn"||e==="error"?e:null}function ud(o){let e=/^(\d+)(m|h)$/.exec(o);if(!e)return null;let t=parseInt(e[1],10),n=e[2];return n==="m"?t*60*1e3:n==="h"?t*60*60*1e3:null}async function gd(o,e,t,n,r,s,i,a){let l=r?Date.now()-r:null,c=[];for(let p of e){let h=Io.join(o,p),w=ve.readFileSync(h,"utf8").split(`
447
- `).filter(u=>u.trim());for(let u of w){let b;try{b=JSON.parse(u)}catch{continue}if(l){let E=new Date(b.ts).getTime();if(Number.isNaN(E)||E<l)continue}Tt[b.level]<Tt[t]||n&&!b.category.startsWith(n)||c.push(b)}}let d=c.slice(-s);for(let p of d)console.log(i?a.formatJson(p):a.format(p));d.length===0&&console.log(at.gray("No matching log entries found."))}async function md(o,e,t,n,r,s,i){let a=r?Date.now()-r:null,l=Si(o),c=0;ve.existsSync(l)&&(c=ve.statSync(l).size);let d=setInterval(()=>{try{let p=Si(o);if(p!==l&&(l=p,c=0),!ve.existsSync(l))return;let h=ve.statSync(l);if(h.size>c){let v=ve.openSync(l,"r"),w=Buffer.alloc(h.size-c);ve.readSync(v,w,0,w.length,c),ve.closeSync(v);let b=w.toString("utf8").split(`
448
- `).filter(E=>E.trim());for(let E of b){let S;try{S=JSON.parse(E)}catch{continue}if(a){let N=new Date(S.ts).getTime();if(Number.isNaN(N)||N<a)continue}Tt[S.level]<Tt[t]||n&&!S.category.startsWith(n)||console.log(s?i.formatJson(S):i.format(S))}c=h.size}}catch(p){console.error(at.red(`Error watching logs: ${p instanceof Error?p.message:String(p)}`))}},500);process.on("SIGINT",()=>{clearInterval(d),process.exit(0)}),await new Promise(()=>{})}function Si(o){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return Io.join(o,`gateway-${t}-${n}-${r}-${s}.jsonl`)}var fd=Ko(),hd="0.3.0";function Ao(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 Ri(){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 yd(o){if(process.platform==="win32")return null;try{let{execSync:e}=_i("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
449
- `);if(n.length<2)return null;let r=n[1].trim().split(/\s+/),s=parseInt(r[3],10);return Number.isNaN(s)?null:s*1024}catch{return null}}async function Ei(o){let e=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(e=!0)}catch{}e&&console.log(C.green(" Ollama detected on localhost:11434"));let t=await pe({type:"select",name:"provider",message:"Choose your provider",choices:[{title:"OpenRouter (recommended \u2014 access 200+ models)",value:"openrouter"},{title:"OpenAI",value:"openai"},{title:"Ollama (local, no API key needed)",value:"ollama"},{title:"Zai (\u667A\u8C31 AI)",value:"zai"},{title:"Custom OpenAI-compatible provider",value:"custom"}]}),n=String(t.provider||"openrouter"),r=fd[n]??[o.agents.defaults.model],s=await pe({type:"select",name:"model",message:"Choose your model",choices:r.map(c=>({title:c,value:c}))}),i=String(s.model||r[0]),a="";if(n!=="vllm"&&n!=="ollama"){let c=await pe({type:"password",name:"apiKey",message:"Enter API key",validate:d=>d&&d.trim().length>0?!0:"API key cannot be empty"});a=String(c.apiKey||"")}let l="";if(n==="custom"||n==="vllm"||n==="ollama"){let c=await pe({type:"text",name:"apiBase",message:"Enter API base URL",initial:n==="ollama"?"http://localhost:11434/v1":n==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"});l=String(c.apiBase||"").trim()}if(n==="custom"){let c;try{c=new URL(l).hostname.replace(/\./g,"-")}catch{c="custom-provider"}o.customLlmProviders.push({name:c,baseUrl:l,apiKey:a,apiFormat:"v1/chat/completions",models:[{id:i,displayName:i}],extraHeaders:null}),o.agents.defaults.provider=zt(c),o.agents.defaults.model=i}else{if(o.agents.defaults.provider=n,o.agents.defaults.model=i,n in o.providers){let c=o.providers[n];c&&(c.apiKey=a)}if((n==="vllm"||n==="ollama")&&l&&n in o.providers){let c=o.providers[n];c&&(c.apiBase=l)}}}async function Ai(o){if((await pe({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await pe({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),n=String(t.channel||"telegram");if(n==="telegram"){let r=await pe({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:i=>i&&i.trim().length>0?!0:"Token cannot be empty"});if(o.channels.telegram.enabled=!0,o.channels.telegram.token=String(r.token||"").trim(),(await pe({type:"confirm",name:"enableGroups",message:"Enable Telegram group chat support?",initial:!0})).enableGroups){let i=await pe({type:"confirm",name:"requireMention",message:"Require @mention to respond in groups? (recommended)",initial:!0});if(o.channels.telegram.groups={requireMention:i.requireMention!==!1,allowedGroupIds:null},(await pe({type:"confirm",name:"restrictGroups",message:"Restrict to specific group IDs?",initial:!1})).restrictGroups){let l=await pe({type:"text",name:"groupIds",message:"Enter allowed group IDs (comma-separated, e.g., -1001234567890)"}),c=String(l.groupIds||"").split(",").map(d=>d.trim()).filter(d=>d.length>0);o.channels.telegram.groups.allowedGroupIds=c.length>0?c:null}}else o.channels.telegram.groups={requireMention:!0,allowedGroupIds:[]}}else if(n==="discord"){let r=await pe({type:"password",name:"token",message:"Enter Discord Bot Token",validate:s=>s&&s.trim().length>0?!0:"Token cannot be empty"});o.channels.discord.enabled=!0,o.channels.discord.token=String(r.token||"").trim()}}}function Pi(o){let e=new pd;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(hd,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
490
+ everclaw logs clear Clear all log files`);return o.command("clear").description("Clear all log files").action(()=>{let e=We();if(!ke.existsSync(e)){console.log(ut.gray("No logs directory found."));return}let t=ke.readdirSync(e).filter(r=>r.startsWith("gateway-")&&r.endsWith(".jsonl"));if(t.length===0){console.log(ut.gray("No log files to clear."));return}let n=0;for(let r of t)try{ke.unlinkSync(ts.join(e,r)),n++}catch(s){console.log(ut.red(`Failed to delete ${r}: ${s instanceof Error?s.message:String(s)}`))}console.log(ut.green(`Cleared ${n} log file(s).`))}),o.action(async e=>{let t=We(),n=Zd(e.level)||"info",r=e.category,s=e.since?eu(e.since):null,i=parseInt(e.lines,10),a=new ro;if(!ke.existsSync(t)){console.log(ut.gray("No logs directory found. Is the gateway running?"));return}let l=ke.readdirSync(t).filter(c=>c.startsWith("gateway-")&&c.endsWith(".jsonl")).sort();if(l.length===0){console.log(ut.gray("No log files found."));return}e.follow?await nu(t,l,n,r,s,e.json,a):await tu(t,l,n,r,s,i,e.json,a)}),o}function Zd(o){let e=o.toLowerCase();return e==="debug"||e==="info"||e==="warn"||e==="error"?e:null}function eu(o){let e=/^(\d+)(m|h)$/.exec(o);if(!e)return null;let t=parseInt(e[1],10),n=e[2];return n==="m"?t*60*1e3:n==="h"?t*60*60*1e3:null}async function tu(o,e,t,n,r,s,i,a){let l=r?Date.now()-r:null,c=[];for(let p of e){let g=ts.join(o,p),y=ke.readFileSync(g,"utf8").split(`
491
+ `).filter(u=>u.trim());for(let u of y){let b;try{b=JSON.parse(u)}catch{continue}if(l){let R=new Date(b.ts).getTime();if(Number.isNaN(R)||R<l)continue}_t[b.level]<_t[t]||n&&!b.category.startsWith(n)||c.push(b)}}let d=c.slice(-s);for(let p of d)console.log(i?a.formatJson(p):a.format(p));d.length===0&&console.log(ut.gray("No matching log entries found."))}async function nu(o,e,t,n,r,s,i){let a=r?Date.now()-r:null,l=aa(o),c=0;ke.existsSync(l)&&(c=ke.statSync(l).size);let d=setInterval(()=>{try{let p=aa(o);if(p!==l&&(l=p,c=0),!ke.existsSync(l))return;let g=ke.statSync(l);if(g.size>c){let x=ke.openSync(l,"r"),y=Buffer.alloc(g.size-c);ke.readSync(x,y,0,y.length,c),ke.closeSync(x);let b=y.toString("utf8").split(`
492
+ `).filter(R=>R.trim());for(let R of b){let S;try{S=JSON.parse(R)}catch{continue}if(a){let D=new Date(S.ts).getTime();if(Number.isNaN(D)||D<a)continue}_t[S.level]<_t[t]||n&&!S.category.startsWith(n)||console.log(s?i.formatJson(S):i.format(S))}c=g.size}}catch(p){console.error(ut.red(`Error watching logs: ${p instanceof Error?p.message:String(p)}`))}},500);process.on("SIGINT",()=>{clearInterval(d),process.exit(0)}),await new Promise(()=>{})}function aa(o){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0");return ts.join(o,`gateway-${t}-${n}-${r}-${s}.jsonl`)}var ou=fs(),su="0.3.0";function Zo(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 ga(){if(process.env.DOCKER==="true"||ue.existsSync("/.dockerenv"))return"Docker";if(process.env.INVOCATION_ID)return"systemd";if(process.env.XPC_SERVICE_NAME||process.env.LAUNCH_DAEMON)return"launchd";if(process.env.PM2_HOME||process.env.pm_id)return"pm2";try{if(ue.existsSync("/.dockerenv"))return"Docker"}catch{}return null}function iu(o){if(process.platform==="win32")return null;try{let{execSync:e}=ya("node:child_process"),n=e(`df -k "${o}"`,{encoding:"utf-8"}).trim().split(`
493
+ `);if(n.length<2)return null;let r=n[1].trim().split(/\s+/),s=parseInt(r[3],10);return Number.isNaN(s)?null:s*1024}catch{return null}}async function ma(o){let e=!1;try{(await fetch("http://localhost:11434/v1/models",{signal:AbortSignal.timeout(2e3)})).ok&&(e=!0)}catch{}e&&console.log(v.green(" Ollama detected on localhost:11434"));let t=await ye({type:"select",name:"provider",message:"Choose your provider",choices:[{title:"OpenRouter (recommended \u2014 access 200+ models)",value:"openrouter"},{title:"OpenAI",value:"openai"},{title:"Ollama (local, no API key needed)",value:"ollama"},{title:"Zai (\u667A\u8C31 AI)",value:"zai"},{title:"Custom OpenAI-compatible provider",value:"custom"}]}),n=String(t.provider||"openrouter"),r=ou[n]??[o.agents.defaults.model],s=await ye({type:"select",name:"model",message:"Choose your model",choices:r.map(c=>({title:c,value:c}))}),i=String(s.model||r[0]),a="";if(n!=="vllm"&&n!=="ollama"){let c=await ye({type:"password",name:"apiKey",message:"Enter API key",validate:d=>d&&d.trim().length>0?!0:"API key cannot be empty"});a=String(c.apiKey||"")}let l="";if(n==="custom"||n==="vllm"||n==="ollama"){let c=await ye({type:"text",name:"apiBase",message:"Enter API base URL",initial:n==="ollama"?"http://localhost:11434/v1":n==="vllm"?"http://localhost:8000/v1":"https://api.openai.com/v1"});l=String(c.apiBase||"").trim()}if(n==="custom"){let c;try{c=new URL(l).hostname.replace(/\./g,"-")}catch{c="custom-provider"}o.customLlmProviders.push({name:c,baseUrl:l,apiKey:a,apiFormat:"v1/chat/completions",models:[{id:i,displayName:i}],extraHeaders:null}),o.agents.defaults.provider=tn(c),o.agents.defaults.model=i}else{if(o.agents.defaults.provider=n,o.agents.defaults.model=i,n in o.providers){let c=o.providers[n];c&&(c.apiKey=a)}if((n==="vllm"||n==="ollama")&&l&&n in o.providers){let c=o.providers[n];c&&(c.apiBase=l)}}}async function pa(o){if((await ye({type:"confirm",name:"wantChannel",message:"Do you want to configure a chat channel now?",initial:!0})).wantChannel){let t=await ye({type:"select",name:"channel",message:"Choose chat channel",choices:[{title:"Telegram",value:"telegram"},{title:"Discord",value:"discord"}]}),n=String(t.channel||"telegram");if(n==="telegram"){let r=await ye({type:"password",name:"token",message:"Enter Telegram Bot Token",validate:i=>i&&i.trim().length>0?!0:"Token cannot be empty"});if(o.channels.telegram.enabled=!0,o.channels.telegram.token=String(r.token||"").trim(),(await ye({type:"confirm",name:"enableGroups",message:"Enable Telegram group chat support?",initial:!0})).enableGroups){let i=await ye({type:"confirm",name:"requireMention",message:"Require @mention to respond in groups? (recommended)",initial:!0});if(o.channels.telegram.groups={requireMention:i.requireMention!==!1,allowedGroupIds:null},(await ye({type:"confirm",name:"restrictGroups",message:"Restrict to specific group IDs?",initial:!1})).restrictGroups){let l=await ye({type:"text",name:"groupIds",message:"Enter allowed group IDs (comma-separated, e.g., -1001234567890)"}),c=String(l.groupIds||"").split(",").map(d=>d.trim()).filter(d=>d.length>0);o.channels.telegram.groups.allowedGroupIds=c.length>0?c:null}}else o.channels.telegram.groups={requireMention:!0,allowedGroupIds:[]}}else if(n==="discord"){let r=await ye({type:"password",name:"token",message:"Enter Discord Bot Token",validate:s=>s&&s.trim().length>0?!0:"Token cannot be empty"});o.channels.discord.enabled=!0,o.channels.discord.token=String(r.token||"").trim()}}}function fa(o){let e=new ru;if(e.name("everclaw").description("everclaw - Personal AI Assistant").version(su,"-v, --version","show version").option("--json","Output in JSON format for scripting").addHelpText("after",`
450
494
  Examples:
451
495
  everclaw onboard Interactive setup wizard
452
496
  everclaw gateway Start the gateway server
@@ -454,41 +498,47 @@ Examples:
454
498
  everclaw doctor Check system health and connectivity
455
499
  everclaw status Show gateway status
456
500
 
457
- Documentation: https://docs.everclaw.ai`),e.addCommand(pi()),e.addCommand(yi()),e.addCommand(bi()),e.addCommand(hi()),e.addCommand(vi()),e.addCommand(ki()),o?.commands)for(let a of o.commands.values()){let l=e.command(a.contribution.name).description(a.contribution.description??"");a.contribution.builder&&a.contribution.builder(l),l.action(async c=>{await a.contribution.handler({},c)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").option("--skip-provider","Keep existing provider/model/apiKey config").option("--skip-channel","Keep existing channel config").option("--skip-workspace","Skip workspace creation and template sync").action(async a=>{let l=mt(),c=ce.existsSync(l),d=M();if(c){console.log(`Config already exists at ${l}`);let h=Ci.createInterface({input:xi,output:Ti}),v=(await h.question("Overwrite? [y/N] ")).trim().toLowerCase();h.close(),v==="y"?(d=structuredClone(de),oe(d),console.log(`Config reset to defaults at ${l}`)):(oe(d),console.log(`Config refreshed at ${l} (existing values preserved)`))}else oe(d),console.log(`Created config at ${l}`);if(a.skipWorkspace)console.log(C.gray("Skipping workspace setup (--skip-workspace)."));else{let h=X(d.agents.defaults.workspace);ce.existsSync(h)||(ce.mkdirSync(h,{recursive:!0}),console.log(`Created workspace at ${h}`)),ut(h)}if(a.provider||a.model||a.apiKey||a.apiBase||a.channel||a.channelToken||a.noChannel){if((a.provider??d.agents.defaults.provider)==="custom"&&a.apiKey&&a.apiBase){let v;try{v=new URL(a.apiBase).hostname.replace(/\./g,"-")}catch{v="custom-provider"}d.customLlmProviders.push({name:v,baseUrl:a.apiBase,apiKey:a.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),d.agents.defaults.provider=zt(v)}else{if(a.provider&&(d.agents.defaults.provider=a.provider),a.apiKey){let v=d.agents.defaults.provider;if(v in d.providers){let w=d.providers[v];w&&(w.apiKey=a.apiKey)}}if(a.apiBase){let v=d.agents.defaults.provider;if(v in d.providers){let w=d.providers[v];w&&(w.apiBase=a.apiBase)}}}if(a.model&&(d.agents.defaults.model=a.model),a.noChannel||(a.channel==="telegram"&&a.channelToken?(d.channels.telegram.enabled=!0,d.channels.telegram.token=a.channelToken):a.channel==="discord"&&a.channelToken&&(d.channels.discord.enabled=!0,d.channels.discord.token=a.channelToken)),oe(d),console.log(C.green(`
458
- Config created via non-interactive mode.`)),!a.noTest){console.log(C.cyan(`
459
- Running connectivity test...`));try{let w=await Le(d).chat({messages:[{role:"user",content:"Reply with: OK"}],model:d.agents.defaults.model,maxTokens:16,temperature:0});(w.content||"").toLowerCase().includes("error")?console.log(C.red(`Connectivity test failed: ${w.content}`)):console.log(C.green(`Connectivity test passed: ${w.content??"(empty response)"}`))}catch(v){console.log(C.red(`Connectivity test failed: ${String(v)}`))}}console.log(C.yellow(`
460
- Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){if(console.log(C.cyan(`
461
- everclaw Setup Wizard`)),console.log(C.gray(`Use arrow keys to pick options.
462
- `)),a.skipProvider)console.log(C.gray(`Skipping provider setup (--skip-provider). Current: ${d.agents.defaults.provider} / ${d.agents.defaults.model}`));else{let h=d.agents.defaults.provider,v=d.agents.defaults.model;h!=="auto"&&h!==de.agents.defaults.provider?(await pe({type:"confirm",name:"keep",message:`Keep current provider (${h}, model: ${v})?`,initial:!0})).keep?console.log(C.gray(`Keeping provider: ${h} / ${v}`)):await Ei(d):await Ei(d)}if(a.skipChannel||a.noChannel)console.log(C.gray("Skipping channel setup (--skip-channel)."));else{let h=d.channels.telegram.enabled&&d.channels.telegram.token,v=d.channels.discord.enabled&&d.channels.discord.token;if(h||v){let w=[];h&&w.push("telegram"),v&&w.push("discord"),(await pe({type:"confirm",name:"keep",message:`Keep current channel config (${w.join(", ")})?`,initial:!0})).keep?console.log(C.gray(`Keeping channel config: ${w.join(", ")}`)):await Ai(d)}else await Ai(d)}oe(d),console.log(C.green(`
463
- Configs created.`)),console.log(C.yellow("Run everclaw gateway")),console.log(C.yellow("or chat with agent: everclaw agent"));return}console.log(`
464
- everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${dt}, then run everclaw gateway or everclaw agent.`)}),e.command("config").description("Manage configuration").command("compact").description("Remove default values from config file (makes it sparse)").action(()=>{let a=mt();if(!ce.existsSync(a)){console.log(C.red(`No config file found at ${a}`)),console.log(C.gray("Run `everclaw onboard` to create one.")),process.exitCode=1;return}let l=M();oe(l),console.log(C.green(`Config compacted at ${a}`))}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new _o("--channel <channel>").default("cli").hideHelp()).addOption(new _o("--chat-id <chatId>").default("direct").hideHelp()).addOption(new _o("--raw-output").default(!1).hideHelp()).action(async a=>{let l=M(),c=Vt(l,process.env),d=X(c.agents.defaults.workspace);ut(d,!0);let p=new ft,h;try{h=Le(c)}catch(b){console.log(C.red(String(b))),process.exitCode=1;return}let v=new et(d),{cron:w}=qe({cron:{dataDir:je()}}),u=new Gt({bus:p,provider:h,workspace:d,model:c.agents.defaults.model,temperature:c.agents.defaults.temperature,maxTokens:c.agents.defaults.maxTokens,maxIterations:c.agents.defaults.maxToolIterations,memoryWindow:c.agents.defaults.memoryWindow,braveApiKey:c.tools.web.search.apiKey||null,execConfig:c.tools.exec,cronService:w,restrictToWorkspace:c.tools.restrictToWorkspace,channelsConfig:c.channels,loadConfig:M});if(a.message){let b=await u.processDirect(String(a.message),String(a.session),String(a.channel),String(a.chatId));a.rawOutput?process.stdout.write(b):console.log(`
501
+ Documentation: https://docs.everclaw.ai`),e.addCommand(ea()),e.addCommand(ra()),e.addCommand(oa()),e.addCommand(na()),e.addCommand(ia()),e.addCommand(la()),o?.commands)for(let c of o.commands.values()){let d=e.command(c.contribution.name).description(c.contribution.description??"");c.contribution.builder&&c.contribution.builder(d),d.action(async p=>{await c.contribution.handler({},p)})}e.command("onboard").description("Initialize everclaw configuration and workspace").option("--provider <name>","Provider name").option("--model <model>","Model ID").option("--api-key <key>","API key").option("--api-base <url>","API base URL").option("--channel <type>","Channel: telegram or discord").option("--channel-token <token>","Channel token").option("--no-channel","Skip channel setup").option("--no-test","Skip connectivity test").option("--skip-provider","Keep existing provider/model/apiKey config").option("--skip-channel","Keep existing channel config").option("--skip-workspace","Skip workspace creation and template sync").action(async c=>{let d=yt(),p=ue.existsSync(d),g=P();if(p){console.log(`Config already exists at ${d}`);let y=ca.createInterface({input:da,output:ua}),u=(await y.question("Overwrite? [y/N] ")).trim().toLowerCase();y.close(),u==="y"?(g=structuredClone(me),oe(g),console.log(`Config reset to defaults at ${d}`)):(oe(g),console.log(`Config refreshed at ${d} (existing values preserved)`))}else oe(g),console.log(`Created config at ${d}`);if(c.skipWorkspace)console.log(v.gray("Skipping workspace setup (--skip-workspace)."));else{let y=Z(g.agents.defaults.workspace);ue.existsSync(y)||(ue.mkdirSync(y,{recursive:!0}),console.log(`Created workspace at ${y}`)),ft(y)}if(c.provider||c.model||c.apiKey||c.apiBase||c.channel||c.channelToken||c.noChannel){if((c.provider??g.agents.defaults.provider)==="custom"&&c.apiKey&&c.apiBase){let u;try{u=new URL(c.apiBase).hostname.replace(/\./g,"-")}catch{u="custom-provider"}g.customLlmProviders.push({name:u,baseUrl:c.apiBase,apiKey:c.apiKey,apiFormat:"v1/chat/completions",models:[],extraHeaders:null}),g.agents.defaults.provider=tn(u)}else{if(c.provider&&(g.agents.defaults.provider=c.provider),c.apiKey){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiKey=c.apiKey)}}if(c.apiBase){let u=g.agents.defaults.provider;if(u in g.providers){let b=g.providers[u];b&&(b.apiBase=c.apiBase)}}}if(c.model&&(g.agents.defaults.model=c.model),c.noChannel||(c.channel==="telegram"&&c.channelToken?(g.channels.telegram.enabled=!0,g.channels.telegram.token=c.channelToken):c.channel==="discord"&&c.channelToken&&(g.channels.discord.enabled=!0,g.channels.discord.token=c.channelToken)),oe(g),console.log(v.green(`
502
+ Config created via non-interactive mode.`)),!c.noTest){console.log(v.cyan(`
503
+ Running connectivity test...`));try{let b=await Ne(g).chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});(b.content||"").toLowerCase().includes("error")?console.log(v.red(`Connectivity test failed: ${b.content}`)):console.log(v.green(`Connectivity test passed: ${b.content??"(empty response)"}`))}catch(u){console.log(v.red(`Connectivity test failed: ${String(u)}`))}}console.log(v.yellow(`
504
+ Run everclaw gateway or everclaw agent to start.`));return}if(process.stdin.isTTY&&process.stdout.isTTY){if(console.log(v.cyan(`
505
+ everclaw Setup Wizard`)),console.log(v.gray(`Use arrow keys to pick options.
506
+ `)),c.skipProvider)console.log(v.gray(`Skipping provider setup (--skip-provider). Current: ${g.agents.defaults.provider} / ${g.agents.defaults.model}`));else{let y=g.agents.defaults.provider,u=g.agents.defaults.model;y!=="auto"&&y!==me.agents.defaults.provider?(await ye({type:"confirm",name:"keep",message:`Keep current provider (${y}, model: ${u})?`,initial:!0})).keep?console.log(v.gray(`Keeping provider: ${y} / ${u}`)):await ma(g):await ma(g)}if(c.skipChannel||c.noChannel)console.log(v.gray("Skipping channel setup (--skip-channel)."));else{let y=g.channels.telegram.enabled&&g.channels.telegram.token,u=g.channels.discord.enabled&&g.channels.discord.token;if(y||u){let b=[];y&&b.push("telegram"),u&&b.push("discord"),(await ye({type:"confirm",name:"keep",message:`Keep current channel config (${b.join(", ")})?`,initial:!0})).keep?console.log(v.gray(`Keeping channel config: ${b.join(", ")}`)):await pa(g)}else await pa(g)}oe(g),console.log(v.green(`
507
+ Configs created.`)),console.log(v.yellow("Run everclaw gateway")),console.log(v.yellow("or chat with agent: everclaw agent"));return}console.log(`
508
+ everclaw is ready!`),console.log("Config is non-interactive in this terminal."),console.log(`Edit ${pt}, then run everclaw gateway or everclaw agent.`)}),e.command("config").description("Manage configuration").command("compact").description("Remove default values from config file (makes it sparse)").action(()=>{let c=yt();if(!ue.existsSync(c)){console.log(v.red(`No config file found at ${c}`)),console.log(v.gray("Run `everclaw onboard` to create one.")),process.exitCode=1;return}let d=P();oe(d),console.log(v.green(`Config compacted at ${c}`))}),e.command("agent").description("Interact with the agent directly").option("-m, --message <message>","Message to send to the agent").option("-s, --session <session>","Session ID","cli:direct").option("--no-markdown","Disable markdown rendering").addOption(new ns("--channel <channel>").default("cli").hideHelp()).addOption(new ns("--chat-id <chatId>").default("direct").hideHelp()).addOption(new ns("--raw-output").default(!1).hideHelp()).action(async c=>{let d=P(),p=nn(d,process.env),g=Z(p.agents.defaults.workspace);ft(g,!0);let x=new wt,y;try{y=Ne(p)}catch(S){console.log(v.red(String(S))),process.exitCode=1;return}let u=new ot(g),{cron:b}=Ve({cron:{dataDir:Be()}}),R=new zt({bus:x,provider:y,workspace:g,model:p.agents.defaults.model,temperature:p.agents.defaults.temperature,maxTokens:p.agents.defaults.maxTokens,maxIterations:p.agents.defaults.maxToolIterations,memoryWindow:p.agents.defaults.memoryWindow,braveApiKey:p.tools.web.search.apiKey||null,execConfig:p.tools.exec,cronService:b,restrictToWorkspace:p.tools.restrictToWorkspace,channelsConfig:p.channels,loadConfig:P});if(c.message){let S=await R.processDirect(String(c.message),String(c.session),String(c.channel),String(c.chatId));c.rawOutput?process.stdout.write(S):console.log(`
465
509
  everclaw
466
- ${b}
467
- `)}else{console.log("Interactive mode (type exit to quit)");let b=Ci.createInterface({input:xi,output:Ti});for(;;){let E=await b.question("You: "),S=E.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes(S))break;let N=await u.processDirect(E,String(a.session));console.log(`
510
+ ${S}
511
+ `)}else{console.log("Interactive mode (type exit to quit)");let S=ca.createInterface({input:da,output:ua});for(;;){let D=await S.question("You: "),$=D.trim().toLowerCase();if(["exit","quit","/exit","/quit",":q"].includes($))break;let I=await R.processDirect(D,String(c.session));console.log(`
468
512
  everclaw
469
- ${N}
470
- `)}b.close()}});let n=e.command("channels").description("Manage channels");n.addHelpText("after",`
513
+ ${I}
514
+ `)}S.close()}});let n=e.command("channels").description("Manage channels");n.addHelpText("after",`
471
515
  Examples:
472
- everclaw channels status Show channel configuration`),n.command("status").action(()=>{let a=M(),l=[["Telegram",a.channels.telegram.enabled?"yes":"no",a.channels.telegram.token?`token: ${a.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",a.channels.discord.enabled?"yes":"no",a.channels.discord.gatewayUrl]];for(let c of l){let d=c[0]??"",p=c[1]??"",h=c[2]??"";console.log(`${d.padEnd(12)} ${p.padEnd(3)} ${h}`)}}),n.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let r=e.command("auto").alias("automation").description("Manage browser automations");r.command("list").action(()=>{let a=M(),l=X(a.agents.defaults.workspace),c=Nt(l);if(!c.length)return console.log("No automations found.");console.log(C.cyan(`
473
- Saved Automations:`));for(let d of c)console.log(`${C.bold(d.id)} | ${d.name} | ${d.stepCount||0} steps | ${d.enabled?C.green("enabled"):C.gray("disabled")}`),d.description&&console.log(C.gray(` ${d.description}`));console.log("")}),r.command("show <id>").action(a=>{let l=M(),c=X(l.agents.defaults.workspace),d=Ce(c,a);if(!d)return console.log(C.red(`Automation '${a}' not found.`));console.log(C.cyan(`
474
- Automation: ${d.name} (${d.id})`)),console.log(C.gray(d.description||"No description")),console.log(`
475
- Steps (${d.steps.length}):`);for(let p of d.steps)console.log(` ${p.order}. ${p.description} (${p.action})`);d.scriptContent&&(console.log(C.yellow(`
476
- Generated Script:`)),console.log(C.gray("----------------------------------------")),console.log(d.scriptContent),console.log(C.gray("----------------------------------------"))),console.log("")}),r.command("run <id>").action(async a=>{let l=M(),c=X(l.agents.defaults.workspace),d=Ce(c,a);if(!d)return console.log(C.red(`Automation '${a}' not found.`));let p;if(l.tools.chromeSession?.enabled&&(p=new vt(l.tools.chromeSession,c,!!l.tools.restrictToWorkspace)),!p)return console.log(C.red("No browser tool available. Enable chrome_session in config."));let h=new Ft(c,p);console.log(C.cyan(`Running automation: ${d.name}...`));let v=await h.execute({command:"run",id:a});console.log(v)}),r.command("remove").alias("delete").argument("<id>").action(a=>{let l=M(),c=X(l.agents.defaults.workspace);jt(c,a)?console.log(C.green(`Removed automation '${a}'`)):console.log(C.red(`Automation '${a}' not found.`))});let s=e.command("cron").description("Manage scheduled tasks");return s.addHelpText("after",`
516
+ everclaw channels status Show channel configuration`),n.command("status").action(()=>{let c=P(),d=[["Telegram",c.channels.telegram.enabled?"yes":"no",c.channels.telegram.token?`token: ${c.channels.telegram.token.slice(0,10)}...`:"not configured"],["Discord",c.channels.discord.enabled?"yes":"no",c.channels.discord.gatewayUrl]];for(let p of d){let g=p[0]??"",x=p[1]??"",y=p[2]??"";console.log(`${g.padEnd(12)} ${x.padEnd(3)} ${y}`)}}),n.command("login").description("Link device via QR code").action(()=>{console.log("Bridge login is not yet implemented in TypeScript port. Use the existing Python bridge flow.")});let r=e.command("auto").alias("automation").description("Manage browser automations");r.command("list").action(()=>{let c=P(),d=Z(c.agents.defaults.workspace),p=Kt(d);if(!p.length)return console.log("No automations found.");console.log(v.cyan(`
517
+ Saved Automations:`));for(let g of p)console.log(`${v.bold(g.id)} | ${g.name} | ${g.stepCount||0} steps | ${g.enabled?v.green("enabled"):v.gray("disabled")}`),g.description&&console.log(v.gray(` ${g.description}`));console.log("")}),r.command("show <id>").action(c=>{let d=P(),p=Z(d.agents.defaults.workspace),g=Te(p,c);if(!g)return console.log(v.red(`Automation '${c}' not found.`));console.log(v.cyan(`
518
+ Automation: ${g.name} (${g.id})`)),console.log(v.gray(g.description||"No description")),console.log(`
519
+ Steps (${g.steps.length}):`);for(let x of g.steps)console.log(` ${x.order}. ${x.description} (${x.action})`);g.scriptContent&&(console.log(v.yellow(`
520
+ Generated Script:`)),console.log(v.gray("----------------------------------------")),console.log(g.scriptContent),console.log(v.gray("----------------------------------------"))),console.log("")}),r.command("run <id>").action(async c=>{let d=P(),p=Z(d.agents.defaults.workspace),g=Te(p,c);if(!g)return console.log(v.red(`Automation '${c}' not found.`));let x;if(d.tools.chromeSession?.enabled&&(x=new xt(d.tools.chromeSession,p,!!d.tools.restrictToWorkspace)),!x)return console.log(v.red("No browser tool available. Enable chrome_session in config."));let y=new Jt(p,x,d.tools.chromeSession?.stealth);console.log(v.cyan(`Running automation: ${g.name}...`));let u=await y.execute({command:"run",id:c});console.log(u)}),r.command("remove").alias("delete").argument("<id>").action(c=>{let d=P(),p=Z(d.agents.defaults.workspace);Ht(p,c)?console.log(v.green(`Removed automation '${c}'`)):console.log(v.red(`Automation '${c}' not found.`))});let s=e.command("cron").description("Manage scheduled tasks");s.addHelpText("after",`
477
521
  Examples:
478
522
  everclaw cron list List all scheduled jobs
479
523
  everclaw cron add -n "daily" --cron "0 9 * * *" -m "Good morning!"
480
524
  everclaw cron add -n "reminder" --at "2024-12-25T09:00:00" -m "Merry Christmas!" -d --to "12345" --channel "telegram"
481
- everclaw cron run abc123 Run a job immediately`),s.command("list").option("-a, --all","Include disabled jobs",!1).action(a=>{let{cron:l}=qe({cron:{dataDir:je()}}),c=l.listJobs(!!a.all);if(!c.length)return console.log("No scheduled jobs.");for(let d of c){let p=d.schedule.kind==="every"?`every ${d.schedule.everyMs/1e3}s`:d.schedule.kind==="cron"?`${d.schedule.expr} (${d.schedule.tz??"local"})`:"one-time",h=d.state.nextRunAtMs?new Date(d.state.nextRunAtMs).toISOString():"";console.log(`${d.id} | ${d.name} | ${p} | ${d.enabled?"enabled":"disabled"} | ${h}`)}}),s.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(a=>{if(a.tz&&!a.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let l;if(a.every)l={kind:"every",everyMs:Number(a.every)*1e3};else if(a.cron){let d={kind:"cron",expr:String(a.cron)};a.tz&&(d.tz=String(a.tz)),l=d}else if(a.at){let d=new Date(String(a.at));if(Number.isNaN(d.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}l={kind:"at",atMs:d.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:c}=qe({cron:{dataDir:je()}});try{let d={name:String(a.name),schedule:l,message:String(a.message),deliver:!!a.deliver};a.to&&(d.to=String(a.to)),a.channel&&(d.channel=String(a.channel));let p=c.addJob(d);console.log(`Added job '${p.name}' (${p.id})`)}catch(d){console.log(`Error: ${String(d).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),s.command("remove").argument("<jobId>").action(a=>{let{cron:l}=qe({cron:{dataDir:je()}});l.removeJob(a)?console.log(`Removed job ${a}`):console.log(`Job ${a} not found`)}),s.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((a,l)=>{let{cron:c}=qe({cron:{dataDir:je()}}),d=c.enableJob(a,!l.disable);if(!d)return console.log(`Job ${a} not found`);console.log(`Job '${d.name}' ${l.disable?"disabled":"enabled"}`)}),s.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(a,l)=>{let c=M(),d=X(c.agents.defaults.workspace),p;try{p=Le(c)}catch(E){console.log(C.red(String(E))),process.exitCode=1;return}let h=new ft,v=vr(c.tools.exec.timeout),w=gn({target:"scheduled-job",timeoutMs:v}),{cron:u}=qe({cron:{dataDir:je(),onJob:async(E,S)=>{let N=await w.run({payload:{message:E.payload.message,session:`cron:${E.id}`,channel:E.payload.channel??"cli",chatId:E.payload.to??"direct"},cwd:process.cwd(),signal:S?.signal});return b.push(N),N}}}),b=[];await u.runJob(a,!!l.force)?(console.log("Job executed"),b.length&&console.log(b[0])):(console.log(`Failed to run job ${a}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let l=!!e.opts().json,c=mt(),d=M(),p=X(d.agents.defaults.workspace),h=d.gateway.port,v=null;try{let b=await fetch(`http://127.0.0.1:${h}/api/status`,{signal:AbortSignal.timeout(2e3)});b.ok&&(v=await b.json())}catch{}let u=await new Ee().getStatus();if(l){let b={gateway:{running:!!v,port:v?v.gateway?.port??h:null},model:d.agents.defaults.model,provider:Qe(d)??null,config:{path:c,exists:ce.existsSync(c)},workspace:{path:p,exists:ce.existsSync(p)},rtk:{installed:u.installed,version:u.version??null,binaryPath:u.binaryPath}};if(v){let E=v.runtime,S=v.channelStatus,N=Ie();b.gateway={running:!0,port:v.gateway?.port??h,pid:N?.pid??null,uptime:N?pt(N.startedAt):null},b.agent={acceptingWork:E?.acceptingWork??!0,activeSessions:E?.activeSessions??0,queuedMessages:E?.queuedMessages??0,subagents:E?.subagents??0},b.channels=S??{}}console.log(JSON.stringify(b,null,2));return}if(console.log(C.cyan(`everclaw Status
482
- `)),v){let b=v.runtime,E=v.gateway,S=v.channelStatus,N=Ie(),U=N?pt(N.startedAt):"unknown";console.log(`Gateway: ${C.green("running")} (port ${E?.port??h}, uptime ${U})`),console.log(`Agent: ${b?.acceptingWork?C.green("idle (accepting work)"):C.yellow("busy")}`),console.log(` Active sessions: ${b?.activeSessions??0}`),console.log(` Queued messages: ${b?.queuedMessages??0}`),console.log(` Subagents: ${b?.subagents??0}`);let I=b?.overload;if(I&&typeof I.rateLimited=="number"&&I.rateLimited>0&&console.log(` Rate limited: ${C.yellow(String(I.rateLimited))} (window: ${I.rateLimitWindowMs??0}ms)`),S&&Object.keys(S).length>0){console.log(`
483
- Channels:`);for(let[J,re]of Object.entries(S)){let K=re?.running?C.green("connected"):C.gray("disconnected");console.log(` ${J.padEnd(12)} ${K}`)}}}else console.log(`Gateway: ${C.gray("not running")}`);console.log(`
484
- Model: ${d.agents.defaults.model}`),console.log(`Provider: ${Qe(d)??"none"}`),console.log(`Config: ${c} ${ce.existsSync(c)?"yes":"no"}`),console.log(`Workspace: ${p} ${ce.existsSync(p)?"yes":"no"}`),console.log(`
485
- RTK Token Compression:`),u.installed&&u.version?(console.log(` Status: ${C.green("Available")} (v${u.version})`),console.log(` Binary: ${u.binaryPath}`)):u.installed?(console.log(` Status: ${C.yellow("Installed but broken")}`),console.log(` Binary: ${u.binaryPath}`),console.log(C.gray(` Run ${C.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${C.gray("Not installed")}`),d.tools.rtk.autoInstall?console.log(C.gray(" Auto-install is enabled and will download on first gateway start")):console.log(C.gray(` Run ${C.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let l=!!e.opts().json,c=M(),d=Vt(c,process.env),p=Qe(d),h=[],v={ok:!0,warnings:[]},w=Ie(),u=w&&Pe(w.pid);v.system={gateway:u?{running:!0,pid:w.pid,port:w.port,uptime:pt(w.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:Ri()??"standalone"},l||(console.log(C.cyan(`everclaw doctor
486
- `)),console.log(C.bold("System:")),console.log(u?` Gateway: ${C.green("running")} (PID ${w.pid}, port ${w.port}, uptime ${pt(w.startedAt)})`:` Gateway: ${C.gray("not running")}`));let b=process.versions.node,E=parseInt(b.split(".")[0]??"0",10);E<20&&h.push("Node.js version below 20 may have compatibility issues");let S=process.getuid?.()===0;if(S&&h.push("Running as root is not recommended for security"),!l){E>=20?console.log(` Node.js: ${C.green(b)}`):console.log(` Node.js: ${C.yellow(b)} (recommend v20+)`),console.log(S?` Running as: ${C.red("root")} (not recommended)`:` Running as: ${C.green("non-root")}`);let R=Ri();console.log(R?` Supervisor: ${C.green(R)}`:` Supervisor: ${C.gray("standalone")}`)}let N=mt();if(ce.existsSync(N))try{let F=!!(ce.statSync(N).mode&511&7);v.system.configPermissions={ok:!F,path:N},F&&h.push("Config file is world-readable \u2014 contains API keys"),l||console.log(F?` Config: ${C.yellow("world-readable")} (${N})`:` Config: ${C.green("ok")} (${N})`)}catch{l||console.log(` Config: ${C.gray("unable to check")}`)}try{let R=je();ce.statSync(R);let O=yd(R);if(O!==null){let F=Math.round(O/1048576);v.system.diskSpace={freeMB:F,path:R,ok:O>=100*1024*1024},O<100*1024*1024&&h.push(`Low disk space: ${F}MB free in ${R}`),l||(O<100*1024*1024?console.log(` Disk space: ${C.yellow(`${F}MB free`)} (${R})`):console.log(` Disk space: ${C.green(`${F}MB free`)} (${R})`))}}catch{}let U=X(d.agents.defaults.workspace);if(ce.existsSync(U))try{let F=!!(ce.statSync(U).mode&511&2);v.system.workspace={ok:!F,path:U},F&&h.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),l||console.log(F?` Workspace: ${C.yellow("world-writable")} (${U})`:` Workspace: ${C.green("ok")} (${U})`)}catch{l||console.log(` Workspace: ${C.gray("unable to check")}`)}else v.system.workspace={ok:!0,path:U,created:!1},l||console.log(` Workspace: ${C.gray("not created")} (${U})`);let I=d.security;if(v.security={enabled:I.enabled,auth:I.auth.enabled,toolGuard:I.toolGuard.enabled,skillScanner:I.skillScanner.enabled,inputSanitizer:I.inputSanitizer.enabled,pathBoundary:d.tools.restrictToWorkspace},l)I.toolGuard.enabled&&I.toolGuard.failOpen&&h.push("Tool guard is fail-open \u2014 consider fail-closed for production"),I.skillScanner.enabled||h.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),d.tools.restrictToWorkspace||h.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!I.auth.enabled&&d.gateway.host!=="127.0.0.1"&&d.gateway.host!=="localhost"&&h.push("Dashboard exposed on non-loopback without auth");else{if(console.log(C.bold(`
487
- Security:`)),console.log(` Master switch: ${I.enabled?C.green("enabled"):C.gray("disabled")}`),I.auth.enabled){let R=I.auth.sessionTtlS?`${Math.floor(I.auth.sessionTtlS/60)}min`:"default",O=I.auth.idleTimeoutS?`${Math.floor(I.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${C.green("enabled")} (PIN, session TTL: ${R}, idle lock: ${O})`)}else console.log(` Authentication: ${C.gray("disabled")}`),d.gateway.host!=="127.0.0.1"&&d.gateway.host!=="localhost"&&h.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${I.toolGuard.enabled?C.green("enabled"):C.gray("disabled")}`),I.toolGuard.enabled&&I.toolGuard.failOpen&&h.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${I.skillScanner.enabled?C.green("enabled"):C.gray("disabled")}`),I.skillScanner.enabled||h.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${I.inputSanitizer.enabled?C.green("enabled"):C.gray("disabled")}`),console.log(` Path Boundary: ${d.tools.restrictToWorkspace?C.green("workspace-restricted"):C.yellow("unrestricted")}`),d.tools.restrictToWorkspace||h.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let J=Vo(d);for(let R of J)h.includes(R)||h.push(R);v.provider={name:p??null,model:d.agents.defaults.model},l||(console.log(C.bold(`
488
- Provider:`)),console.log(` Resolved: ${p??"none"}`),console.log(` Model: ${d.agents.defaults.model}`));let q=await new Ee().getStatus();v.rtk={installed:q.installed,version:q.version??null,binaryPath:q.binaryPath},q.installed&&q.version&&!xt(q.version,Re)&&h.push(`RTK version ${q.version} is below minimum ${Re}`),l||(console.log(C.bold(`
489
- RTK Token Compression:`)),q.installed&&q.version?xt(q.version,Re)?console.log(` Status: ${C.green("Available")} (v${q.version})`):console.log(` Status: ${C.yellow("Outdated")} (v${q.version}, min: ${Re})`):console.log(` Status: ${C.gray("Not installed")}`));let K=Object.keys(d.tools.mcpServers);if(K.length>0){let R={};l||console.log(C.bold(`
490
- MCP Servers:`));for(let O of K)try{let{McpClientManager:F}=await Promise.resolve().then(()=>(un(),br)),z=new F;z.updateConfig(d.tools.mcpServers);let g=await z.getServerTools(O);await z.closeAll(),R[O]={connected:!0,tools:g.length},l||console.log(` ${O.padEnd(20)} ${C.green("\u2713 connected")} (${g.length} tools)`)}catch(F){let z=F instanceof Error?F.message:String(F);R[O]={connected:!1,error:z},l||console.log(` ${O.padEnd(20)} ${C.red("\u2717 "+z)}`)}v.mcp=R}let V={};if(d.channels.telegram.enabled){let R=d.channels.telegram.token,O=R?/^\d+:[A-Za-z0-9_-]{30,}$/.test(R):!1;V.telegram={enabled:!0,configured:!!R,validFormat:O},R?O||h.push("Telegram token format does not match expected pattern"):h.push("Telegram channel enabled but no token configured")}if(d.channels.discord.enabled){let R=d.channels.discord.token,O=R?R.length>=50&&/^[A-Za-z0-9._-]+$/.test(R):!1;V.discord={enabled:!0,configured:!!R,validFormat:O},R?O||h.push("Discord token format does not match expected pattern"):h.push("Discord channel enabled but no token configured")}if(Object.keys(V).length>0&&(v.channels=V,!l)){if(console.log(C.bold(`
491
- Channel Tokens:`)),d.channels.telegram.enabled){let R=d.channels.telegram.token;R&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(R)?console.log(` Telegram: ${C.green("valid format")}`):console.log(R?` Telegram: ${C.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${C.red("not configured")}`)}if(d.channels.discord.enabled){let R=d.channels.discord.token;R&&R.length>=50&&/^[A-Za-z0-9._-]+$/.test(R)?console.log(` Discord: ${C.green("valid format")}`):console.log(R?` Discord: ${C.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${C.red("not configured")}`)}}l||console.log(C.bold(`
492
- LLM Connectivity:`));let ie;try{ie=Le(d)}catch(R){v.llm={connected:!1,error:String(R)},v.ok=!1,v.warnings=h,console.log(l?JSON.stringify(v,null,2):` ${C.red("Failed to create provider: "+String(R))}`),process.exitCode=W.GENERAL_ERROR;return}try{let R=await ie.chat({messages:[{role:"user",content:"Reply with: OK"}],model:d.agents.defaults.model,maxTokens:16,temperature:0});if((R.content||"").toLowerCase().includes("error")){v.llm={connected:!1,error:R.content},v.ok=!1,v.warnings=h,console.log(l?JSON.stringify(v,null,2):` ${C.red("Failed: "+R.content)}`),process.exitCode=W.CONNECTIVITY_ERROR;return}v.llm={connected:!0},l||console.log(` ${C.green("Passed")}: ${R.content??"(empty response)"}`)}catch(R){v.llm={connected:!1,error:String(R)},v.ok=!1,v.warnings=h,console.log(l?JSON.stringify(v,null,2):` ${C.red("Failed: "+String(R))}`),process.exitCode=W.CONNECTIVITY_ERROR;return}if(v.warnings=h,l){console.log(JSON.stringify(v,null,2));return}if(h.length>0){console.log(C.bold(`
493
- Warnings:`));for(let R of h)console.log(` ${C.yellow("\u26A0")} ${R}`)}console.log(C.green(`
494
- Doctor check complete.`))}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(a=>{let l=a.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(l)){console.log(`Unknown OAuth provider: ${a}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${a} is not yet implemented in TypeScript port.`)}),e}Uo(process.argv);var bd=Pi();bd.parseAsync(process.argv);
525
+ everclaw cron run abc123 Run a job immediately`),s.command("list").option("-a, --all","Include disabled jobs",!1).action(c=>{let{cron:d}=Ve({cron:{dataDir:Be()}}),p=d.listJobs(!!c.all);if(!p.length)return console.log("No scheduled jobs.");for(let g of p){let x=g.schedule.kind==="every"?`every ${g.schedule.everyMs/1e3}s`:g.schedule.kind==="cron"?`${g.schedule.expr} (${g.schedule.tz??"local"})`:"one-time",y=g.state.nextRunAtMs?new Date(g.state.nextRunAtMs).toISOString():"";console.log(`${g.id} | ${g.name} | ${x} | ${g.enabled?"enabled":"disabled"} | ${y}`)}}),s.command("add").requiredOption("-n, --name <name>").requiredOption("-m, --message <message>").option("-e, --every <seconds>").option("-c, --cron <expr>").option("--tz <tz>").option("--at <iso>").option("-d, --deliver","Deliver response to channel",!1).option("--to <recipient>").option("--channel <channel>").action(c=>{if(c.tz&&!c.cron){console.log("Error: --tz can only be used with --cron"),process.exitCode=1;return}let d;if(c.every)d={kind:"every",everyMs:Number(c.every)*1e3};else if(c.cron){let g={kind:"cron",expr:String(c.cron)};c.tz&&(g.tz=String(c.tz)),d=g}else if(c.at){let g=new Date(String(c.at));if(Number.isNaN(g.getTime())){console.log("Error: invalid --at datetime"),process.exitCode=1;return}d={kind:"at",atMs:g.getTime()}}else{console.log("Error: Must specify --every, --cron, or --at"),process.exitCode=1;return}let{cron:p}=Ve({cron:{dataDir:Be()}});try{let g={name:String(c.name),schedule:d,message:String(c.message),deliver:!!c.deliver};c.to&&(g.to=String(c.to)),c.channel&&(g.channel=String(c.channel));let x=p.addJob(g);console.log(`Added job '${x.name}' (${x.id})`)}catch(g){console.log(`Error: ${String(g).replace(/^Error:\s*/,"")}`),process.exitCode=1}}),s.command("remove").argument("<jobId>").action(c=>{let{cron:d}=Ve({cron:{dataDir:Be()}});d.removeJob(c)?console.log(`Removed job ${c}`):console.log(`Job ${c} not found`)}),s.command("enable").argument("<jobId>").option("--disable","Disable instead",!1).action((c,d)=>{let{cron:p}=Ve({cron:{dataDir:Be()}}),g=p.enableJob(c,!d.disable);if(!g)return console.log(`Job ${c} not found`);console.log(`Job '${g.name}' ${d.disable?"disabled":"enabled"}`)}),s.command("run").argument("<jobId>").option("-f, --force","Run even if disabled",!1).action(async(c,d)=>{let p=P(),g=Z(p.agents.defaults.workspace),x;try{x=Ne(p)}catch(D){console.log(v.red(String(D))),process.exitCode=1;return}let y=new wt,u=Dr(p.tools.exec.timeout),b=Cn({target:"scheduled-job",timeoutMs:u}),{cron:R}=Ve({cron:{dataDir:Be(),onJob:async(D,$)=>{let I=await b.run({payload:{message:D.payload.message,session:`cron:${D.id}`,channel:D.payload.channel??"cli",chatId:D.payload.to??"direct"},cwd:process.cwd(),signal:$?.signal});return S.push(I),I}}}),S=[];await R.runJob(c,!!d.force)?(console.log("Job executed"),S.length&&console.log(S[0])):(console.log(`Failed to run job ${c}`),process.exitCode=1)}),e.command("status").description("Show everclaw status").action(async()=>{let d=!!e.opts().json,p=yt(),g=P(),x=Z(g.agents.defaults.workspace),y=g.gateway.port,u=null;try{let S=await fetch(`http://127.0.0.1:${y}/api/status`,{signal:AbortSignal.timeout(2e3)});S.ok&&(u=await S.json())}catch{}let R=await new Pe().getStatus();if(d){let S={gateway:{running:!!u,port:u?u.gateway?.port??y:null},model:g.agents.defaults.model,provider:nt(g)??null,config:{path:p,exists:ue.existsSync(p)},workspace:{path:x,exists:ue.existsSync(x)},rtk:{installed:R.installed,version:R.version??null,binaryPath:R.binaryPath}};if(u){let D=u.runtime,$=u.channelStatus,I=Ie();S.gateway={running:!0,port:u.gateway?.port??y,pid:I?.pid??null,uptime:I?bt(I.startedAt):null},S.agent={acceptingWork:D?.acceptingWork??!0,activeSessions:D?.activeSessions??0,queuedMessages:D?.queuedMessages??0,subagents:D?.subagents??0},S.channels=$??{}}console.log(JSON.stringify(S,null,2));return}if(console.log(v.cyan(`everclaw Status
526
+ `)),u){let S=u.runtime,D=u.gateway,$=u.channelStatus,I=Ie(),H=I?bt(I.startedAt):"unknown";console.log(`Gateway: ${v.green("running")} (port ${D?.port??y}, uptime ${H})`),console.log(`Agent: ${S?.acceptingWork?v.green("idle (accepting work)"):v.yellow("busy")}`),console.log(` Active sessions: ${S?.activeSessions??0}`),console.log(` Queued messages: ${S?.queuedMessages??0}`),console.log(` Subagents: ${S?.subagents??0}`);let L=S?.overload;if(L&&typeof L.rateLimited=="number"&&L.rateLimited>0&&console.log(` Rate limited: ${v.yellow(String(L.rateLimited))} (window: ${L.rateLimitWindowMs??0}ms)`),$&&Object.keys($).length>0){console.log(`
527
+ Channels:`);for(let[Q,Y]of Object.entries($)){let z=Y?.running?v.green("connected"):v.gray("disconnected");console.log(` ${Q.padEnd(12)} ${z}`)}}}else console.log(`Gateway: ${v.gray("not running")}`);console.log(`
528
+ Model: ${g.agents.defaults.model}`),console.log(`Provider: ${nt(g)??"none"}`),console.log(`Config: ${p} ${ue.existsSync(p)?"yes":"no"}`),console.log(`Workspace: ${x} ${ue.existsSync(x)?"yes":"no"}`),console.log(`
529
+ RTK Token Compression:`),R.installed&&R.version?(console.log(` Status: ${v.green("Available")} (v${R.version})`),console.log(` Binary: ${R.binaryPath}`)):R.installed?(console.log(` Status: ${v.yellow("Installed but broken")}`),console.log(` Binary: ${R.binaryPath}`),console.log(v.gray(` Run ${v.cyan("everclaw rtk install --force")} to reinstall`))):(console.log(` Status: ${v.gray("Not installed")}`),g.tools.rtk.autoInstall?console.log(v.gray(" Auto-install is enabled and will download on first gateway start")):console.log(v.gray(` Run ${v.cyan("everclaw rtk install")} to install`)))}),e.command("doctor").description("Validate provider/model configuration and connectivity").action(async()=>{let d=!!e.opts().json,p=P(),g=nn(p,process.env),x=nt(g),y=[],u={ok:!0,warnings:[]},b=Ie(),R=b&&Me(b.pid);u.system={gateway:R?{running:!0,pid:b.pid,port:b.port,uptime:bt(b.startedAt)}:{running:!1},nodeVersion:process.versions.node,root:process.getuid?.()===0,supervisor:ga()??"standalone"},d||(console.log(v.cyan(`everclaw doctor
530
+ `)),console.log(v.bold("System:")),console.log(R?` Gateway: ${v.green("running")} (PID ${b.pid}, port ${b.port}, uptime ${bt(b.startedAt)})`:` Gateway: ${v.gray("not running")}`));let S=process.versions.node,D=parseInt(S.split(".")[0]??"0",10);D<20&&y.push("Node.js version below 20 may have compatibility issues");let $=process.getuid?.()===0;if($&&y.push("Running as root is not recommended for security"),!d){D>=20?console.log(` Node.js: ${v.green(S)}`):console.log(` Node.js: ${v.yellow(S)} (recommend v20+)`),console.log($?` Running as: ${v.red("root")} (not recommended)`:` Running as: ${v.green("non-root")}`);let m=ga();console.log(m?` Supervisor: ${v.green(m)}`:` Supervisor: ${v.gray("standalone")}`)}let I=yt();if(ue.existsSync(I))try{let C=!!(ue.statSync(I).mode&511&7);u.system.configPermissions={ok:!C,path:I},C&&y.push("Config file is world-readable \u2014 contains API keys"),d||console.log(C?` Config: ${v.yellow("world-readable")} (${I})`:` Config: ${v.green("ok")} (${I})`)}catch{d||console.log(` Config: ${v.gray("unable to check")}`)}try{let m=Be();ue.statSync(m);let k=iu(m);if(k!==null){let C=Math.round(k/1048576);u.system.diskSpace={freeMB:C,path:m,ok:k>=100*1024*1024},k<100*1024*1024&&y.push(`Low disk space: ${C}MB free in ${m}`),d||(k<100*1024*1024?console.log(` Disk space: ${v.yellow(`${C}MB free`)} (${m})`):console.log(` Disk space: ${v.green(`${C}MB free`)} (${m})`))}}catch{}let H=Z(g.agents.defaults.workspace);if(ue.existsSync(H))try{let C=!!(ue.statSync(H).mode&511&2);u.system.workspace={ok:!C,path:H},C&&y.push("Workspace directory is world-writable \u2014 may allow unauthorized file modifications"),d||console.log(C?` Workspace: ${v.yellow("world-writable")} (${H})`:` Workspace: ${v.green("ok")} (${H})`)}catch{d||console.log(` Workspace: ${v.gray("unable to check")}`)}else u.system.workspace={ok:!0,path:H,created:!1},d||console.log(` Workspace: ${v.gray("not created")} (${H})`);let L=g.security;if(u.security={enabled:L.enabled,auth:L.auth.enabled,toolGuard:L.toolGuard.enabled,skillScanner:L.skillScanner.enabled,inputSanitizer:L.inputSanitizer.enabled,pathBoundary:g.tools.restrictToWorkspace},d)L.toolGuard.enabled&&L.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),L.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace"),!L.auth.enabled&&g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");else{if(console.log(v.bold(`
531
+ Security:`)),console.log(` Master switch: ${L.enabled?v.green("enabled"):v.gray("disabled")}`),L.auth.enabled){let m=L.auth.sessionTtlS?`${Math.floor(L.auth.sessionTtlS/60)}min`:"default",k=L.auth.idleTimeoutS?`${Math.floor(L.auth.idleTimeoutS/60)}min`:"off";console.log(` Authentication: ${v.green("enabled")} (PIN, session TTL: ${m}, idle lock: ${k})`)}else console.log(` Authentication: ${v.gray("disabled")}`),g.gateway.host!=="127.0.0.1"&&g.gateway.host!=="localhost"&&y.push("Dashboard exposed on non-loopback without auth");console.log(` Tool Guard: ${L.toolGuard.enabled?v.green("enabled"):v.gray("disabled")}`),L.toolGuard.enabled&&L.toolGuard.failOpen&&y.push("Tool guard is fail-open \u2014 consider fail-closed for production"),console.log(` Skill Scanner: ${L.skillScanner.enabled?v.green("enabled"):v.gray("disabled")}`),L.skillScanner.enabled||y.push("Skill scanner disabled \u2014 unsafe skills will not be blocked"),console.log(` Input Sanitizer: ${L.inputSanitizer.enabled?v.green("enabled"):v.gray("disabled")}`),console.log(` Path Boundary: ${g.tools.restrictToWorkspace?v.green("workspace-restricted"):v.yellow("unrestricted")}`),g.tools.restrictToWorkspace||y.push("Path boundary not restricted \u2014 agent can access files outside workspace")}let Q=vs(g);for(let m of Q)y.includes(m)||y.push(m);u.provider={name:x??null,model:g.agents.defaults.model},d||(console.log(v.bold(`
532
+ Provider:`)),console.log(` Resolved: ${x??"none"}`),console.log(` Model: ${g.agents.defaults.model}`));let F=await new Pe().getStatus();u.rtk={installed:F.installed,version:F.version??null,binaryPath:F.binaryPath},F.installed&&F.version&&!Pt(F.version,Ee)&&y.push(`RTK version ${F.version} is below minimum ${Ee}`),d||(console.log(v.bold(`
533
+ RTK Token Compression:`)),F.installed&&F.version?Pt(F.version,Ee)?console.log(` Status: ${v.green("Available")} (v${F.version})`):console.log(` Status: ${v.yellow("Outdated")} (v${F.version}, min: ${Ee})`):console.log(` Status: ${v.gray("Not installed")}`));let z=Object.keys(g.tools.mcpServers);if(z.length>0){let m={};d||console.log(v.bold(`
534
+ MCP Servers:`));for(let k of z)try{let{McpClientManager:C}=await Promise.resolve().then(()=>(wn(),$r)),A=new C;A.updateConfig(g.tools.mcpServers);let T=await A.getServerTools(k);await A.closeAll(),m[k]={connected:!0,tools:T.length},d||console.log(` ${k.padEnd(20)} ${v.green("\u2713 connected")} (${T.length} tools)`)}catch(C){let A=C instanceof Error?C.message:String(C);m[k]={connected:!1,error:A},d||console.log(` ${k.padEnd(20)} ${v.red("\u2717 "+A)}`)}u.mcp=m}let B={};if(g.channels.telegram.enabled){let m=g.channels.telegram.token,k=m?/^\d+:[A-Za-z0-9_-]{30,}$/.test(m):!1;B.telegram={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Telegram token format does not match expected pattern"):y.push("Telegram channel enabled but no token configured")}if(g.channels.discord.enabled){let m=g.channels.discord.token,k=m?m.length>=50&&/^[A-Za-z0-9._-]+$/.test(m):!1;B.discord={enabled:!0,configured:!!m,validFormat:k},m?k||y.push("Discord token format does not match expected pattern"):y.push("Discord channel enabled but no token configured")}if(Object.keys(B).length>0&&(u.channels=B,!d)){if(console.log(v.bold(`
535
+ Channel Tokens:`)),g.channels.telegram.enabled){let m=g.channels.telegram.token;m&&/^\d+:[A-Za-z0-9_-]{30,}$/.test(m)?console.log(` Telegram: ${v.green("valid format")}`):console.log(m?` Telegram: ${v.yellow("unusual format")} \u2014 verify the token is correct`:` Telegram: ${v.red("not configured")}`)}if(g.channels.discord.enabled){let m=g.channels.discord.token;m&&m.length>=50&&/^[A-Za-z0-9._-]+$/.test(m)?console.log(` Discord: ${v.green("valid format")}`):console.log(m?` Discord: ${v.yellow("unusual format")} \u2014 verify the token is correct`:` Discord: ${v.red("not configured")}`)}}d||console.log(v.bold(`
536
+ LLM Connectivity:`));let N;try{N=Ne(g)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${v.red("Failed to create provider: "+String(m))}`),process.exitCode=W.GENERAL_ERROR;return}try{let m=await N.chat({messages:[{role:"user",content:"Reply with: OK"}],model:g.agents.defaults.model,maxTokens:16,temperature:0});if((m.content||"").toLowerCase().includes("error")){u.llm={connected:!1,error:m.content},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${v.red("Failed: "+m.content)}`),process.exitCode=W.CONNECTIVITY_ERROR;return}u.llm={connected:!0},d||console.log(` ${v.green("Passed")}: ${m.content??"(empty response)"}`)}catch(m){u.llm={connected:!1,error:String(m)},u.ok=!1,u.warnings=y,console.log(d?JSON.stringify(u,null,2):` ${v.red("Failed: "+String(m))}`),process.exitCode=W.CONNECTIVITY_ERROR;return}u.warnings=y;let J=g.compaction||{},G=J.enabled!==!1,f=g.tools?.chromeSession?.stealth?.enabled??!1;if(u.compaction={enabled:G,...G?{microCompactThresholdRatio:J.microCompactThresholdRatio??.6,autoCompactThresholdRatio:J.autoCompactThresholdRatio??.8,keepRecentMessages:J.keepRecentMessages??10}:{}},u.stealth={enabled:f,chromeEnabled:g.tools?.chromeSession?.enabled??!1},d||(console.log(v.bold(`
537
+ Compaction:`)),console.log(` Status: ${G?v.green("enabled"):v.gray("disabled")}`),G&&(console.log(` Micro: ${((J.microCompactThresholdRatio??.6)*100).toFixed(0)}% threshold`),console.log(` Auto: ${((J.autoCompactThresholdRatio??.8)*100).toFixed(0)}% threshold`),console.log(` Keep: ${J.keepRecentMessages??10} messages`)),console.log(v.bold(`
538
+ Stealth:`)),console.log(` Status: ${f?v.green("enabled"):v.gray("disabled")}`),g.tools?.chromeSession?.enabled?console.log(` Chrome: ${v.green("enabled")}`):console.log(` Chrome: ${v.gray("disabled")}`)),d){console.log(JSON.stringify(u,null,2));return}if(y.length>0){console.log(v.bold(`
539
+ Warnings:`));for(let m of y)console.log(` ${v.yellow("\u26A0")} ${m}`)}console.log(v.green(`
540
+ Doctor check complete.`))}),e.command("provider").description("Manage providers").command("login").argument("<provider>").action(c=>{let d=c.replace(/-/g,"_");if(!["openai_codex","github_copilot"].includes(d)){console.log(`Unknown OAuth provider: ${c}. Supported: openai-codex, github-copilot`),process.exitCode=1;return}console.log(`OAuth login for ${c} is not yet implemented in TypeScript port.`)}),e.command("tasks").description("List active tasks from the running gateway").option("--session <key>","Filter by session key").option("--status <status>","Filter by status (pending|running|completed|failed|killed)").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,x=P().gateway.port,y=null;try{let S=await fetch(`http://127.0.0.1:${x}/api/status`,{signal:AbortSignal.timeout(2e3)});S.ok&&(y=await S.json())}catch{console.log(v.gray("Gateway not running. Use `everclaw gateway start` to start the gateway.")),process.exitCode=W.GENERAL_ERROR;return}let R=y?.runtime?.tasks||[];if(c.status&&(R=R.filter(S=>S.status===c.status)),c.session&&(R=R.filter(S=>S.sessionKey===c.session)),p){console.log(JSON.stringify(R,null,2));return}if(R.length===0){console.log(v.gray("No active tasks."));return}console.log(v.cyan(`Active Tasks
541
+ `)),console.log("ID".padEnd(12)+"Type".padEnd(12)+"Status".padEnd(12)+"Label".padEnd(40)+"Duration"),console.log("-".repeat(88));for(let S of R){let D=String(S.id||"").slice(0,10).padEnd(12),$=String(S.type||"unknown").padEnd(12),I=String(S.status||"pending"),H=String(S.label||"Untitled").slice(0,38).padEnd(40),L=S.startedAt?new Date(S.startedAt):null,Q=L?`${Math.floor((Date.now()-L.getTime())/1e3)}s`:"-",Y=I==="running"?v.blue(I.padEnd(12)):I==="completed"?v.green(I.padEnd(12)):I==="failed"?v.red(I.padEnd(12)):I==="killed"?v.gray(I.padEnd(12)):I.padEnd(12);console.log(`${D}${$}${Y}${H}${Q}`)}});let a=e.command("compact").description("Context compaction telemetry and configuration");a.command("status").description("Show compaction stats from the running gateway").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,x=P().gateway.port,y=null;try{let S=await fetch(`http://127.0.0.1:${x}/api/status`,{signal:AbortSignal.timeout(2e3)});S.ok&&(y=await S.json())}catch{console.log(v.gray("Gateway not running. Use `everclaw gateway start` to start the gateway.")),process.exitCode=W.GENERAL_ERROR;return}let b=y?.runtime?.compaction;if(p){console.log(JSON.stringify(b||{},null,2));return}if(!b){console.log(v.gray("Compaction stats not available."));return}console.log(v.cyan(`Context Compaction
542
+ `)),console.log(` Status: ${b.enabled?v.green("enabled"):v.gray("disabled")}`),console.log(` Micro compactions: ${b.microCompactions??0}`),console.log(` Auto compactions: ${b.autoCompactions??0}`),console.log(` Reactive compactions: ${b.reactiveCompactions??0}`);let R=b.tokensFreed;console.log(` Tokens freed: ${R?R>=1e3?`${(R/1e3).toFixed(1)}K`:R:0}`),b.circuitBreakerTripped&&console.log(` Circuit breaker: ${v.red("tripped")} (compaction paused)`)}),a.command("config").description("Show compaction configuration").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,x=P().compaction||{};if(p){console.log(JSON.stringify(x,null,2));return}console.log(v.cyan(`Compaction Configuration
543
+ `)),console.log(` Enabled: ${x.enabled!==!1?v.green("yes"):v.gray("no")}`),console.log(` Micro-compact threshold: ${((x.microCompactThresholdRatio??.6)*100).toFixed(0)}%`),console.log(` Auto-compact threshold: ${((x.autoCompactThresholdRatio??.8)*100).toFixed(0)}%`),console.log(` Keep recent messages: ${x.keepRecentMessages??10}`),console.log(` Max consecutive failures: ${x.maxConsecutiveFailures??3}`)});let l=e.command("stealth").description("Stealth mode configuration for Chrome automation");return l.command("status").description("Show stealth mode configuration").option("--json","Output in JSON format").action(async c=>{let p=!!e.opts().json||!!c.json,g=P(),x=g.tools?.chromeSession?.stealth??{enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]};if(p){console.log(JSON.stringify(x,null,2));return}if(console.log(v.cyan(`Stealth Mode Configuration
544
+ `)),console.log(` Status: ${x.enabled?v.green("enabled"):v.gray("disabled")}`),g.tools?.chromeSession?.enabled?console.log(` Chrome Session: ${v.green("enabled")}`):console.log(` Chrome Session: ${v.gray("disabled")}`),x.enabled){console.log(` Cursor movement: ${x.cursorMovement!==!1?v.green("yes"):v.gray("no")}`),console.log(` Humanized typing: ${x.humanizedTyping!==!1?v.green("yes"):v.gray("no")}`);let y=x.interStepDelay||[300,1500];console.log(` Inter-step delay: ${y[0]}\u2013${y[1]} ms`)}}),l.command("enable").description("Enable stealth mode").action(async()=>{let c=P();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!0,oe(c),console.log(v.green("Stealth mode enabled. Restart gateway for changes to take effect."))}),l.command("disable").description("Disable stealth mode").action(async()=>{let c=P();c.tools.chromeSession.stealth||(c.tools.chromeSession.stealth={enabled:!1,cursorMovement:!0,humanizedTyping:!0,interStepDelay:[300,1500]}),c.tools.chromeSession.stealth.enabled=!1,oe(c),console.log(v.gray("Stealth mode disabled. Restart gateway for changes to take effect."))}),e}ms(process.argv);var au=fa();au.parseAsync(process.argv);