@agensis/agensis-agent 0.1.25 → 0.1.27

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/README.md CHANGED
@@ -60,6 +60,9 @@ Optional:
60
60
  - `--name <name>` — display name
61
61
  - `--cwd <path>` — folder where the coding CLI runs
62
62
  - `--coding-cmd <command>` — command used for jobs (default `claude -p`)
63
+ - `--full-cli-context` — opt out of the default isolated Claude/Codex launch
64
+ - `--sync-memory` — opt in to mirroring Claude memory files to Agensis
65
+ - `--max-concurrency <n>` — simultaneous coding CLI jobs (default `2`)
63
66
  - `--model <id>` — default model passed to supported coding CLIs
64
67
  - `--permission-mode <mode>` — `default`, `accept_edits`, or `yolo`
65
68
  - `--yolo` / `--no-sandbox` — alias for `--permission-mode yolo`
@@ -73,18 +76,30 @@ Environment fallbacks: `AGENSIS_URL`, `AGENSIS_TOKEN`,
73
76
  `AGENSIS_WORKSPACE` / `AGENSIS_WORKSPACE_ID`, `AGENSIS_AGENT` / `AGENSIS_AGENT_ID`,
74
77
  `AGENSIS_HANDLE`, `AGENSIS_NAME`, `AGENSIS_CWD`, `AGENSIS_CODING_CMD` / `CODING_CMD`,
75
78
  `AGENSIS_MODEL` / `CLAUDE_MODEL`, `AGENSIS_PERMISSION_MODE`, `AGENSIS_TIMEOUT_MS`,
76
- `AGENSIS_HEARTBEAT_MS`, `AGENSIS_ONCE=1`.
79
+ `AGENSIS_HEARTBEAT_MS`, `AGENSIS_SYNC_MEMORY=1`, `AGENSIS_ONCE=1`.
77
80
 
78
81
  ## Security
79
82
 
80
83
  The daemon runs on your machine and executes the configured coding command in
81
- the working directory you start it in. Your local credentials and filesystem
82
- stay local; agensis sends the job payload and receives the result. Treat it like
83
- any local coding agent with access to that folder.
84
+ the working directory you start it in. Agensis sends the job payload and
85
+ receives streamed CLI output and the final result. Local credentials are not
86
+ intentionally uploaded, but the coding CLI can read files allowed by its own
87
+ permission mode, so treat it like any local coding agent with access to that
88
+ folder.
89
+
90
+ Claude memory synchronization is off by default. `--sync-memory` opts in to
91
+ uploading the selected project's memory file names, contents, sizes, and
92
+ absolute memory-root path to the connected Agensis workspace. Reads are
93
+ restricted to that root and each file is capped at 256 KiB.
84
94
 
85
95
  Keep `aga_...` tokens out of shared logs and shell history. Generate a fresh
86
96
  token from agensis if one is exposed.
87
97
 
98
+ By default, Claude runs in safe mode and Codex skips user configuration,
99
+ project instructions, memories, plugins, hooks, and skill search. Both are
100
+ given only the Agensis MCP configuration, and the complete daemon prompt is
101
+ bounded. `--full-cli-context` deliberately restores normal CLI discovery.
102
+
88
103
  ## Requirements
89
104
 
90
105
  - Node.js >= 18
package/bin/agensis.mjs CHANGED
@@ -1,15 +1,23 @@
1
1
  #!/usr/bin/env node
2
- var Vt=Object.defineProperty;var Qt=(e,t)=>()=>(e&&(t=e(e=0)),t);var Zt=(e,t)=>{for(var n in t)Vt(e,n,{get:t[n],enumerable:!0})};var Je={};Zt(Je,{createE2bProvider:()=>rn});function ve(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function rn({apiKey:e,anthropicApiKey:t,gitToken:n="",repoUrl:r="",template:o=""}={}){if(!e)throw new Error("E2B_API_KEY is not set on the daemon host.");if(!r)throw new Error("Sandbox needs a repo URL (set sandbox_config.repoUrl or the agent's repo).");return{async ensureEnv(){let s={apiKey:e,envs:t?{ANTHROPIC_API_KEY:t}:{}},i;try{({Sandbox:i}=await import("e2b"))}catch(d){if(d&&(d.code==="ERR_MODULE_NOT_FOUND"||d.code==="MODULE_NOT_FOUND"||/Cannot find package 'e2b'/.test(String(d&&d.message)))){let u=Number(String(process.versions.node).split(".")[0])||0,m=u<20||u===21?` Sandbox mode needs Node >=20.18.1 (<21 or >=22); you have ${process.versions.node}. Upgrade Node, then run \`npm i e2b\` in the daemon.`:" Run `npm i e2b` in the daemon to enable Sandbox mode.";throw new Error(`Sandbox execution requires the optional 'e2b' package, which is not installed.${m}`)}throw d}let a=o?await i.create(o,s):await i.create(s);return await a.commands.run("bash -lc 'command -v claude >/dev/null || npm i -g @anthropic-ai/claude-code'"),{sbx:a,dir:nn}},async putRepo(s){let i=n?r.replace(/^https:\/\//,`https://x-access-token:${n}@`):r;try{let a=await s.sbx.commands.run(`git clone ${ve(i)} ${ve(s.dir)}`);if(a&&typeof a.exitCode=="number"&&a.exitCode!==0)throw new Error(`git clone failed: ${a.stderr||`exit ${a.exitCode}`}`)}catch(a){if(a&&String(a.message||"").startsWith("git clone failed:"))throw a;let d=a&&(a.stderr||a.exitCode!=null)?a.stderr||`exit ${a.exitCode}`:String(a?.message||a);throw new Error(`git clone failed: ${d}`)}},async exec(s,{cmd:i,args:a=[],onData:d}){let u=`${i} ${a.map(ve).join(" ")}`,m={cwd:s.dir,envs:{IS_SANDBOX:"1",AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS:"1"},onStdout:g=>{try{d?.(g)}catch{}}};try{let g=await s.sbx.commands.run(u,m);return{status:g.exitCode,stdout:g.stdout||"",stderr:g.stderr||"",error:null}}catch(g){return g&&typeof g.exitCode=="number"?{status:g.exitCode,stdout:g.stdout||"",stderr:g.stderr||"",error:null}:{status:null,stdout:"",stderr:String(g?.message||g),error:g}}},async getResult(s){try{return{patch:(await s.sbx.commands.run("git add -A && git diff --cached",{cwd:s.dir})).stdout||""}}catch(i){return{patch:i&&i.stdout||""}}},async destroy(s){await s.sbx.kill()}}}var nn,We=Qt(()=>{nn="/home/user/repo"});import Y from"node:process";import ue from"node:fs";import de from"node:path";import le from"node:os";import Xn from"node:crypto";import w from"node:process";import ce from"ws";import{spawn as en}from"node:child_process";function He(e){let t=Math.max(0,Math.round(e/1e3)),n=Math.floor(t/60),r=t%60;return n>0?`${n}m ${r}s`:`${r}s`}var tn=50*1024*1024;function se(e){let{cmd:t,args:n=[],cwd:r,timeoutMs:o=0,label:s="working",heartbeatMs:i=15e3,input:a="",now:d=Date.now,log:u=console,signal:m,onData:g}=e||{};return new Promise(_=>{if(m?.aborted){_({status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")});return}let h;try{let c=n.some(P=>P==="--dangerously-skip-permissions"),y=typeof process.getuid=="function"&&process.getuid()===0,v={...process.env};delete v.ANTHROPIC_API_KEY,delete v.ANTHROPIC_AUTH_TOKEN,c&&y&&(v.IS_SANDBOX="1"),h=en(t,n,{cwd:r,detached:!0,env:v})}catch(c){_({status:null,stdout:"",stderr:"",error:c});return}a?h.stdin?.end(String(a)):h.stdin?.end();let x="",$="";h.stdout?.setEncoding("utf8"),h.stderr?.setEncoding("utf8");let b=(c,y)=>c.length>=tn?c:c+y;h.stdout?.on("data",c=>{if(x=b(x,c),g)try{g(c)}catch{}}),h.stderr?.on("data",c=>$=b($,c));let S=d(),M=i>0?setInterval(()=>{u.log(` \u2026 still ${s} (${He(d()-S)}) \u2014 Ctrl+C to cancel`)},i):null;M?.unref&&M.unref();let N=c=>{if(h.pid!=null)try{process.kill(-h.pid,c)}catch{try{h.kill(c)}catch{}}},O=!1,j=o>0?setTimeout(()=>{O=!0,N("SIGKILL")},o):null;j?.unref&&j.unref();let U=!1,l=null,p=()=>{U=!0,N("SIGTERM"),l=setTimeout(()=>N("SIGKILL"),3e3),l?.unref&&l.unref()};m&&m.addEventListener("abort",p,{once:!0});let k=(c,y)=>{M&&clearInterval(M),j&&clearTimeout(j),l&&clearTimeout(l),m&&m.removeEventListener("abort",p),_({status:c,stdout:x,stderr:$,aborted:U,error:y||(U?new Error("cancelled"):O?new Error(`timed out after ${He(o)}`):null)})};h.on("error",c=>k(null,c)),h.on("close",c=>k(c,null))})}function on({run:e=se}={}){return{run:t=>e(t)}}function sn(e){return{async run({cmd:t,args:n=[],onData:r,signal:o,job:s}){let i=null;try{i=await e.ensureEnv({job:s,signal:o}),await e.putRepo(i,{job:s,signal:o});let a=await e.exec(i,{cmd:t,args:n,onData:r,signal:o}),d=await e.getResult(i,{job:s}).catch(()=>({})),u=d&&d.patch?String(d.patch).trim():"",m=u?`${a.stdout||""}
2
+ var fn=Object.defineProperty;var pn=(e,t)=>()=>(e&&(t=e(e=0)),t);var hn=(e,t)=>{for(var n in t)fn(e,n,{get:t[n],enumerable:!0})};var et={};hn(et,{createE2bProvider:()=>In});function Ce(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function In({apiKey:e,anthropicApiKey:t,gitToken:n="",repoUrl:r="",template:o=""}={}){if(!e)throw new Error("E2B_API_KEY is not set on the daemon host.");if(!r)throw new Error("Sandbox needs a repo URL (set sandbox_config.repoUrl or the agent's repo).");return{async ensureEnv(){let s={apiKey:e,envs:t?{ANTHROPIC_API_KEY:t}:{}},i;try{({Sandbox:i}=await import("e2b"))}catch(u){if(u&&(u.code==="ERR_MODULE_NOT_FOUND"||u.code==="MODULE_NOT_FOUND"||/Cannot find package 'e2b'/.test(String(u&&u.message)))){let a=Number(String(process.versions.node).split(".")[0])||0,l=a<20||a===21?` Sandbox mode needs Node >=20.18.1 (<21 or >=22); you have ${process.versions.node}. Upgrade Node, then run \`npm i e2b\` in the daemon.`:" Run `npm i e2b` in the daemon to enable Sandbox mode.";throw new Error(`Sandbox execution requires the optional 'e2b' package, which is not installed.${l}`)}throw u}let c=o?await i.create(o,s):await i.create(s);return await c.commands.run("bash -lc 'command -v claude >/dev/null || npm i -g @anthropic-ai/claude-code'"),{sbx:c,dir:Cn}},async putRepo(s){let i=n?r.replace(/^https:\/\//,`https://x-access-token:${n}@`):r;try{let c=await s.sbx.commands.run(`git clone ${Ce(i)} ${Ce(s.dir)}`);if(c&&typeof c.exitCode=="number"&&c.exitCode!==0)throw new Error(`git clone failed: ${c.stderr||`exit ${c.exitCode}`}`)}catch(c){if(c&&String(c.message||"").startsWith("git clone failed:"))throw c;let u=c&&(c.stderr||c.exitCode!=null)?c.stderr||`exit ${c.exitCode}`:String(c?.message||c);throw new Error(`git clone failed: ${u}`)}},async exec(s,{cmd:i,args:c=[],env:u={},onData:a}){let l=`${i} ${c.map(Ce).join(" ")}`,m={cwd:s.dir,envs:{...u,IS_SANDBOX:"1",AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS:"1"},onStdout:_=>{try{a?.(_)}catch{}}};try{let _=await s.sbx.commands.run(l,m);return{status:_.exitCode,stdout:_.stdout||"",stderr:_.stderr||"",error:null}}catch(_){return _&&typeof _.exitCode=="number"?{status:_.exitCode,stdout:_.stdout||"",stderr:_.stderr||"",error:null}:{status:null,stdout:"",stderr:String(_?.message||_),error:_}}},async getResult(s){try{return{patch:(await s.sbx.commands.run("git add -A && git diff --cached",{cwd:s.dir})).stdout||""}}catch(i){return{patch:i&&i.stdout||""}}},async destroy(s){await s.sbx.kill()}}}var Cn,tt=pn(()=>{Cn="/home/user/repo"});import Y from"node:process";import le from"node:fs";import de from"node:path";import me from"node:os";import _r from"node:crypto";import k from"node:process";import ue from"ws";import{spawn as gn}from"node:child_process";function qe(e){let t=Math.max(0,Math.round(e/1e3)),n=Math.floor(t/60),r=t%60;return n>0?`${n}m ${r}s`:`${r}s`}var yn=50*1024*1024;function ie(e){let{cmd:t,args:n=[],env:r={},cwd:o,timeoutMs:s=0,label:i="working",heartbeatMs:c=15e3,input:u="",now:a=Date.now,log:l=console,signal:m,onData:_}=e||{};return new Promise(b=>{if(m?.aborted){b({status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")});return}let h;try{let f=n.some(C=>C==="--dangerously-skip-permissions"),v=typeof process.getuid=="function"&&process.getuid()===0,D={...process.env,...r};delete D.AGENSIS_TOKEN,delete D.ANTHROPIC_API_KEY,delete D.ANTHROPIC_AUTH_TOKEN,f&&v&&(D.IS_SANDBOX="1"),h=gn(t,n,{cwd:o,detached:!0,env:D})}catch(f){b({status:null,stdout:"",stderr:"",error:f});return}u?h.stdin?.end(String(u)):h.stdin?.end();let M="",w="";h.stdout?.setEncoding("utf8"),h.stderr?.setEncoding("utf8");let S=(f,v)=>f.length>=yn?f:f+v;h.stdout?.on("data",f=>{if(M=S(M,f),_)try{_(f)}catch{}}),h.stderr?.on("data",f=>w=S(w,f));let E=a(),I=c>0?setInterval(()=>{l.log(` \u2026 still ${i} (${qe(a()-E)}) \u2014 Ctrl+C to cancel`)},c):null;I?.unref&&I.unref();let x=f=>{if(h.pid!=null)try{process.kill(-h.pid,f)}catch{try{h.kill(f)}catch{}}},$=!1,P=s>0?setTimeout(()=>{$=!0,x("SIGKILL")},s):null;P?.unref&&P.unref();let p=!1,g=null,A=()=>{p=!0,x("SIGTERM"),g=setTimeout(()=>x("SIGKILL"),3e3),g?.unref&&g.unref()};m&&m.addEventListener("abort",A,{once:!0});let d=(f,v)=>{I&&clearInterval(I),P&&clearTimeout(P),g&&clearTimeout(g),m&&m.removeEventListener("abort",A),b({status:f,stdout:M,stderr:w,aborted:p,error:v||(p?new Error("cancelled"):$?new Error(`timed out after ${qe(s)}`):null)})};h.on("error",f=>d(null,f)),h.on("close",f=>d(f,null))})}import{spawn as Sn}from"node:child_process";var ze=10*60*1e3;function Ye(e={}){let t={...process.env,...e};return delete t.AGENSIS_TOKEN,delete t.ANTHROPIC_API_KEY,delete t.ANTHROPIC_AUTH_TOKEN,t}var ke=class{#e=[];#t=[];#n=!1;push(t){if(this.#n)return;let n=this.#t.shift();n?n({value:t,done:!1}):this.#e.push(t)}close(){this.#n=!0;for(let t of this.#t.splice(0))t({value:void 0,done:!0})}[Symbol.asyncIterator](){return{next:()=>this.#e.length?Promise.resolve({value:this.#e.shift(),done:!1}):this.#n?Promise.resolve({value:void 0,done:!0}):new Promise(t=>this.#t.push(t))}}};function Xe(){let e=new Map;return(t,n)=>{let r=(e.get(t)||Promise.resolve()).then(n,n);return e.set(t,r.catch(()=>{})),r}}function wn(e){return e==="yolo"?{permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0}:e==="accept_edits"?{permissionMode:"acceptEdits"}:{permissionMode:"default"}}function bn(e){if(!e||e.type!=="content_block_delta")return"";let t=e.delta;return t&&t.type==="text_delta"&&typeof t.text=="string"?t.text:""}function _n(e){return`${JSON.stringify({type:"stream_event",event:{type:"content_block_delta",delta:{type:"text_delta",text:e}}})}
3
+ `}function vn(e){return`${JSON.stringify({type:"result",result:e})}
4
+ `}function Ve(e){return JSON.stringify({cwd:e.cwd||"",model:e.model||"",permissionMode:e.permissionMode||"default",hostFolders:[...e.hostFolders||[]].sort(),leanCli:!!e.leanCli,mcpUrl:e.mcp?.url||"",mcpToken:e.mcp?.env?.AGENSIS_MCP_TOKEN||""})}function Qe({queryFn:e,idleCloseMs:t=ze}={}){let n=new Map,r=Xe(),o=(u,a,l)=>{let m=n.get(u);if(!(!m||a&&m!==a))if(n.delete(u),clearTimeout(m.idleTimer),m.closed=!0,m.queue.close(),l&&m.activeTurn&&m.activeTurn.finish(l),typeof m.query.close=="function")try{m.query.close()}catch{}else Promise.resolve(m.query.return?.()).catch(()=>{})},s=u=>{let a=n.get(u);a&&(clearTimeout(a.idleTimer),a.idleTimer=setTimeout(()=>o(u),t),a.idleTimer.unref?.())},i=async(u,a)=>{let l=n.get(u),m=Ve(a);if(l&&l.fingerprint===m&&!l.closed)return l;l&&o(u,l),e||(e=(await import("@anthropic-ai/claude-agent-sdk")).query);let _=new ke,b=wn(a.permissionMode),h=a.leanCli&&a.mcp?{agensis:{type:"http",url:a.mcp.url,headers:{Authorization:"Bearer ${AGENSIS_MCP_TOKEN}"}}}:void 0,M=e({prompt:_,options:{cwd:a.cwd,model:a.model,...b,additionalDirectories:a.hostFolders&&a.hostFolders.length?a.hostFolders:void 0,mcpServers:h,strictMcpConfig:a.leanCli?!0:void 0,settingSources:a.leanCli?[]:void 0,persistSession:a.leanCli?!1:void 0,includePartialMessages:!0,env:Ye(a.mcp?.env)}});return l={query:M,queue:_,sessionId:"",idleTimer:null,activeTurn:null,closed:!1,terminalError:null,fingerprint:m},n.set(u,l),l.pump=(async()=>{let w=null;try{for await(let S of M){S.session_id&&(l.sessionId=S.session_id);let E=l.activeTurn;if(E){if(S.type==="stream_event"){let I=bn(S.event);I&&(E.streamed+=I,E.onData?.(_n(I)))}else if(S.type==="result")if(S.subtype==="success"){let I=S.result==null?E.streamed:String(S.result);E.onData?.(vn(I)),E.finish({status:0,stdout:I,stderr:"",error:null})}else{let I=Array.isArray(S.errors)?S.errors.filter(Boolean).join(`
5
+ `):S.result,x=new Error(I||`claude-agent-sdk result error: ${S.subtype}`);E.finish({status:1,stdout:E.streamed,stderr:x.message,error:x})}}}w=new Error("claude-agent-sdk connection closed")}catch(S){w=S}finally{l.closed=!0,l.terminalError=w,clearTimeout(l.idleTimer),l.queue.close(),n.get(u)===l&&n.delete(u),l.activeTurn&&l.activeTurn.finish({status:null,stdout:l.activeTurn.streamed,stderr:String(w?.message||w||""),error:w})}})(),l};return{run:u=>r(u.sessionKey||"default",async()=>{let{sessionKey:a="default",prompt:l,signal:m,onData:_,timeoutMs:b=0}=u;if(m?.aborted)return{status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")};let h;try{h=await i(a,u)}catch(w){return{status:null,stdout:"",stderr:"",error:w}}if(h.closed){let w=h.terminalError||new Error("claude-agent-sdk connection closed");return{status:null,stdout:"",stderr:String(w.message||w),error:w}}clearTimeout(h.idleTimer);let M=await new Promise(w=>{let S=!1,E=null,I={streamed:"",onData:_,finish($){S||(S=!0,h.activeTurn===I&&(h.activeTurn=null),m&&m.removeEventListener("abort",x),E&&clearTimeout(E),w($))}},x=()=>{let $={status:null,stdout:I.streamed,stderr:"",aborted:!0,error:new Error("cancelled")};Promise.resolve(h.query.interrupt?.()).catch(()=>{}),o(a,h,$)};h.activeTurn=I,m&&m.addEventListener("abort",x,{once:!0}),b>0&&(E=setTimeout(()=>{let $=new Error(`timed out after ${b}ms`);Promise.resolve(h.query.interrupt?.()).catch(()=>{}),o(a,h,{status:null,stdout:I.streamed,stderr:$.message,error:$})},b),E.unref?.()),h.queue.push({type:"user",message:{role:"user",content:l},parent_tool_use_id:null,session_id:h.sessionId})});return n.get(a)===h&&s(a),M}),shutdown:()=>{for(let u of[...n.keys()])o(u)}}}function En(e){let t=1,n="",r=new Map,o=new Set;e.stdout.setEncoding("utf8"),e.stdout.on("data",i=>{n+=i;let c;for(;(c=n.indexOf(`
6
+ `))>=0;){let u=n.slice(0,c);if(n=n.slice(c+1),!u.trim())continue;let a;try{a=JSON.parse(u)}catch{continue}if(a.id!==void 0&&r.has(a.id)){let{resolve:l,reject:m}=r.get(a.id);r.delete(a.id),a.error?m(new Error(a.error.message||"codex app-server error")):l(a.result)}else if(a.method)for(let l of o)l(a.method,a.params,a.id)}});let s=i=>{for(let{reject:c}of r.values())c(i);r.clear()};return e.on("exit",()=>s(new Error("codex app-server exited"))),e.on("error",i=>s(i)),{request(i,c){let u=t++;return new Promise((a,l)=>{r.set(u,{resolve:a,reject:l}),e.stdin.write(`${JSON.stringify({id:u,method:i,params:c})}
7
+ `)})},notify(i,c){e.stdin.write(`${JSON.stringify({method:i,params:c})}
8
+ `)},respond(i,c){e.stdin.write(`${JSON.stringify({id:i,result:c})}
9
+ `)},respondError(i,c){e.stdin.write(`${JSON.stringify({id:i,error:{code:-32601,message:c}})}
10
+ `)},onMessage(i){return o.add(i),()=>o.delete(i)}}}function kn(e){return e==="yolo"?{approvalPolicy:"never",sandbox:"danger-full-access"}:{}}function Ze({spawnFn:e=Sn,idleCloseMs:t=ze}={}){let n=new Map,r=Xe(),o=u=>{let a=n.get(u);if(a){n.delete(u),clearTimeout(a.idleTimer);try{a.child.kill("SIGTERM")}catch{}}},s=u=>{let a=n.get(u);a&&(clearTimeout(a.idleTimer),a.idleTimer=setTimeout(()=>o(u),t),a.idleTimer.unref?.())},i=async(u,a)=>{let l=n.get(u),m=Ve(a);if(l&&l.fingerprint===m)return l;l&&o(u);let _=e("codex",["app-server"],{cwd:a.cwd,env:Ye(a.mcp?.env),stdio:["pipe","pipe","pipe"]}),b=En(_);await b.request("initialize",{clientInfo:{name:"agensis-agent",version:a.clientVersion||"unknown"}}),b.notify("initialized");let h=a.leanCli&&a.mcp?{mcp_servers:{agensis:{url:a.mcp.url,bearer_token_env_var:"AGENSIS_MCP_TOKEN"}}}:void 0,M=await b.request("thread/start",{cwd:a.cwd,ephemeral:a.leanCli||void 0,model:a.model,config:h,...kn(a.permissionMode)}),w={child:_,rpc:b,threadId:M.thread.id,fingerprint:m,idleTimer:null};return n.set(u,w),w};return{run:u=>r(u.sessionKey||"default",async()=>{let{sessionKey:a="default",prompt:l,signal:m,onData:_,timeoutMs:b=0}=u;if(m?.aborted)return{status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")};let h;try{h=await i(a,u)}catch(x){return{status:null,stdout:"",stderr:"",error:x}}let M="",w="",S=null,E=!1,I=await new Promise(x=>{let $=!1,P=f=>{$||($=!0,d(),x(f))},p=h.rpc.onMessage((f,v,D)=>{if(D!==void 0){if(f==="item/commandExecution/requestApproval"){let C=u.permissionMode==="yolo"?"acceptForSession":"decline";h.rpc.respond(D,{decision:C})}else if(f==="item/fileChange/requestApproval"){let C=u.permissionMode==="yolo"||u.permissionMode==="accept_edits"?"acceptForSession":"decline";h.rpc.respond(D,{decision:C})}else h.rpc.respondError(D,`Agensis daemon cannot handle Codex request ${f}`);return}if(!(!v||v.threadId!==h.threadId)){if(f==="turn/started"){S=v.turn?.id??S;return}if(!(S&&v.turnId&&v.turnId!==S)){if(f==="item/agentMessage/delta")M+=v.delta||"",_?.(v.delta||"");else if(f==="item/completed"&&v.item?.type==="agentMessage")w=v.item.text||w;else if(f==="turn/completed"){let C=v.turn?.status==="failed"||v.turn?.error;P({status:C?1:0,stdout:w||M,stderr:C?String(v.turn?.error?.message||v.turn?.error||""):"",error:C?new Error(String(v.turn?.error?.message||v.turn?.error||"codex turn failed")):null})}}}}),g=()=>{E=!0,h.rpc.request("turn/interrupt",{threadId:h.threadId}).catch(()=>{});let f={status:null,stdout:M,stderr:"",aborted:!0,error:new Error("cancelled")};P(f),o(a)};m&&m.addEventListener("abort",g,{once:!0});let A=b>0?setTimeout(()=>{let f=new Error(`timed out after ${b}ms`);h.rpc.request("turn/interrupt",{threadId:h.threadId}).catch(()=>{}),P({status:null,stdout:M,stderr:f.message,error:f}),o(a)},b):null;A?.unref?.();function d(){p(),m&&m.removeEventListener("abort",g),A&&clearTimeout(A)}h.rpc.request("turn/start",{threadId:h.threadId,input:[{type:"text",text:l}]}).then(f=>{S=f?.turn?.id||S}).catch(f=>P({status:null,stdout:"",stderr:"",error:f}))});return E||s(a),I}),shutdown:()=>{for(let u of[...n.keys()])o(u)}}}function rt({run:e=ie}={}){return{run:t=>e(t)}}var An=null,xn=null,nt=new Set;function Mn(e){let t=String(e&&e.message||e||"");return/Cannot find module|ERR_MODULE_NOT_FOUND|ENOENT|command not found/i.test(t)}function Nn(e,{local:t,pooled:n,log:r=console}={}){let o=t||rt(),s=n||(e==="claude"?An||=Qe():e==="codex"?xn||=Ze():null);return s?{async run(i){if(nt.has(e))return o.run(i);let c=await s.run(i);return c.error&&Mn(c.error)?(nt.add(e),r.log?.(`[executor] ${e} fast connection unavailable (${c.error.message}); falling back to subprocess mode for this and future jobs.`),o.run(i)):c}}:o}function On(e){return{async run({cmd:t,args:n=[],env:r={},onData:o,signal:s,job:i}){let c=null;try{c=await e.ensureEnv({job:i,signal:s}),await e.putRepo(c,{job:i,signal:s});let u=await e.exec(c,{cmd:t,args:n,env:r,onData:o,signal:s}),a=await e.getResult(c,{job:i}).catch(()=>({})),l=a&&a.patch?String(a.patch).trim():"",m=l?`${u.stdout||""}
3
11
 
4
12
  \`\`\`diff
5
- ${u}
6
- \`\`\``:a.stdout||"";return{status:a.status,stdout:m,stderr:a.stderr||"",error:a.error||null}}catch(a){return{status:null,stdout:"",stderr:"",error:a}}finally{if(i)try{await e.destroy(i)}catch{}}}}}function Ke(e,{makeProvider:t}={}){return(e&&e.agent&&e.agent.run_mode)==="sandbox"?sn((t||an)(e)):on()}function an(e){let t=e.agent&&e.agent.sandbox_provider||"e2b",n=e.agent&&e.agent.sandbox_config||{};if(t!=="e2b")throw new Error(`Sandbox provider "${t}" is not available yet (only e2b is wired).`);return un({apiKey:process.env.E2B_API_KEY,anthropicApiKey:process.env.ANTHROPIC_API_KEY,gitToken:process.env.GIT_TOKEN||"",repoUrl:e.repoUrl||e.agent&&e.agent.repo_url||n.repoUrl||"",template:n.template||""})}function cn(e=process.versions.node){let[t,n,r]=String(e).split(".").map(o=>Number(o)||0);return t===21?!1:t>=22?!0:t!==20?!1:n>18?!0:n<18?!1:r>=1}function un(e){let t=null,n=async()=>{if(!t){if(!cn())throw new Error(`Sandbox execution requires Node >=20.18.1 (you have ${process.versions.node}). Upgrade Node to use Sandbox agents; Built-in and Remote daemon modes still work on Node 18.`);t=(await Promise.resolve().then(()=>(We(),Je))).createE2bProvider(e)}return t};return{ensureEnv:async r=>(await n()).ensureEnv(r),putRepo:async(r,o)=>(await n()).putRepo(r,o),exec:async(r,o)=>(await n()).exec(r,o),getResult:async(r,o)=>(await n()).getResult(r,o),destroy:async r=>(await n()).destroy(r)}}function ze(e={}){let{runJob:t}=e,n=Math.max(1,Number(e.concurrency)||1),r=new Map,o=0,s=[];function i(b){let S=r.get(b);return S||(S={queued:[],active:null},r.set(b,S)),S}function a(b){if(b==null)return!1;for(let S of r.values())if(S.active&&!S.active.cancelled&&S.active.job.key===b||S.queued.some(M=>M.key===b))return!0;return!1}function d(){for(let[b,S]of r){if(o>=n)break;if(S.active||S.queued.length===0)continue;let M=S.queued.shift(),N=new AbortController;S.active={job:M,controller:N,cancelled:!1},o+=1,Promise.resolve().then(()=>N.signal.aborted?void 0:t(M,{signal:N.signal})).catch(()=>{}).finally(()=>{S.active=null,o-=1,S.queued.length===0&&!S.active&&r.delete(b),d(),u()})}}function u(){if(o>0)return;for(let S of r.values())if(S.queued.length)return;let b=s;s=[];for(let S of b)S()}function m(b){if(b&&b.key!=null&&a(b.key))return{accepted:!1,deduped:!0,position:0,startedImmediately:!1};let S=b&&b.lane!=null?String(b.lane):"",M=i(S),N=!M.active&&M.queued.length===0&&o<n;M.queued.push(b);let O=M.queued.length+(M.active?1:0);return d(),{accepted:!0,deduped:!1,position:O,startedImmediately:N}}function g(b,S){let M=!1;for(let[N,O]of r)S!=null&&N!==String(S)||O.active&&(O.active.cancelled=!0,O.active.controller.abort(b||"cancelled"),M=!0);return M}function _(b,S){if(b==null)return!1;let M=!1;for(let[N,O]of[...r]){O.active?.job?.key===b&&(O.active.cancelled=!0,O.active.controller.abort(S||"cancelled"),M=!0);let j=O.queued.length;O.queued=O.queued.filter(U=>U.key!==b),O.queued.length!==j&&(M=!0),!O.active&&O.queued.length===0&&r.delete(N)}return u(),M}function h(){let b=0;for(let S of r.values())b+=S.queued.length;return b}function x(){return o}function $(){return o===0&&h()===0?Promise.resolve():new Promise(b=>s.push(b))}return{enqueue:m,cancel:_,cancelActive:g,has:a,size:h,active:x,idle:$}}import Ze from"node:crypto";import dn from"node:http";import et from"node:os";import X from"node:process";var qe=8787,Ee="claude-haiku-4-5",ln=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/,mn=100,fn=new Set(["say","wave","hush","open","choose"]),ge="x-agensis-bridge-secret";function pn(){return`cbs_${Ze.randomBytes(24).toString("base64url")}`}function hn(e){let t=e?.headers||{},n=String(t[ge]||t[ge.toLowerCase()]||"").trim();if(n)return n;let o=String(t.authorization||t.Authorization||"").trim().match(/^Bearer\s+(.+)$/i);return o?o[1].trim():""}function gn(e,t){let n=String(t||""),r=hn(e);if(!n||!r)return!1;let o=Buffer.from(r),s=Buffer.from(n);return o.length!==s.length?!1:Ze.timingSafeEqual(o,s)}function yn(e={},t={}){let n=String(t.authSecret||"").trim();if(n)return n;let r=String(e.cursorBuddyBridgeSecret||"").trim();if(r)return r;let o=String(X.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim();return o||pn()}function Sn(e,t){return e==="OPTIONS"||e==="GET"&&t==="/cursorbuddy/health"}function F(e,t,n){e.writeHead(t,{"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization, x-agensis-bridge-secret"}),e.end(JSON.stringify(n))}function Ye(e){e.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-store, no-transform",connection:"keep-alive","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization, x-agensis-bridge-secret","x-accel-buffering":"no"})}function H(e,t){e.write(`data: ${typeof t=="string"?t:JSON.stringify(t)}
13
+ ${l}
14
+ \`\`\``:u.stdout||"";return{status:u.status,stdout:m,stderr:u.stderr||"",error:u.error||null}}catch(u){return{status:null,stdout:"",stderr:"",error:u}}finally{if(c)try{await e.destroy(c)}catch{}}}}}function ot(e,{makeProvider:t,family:n}={}){return(e&&e.agent&&e.agent.run_mode)==="sandbox"?On((t||Tn)(e)):n==="claude"||n==="codex"?Nn(n):rt()}function Tn(e){let t=e.agent&&e.agent.sandbox_provider||"e2b",n=e.agent&&e.agent.sandbox_config||{};if(t!=="e2b")throw new Error(`Sandbox provider "${t}" is not available yet (only e2b is wired).`);return $n({apiKey:process.env.E2B_API_KEY,anthropicApiKey:process.env.ANTHROPIC_API_KEY,gitToken:process.env.GIT_TOKEN||"",repoUrl:e.repoUrl||e.agent&&e.agent.repo_url||n.repoUrl||"",template:n.template||""})}function Bn(e=process.versions.node){let[t,n,r]=String(e).split(".").map(o=>Number(o)||0);return t===21?!1:t>=22?!0:t!==20?!1:n>18?!0:n<18?!1:r>=1}function $n(e){let t=null,n=async()=>{if(!t){if(!Bn())throw new Error(`Sandbox execution requires Node >=20.18.1 (you have ${process.versions.node}). Upgrade Node to use Sandbox agents; Built-in and Remote daemon modes still work on Node 18.`);t=(await Promise.resolve().then(()=>(tt(),et))).createE2bProvider(e)}return t};return{ensureEnv:async r=>(await n()).ensureEnv(r),putRepo:async(r,o)=>(await n()).putRepo(r,o),exec:async(r,o)=>(await n()).exec(r,o),getResult:async(r,o)=>(await n()).getResult(r,o),destroy:async r=>(await n()).destroy(r)}}function st(e={}){let{runJob:t}=e,n=Math.max(1,Number(e.concurrency)||1),r=new Map,o=0,s=[];function i(w){let S=r.get(w);return S||(S={queued:[],active:null},r.set(w,S)),S}function c(w){if(w==null)return!1;for(let S of r.values())if(S.active&&!S.active.cancelled&&S.active.job.key===w||S.queued.some(E=>E.key===w))return!0;return!1}function u(){for(let[w,S]of r){if(o>=n)break;if(S.active||S.queued.length===0)continue;let E=S.queued.shift(),I=new AbortController;S.active={job:E,controller:I,cancelled:!1},o+=1,Promise.resolve().then(()=>I.signal.aborted?void 0:t(E,{signal:I.signal})).catch(()=>{}).finally(()=>{S.active=null,o-=1,S.queued.length===0&&!S.active&&r.delete(w),u(),a()})}}function a(){if(o>0)return;for(let S of r.values())if(S.queued.length)return;let w=s;s=[];for(let S of w)S()}function l(w){if(w&&w.key!=null&&c(w.key))return{accepted:!1,deduped:!0,position:0,startedImmediately:!1};let S=w&&w.lane!=null?String(w.lane):"",E=i(S),I=!E.active&&E.queued.length===0&&o<n;E.queued.push(w);let x=E.queued.length+(E.active?1:0);return u(),{accepted:!0,deduped:!1,position:x,startedImmediately:I}}function m(w,S){let E=!1;for(let[I,x]of r)S!=null&&I!==String(S)||x.active&&(x.active.cancelled=!0,x.active.controller.abort(w||"cancelled"),E=!0);return E}function _(w,S){if(w==null)return!1;let E=!1;for(let[I,x]of[...r]){x.active?.job?.key===w&&(x.active.cancelled=!0,x.active.controller.abort(S||"cancelled"),E=!0);let $=x.queued.length;x.queued=x.queued.filter(P=>P.key!==w),x.queued.length!==$&&(E=!0),!x.active&&x.queued.length===0&&r.delete(I)}return a(),E}function b(){let w=0;for(let S of r.values())w+=S.queued.length;return w}function h(){return o}function M(){return o===0&&b()===0?Promise.resolve():new Promise(w=>s.push(w))}return{enqueue:l,cancel:_,cancelActive:m,has:c,size:b,active:h,idle:M}}import dt from"node:crypto";import Dn from"node:http";import mt from"node:os";import X from"node:process";var it=8787,Ie="claude-haiku-4-5",Pn=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/,Rn=100,Ln=new Set(["say","wave","hush","open","choose"]),ye="x-agensis-bridge-secret";function Un(){return`cbs_${dt.randomBytes(24).toString("base64url")}`}function Fn(e){let t=e?.headers||{},n=String(t[ye]||t[ye.toLowerCase()]||"").trim();if(n)return n;let o=String(t.authorization||t.Authorization||"").trim().match(/^Bearer\s+(.+)$/i);return o?o[1].trim():""}function jn(e,t){let n=String(t||""),r=Fn(e);if(!n||!r)return!1;let o=Buffer.from(r),s=Buffer.from(n);return o.length!==s.length?!1:dt.timingSafeEqual(o,s)}function Gn(e={},t={}){let n=String(t.authSecret||"").trim();if(n)return n;let r=String(e.cursorBuddyBridgeSecret||"").trim();if(r)return r;let o=String(X.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim();return o||Un()}function Hn(e,t){return e==="OPTIONS"||e==="GET"&&t==="/cursorbuddy/health"}function j(e,t,n){e.writeHead(t,{"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization, x-agensis-bridge-secret"}),e.end(JSON.stringify(n))}function at(e){e.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-store, no-transform",connection:"keep-alive","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization, x-agensis-bridge-secret","x-accel-buffering":"no"})}function H(e,t){e.write(`data: ${typeof t=="string"?t:JSON.stringify(t)}
7
15
 
8
- `)}function ie(e){return new Promise((t,n)=>{let r="";e.on("data",o=>{r+=o,r.length>256*1024&&(n(new Error("request body is too large")),e.destroy())}),e.on("error",n),e.on("end",()=>t(r))})}function wn(e){let t=[],n="",r="",o=!1;for(let s of String(e||"")){if(o){n+=s,o=!1;continue}if(s==="\\"){o=!0;continue}if(r){s===r?r="":n+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){n&&(t.push(n),n="");continue}n+=s}if(n&&t.push(n),!t.length)throw new Error("coding command is empty");return{cmd:t[0],args:t.slice(1)}}function bn(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function pe(e,t){return e.some(n=>n===t||String(n).startsWith(`${t}=`))}function Xe(e,t){let n=[];t&&n.push("CursorBuddy local runtime context:",JSON.stringify(t,null,2),"");for(let r of Array.isArray(e)?e:[]){let o=String(r?.role||"user"),s=String(r?.content||"");s.trim()&&n.push(`${o.toUpperCase()}:
16
+ `)}function ae(e){return new Promise((t,n)=>{let r="";e.on("data",o=>{r+=o,r.length>256*1024&&(n(new Error("request body is too large")),e.destroy())}),e.on("error",n),e.on("end",()=>t(r))})}function Jn(e){let t=[],n="",r="",o=!1;for(let s of String(e||"")){if(o){n+=s,o=!1;continue}if(s==="\\"){o=!0;continue}if(r){s===r?r="":n+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){n&&(t.push(n),n="");continue}n+=s}if(n&&t.push(n),!t.length)throw new Error("coding command is empty");return{cmd:t[0],args:t.slice(1)}}function Kn(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function he(e,t){return e.some(n=>n===t||String(n).startsWith(`${t}=`))}function ct(e,t){let n=[];t&&n.push("CursorBuddy local runtime context:",JSON.stringify(t,null,2),"");for(let r of Array.isArray(e)?e:[]){let o=String(r?.role||"user"),s=String(r?.content||"");s.trim()&&n.push(`${o.toUpperCase()}:
9
17
  ${s}`)}return n.join(`
10
18
 
11
- `).trim()||"Say that the local Agensis runtime is connected."}function Ve(e){let t=String(e||"").trim();if(!t)return"";try{let n=JSON.parse(t);if(typeof n?.result=="string")return n.result;if(typeof n?.message=="string")return n.message;if(typeof n?.content=="string")return n.content}catch{}return t}function _n(e){let t=Array.isArray(e?.messages)?e.messages:[];for(let n=t.length-1;n>=0;n-=1){let r=t[n];if(String(r?.role||"user")!=="user")continue;let o=String(r?.content||"").trim();if(o)return o}return""}function kn(e,t=280){let n=_n(e).replace(/\s+/g," ").trim();if(!n)return"";if(n.length<=t)return n;let r=[/\b(tell me (?:a )?joke)\b/i,/\b(make (?:him|the buddy|cursorbuddy|avatar) wave|wave(?: hello)?|say hi|say hello)\b/i,/\b(what site|which site|what page|where am i|where are you|current url)\b/i,/\b(are you connected|connected|working|online|there)\b/i,/\b(show|guide|tour|walk|around|sections?|features?|important|highlight|what can i do|what should i do|help me)\b/i,/\b(open|show|bring up|get back|display)\b.{0,80}\b(prompt|bubble|dialog|panel|options|menu)\b/i,/\b(hide|hush|close|dismiss|clear|stop|cancel|be quiet)\b.{0,80}\b(bubble|prompt|dialog|panel|options|menu)?\b/i,/^(hi|hello|hey|yo|sup)\b/i];for(let o of r){let s=n.match(o);if(s?.[0])return s[0].trim()}return n.slice(-t).trim()}function vn(e){let t=kn(e);if(!t)return null;if(/\b(?:him|the buddy|cursorbuddy|cursor buddy|avatar|buddy|pet|character)\b/i.test(t)&&/\bwave(?: hello)?\b/i.test(t))return{content:"Waving now.",command:{action:"wave",text:"Hi. How can I help?",source:"chat"}};let r=t.match(/^(?:say|speak)\s+(.{1,180})$/i)||t.match(/\b(?:make|tell)\s+(?:him|the buddy|cursorbuddy|avatar)\s+(?:say|speak)\s+(.{1,180})$/i);return r?.[1]?{content:"Saying it now.",command:{action:"say",text:r[1].trim(),source:"chat"}}:/^(stop|cancel|dismiss|close|hide|hush|be quiet)\b/i.test(t)?{content:"Closed.",command:{action:"hush",source:"chat"}}:/\b(open|show)\b.*\b(options|chat|bubble|prompt)\b/i.test(t)?{content:"Opening options.",command:{action:"open",text:"What should I help with?",source:"chat"}}:null}function En(e){let t=String(e||"").trim();return t?/\s/.test(t)||t.startsWith("-")?!0:/^(claude|codex|node|npm|bun|python|python3|sh|bash|zsh)(?:$|\.)/.test(t):!1}function tt(e,t){let n=String(e||"").trim();return!n||En(n)?t:n}function nt(e){let t=String(e||"").trim();return!t||t==="haiku-4.5"||t==="claude-haiku-4.5"?Ee:t}function Ie(e={}){return nt(e.cursorBuddyModel||X.env.AGENSIS_CURSORBUDDY_MODEL||Ee)}function Qe(e,t,n,r={}){let{cmd:o,args:s}=wn(e.codingCmd||"claude -p"),i=[...s],a=nt(tt(n,Ie(e))),d="",u=!1;return bn(o)?(a&&!pe(i,"--model")&&i.push("--model",a),r.stream===!0&&!pe(i,"--output-format")?(i.push("--output-format","stream-json","--include-partial-messages"),pe(i,"--verbose")||i.push("--verbose"),u=!0):(pe(i,"--output-format")||i.push("--output-format","json"),u=i.some(g=>String(g).includes("stream-json"))),d=t):i.push(t),{cmd:o,args:i,model:a,stdin:d,streamJson:u}}function In(e=()=>{}){let t="",n="",r=!1,o="",s=null,i=u=>{u&&e(u)},a=u=>{if(!u||typeof u!="object")return;let m=u.event&&u.event.delta||u.delta;if(m&&m.type==="text_delta"&&typeof m.text=="string"){r=!0,n+=m.text,i(m.text);return}if(u.type==="result"&&typeof u.result=="string"){s=u.result;return}if(u.type==="assistant"&&u.message&&Array.isArray(u.message.content)){let g=u.message.content.filter(_=>_&&_.type==="text"&&typeof _.text=="string").map(_=>_.text).join("");g&&(o+=g)}},d=u=>{let m=String(u).trim();if(m)try{a(JSON.parse(m))}catch{}};return{feed(u){t+=String(u||"");let m;for(;(m=t.indexOf(`
12
- `))>=0;)d(t.slice(0,m)),t=t.slice(m+1)},end(){t&&(d(t),t="")},get live(){return r?n:o},get result(){return s??(r?n:o)}}}function ee(e,t,n,r=null){return{id:e,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:t,choices:[{index:0,delta:n?{content:n}:{},finish_reason:r}]}}function he(e){return`http://127.0.0.1:${e}`}function An(e={},t={}){return String(t.agensisUrl||t.baseUrl||e.url||X.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function Cn(e){return String(e||"").slice(0,18)}function R(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function xn(e={},t={},n={}){let r=R(e.metadata)||{},o=R(e.page)||R(r.page)||{},s=R(e.client)||R(r.client)||{},i=R(r.runtime)||{},a=R(e.manifest)||R(r.manifest)||null;return{url:String(e.url||o.url||r.websiteSource||e.websiteSource||"").slice(0,2048),title:String(e.title||o.title||"").slice(0,300),surface:String(e.surface||i.surface||t.surface||"").slice(0,80),instanceId:String(e.instanceId||i.instanceId||"").slice(0,140),workspaceId:String(t.workspaceId||e.workspaceId||n.workspace||"").slice(0,120),agentId:String(t.agentId||e.agentId||n.agent||"").slice(0,120),runtime:{...i,local:!0,connected:!0,connection:t},page:o,client:s,project:R(e.project)||R(r.project)||null,manifest:a,selection:R(e.selection)||null,updatedAt:new Date().toISOString()}}function Mn(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function On(e,t={},n=globalThis.fetch){let r=String(t.key||"").trim();if(!ln.test(r))throw new Error("Connection key format is invalid. Create a fresh CursorBuddy key first.");if(typeof n!="function")throw new Error("This Node.js runtime does not provide fetch; use a current Node.js release.");let o=An(e,t),s=await n(`${o}/backend/cursorbuddy/connection-keys/claim`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:r,baseUrl:o,host:et.hostname(),cwd:t.cwd||e.cwd||X.cwd(),name:t.name||e.name||e.handle||"CursorBuddy runtime",surface:t.surface||"browser_extension",scope:t.scope||"machine",runtimeKind:t.runtimeKind||"agensis-cli-local-bridge",version:t.version||e.version||X.env.npm_package_version||"",permissionMode:t.permissionMode||e.permissionMode,model:t.model||e.model,metadata:R(t.metadata)||null,websiteSource:t.websiteSource||t.metadata?.websiteSource||"",page:R(t.page)||R(t.metadata?.page)||null,client:R(t.client)||R(t.metadata?.client)||null,manifest:R(t.manifest)||R(t.metadata?.manifest)||null})}),i=await s.json().catch(()=>({}));if(!s.ok)throw new Error(Mn(s,i));return{key:r,baseUrl:o,data:i?.data||i}}async function rt(e,t={}){let n=Number(t.port??e.cursorBuddyPort??X.env.AGENSIS_CURSORBUDDY_PORT??qe),r=yn(e,t),o=new Date().toISOString(),s=[],i=[],a=new Set,d=t.fetchImpl||globalThis.fetch,u=1,m=null,g=n,_=null,h=(l,p={})=>{let k={ts:new Date().toISOString(),event:l,detail:p};return s.push(k),s.length>200&&s.shift(),t.log?.(`CursorBuddy local bridge: ${l}${Object.keys(p).length?` ${JSON.stringify(p)}`:""}`),k},x=()=>({connected:!!e.cursorBuddyRuntime,mode:e.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:e.agent,workspaceId:e.workspace,agensisUrl:e.url,handle:e.handle,name:e.name,cwd:e.cwd,updatedAt:new Date().toISOString()}),$=()=>{if(typeof t.connectionProvider!="function")return null;try{let l=t.connectionProvider();return!l||typeof l!="object"||Array.isArray(l)?null:{...x(),...l,connected:l.connected===!0}}catch{return null}},b=()=>{let l=$();return l?.connected===!1?l:_?{...x(),...l||{},..._,connected:!0,updatedAt:l?.updatedAt||_.updatedAt}:l||x()};function S(l={}){if(!l||typeof l!="object"||Array.isArray(l))return null;let p=String(l.action||l.type||"").trim().toLowerCase();if(!fn.has(p))return null;let k={id:u++,ts:new Date().toISOString(),action:p,text:String(l.text||l.say||l.message||"").slice(0,1200),label:String(l.label||"").slice(0,80),value:String(l.value||l.prompt||"").slice(0,1200),holdMs:Number.isFinite(l.holdMs)?Math.max(0,Math.min(6e4,l.holdMs)):void 0,source:String(l.source||"agensis-daemon").slice(0,80)};return l.options&&Array.isArray(l.options)&&(k.options=l.options.map(c=>({label:String(c?.label||"").slice(0,80),value:String(c?.value||c?.task||"").slice(0,1200)})).filter(c=>c.label).slice(0,6)),k}function M(l){for(i.push(l);i.length>mn;)i.shift();h("control",{id:l.id,action:l.action,chars:l.text.length});for(let p of[...a])try{H(p,{type:"command",command:l})}catch{a.delete(p)}return l}function N(l){let p=vn(l);if(p){let k=S(p.command);return k&&(M(k),h("chat_control",{id:k.id,action:k.action})),{content:p.content,model:"cursorbuddy-local-control",fast:!0}}return null}async function O(l){let p=N(l);if(p)return p;let k=Xe(l?.messages,m),c=Qe(e,k,l?.model),y=await se({cmd:c.cmd,args:c.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:c.stdin});if(y.error||y.status!==0)throw new Error(y.error?.message||String(y.stderr||"").trim()||`Command exited with status ${y.status}`);return{content:Ve(y.stdout||y.stderr),model:c.model}}async function j(l,p){let k=`agensis-cursorbuddy-${Date.now()}`,c=N(l);if(c){let C=c.model||"cursorbuddy-local-control";return H(p,ee(k,C,c.content)),H(p,ee(k,C,"","stop")),H(p,"[DONE]"),h("chat_fast",{chars:c.content.length,model:C}),{content:c.content,model:C,fast:!0}}let y=Xe(l?.messages,m),v=Qe(e,y,l?.model,{stream:!0}),P="",I=C=>{C&&(P+=C,H(p,ee(k,v.model||e.model,C)))},A=v.streamJson?In(I):null,f=await se({cmd:v.cmd,args:v.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:v.stdin,onData:C=>{if(A)A.feed(C);else{let L=String(C||"");P+=L,H(p,ee(k,v.model||e.model,L))}}});if(A){A.end();let C=A.result||"";!P&&C?I(C):P=C||P}if(f.error||f.status!==0){let C=f.error?.message||String(f.stderr||"").trim()||`Command exited with status ${f.status}`;throw new Error(C)}let E=A?P:Ve(P||f.stdout||f.stderr);return!A&&E&&E!==P&&(H(p,ee(k,v.model||e.model,E)),P=E),H(p,ee(k,v.model||e.model,"","stop")),H(p,"[DONE]"),{content:P||E,model:v.model}}let U=dn.createServer(async(l,p)=>{if(p.setHeader("access-control-allow-origin","*"),p.setHeader("access-control-allow-methods","GET, POST, OPTIONS"),p.setHeader("access-control-allow-headers","content-type, authorization, x-agensis-bridge-secret"),l.method==="OPTIONS"){p.writeHead(204),p.end();return}let k=new URL(l.url||"/",he(g||qe));if(!Sn(l.method,k.pathname)&&!gn(l,r)){F(p,401,{ok:!1,error:"Authentication required",code:"bridge_auth_required"});return}if(l.method==="GET"&&k.pathname==="/cursorbuddy/health"){let c=he(g);F(p,200,{ok:!0,runtime:"agensis-cli",backend:e.codingCmd,model:Ie(e),daemonModel:e.model,port:g,host:et.hostname(),pid:X.pid,bootedAt:o,authRequired:!0,authHeader:ge,stream:!0,streaming:!0,supportsStreaming:!0,chatStream:!0,capabilities:{chatStream:!0,controlStream:!0,fastAvatarReplies:!1,nativeCursorBuddyControl:!0},latestControlId:i.at(-1)?.id||0,connection:b(),context:m,endpoints:{chat:`${c}/v1/chat/completions`,chatStream:`${c}/v1/chat/completions`,edit:`${c}/cursorbuddy/edit`,context:`${c}/cursorbuddy/context`,control:`${c}/cursorbuddy/control`,controlStream:`${c}/cursorbuddy/control/stream`,logs:`${c}/cursorbuddy/logs`}});return}if(l.method==="GET"&&k.pathname==="/cursorbuddy/logs"){F(p,200,{ok:!0,events:s.slice(-100)});return}if(l.method==="GET"&&k.pathname==="/cursorbuddy/context"){F(p,200,{ok:!0,context:m});return}if(l.method==="GET"&&k.pathname==="/cursorbuddy/control"){let c=Number(k.searchParams.get("after")||0),y=i.filter(v=>v.id>c);F(p,200,{ok:!0,commands:y,latestId:i.at(-1)?.id||0});return}if(l.method==="GET"&&k.pathname==="/cursorbuddy/control/stream"){let c=Number(k.searchParams.get("after")||0);Ye(p),a.add(p),H(p,{type:"ready",latestId:i.at(-1)?.id||0});for(let v of i.filter(P=>P.id>c))H(p,{type:"command",command:v});let y=setInterval(()=>{try{H(p,{type:"ping",ts:new Date().toISOString()})}catch{a.delete(p),clearInterval(y)}},15e3);y.unref&&y.unref(),l.on("close",()=>{a.delete(p),clearInterval(y)});return}if(l.method==="POST"&&k.pathname==="/cursorbuddy/control"){try{let c=JSON.parse(await ie(l)||"{}"),y=S(c);if(!y){F(p,400,{ok:!1,error:"unsupported CursorBuddy control command"});return}let v=M(y);F(p,200,{ok:!0,command:v})}catch(c){h("control_error",{error:String(c?.message||c)}),F(p,400,{ok:!1,error:String(c?.message||c)})}return}if(l.method==="POST"&&k.pathname==="/cursorbuddy/context"){try{let c=JSON.parse(await ie(l)||"{}");m={url:String(c.url||"").slice(0,2048),title:String(c.title||"").slice(0,300),surface:String(c.surface||"").slice(0,80),instanceId:String(c.instanceId||"").slice(0,140),workspaceId:String(c.workspaceId||e.workspace||"").slice(0,120),agentId:String(c.agentId||e.agent||"").slice(0,120),runtime:c.runtime&&typeof c.runtime=="object"?c.runtime:null,page:c.page&&typeof c.page=="object"?c.page:null,client:c.client&&typeof c.client=="object"?c.client:null,project:c.project&&typeof c.project=="object"?c.project:null,manifest:c.manifest&&typeof c.manifest=="object"?c.manifest:null,selection:c.selection&&typeof c.selection=="object"?c.selection:null,updatedAt:new Date().toISOString()},h("context",{url:m.url,surface:m.surface,instanceId:m.instanceId}),F(p,200,{ok:!0,context:m})}catch(c){h("context_error",{error:String(c?.message||c)}),F(p,400,{ok:!1,error:String(c?.message||c)})}return}if(l.method==="POST"&&k.pathname==="/cursorbuddy/connect"){try{let c=JSON.parse(await ie(l)||"{}"),y=await On(e,c,d),v=y.data||{};_={connected:!0,mode:"agensis-claimed",keyId:Cn(y.key),agentId:String(v.agentId||v.agent?.id||e.agent||""),workspaceId:String(v.workspaceId||v.workspace_id||v.agent?.workspace_id||e.workspace||""),agensisUrl:y.baseUrl,handle:String(v.handle||v.agent?.handle||e.handle||""),name:String(v.agent?.name||c.name||e.name||"CursorBuddy runtime"),cwd:String(c.cwd||e.cwd||X.cwd()),surface:String(c.surface||"browser_extension"),command:String(v.command||v.localCommand||""),updatedAt:new Date().toISOString()},m=xn(c,_,e),h("connect",{mode:_.mode,keyId:_.keyId,agentId:_.agentId,workspaceId:_.workspaceId,url:m.url}),F(p,200,{ok:!0,connection:_,claim:v})}catch(c){h("connect_error",{error:String(c?.message||c)}),F(p,400,{ok:!1,error:String(c?.message||c)})}return}if(l.method==="POST"&&k.pathname==="/cursorbuddy/edit"){try{let c=JSON.parse(await ie(l)||"{}"),y=[{role:"system",content:"You are the local CursorBuddy edit agent. The user selected a DOM element in their own site. Use the payload to inspect and change the local checkout, then report what changed."},{role:"user",content:JSON.stringify(c,null,2)}];h("edit_request",{selector:c?.target?.selector||""});let v=await O({messages:y,model:c?.model});h("edit_done",{chars:v.content.length}),F(p,200,{ok:!0,backend:e.codingCmd,cwd:e.cwd,content:v.content})}catch(c){h("edit_error",{error:String(c?.message||c)}),F(p,500,{ok:!1,error:String(c?.message||c)})}return}if(l.method==="POST"&&k.pathname.endsWith("/chat/completions")){try{let c=JSON.parse(await ie(l)||"{}");if(h("chat_request",{messages:Array.isArray(c.messages)?c.messages.length:0,model:tt(c.model,Ie(e))}),c.stream===!0){Ye(p);let v=await j(c,p);h("chat_done",{chars:v.content.length,stream:!0,fast:v.fast===!0}),p.end();return}let y=await O(c);h("chat_done",{chars:y.content.length,fast:y.fast===!0}),F(p,200,{id:`agensis-cursorbuddy-${Date.now()}`,object:"chat.completion",model:y.model||c.model||e.model,choices:[{index:0,message:{role:"assistant",content:y.content},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}catch(c){h("chat_error",{error:String(c?.message||c)}),F(p,500,{error:{message:String(c?.message||c)}})}return}p.writeHead(404),p.end("CursorBuddy local bridge")});return await new Promise((l,p)=>{U.once("error",p),U.listen(n,"127.0.0.1",()=>{g=U.address().port,U.off("error",p),l()})}),h("listening",{url:`${he(g)}/cursorbuddy/health`}),{port:g,url:he(g),secret:r,authHeader:ge,close(){return new Promise(l=>U.close(()=>l()))},getContext(){return m}}}import te from"node:fs/promises";import Nn from"node:os";import J from"node:path";var ot=200,st=256*1024,Bn=2,$n=new Set([".md",".markdown",".txt"]);function Tn(e){return String(e||"").replace(/[^a-zA-Z0-9]/g,"-")}function Ae({cwd:e,memoryDir:t,homedir:n=Nn.homedir()}={}){let r=String(t||"").trim();if(r)return r.startsWith("~")?J.join(n,r.slice(1)):J.resolve(r);let o=String(e||"").trim();return o?J.join(n,".claude","projects",Tn(o),"memory"):null}async function Ce(e){if(!e)return null;try{let t=await te.realpath(e);return(await te.stat(t)).isDirectory()?t:null}catch{return null}}async function Dn(e,t){if(!e)throw new Error("memory root unavailable");let n=J.isAbsolute(String(t))?String(t):J.join(e,String(t)),r=await te.realpath(n),o=e.endsWith(J.sep)?e:e+J.sep;if(r!==e&&!r.startsWith(o))throw new Error(`path escapes memory root: ${t}`);return r}function Rn(e){let t=J.basename(e).toLowerCase();return t==="memory.md"?"index":t==="claude.md"?"instructions":"memory"}async function xe(e,t,n,r){if(n>Bn||r.length>=ot)return;let o;try{o=await te.readdir(t,{withFileTypes:!0})}catch{return}for(let s of o){if(r.length>=ot)break;if(s.name.startsWith("."))continue;let i=J.join(t,s.name);if(s.isDirectory())await xe(e,i,n+1,r);else if(s.isFile()&&$n.has(J.extname(s.name).toLowerCase())){let a=J.relative(e,i);r.push({path:a,kind:Rn(a)})}}}async function Pn(e){let t=await Ce(e);if(!t)return[];let n=[];return await xe(t,t,0,n),n.sort((r,o)=>r.kind==="index"?-1:o.kind==="index"?1:r.path.localeCompare(o.path)),n}async function Ln(e,t){let n=await Ce(e),r=await Dn(n,t),o=await te.readFile(r),s=o.length>st;return{content:o.subarray(0,st).toString("utf8"),byteSize:o.length,truncated:s}}async function it(e){let t=await Ce(e);if(!t)return"";let n=[];await xe(t,t,0,n),n.sort((o,s)=>o.path.localeCompare(s.path));let r=[];for(let o of n)try{let s=await te.stat(J.join(t,o.path));r.push(`${o.path}:${s.size}:${Math.floor(s.mtimeMs)}`)}catch{}return r.join("|")}async function at(e){let t=await Pn(e),n=[];for(let r of t)try{let{content:o,byteSize:s}=await Ln(e,r.path);n.push({path:r.path,kind:r.kind,content:o,byteSize:s})}catch{}return n}import ct from"node:fs";import ne from"node:path";import ut from"node:os";function Un(e){try{return ct.statSync(e).isDirectory()}catch{return!1}}function Me(e){try{return ct.readdirSync(e,{withFileTypes:!0})}catch{return[]}}function dt({home:e=ut.homedir(),cwd:t=process.cwd()}={}){let n=[e&&ne.join(e,".claude","commands"),t&&ne.join(t,".claude","commands")].filter(Boolean),r=new Set,o=[],s=(i,a)=>{if(!i)return;let d=a?`${a}:${i}`:i;r.has(d)||(r.add(d),o.push({name:i,parent:a||null}))};for(let i of n)for(let a of Me(i)){if(a.name.startsWith("."))continue;if(a.name.endsWith(".md")){s(a.name.slice(0,-3),null);continue}let d=ne.join(i,a.name);if(a.isDirectory()||a.isSymbolicLink()&&Un(d))for(let u of Me(d))u.name.startsWith(".")||u.name.endsWith(".md")&&s(u.name.slice(0,-3),a.name)}return o}function lt({home:e=ut.homedir(),cwd:t=process.cwd()}={}){let n=[e&&ne.join(e,".claude","skills"),e&&ne.join(e,".codex","skills"),t&&ne.join(t,".claude","skills")].filter(Boolean),r=new Set;for(let o of n)for(let s of Me(o))s.name.startsWith(".")||(s.name.endsWith(".md")?r.add(s.name.slice(0,-3)):(s.isDirectory()||s.isSymbolicLink())&&r.add(s.name));return[...r].sort()}import{readFile as Fn}from"node:fs/promises";var jn=new Set(["127.0.0.1","localhost","::1","[::1]"]);function mt(e,t,n){let r=Number(e);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.trunc(r))):t}function Gn(e,t){if(!e||typeof e!="object"||e.shared===!1)return null;let n=String(e.id||e.upstreamModel||`model-${t+1}`).trim();if(!n)return null;if(!/^[a-zA-Z0-9._:@/-]+$/.test(n))throw new Error(`Shared model id '${n}' may only contain letters, numbers, dot, underscore, colon, at, slash, or dash.`);let r=new URL(String(e.baseUrl||"http://127.0.0.1:11434/v1"));if(!jn.has(r.hostname))throw new Error(`Shared model '${n}' must use a loopback endpoint.`);if(!["http:","https:"].includes(r.protocol))throw new Error(`Shared model '${n}' must use an HTTP endpoint.`);return{id:n.slice(0,160),name:String(e.name||n).trim().slice(0,160)||n,provider:String(e.provider||"local").trim().slice(0,80)||"local",protocol:"openai-chat",baseUrl:r.toString().replace(/\/$/,""),upstreamModel:String(e.upstreamModel||n).trim().slice(0,200)||n,apiKeyEnv:String(e.apiKeyEnv||"").trim().slice(0,120),capabilities:[...new Set((Array.isArray(e.capabilities)?e.capabilities:["text","streaming"]).map(o=>String(o||"").trim().toLowerCase()).filter(Boolean))].slice(0,16),...e.contextWindow?{contextWindow:mt(e.contextWindow,void 0,1e7)}:{},maxConcurrency:mt(e.maxConcurrency,1,64),shared:!0}}async function ft(e){if(!e)return[];let t=JSON.parse(await Fn(e,"utf8")),n=Array.isArray(t)?t:t?.models;if(!Array.isArray(n))throw new Error("Shared model config must contain a models array.");return n.slice(0,32).map(Gn).filter(Boolean)}function pt(e){return(Array.isArray(e)?e:[]).filter(t=>t?.shared).map(t=>({id:t.id,name:t.name,provider:t.provider,protocol:t.protocol,upstreamModel:t.upstreamModel,capabilities:[...t.capabilities],...t.contextWindow?{contextWindow:t.contextWindow}:{},maxConcurrency:t.maxConcurrency,shared:!0}))}async function ht({models:e,request:t,send:n,signal:r,fetchImpl:o=fetch,env:s=process.env}){let i=String(t?.requestId||"").trim();if(!i)throw new Error("Inference requestId is required.");let a=(Array.isArray(e)?e:[]).find(S=>S.id===t?.model);if(!a)throw new Error(`Shared model '${t?.model||""}' is not available.`);let d={"content-type":"application/json"},u=a.apiKeyEnv?s[a.apiKeyEnv]:"";u&&(d.authorization=`Bearer ${u}`),n({action:"agent_inference_started",requestId:i,model:a.id});let{requestId:m,model:g,type:_,action:h,...x}=t,$=await o(`${a.baseUrl}/chat/completions`,{method:"POST",headers:d,body:JSON.stringify({...x,model:a.upstreamModel,stream:t.stream===!0}),signal:r});if(!$.ok){let S=await $.text().catch(()=>"");throw new Error(S||`Local model returned HTTP ${$.status}.`)}if(t.stream===!0){if(!$.body)throw new Error("Local model returned an empty stream.");let S=$.body.getReader(),M=new TextDecoder,N="",O,j=p=>{let k=p.trim();if(!k.startsWith("data:"))return!1;let c=k.slice(5).trim();if(!c)return!1;if(c==="[DONE]")return!0;try{let y=JSON.parse(c);y?.usage&&(O=y.usage),n({action:"agent_inference_delta",requestId:i,model:a.id,chunk:y})}catch{}return!1},U=!1;for(;!U;){let{done:p,value:k}=await S.read();N+=M.decode(k||new Uint8Array,{stream:!p});let c=N.split(/\r?\n/);N=p?"":c.pop()||"";for(let y of c)if(j(y)){U=!0;break}if(p)break}N&&j(N);let l={action:"agent_inference_result",requestId:i,model:a.id,...O?{usage:O}:{}};return n(l),l}let b=await $.json();return n({action:"agent_inference_result",requestId:i,model:a.id,response:b}),b}import gt from"node:fs";import K from"node:fs/promises";import Hn from"node:os";import W from"node:path";var wt="status.json",bt="heartbeat.json",Oe="heartbeat.md",Jn="agent.json",Wn="soul.md",Kn=16*1024,zn=`# Heartbeat
19
+ `).trim()||"Say that the local Agensis runtime is connected."}function ut(e){let t=String(e||"").trim();if(!t)return"";try{let n=JSON.parse(t);if(typeof n?.result=="string")return n.result;if(typeof n?.message=="string")return n.message;if(typeof n?.content=="string")return n.content}catch{}return t}function Wn(e){let t=Array.isArray(e?.messages)?e.messages:[];for(let n=t.length-1;n>=0;n-=1){let r=t[n];if(String(r?.role||"user")!=="user")continue;let o=String(r?.content||"").trim();if(o)return o}return""}function qn(e,t=280){let n=Wn(e).replace(/\s+/g," ").trim();if(!n)return"";if(n.length<=t)return n;let r=[/\b(tell me (?:a )?joke)\b/i,/\b(make (?:him|the buddy|cursorbuddy|avatar) wave|wave(?: hello)?|say hi|say hello)\b/i,/\b(what site|which site|what page|where am i|where are you|current url)\b/i,/\b(are you connected|connected|working|online|there)\b/i,/\b(show|guide|tour|walk|around|sections?|features?|important|highlight|what can i do|what should i do|help me)\b/i,/\b(open|show|bring up|get back|display)\b.{0,80}\b(prompt|bubble|dialog|panel|options|menu)\b/i,/\b(hide|hush|close|dismiss|clear|stop|cancel|be quiet)\b.{0,80}\b(bubble|prompt|dialog|panel|options|menu)?\b/i,/^(hi|hello|hey|yo|sup)\b/i];for(let o of r){let s=n.match(o);if(s?.[0])return s[0].trim()}return n.slice(-t).trim()}function zn(e){let t=qn(e);if(!t)return null;if(/\b(?:him|the buddy|cursorbuddy|cursor buddy|avatar|buddy|pet|character)\b/i.test(t)&&/\bwave(?: hello)?\b/i.test(t))return{content:"Waving now.",command:{action:"wave",text:"Hi. How can I help?",source:"chat"}};let r=t.match(/^(?:say|speak)\s+(.{1,180})$/i)||t.match(/\b(?:make|tell)\s+(?:him|the buddy|cursorbuddy|avatar)\s+(?:say|speak)\s+(.{1,180})$/i);return r?.[1]?{content:"Saying it now.",command:{action:"say",text:r[1].trim(),source:"chat"}}:/^(stop|cancel|dismiss|close|hide|hush|be quiet)\b/i.test(t)?{content:"Closed.",command:{action:"hush",source:"chat"}}:/\b(open|show)\b.*\b(options|chat|bubble|prompt)\b/i.test(t)?{content:"Opening options.",command:{action:"open",text:"What should I help with?",source:"chat"}}:null}function Yn(e){let t=String(e||"").trim();return t?/\s/.test(t)||t.startsWith("-")?!0:/^(claude|codex|node|npm|bun|python|python3|sh|bash|zsh)(?:$|\.)/.test(t):!1}function ft(e,t){let n=String(e||"").trim();return!n||Yn(n)?t:n}function pt(e){let t=String(e||"").trim();return!t||t==="haiku-4.5"||t==="claude-haiku-4.5"?Ie:t}function Ae(e={}){return pt(e.cursorBuddyModel||X.env.AGENSIS_CURSORBUDDY_MODEL||Ie)}function lt(e,t,n,r={}){let{cmd:o,args:s}=Jn(e.codingCmd||"claude -p"),i=[...s],c=pt(ft(n,Ae(e))),u="",a=!1;return Kn(o)?(c&&!he(i,"--model")&&i.push("--model",c),r.stream===!0&&!he(i,"--output-format")?(i.push("--output-format","stream-json","--include-partial-messages"),he(i,"--verbose")||i.push("--verbose"),a=!0):(he(i,"--output-format")||i.push("--output-format","json"),a=i.some(m=>String(m).includes("stream-json"))),u=t):i.push(t),{cmd:o,args:i,model:c,stdin:u,streamJson:a}}function Xn(e=()=>{}){let t="",n="",r=!1,o="",s=null,i=a=>{a&&e(a)},c=a=>{if(!a||typeof a!="object")return;let l=a.event&&a.event.delta||a.delta;if(l&&l.type==="text_delta"&&typeof l.text=="string"){r=!0,n+=l.text,i(l.text);return}if(a.type==="result"&&typeof a.result=="string"){s=a.result;return}if(a.type==="assistant"&&a.message&&Array.isArray(a.message.content)){let m=a.message.content.filter(_=>_&&_.type==="text"&&typeof _.text=="string").map(_=>_.text).join("");m&&(o+=m)}},u=a=>{let l=String(a).trim();if(l)try{c(JSON.parse(l))}catch{}};return{feed(a){t+=String(a||"");let l;for(;(l=t.indexOf(`
20
+ `))>=0;)u(t.slice(0,l)),t=t.slice(l+1)},end(){t&&(u(t),t="")},get live(){return r?n:o},get result(){return s??(r?n:o)}}}function te(e,t,n,r=null){return{id:e,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:t,choices:[{index:0,delta:n?{content:n}:{},finish_reason:r}]}}function ge(e){return`http://127.0.0.1:${e}`}function Vn(e={},t={}){return String(t.agensisUrl||t.baseUrl||e.url||X.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function Qn(e){return String(e||"").slice(0,18)}function U(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Zn(e={},t={},n={}){let r=U(e.metadata)||{},o=U(e.page)||U(r.page)||{},s=U(e.client)||U(r.client)||{},i=U(r.runtime)||{},c=U(e.manifest)||U(r.manifest)||null;return{url:String(e.url||o.url||r.websiteSource||e.websiteSource||"").slice(0,2048),title:String(e.title||o.title||"").slice(0,300),surface:String(e.surface||i.surface||t.surface||"").slice(0,80),instanceId:String(e.instanceId||i.instanceId||"").slice(0,140),workspaceId:String(t.workspaceId||e.workspaceId||n.workspace||"").slice(0,120),agentId:String(t.agentId||e.agentId||n.agent||"").slice(0,120),runtime:{...i,local:!0,connected:!0,connection:t},page:o,client:s,project:U(e.project)||U(r.project)||null,manifest:c,selection:U(e.selection)||null,updatedAt:new Date().toISOString()}}function er(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function tr(e,t={},n=globalThis.fetch){let r=String(t.key||"").trim();if(!Pn.test(r))throw new Error("Connection key format is invalid. Create a fresh CursorBuddy key first.");if(typeof n!="function")throw new Error("This Node.js runtime does not provide fetch; use a current Node.js release.");let o=Vn(e,t),s=await n(`${o}/backend/cursorbuddy/connection-keys/claim`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:r,baseUrl:o,host:mt.hostname(),cwd:t.cwd||e.cwd||X.cwd(),name:t.name||e.name||e.handle||"CursorBuddy runtime",surface:t.surface||"browser_extension",scope:t.scope||"machine",runtimeKind:t.runtimeKind||"agensis-cli-local-bridge",version:t.version||e.version||X.env.npm_package_version||"",permissionMode:t.permissionMode||e.permissionMode,model:t.model||e.model,metadata:U(t.metadata)||null,websiteSource:t.websiteSource||t.metadata?.websiteSource||"",page:U(t.page)||U(t.metadata?.page)||null,client:U(t.client)||U(t.metadata?.client)||null,manifest:U(t.manifest)||U(t.metadata?.manifest)||null})}),i=await s.json().catch(()=>({}));if(!s.ok)throw new Error(er(s,i));return{key:r,baseUrl:o,data:i?.data||i}}async function ht(e,t={}){let n=Number(t.port??e.cursorBuddyPort??X.env.AGENSIS_CURSORBUDDY_PORT??it),r=Gn(e,t),o=new Date().toISOString(),s=[],i=[],c=new Set,u=t.fetchImpl||globalThis.fetch,a=1,l=null,m=n,_=null,b=(p,g={})=>{let A={ts:new Date().toISOString(),event:p,detail:g};return s.push(A),s.length>200&&s.shift(),t.log?.(`CursorBuddy local bridge: ${p}${Object.keys(g).length?` ${JSON.stringify(g)}`:""}`),A},h=()=>({connected:!!e.cursorBuddyRuntime,mode:e.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:e.agent,workspaceId:e.workspace,agensisUrl:e.url,handle:e.handle,name:e.name,cwd:e.cwd,updatedAt:new Date().toISOString()}),M=()=>{if(typeof t.connectionProvider!="function")return null;try{let p=t.connectionProvider();return!p||typeof p!="object"||Array.isArray(p)?null:{...h(),...p,connected:p.connected===!0}}catch{return null}},w=()=>{let p=M();return p?.connected===!1?p:_?{...h(),...p||{},..._,connected:!0,updatedAt:p?.updatedAt||_.updatedAt}:p||h()};function S(p={}){if(!p||typeof p!="object"||Array.isArray(p))return null;let g=String(p.action||p.type||"").trim().toLowerCase();if(!Ln.has(g))return null;let A={id:a++,ts:new Date().toISOString(),action:g,text:String(p.text||p.say||p.message||"").slice(0,1200),label:String(p.label||"").slice(0,80),value:String(p.value||p.prompt||"").slice(0,1200),holdMs:Number.isFinite(p.holdMs)?Math.max(0,Math.min(6e4,p.holdMs)):void 0,source:String(p.source||"agensis-daemon").slice(0,80)};return p.options&&Array.isArray(p.options)&&(A.options=p.options.map(d=>({label:String(d?.label||"").slice(0,80),value:String(d?.value||d?.task||"").slice(0,1200)})).filter(d=>d.label).slice(0,6)),A}function E(p){for(i.push(p);i.length>Rn;)i.shift();b("control",{id:p.id,action:p.action,chars:p.text.length});for(let g of[...c])try{H(g,{type:"command",command:p})}catch{c.delete(g)}return p}function I(p){let g=zn(p);if(g){let A=S(g.command);return A&&(E(A),b("chat_control",{id:A.id,action:A.action})),{content:g.content,model:"cursorbuddy-local-control",fast:!0}}return null}async function x(p){let g=I(p);if(g)return g;let A=ct(p?.messages,l),d=lt(e,A,p?.model),f=await ie({cmd:d.cmd,args:d.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:d.stdin});if(f.error||f.status!==0)throw new Error(f.error?.message||String(f.stderr||"").trim()||`Command exited with status ${f.status}`);return{content:ut(f.stdout||f.stderr),model:d.model}}async function $(p,g){let A=`agensis-cursorbuddy-${Date.now()}`,d=I(p);if(d){let T=d.model||"cursorbuddy-local-control";return H(g,te(A,T,d.content)),H(g,te(A,T,"","stop")),H(g,"[DONE]"),b("chat_fast",{chars:d.content.length,model:T}),{content:d.content,model:T,fast:!0}}let f=ct(p?.messages,l),v=lt(e,f,p?.model,{stream:!0}),D="",C=T=>{T&&(D+=T,H(g,te(A,v.model||e.model,T)))},O=v.streamJson?Xn(C):null,y=await ie({cmd:v.cmd,args:v.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:v.stdin,onData:T=>{if(O)O.feed(T);else{let F=String(T||"");D+=F,H(g,te(A,v.model||e.model,F))}}});if(O){O.end();let T=O.result||"";!D&&T?C(T):D=T||D}if(y.error||y.status!==0){let T=y.error?.message||String(y.stderr||"").trim()||`Command exited with status ${y.status}`;throw new Error(T)}let N=O?D:ut(D||y.stdout||y.stderr);return!O&&N&&N!==D&&(H(g,te(A,v.model||e.model,N)),D=N),H(g,te(A,v.model||e.model,"","stop")),H(g,"[DONE]"),{content:D||N,model:v.model}}let P=Dn.createServer(async(p,g)=>{if(g.setHeader("access-control-allow-origin","*"),g.setHeader("access-control-allow-methods","GET, POST, OPTIONS"),g.setHeader("access-control-allow-headers","content-type, authorization, x-agensis-bridge-secret"),p.method==="OPTIONS"){g.writeHead(204),g.end();return}let A=new URL(p.url||"/",ge(m||it));if(!Hn(p.method,A.pathname)&&!jn(p,r)){j(g,401,{ok:!1,error:"Authentication required",code:"bridge_auth_required"});return}if(p.method==="GET"&&A.pathname==="/cursorbuddy/health"){let d=ge(m);j(g,200,{ok:!0,runtime:"agensis-cli",backend:e.codingCmd,model:Ae(e),daemonModel:e.model,port:m,host:mt.hostname(),pid:X.pid,bootedAt:o,authRequired:!0,authHeader:ye,stream:!0,streaming:!0,supportsStreaming:!0,chatStream:!0,capabilities:{chatStream:!0,controlStream:!0,fastAvatarReplies:!1,nativeCursorBuddyControl:!0},latestControlId:i.at(-1)?.id||0,connection:w(),context:l,endpoints:{chat:`${d}/v1/chat/completions`,chatStream:`${d}/v1/chat/completions`,edit:`${d}/cursorbuddy/edit`,context:`${d}/cursorbuddy/context`,control:`${d}/cursorbuddy/control`,controlStream:`${d}/cursorbuddy/control/stream`,logs:`${d}/cursorbuddy/logs`}});return}if(p.method==="GET"&&A.pathname==="/cursorbuddy/logs"){j(g,200,{ok:!0,events:s.slice(-100)});return}if(p.method==="GET"&&A.pathname==="/cursorbuddy/context"){j(g,200,{ok:!0,context:l});return}if(p.method==="GET"&&A.pathname==="/cursorbuddy/control"){let d=Number(A.searchParams.get("after")||0),f=i.filter(v=>v.id>d);j(g,200,{ok:!0,commands:f,latestId:i.at(-1)?.id||0});return}if(p.method==="GET"&&A.pathname==="/cursorbuddy/control/stream"){let d=Number(A.searchParams.get("after")||0);at(g),c.add(g),H(g,{type:"ready",latestId:i.at(-1)?.id||0});for(let v of i.filter(D=>D.id>d))H(g,{type:"command",command:v});let f=setInterval(()=>{try{H(g,{type:"ping",ts:new Date().toISOString()})}catch{c.delete(g),clearInterval(f)}},15e3);f.unref&&f.unref(),p.on("close",()=>{c.delete(g),clearInterval(f)});return}if(p.method==="POST"&&A.pathname==="/cursorbuddy/control"){try{let d=JSON.parse(await ae(p)||"{}"),f=S(d);if(!f){j(g,400,{ok:!1,error:"unsupported CursorBuddy control command"});return}let v=E(f);j(g,200,{ok:!0,command:v})}catch(d){b("control_error",{error:String(d?.message||d)}),j(g,400,{ok:!1,error:String(d?.message||d)})}return}if(p.method==="POST"&&A.pathname==="/cursorbuddy/context"){try{let d=JSON.parse(await ae(p)||"{}");l={url:String(d.url||"").slice(0,2048),title:String(d.title||"").slice(0,300),surface:String(d.surface||"").slice(0,80),instanceId:String(d.instanceId||"").slice(0,140),workspaceId:String(d.workspaceId||e.workspace||"").slice(0,120),agentId:String(d.agentId||e.agent||"").slice(0,120),runtime:d.runtime&&typeof d.runtime=="object"?d.runtime:null,page:d.page&&typeof d.page=="object"?d.page:null,client:d.client&&typeof d.client=="object"?d.client:null,project:d.project&&typeof d.project=="object"?d.project:null,manifest:d.manifest&&typeof d.manifest=="object"?d.manifest:null,selection:d.selection&&typeof d.selection=="object"?d.selection:null,updatedAt:new Date().toISOString()},b("context",{url:l.url,surface:l.surface,instanceId:l.instanceId}),j(g,200,{ok:!0,context:l})}catch(d){b("context_error",{error:String(d?.message||d)}),j(g,400,{ok:!1,error:String(d?.message||d)})}return}if(p.method==="POST"&&A.pathname==="/cursorbuddy/connect"){try{let d=JSON.parse(await ae(p)||"{}"),f=await tr(e,d,u),v=f.data||{};_={connected:!0,mode:"agensis-claimed",keyId:Qn(f.key),agentId:String(v.agentId||v.agent?.id||e.agent||""),workspaceId:String(v.workspaceId||v.workspace_id||v.agent?.workspace_id||e.workspace||""),agensisUrl:f.baseUrl,handle:String(v.handle||v.agent?.handle||e.handle||""),name:String(v.agent?.name||d.name||e.name||"CursorBuddy runtime"),cwd:String(d.cwd||e.cwd||X.cwd()),surface:String(d.surface||"browser_extension"),command:String(v.command||v.localCommand||""),updatedAt:new Date().toISOString()},l=Zn(d,_,e),b("connect",{mode:_.mode,keyId:_.keyId,agentId:_.agentId,workspaceId:_.workspaceId,url:l.url}),j(g,200,{ok:!0,connection:_,claim:v})}catch(d){b("connect_error",{error:String(d?.message||d)}),j(g,400,{ok:!1,error:String(d?.message||d)})}return}if(p.method==="POST"&&A.pathname==="/cursorbuddy/edit"){try{let d=JSON.parse(await ae(p)||"{}"),f=[{role:"system",content:"You are the local CursorBuddy edit agent. The user selected a DOM element in their own site. Use the payload to inspect and change the local checkout, then report what changed."},{role:"user",content:JSON.stringify(d,null,2)}];b("edit_request",{selector:d?.target?.selector||""});let v=await x({messages:f,model:d?.model});b("edit_done",{chars:v.content.length}),j(g,200,{ok:!0,backend:e.codingCmd,cwd:e.cwd,content:v.content})}catch(d){b("edit_error",{error:String(d?.message||d)}),j(g,500,{ok:!1,error:String(d?.message||d)})}return}if(p.method==="POST"&&A.pathname.endsWith("/chat/completions")){try{let d=JSON.parse(await ae(p)||"{}");if(b("chat_request",{messages:Array.isArray(d.messages)?d.messages.length:0,model:ft(d.model,Ae(e))}),d.stream===!0){at(g);let v=await $(d,g);b("chat_done",{chars:v.content.length,stream:!0,fast:v.fast===!0}),g.end();return}let f=await x(d);b("chat_done",{chars:f.content.length,fast:f.fast===!0}),j(g,200,{id:`agensis-cursorbuddy-${Date.now()}`,object:"chat.completion",model:f.model||d.model||e.model,choices:[{index:0,message:{role:"assistant",content:f.content},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}catch(d){b("chat_error",{error:String(d?.message||d)}),j(g,500,{error:{message:String(d?.message||d)}})}return}g.writeHead(404),g.end("CursorBuddy local bridge")});return await new Promise((p,g)=>{P.once("error",g),P.listen(n,"127.0.0.1",()=>{m=P.address().port,P.off("error",g),p()})}),b("listening",{url:`${ge(m)}/cursorbuddy/health`}),{port:m,url:ge(m),secret:r,authHeader:ye,close(){return new Promise(p=>P.close(()=>p()))},getContext(){return l}}}import ne from"node:fs/promises";import nr from"node:os";import J from"node:path";var gt=200,yt=256*1024,rr=2,or=new Set([".md",".markdown",".txt"]);function sr(e){return String(e||"").replace(/[^a-zA-Z0-9]/g,"-")}function xe({cwd:e,memoryDir:t,homedir:n=nr.homedir()}={}){let r=String(t||"").trim();if(r)return r.startsWith("~")?J.join(n,r.slice(1)):J.resolve(r);let o=String(e||"").trim();return o?J.join(n,".claude","projects",sr(o),"memory"):null}async function Me(e){if(!e)return null;try{let t=await ne.realpath(e);return(await ne.stat(t)).isDirectory()?t:null}catch{return null}}async function ir(e,t){if(!e)throw new Error("memory root unavailable");let n=J.isAbsolute(String(t))?String(t):J.join(e,String(t)),r=await ne.realpath(n),o=e.endsWith(J.sep)?e:e+J.sep;if(r!==e&&!r.startsWith(o))throw new Error(`path escapes memory root: ${t}`);return r}function ar(e){let t=J.basename(e).toLowerCase();return t==="memory.md"?"index":t==="claude.md"?"instructions":"memory"}async function Ne(e,t,n,r){if(n>rr||r.length>=gt)return;let o;try{o=await ne.readdir(t,{withFileTypes:!0})}catch{return}for(let s of o){if(r.length>=gt)break;if(s.name.startsWith("."))continue;let i=J.join(t,s.name);if(s.isDirectory())await Ne(e,i,n+1,r);else if(s.isFile()&&or.has(J.extname(s.name).toLowerCase())){let c=J.relative(e,i);r.push({path:c,kind:ar(c)})}}}async function cr(e){let t=await Me(e);if(!t)return[];let n=[];return await Ne(t,t,0,n),n.sort((r,o)=>r.kind==="index"?-1:o.kind==="index"?1:r.path.localeCompare(o.path)),n}async function ur(e,t){let n=await Me(e),r=await ir(n,t),o=await ne.readFile(r),s=o.length>yt;return{content:o.subarray(0,yt).toString("utf8"),byteSize:o.length,truncated:s}}async function St(e){let t=await Me(e);if(!t)return"";let n=[];await Ne(t,t,0,n),n.sort((o,s)=>o.path.localeCompare(s.path));let r=[];for(let o of n)try{let s=await ne.stat(J.join(t,o.path));r.push(`${o.path}:${s.size}:${Math.floor(s.mtimeMs)}`)}catch{}return r.join("|")}async function wt(e){let t=await cr(e),n=[];for(let r of t)try{let{content:o,byteSize:s}=await ur(e,r.path);n.push({path:r.path,kind:r.kind,content:o,byteSize:s})}catch{}return n}import bt from"node:fs";import re from"node:path";import _t from"node:os";function lr(e){try{return bt.statSync(e).isDirectory()}catch{return!1}}function Oe(e){try{return bt.readdirSync(e,{withFileTypes:!0})}catch{return[]}}function vt({home:e=_t.homedir(),cwd:t=process.cwd()}={}){let n=[e&&re.join(e,".claude","commands"),t&&re.join(t,".claude","commands")].filter(Boolean),r=new Set,o=[],s=(i,c)=>{if(!i)return;let u=c?`${c}:${i}`:i;r.has(u)||(r.add(u),o.push({name:i,parent:c||null}))};for(let i of n)for(let c of Oe(i)){if(c.name.startsWith("."))continue;if(c.name.endsWith(".md")){s(c.name.slice(0,-3),null);continue}let u=re.join(i,c.name);if(c.isDirectory()||c.isSymbolicLink()&&lr(u))for(let a of Oe(u))a.name.startsWith(".")||a.name.endsWith(".md")&&s(a.name.slice(0,-3),c.name)}return o}function Et({home:e=_t.homedir(),cwd:t=process.cwd()}={}){let n=[e&&re.join(e,".claude","skills"),e&&re.join(e,".codex","skills"),t&&re.join(t,".claude","skills")].filter(Boolean),r=new Set;for(let o of n)for(let s of Oe(o))s.name.startsWith(".")||(s.name.endsWith(".md")?r.add(s.name.slice(0,-3)):(s.isDirectory()||s.isSymbolicLink())&&r.add(s.name));return[...r].sort()}import{readFile as dr}from"node:fs/promises";var mr=new Set(["127.0.0.1","localhost","::1","[::1]"]);function kt(e,t,n){let r=Number(e);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.trunc(r))):t}function fr(e,t){if(!e||typeof e!="object"||e.shared===!1)return null;let n=String(e.id||e.upstreamModel||`model-${t+1}`).trim();if(!n)return null;if(!/^[a-zA-Z0-9._:@/-]+$/.test(n))throw new Error(`Shared model id '${n}' may only contain letters, numbers, dot, underscore, colon, at, slash, or dash.`);let r=new URL(String(e.baseUrl||"http://127.0.0.1:11434/v1"));if(!mr.has(r.hostname))throw new Error(`Shared model '${n}' must use a loopback endpoint.`);if(!["http:","https:"].includes(r.protocol))throw new Error(`Shared model '${n}' must use an HTTP endpoint.`);return{id:n.slice(0,160),name:String(e.name||n).trim().slice(0,160)||n,provider:String(e.provider||"local").trim().slice(0,80)||"local",protocol:"openai-chat",baseUrl:r.toString().replace(/\/$/,""),upstreamModel:String(e.upstreamModel||n).trim().slice(0,200)||n,apiKeyEnv:String(e.apiKeyEnv||"").trim().slice(0,120),capabilities:[...new Set((Array.isArray(e.capabilities)?e.capabilities:["text","streaming"]).map(o=>String(o||"").trim().toLowerCase()).filter(Boolean))].slice(0,16),...e.contextWindow?{contextWindow:kt(e.contextWindow,void 0,1e7)}:{},maxConcurrency:kt(e.maxConcurrency,1,64),shared:!0}}async function Ct(e){if(!e)return[];let t=JSON.parse(await dr(e,"utf8")),n=Array.isArray(t)?t:t?.models;if(!Array.isArray(n))throw new Error("Shared model config must contain a models array.");return n.slice(0,32).map(fr).filter(Boolean)}function It(e){return(Array.isArray(e)?e:[]).filter(t=>t?.shared).map(t=>({id:t.id,name:t.name,provider:t.provider,protocol:t.protocol,upstreamModel:t.upstreamModel,capabilities:[...t.capabilities],...t.contextWindow?{contextWindow:t.contextWindow}:{},maxConcurrency:t.maxConcurrency,shared:!0}))}async function At({models:e,request:t,send:n,signal:r,fetchImpl:o=fetch,env:s=process.env}){let i=String(t?.requestId||"").trim();if(!i)throw new Error("Inference requestId is required.");let c=(Array.isArray(e)?e:[]).find(S=>S.id===t?.model);if(!c)throw new Error(`Shared model '${t?.model||""}' is not available.`);let u={"content-type":"application/json"},a=c.apiKeyEnv?s[c.apiKeyEnv]:"";a&&(u.authorization=`Bearer ${a}`),n({action:"agent_inference_started",requestId:i,model:c.id});let{requestId:l,model:m,type:_,action:b,...h}=t,M=await o(`${c.baseUrl}/chat/completions`,{method:"POST",headers:u,body:JSON.stringify({...h,model:c.upstreamModel,stream:t.stream===!0}),signal:r});if(!M.ok){let S=await M.text().catch(()=>"");throw new Error(S||`Local model returned HTTP ${M.status}.`)}if(t.stream===!0){if(!M.body)throw new Error("Local model returned an empty stream.");let S=M.body.getReader(),E=new TextDecoder,I="",x,$=g=>{let A=g.trim();if(!A.startsWith("data:"))return!1;let d=A.slice(5).trim();if(!d)return!1;if(d==="[DONE]")return!0;try{let f=JSON.parse(d);f?.usage&&(x=f.usage),n({action:"agent_inference_delta",requestId:i,model:c.id,chunk:f})}catch{}return!1},P=!1;for(;!P;){let{done:g,value:A}=await S.read();I+=E.decode(A||new Uint8Array,{stream:!g});let d=I.split(/\r?\n/);I=g?"":d.pop()||"";for(let f of d)if($(f)){P=!0;break}if(g)break}I&&$(I);let p={action:"agent_inference_result",requestId:i,model:c.id,...x?{usage:x}:{}};return n(p),p}let w=await M.json();return n({action:"agent_inference_result",requestId:i,model:c.id,response:w}),w}import xt from"node:fs";import W from"node:fs/promises";import pr from"node:os";import K from"node:path";var Ot="status.json",Tt="heartbeat.json",Te="heartbeat.md",hr="agent.json",gr="soul.md",yr=16*1024,Sr=`# Heartbeat
13
21
 
14
22
  This file tells you what to do on each heartbeat \u2014 the recurring "still here, still
15
23
  working" moment. Edit it freely; the daemon reads it but never overwrites your edits.
@@ -22,28 +30,30 @@ On each heartbeat:
22
30
  - If you've finished and there's nothing to do, a short idle note is fine.
23
31
 
24
32
  Add your own recurring checks below.
25
- `,qn=8*1024,Yn=400;function yt(e,t){return String(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/\.{2,}/g,".").replace(/^[.-]+/,"").slice(0,96)||t}function re({workspace:e,agent:t,homedir:n=Hn.homedir()}={}){return W.join(n,".agensis",yt(e,"workspace"),yt(t,"agent"))}function _t(e){return W.join(re(e),wt)}function kt(e){return W.join(re(e),Oe)}async function Ne(e){let t=re(e);try{return await K.mkdir(t,{recursive:!0}),t}catch{return null}}async function ye(e,t){let n=`${e}.tmp-${process.pid}`;try{return await K.writeFile(n,t),await K.rename(n,e),!0}catch{try{await K.rm(n,{force:!0})}catch{}return!1}}async function Be(e,t){if(!t||typeof t!="object")return!1;let n=await Ne(e);if(!n)return!1;let r={id:t.id??e.agent??"",workspace:t.workspace_id??e.workspace??"",name:t.name??e.name??"",handle:t.handle??e.handle??"",model:t.model??e.model??"",permissionMode:t.permissionMode??t.permission_mode??e.permissionMode??"",description:t.description??"",instructions:t.instructions??"",systemPrompt:t.system_prompt??t.systemPrompt??"",tools:Array.isArray(t.tools)?t.tools:[],skills:Array.isArray(t.skills)?t.skills:[],memoryDir:t.memory_dir??t.memoryDir??"",version:Number(t.version||0),updatedAt:new Date().toISOString()},o=await ye(W.join(n,Jn),`${JSON.stringify(r,null,2)}
26
- `),s=String(t.soul??""),i=await ye(W.join(n,Wn),s);return o&&i}async function vt(e,t={}){let n=await Ne(e);return n?ye(W.join(n,bt),It(e,t)):!1}function Et(e,t={}){let n=re(e);try{return gt.mkdirSync(n,{recursive:!0}),gt.writeFileSync(W.join(n,bt),It(e,t)),!0}catch{return!1}}function It(e,t){let n=Date.now(),r={ts:n,iso:new Date(n).toISOString(),status:t.status||(t.busy?"busy":"online"),busy:!!t.busy,active:Number(t.active||0),queueSize:Number(t.queueSize||0),connected:!!t.connected,model:e.model||"",permissionMode:e.permissionMode||"",handle:e.handle||"",agent:e.agent||"",workspace:e.workspace||"",pid:process.pid,heartbeatMs:e.heartbeatMs,...t.agentStatus?{agentStatus:t.agentStatus}:{},...t.agentNote?{agentNote:t.agentNote}:{}};return`${JSON.stringify(r,null,2)}
27
- `}async function $e(e){let t=W.join(re(e),wt),n;try{let a=await K.stat(t);if(!a.isFile()||a.size>qn)return null;n=await K.readFile(t,"utf8")}catch{return null}let r;try{r=JSON.parse(n)}catch{return null}if(!r||typeof r!="object"||Array.isArray(r))return null;let o=St(r.status),s=St(r.note??r.message);if(!o&&!s)return null;let i={};return o&&(i.status=o),s&&(i.note=s),r.ts!=null&&Number.isFinite(Number(r.ts))&&(i.ts=Number(r.ts)),i}function St(e){return e==null?"":String(e).trim().replace(/\s+/g," ").slice(0,Yn)}async function At(e){let t=await Ne(e);if(!t)return!1;let n=W.join(t,Oe);try{return await K.access(n),!0}catch{}return ye(n,zn)}async function Ct(e){let t=W.join(re(e),Oe);try{let n=await K.stat(t);return!n.isFile()||n.size>Kn?null:(await K.readFile(t,"utf8")).trim()||null}catch{return null}}var Vn=30*60*1e3,Qn=15*1e3,xt=8,Zn="claude-opus-4-8",oe="0.1.25";async function Se(e={}){let t=er(e);t.sharedModels=t.share?await ft(t.sharedModelsFile):[];let n=!1,r=null,o=null,s=null,i=null,a=0,d=null,u=null,m="",g=null,_=!1,h=null,x=new Map,$=null,b={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"},S=new Map,M=new Map,N=[],O=()=>b,j=()=>({connected:_&&!!t.cursorBuddyRuntime,mode:t.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:h?.agentId||h?.agent_id||t.agent,workspaceId:h?.workspaceId||h?.workspace_id||t.workspace,agensisUrl:t.url,handle:h?.handle||t.handle,name:h?.name||t.name,cwd:t.cwd,updatedAt:new Date().toISOString()}),U=()=>{$||!t.lanListener||($=new ce.Server({port:0}),$.on("listening",()=>{let{port:I}=$.address();b={transport:"ws",listening:!0,addrs:Er(I),auth:"hub-pairwise"},B(`Agent-mesh LAN listener on port ${I}`),ae(r,t,O())}),$.on("connection",I=>{let A=!1,f=setTimeout(()=>{if(!A)try{I.close(1008,"peer auth required")}catch{}},5e3);I.once("message",E=>{clearTimeout(f);let C=De(E),L=C?.type==="peer_auth"?S.get(C.ticket):null;if(!L||L.fromAgentId!==C.fromAgentId||Date.now()>L.exp){try{I.close(1008,"invalid ticket")}catch{}return}S.delete(C.ticket),A=!0,I.on("message",G=>{let T=De(G);T?.type==="agent_job"&&T.job?.id&&u.enqueue({...T.job,key:T.job.id,lane:Mt(T.job),ws:r}).accepted&&B(`Queued peer-handoff job ${T.job.id} from ${C.fromAgentId}`)})})}),$.on("error",I=>B(`LAN listener error: ${I?.message||I}`)))},l=()=>{if($){try{$.close()}catch{}$=null}b={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"}},p=I=>new Promise((A,f)=>{if(!D(r,{action:"peer_ticket_request",targetAgentId:I})){f(new Error("hub socket not open"));return}let E=M.get(I)||[];E.push({resolve:A,reject:f}),M.set(I,E),setTimeout(()=>{let C=M.get(I)||[],L=C.findIndex(G=>G.resolve===A);L>=0&&(C.splice(L,1),f(new Error("peer ticket request timed out")))},1e4)}),k=()=>new Promise((I,A)=>{if(!D(r,{action:"peer_list_request"})){A(new Error("hub socket not open"));return}N.push(I),setTimeout(()=>{let f=N.indexOf(I);f>=0&&(N.splice(f,1),I([]))},1e4)}),c=async(I,A)=>{let f=null;try{let C=(await k()).find(T=>T.agentId===I&&T.reach?.listening&&T.reach.addrs?.length);if(!C)return!1;let L=await p(I),G=L.peer?.addrs?.[0]||C.reach.addrs[0];return!G?.host||!G?.port?!1:(f=new ce(`ws://${G.host}:${G.port}`),await new Promise((T,ke)=>{f.once("open",T),f.once("error",ke),setTimeout(()=>ke(new Error("peer connect timed out")),5e3)}),D(f,{type:"peer_auth",ticket:L.ticket,fromAgentId:t.agent}),D(f,{type:"agent_job",job:A}),!0)}catch(E){return B(`Peer handoff to ${I} failed, falling back to hub relay: ${E?.message||E}`),!1}finally{try{f?.close()}catch{}}},y=()=>{n=!0,$t(x),o&&clearTimeout(o),s&&clearInterval(s),i&&clearInterval(i),g&&(g.close().catch(()=>{}),g=null),l(),Et(t,{status:"stopped",connected:!1});try{r?.close()}catch{}d&&d()};if(u=ze({concurrency:t.once?1:t.maxConcurrency,runJob:async(I,A)=>{await hr(t,I,A),t.once&&y()}}),t.cursorBuddyBridge)try{g=await rt(t,{port:t.cursorBuddyPort,authSecret:t.cursorBuddyBridgeSecret||void 0,log:B,connectionProvider:j}),g?.secret&&(t.cursorBuddyBridgeSecret=g.secret)}catch(I){if(Or(I)){let A=await Nr(t.cursorBuddyPort);if(A?.ok){let f=A.pid?` pid ${A.pid}`:"";B(`CursorBuddy local bridge already running on http://127.0.0.1:${t.cursorBuddyPort}${f}`)}else B(`CursorBuddy local bridge port ${t.cursorBuddyPort} is in use but did not answer health`)}else B(`CursorBuddy local bridge unavailable: ${I?.message||I}`);g=null}w.once("SIGINT",y),w.once("SIGTERM",y);let v=()=>{if(n)return;let I=nr(t.url,t.token,t);m="",B(`Connecting to ${I.replace(t.token,"redacted")}`),r=new ce(I),r.on("open",()=>{_=!1,h=null,B(`Connected. Registering @${t.handle||"agent"} from ${t.cwd}`),D(r,{type:"auth",token:t.token}),D(r,{action:"agent_register",workspaceId:t.workspace,agentId:t.agent,handle:t.handle,name:t.name,host:le.hostname(),cwd:t.cwd,metadata:{codingCmd:t.codingCmd,model:t.model,permissionMode:t.permissionMode,permissionFlags:Pe(t.permissionMode),once:t.once,runtime:"agensis",version:oe}}),s=setInterval(()=>{Promise.all([Ut(t,O()).catch(()=>null),$e(t).catch(()=>null)]).then(([A,f])=>{D(r,{action:"agent_heartbeat",...A?{capabilitiesHash:A.capabilitiesHash,memoryHash:A.memoryHash}:{},metadata:Te(t,u,f,Dt(t)?g?.getContext?.():null,x)})})},t.heartbeatMs),s.unref&&s.unref()}),r.on("message",A=>{let f=De(A);if(f){if(f.type==="agent_registered"){_=!0,h=f.connection||f.agent||null,Ot(t,f.agent),B(`Registered as ${f.connection?.name||t.name} on ${f.connection?.host||le.hostname()}`),t.onRegistered&&Promise.resolve(t.onRegistered(t,f)).catch(E=>{B(`Profile save failed: ${E?.message||E}`)}),Be(t,f.agent).catch(()=>{}),At(t).catch(()=>{}),Bt(r,t),U(),ae(r,t,O());return}if(f.type==="agent_config"){Ot(t,f.agent),B(`Updated config for @${t.handle||"agent"}: model=${t.model}, permission=${t.permissionMode}`),Be(t,f.agent).catch(()=>{});return}if(f.type==="agent_memory_refresh"){Bt(r,t),ae(r,t,O());return}if(f.type==="agent_capabilities_refresh"){ae(r,t,O());return}if(f.type==="agent_inference_cancel"){x.get(String(f.requestId||""))?.abort();return}if(f.type==="agent_job_cancel"){let E=String(f.jobId||"");E&&u.cancel(E,f.reason||"Cancelled by Agensis")&&B(`Cancelled job ${E}`);return}if(f.type==="agent_inference_request"&&f.requestId){let E=String(f.requestId),C=t.sharedModels.find(T=>T.id===f.model),L=[...x.values()].filter(T=>T.model===f.model).length;if(!C){D(r,{action:"agent_inference_error",requestId:E,error:`Shared model '${f.model||""}' is not available.`});return}if(L>=C.maxConcurrency){D(r,{action:"agent_inference_error",requestId:E,error:"Shared model is at capacity.",code:"capacity_exhausted"});return}let G=new AbortController;x.set(E,{abort:()=>G.abort(),model:C.id}),D(r,{action:"agent_heartbeat",metadata:Te(t,u,null,null,x)}),ht({models:t.sharedModels,request:f,signal:G.signal,send:T=>D(r,T)}).catch(T=>{D(r,{action:"agent_inference_error",requestId:E,error:G.signal.aborted?"Inference cancelled.":T?.message||String(T),code:G.signal.aborted?"cancelled":"inference_failed"})}).finally(()=>{x.delete(E),D(r,{action:"agent_heartbeat",metadata:Te(t,u,null,null,x)})});return}if(f.type==="peer_ticket"){let E=f.peer?.agentId,C=M.get(E)||[],L=C.shift();C.length?M.set(E,C):M.delete(E),L&&L.resolve(f);return}if(f.type==="peer_ticket_grant"){S.set(f.ticket,{fromAgentId:f.fromAgentId,exp:f.exp});return}if(f.type==="peer_list"){let E=N.shift();E&&E(Array.isArray(f.peers)?f.peers:[]);return}if(f.type==="agent_reach_disable"){l(),ae(r,t,O());return}if(f.type==="error"){B(`Server rejected request: ${f.message||"unknown error"}`);return}if(f.type==="agent_disabled"){_=!1,h=null,B(`Agent disabled by Agensis: ${f.reason||"deactivated"}`),y();return}if(f.type==="agent_job"&&f.job?.id){let E=u.enqueue({...f.job,key:f.job.id,lane:Mt(f.job),ws:r});E.accepted&&(a+=1,B(`Queued job ${f.job.id} at position ${E.position}`),t.once&&u.idle().then(()=>y()))}}}),r.on("close",(A,f)=>{$t(x),_=!1,h=null;let E=String(f||"");if(B(`Socket closed (${A||"no-code"}${E?`: ${E}`:""})`),s&&(clearInterval(s),s=null),A===1008&&/agent deactivated|authentication failed/i.test(E)){B("Stopping daemon because Agensis rejected this agent connection."),y();return}if(m==="ECONNREFUSED"&&or(t.url)){B("Local agent backend is not running on 127.0.0.1:3142."),B("Start it in another terminal with: npm run backend"),B("Then rerun this connect command."),y();return}t.once&&a>0&&u.active()===0&&u.size()===0&&y(),!(n||t.once)&&(o=setTimeout(v,2e3),o.unref&&o.unref())}),r.on("error",A=>{m=A?.code||"",B(`Socket error: ${A?.message||A}`)})},P=async()=>{let I=await $e(t).catch(()=>null);await vt(t,{busy:u.active()>0,active:u.active(),queueSize:u.size(),connected:r?.readyState===ce.OPEN,agentStatus:I?.status,agentNote:I?.note}).catch(()=>{})};P(),i=setInterval(()=>{P()},t.heartbeatMs),i.unref&&i.unref(),v(),await new Promise(I=>{let A=setInterval(async()=>{t.once&&a>0&&u.active()===0&&u.size()===0&&y(),n&&y()},500);d=()=>{clearInterval(A),I()}}),d=null,w.off("SIGINT",y),w.off("SIGTERM",y)}function er(e){let t=tr(e.cursorBuddyBridge),n=e.noCoding===!0||w.env.AGENSIS_NO_CODING==="1",r={url:String(e.url||e.baseUrl||w.env.AGENSIS_URL||"").trim(),token:String(e.token||w.env.AGENSIS_TOKEN||"").trim(),workspace:String(e.workspace||e.workspaceId||w.env.AGENSIS_WORKSPACE||w.env.AGENSIS_WORKSPACE_ID||"").trim(),agent:String(e.agent||e.agentId||w.env.AGENSIS_AGENT||w.env.AGENSIS_AGENT_ID||"").trim(),handle:Ft(e.handle||w.env.AGENSIS_HANDLE||e.name||w.env.AGENSIS_NAME||"agent"),name:String(e.name||w.env.AGENSIS_NAME||e.handle||w.env.AGENSIS_HANDLE||"agensis Agent").trim(),cwd:String(e.cwd||w.env.AGENSIS_CWD||w.cwd()).trim(),codingCmd:n?"":String(e.codingCmd||w.env.AGENSIS_CODING_CMD||w.env.CODING_CMD||"claude -p").trim(),model:Re(e.model||w.env.AGENSIS_MODEL||w.env.CLAUDE_MODEL||""),permissionMode:we(e.permissionMode||e.permission_mode||e.permission||w.env.AGENSIS_PERMISSION_MODE||"default"),timeoutMs:Number(e.timeoutMs||w.env.AGENSIS_TIMEOUT_MS||Vn),heartbeatMs:Number(e.heartbeatMs||w.env.AGENSIS_HEARTBEAT_MS||Qn),maxConcurrency:Math.max(1,Number(e.maxConcurrency||w.env.AGENSIS_MAX_CONCURRENCY||xt)||xt),once:!!(e.once||w.env.AGENSIS_ONCE==="1"),exitOnOnce:!!e.exitOnOnce,onRegistered:typeof e.onRegistered=="function"?e.onRegistered:null,primaryDaemon:!!(e.primaryDaemon||w.env.AGENSIS_PRIMARY_DAEMON==="1"),cursorBuddyRuntime:!!(e.cursorBuddyRuntime||w.env.AGENSIS_CURSORBUDDY_RUNTIME==="1"),cursorBuddyBridge:t,cursorBuddyPort:Number(e.cursorBuddyPort||w.env.AGENSIS_CURSORBUDDY_PORT||8787),cursorBuddyBridgeSecret:String(e.cursorBuddyBridgeSecret||w.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),cursorBuddyModel:String(e.cursorBuddyModel||w.env.AGENSIS_CURSORBUDDY_MODEL||"haiku-4.5").trim(),lanListener:!!(e.lanListener||e.lan||w.env.AGENSIS_LAN==="1"),share:!!(e.share||w.env.AGENSIS_SHARE==="1"),sharedModelsFile:String(e.sharedModelsFile||w.env.AGENSIS_SHARED_MODELS_FILE||"").trim(),noCoding:n,hostFolders:Lt(e.hostFolders??e.host_folders??w.env.AGENSIS_HOST_FOLDERS)};r.sharedModelsFile&&!de.isAbsolute(r.sharedModelsFile)&&(r.sharedModelsFile=de.resolve(r.cwd,r.sharedModelsFile));let o=[];if(r.url||o.push("--url"),r.token||o.push("--token"),r.workspace||o.push("--workspace"),r.agent||o.push("--agent"),r.share&&!r.sharedModelsFile&&o.push("--shared-models-file"),o.length)throw new Error(`Missing required option(s): ${o.join(", ")}`);return r}function tr(e){let t=w.env.AGENSIS_CURSORBUDDY_BRIDGE;return t!==void 0&&t!==""?!/^(0|false|off|no)$/i.test(String(t).trim()):e==null||e===""?!1:typeof e=="boolean"?e:!/^(0|false|off|no)$/i.test(String(e).trim())}function nr(e,t,n={}){let r=Tt(e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",r.pathname="/backend/ws",r.search="",n.workspace&&r.searchParams.set("workspaceId",n.workspace),n.agent&&r.searchParams.set("agentId",n.agent),r.toString()}function Tt(e){let t=new URL(e);return rr(t)&&(t.protocol="http:",t.hostname="127.0.0.1",t.port="3142"),t}function rr(e){if(!(e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname==="0.0.0.0")||e.port==="3142")return!1;if(e.port==="5173"||e.port==="8888")return!0;let t=Number(e.port||0);return t>=49152&&t<=65535}function or(e){try{let t=Tt(e);return(t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="0.0.0.0")&&t.port==="3142"}catch{return!1}}function Mt(e){let t=String(e?.sessionId||""),n=String(e?.threadParentId||"");return`${t}::${n}`}var sr=/\b(cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b/i,ir=[/\b(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:say|speak)\s+(.+)$/i];function ar(e){return String(e||"").trim().replace(/^[`"'“”‘’]+|[`"'“”‘’?.!]+$/g,"").trim().slice(0,1200)}function cr(e){for(let t of ir){let n=String(e||"").match(t),r=ar(n?.[1]||"");if(r)return r}return""}function ur(e){let t=String(e||"").replace(/\s+/g," ").trim();if(!t)return"";let n=/latest user message\s*:\s*/gi,r=null,o=null;for(;r=n.exec(t);)o=r;if(!o)return"";let s=t.slice(o.index+o[0].length).trim(),i=s.search(/\b(Return a useful response|Conversation context follows|Previous user|Previous assistant|Diagnostic notes|System prompt|Developer message)\b/i);return(i>=0?s.slice(0,i):s).trim().replace(/^["'“”‘’]+|["'“”‘’]+$/g,"").trim()}function dr(e){let t=String(e||"").replace(/\s+/g," ").trim(),r=ur(t)||t;if(!r)return"";if(r.length<=500)return r;let o=[/\b(?:can you\s+)?(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:wave|waves|waving|say|speak)\b.{0,160}/i,/\b(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b.{0,120}\b(?:wave|waves|waving|say|speak|open|show|hide|hush|close|dismiss|clear)\b.{0,160}/i,/\b(?:wave|open|show|hide|hush|close|dismiss|clear)\b.{0,120}\b(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy|bubble|prompt|dialog|panel|options|menu)\b/i,/\b(?:say|speak)\s+[`"'“”‘’]?.{1,180}/i];for(let s of o){let i=r.match(s);if(i?.[0])return i[0].trim()}return""}function lr(e){let t=dr(e);if(!t)return null;let n=/^(open|show|hide|hush|close|dismiss)\b/i.test(t),r=sr.test(t);if(!n&&!r)return null;let o="agensis-native-control";if(/\b(hide|hush|close|dismiss|clear)\b.*\b(bubble|prompt|dialog|panel|options|menu)\b/i.test(t)||/^hush\b/i.test(t))return{action:"hush",source:o};if(/\b(open|show|bring up|get back|display)\b.*\b(prompt|bubble|dialog|panel|options|menu)\b/i.test(t)||/^open\b/i.test(t))return{action:"open",source:o};let s=cr(t);return s&&r?{action:"say",text:s,source:o}:r&&/\b(wave|waves|waving)\b/i.test(t)?{action:"wave",text:s,source:o}:null}async function mr(e,t){let r=`http://127.0.0.1:${Number(e.cursorBuddyPort||8787)}/cursorbuddy/control`,o=String(e.cursorBuddyBridgeSecret||w.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),s={"content-type":"application/json"};o&&(s.authorization=`Bearer ${o}`,s["x-agensis-bridge-secret"]=o);let i=await fetch(r,{method:"POST",headers:s,body:JSON.stringify(t)}),a=null;try{a=await i.json()}catch{a=null}if(!i.ok||a?.ok===!1)throw new Error(a?.error||`CursorBuddy control failed with HTTP ${i.status}`);return a}function fr(e){return e.action==="wave"?"Sent CursorBuddy a wave command.":e.action==="say"?`Sent CursorBuddy speech: ${e.text||""}`.trim():e.action==="open"?"Opened CursorBuddy's prompt.":e.action==="hush"?"Dismissed CursorBuddy's bubble.":e.action==="choose"?"Sent CursorBuddy options.":"Sent CursorBuddy control command."}function Dt(e={}){return e.cursorBuddyBridge===!1?!1:!!(e.cursorBuddyRuntime||e.primaryDaemon)}async function pr(e,t,n,r){let o="cursorbuddy-control",s="native",i=[],a=(m="")=>{D(t.ws,{action:"agent_job_delta",jobId:t.id,content:m,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i})};a("");let d="",u="";try{await mr(e,n),d=fr(n),a(d)}catch(m){u=String(m?.message||m),d=`CursorBuddy control failed: ${u}`,a(d)}D(t.ws,{action:"agent_job_result",jobId:t.id,response:d,error:u,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i}),B(`Finished native CursorBuddy ${n.action} job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`)}async function hr(e,t,{signal:n}){let r=Date.now();B(`Starting job ${t.id}`);let o=lr(t.prompt);if(o&&Dt(e)){await pr(e,t,o,r),e.once&&(B("One-shot CursorBuddy control job complete; exiting."),setTimeout(()=>w.exit(0),150));return}let s=yr(e,t),i=await gr(e,t),a="",d="",u=0,m=(N="")=>{D(t.ws,{action:"agent_job_delta",jobId:t.id,content:N,elapsedMs:Date.now()-r,model:s.model,permissionMode:s.permissionMode,permissionFlags:s.permissionFlags})};m("");let g=s.streamJson?Sr():null,_=setInterval(()=>m(a),1e3);_.unref&&_.unref();let x=await Ke(t).run({cmd:s.cmd,args:[...s.args,i],cwd:t.cwd||e.cwd,timeoutMs:e.timeoutMs,heartbeatMs:e.heartbeatMs,label:"agent job",signal:n,job:t,onData:N=>{g?(g.feed(N),a=g.live):(a+=String(N||""),d=Mr(`${d}
28
- ${N}`));let O=Date.now();O-u>150&&(u=O,m(a))}});clearInterval(_),g&&(g.end(),a=g.live,m(a));let $=String(x.stdout||"").trim(),b=String(x.stderr||"").trim(),S=x.error?x.error.message:x.status===0?"":b||`Command exited with status ${x.status}`,M=g?g.result||(S?"":b):$||(S?"":b)||d||"";D(t.ws,{action:"agent_job_result",jobId:t.id,response:M,error:S,elapsedMs:Date.now()-r,model:s.model,permissionMode:s.permissionMode,permissionFlags:s.permissionFlags}),B(`Finished job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`),e.once&&(B("One-shot job complete; exiting."),setTimeout(()=>w.exit(0),150))}async function gr(e,t){let n=t.agent||{},r=Array.isArray(n.skills)?n.skills.join(", "):String(n.skills||""),o=Array.isArray(n.tools)?n.tools.join(", "):String(n.tools||""),s=Rt(e,t),i=Pt(e,t),a=await Ct(e).catch(()=>null),d=a?`Heartbeat (recurring instructions \u2014 edit at ${kt(e)}):
29
- ${a}`:"";return["You are running as a local agensis workspace agent daemon.",`Workspace: ${t.workspaceId||e.workspace}`,`Channel session: ${t.sessionId||""}`,`Agent: ${n.name||e.name} (@${n.handle||e.handle})`,`Requested model: ${s}`,`Permission mode: ${i}`,n.description?`Description:
33
+ `,wr=8*1024,br=400;function Mt(e,t){return String(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/\.{2,}/g,".").replace(/^[.-]+/,"").slice(0,96)||t}function oe({workspace:e,agent:t,homedir:n=pr.homedir()}={}){return K.join(n,".agensis",Mt(e,"workspace"),Mt(t,"agent"))}function Bt(e){return K.join(oe(e),Ot)}function $t(e){return K.join(oe(e),Te)}async function Be(e){let t=oe(e);try{return await W.mkdir(t,{recursive:!0}),t}catch{return null}}async function Se(e,t){let n=`${e}.tmp-${process.pid}`;try{return await W.writeFile(n,t),await W.rename(n,e),!0}catch{try{await W.rm(n,{force:!0})}catch{}return!1}}async function $e(e,t){if(!t||typeof t!="object")return!1;let n=await Be(e);if(!n)return!1;let r={id:t.id??e.agent??"",workspace:t.workspace_id??e.workspace??"",name:t.name??e.name??"",handle:t.handle??e.handle??"",model:t.model??e.model??"",permissionMode:t.permissionMode??t.permission_mode??e.permissionMode??"",description:t.description??"",instructions:t.instructions??"",systemPrompt:t.system_prompt??t.systemPrompt??"",tools:Array.isArray(t.tools)?t.tools:[],skills:Array.isArray(t.skills)?t.skills:[],memoryDir:t.memory_dir??t.memoryDir??"",version:Number(t.version||0),updatedAt:new Date().toISOString()},o=await Se(K.join(n,hr),`${JSON.stringify(r,null,2)}
34
+ `),s=String(t.soul??""),i=await Se(K.join(n,gr),s);return o&&i}async function Dt(e,t={}){let n=await Be(e);return n?Se(K.join(n,Tt),Rt(e,t)):!1}function Pt(e,t={}){let n=oe(e);try{return xt.mkdirSync(n,{recursive:!0}),xt.writeFileSync(K.join(n,Tt),Rt(e,t)),!0}catch{return!1}}function Rt(e,t){let n=Date.now(),r={ts:n,iso:new Date(n).toISOString(),status:t.status||(t.busy?"busy":"online"),busy:!!t.busy,active:Number(t.active||0),queueSize:Number(t.queueSize||0),connected:!!t.connected,model:e.model||"",permissionMode:e.permissionMode||"",handle:e.handle||"",agent:e.agent||"",workspace:e.workspace||"",pid:process.pid,heartbeatMs:e.heartbeatMs,...t.agentStatus?{agentStatus:t.agentStatus}:{},...t.agentNote?{agentNote:t.agentNote}:{}};return`${JSON.stringify(r,null,2)}
35
+ `}async function De(e){let t=K.join(oe(e),Ot),n;try{let c=await W.stat(t);if(!c.isFile()||c.size>wr)return null;n=await W.readFile(t,"utf8")}catch{return null}let r;try{r=JSON.parse(n)}catch{return null}if(!r||typeof r!="object"||Array.isArray(r))return null;let o=Nt(r.status),s=Nt(r.note??r.message);if(!o&&!s)return null;let i={};return o&&(i.status=o),s&&(i.note=s),r.ts!=null&&Number.isFinite(Number(r.ts))&&(i.ts=Number(r.ts)),i}function Nt(e){return e==null?"":String(e).trim().replace(/\s+/g," ").slice(0,br)}async function Lt(e){let t=await Be(e);if(!t)return!1;let n=K.join(t,Te);try{return await W.access(n),!0}catch{}return Se(n,Sr)}async function Ut(e){let t=K.join(oe(e),Te);try{let n=await W.stat(t);return!n.isFile()||n.size>yr?null:(await W.readFile(t,"utf8")).trim()||null}catch{return null}}var vr=30*60*1e3,Er=15*1e3,Ft=2,kr=10*1024,Cr="claude-opus-4-8",Z="0.1.27";async function we(e={}){let t=Ir(e);t.sharedModels=t.share?await Ct(t.sharedModelsFile):[];let n=!1,r=null,o=null,s=null,i=null,c=0,u=null,a=null,l="",m=null,_=!1,b=null,h=new Map,M=null,w={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"},S=new Map,E=new Map,I=[],x=()=>w,$=()=>({connected:_&&!!t.cursorBuddyRuntime,mode:t.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:b?.agentId||b?.agent_id||t.agent,workspaceId:b?.workspaceId||b?.workspace_id||t.workspace,agensisUrl:t.url,handle:b?.handle||t.handle,name:b?.name||t.name,cwd:t.cwd,updatedAt:new Date().toISOString()}),P=()=>{M||!t.lanListener||(M=new ue.Server({port:0}),M.on("listening",()=>{let{port:C}=M.address();w={transport:"ws",listening:!0,addrs:Xr(C),auth:"hub-pairwise"},B(`Agent-mesh LAN listener on port ${C}`),ce(r,t,x())}),M.on("connection",C=>{let O=!1,y=setTimeout(()=>{if(!O)try{C.close(1008,"peer auth required")}catch{}},5e3);C.once("message",N=>{clearTimeout(y);let T=Re(N),F=T?.type==="peer_auth"?S.get(T.ticket):null;if(!F||F.fromAgentId!==T.fromAgentId||Date.now()>F.exp){try{C.close(1008,"invalid ticket")}catch{}return}S.delete(T.ticket),O=!0,C.on("message",G=>{let R=Re(G);R?.type==="agent_job"&&R.job?.id&&a.enqueue({...R.job,key:R.job.id,lane:jt(R.job),ws:r}).accepted&&B(`Queued peer-handoff job ${R.job.id} from ${T.fromAgentId}`)})})}),M.on("error",C=>B(`LAN listener error: ${C?.message||C}`)))},p=()=>{if(M){try{M.close()}catch{}M=null}w={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"}},g=C=>new Promise((O,y)=>{if(!L(r,{action:"peer_ticket_request",targetAgentId:C})){y(new Error("hub socket not open"));return}let N=E.get(C)||[];N.push({resolve:O,reject:y}),E.set(C,N),setTimeout(()=>{let T=E.get(C)||[],F=T.findIndex(G=>G.resolve===O);F>=0&&(T.splice(F,1),y(new Error("peer ticket request timed out")))},1e4)}),A=()=>new Promise((C,O)=>{if(!L(r,{action:"peer_list_request"})){O(new Error("hub socket not open"));return}I.push(C),setTimeout(()=>{let y=I.indexOf(C);y>=0&&(I.splice(y,1),C([]))},1e4)}),d=async(C,O)=>{let y=null;try{let T=(await A()).find(R=>R.agentId===C&&R.reach?.listening&&R.reach.addrs?.length);if(!T)return!1;let F=await g(C),G=F.peer?.addrs?.[0]||T.reach.addrs[0];return!G?.host||!G?.port?!1:(y=new ue(`ws://${G.host}:${G.port}`),await new Promise((R,Ee)=>{y.once("open",R),y.once("error",Ee),setTimeout(()=>Ee(new Error("peer connect timed out")),5e3)}),L(y,{type:"peer_auth",ticket:F.ticket,fromAgentId:t.agent}),L(y,{type:"agent_job",job:O}),!0)}catch(N){return B(`Peer handoff to ${C} failed, falling back to hub relay: ${N?.message||N}`),!1}finally{try{y?.close()}catch{}}},f=()=>{n=!0,Kt(h),o&&clearTimeout(o),s&&clearInterval(s),i&&clearInterval(i),m&&(m.close().catch(()=>{}),m=null),p(),Pt(t,{status:"stopped",connected:!1});try{r?.close()}catch{}u&&u()};if(a=st({concurrency:t.once?1:t.maxConcurrency,runJob:async(C,O)=>{await jr(t,C,O),t.once&&f()}}),t.cursorBuddyBridge)try{m=await ht(t,{port:t.cursorBuddyPort,authSecret:t.cursorBuddyBridgeSecret||void 0,log:B,connectionProvider:$}),m?.secret&&(t.cursorBuddyBridgeSecret=m.secret)}catch(C){if(eo(C)){let O=await to(t.cursorBuddyPort);if(O?.ok){let y=O.pid?` pid ${O.pid}`:"";B(`CursorBuddy local bridge already running on http://127.0.0.1:${t.cursorBuddyPort}${y}`)}else B(`CursorBuddy local bridge port ${t.cursorBuddyPort} is in use but did not answer health`)}else B(`CursorBuddy local bridge unavailable: ${C?.message||C}`);m=null}k.once("SIGINT",f),k.once("SIGTERM",f);let v=()=>{if(n)return;let C=xr(t.url,t.token,t);l="",B(`Connecting to ${C.replace(t.token,"redacted")}`),r=new ue(C),r.on("open",()=>{_=!1,b=null,B(`Connected. Registering @${t.handle||"agent"} from ${t.cwd}`),L(r,{type:"auth",token:t.token}),L(r,{action:"agent_register",workspaceId:t.workspace,agentId:t.agent,handle:t.handle,name:t.name,host:me.hostname(),cwd:t.cwd,metadata:{codingCmd:t.codingCmd,model:t.model,permissionMode:t.permissionMode,permissionFlags:je(t.permissionMode),once:t.once,runtime:"agensis",version:Z}}),s=setInterval(()=>{Promise.all([Vt(t,x()).catch(()=>null),De(t).catch(()=>null)]).then(([O,y])=>{L(r,{action:"agent_heartbeat",...O?{capabilitiesHash:O.capabilitiesHash,memoryHash:O.memoryHash}:{},metadata:Pe(t,a,y,Wt(t)?m?.getContext?.():null,h)})})},t.heartbeatMs),s.unref&&s.unref()}),r.on("message",O=>{let y=Re(O);if(y){if(y.type==="agent_registered"){_=!0,b=y.connection||y.agent||null,Gt(t,y.agent),B(`Registered as ${y.connection?.name||t.name} on ${y.connection?.host||me.hostname()}`),t.onRegistered&&Promise.resolve(t.onRegistered(t,y)).catch(N=>{B(`Profile save failed: ${N?.message||N}`)}),$e(t,y.agent).catch(()=>{}),Lt(t).catch(()=>{}),Jt(r,t),P(),ce(r,t,x());return}if(y.type==="agent_config"){Gt(t,y.agent),B(`Updated config for @${t.handle||"agent"}: model=${t.model}, permission=${t.permissionMode}`),$e(t,y.agent).catch(()=>{});return}if(y.type==="agent_memory_refresh"){Jt(r,t),ce(r,t,x());return}if(y.type==="agent_capabilities_refresh"){ce(r,t,x());return}if(y.type==="agent_inference_cancel"){h.get(String(y.requestId||""))?.abort();return}if(y.type==="agent_job_cancel"){let N=String(y.jobId||"");N&&a.cancel(N,y.reason||"Cancelled by Agensis")&&B(`Cancelled job ${N}`);return}if(y.type==="agent_inference_request"&&y.requestId){let N=String(y.requestId),T=t.sharedModels.find(R=>R.id===y.model),F=[...h.values()].filter(R=>R.model===y.model).length;if(!T){L(r,{action:"agent_inference_error",requestId:N,error:`Shared model '${y.model||""}' is not available.`});return}if(F>=T.maxConcurrency){L(r,{action:"agent_inference_error",requestId:N,error:"Shared model is at capacity.",code:"capacity_exhausted"});return}let G=new AbortController;h.set(N,{abort:()=>G.abort(),model:T.id}),L(r,{action:"agent_heartbeat",metadata:Pe(t,a,null,null,h)}),At({models:t.sharedModels,request:y,signal:G.signal,send:R=>L(r,R)}).catch(R=>{L(r,{action:"agent_inference_error",requestId:N,error:G.signal.aborted?"Inference cancelled.":R?.message||String(R),code:G.signal.aborted?"cancelled":"inference_failed"})}).finally(()=>{h.delete(N),L(r,{action:"agent_heartbeat",metadata:Pe(t,a,null,null,h)})});return}if(y.type==="peer_ticket"){let N=y.peer?.agentId,T=E.get(N)||[],F=T.shift();T.length?E.set(N,T):E.delete(N),F&&F.resolve(y);return}if(y.type==="peer_ticket_grant"){S.set(y.ticket,{fromAgentId:y.fromAgentId,exp:y.exp});return}if(y.type==="peer_list"){let N=I.shift();N&&N(Array.isArray(y.peers)?y.peers:[]);return}if(y.type==="agent_reach_disable"){p(),ce(r,t,x());return}if(y.type==="error"){B(`Server rejected request: ${y.message||"unknown error"}`);return}if(y.type==="agent_disabled"){_=!1,b=null,B(`Agent disabled by Agensis: ${y.reason||"deactivated"}`),f();return}if(y.type==="agent_job"&&y.job?.id){let N=a.enqueue({...y.job,key:y.job.id,lane:jt(y.job),ws:r});N.accepted&&(c+=1,B(`Queued job ${y.job.id} at position ${N.position}`),t.once&&a.idle().then(()=>f()))}}}),r.on("close",(O,y)=>{Kt(h),_=!1,b=null;let N=String(y||"");if(B(`Socket closed (${O||"no-code"}${N?`: ${N}`:""})`),s&&(clearInterval(s),s=null),O===1008&&/agent deactivated|authentication failed/i.test(N)){B("Stopping daemon because Agensis rejected this agent connection."),f();return}if(l==="ECONNREFUSED"&&Nr(t.url)){B("Local agent backend is not running on 127.0.0.1:3142."),B("Start it in another terminal with: npm run backend"),B("Then rerun this connect command."),f();return}t.once&&c>0&&a.active()===0&&a.size()===0&&f(),!(n||t.once)&&(o=setTimeout(v,2e3),o.unref&&o.unref())}),r.on("error",O=>{l=O?.code||"",B(`Socket error: ${O?.message||O}`)})},D=async()=>{let C=await De(t).catch(()=>null);await Dt(t,{busy:a.active()>0,active:a.active(),queueSize:a.size(),connected:r?.readyState===ue.OPEN,agentStatus:C?.status,agentNote:C?.note}).catch(()=>{})};D(),i=setInterval(()=>{D()},t.heartbeatMs),i.unref&&i.unref(),v(),await new Promise(C=>{let O=setInterval(async()=>{t.once&&c>0&&a.active()===0&&a.size()===0&&f(),n&&f()},500);u=()=>{clearInterval(O),C()}}),u=null,k.off("SIGINT",f),k.off("SIGTERM",f)}function Ir(e){let t=Ar(e.cursorBuddyBridge),n=e.noCoding===!0||k.env.AGENSIS_NO_CODING==="1",o=!se(e.fullCliContext,se(k.env.AGENSIS_FULL_CLI_CONTEXT,!1))&&se(e.leanCli,!0),s={url:String(e.url||e.baseUrl||k.env.AGENSIS_URL||"").trim(),token:String(e.token||k.env.AGENSIS_TOKEN||"").trim(),workspace:String(e.workspace||e.workspaceId||k.env.AGENSIS_WORKSPACE||k.env.AGENSIS_WORKSPACE_ID||"").trim(),agent:String(e.agent||e.agentId||k.env.AGENSIS_AGENT||k.env.AGENSIS_AGENT_ID||"").trim(),handle:en(e.handle||k.env.AGENSIS_HANDLE||e.name||k.env.AGENSIS_NAME||"agent"),name:String(e.name||k.env.AGENSIS_NAME||e.handle||k.env.AGENSIS_HANDLE||"agensis Agent").trim(),cwd:String(e.cwd||k.env.AGENSIS_CWD||k.cwd()).trim(),codingCmd:n?"":String(e.codingCmd||k.env.AGENSIS_CODING_CMD||k.env.CODING_CMD||"claude -p").trim(),model:Fe(e.model||k.env.AGENSIS_MODEL||k.env.CLAUDE_MODEL||""),permissionMode:be(e.permissionMode||e.permission_mode||e.permission||k.env.AGENSIS_PERMISSION_MODE||"default"),timeoutMs:Number(e.timeoutMs||k.env.AGENSIS_TIMEOUT_MS||vr),heartbeatMs:Number(e.heartbeatMs||k.env.AGENSIS_HEARTBEAT_MS||Er),maxConcurrency:Math.max(1,Number(e.maxConcurrency||k.env.AGENSIS_MAX_CONCURRENCY||Ft)||Ft),once:!!(e.once||k.env.AGENSIS_ONCE==="1"),exitOnOnce:!!e.exitOnOnce,onRegistered:typeof e.onRegistered=="function"?e.onRegistered:null,primaryDaemon:!!(e.primaryDaemon||k.env.AGENSIS_PRIMARY_DAEMON==="1"),cursorBuddyRuntime:!!(e.cursorBuddyRuntime||k.env.AGENSIS_CURSORBUDDY_RUNTIME==="1"),cursorBuddyBridge:t,cursorBuddyPort:Number(e.cursorBuddyPort||k.env.AGENSIS_CURSORBUDDY_PORT||8787),cursorBuddyBridgeSecret:String(e.cursorBuddyBridgeSecret||k.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),cursorBuddyModel:String(e.cursorBuddyModel||k.env.AGENSIS_CURSORBUDDY_MODEL||"haiku-4.5").trim(),lanListener:!!(e.lanListener||e.lan||k.env.AGENSIS_LAN==="1"),share:!!(e.share||k.env.AGENSIS_SHARE==="1"),sharedModelsFile:String(e.sharedModelsFile||k.env.AGENSIS_SHARED_MODELS_FILE||"").trim(),noCoding:n,leanCli:o,fastConnection:se(e.fastConnection,se(k.env.AGENSIS_FAST_CONNECTION,!0)),syncMemory:se(e.syncMemory,k.env.AGENSIS_SYNC_MEMORY==="1"),hostFolders:Yt(e.hostFolders??e.host_folders??k.env.AGENSIS_HOST_FOLDERS)};s.sharedModelsFile&&!de.isAbsolute(s.sharedModelsFile)&&(s.sharedModelsFile=de.resolve(s.cwd,s.sharedModelsFile));let i=[];if(s.url||i.push("--url"),s.token||i.push("--token"),s.workspace||i.push("--workspace"),s.agent||i.push("--agent"),s.share&&!s.sharedModelsFile&&i.push("--shared-models-file"),i.length)throw new Error(`Missing required option(s): ${i.join(", ")}`);return s}function se(e,t){return e==null||e===""?t:typeof e=="boolean"?e:!/^(0|false|off|no)$/i.test(String(e).trim())}function Ar(e){let t=k.env.AGENSIS_CURSORBUDDY_BRIDGE;return t!==void 0&&t!==""?!/^(0|false|off|no)$/i.test(String(t).trim()):e==null||e===""?!1:typeof e=="boolean"?e:!/^(0|false|off|no)$/i.test(String(e).trim())}function xr(e,t,n={}){let r=Ue(e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",r.pathname="/backend/ws",r.search="",n.workspace&&r.searchParams.set("workspaceId",n.workspace),n.agent&&r.searchParams.set("agentId",n.agent),r.toString()}function Ue(e){let t=new URL(e);return Mr(t)&&(t.protocol="http:",t.hostname="127.0.0.1",t.port="3142"),t}function Mr(e){if(!(e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname==="0.0.0.0")||e.port==="3142")return!1;if(e.port==="5173"||e.port==="8888")return!0;let t=Number(e.port||0);return t>=49152&&t<=65535}function Nr(e){try{let t=Ue(e);return(t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="0.0.0.0")&&t.port==="3142"}catch{return!1}}function jt(e){let t=String(e?.sessionId||""),n=String(e?.threadParentId||"");return`${t}::${n}`}var Or=/\b(cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b/i,Tr=[/\b(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:say|speak)\s+(.+)$/i];function Br(e){return String(e||"").trim().replace(/^[`"'“”‘’]+|[`"'“”‘’?.!]+$/g,"").trim().slice(0,1200)}function $r(e){for(let t of Tr){let n=String(e||"").match(t),r=Br(n?.[1]||"");if(r)return r}return""}function Dr(e){let t=String(e||"").replace(/\s+/g," ").trim();if(!t)return"";let n=/latest user message\s*:\s*/gi,r=null,o=null;for(;r=n.exec(t);)o=r;if(!o)return"";let s=t.slice(o.index+o[0].length).trim(),i=s.search(/\b(Return a useful response|Conversation context follows|Previous user|Previous assistant|Diagnostic notes|System prompt|Developer message)\b/i);return(i>=0?s.slice(0,i):s).trim().replace(/^["'“”‘’]+|["'“”‘’]+$/g,"").trim()}function Pr(e){let t=String(e||"").replace(/\s+/g," ").trim(),r=Dr(t)||t;if(!r)return"";if(r.length<=500)return r;let o=[/\b(?:can you\s+)?(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:wave|waves|waving|say|speak)\b.{0,160}/i,/\b(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b.{0,120}\b(?:wave|waves|waving|say|speak|open|show|hide|hush|close|dismiss|clear)\b.{0,160}/i,/\b(?:wave|open|show|hide|hush|close|dismiss|clear)\b.{0,120}\b(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy|bubble|prompt|dialog|panel|options|menu)\b/i,/\b(?:say|speak)\s+[`"'“”‘’]?.{1,180}/i];for(let s of o){let i=r.match(s);if(i?.[0])return i[0].trim()}return""}function Rr(e){let t=Pr(e);if(!t)return null;let n=/^(open|show|hide|hush|close|dismiss)\b/i.test(t),r=Or.test(t);if(!n&&!r)return null;let o="agensis-native-control";if(/\b(hide|hush|close|dismiss|clear)\b.*\b(bubble|prompt|dialog|panel|options|menu)\b/i.test(t)||/^hush\b/i.test(t))return{action:"hush",source:o};if(/\b(open|show|bring up|get back|display)\b.*\b(prompt|bubble|dialog|panel|options|menu)\b/i.test(t)||/^open\b/i.test(t))return{action:"open",source:o};let s=$r(t);return s&&r?{action:"say",text:s,source:o}:r&&/\b(wave|waves|waving)\b/i.test(t)?{action:"wave",text:s,source:o}:null}async function Lr(e,t){let r=`http://127.0.0.1:${Number(e.cursorBuddyPort||8787)}/cursorbuddy/control`,o=String(e.cursorBuddyBridgeSecret||k.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),s={"content-type":"application/json"};o&&(s.authorization=`Bearer ${o}`,s["x-agensis-bridge-secret"]=o);let i=await fetch(r,{method:"POST",headers:s,body:JSON.stringify(t)}),c=null;try{c=await i.json()}catch{c=null}if(!i.ok||c?.ok===!1)throw new Error(c?.error||`CursorBuddy control failed with HTTP ${i.status}`);return c}function Ur(e){return e.action==="wave"?"Sent CursorBuddy a wave command.":e.action==="say"?`Sent CursorBuddy speech: ${e.text||""}`.trim():e.action==="open"?"Opened CursorBuddy's prompt.":e.action==="hush"?"Dismissed CursorBuddy's bubble.":e.action==="choose"?"Sent CursorBuddy options.":"Sent CursorBuddy control command."}function Wt(e={}){return e.cursorBuddyBridge===!1?!1:!!(e.cursorBuddyRuntime||e.primaryDaemon)}async function Fr(e,t,n,r){let o="cursorbuddy-control",s="native",i=[],c=(l="")=>{L(t.ws,{action:"agent_job_delta",jobId:t.id,content:l,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i})};c("");let u="",a="";try{await Lr(e,n),u=Ur(n),c(u)}catch(l){a=String(l?.message||l),u=`CursorBuddy control failed: ${a}`,c(u)}L(t.ws,{action:"agent_job_result",jobId:t.id,response:u,error:a,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i}),B(`Finished native CursorBuddy ${n.action} job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`)}async function jr(e,t,{signal:n}){let r=Date.now();B(`Starting job ${t.id}`);let o=Rr(t.prompt);if(o&&Wt(e)){await Fr(e,t,o,r),e.once&&(B("One-shot CursorBuddy control job complete; exiting."),setTimeout(()=>k.exit(0),150));return}let s=Jr(e,t),i=await Gr(e,t),c="",u="",a=0,l=($="")=>{L(t.ws,{action:"agent_job_delta",jobId:t.id,content:$,elapsedMs:Date.now()-r,model:s.model,permissionMode:s.permissionMode,permissionFlags:s.permissionFlags})};l("");let m=s.streamJson?Kr():null,_=setInterval(()=>l(c),1e3);_.unref&&_.unref();let b=!/[\\/]/.test(s.cmd),h=e.fastConnection&&b?Qt(s.cmd)?"claude":Zt(s.cmd)?"codex":null:null,w=await ot(t,{family:h}).run({cmd:s.cmd,args:[...s.args,i],env:s.env,cwd:t.cwd||e.cwd,timeoutMs:e.timeoutMs,heartbeatMs:e.heartbeatMs,label:"agent job",signal:n,job:t,prompt:i,model:s.model,permissionMode:s.permissionMode,hostFolders:Xt(e,t),leanCli:e.leanCli,mcp:e.leanCli?Le(e):null,sessionKey:`${t.workspaceId||e.workspace||""}:${e.agent||e.handle||""}`,clientVersion:Z,onData:$=>{m?(m.feed($),c=m.live):(c+=String($||""),u=Zr(`${u}
36
+ ${$}`));let P=Date.now();P-a>150&&(a=P,l(c))}});clearInterval(_),m&&(m.end(),c=m.live,l(c));let S=String(w.stdout||"").trim(),E=String(w.stderr||"").trim(),I=w.error?w.error.message:w.status===0?"":E||`Command exited with status ${w.status}`,x=m?m.result||(I?"":E):S||(I?"":E)||u||"";L(t.ws,{action:"agent_job_result",jobId:t.id,response:x,error:I,elapsedMs:Date.now()-r,model:s.model,permissionMode:s.permissionMode,permissionFlags:s.permissionFlags}),B(`Finished job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`),e.once&&(B("One-shot job complete; exiting."),setTimeout(()=>k.exit(0),150))}async function Gr(e,t){let n=t.agent||{},r=Array.isArray(n.skills)?n.skills.join(", "):String(n.skills||""),o=Array.isArray(n.tools)?n.tools.join(", "):String(n.tools||""),s=qt(e,t),i=zt(e,t),c=await Ut(e).catch(()=>null),u=c?`Heartbeat (recurring instructions \u2014 edit at ${$t(e)}):
37
+ ${c}`:"",l=["You are running as a local agensis workspace agent daemon.",`Workspace: ${t.workspaceId||e.workspace}`,`Channel session: ${t.sessionId||""}`,`Agent: ${n.name||e.name} (@${n.handle||e.handle})`,`Requested model: ${s}`,`Permission mode: ${i}`,n.description?`Description:
30
38
  ${n.description}`:"",n.soul?`Soul:
31
39
  ${n.soul}`:"",n.system_prompt?`System instructions:
32
40
  ${n.system_prompt}`:"",n.instructions?`Additional instructions:
33
41
  ${n.instructions}`:"",o?`Enabled tools:
34
42
  ${o}`:"",r?`Enabled skills:
35
- ${r}`:"",'Thread widgets: this chat has a right-side widget rail the human watches. When you work a multi-step task here, surface it: call create_thread_item (kind "todo", "plan", or "blocker") with the Channel session id above to post your plan steps and to-dos, mark them done with update_thread_item as you finish, and raise a "blocker" when you need the human to answer something (read their reply from the item response via list_thread_items). Keep it to a few real items, not every micro-step; skip it for quick one-off replies.',`Status file: you can report your own working status by overwriting the JSON file at ${_t(e)} with e.g. {"status":"working","note":"short summary of what you're doing"}. Your daemon reads it on its next heartbeat (~${Math.round((e.heartbeatMs||15e3)/1e3)}s) and surfaces it on your agent card. Optional and best-effort \u2014 overwrite the whole file, keep note under ~200 chars, and there's no need to clear it.`,d,"Identity boundary: answer as the workspace agent named above. Do not adopt the identity of any browser, desktop, avatar, pet, widget, or UI surface.","Respond with a clear channel-ready result. Use markdown for structure \u2014 bullets, headers, and code blocks where appropriate. If you changed files, summarize the files and verification. If you cannot complete it, say exactly why.","User message:",String(t.prompt||"")].filter(Boolean).join(`
43
+ ${r}`:"",'Thread widgets: this chat has a right-side widget rail the human watches. When you work a multi-step task here, surface it: call create_thread_item (kind "todo", "plan", or "blocker") with the Channel session id above to post your plan steps and to-dos, mark them done with update_thread_item as you finish, and raise a "blocker" when you need the human to answer something (read their reply from the item response via list_thread_items). Keep it to a few real items, not every micro-step; skip it for quick one-off replies.',`Status file: you can report your own working status by overwriting the JSON file at ${Bt(e)} with e.g. {"status":"working","note":"short summary of what you're doing"}. Your daemon reads it on its next heartbeat (~${Math.round((e.heartbeatMs||15e3)/1e3)}s) and surfaces it on your agent card. Optional and best-effort \u2014 overwrite the whole file, keep note under ~200 chars, and there's no need to clear it.`,u,"User message:",String(t.prompt||""),"Identity boundary: answer as the workspace agent named above. Do not adopt the identity of any browser, desktop, avatar, pet, widget, or UI surface.","Respond with a clear channel-ready result. Use markdown for structure \u2014 bullets, headers, and code blocks where appropriate. If you changed files, summarize the files and verification. If you cannot complete it, say exactly why."].filter(Boolean).join(`
44
+
45
+ `);return e.leanCli?Hr(l,kr):l}function Hr(e,t){let n=String(e||"");if(Buffer.byteLength(n,"utf8")<=t)return n;let r=`[... older or optional Agensis context omitted ...]
36
46
 
37
- `)}function yr(e,t){let{cmd:n,args:r}=xr(e.codingCmd),o=Rt(e,t),s=Pt(e,t),i=Ir(r),a=Pe(s),d=wr(e,t);if(Ar(n)){let u=[...i];if(o&&u.push("--model",o),s==="accept_edits"&&u.push("--permission-mode","acceptEdits"),s==="yolo"){let h=t&&t.agent&&t.agent.run_mode==="sandbox",x=typeof w.getuid=="function"&&w.getuid()===0,$=h||br(),b=w.env.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1";$||!x||b?u.push("--dangerously-skip-permissions"):(a=[],B("running as root with no sandbox detected: dropping --dangerously-skip-permissions (Claude rejects it as root). Set AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS=1 if this host really is sandboxed."))}let m=i.some(h=>h==="--output-format"||String(h).startsWith("--output-format=")),g=i.includes("-p")||i.includes("--print"),_=!1;!m&&g?(u.push("--output-format","stream-json","--include-partial-messages"),i.includes("--verbose")||u.push("--verbose"),_=!0):m&&(_=i.some(h=>/stream-json/.test(String(h))));for(let h of d)u.push("--add-dir",h);return{cmd:n,args:u,model:o,permissionMode:s,permissionFlags:a,streamJson:_}}if(Cr(n)){let u=[...i];return o&&u.push("--model",o),s==="yolo"&&u.push("--sandbox","danger-full-access","--ask-for-approval","never"),{cmd:n,args:u,model:o,permissionMode:s,permissionFlags:a}}return{cmd:n,args:r,model:o,permissionMode:s,permissionFlags:a}}function Sr(){let e="",t="",n=!1,r="",o=null,s=a=>{if(!a||typeof a!="object")return;let d=a.event&&a.event.delta||a.delta;if(d&&d.type==="text_delta"&&typeof d.text=="string"){n=!0,t+=d.text;return}if(a.type==="result"&&typeof a.result=="string"){o=a.result;return}if(a.type==="assistant"&&a.message&&Array.isArray(a.message.content)){let u=a.message.content.filter(m=>m&&m.type==="text"&&typeof m.text=="string").map(m=>m.text).join("");u&&(r+=u)}},i=a=>{let d=String(a).trim();if(d)try{s(JSON.parse(d))}catch{}};return{feed(a){e+=String(a||"");let d;for(;(d=e.indexOf(`
38
- `))>=0;)i(e.slice(0,d)),e=e.slice(d+1)},end(){e&&(i(e),e="")},get live(){return n?t:r},get result(){return o??(n?t:r)}}}function Rt(e,t){return Re(t?.agent?.model||t?.model||e.model)}function Re(e){let t=String(e||"").trim();return!t||t==="auto"||t==="claude-fable-5"?Zn:t}function Pt(e,t){return we(t?.agent?.permissionMode||t?.agent?.permission_mode||t?.permissionMode||t?.permission_mode||e.permissionMode)}function we(e){let t=String(e||"").trim().toLowerCase().replace(/[-\s]+/g,"_");return["yolo","no_sandbox","danger","danger_full_access","dangerously_skip_permissions"].includes(t)?"yolo":["accept_edits","acceptedits","auto_approve","auto_approve_edits"].includes(t)?"accept_edits":"default"}function Pe(e){return we(e)==="yolo"?["--no-sandbox","--yolo"]:[]}function Lt(e){let t=Array.isArray(e)?e:String(e||"").split(/[,\n]/),n=new Set,r=[];for(let o of t){let s=String(o||"").trim();!s||n.has(s)||(n.add(s),r.push(s))}return r}function wr(e,t){let n=t?.agent?.metadata?.host_folders??t?.agent?.hostFolders??t?.hostFolders??t?.host_folders,r=Lt(n);return r.length>0?r:e.hostFolders||[]}var Q;function br(){if(Q!==void 0)return Q;let e=w.env;if(e.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1"||e.AGENSIS_SANDBOX_HOST==="1"||e.IS_SANDBOX==="1")return Q=!0;if(e.AGENSIS_NO_SANDBOX_AUTODETECT==="1")return Q=!1;try{if(ue.existsSync("/.dockerenv")||ue.existsSync("/run/.containerenv"))return Q=!0}catch{}try{let t=ue.readFileSync("/proc/1/cgroup","utf8");if(/docker|kubepods|containerd|lxc|podman/i.test(t))return Q=!0}catch{}return Q=!1}function Te(e,t,n,r=null,o=null){let s={busy:t.active()>0,queueSize:t.size(),cwd:e.cwd,model:e.model,permissionMode:e.permissionMode,permissionFlags:Pe(e.permissionMode),daemon:{runtime:"agensis-cli",version:oe,pid:w.pid,node:w.version,platform:w.platform,arch:w.arch,host:le.hostname(),cwd:e.cwd}};if(o instanceof Map){let i={};for(let a of o.values()){let d=String(a?.model||"");d&&(i[d]=(i[d]||0)+1)}s.activeInferenceByModel=i}return r&&typeof r=="object"&&(s.cursorBuddy=_r(r)),n?.status&&(s.agentStatus=n.status),n?.note&&(s.agentNote=n.note),(n?.status||n?.note)&&(s.agentStatusAt=new Date().toISOString()),s}function _r(e={}){let t=e.client&&typeof e.client=="object"?e.client:{},n=e.page&&typeof e.page=="object"?e.page:{},r=e.runtime&&typeof e.runtime=="object"?e.runtime:{},o=e.manifest&&typeof e.manifest=="object"?e.manifest:{},s=e.project&&typeof e.project=="object"?e.project:{};return{surface:String(e.surface||"").slice(0,80),instanceId:String(e.instanceId||"").slice(0,140),url:String(e.url||"").slice(0,2048),title:String(e.title||"").slice(0,300),origin:String(n.origin||"").slice(0,300),hostname:String(n.hostname||"").slice(0,200),pathname:String(n.pathname||"").slice(0,500),visibilityState:String(n.visibilityState||"").slice(0,40),focused:n.focused===!0,userAgent:String(t.userAgent||"").slice(0,500),platform:String(t.platform||"").slice(0,120),language:String(t.language||"").slice(0,80),viewport:t.viewport&&typeof t.viewport=="object"?{width:Number(t.viewport.width)||0,height:Number(t.viewport.height)||0,devicePixelRatio:Number(t.viewport.devicePixelRatio)||0}:null,runtimeMarker:String(r.marker||"").slice(0,120),extensionMarker:String(r.extensionMarker||"").slice(0,120),manifest:{name:String(o.name||"").slice(0,120),version:String(o.version||"").slice(0,80),source:String(o.source||"").slice(0,500)},project:{name:String(s.name||"").slice(0,120),root:String(s.root||"").slice(0,500),agent:String(s.agent||"").slice(0,80)},updatedAt:String(e.updatedAt||"").slice(0,80)}}function Ot(e,t){if(!t||typeof t!="object")return;t.name&&(e.name=String(t.name).trim()||e.name),(t.handle||t.name)&&(e.handle=Ft(t.handle||t.name||e.handle)),t.model&&(e.model=Re(t.model));let n=t.permissionMode||t.permission_mode;n&&(e.permissionMode=we(n)),(t.memory_dir!==void 0||t.memoryDir!==void 0)&&(e.memoryDir=String(t.memory_dir??t.memoryDir??"").trim())}function kr(){let e=["claude","codex","gh","node","npm","python3","git","fly","vercel"],t=(w.env.PATH||"").split(de.delimiter).filter(Boolean);return e.filter(n=>t.some(r=>{try{return ue.existsSync(de.join(r,n))}catch{return!1}}))}function vr(){try{let e=ue.readFileSync(de.join(le.homedir(),".claude.json"),"utf8"),n=JSON.parse(e)?.mcpServers;if(n&&typeof n=="object")return Object.keys(n).sort()}catch{}return[]}function Nt(e){return Xn.createHash("sha1").update(String(e)).digest("hex").slice(0,16)}async function Ut(e,t=null){let n=lt({cwd:e.cwd}),r=dt({cwd:e.cwd}),o=kr(),s=vr(),i=Ae({cwd:e.cwd,memoryDir:e.memoryDir})||null,a=pt(e.sharedModels),d=Nt(JSON.stringify({skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:a,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null})),u=Nt(await it(i));return{skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:a,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null,capabilitiesHash:d,memoryHash:u}}async function ae(e,t,n=null){try{let r=await Ut(t,n);D(e,{action:"agent_capabilities_sync",workspaceId:t.workspace,agentId:t.agent,skills:r.skills,commands:r.commands,clis:r.clis,mcpServers:r.mcpServers,sharedModels:r.sharedModels,codingRoute:r.codingRoute,shared:r.shared,memoryRoot:r.memoryRoot,reach:r.reach||void 0,hash:r.capabilitiesHash,memoryHash:r.memoryHash}),B(`Capabilities synced \u2014 skills:${r.skills.length} commands:${r.commands.length} clis:${r.clis.length} mcp:${r.mcpServers.length}`)}catch(r){B(`Capabilities sync skipped: ${r?.message||r}`)}}function Er(e){let t=le.networkInterfaces(),n=[];for(let r of Object.values(t))for(let o of r||[])o.family==="IPv4"&&!o.internal&&n.push({host:o.address,port:e,scope:"lan"});return n.slice(0,4)}async function Bt(e,t){try{let n=Ae({cwd:t.cwd,memoryDir:t.memoryDir});if(!n)return;let r=await at(n);D(e,{action:"agent_memory_sync",workspaceId:t.workspace,agentId:t.agent,root:n,files:r}),B(`Synced ${r.length} memory file${r.length===1?"":"s"} from ${n}`)}catch(n){B(`Memory sync skipped: ${n?.message||n}`)}}function Ir(e){let t=new Set(["--model","-m","--permission-mode","--sandbox","--ask-for-approval","--approval-policy"]),n=new Set(["--dangerously-skip-permissions","--no-sandbox","--yolo","--accept-edits"]),r=[];for(let o=0;o<e.length;o+=1){let s=e[o],[i]=String(s).split("=",1);if(!n.has(s)){if(t.has(i)){String(s).includes("=")||(o+=1);continue}r.push(s)}}return r}function Ar(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function Cr(e){return/(^|\/)codex(?:$|\.)/.test(String(e||""))}function xr(e){let t=[],n="",r="",o=!1;for(let s of e){if(o){n+=s,o=!1;continue}if(s==="\\"){o=!0;continue}if(r){s===r?r="":n+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){n&&(t.push(n),n="");continue}n+=s}if(n&&t.push(n),!t.length)throw new Error("coding command is empty");return{cmd:t[0],args:t.slice(1)}}function De(e){try{return JSON.parse(String(e))}catch{return null}}function D(e,t){return!e||e.readyState!==ce.OPEN?!1:(e.send(JSON.stringify(t)),!0)}function Mr(e){return String(e||"").split(/\r?\n/).map(t=>t.trim()).filter(Boolean).slice(-1)[0]||""}function Ft(e){return String(e||"").trim().toLowerCase().replace(/^@+/,"").replace(/[^a-z0-9_.-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function Or(e){return e?.code==="EADDRINUSE"||/\bEADDRINUSE\b/.test(String(e?.message||e))}async function Nr(e){let t=new AbortController,n=setTimeout(()=>t.abort(),700);try{let r=await fetch(`http://127.0.0.1:${Number(e||8787)}/cursorbuddy/health`,{cache:"no-store",signal:t.signal}),o=await r.json().catch(()=>({}));return!r.ok||!o?.ok?null:o}catch{return null}finally{clearTimeout(n)}}function B(e){w.stderr.write(`[agensis] ${e}
39
- `)}function $t(e){if(e instanceof Map)for(let t of e.values())try{t?.abort?.()}catch{}}import Br from"node:crypto";import me from"node:fs/promises";import $r from"node:os";import jt from"node:path";var Z="default",Tr=/^[a-zA-Z0-9_.-]{1,64}$/,Dr=["url","token","workspace","agent","handle","name","cwd","codingCmd","model","permissionMode","timeoutMs","heartbeatMs","maxConcurrency","share","sharedModelsFile","noCoding","lanListener","primaryDaemon","cursorBuddyBridge","cursorBuddyPort","hostFolders"];function z(e=Z){let t=String(e||Z).trim();if(!Tr.test(t))throw new Error("Daemon profile names may only contain letters, numbers, dot, dash, and underscore.");return t}function Gt(e=Z,t={}){let n=t.homedir||$r.homedir();return jt.join(n,".agensis","daemon-profiles",`${z(e)}.json`)}function Le(e={}){let t={};for(let n of Dr){let r=e[n];r!=null&&r!==""&&(t[n]=r)}return t}function V(e,t,n=[]){for(let r of t)if(String(e?.[r]||"").trim())return!0;for(let r of n)if(String(process.env[r]||"").trim())return!0;return!1}function Ht(e={}){return!!(V(e,["url","baseUrl"],["AGENSIS_URL"])||V(e,["token"],["AGENSIS_TOKEN"])||V(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])||V(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}function Ue(e={}){return!!(V(e,["url","baseUrl"],["AGENSIS_URL"])&&V(e,["token"],["AGENSIS_TOKEN"])&&V(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])&&V(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}async function Jt(e=Z,t={}){let n=Gt(e,t),r;try{r=await me.readFile(n,"utf8")}catch(i){if(i?.code==="ENOENT")return null;throw i}let o;try{o=JSON.parse(r)}catch(i){throw new Error(`Daemon profile "${z(e)}" is unreadable: ${i?.message||i}`)}let s=o?.config;return!s?.url||!s?.token||!s?.workspace||!s?.agent?null:Le(s)}async function be(e=Z,t={},n={}){let r=Le(t);if(!r.url||!r.token||!r.workspace||!r.agent)return null;let o=Gt(e,n),s=jt.dirname(o);await me.mkdir(s,{recursive:!0,mode:448});let i=`${o}.${process.pid}.${Date.now()}.tmp`,a={version:1,savedAt:new Date().toISOString(),profile:z(e),tokenHash:Br.createHash("sha256").update(r.token).digest("hex"),config:r};return await me.writeFile(i,`${JSON.stringify(a,null,2)}
40
- `,{mode:384}),await me.rename(i,o),await me.chmod(o,384).catch(()=>{}),o}function Wt(e,t={}){let n={...e,...Le(t),command:"connect"};return t.codingCmd!==void 0&&t.noCoding===void 0&&(n.noCoding=!1),t.cursorBuddyBridge===void 0&&!n.primaryDaemon&&(n.cursorBuddyBridge=!1),t.once!==void 0&&(n.once=t.once),t.exitOnOnce!==void 0&&(n.exitOnOnce=t.exitOnOnce),n}function Kt(e=Z){let t=z(e);return[`No saved Agensis daemon profile found for "${t}".`,"","To connect the main agent once:","1. Run: agensis setup","2. Sign in or create an account in the browser.","3. Approve this machine as your primary local agent.","","Manual fallback: open Agensis > AI Agents, copy a connection command,","and run that full agensis connect command from the repo folder.","","After the daemon registers successfully, this CLI saves the profile locally.",`Then restart it with: agensis connect${t===Z?"":` --profile ${t}`}`].join(`
41
- `)}import Rr from"node:crypto";import fe from"node:fs/promises";import zt from"node:os";import Fe from"node:path";import je from"node:process";var Pr=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/;function Lr(e={}){return String(e.url||e.baseUrl||je.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function qt(e,t={}){let n=t.homedir||zt.homedir(),r=Rr.createHash("sha256").update(String(e)).digest("hex");return Fe.join(n,".agensis","cursorbuddy","connection-keys",`${r}.json`)}function Ur(){return new Error("Missing or invalid --key. Create a CursorBuddy connection key in Agensis first.")}function Ge(e){let t=String(e||"").trim();if(!Pr.test(t))throw Ur();return t}function Fr(e,t,n,r){let o=t?.token,s=t?.workspaceId||t?.workspace_id||t?.agent?.workspace_id,i=t?.agentId||t?.agent?.id;if(!o||!s||!i)throw new Error("CursorBuddy key claim did not return a complete daemon connection payload");let{key:a,subcommand:d,...u}=e;return{...u,command:"connect",url:t.baseUrl||n,token:o,workspace:s,agent:i,handle:t.handle||e.handle,name:t.agent?.name||e.name||"CursorBuddy runtime",model:t.model||e.model,permissionMode:t.permissionMode||t.permission_mode||e.permissionMode,cwd:e.cwd||r,cursorBuddyRuntime:!0}}async function jr(e,t={}){Ge(e);let n=qt(e,t),r;try{r=await fe.readFile(n,"utf8")}catch(i){if(i?.code==="ENOENT")return null;throw i}let o;try{o=JSON.parse(r)}catch(i){throw new Error(`Cached CursorBuddy daemon config is unreadable: ${i?.message||i}`)}let s=o?.daemonArgs;return!s?.token||!s?.workspace||!s?.agent||!s?.url?null:s}async function Gr(e,t,n={}){if(Ge(e),!t?.token||!t?.workspace||!t?.agent||!t?.url)return;let r=qt(e,n),o=Fe.dirname(r);await fe.mkdir(o,{recursive:!0,mode:448});let s=`${r}.${je.pid}.${Date.now()}.tmp`,i={version:1,savedAt:new Date().toISOString(),keyHash:Fe.basename(r,".json"),daemonArgs:t};await fe.writeFile(s,`${JSON.stringify(i,null,2)}
42
- `,{mode:384}),await fe.rename(s,r),await fe.chmod(r,384).catch(()=>{})}function Hr(e,t,n){let r={...e,command:"connect"};for(let o of["cwd","codingCmd","model","permissionMode","timeoutMs","heartbeatMs","maxConcurrency","share","sharedModelsFile","noCoding","lanListener","once"])t[o]!==void 0&&(r[o]=t[o]);return t.codingCmd!==void 0&&t.noCoding===void 0&&(r.noCoding=!1),r.cwd||(r.cwd=n),r.cursorBuddyRuntime=!0,r}function Jr(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function Wr(e){return e.json().catch(()=>({}))}async function Yt(e,t={}){let n=Ge(e?.key),r=Lr(e),o=t.fetchImpl||globalThis.fetch;if(typeof o!="function")throw new Error("This Node.js runtime does not provide fetch; use a current Node.js release.");let s=t.cwd||je.cwd(),i=t.hostname||zt.hostname(),a=t.version||oe,d={homedir:t.homedir},u=await o(`${r}/backend/cursorbuddy/connection-keys/claim`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:n,baseUrl:r,host:i,cwd:e.cwd||s,name:e.name,surface:e.surface||"local_cli",scope:e.scope||"machine",runtimeKind:"agensis-cli",version:a,permissionMode:e.permissionMode,model:e.model})}),m=await Wr(u);if(!u.ok){let _=Jr(u,m);if(u.status===409||/already been claimed/i.test(_)){let h=await jr(n,d);if(h)return Hr(h,e,s);throw new Error(`${_}. No cached daemon config was found on this machine; create a new CursorBuddy key in Agensis or run the full copied agensis connect command.`)}throw new Error(_)}let g=Fr(e,m?.data||m,r,s);return await Gr(n,g,d),g}import Kr from"node:crypto";import zr from"node:http";import qr from"node:os";import q from"node:process";import{spawn as Yr}from"node:child_process";var Xr="https://agensis.io",Vr=10*60*1e3;function _e(e,t,n){e.writeHead(t,{"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"content-type"}),e.end(JSON.stringify(n))}function Qr(e){return new Promise((t,n)=>{let r="";e.on("data",o=>{r+=o,r.length>128*1024&&(n(new Error("setup callback body is too large")),e.destroy())}),e.on("error",n),e.on("end",()=>t(r))})}function Zr(e){let t=String(e||q.env.AGENSIS_URL||Xr).trim(),n=new URL(t);if(n.protocol!=="http:"&&n.protocol!=="https:")throw new Error("Agensis setup URL must be http or https.");return n.search="",n.hash="",n.toString().replace(/\/+$/,"")}function eo(e){let t=q.platform==="darwin"?"open":q.platform==="win32"?"cmd":"xdg-open",n=q.platform==="win32"?["/c","start","",e]:[e],r=Yr(t,n,{detached:!0,stdio:"ignore"});r.on("error",()=>{}),r.unref()}function to(e){let t=e?.daemonArgs||e?.data?.daemonArgs||e?.data||{},r=["url","token","workspace","agent"].filter(o=>!String(t[o]||"").trim());if(r.length)throw new Error(`Setup callback did not include ${r.join(", ")}`);return{...t,command:"connect"}}function no(e,t,n){let r=new URL(Zr(e.url||e.baseUrl));return r.searchParams.set("source","agensis-cli"),r.searchParams.set("referrer","agensis-cli"),r.searchParams.set("intent","setup"),r.searchParams.set("callback",t),r.searchParams.set("state",n),r.searchParams.set("profile",z(e.profile||"default")),r.searchParams.set("host",qr.hostname()),r.searchParams.set("cwd",String(e.cwd||q.cwd())),e.handle&&r.searchParams.set("handle",String(e.handle)),e.name&&r.searchParams.set("name",String(e.name)),r.toString()}async function Xt(e={}){let t=z(e.profile||"default"),n=Kr.randomBytes(24).toString("base64url"),r=Number(e.setupTimeoutMs||q.env.AGENSIS_SETUP_TIMEOUT_MS||Vr),o,s=new Promise((u,m)=>{let g=setTimeout(()=>m(new Error("Agensis setup timed out waiting for browser login.")),r);g.unref&&g.unref(),o=zr.createServer(async(_,h)=>{if(h.setHeader("access-control-allow-origin","*"),h.setHeader("access-control-allow-methods","POST, OPTIONS"),h.setHeader("access-control-allow-headers","content-type"),_.method==="OPTIONS"){h.writeHead(204),h.end();return}if(_.method!=="POST"||_.url!=="/agensis/setup-callback"){_e(h,404,{ok:!1,error:"Unknown Agensis setup callback route"});return}try{let x=JSON.parse(await Qr(_)||"{}");if(x?.state!==n){_e(h,403,{ok:!1,error:"Setup state did not match"});return}let $={...to(x),primaryDaemon:!0,cursorBuddyBridge:e.cursorBuddyBridge!==!1};await be(t,$),clearTimeout(g),_e(h,200,{ok:!0,profile:t}),u($)}catch(x){_e(h,400,{ok:!1,error:String(x?.message||x)})}}),o.once("error",m)});await new Promise((u,m)=>{o.listen(0,"127.0.0.1",g=>g?m(g):u())});let{port:i}=o.address(),a=`http://127.0.0.1:${i}/agensis/setup-callback`,d=no(e,a,n);q.stdout.write(`[agensis] Opening Agensis to sign in and connect this machine.
43
- `),q.stdout.write(`[agensis] If the browser did not open, visit:
44
- ${d}
45
- `),eo(d);try{let u=await s;return q.stdout.write(`[agensis] Saved daemon profile "${t}". Starting primary agent daemon.
46
- `),u}finally{await new Promise(u=>o.close(()=>u())).catch(()=>{})}}function ro(e){let t={command:"connect"},n=[...e],r=n[0];if(r&&!r.startsWith("-")&&(t.command=n.shift(),t.command==="buddy")){let o=n[0];o&&!o.startsWith("-")?t.subcommand=n.shift():t.subcommand="connect"}for(let o=0;o<n.length;o+=1){let s=n[o];if(!s.startsWith("--"))throw new Error(`Unexpected argument: ${s}`);let[i,a]=s.slice(2).split(/=(.*)/s,2),d=i.replace(/-([a-z])/g,(m,g)=>g.toUpperCase());if(d==="help"){t.help=!0;continue}if(d==="version"){t.version=!0;continue}if(d==="once"){t.once=!0;continue}if(d==="lan"){t.lanListener=!0;continue}if(d==="share"){t.share=!0;continue}if(d==="noCoding"){t.noCoding=!0;continue}if(d==="cursorbuddyBridge"){t.cursorBuddyBridge=!0;continue}if(d==="noCursorbuddyBridge"){t.cursorBuddyBridge=!1;continue}if(d==="yolo"||d==="noSandbox"){t.permissionMode="yolo";continue}if(d==="acceptEdits"){t.permissionMode="accept_edits";continue}if(d==="hostFolder"||d==="hostFolders"||d==="addDir"){let m=a!==void 0?a:n[++o];if(m==null||m.startsWith("--"))throw new Error(`Missing value for --${i}`);t.hostFolders=[...t.hostFolders||[],m];continue}let u=a!==void 0?a:n[++o];if(u==null||u.startsWith("--"))throw new Error(`Missing value for --${i}`);t[d]=u}return t}function oo(){return`agensis agent daemon
47
+ `,o=Math.max(0,t-Buffer.byteLength(r,"utf8")),s=[...n],i=0,c=s.length;for(;i<c;){let u=Math.ceil((i+c)/2),a=s.slice(s.length-u).join("");Buffer.byteLength(a,"utf8")<=o?i=u:c=u-1}return r+s.slice(s.length-i).join("")}function Jr(e,t){let{cmd:n,args:r}=Qr(e.codingCmd),o=qt(e,t),s=zt(e,t),i=Vr(r),c=je(s),u=Xt(e,t);if(Qt(n)){let a=[...i];o&&a.push("--model",o);let l;if(e.leanCli){let h=Le(e);a.push("--no-session-persistence","--safe-mode","--mcp-config",JSON.stringify({mcpServers:{agensis:{type:"http",url:h.url,headers:{Authorization:"Bearer ${AGENSIS_MCP_TOKEN}"}}}}),"--strict-mcp-config"),l=h.env}if(s==="accept_edits"&&a.push("--permission-mode","acceptEdits"),s==="yolo"){let h=t&&t.agent&&t.agent.run_mode==="sandbox",M=typeof k.getuid=="function"&&k.getuid()===0,w=h||Wr(),S=k.env.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1";w||!M||S?a.push("--dangerously-skip-permissions"):(c=[],B("running as root with no sandbox detected: dropping --dangerously-skip-permissions (Claude rejects it as root). Set AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS=1 if this host really is sandboxed."))}let m=i.some(h=>h==="--output-format"||String(h).startsWith("--output-format=")),_=i.includes("-p")||i.includes("--print"),b=!1;!m&&_?(a.push("--output-format","stream-json","--include-partial-messages"),i.includes("--verbose")||a.push("--verbose"),b=!0):m&&(b=i.some(h=>/stream-json/.test(String(h))));for(let h of u)a.push("--add-dir",h);return{cmd:n,args:a,model:o,permissionMode:s,permissionFlags:c,streamJson:b,env:l}}if(Zt(n)){let a=[...i];o&&a.push("--model",o);let l;if(e.leanCli&&i.includes("exec")){let m=Le(e);a.push("--ephemeral","--ignore-user-config","--ignore-rules","--disable","plugins","--disable","memories","--disable","hooks","--disable","skill_search","-c","project_doc_max_bytes=0","-c",`mcp_servers.agensis.url=${JSON.stringify(m.url)}`,"-c",'mcp_servers.agensis.bearer_token_env_var="AGENSIS_MCP_TOKEN"'),l=m.env}return s==="yolo"&&a.push("--sandbox","danger-full-access","--ask-for-approval","never"),{cmd:n,args:a,model:o,permissionMode:s,permissionFlags:c,env:l}}return{cmd:n,args:r,model:o,permissionMode:s,permissionFlags:c}}function Le(e){let t=Ue(e.url);return t.pathname="/backend/mcp",t.search="",t.hash="",{url:t.toString(),env:{AGENSIS_MCP_TOKEN:e.token}}}function Kr(){let e="",t="",n=!1,r="",o=null,s=c=>{if(!c||typeof c!="object")return;let u=c.event&&c.event.delta||c.delta;if(u&&u.type==="text_delta"&&typeof u.text=="string"){n=!0,t+=u.text;return}if(c.type==="result"&&typeof c.result=="string"){o=c.result;return}if(c.type==="assistant"&&c.message&&Array.isArray(c.message.content)){let a=c.message.content.filter(l=>l&&l.type==="text"&&typeof l.text=="string").map(l=>l.text).join("");a&&(r+=a)}},i=c=>{let u=String(c).trim();if(u)try{s(JSON.parse(u))}catch{}};return{feed(c){e+=String(c||"");let u;for(;(u=e.indexOf(`
48
+ `))>=0;)i(e.slice(0,u)),e=e.slice(u+1)},end(){e&&(i(e),e="")},get live(){return n?t:r},get result(){return o??(n?t:r)}}}function qt(e,t){return Fe(t?.agent?.model||t?.model||e.model)}function Fe(e){let t=String(e||"").trim();return!t||t==="auto"||t==="claude-fable-5"?Cr:t}function zt(e,t){return be(t?.agent?.permissionMode||t?.agent?.permission_mode||t?.permissionMode||t?.permission_mode||e.permissionMode)}function be(e){let t=String(e||"").trim().toLowerCase().replace(/[-\s]+/g,"_");return["yolo","no_sandbox","danger","danger_full_access","dangerously_skip_permissions"].includes(t)?"yolo":["accept_edits","acceptedits","auto_approve","auto_approve_edits"].includes(t)?"accept_edits":"default"}function je(e){return be(e)==="yolo"?["--no-sandbox","--yolo"]:[]}function Yt(e){let t=Array.isArray(e)?e:String(e||"").split(/[,\n]/),n=new Set,r=[];for(let o of t){let s=String(o||"").trim();!s||n.has(s)||(n.add(s),r.push(s))}return r}function Xt(e,t){let n=t?.agent?.metadata?.host_folders??t?.agent?.hostFolders??t?.hostFolders??t?.host_folders,r=Yt(n);return r.length>0?r:e.hostFolders||[]}var Q;function Wr(){if(Q!==void 0)return Q;let e=k.env;if(e.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1"||e.AGENSIS_SANDBOX_HOST==="1"||e.IS_SANDBOX==="1")return Q=!0;if(e.AGENSIS_NO_SANDBOX_AUTODETECT==="1")return Q=!1;try{if(le.existsSync("/.dockerenv")||le.existsSync("/run/.containerenv"))return Q=!0}catch{}try{let t=le.readFileSync("/proc/1/cgroup","utf8");if(/docker|kubepods|containerd|lxc|podman/i.test(t))return Q=!0}catch{}return Q=!1}function Pe(e,t,n,r=null,o=null){let s={busy:t.active()>0,queueSize:t.size(),cwd:e.cwd,model:e.model,permissionMode:e.permissionMode,permissionFlags:je(e.permissionMode),daemon:{runtime:"agensis-cli",version:Z,pid:k.pid,node:k.version,platform:k.platform,arch:k.arch,host:me.hostname(),cwd:e.cwd}};if(o instanceof Map){let i={};for(let c of o.values()){let u=String(c?.model||"");u&&(i[u]=(i[u]||0)+1)}s.activeInferenceByModel=i}return r&&typeof r=="object"&&(s.cursorBuddy=qr(r)),n?.status&&(s.agentStatus=n.status),n?.note&&(s.agentNote=n.note),(n?.status||n?.note)&&(s.agentStatusAt=new Date().toISOString()),s}function qr(e={}){let t=e.client&&typeof e.client=="object"?e.client:{},n=e.page&&typeof e.page=="object"?e.page:{},r=e.runtime&&typeof e.runtime=="object"?e.runtime:{},o=e.manifest&&typeof e.manifest=="object"?e.manifest:{},s=e.project&&typeof e.project=="object"?e.project:{};return{surface:String(e.surface||"").slice(0,80),instanceId:String(e.instanceId||"").slice(0,140),url:String(e.url||"").slice(0,2048),title:String(e.title||"").slice(0,300),origin:String(n.origin||"").slice(0,300),hostname:String(n.hostname||"").slice(0,200),pathname:String(n.pathname||"").slice(0,500),visibilityState:String(n.visibilityState||"").slice(0,40),focused:n.focused===!0,userAgent:String(t.userAgent||"").slice(0,500),platform:String(t.platform||"").slice(0,120),language:String(t.language||"").slice(0,80),viewport:t.viewport&&typeof t.viewport=="object"?{width:Number(t.viewport.width)||0,height:Number(t.viewport.height)||0,devicePixelRatio:Number(t.viewport.devicePixelRatio)||0}:null,runtimeMarker:String(r.marker||"").slice(0,120),extensionMarker:String(r.extensionMarker||"").slice(0,120),manifest:{name:String(o.name||"").slice(0,120),version:String(o.version||"").slice(0,80),source:String(o.source||"").slice(0,500)},project:{name:String(s.name||"").slice(0,120),root:String(s.root||"").slice(0,500),agent:String(s.agent||"").slice(0,80)},updatedAt:String(e.updatedAt||"").slice(0,80)}}function Gt(e,t){if(!t||typeof t!="object")return;t.name&&(e.name=String(t.name).trim()||e.name),(t.handle||t.name)&&(e.handle=en(t.handle||t.name||e.handle)),t.model&&(e.model=Fe(t.model));let n=t.permissionMode||t.permission_mode;n&&(e.permissionMode=be(n)),(t.memory_dir!==void 0||t.memoryDir!==void 0)&&(e.memoryDir=String(t.memory_dir??t.memoryDir??"").trim())}function zr(){let e=["claude","codex","gh","node","npm","python3","git","fly","vercel"],t=(k.env.PATH||"").split(de.delimiter).filter(Boolean);return e.filter(n=>t.some(r=>{try{return le.existsSync(de.join(r,n))}catch{return!1}}))}function Yr(){try{let e=le.readFileSync(de.join(me.homedir(),".claude.json"),"utf8"),n=JSON.parse(e)?.mcpServers;if(n&&typeof n=="object")return Object.keys(n).sort()}catch{}return[]}function Ht(e){return _r.createHash("sha1").update(String(e)).digest("hex").slice(0,16)}async function Vt(e,t=null){let n=Et({cwd:e.cwd}),r=vt({cwd:e.cwd}),o=zr(),s=Yr(),i=e.syncMemory&&xe({cwd:e.cwd,memoryDir:e.memoryDir})||null,c=It(e.sharedModels),u=Ht(JSON.stringify({skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:c,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null})),a=Ht(await St(i));return{skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:c,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null,capabilitiesHash:u,memoryHash:a}}async function ce(e,t,n=null){try{let r=await Vt(t,n);L(e,{action:"agent_capabilities_sync",workspaceId:t.workspace,agentId:t.agent,skills:r.skills,commands:r.commands,clis:r.clis,mcpServers:r.mcpServers,sharedModels:r.sharedModels,codingRoute:r.codingRoute,shared:r.shared,memoryRoot:r.memoryRoot,reach:r.reach||void 0,hash:r.capabilitiesHash,memoryHash:r.memoryHash}),B(`Capabilities synced \u2014 skills:${r.skills.length} commands:${r.commands.length} clis:${r.clis.length} mcp:${r.mcpServers.length}`)}catch(r){B(`Capabilities sync skipped: ${r?.message||r}`)}}function Xr(e){let t=me.networkInterfaces(),n=[];for(let r of Object.values(t))for(let o of r||[])o.family==="IPv4"&&!o.internal&&n.push({host:o.address,port:e,scope:"lan"});return n.slice(0,4)}async function Jt(e,t){try{if(!t.syncMemory)return;let n=xe({cwd:t.cwd,memoryDir:t.memoryDir});if(!n)return;let r=await wt(n);L(e,{action:"agent_memory_sync",workspaceId:t.workspace,agentId:t.agent,root:n,files:r}),B(`Synced ${r.length} memory file${r.length===1?"":"s"} from ${n}`)}catch(n){B(`Memory sync skipped: ${n?.message||n}`)}}function Vr(e){let t=new Set(["--model","-m","--permission-mode","--sandbox","--ask-for-approval","--approval-policy"]),n=new Set(["--dangerously-skip-permissions","--no-sandbox","--yolo","--accept-edits"]),r=[];for(let o=0;o<e.length;o+=1){let s=e[o],[i]=String(s).split("=",1);if(!n.has(s)){if(t.has(i)){String(s).includes("=")||(o+=1);continue}r.push(s)}}return r}function Qt(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function Zt(e){return/(^|\/)codex(?:$|\.)/.test(String(e||""))}function Qr(e){let t=[],n="",r="",o=!1;for(let s of e){if(o){n+=s,o=!1;continue}if(s==="\\"){o=!0;continue}if(r){s===r?r="":n+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){n&&(t.push(n),n="");continue}n+=s}if(n&&t.push(n),!t.length)throw new Error("coding command is empty");return{cmd:t[0],args:t.slice(1)}}function Re(e){try{return JSON.parse(String(e))}catch{return null}}function L(e,t){return!e||e.readyState!==ue.OPEN?!1:(e.send(JSON.stringify(t)),!0)}function Zr(e){return String(e||"").split(/\r?\n/).map(t=>t.trim()).filter(Boolean).slice(-1)[0]||""}function en(e){return String(e||"").trim().toLowerCase().replace(/^@+/,"").replace(/[^a-z0-9_.-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function eo(e){return e?.code==="EADDRINUSE"||/\bEADDRINUSE\b/.test(String(e?.message||e))}async function to(e){let t=new AbortController,n=setTimeout(()=>t.abort(),700);try{let r=await fetch(`http://127.0.0.1:${Number(e||8787)}/cursorbuddy/health`,{cache:"no-store",signal:t.signal}),o=await r.json().catch(()=>({}));return!r.ok||!o?.ok?null:o}catch{return null}finally{clearTimeout(n)}}function B(e){k.stderr.write(`[agensis] ${e}
49
+ `)}function Kt(e){if(e instanceof Map)for(let t of e.values())try{t?.abort?.()}catch{}}import no from"node:crypto";import fe from"node:fs/promises";import ro from"node:os";import tn from"node:path";var ee="default",nn=2,oo=/^[a-zA-Z0-9_.-]{1,64}$/,so=["url","token","workspace","agent","handle","name","cwd","codingCmd","model","permissionMode","timeoutMs","heartbeatMs","maxConcurrency","share","sharedModelsFile","noCoding","leanCli","fullCliContext","syncMemory","lanListener","primaryDaemon","cursorBuddyBridge","cursorBuddyPort","hostFolders"];function q(e=ee){let t=String(e||ee).trim();if(!oo.test(t))throw new Error("Daemon profile names may only contain letters, numbers, dot, dash, and underscore.");return t}function rn(e=ee,t={}){let n=t.homedir||ro.homedir();return tn.join(n,".agensis","daemon-profiles",`${q(e)}.json`)}function Ge(e={}){let t={};for(let n of so){let r=e[n];r!=null&&r!==""&&(t[n]=r)}return t}function V(e,t,n=[]){for(let r of t)if(String(e?.[r]||"").trim())return!0;for(let r of n)if(String(process.env[r]||"").trim())return!0;return!1}function on(e={}){return!!(V(e,["url","baseUrl"],["AGENSIS_URL"])||V(e,["token"],["AGENSIS_TOKEN"])||V(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])||V(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}function He(e={}){return!!(V(e,["url","baseUrl"],["AGENSIS_URL"])&&V(e,["token"],["AGENSIS_TOKEN"])&&V(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])&&V(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}async function sn(e=ee,t={}){let n=rn(e,t),r;try{r=await fe.readFile(n,"utf8")}catch(c){if(c?.code==="ENOENT")return null;throw c}let o;try{o=JSON.parse(r)}catch(c){throw new Error(`Daemon profile "${q(e)}" is unreadable: ${c?.message||c}`)}let s=o?.config;if(!s?.url||!s?.token||!s?.workspace||!s?.agent)return null;let i=Ge(s);return Number(o.version||1)<nn&&Number(i.maxConcurrency)===8&&(i.maxConcurrency=2),i}async function _e(e=ee,t={},n={}){let r=Ge(t);if(!r.url||!r.token||!r.workspace||!r.agent)return null;let o=rn(e,n),s=tn.dirname(o);await fe.mkdir(s,{recursive:!0,mode:448});let i=`${o}.${process.pid}.${Date.now()}.tmp`,c={version:nn,savedAt:new Date().toISOString(),profile:q(e),tokenHash:no.createHash("sha256").update(r.token).digest("hex"),config:r};return await fe.writeFile(i,`${JSON.stringify(c,null,2)}
50
+ `,{mode:384}),await fe.rename(i,o),await fe.chmod(o,384).catch(()=>{}),o}function an(e,t={}){let n={...e,...Ge(t),command:"connect"};return t.fullCliContext===!0&&(n.leanCli=!1),t.codingCmd!==void 0&&t.noCoding===void 0&&(n.noCoding=!1),t.cursorBuddyBridge===void 0&&!n.primaryDaemon&&(n.cursorBuddyBridge=!1),t.once!==void 0&&(n.once=t.once),t.exitOnOnce!==void 0&&(n.exitOnOnce=t.exitOnOnce),n}function cn(e=ee){let t=q(e);return[`No saved Agensis daemon profile found for "${t}".`,"","To connect the main agent once:","1. Run: agensis setup","2. Sign in or create an account in the browser.","3. Approve this machine as your primary local agent.","","Manual fallback: open Agensis > AI Agents, copy a connection command,","and run that full agensis connect command from the repo folder.","","After the daemon registers successfully, this CLI saves the profile locally.",`Then restart it with: agensis connect${t===ee?"":` --profile ${t}`}`].join(`
51
+ `)}import io from"node:crypto";import pe from"node:fs/promises";import un from"node:os";import Je from"node:path";import Ke from"node:process";var ao=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/;function co(e={}){return String(e.url||e.baseUrl||Ke.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function ln(e,t={}){let n=t.homedir||un.homedir(),r=io.createHash("sha256").update(String(e)).digest("hex");return Je.join(n,".agensis","cursorbuddy","connection-keys",`${r}.json`)}function uo(){return new Error("Missing or invalid --key. Create a CursorBuddy connection key in Agensis first.")}function We(e){let t=String(e||"").trim();if(!ao.test(t))throw uo();return t}function lo(e,t,n,r){let o=t?.token,s=t?.workspaceId||t?.workspace_id||t?.agent?.workspace_id,i=t?.agentId||t?.agent?.id;if(!o||!s||!i)throw new Error("CursorBuddy key claim did not return a complete daemon connection payload");let{key:c,subcommand:u,...a}=e;return{...a,command:"connect",url:t.baseUrl||n,token:o,workspace:s,agent:i,handle:t.handle||e.handle,name:t.agent?.name||e.name||"CursorBuddy runtime",model:t.model||e.model,permissionMode:t.permissionMode||t.permission_mode||e.permissionMode,cwd:e.cwd||r,cursorBuddyRuntime:!0}}async function mo(e,t={}){We(e);let n=ln(e,t),r;try{r=await pe.readFile(n,"utf8")}catch(i){if(i?.code==="ENOENT")return null;throw i}let o;try{o=JSON.parse(r)}catch(i){throw new Error(`Cached CursorBuddy daemon config is unreadable: ${i?.message||i}`)}let s=o?.daemonArgs;return!s?.token||!s?.workspace||!s?.agent||!s?.url?null:s}async function fo(e,t,n={}){if(We(e),!t?.token||!t?.workspace||!t?.agent||!t?.url)return;let r=ln(e,n),o=Je.dirname(r);await pe.mkdir(o,{recursive:!0,mode:448});let s=`${r}.${Ke.pid}.${Date.now()}.tmp`,i={version:1,savedAt:new Date().toISOString(),keyHash:Je.basename(r,".json"),daemonArgs:t};await pe.writeFile(s,`${JSON.stringify(i,null,2)}
52
+ `,{mode:384}),await pe.rename(s,r),await pe.chmod(r,384).catch(()=>{})}function po(e,t,n){let r={...e,command:"connect"};for(let o of["cwd","codingCmd","model","permissionMode","timeoutMs","heartbeatMs","maxConcurrency","share","sharedModelsFile","noCoding","leanCli","lanListener","once"])t[o]!==void 0&&(r[o]=t[o]);return t.codingCmd!==void 0&&t.noCoding===void 0&&(r.noCoding=!1),r.cwd||(r.cwd=n),r.cursorBuddyRuntime=!0,r}function ho(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function go(e){return e.json().catch(()=>({}))}async function dn(e,t={}){let n=We(e?.key),r=co(e),o=t.fetchImpl||globalThis.fetch;if(typeof o!="function")throw new Error("This Node.js runtime does not provide fetch; use a current Node.js release.");let s=t.cwd||Ke.cwd(),i=t.hostname||un.hostname(),c=t.version||Z,u={homedir:t.homedir},a=await o(`${r}/backend/cursorbuddy/connection-keys/claim`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:n,baseUrl:r,host:i,cwd:e.cwd||s,name:e.name,surface:e.surface||"local_cli",scope:e.scope||"machine",runtimeKind:"agensis-cli",version:c,permissionMode:e.permissionMode,model:e.model})}),l=await go(a);if(!a.ok){let _=ho(a,l);if(a.status===409||/already been claimed/i.test(_)){let b=await mo(n,u);if(b)return po(b,e,s);throw new Error(`${_}. No cached daemon config was found on this machine; create a new CursorBuddy key in Agensis or run the full copied agensis connect command.`)}throw new Error(_)}let m=lo(e,l?.data||l,r,s);return await fo(n,m,u),m}import yo from"node:crypto";import So from"node:http";import wo from"node:os";import z from"node:process";import{spawn as bo}from"node:child_process";var _o="https://agensis.io",vo=10*60*1e3;function ve(e,t,n){e.writeHead(t,{"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"POST, OPTIONS","access-control-allow-headers":"content-type"}),e.end(JSON.stringify(n))}function Eo(e){return new Promise((t,n)=>{let r="";e.on("data",o=>{r+=o,r.length>128*1024&&(n(new Error("setup callback body is too large")),e.destroy())}),e.on("error",n),e.on("end",()=>t(r))})}function ko(e){let t=String(e||z.env.AGENSIS_URL||_o).trim(),n=new URL(t);if(n.protocol!=="http:"&&n.protocol!=="https:")throw new Error("Agensis setup URL must be http or https.");return n.search="",n.hash="",n.toString().replace(/\/+$/,"")}function Co(e){let t=z.platform==="darwin"?"open":z.platform==="win32"?"cmd":"xdg-open",n=z.platform==="win32"?["/c","start","",e]:[e],r=bo(t,n,{detached:!0,stdio:"ignore"});r.on("error",()=>{}),r.unref()}function Io(e){let t=e?.daemonArgs||e?.data?.daemonArgs||e?.data||{},r=["url","token","workspace","agent"].filter(o=>!String(t[o]||"").trim());if(r.length)throw new Error(`Setup callback did not include ${r.join(", ")}`);return{...t,command:"connect"}}function Ao(e,t,n){let r=new URL(ko(e.url||e.baseUrl));return r.searchParams.set("source","agensis-cli"),r.searchParams.set("referrer","agensis-cli"),r.searchParams.set("intent","setup"),r.searchParams.set("callback",t),r.searchParams.set("state",n),r.searchParams.set("profile",q(e.profile||"default")),r.searchParams.set("host",wo.hostname()),r.searchParams.set("cwd",String(e.cwd||z.cwd())),e.handle&&r.searchParams.set("handle",String(e.handle)),e.name&&r.searchParams.set("name",String(e.name)),r.toString()}async function mn(e={}){let t=q(e.profile||"default"),n=yo.randomBytes(24).toString("base64url"),r=Number(e.setupTimeoutMs||z.env.AGENSIS_SETUP_TIMEOUT_MS||vo),o,s=new Promise((a,l)=>{let m=setTimeout(()=>l(new Error("Agensis setup timed out waiting for browser login.")),r);m.unref&&m.unref(),o=So.createServer(async(_,b)=>{if(b.setHeader("access-control-allow-origin","*"),b.setHeader("access-control-allow-methods","POST, OPTIONS"),b.setHeader("access-control-allow-headers","content-type"),_.method==="OPTIONS"){b.writeHead(204),b.end();return}if(_.method!=="POST"||_.url!=="/agensis/setup-callback"){ve(b,404,{ok:!1,error:"Unknown Agensis setup callback route"});return}try{let h=JSON.parse(await Eo(_)||"{}");if(h?.state!==n){ve(b,403,{ok:!1,error:"Setup state did not match"});return}let M={...Io(h),primaryDaemon:!0,cursorBuddyBridge:e.cursorBuddyBridge!==!1};await _e(t,M),clearTimeout(m),ve(b,200,{ok:!0,profile:t}),a(M)}catch(h){ve(b,400,{ok:!1,error:String(h?.message||h)})}}),o.once("error",l)});await new Promise((a,l)=>{o.listen(0,"127.0.0.1",m=>m?l(m):a())});let{port:i}=o.address(),c=`http://127.0.0.1:${i}/agensis/setup-callback`,u=Ao(e,c,n);z.stdout.write(`[agensis] Opening Agensis to sign in and connect this machine.
53
+ `),z.stdout.write(`[agensis] If the browser did not open, visit:
54
+ ${u}
55
+ `),Co(u);try{let a=await s;return z.stdout.write(`[agensis] Saved daemon profile "${t}". Starting primary agent daemon.
56
+ `),a}finally{await new Promise(a=>o.close(()=>a())).catch(()=>{})}}function xo(e){let t={command:"connect"},n=[...e],r=n[0];if(r&&!r.startsWith("-")&&(t.command=n.shift(),t.command==="buddy")){let o=n[0];o&&!o.startsWith("-")?t.subcommand=n.shift():t.subcommand="connect"}for(let o=0;o<n.length;o+=1){let s=n[o];if(!s.startsWith("--"))throw new Error(`Unexpected argument: ${s}`);let[i,c]=s.slice(2).split(/=(.*)/s,2),u=i.replace(/-([a-z])/g,(l,m)=>m.toUpperCase());if(u==="help"){t.help=!0;continue}if(u==="version"){t.version=!0;continue}if(u==="once"){t.once=!0;continue}if(u==="lan"){t.lanListener=!0;continue}if(u==="share"){t.share=!0;continue}if(u==="noCoding"){t.noCoding=!0;continue}if(u==="fullCliContext"){t.fullCliContext=!0;continue}if(u==="syncMemory"){t.syncMemory=!0;continue}if(u==="cursorbuddyBridge"){t.cursorBuddyBridge=!0;continue}if(u==="noCursorbuddyBridge"){t.cursorBuddyBridge=!1;continue}if(u==="yolo"||u==="noSandbox"){t.permissionMode="yolo";continue}if(u==="acceptEdits"){t.permissionMode="accept_edits";continue}if(u==="hostFolder"||u==="hostFolders"||u==="addDir"){let l=c!==void 0?c:n[++o];if(l==null||l.startsWith("--"))throw new Error(`Missing value for --${i}`);t.hostFolders=[...t.hostFolders||[],l];continue}let a=c!==void 0?c:n[++o];if(a==null||a.startsWith("--"))throw new Error(`Missing value for --${i}`);t[u]=a}return t}function Mo(){return`agensis agent daemon
47
57
 
48
58
  Usage:
49
59
  agensis --url <workspace-url> --token <token> --workspace <id> --agent <id> [options]
@@ -66,12 +76,17 @@ Options:
66
76
  --host-folder <path> Extra folder the coding CLI may read/write (repeatable; passed as --add-dir)
67
77
  --coding-cmd <command> Command used for jobs, default: claude -p
68
78
  --no-coding Disable coding jobs; keep presence/shared inference only
79
+ --full-cli-context Load all user CLI skills, plugins, hooks, memory, and MCPs
80
+ (default isolates Claude/Codex to project + Agensis context)
81
+ --sync-memory Opt in to mirroring this project's Claude memory files
82
+ to the connected Agensis workspace (default: off)
69
83
  --model <id> Default model to pass to supported coding CLIs
70
84
  --permission-mode <m> default, accept_edits, or yolo
71
85
  --yolo Alias for --permission-mode yolo
72
86
  --no-sandbox Alias for --permission-mode yolo
73
87
  --timeout-ms <ms> Kill a job after this time, default: 1800000
74
88
  --heartbeat-ms <ms> Local terminal heartbeat interval, default: 15000
89
+ --max-concurrency <n> Maximum simultaneous coding CLI jobs, default: 2
75
90
  --cursorbuddy-port <n> Local CursorBuddy discovery/chat port, default: 8787
76
91
  --cursorbuddy-bridge Enable local CursorBuddy discovery/chat bridge
77
92
  --no-cursorbuddy-bridge Disable local CursorBuddy discovery/chat bridge
@@ -84,7 +99,7 @@ Options:
84
99
  --profile <name> Save/reuse a local daemon profile, default: default
85
100
  --version Print the CLI version
86
101
  --help Show this help
87
- `}async function so(e){let t=e.profile!==void 0,n=e.handle||e.name,r=z(e.profile||(Ue(e)&&n?n:"default"));if(!Ht(e)){let o=await Jt(r);if(!o)throw new Error(Kt(r));return Wt(o,e)}return Ue(e)?{...e,cursorBuddyBridge:e.cursorBuddyBridge===!0,onRegistered:async o=>{await be(r,o);let s=t||r!=="default"?`agensis connect --profile ${r}`:"agensis connect";Y.stdout.write(`[agensis] Saved daemon profile "${r}". Restart with: ${s}
88
- `)}}:e}async function io(){let e=ro(Y.argv.slice(2));if(e.help){Y.stdout.write(oo());return}if(e.version){Y.stdout.write(`${oe}
89
- `);return}if(e.command==="buddy"){if(e.subcommand!=="connect")throw new Error(`Unknown buddy command "${e.subcommand||""}". Use "agensis buddy connect --key <cbk_...>".`);let n=await Yt(e);n.cursorBuddyBridge=e.cursorBuddyBridge!==!1,n.cursorBuddyRuntime=!0,n.exitOnOnce=!0,await Se(n),n.once&&Y.exit(0);return}if(e.command==="setup"){let n=await Xt(e);n.exitOnOnce=!0,await Se({...e,...n}),n.once&&Y.exit(0);return}if(e.command!=="connect")throw new Error(`Unknown command "${e.command}". Use "agensis setup", "agensis connect --url ...", or "agensis buddy connect --key ...".`);let t=await so(e);t.exitOnOnce=!0,await Se(t),t.once&&Y.exit(0)}io().catch(e=>{Y.stderr.write(`${e?.message||e}
102
+ `}async function No(e){let t=e.profile!==void 0,n=e.handle||e.name,r=q(e.profile||(He(e)&&n?n:"default"));if(!on(e)){let o=await sn(r);if(!o)throw new Error(cn(r));return an(o,e)}return He(e)?{...e,cursorBuddyBridge:e.cursorBuddyBridge===!0,onRegistered:async o=>{await _e(r,o);let s=t||r!=="default"?`agensis connect --profile ${r}`:"agensis connect";Y.stdout.write(`[agensis] Saved daemon profile "${r}". Restart with: ${s}
103
+ `)}}:e}async function Oo(){let e=xo(Y.argv.slice(2));if(e.help){Y.stdout.write(Mo());return}if(e.version){Y.stdout.write(`${Z}
104
+ `);return}if(e.command==="buddy"){if(e.subcommand!=="connect")throw new Error(`Unknown buddy command "${e.subcommand||""}". Use "agensis buddy connect --key <cbk_...>".`);let n=await dn(e);n.cursorBuddyBridge=e.cursorBuddyBridge!==!1,n.cursorBuddyRuntime=!0,n.exitOnOnce=!0,await we(n),n.once&&Y.exit(0);return}if(e.command==="setup"){let n=await mn(e);n.exitOnOnce=!0,await we({...e,...n}),n.once&&Y.exit(0);return}if(e.command!=="connect")throw new Error(`Unknown command "${e.command}". Use "agensis setup", "agensis connect --url ...", or "agensis buddy connect --key ...".`);let t=await No(e);t.exitOnOnce=!0,await we(t),t.once&&Y.exit(0)}Oo().catch(e=>{Y.stderr.write(`${e?.message||e}
90
105
  `),Y.exitCode=1});
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@agensis/agensis-agent",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Run a local agensis workspace agent daemon. Connects to a workspace, receives @mention jobs, runs a configured coding CLI in the local folder, and posts results back to agensis. Ships as a single minified bundle.",
5
5
  "homepage": "https://agensis.io",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/jasonkneen/agensis.git",
9
- "directory": "agent/agensis-agent"
8
+ "url": "git+https://github.com/jasonkneen/agensis-agent.git",
9
+ "directory": "packages/agensis-agent"
10
10
  },
11
11
  "bugs": {
12
- "url": "https://github.com/jasonkneen/agensis/issues"
12
+ "url": "https://github.com/jasonkneen/agensis-agent/issues"
13
13
  },
14
14
  "type": "module",
15
15
  "bin": {
@@ -35,6 +35,7 @@
35
35
  "coding-agent"
36
36
  ],
37
37
  "dependencies": {
38
+ "@anthropic-ai/claude-agent-sdk": "^0.3.218",
38
39
  "ws": "^8.20.0"
39
40
  },
40
41
  "optionalDependencies": {