@agensis/agensis-agent 0.1.36 → 0.1.38
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/bin/agensis.mjs +39 -38
- package/package.json +1 -1
package/bin/agensis.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`),s=String(t.soul??""),i=await ve(q.join(n,
|
|
4
|
-
`}async function
|
|
5
|
-
`)}async function
|
|
2
|
+
var Rr=Object.defineProperty;var Me=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ft=(e,t)=>{for(var n in t)Rr(e,n,{get:t[n],enumerable:!0})};var rn={};Ft(rn,{createE2bProvider:()=>ao});function Ve(e){return`'${String(e).replace(/'/g,"'\\''")}'`}function ao({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 c=Number(String(process.versions.node).split(".")[0])||0,u=c<20||c===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.${u}`)}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:io}},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=[],env:d={},onData:c}){let u=`${i} ${a.map(Ve).join(" ")}`,h={cwd:s.dir,envs:{...d,IS_SANDBOX:"1",AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS:"1"},onStdout:f=>{try{c?.(f)}catch{}}};try{let f=await s.sbx.commands.run(u,h);return{status:f.exitCode,stdout:f.stdout||"",stderr:f.stderr||"",error:null}}catch(f){return f&&typeof f.exitCode=="number"?{status:f.exitCode,stdout:f.stdout||"",stderr:f.stderr||"",error:null}:{status:null,stdout:"",stderr:String(f?.message||f),error:f}}},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 io,on=Me(()=>{io="/home/user/repo"});import jn from"node:fs";import G from"node:fs/promises";import as from"node:os";import q from"node:path";function Fn(e,t){return String(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/\.{2,}/g,".").replace(/^[.-]+/,"").slice(0,96)||t}function K({workspace:e,agent:t,homedir:n=as.homedir()}={}){return q.join(n,".agensis",Fn(e,"workspace"),Fn(t,"agent"))}function Jn(e){return q.join(K(e),Gn)}function zn(e){return q.join(K(e),mt)}async function Pe(e){let t=K(e);try{return await G.mkdir(t,{recursive:!0}),t}catch{return null}}async function ve(e,t){let n=`${e}.tmp-${process.pid}`;try{return await G.writeFile(n,t),await G.rename(n,e),!0}catch{try{await G.rm(n,{force:!0})}catch{}return!1}}async function ft(e,t){if(!t||typeof t!="object")return!1;let n=await Pe(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 ve(q.join(n,us),`${JSON.stringify(r,null,2)}
|
|
3
|
+
`),s=String(t.soul??""),i=await ve(q.join(n,ls),s);return o&&i}async function Kn(e,t={}){let n=await Pe(e);return n?ve(q.join(n,Hn),Yn(e,t)):!1}function Wn(e,t={}){let n=K(e);try{return jn.mkdirSync(n,{recursive:!0}),jn.writeFileSync(q.join(n,Hn),Yn(e,t)),!0}catch{return!1}}function Yn(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)}
|
|
4
|
+
`}async function pt(e){let t=q.join(K(e),Gn),n;try{let a=await G.stat(t);if(!a.isFile()||a.size>ys)return null;n=await G.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=dt(r.status),s=dt(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 dt(e){return e==null?"":String(e).trim().replace(/\s+/g," ").slice(0,Ss)}function ht(e){return q.join(K(e),cs)}async function Vn(e){let t=ht(e),n;try{let i=await G.stat(t);if(!i.isFile()||i.size>ws)return null;n=await G.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={};for(let i of bs){let a=i==="description"&&r.description==null?r.profile:r[i];typeof a!="string"||!a.trim()||(o[i]=a.trim())}let s=vs(r.voice,r.attitude);return s&&(o.voice=s),Object.keys(o).length>0?o:null}function vs(e,t){let n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},r={};for(let o of _s){let s=n[o];typeof s=="string"&&s.trim()?r[o]=s.trim():o==="speed"&&typeof s=="number"&&Number.isFinite(s)&&(r.speed=s)}return!r.emotion&&!r.attitude&&typeof t=="string"&&t.trim()&&(r.attitude=t.trim()),Object.keys(r).length>0?r:null}function Xn(e){return q.join(K(e),ds)}function Es(e){return q.join(K(e),qn)}async function Qn(e){let t=Xn(e),n;try{let a=await G.stat(t);if(!a.isFile()||a.size>ms)return null;n=await G.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=String(r.targetVersion||"").trim();if(!ps.test(o))return null;let s={targetVersion:o},i=dt(r.note);return i&&(s.note=i),typeof r.requestedAt=="string"&&(s.requestedAt=r.requestedAt),s}async function Zn(e){try{return await G.rm(Xn(e),{force:!0}),!0}catch{return!1}}async function Le(e){let t=Es(e),n;try{let r=await G.stat(t);if(!r.isFile()||r.size>fs)return null;n=await G.readFile(t,"utf8")}catch{return null}try{let r=JSON.parse(n);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}async function le(e,t={}){let n=await Pe(e);if(!n)return!1;let r={...t,updatedAt:new Date().toISOString()};return ve(q.join(n,qn),`${JSON.stringify(r,null,2)}
|
|
5
|
+
`)}async function er(e){let t=await Pe(e);if(!t)return!1;let n=q.join(t,mt);try{return await G.access(n),!0}catch{}return ve(n,gs)}async function tr(e){let t=q.join(K(e),mt);try{let n=await G.stat(t);return!n.isFile()||n.size>hs?null:(await G.readFile(t,"utf8")).trim()||null}catch{return null}}var Gn,cs,Hn,mt,us,ls,ds,qn,ms,fs,ps,hs,gs,ys,Ss,ws,bs,_s,Ue=Me(()=>{Gn="status.json",cs="identity.json",Hn="heartbeat.json",mt="heartbeat.md",us="agent.json",ls="soul.md",ds="update-request.json",qn="update.json",ms=4*1024,fs=16*1024,ps=/^[a-zA-Z0-9._+-]{1,64}$/,hs=16*1024,gs=`# Heartbeat
|
|
6
6
|
|
|
7
7
|
This file tells you what to do on each heartbeat \u2014 the recurring "still here, still
|
|
8
8
|
working" moment. Edit it freely; the daemon reads it but never overwrites your edits.
|
|
@@ -15,57 +15,57 @@ On each heartbeat:
|
|
|
15
15
|
- If you've finished and there's nothing to do, a short idle note is fine.
|
|
16
16
|
|
|
17
17
|
Add your own recurring checks below.
|
|
18
|
-
`,
|
|
19
|
-
`),signal:i,installFn:a
|
|
20
|
-
`}function
|
|
21
|
-
`}function
|
|
22
|
-
`}function
|
|
23
|
-
`}var
|
|
24
|
-
`):_.result,M=new Error(N||`claude-agent-sdk result error: ${_.subtype}`);k.finish({status:1,stdout:k.text,stderr:M.message,error:M})}else if(_.type==="assistant"){let N=_.message?.content;if(Array.isArray(N)){let M=N.filter(
|
|
25
|
-
`))>=0;){let d=n.slice(0,a);if(n=n.slice(a+1),!d.trim())continue;let c;try{c=JSON.parse(d)}catch{continue}if(c.id!==void 0&&r.has(c.id)){let{resolve:
|
|
18
|
+
`,ys=8*1024,Ss=400;ws=16*1024,bs=["name","avatar","accent_color","description","soul"],_s=["cartesia_voice_id","voice_id","id","speed","emotion","attitude"]});import{spawn as $i,execFile as Ri}from"node:child_process";import Ot from"node:fs";import Te from"node:fs/promises";import Di from"node:os";import be from"node:path";import{promisify as Bi}from"node:util";function Rt({homedir:e=Di.homedir()}={}){return be.join(e,".agensis","versions")}function Je(e,t){return be.join(e,t)}function Dt(e){return be.join(e,Li)}function we(e){return be.join(e,"node_modules",$t,"bin","agensis.mjs")}async function Ir(e,t){await Te.mkdir(be.dirname(e),{recursive:!0}),await Te.rm(e,{force:!0}),await Te.symlink(t,e)}async function Bt({root:e,version:t,log:n=()=>{}}){let r=Je(e,t),o=we(r);if(Ot.existsSync(o))return n(`[self-update] ${t} already installed at ${r}`),r;if(await Te.mkdir(r,{recursive:!0}),n(`[self-update] installing ${$t}@${t} into ${r}`),await Pi("npm",["install","--prefix",r,`${$t}@${t}`,"--no-audit","--no-fund","--no-save","--omit=dev"]),!Ot.existsSync(o))throw new Error(`npm install reported success but ${o} is missing`);return r}function Pt({entry:e,profileName:t,extraArgs:n=[],env:r=process.env}){let o=["connect","--profile",t,...n],s=$i(process.execPath,[e,...o],{detached:!0,stdio:"inherit",env:r});return s.unref(),s}async function Lt(e,{graceMs:t=5e3}={}){return!e||e.exitCode!==null||e.killed||await new Promise(n=>{let r=!1,o=()=>{r||(r=!0,clearTimeout(s),n())},s=setTimeout(()=>{try{e.kill("SIGKILL")}catch{}},t);s.unref?.(),e.once("exit",o);try{e.kill("SIGTERM")}catch{o()}}),!0}async function Ut({config:e,pid:t,timeoutMs:n=Cr}){let r=be.join(K(e),"heartbeat.json"),o=Date.now()+n;for(;Date.now()<o;){try{let s=await Te.readFile(r,"utf8"),i=JSON.parse(s);if(Number.isFinite(i.ts)&&Date.now()-i.ts<=ji&&i.connected&&(t==null||i.pid===t))return!0}catch{}await new Promise(s=>setTimeout(s,Ui))}return!1}async function Tr({config:e,targetVersion:t,currentVersion:n,root:r=Rt({}),profileName:o="default",runningChild:s=null,installFn:i=Bt,spawnFn:a=Pt,stopFn:d=Lt,healthCheckFn:c=Ut,healthTimeoutMs:u=Cr,log:h=()=>{}}={}){let f=await Le(e)||{},y=n||f.currentVersion||null,b=Dt(r),m={version:t,startedAt:new Date().toISOString()};if(t===y){let l={currentVersion:y,previousVersion:f.previousVersion||null,lastAttempt:{...m,result:"noop_already_current"}};return await le(e,l),{...l,child:s}}let w;try{w=await i({root:r,version:t,log:h})}catch(l){let g={currentVersion:y,previousVersion:f.previousVersion||null,lastAttempt:{...m,result:"install_failed",error:String(l?.message||l)}};return await le(e,g),{...g,child:s}}s&&await d(s),await Ir(b,w);let S=we(w),E=a({entry:S,profileName:o});if(await c({config:e,pid:E.pid,timeoutMs:u})){let l={currentVersion:t,previousVersion:y,lastAttempt:{...m,result:"ok"}};return await le(e,l),{...l,child:E}}h(`[self-update] ${t} failed its health check within ${u}ms \u2014 rolling back to ${y||"(no known previous version)"}`),await d(E);let k=!1,N=null;if(y){let l=Je(r,y);Ot.existsSync(we(l))&&(await Ir(b,l),N=a({entry:we(l),profileName:o}),k=!0)}let M={currentVersion:k?y:f.currentVersion||y,previousVersion:y,lastAttempt:{...m,result:k?"rolled_back":"failed_no_fallback"}};return await le(e,M),{...M,child:N}}var Pi,$t,Li,Cr,Ui,ji,Mr=Me(()=>{Ue();Pi=Bi(Ri),$t="@agensis/agensis-agent",Li="current",Cr=3e4,Ui=1e3,ji=1e4});var Or={};Ft(Or,{runSupervisor:()=>Ji});import Fi from"node:fs";import jt from"node:fs/promises";import Gi from"node:path";async function qi({root:e,runningVersion:t,installFn:n,log:r}){let o=Dt(e);if(Fi.existsSync(o))return;r(`[supervise] no current version linked yet \u2014 adopting the running version ${t}`);let s=await n({root:e,version:t,log:r});await jt.mkdir(Gi.dirname(o),{recursive:!0}),await jt.rm(o,{force:!0}),await jt.symlink(s,o)}async function Ji({config:e,runningVersion:t,profileName:n="default",pollIntervalMs:r=Hi,root:o=Rt({}),log:s=f=>process.stdout.write(`${f}
|
|
19
|
+
`),signal:i,installFn:a=Bt,spawnFn:d=Pt,stopFn:c=Lt,healthCheckFn:u=Ut,maxIterations:h=1/0}={}){if(!e?.workspace||!e?.agent)throw new Error("supervise requires a resolved profile with workspace + agent (run `agensis setup`/`agensis connect` first).");await qi({root:o,runningVersion:t,installFn:a,log:s});let f=await Le(e);f?.currentVersion||(f={currentVersion:t,previousVersion:null,lastAttempt:null},await le(e,f));let y=null,b=!1,m=0,w=()=>{let _=Je(o,f.currentVersion);return y=d({entry:we(_),profileName:n}),y.on?.("exit",(k,N)=>{if(b)return;s(`[supervise] daemon (version ${f.currentVersion}) exited (code=${k} signal=${N}); respawning`);let M=Nr[Math.min(m,Nr.length-1)];m+=1,setTimeout(()=>{b||w()},M).unref?.()}),y.on?.("spawn",()=>{m=0}),y};w();let S=async()=>{b=!0,y&&await c(y)};i?.addEventListener("abort",()=>{S()}),process.once("SIGTERM",()=>{S().then(()=>process.exit(0))}),process.once("SIGINT",()=>{S().then(()=>process.exit(0))});let E=0;for(;!b&&!i?.aborted&&E<h&&(E+=1,await new Promise(N=>setTimeout(N,r)),!(b||i?.aborted));){let _=await Qn(e);if(!_||_.targetVersion===f.currentVersion)continue;s(`[supervise] update requested: ${f.currentVersion} -> ${_.targetVersion}${_.note?` (${_.note})`:""}`);let k=await Tr({config:e,targetVersion:_.targetVersion,currentVersion:f.currentVersion,root:o,profileName:n,runningChild:y,installFn:a,spawnFn:d,stopFn:c,healthCheckFn:u,log:s});await Zn(e),f=k,y=k.child||y,m=0,s(`[supervise] update attempt "${_.targetVersion}" -> ${k.lastAttempt?.result} (running ${k.currentVersion})`)}return{state:f,child:y}}var Hi,Nr,$r=Me(()=>{Mr();Ue();Hi=5e3,Nr=[1e3,5e3,15e3,3e4]});import ne from"node:process";import Ae from"node:fs";import me from"node:path";import xe from"node:os";import ks from"node:crypto";import T from"node:process";import ke from"ws";import{spawn as Dr}from"node:child_process";function Gt(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 Br=50*1024*1024;function Z(e){let{cmd:t,args:n=[],env:r={},cwd:o,timeoutMs:s=0,label:i="working",heartbeatMs:a=15e3,input:d="",now:c=Date.now,log:u=console,signal:h,onData:f}=e||{};return new Promise(y=>{if(h?.aborted){y({status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")});return}let b;try{let A=n.some(V=>V==="--dangerously-skip-permissions"),C=typeof process.getuid=="function"&&process.getuid()===0,$={...process.env,...r};delete $.AGENSIS_TOKEN,delete $.ANTHROPIC_API_KEY,delete $.ANTHROPIC_AUTH_TOKEN,A&&C&&($.IS_SANDBOX="1"),b=Dr(t,n,{cwd:o,detached:!0,env:$})}catch(A){y({status:null,stdout:"",stderr:"",error:A});return}d?b.stdin?.end(String(d)):b.stdin?.end();let m="",w="";b.stdout?.setEncoding("utf8"),b.stderr?.setEncoding("utf8");let S=(A,C)=>A.length>=Br?A:A+C;b.stdout?.on("data",A=>{if(m=S(m,A),f)try{f(A)}catch{}}),b.stderr?.on("data",A=>w=S(w,A));let E=c(),_=a>0?setInterval(()=>{u.log(` \u2026 still ${i} (${Gt(c()-E)}) \u2014 Ctrl+C to cancel`)},a):null;_?.unref&&_.unref();let k=A=>{if(b.pid!=null)try{process.kill(-b.pid,A)}catch{try{b.kill(A)}catch{}}},N=!1,M=s>0?setTimeout(()=>{N=!0,k("SIGKILL")},s):null;M?.unref&&M.unref();let l=!1,g=null,I=()=>{l=!0,k("SIGTERM"),g=setTimeout(()=>k("SIGKILL"),3e3),g?.unref&&g.unref()};h&&h.addEventListener("abort",I,{once:!0});let p=(A,C)=>{_&&clearInterval(_),M&&clearTimeout(M),g&&clearTimeout(g),h&&h.removeEventListener("abort",I),y({status:A,stdout:m,stderr:w,aborted:l,error:C||(l?new Error("cancelled"):N?new Error(`timed out after ${Gt(s)}`):null)})};b.on("error",A=>p(null,A)),b.on("close",A=>p(A,null))})}import{spawn as qr}from"node:child_process";import Pr from"node:crypto";var Lr=Number(process.env.AGENSIS_PERMISSION_TIMEOUT_MS||10*60*1e3),Ht=["once","session","always"];function qt(e){let t=String(e?.toolName??"").trim();if(!t)return"";let n=String(e?.ruleContent??"").trim();return n?`${t}(${n})`:t}function Ur(e){let t=[];for(let n of Array.isArray(e)?e:[])if(!(!n||n.type!=="addRules"||n.behavior!=="allow"))for(let r of Array.isArray(n.rules)?n.rules:[]){let o=qt(r);o&&!t.includes(o)&&t.push(o)}return t}var jr=/\d*>&\d*|&>/g,Fr=/[;&|`]|\$\(/;function Gr(e,t){if(String(e||"")!=="Bash")return[];let n=String(t?.command??"").trim();if(!n||Fr.test(n.replace(jr," ")))return[];let r=n.split(/\s+/),o=r[0];if(!o||o.startsWith("-"))return[];let s=r[1];return[`Bash(${s&&/^[a-z][a-z0-9:_-]*$/i.test(s)?`${o} ${s}`:o}:*)`]}function Jt({toolName:e,input:t,suggestions:n}={}){let r=Ur(n);return r.length>0?r:Gr(e,t)}function Hr(e){let t=Array.isArray(e)?e:Array.isArray(e?.allow)?e.allow:[],n=[];for(let r of t){let o=typeof r=="string"?r.trim():qt(r);o&&!n.includes(o)&&n.push(o)}return n}function zt(e){return Hr(e?.agent?.metadata?.permission_rules??e?.agent?.permissionRules??e?.permissionRules??e?.permission_rules)}function Kt(e,{toolName:t,input:n,suggestions:r}={}){let o=Array.isArray(e)?e:[];if(o.length===0)return!1;let s=String(t||"").trim();return s&&o.includes(s)?!0:Jt({toolName:t,input:n,suggestions:r}).some(i=>o.includes(i))}function pe(e){return{behavior:"deny",message:e}}function Wt({send:e,timeoutMs:t=Lr,log:n=()=>{},idFactory:r=()=>Pr.randomUUID()}={}){if(typeof e!="function")throw new Error("createPermissionBroker requires send()");let o=new Map,s=(i,a)=>{let d=o.get(i);return d?(o.delete(i),clearTimeout(d.timer),d.resolve(a),!0):!1};return{request({jobId:i,toolName:a,title:d,description:c,detail:u,input:h,suggestions:f,signal:y}={}){let b=r(),m=Jt({toolName:a,input:h,suggestions:f});return e({action:"agent_permission_request",jobId:i||"",requestId:b,toolName:String(a||"").trim(),title:String(d||"").trim(),description:String(c||"").trim(),detail:String(u||"").trim(),input:h||null,rules:m,scopes:m.length>0?Ht:["once","session"],expiresInMs:t})?(n(`permission requested for ${a||"a tool"} (${b})`),new Promise(S=>{let E=setTimeout(()=>{s(b,pe(`Nobody approved this within ${Math.round(t/6e4)} minutes. Ask again in the chat, or have the workspace grant it on the agent.`))},t);E.unref?.();let _={jobId:i||"",timer:E,resolve:S};o.set(b,_),y?.addEventListener?.("abort",()=>{s(b,pe("The job was cancelled before this was approved."))},{once:!0})})):Promise.resolve(pe("Agensis was unreachable, so this tool call could not be approved."))},decide(i){let a=String(i?.requestId||"");if(!a||!o.has(a))return!1;let d=i.behavior==="allow",c=Ht.includes(i.scope)?i.scope:"once",u=String(i.decidedBy||"").trim();return n(`permission ${d?`allowed (${c})`:"denied"} for ${a}${u?` by ${u}`:""}`),s(a,d?{behavior:"allow",scope:c,decidedBy:u}:pe(String(i.message||"").trim()||`${u||"The workspace"} denied this tool call.`))},cancelJob(i,a="The job ended before this was approved."){let d=String(i||""),c=0;for(let[u,h]of[...o.entries()])h.jobId===d&&s(u,pe(a))&&(c+=1);return c},shutdown(i="The agent daemon disconnected before this was approved."){let a=0;for(let d of[...o.keys()])s(d,pe(i))&&(a+=1);return a},pendingCount(){return o.size}}}var Xt=10*60*1e3;function Qt(e={}){let t={...process.env,...e};return delete t.AGENSIS_TOKEN,delete t.ANTHROPIC_API_KEY,delete t.ANTHROPIC_AUTH_TOKEN,t}var Ye=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 Zt(){let e=new Map;return(t,n)=>{let r=(e.get(t)||Promise.resolve()).then(n,n);return e.set(t,r.catch(()=>{})),r}}var Jr=["mcp__agensis"],zr=["Grep","Glob"];function Kr(e){return e==="yolo"?{permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0}:e==="accept_edits"?{permissionMode:"acceptEdits"}:{permissionMode:"default"}}function Wr(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 Yr(e){return`${JSON.stringify({type:"stream_event",event:{type:"content_block_delta",delta:{type:"text_delta",text:e}}})}
|
|
20
|
+
`}function Vr(e){return`${JSON.stringify({type:"result",result:e})}
|
|
21
|
+
`}function Xr(e){return`${JSON.stringify({type:"agensis_step",step:e})}
|
|
22
|
+
`}function Qr(e){return`${JSON.stringify({type:"agensis_segment",segment:e})}
|
|
23
|
+
`}var Zr=["file_path","path","pattern","command","description","prompt"],Yt=120;function Ne(e){if(!e||typeof e!="object")return"";for(let t of Zr){let n=e[t];if(typeof n!="string")continue;let r=n.replace(/\s+/g," ").trim();if(r)return r.length>Yt?`${r.slice(0,Yt)}\u2026`:r}return""}function en(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||"",canAsk:!!e.requestPermission})}function eo(e,t){return async(n,r,o={})=>{let s=e.activeTurn;if(!s)return{behavior:"deny",message:"This tool call arrived with no active job to ask about."};let i=s.requestPermission||t;if(!i)return{behavior:"deny",message:"This agent has no way to ask for approval right now."};if(Kt(s.permissionRules,{toolName:n,input:r,suggestions:o.suggestions}))return{behavior:"allow"};let a=await i({jobId:s.jobId,toolName:n,title:o.title,description:o.description,detail:Ne(r),input:r,suggestions:o.suggestions,signal:o.signal});if(a?.behavior!=="allow")return{behavior:"deny",message:a?.message||"This tool call was not approved."};let d=a.scope==="once"?void 0:o.suggestions;return d?.length?{behavior:"allow",updatedPermissions:d}:{behavior:"allow"}}}function tn({queryFn:e,idleCloseMs:t=Xt,requestPermission:n}={}){let r=new Map,o=Zt(),s=(c,u,h)=>{let f=r.get(c);if(!(!f||u&&f!==u))if(r.delete(c),clearTimeout(f.idleTimer),f.closed=!0,f.queue.close(),h&&f.activeTurn&&f.activeTurn.finish(h),typeof f.query.close=="function")try{f.query.close()}catch{}else Promise.resolve(f.query.return?.()).catch(()=>{})},i=c=>{let u=r.get(c);u&&(clearTimeout(u.idleTimer),u.idleTimer=setTimeout(()=>s(c),t),u.idleTimer.unref?.())},a=async(c,u)=>{let h=r.get(c),f=en(u);if(h&&h.fingerprint===f&&!h.closed)return h;h&&s(c,h),e||(e=(await import("@anthropic-ai/claude-agent-sdk")).query);let y=new Ye,b=Kr(u.permissionMode),m={query:null,queue:y,sessionId:"",idleTimer:null,activeTurn:null,closed:!1,terminalError:null,fingerprint:f},w=u.leanCli&&u.mcp?{agensis:{type:"http",url:u.mcp.url,headers:{Authorization:"Bearer ${AGENSIS_MCP_TOKEN}"}}}:void 0,S=e({prompt:y,options:{cwd:u.cwd,model:u.model,...b,allowedTools:[...Jr,...zr],canUseTool:n||u.requestPermission?eo(m,n):void 0,additionalDirectories:u.hostFolders&&u.hostFolders.length?u.hostFolders:void 0,mcpServers:w,strictMcpConfig:u.leanCli?!0:void 0,settingSources:u.leanCli?[]:void 0,persistSession:u.leanCli?!1:void 0,includePartialMessages:!0,env:Qt(u.mcp?.env)}});return m.query=S,r.set(c,m),m.pump=(async()=>{let E=null;try{for await(let _ of S){_.session_id&&(m.sessionId=_.session_id);let k=m.activeTurn;if(k){if(_.type==="stream_event"){let N=Wr(_.event);N&&(k.streamed+=N,k.onData?.(Yr(N)))}else if(_.type==="result")if(_.subtype==="success"){let N=_.result==null?k.text:String(_.result);k.onData?.(Vr(N)),k.finish({status:0,stdout:N,stderr:"",error:null})}else{let N=Array.isArray(_.errors)?_.errors.filter(Boolean).join(`
|
|
24
|
+
`):_.result,M=new Error(N||`claude-agent-sdk result error: ${_.subtype}`);k.finish({status:1,stdout:k.text,stderr:M.message,error:M})}else if(_.type==="assistant"){let N=_.message?.content;if(Array.isArray(N)){let M=N.filter(l=>l&&l.type==="text"&&typeof l.text=="string").map(l=>l.text).join("");M&&(k.onData?.(Qr({text:M})),k.flushed+=k.streamed,k.streamed="");for(let l of N)!l||l.type!=="tool_use"||!l.name||k.onData?.(Xr({kind:"tool",name:String(l.name),detail:Ne(l.input)}))}}}}E=new Error("claude-agent-sdk connection closed")}catch(_){E=_}finally{m.closed=!0,m.terminalError=E,clearTimeout(m.idleTimer),m.queue.close(),r.get(c)===m&&r.delete(c),m.activeTurn&&m.activeTurn.finish({status:null,stdout:m.activeTurn.text,stderr:String(E?.message||E||""),error:E})}})(),m};return{run:c=>o(c.sessionKey||"default",async()=>{let{sessionKey:u="default",prompt:h,signal:f,onData:y,timeoutMs:b=0}=c;if(f?.aborted)return{status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")};let m;try{m=await a(u,c)}catch(S){return{status:null,stdout:"",stderr:"",error:S}}if(m.closed){let S=m.terminalError||new Error("claude-agent-sdk connection closed");return{status:null,stdout:"",stderr:String(S.message||S),error:S}}clearTimeout(m.idleTimer);let w=await new Promise(S=>{let E=!1,_=null,k={streamed:"",flushed:"",get text(){return this.flushed+this.streamed},onData:y,jobId:c.job?.id||"",permissionRules:zt(c.job),requestPermission:c.requestPermission||null,finish(M){E||(E=!0,m.activeTurn===k&&(m.activeTurn=null),f&&f.removeEventListener("abort",N),_&&clearTimeout(_),S(M))}},N=()=>{let M={status:null,stdout:k.text,stderr:"",aborted:!0,error:new Error("cancelled")};Promise.resolve(m.query.interrupt?.()).catch(()=>{}),s(u,m,M)};m.activeTurn=k,f&&f.addEventListener("abort",N,{once:!0}),b>0&&(_=setTimeout(()=>{let M=new Error(`timed out after ${b}ms`);Promise.resolve(m.query.interrupt?.()).catch(()=>{}),s(u,m,{status:null,stdout:k.text,stderr:M.message,error:M})},b),_.unref?.()),m.queue.push({type:"user",message:{role:"user",content:h},parent_tool_use_id:null,session_id:m.sessionId})});return r.get(u)===m&&i(u),w}),shutdown:()=>{for(let c of[...r.keys()])s(c)}}}function to(e){let t=1,n="",r=new Map,o=new Set;e.stdout.setEncoding("utf8"),e.stdout.on("data",i=>{n+=i;let a;for(;(a=n.indexOf(`
|
|
25
|
+
`))>=0;){let d=n.slice(0,a);if(n=n.slice(a+1),!d.trim())continue;let c;try{c=JSON.parse(d)}catch{continue}if(c.id!==void 0&&r.has(c.id)){let{resolve:u,reject:h}=r.get(c.id);r.delete(c.id),c.error?h(new Error(c.error.message||"codex app-server error")):u(c.result)}else if(c.method)for(let u of o)u(c.method,c.params,c.id)}});let s=i=>{for(let{reject:a}of r.values())a(i);r.clear()};return e.on("exit",()=>s(new Error("codex app-server exited"))),e.on("error",i=>s(i)),{request(i,a){let d=t++;return new Promise((c,u)=>{r.set(d,{resolve:c,reject:u}),e.stdin.write(`${JSON.stringify({id:d,method:i,params:a})}
|
|
26
26
|
`)})},notify(i,a){e.stdin.write(`${JSON.stringify({method:i,params:a})}
|
|
27
27
|
`)},respond(i,a){e.stdin.write(`${JSON.stringify({id:i,result:a})}
|
|
28
28
|
`)},respondError(i,a){e.stdin.write(`${JSON.stringify({id:i,error:{code:-32601,message:a}})}
|
|
29
|
-
`)},onMessage(i){return o.add(i),()=>o.delete(i)}}}function
|
|
29
|
+
`)},onMessage(i){return o.add(i),()=>o.delete(i)}}}function no(e){return e==="yolo"?{approvalPolicy:"never",sandbox:"danger-full-access"}:{}}function ro(e,t,n){let r=Array.isArray(e)?e.map(String):[];if(r.length){let o=t.find(s=>r.includes(s));if(o)return o}return n}var Ke={preferences:["decline"],fallback:"decline"},oo={preferences:["accept","acceptForSession"],fallback:"acceptForSession"},Vt={preferences:["acceptForSession","accept"],fallback:"acceptForSession"};function We(e,t){return ro(e,t.preferences,t.fallback)}function so(e,t){let n=t?.command,r=Array.isArray(n)?n.join(" "):String(n||"");if(r.trim())return r.replace(/\s+/g," ").trim().slice(0,200);let o=t?.fileChanges||t?.changes,s=o&&typeof o=="object"?Object.keys(o):[];return s.length?s.slice(0,4).join(", "):e==="item/fileChange/requestApproval"?"apply a file change":"run a command"}function nn({spawnFn:e=qr,idleCloseMs:t=Xt,requestPermission:n}={}){let r=new Map,o=Zt(),s=c=>{let u=r.get(c);if(u){r.delete(c),clearTimeout(u.idleTimer);try{u.child.kill("SIGTERM")}catch{}}},i=c=>{let u=r.get(c);u&&(clearTimeout(u.idleTimer),u.idleTimer=setTimeout(()=>s(c),t),u.idleTimer.unref?.())},a=async(c,u)=>{let h=r.get(c),f=en(u);if(h&&h.fingerprint===f)return h;h&&s(c);let y=e("codex",["app-server"],{cwd:u.cwd,env:Qt(u.mcp?.env),stdio:["pipe","pipe","pipe"]}),b=to(y);await b.request("initialize",{clientInfo:{name:"agensis-agent",version:u.clientVersion||"unknown"}}),b.notify("initialized");let m=u.leanCli&&u.mcp?{mcp_servers:{agensis:{url:u.mcp.url,bearer_token_env_var:"AGENSIS_MCP_TOKEN"}}}:void 0,w=await b.request("thread/start",{cwd:u.cwd,ephemeral:u.leanCli||void 0,model:u.model,config:m,...no(u.permissionMode)}),S={child:y,rpc:b,threadId:w.thread.id,fingerprint:f,idleTimer:null};return r.set(c,S),S};return{run:c=>o(c.sessionKey||"default",async()=>{let{sessionKey:u="default",prompt:h,signal:f,onData:y,timeoutMs:b=0}=c;if(f?.aborted)return{status:null,stdout:"",stderr:"",aborted:!0,error:new Error("cancelled")};let m;try{m=await a(u,c)}catch(N){return{status:null,stdout:"",stderr:"",error:N}}let w="",S="",E=null,_=!1,k=await new Promise(N=>{let M=!1,l=C=>{M||(M=!0,A(),N(C))},g=m.rpc.onMessage((C,$,V)=>{if(V!==void 0){let B=C==="item/commandExecution/requestApproval",J=C==="item/fileChange/requestApproval";if(!B&&!J){m.rpc.respondError(V,`Agensis daemon cannot handle Codex request ${C}`);return}let X=c.permissionMode==="yolo"||J&&c.permissionMode==="accept_edits",x=c.requestPermission||n;if(X||!x){let D=We($?.availableDecisions,X?Vt:Ke);m.rpc.respond(V,{decision:D});return}Promise.resolve(x({jobId:c.job?.id||"",toolName:B?"Codex command":"Codex file change",detail:so(C,$),description:String($?.reason||"").trim(),input:$||null})).then(D=>{let v=D?.behavior!=="allow"?Ke:D.scope==="once"?oo:Vt;m.rpc.respond(V,{decision:We($?.availableDecisions,v)})}).catch(()=>{m.rpc.respond(V,{decision:We($?.availableDecisions,Ke)})});return}if(!(!$||$.threadId!==m.threadId)){if(C==="turn/started"){E=$.turn?.id??E;return}if(!(E&&$.turnId&&$.turnId!==E)){if(C==="item/agentMessage/delta")w+=$.delta||"",y?.($.delta||"");else if(C==="item/completed"&&$.item?.type==="agentMessage")S=$.item.text||S;else if(C==="turn/completed"){let B=$.turn?.status==="failed"||$.turn?.error;l({status:B?1:0,stdout:S||w,stderr:B?String($.turn?.error?.message||$.turn?.error||""):"",error:B?new Error(String($.turn?.error?.message||$.turn?.error||"codex turn failed")):null})}}}}),I=()=>{_=!0,m.rpc.request("turn/interrupt",{threadId:m.threadId}).catch(()=>{});let C={status:null,stdout:w,stderr:"",aborted:!0,error:new Error("cancelled")};l(C),s(u)};f&&f.addEventListener("abort",I,{once:!0});let p=b>0?setTimeout(()=>{let C=new Error(`timed out after ${b}ms`);m.rpc.request("turn/interrupt",{threadId:m.threadId}).catch(()=>{}),l({status:null,stdout:w,stderr:C.message,error:C}),s(u)},b):null;p?.unref?.();function A(){g(),f&&f.removeEventListener("abort",I),p&&clearTimeout(p)}m.rpc.request("turn/start",{threadId:m.threadId,input:[{type:"text",text:h}]}).then(C=>{E=C?.turn?.id||E}).catch(C=>l({status:null,stdout:"",stderr:"",error:C}))});return _||i(u),k}),shutdown:()=>{for(let c of[...r.keys()])s(c)}}}function an({run:e=Z}={}){return{run:t=>e(t)}}var co=null,uo=null,sn=new Set;function lo(e){let t=String(e&&e.message||e||"");return/Cannot find module|ERR_MODULE_NOT_FOUND|ENOENT|command not found/i.test(t)}function mo(e,{local:t,pooled:n,log:r=console}={}){let o=t||an(),s=n||(e==="claude"?co||=tn():e==="codex"?uo||=nn():null);return s?{async run(i){if(sn.has(e))return o.run(i);let a=await s.run(i);return a.error&&lo(a.error)?(sn.add(e),r.log?.(`[executor] ${e} fast connection unavailable (${a.error.message}); falling back to subprocess mode for this and future jobs.`),o.run(i)):a}}:o}function fo(e){return{async run({cmd:t,args:n=[],env:r={},onData:o,signal:s,job:i}){let a=null;try{a=await e.ensureEnv({job:i,signal:s}),await e.putRepo(a,{job:i,signal:s});let d=await e.exec(a,{cmd:t,args:n,env:r,onData:o,signal:s}),c=await e.getResult(a,{job:i}).catch(()=>({})),u=c&&c.patch?String(c.patch).trim():"",h=u?`${d.stdout||""}
|
|
30
30
|
|
|
31
31
|
\`\`\`diff
|
|
32
|
-
${
|
|
33
|
-
\`\`\``:d.stdout||"";return{status:d.status,stdout:
|
|
34
|
-
`))>=0;)n(e.slice(0,o)),e=e.slice(o+1)},end(){e&&n(e),e=""},get threadId(){return t},get threadUrl(){return
|
|
32
|
+
${u}
|
|
33
|
+
\`\`\``:d.stdout||"";return{status:d.status,stdout:h,stderr:d.stderr||"",error:d.error||null}}catch(d){return{status:null,stdout:"",stderr:"",error:d}}finally{if(a)try{await e.destroy(a)}catch{}}}}}function cn(e,{makeProvider:t,family:n}={}){return(e&&e.agent&&e.agent.run_mode)==="sandbox"?fo((t||po)(e)):n==="claude"||n==="codex"?mo(n):an()}function po(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 go({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 ho(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 go(e){let t=null,n=async()=>{if(!t){if(!ho())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(()=>(on(),rn))).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)}}import un from"node:fs/promises";import Oe from"node:path";var Qe="amp",yo=/^T-[A-Za-z0-9-]{20,100}$/,Xe={amp_not_installed:"Amp CLI is not installed on the connected machine. Install Amp, then reconnect this agent.",amp_version_unsupported:"The installed Amp CLI does not support orb execute streaming. Update Amp, then reconnect this agent.",amp_not_authenticated:"Amp is not signed in on the connected machine. Run `amp login` there, then try again.",amp_auth_expired:"The Amp sign-in on the connected machine has expired. Run `amp login` there, then try again.",amp_project_not_found:"This repository is not an Amp project. Run `amp projects create <repository-url> --workspace` in it (or `--personal`), then try again.",amp_project_unmatched:"This repository is not linked to an Amp project. Run `amp projects create <repository-url> --workspace` in it (or `--personal`), then try again.",amp_project_forbidden:"The connected Amp account cannot access this repository project.",amp_repo_access_denied:"Amp cannot reach this GitHub repository. Grant the Amp GitHub connection access to it at https://ampcode.com/settings, then try again.",amp_repo_not_allowed:"This repository is not allowed by the connected Agensis daemon profile.",amp_insufficient_credit:"The connected Amp account does not have enough credit to start or continue this orb.",amp_orb_provision_failed:"Amp could not provision the orb for this turn.",amp_setup_failed:"The repository `.agents/setup` script exists but is not executable.",amp_thread_not_found:"The Amp thread linked to this conversation no longer exists. Start a new Agensis conversation to create a new thread.",amp_stream_invalid:"Amp completed without returning a valid thread stream.",amp_cli_crashed:"The Amp CLI stopped unexpectedly on the connected machine.",amp_turn_cancelled:"The Amp turn was cancelled.",amp_turn_timed_out:"The Amp turn timed out on the connected machine."};function ee(e,t=""){let n=new Error(Xe[e]||Xe.amp_cli_crashed);return n.code=e,t&&(n.detail=String(t).slice(0,1e3)),n}function Ze(e){return String(e?.agent?.metadata?.runtime||"").trim().toLowerCase()===Qe}function he(e){let t=String(e||"").trim();return yo.test(t)?t:""}function So(e){let t=he(e);return t?`https://ampcode.com/threads/${t}`:""}function ln({prompt:e,threadId:t="",executable:n="amp"}={}){let r=he(t);return r?{cmd:n,args:["threads","continue",r,"-x",String(e||""),"--stream-json"]}:{cmd:n,args:["-ox",String(e||""),"--stream-json","--no-archive-after-execute"]}}function dn(){let e="",t="",n=r=>{try{let o=JSON.parse(String(r).trim()),s=he(o?.session_id||o?.sessionId||o?.thread_id||o?.threadId);s&&(t=s)}catch{}};return{feed(r){e+=String(r||"");let o;for(;(o=e.indexOf(`
|
|
34
|
+
`))>=0;)n(e.slice(0,o)),e=e.slice(o+1)},end(){e&&n(e),e=""},get threadId(){return t},get threadUrl(){return So(t)}}}function $e(e={}){let t=`${e?.error?.message||""}
|
|
35
35
|
${e?.stderr||""}
|
|
36
|
-
${e?.stdout||""}`.trim(),n="amp_cli_crashed";return e?.error?.code==="ENOENT"||/spawn\s+amp\s+ENOENT|command not found/i.test(t)?n="amp_not_installed":e?.aborted===!0||/^cancelled$/i.test(String(e?.error?.message||"").trim())?n="amp_turn_cancelled":/timed out|timeout/i.test(t)?n="amp_turn_timed_out":/(?:auth(?:entication)?|session|token|credential)[^\n]*(?:expired|invalid|revoked)/i.test(t)?n="amp_auth_expired":/not (?:logged|signed) in|not authenticated|please (?:log|sign) ?in|(?:log|sign) ?in (?:to|required)|authentication required|unauthenticated|unauthorized/i.test(t)?n="amp_not_authenticated":/insufficient[^\n]*(?:credit|balance)|(?:credit|balance)[^\n]*(?:exhausted|too low|not enough|run out|out of)|(?:run )?out of[^\n]*(?:credit|balance)|(?:usage|spend)[^\n]*limit[^\n]*(?:exceeded|reached)/i.test(t)?n="amp_insufficient_credit":/thread[^\n]*(?:not found|does not exist|unknown)/i.test(t)?n="amp_thread_not_found":/project[^\n]*(?:forbidden|permission|access denied|not allowed)/i.test(t)?n="amp_project_forbidden":/project[^\n]*(?:not found|does not exist|unmatched)/i.test(t)?n="amp_project_not_found":/\.agents\/setup|setup script/i.test(t)?n="amp_setup_failed":/provision|creating orb|start(?:ing)? orb/i.test(t)&&(n="amp_orb_provision_failed"),{code:n,message:Xe[n],detail:t.slice(0,1e3)}}async function
|
|
37
|
-
${a?.stderr||""}`;if(a?.status!==0||!/--stream-json/.test(d)||!/threads[\s\S]*continue/i.test(d)||!/\borb\b/i.test(d))return
|
|
36
|
+
${e?.stdout||""}`.trim(),n="amp_cli_crashed";return e?.error?.code==="ENOENT"||/spawn\s+amp\s+ENOENT|command not found/i.test(t)?n="amp_not_installed":/unknown option|unknown command|unrecognized option/i.test(t)?n="amp_version_unsupported":/could not access this github repository|github connection has access/i.test(t)?n="amp_repo_access_denied":e?.aborted===!0||/^cancelled$/i.test(String(e?.error?.message||"").trim())?n="amp_turn_cancelled":/timed out|timeout/i.test(t)?n="amp_turn_timed_out":/(?:auth(?:entication)?|session|token|credential)[^\n]*(?:expired|invalid|revoked)/i.test(t)?n="amp_auth_expired":/not (?:logged|signed) in|not authenticated|please (?:log|sign) ?in|(?:log|sign) ?in (?:to|required)|authentication required|unauthenticated|unauthorized/i.test(t)?n="amp_not_authenticated":/insufficient[^\n]*(?:credit|balance)|(?:credit|balance)[^\n]*(?:exhausted|too low|not enough|run out|out of)|(?:run )?out of[^\n]*(?:credit|balance)|(?:usage|spend)[^\n]*limit[^\n]*(?:exceeded|reached)/i.test(t)?n="amp_insufficient_credit":/thread[^\n]*(?:not found|does not exist|unknown)/i.test(t)?n="amp_thread_not_found":/project[^\n]*(?:forbidden|permission|access denied|not allowed)/i.test(t)?n="amp_project_forbidden":/project[^\n]*(?:not found|does not exist|unmatched)/i.test(t)?n="amp_project_not_found":/\.agents\/setup|setup script/i.test(t)?n="amp_setup_failed":/provision|creating orb|start(?:ing)? orb/i.test(t)&&(n="amp_orb_provision_failed"),{code:n,message:Xe[n],detail:t.slice(0,1e3)}}async function mn({cwd:e,allowedRoots:t=[]}={}){let n=Oe.resolve(String(e||""));if(!t.map(s=>String(s||"").trim()).filter(Boolean).map(s=>Oe.resolve(s)).includes(n))throw ee("amp_repo_not_allowed");try{await un.access(Oe.join(n,".git"))}catch{throw ee("amp_repo_not_allowed","cwd is not a Git repository root")}let o=Oe.join(n,".agents","setup");try{let s=await un.stat(o);if(s.isFile()&&!(s.mode&73))throw ee("amp_setup_failed")}catch(s){if(s?.code!=="ENOENT")throw s}return n}function re(e,t){return{id:Qe,available:!1,version:e,reason:t,project:null}}function wo(e){return!e||typeof e!="object"?null:{id:String(e.id||"").slice(0,160),name:String(e.name||e.slug||"").slice(0,200),repository:String(e.repositoryURL||e.repository||e.repo||e.repositoryUrl||"").slice(0,500)}}async function et({cwd:e,executable:t="amp",run:n=Z,signal:r}={}){let o=(f,y=1e4)=>n({cmd:t,args:f,cwd:e,timeoutMs:y,heartbeatMs:0,label:"checking Amp",signal:r}),s=await o(["version"],5e3);if(s?.status!==0){let f=$e(s);return re("",f.code)}let i=String(s.stdout||s.stderr||"").trim().split(/\r?\n/).at(-1)?.slice(0,120)||"",a=await o(["--help"],5e3),d=`${a?.stdout||""}
|
|
37
|
+
${a?.stderr||""}`;if(a?.status!==0||!/--stream-json/.test(d)||!/threads[\s\S]*continue/i.test(d)||!/\borb\b/i.test(d))return re(i,"amp_version_unsupported");let c=await o(["usage"]);if(c?.status!==0){let f=$e(c);return re(i,f.code)}let u=await o(["projects","status","--json"]);if(u?.status!==0){let f=$e(u);return re(i,f.code)}let h;try{h=JSON.parse(String(u.stdout||""))}catch{return re(i,"amp_version_unsupported")}return["forbidden","permission_denied","access_denied"].includes(String(h?.status||"").toLowerCase())?re(i,"amp_project_forbidden"):h?.status==="unmatched"?re(i,"amp_project_unmatched"):h?.status!=="matched"||!h?.project?re(i,"amp_project_not_found"):{id:Qe,available:!0,version:i,reason:null,project:wo(h.project)}}function fn(e){let t=$e(e);return ee(t.code,t.detail)}function pn(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 a(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 d(){for(let[w,S]of r){if(o>=n)break;if(S.active||S.queued.length===0)continue;let E=S.queued.shift(),_=new AbortController;S.active={job:E,controller:_,cancelled:!1},o+=1,Promise.resolve().then(()=>_.signal.aborted?void 0:t(E,{signal:_.signal})).catch(()=>{}).finally(()=>{S.active=null,o-=1,S.queued.length===0&&!S.active&&r.delete(w),d(),c()})}}function c(){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 u(w){if(w&&w.key!=null&&a(w.key))return{accepted:!1,deduped:!0,position:0,startedImmediately:!1};let S=w&&w.lane!=null?String(w.lane):"",E=i(S),_=!E.active&&E.queued.length===0&&o<n;E.queued.push(w);let k=E.queued.length+(E.active?1:0);return d(),{accepted:!0,deduped:!1,position:k,startedImmediately:_}}function h(w,S){let E=!1;for(let[_,k]of r)S!=null&&_!==String(S)||k.active&&(k.active.cancelled=!0,k.active.controller.abort(w||"cancelled"),E=!0);return E}function f(w,S){if(w==null)return!1;let E=!1;for(let[_,k]of[...r]){k.active?.job?.key===w&&(k.active.cancelled=!0,k.active.controller.abort(S||"cancelled"),E=!0);let N=k.queued.length;k.queued=k.queued.filter(M=>M.key!==w),k.queued.length!==N&&(E=!0),!k.active&&k.queued.length===0&&r.delete(_)}return c(),E}function y(){let w=0;for(let S of r.values())w+=S.queued.length;return w}function b(){return o}function m(){return o===0&&y()===0?Promise.resolve():new Promise(w=>s.push(w))}return{enqueue:u,cancel:f,cancelActive:h,has:a,size:y,active:b,idle:m}}import bn from"node:crypto";import bo from"node:http";import _n from"node:os";import oe from"node:process";var hn=8787,tt="claude-haiku-4-5",_o=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/,vo=100,Eo=new Set(["say","wave","hush","open","choose"]),Be="x-agensis-bridge-secret";function ko(){return`cbs_${bn.randomBytes(24).toString("base64url")}`}function Ao(e){let t=e?.headers||{},n=String(t[Be]||t[Be.toLowerCase()]||"").trim();if(n)return n;let o=String(t.authorization||t.Authorization||"").trim().match(/^Bearer\s+(.+)$/i);return o?o[1].trim():""}function xo(e,t){let n=String(t||""),r=Ao(e);if(!n||!r)return!1;let o=Buffer.from(r),s=Buffer.from(n);return o.length!==s.length?!1:bn.timingSafeEqual(o,s)}function Io(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(oe.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim();return o||ko()}function Co(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 gn(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 W(e,t){e.write(`data: ${typeof t=="string"?t:JSON.stringify(t)}
|
|
38
38
|
|
|
39
|
-
`)}function _e(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
|
|
39
|
+
`)}function _e(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 To(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 Mo(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function Re(e,t){return e.some(n=>n===t||String(n).startsWith(`${t}=`))}function yn(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()}:
|
|
40
40
|
${s}`)}return n.join(`
|
|
41
41
|
|
|
42
|
-
`).trim()||"Say that the local Agensis runtime is connected."}function
|
|
43
|
-
`))>=0;)d(t.slice(0,l)),t=t.slice(l+1)},end(){t&&(d(t),t="")},get live(){return r?n:o},get result(){return s??(r?n:o)}}}function ge(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 Re(e){return`http://127.0.0.1:${e}`}function Do(e={},t={}){return String(t.agensisUrl||t.baseUrl||e.url||re.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function Ro(e){return String(e||"").slice(0,18)}function j(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Bo(e={},t={},n={}){let r=j(e.metadata)||{},o=j(e.page)||j(r.page)||{},s=j(e.client)||j(r.client)||{},i=j(r.runtime)||{},a=j(e.manifest)||j(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:j(e.project)||j(r.project)||null,manifest:a,selection:j(e.selection)||null,updatedAt:new Date().toISOString()}}function Po(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function Lo(e,t={},n=globalThis.fetch){let r=String(t.key||"").trim();if(!wo.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=Do(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:wn.hostname(),cwd:t.cwd||e.cwd||re.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||re.env.npm_package_version||"",permissionMode:t.permissionMode||e.permissionMode,model:t.model||e.model,metadata:j(t.metadata)||null,websiteSource:t.websiteSource||t.metadata?.websiteSource||"",page:j(t.page)||j(t.metadata?.page)||null,client:j(t.client)||j(t.metadata?.client)||null,manifest:j(t.manifest)||j(t.metadata?.manifest)||null})}),i=await s.json().catch(()=>({}));if(!s.ok)throw new Error(Po(s,i));return{key:r,baseUrl:o,data:i?.data||i}}async function vn(e,t={}){let n=Number(t.port??e.cursorBuddyPort??re.env.AGENSIS_CURSORBUDDY_PORT??fn),r=Ao(e,t),o=new Date().toISOString(),s=[],i=[],a=new Set,d=t.fetchImpl||globalThis.fetch,c=1,l=null,g=n,m=null,y=(u,h={})=>{let T={ts:new Date().toISOString(),event:u,detail:h};return s.push(T),s.length>200&&s.shift(),t.log?.(`CursorBuddy local bridge: ${u}${Object.keys(h).length?` ${JSON.stringify(h)}`:""}`),T},S=()=>({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()}),f=()=>{if(typeof t.connectionProvider!="function")return null;try{let u=t.connectionProvider();return!u||typeof u!="object"||Array.isArray(u)?null:{...S(),...u,connected:u.connected===!0}}catch{return null}},b=()=>{let u=f();return u?.connected===!1?u:m?{...S(),...u||{},...m,connected:!0,updatedAt:u?.updatedAt||m.updatedAt}:u||S()};function w(u={}){if(!u||typeof u!="object"||Array.isArray(u))return null;let h=String(u.action||u.type||"").trim().toLowerCase();if(!_o.has(h))return null;let T={id:c++,ts:new Date().toISOString(),action:h,text:String(u.text||u.say||u.message||"").slice(0,1200),label:String(u.label||"").slice(0,80),value:String(u.value||u.prompt||"").slice(0,1200),holdMs:Number.isFinite(u.holdMs)?Math.max(0,Math.min(6e4,u.holdMs)):void 0,source:String(u.source||"agensis-daemon").slice(0,80)};return u.options&&Array.isArray(u.options)&&(T.options=u.options.map(p=>({label:String(p?.label||"").slice(0,80),value:String(p?.value||p?.task||"").slice(0,1200)})).filter(p=>p.label).slice(0,6)),T}function E(u){for(i.push(u);i.length>bo;)i.shift();y("control",{id:u.id,action:u.action,chars:u.text.length});for(let h of[...a])try{W(h,{type:"command",command:u})}catch{a.delete(h)}return u}function _(u){let h=No(u);if(h){let T=w(h.command);return T&&(E(T),y("chat_control",{id:T.id,action:T.action})),{content:h.content,model:"cursorbuddy-local-control",fast:!0}}return null}async function k(u){let h=_(u);if(h)return h;let T=hn(u?.messages,l),p=yn(e,T,u?.model),A=await Z({cmd:p.cmd,args:p.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:p.stdin});if(A.error||A.status!==0)throw new Error(A.error?.message||String(A.stderr||"").trim()||`Command exited with status ${A.status}`);return{content:gn(A.stdout||A.stderr),model:p.model}}async function N(u,h){let T=`agensis-cursorbuddy-${Date.now()}`,p=_(u);if(p){let I=p.model||"cursorbuddy-local-control";return W(h,ge(T,I,p.content)),W(h,ge(T,I,"","stop")),W(h,"[DONE]"),y("chat_fast",{chars:p.content.length,model:I}),{content:p.content,model:I,fast:!0}}let A=hn(u?.messages,l),x=yn(e,A,u?.model,{stream:!0}),$="",V=I=>{I&&($+=I,W(h,ge(T,x.model||e.model,I)))},B=x.streamJson?$o(V):null,J=await Z({cmd:x.cmd,args:x.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:x.stdin,onData:I=>{if(B)B.feed(I);else{let R=String(I||"");$+=R,W(h,ge(T,x.model||e.model,R))}}});if(B){B.end();let I=B.result||"";!$&&I?V(I):$=I||$}if(J.error||J.status!==0){let I=J.error?.message||String(J.stderr||"").trim()||`Command exited with status ${J.status}`;throw new Error(I)}let X=B?$:gn($||J.stdout||J.stderr);return!B&&X&&X!==$&&(W(h,ge(T,x.model||e.model,X)),$=X),W(h,ge(T,x.model||e.model,"","stop")),W(h,"[DONE]"),{content:$||X,model:x.model}}let M=So.createServer(async(u,h)=>{if(h.setHeader("access-control-allow-origin","*"),h.setHeader("access-control-allow-methods","GET, POST, OPTIONS"),h.setHeader("access-control-allow-headers","content-type, authorization, x-agensis-bridge-secret"),u.method==="OPTIONS"){h.writeHead(204),h.end();return}let T=new URL(u.url||"/",Re(g||fn));if(!Io(u.method,T.pathname)&&!ko(u,r)){F(h,401,{ok:!1,error:"Authentication required",code:"bridge_auth_required"});return}if(u.method==="GET"&&T.pathname==="/cursorbuddy/health"){let p=Re(g);F(h,200,{ok:!0,runtime:"agensis-cli",backend:e.codingCmd,model:tt(e),daemonModel:e.model,port:g,host:wn.hostname(),pid:re.pid,bootedAt:o,authRequired:!0,authHeader:Be,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:l,endpoints:{chat:`${p}/v1/chat/completions`,chatStream:`${p}/v1/chat/completions`,edit:`${p}/cursorbuddy/edit`,context:`${p}/cursorbuddy/context`,control:`${p}/cursorbuddy/control`,controlStream:`${p}/cursorbuddy/control/stream`,logs:`${p}/cursorbuddy/logs`}});return}if(u.method==="GET"&&T.pathname==="/cursorbuddy/logs"){F(h,200,{ok:!0,events:s.slice(-100)});return}if(u.method==="GET"&&T.pathname==="/cursorbuddy/context"){F(h,200,{ok:!0,context:l});return}if(u.method==="GET"&&T.pathname==="/cursorbuddy/control"){let p=Number(T.searchParams.get("after")||0),A=i.filter(x=>x.id>p);F(h,200,{ok:!0,commands:A,latestId:i.at(-1)?.id||0});return}if(u.method==="GET"&&T.pathname==="/cursorbuddy/control/stream"){let p=Number(T.searchParams.get("after")||0);pn(h),a.add(h),W(h,{type:"ready",latestId:i.at(-1)?.id||0});for(let x of i.filter($=>$.id>p))W(h,{type:"command",command:x});let A=setInterval(()=>{try{W(h,{type:"ping",ts:new Date().toISOString()})}catch{a.delete(h),clearInterval(A)}},15e3);A.unref&&A.unref(),u.on("close",()=>{a.delete(h),clearInterval(A)});return}if(u.method==="POST"&&T.pathname==="/cursorbuddy/control"){try{let p=JSON.parse(await _e(u)||"{}"),A=w(p);if(!A){F(h,400,{ok:!1,error:"unsupported CursorBuddy control command"});return}let x=E(A);F(h,200,{ok:!0,command:x})}catch(p){y("control_error",{error:String(p?.message||p)}),F(h,400,{ok:!1,error:String(p?.message||p)})}return}if(u.method==="POST"&&T.pathname==="/cursorbuddy/context"){try{let p=JSON.parse(await _e(u)||"{}");l={url:String(p.url||"").slice(0,2048),title:String(p.title||"").slice(0,300),surface:String(p.surface||"").slice(0,80),instanceId:String(p.instanceId||"").slice(0,140),workspaceId:String(p.workspaceId||e.workspace||"").slice(0,120),agentId:String(p.agentId||e.agent||"").slice(0,120),runtime:p.runtime&&typeof p.runtime=="object"?p.runtime:null,page:p.page&&typeof p.page=="object"?p.page:null,client:p.client&&typeof p.client=="object"?p.client:null,project:p.project&&typeof p.project=="object"?p.project:null,manifest:p.manifest&&typeof p.manifest=="object"?p.manifest:null,selection:p.selection&&typeof p.selection=="object"?p.selection:null,updatedAt:new Date().toISOString()},y("context",{url:l.url,surface:l.surface,instanceId:l.instanceId}),F(h,200,{ok:!0,context:l})}catch(p){y("context_error",{error:String(p?.message||p)}),F(h,400,{ok:!1,error:String(p?.message||p)})}return}if(u.method==="POST"&&T.pathname==="/cursorbuddy/connect"){try{let p=JSON.parse(await _e(u)||"{}"),A=await Lo(e,p,d),x=A.data||{};m={connected:!0,mode:"agensis-claimed",keyId:Ro(A.key),agentId:String(x.agentId||x.agent?.id||e.agent||""),workspaceId:String(x.workspaceId||x.workspace_id||x.agent?.workspace_id||e.workspace||""),agensisUrl:A.baseUrl,handle:String(x.handle||x.agent?.handle||e.handle||""),name:String(x.agent?.name||p.name||e.name||"CursorBuddy runtime"),cwd:String(p.cwd||e.cwd||re.cwd()),surface:String(p.surface||"browser_extension"),command:String(x.command||x.localCommand||""),updatedAt:new Date().toISOString()},l=Bo(p,m,e),y("connect",{mode:m.mode,keyId:m.keyId,agentId:m.agentId,workspaceId:m.workspaceId,url:l.url}),F(h,200,{ok:!0,connection:m,claim:x})}catch(p){y("connect_error",{error:String(p?.message||p)}),F(h,400,{ok:!1,error:String(p?.message||p)})}return}if(u.method==="POST"&&T.pathname==="/cursorbuddy/edit"){try{let p=JSON.parse(await _e(u)||"{}"),A=[{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(p,null,2)}];y("edit_request",{selector:p?.target?.selector||""});let x=await k({messages:A,model:p?.model});y("edit_done",{chars:x.content.length}),F(h,200,{ok:!0,backend:e.codingCmd,cwd:e.cwd,content:x.content})}catch(p){y("edit_error",{error:String(p?.message||p)}),F(h,500,{ok:!1,error:String(p?.message||p)})}return}if(u.method==="POST"&&T.pathname.endsWith("/chat/completions")){try{let p=JSON.parse(await _e(u)||"{}");if(y("chat_request",{messages:Array.isArray(p.messages)?p.messages.length:0,model:bn(p.model,tt(e))}),p.stream===!0){pn(h);let x=await N(p,h);y("chat_done",{chars:x.content.length,stream:!0,fast:x.fast===!0}),h.end();return}let A=await k(p);y("chat_done",{chars:A.content.length,fast:A.fast===!0}),F(h,200,{id:`agensis-cursorbuddy-${Date.now()}`,object:"chat.completion",model:A.model||p.model||e.model,choices:[{index:0,message:{role:"assistant",content:A.content},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}catch(p){y("chat_error",{error:String(p?.message||p)}),F(h,500,{error:{message:String(p?.message||p)}})}return}h.writeHead(404),h.end("CursorBuddy local bridge")});return await new Promise((u,h)=>{M.once("error",h),M.listen(n,"127.0.0.1",()=>{g=M.address().port,M.off("error",h),u()})}),y("listening",{url:`${Re(g)}/cursorbuddy/health`}),{port:g,url:Re(g),secret:r,authHeader:Be,close(){return new Promise(u=>M.close(()=>u()))},getContext(){return l}}}import ye from"node:fs/promises";import Uo from"node:os";import Y from"node:path";var En=200,kn=256*1024,jo=2,Fo=new Set([".md",".markdown",".txt"]);function Go(e){return String(e||"").replace(/[^a-zA-Z0-9]/g,"-")}function nt({cwd:e,memoryDir:t,homedir:n=Uo.homedir()}={}){let r=String(t||"").trim();if(r)return r.startsWith("~")?Y.join(n,r.slice(1)):Y.resolve(r);let o=String(e||"").trim();return o?Y.join(n,".claude","projects",Go(o),"memory"):null}async function rt(e){if(!e)return null;try{let t=await ye.realpath(e);return(await ye.stat(t)).isDirectory()?t:null}catch{return null}}async function Ho(e,t){if(!e)throw new Error("memory root unavailable");let n=Y.isAbsolute(String(t))?String(t):Y.join(e,String(t)),r=await ye.realpath(n),o=e.endsWith(Y.sep)?e:e+Y.sep;if(r!==e&&!r.startsWith(o))throw new Error(`path escapes memory root: ${t}`);return r}function qo(e){let t=Y.basename(e).toLowerCase();return t==="memory.md"?"index":t==="claude.md"?"instructions":"memory"}async function ot(e,t,n,r){if(n>jo||r.length>=En)return;let o;try{o=await ye.readdir(t,{withFileTypes:!0})}catch{return}for(let s of o){if(r.length>=En)break;if(s.name.startsWith("."))continue;let i=Y.join(t,s.name);if(s.isDirectory())await ot(e,i,n+1,r);else if(s.isFile()&&Fo.has(Y.extname(s.name).toLowerCase())){let a=Y.relative(e,i);r.push({path:a,kind:qo(a)})}}}async function Jo(e){let t=await rt(e);if(!t)return[];let n=[];return await ot(t,t,0,n),n.sort((r,o)=>r.kind==="index"?-1:o.kind==="index"?1:r.path.localeCompare(o.path)),n}async function zo(e,t){let n=await rt(e),r=await Ho(n,t),o=await ye.readFile(r),s=o.length>kn;return{content:o.subarray(0,kn).toString("utf8"),byteSize:o.length,truncated:s}}async function An(e){let t=await rt(e);if(!t)return"";let n=[];await ot(t,t,0,n),n.sort((o,s)=>o.path.localeCompare(s.path));let r=[];for(let o of n)try{let s=await ye.stat(Y.join(t,o.path));r.push(`${o.path}:${s.size}:${Math.floor(s.mtimeMs)}`)}catch{}return r.join("|")}async function In(e){let t=await Jo(e),n=[];for(let r of t)try{let{content:o,byteSize:s}=await zo(e,r.path);n.push({path:r.path,kind:r.kind,content:o,byteSize:s})}catch{}return n}import it from"node:fs";import oe from"node:path";import xn from"node:os";function Ko(e){try{return it.statSync(e).isDirectory()}catch{return!1}}function Wo(e){try{return it.statSync(e).isFile()}catch{return!1}}function st(e){try{return it.readdirSync(e,{withFileTypes:!0})}catch{return[]}}function Cn({home:e=xn.homedir(),cwd:t=process.cwd()}={}){let n=[e&&oe.join(e,".claude","commands"),t&&oe.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 st(i)){if(a.name.startsWith("."))continue;if(a.name.endsWith(".md")){s(a.name.slice(0,-3),null);continue}let d=oe.join(i,a.name);if(a.isDirectory()||a.isSymbolicLink()&&Ko(d))for(let c of st(d))c.name.startsWith(".")||c.name.endsWith(".md")&&s(c.name.slice(0,-3),a.name)}return o}function at({home:e=xn.homedir(),cwd:t=process.cwd()}={}){let n=[e&&oe.join(e,".claude","skills"),e&&oe.join(e,".codex","skills"),t&&oe.join(t,".claude","skills")].filter(Boolean),r=new Map,o=(s,i)=>{!s||r.has(s)||r.set(s,{name:s,file:i||""})};for(let s of n)for(let i of st(s)){if(i.name.startsWith("."))continue;let a=oe.join(s,i.name);if(i.name.endsWith(".md"))o(i.name.slice(0,-3),a);else if(i.isDirectory()||i.isSymbolicLink()){let d=oe.join(a,"SKILL.md");o(i.name,Wo(d)?d:"")}}return[...r.values()].sort((s,i)=>s.name<i.name?-1:s.name>i.name?1:0)}function Tn(e={}){return at(e).map(t=>t.name)}import ct from"node:fs/promises";var Se=64*1024,Yo=200,Nn=4*1024*1024,Vo=2e3,Xo=512;function Mn(e,t,n=Se){let r=`
|
|
42
|
+
`).trim()||"Say that the local Agensis runtime is connected."}function Sn(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 No(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 Oo(e,t=280){let n=No(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 $o(e){let t=Oo(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 Ro(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 vn(e,t){let n=String(e||"").trim();return!n||Ro(n)?t:n}function En(e){let t=String(e||"").trim();return!t||t==="haiku-4.5"||t==="claude-haiku-4.5"?tt:t}function nt(e={}){return En(e.cursorBuddyModel||oe.env.AGENSIS_CURSORBUDDY_MODEL||tt)}function wn(e,t,n,r={}){let{cmd:o,args:s}=To(e.codingCmd||"claude -p"),i=[...s],a=En(vn(n,nt(e))),d="",c=!1;return Mo(o)?(a&&!Re(i,"--model")&&i.push("--model",a),r.stream===!0&&!Re(i,"--output-format")?(i.push("--output-format","stream-json","--include-partial-messages"),Re(i,"--verbose")||i.push("--verbose"),c=!0):(Re(i,"--output-format")||i.push("--output-format","json"),c=i.some(h=>String(h).includes("stream-json"))),d=t):i.push(t),{cmd:o,args:i,model:a,stdin:d,streamJson:c}}function Do(e=()=>{}){let t="",n="",r=!1,o="",s=null,i=c=>{c&&e(c)},a=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"){r=!0,n+=u.text,i(u.text);return}if(c.type==="result"&&typeof c.result=="string"){s=c.result;return}if(c.type==="assistant"&&c.message&&Array.isArray(c.message.content)){let h=c.message.content.filter(f=>f&&f.type==="text"&&typeof f.text=="string").map(f=>f.text).join("");h&&(o+=h)}},d=c=>{let u=String(c).trim();if(u)try{a(JSON.parse(u))}catch{}};return{feed(c){t+=String(c||"");let u;for(;(u=t.indexOf(`
|
|
43
|
+
`))>=0;)d(t.slice(0,u)),t=t.slice(u+1)},end(){t&&(d(t),t="")},get live(){return r?n:o},get result(){return s??(r?n:o)}}}function ge(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 De(e){return`http://127.0.0.1:${e}`}function Bo(e={},t={}){return String(t.agensisUrl||t.baseUrl||e.url||oe.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function Po(e){return String(e||"").slice(0,18)}function j(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Lo(e={},t={},n={}){let r=j(e.metadata)||{},o=j(e.page)||j(r.page)||{},s=j(e.client)||j(r.client)||{},i=j(r.runtime)||{},a=j(e.manifest)||j(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:j(e.project)||j(r.project)||null,manifest:a,selection:j(e.selection)||null,updatedAt:new Date().toISOString()}}function Uo(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function jo(e,t={},n=globalThis.fetch){let r=String(t.key||"").trim();if(!_o.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=Bo(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:_n.hostname(),cwd:t.cwd||e.cwd||oe.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||oe.env.npm_package_version||"",permissionMode:t.permissionMode||e.permissionMode,model:t.model||e.model,metadata:j(t.metadata)||null,websiteSource:t.websiteSource||t.metadata?.websiteSource||"",page:j(t.page)||j(t.metadata?.page)||null,client:j(t.client)||j(t.metadata?.client)||null,manifest:j(t.manifest)||j(t.metadata?.manifest)||null})}),i=await s.json().catch(()=>({}));if(!s.ok)throw new Error(Uo(s,i));return{key:r,baseUrl:o,data:i?.data||i}}async function kn(e,t={}){let n=Number(t.port??e.cursorBuddyPort??oe.env.AGENSIS_CURSORBUDDY_PORT??hn),r=Io(e,t),o=new Date().toISOString(),s=[],i=[],a=new Set,d=t.fetchImpl||globalThis.fetch,c=1,u=null,h=n,f=null,y=(l,g={})=>{let I={ts:new Date().toISOString(),event:l,detail:g};return s.push(I),s.length>200&&s.shift(),t.log?.(`CursorBuddy local bridge: ${l}${Object.keys(g).length?` ${JSON.stringify(g)}`:""}`),I},b=()=>({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 l=t.connectionProvider();return!l||typeof l!="object"||Array.isArray(l)?null:{...b(),...l,connected:l.connected===!0}}catch{return null}},w=()=>{let l=m();return l?.connected===!1?l:f?{...b(),...l||{},...f,connected:!0,updatedAt:l?.updatedAt||f.updatedAt}:l||b()};function S(l={}){if(!l||typeof l!="object"||Array.isArray(l))return null;let g=String(l.action||l.type||"").trim().toLowerCase();if(!Eo.has(g))return null;let I={id:c++,ts:new Date().toISOString(),action:g,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)&&(I.options=l.options.map(p=>({label:String(p?.label||"").slice(0,80),value:String(p?.value||p?.task||"").slice(0,1200)})).filter(p=>p.label).slice(0,6)),I}function E(l){for(i.push(l);i.length>vo;)i.shift();y("control",{id:l.id,action:l.action,chars:l.text.length});for(let g of[...a])try{W(g,{type:"command",command:l})}catch{a.delete(g)}return l}function _(l){let g=$o(l);if(g){let I=S(g.command);return I&&(E(I),y("chat_control",{id:I.id,action:I.action})),{content:g.content,model:"cursorbuddy-local-control",fast:!0}}return null}async function k(l){let g=_(l);if(g)return g;let I=yn(l?.messages,u),p=wn(e,I,l?.model),A=await Z({cmd:p.cmd,args:p.args,cwd:e.cwd,timeoutMs:Math.min(Number(e.timeoutMs||18e5),5*60*1e3),heartbeatMs:e.heartbeatMs,label:"cursorbuddy local chat",input:p.stdin});if(A.error||A.status!==0)throw new Error(A.error?.message||String(A.stderr||"").trim()||`Command exited with status ${A.status}`);return{content:Sn(A.stdout||A.stderr),model:p.model}}async function N(l,g){let I=`agensis-cursorbuddy-${Date.now()}`,p=_(l);if(p){let x=p.model||"cursorbuddy-local-control";return W(g,ge(I,x,p.content)),W(g,ge(I,x,"","stop")),W(g,"[DONE]"),y("chat_fast",{chars:p.content.length,model:x}),{content:p.content,model:x,fast:!0}}let A=yn(l?.messages,u),C=wn(e,A,l?.model,{stream:!0}),$="",V=x=>{x&&($+=x,W(g,ge(I,C.model||e.model,x)))},B=C.streamJson?Do(V):null,J=await Z({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,onData:x=>{if(B)B.feed(x);else{let D=String(x||"");$+=D,W(g,ge(I,C.model||e.model,D))}}});if(B){B.end();let x=B.result||"";!$&&x?V(x):$=x||$}if(J.error||J.status!==0){let x=J.error?.message||String(J.stderr||"").trim()||`Command exited with status ${J.status}`;throw new Error(x)}let X=B?$:Sn($||J.stdout||J.stderr);return!B&&X&&X!==$&&(W(g,ge(I,C.model||e.model,X)),$=X),W(g,ge(I,C.model||e.model,"","stop")),W(g,"[DONE]"),{content:$||X,model:C.model}}let M=bo.createServer(async(l,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"),l.method==="OPTIONS"){g.writeHead(204),g.end();return}let I=new URL(l.url||"/",De(h||hn));if(!Co(l.method,I.pathname)&&!xo(l,r)){F(g,401,{ok:!1,error:"Authentication required",code:"bridge_auth_required"});return}if(l.method==="GET"&&I.pathname==="/cursorbuddy/health"){let p=De(h);F(g,200,{ok:!0,runtime:"agensis-cli",backend:e.codingCmd,model:nt(e),daemonModel:e.model,port:h,host:_n.hostname(),pid:oe.pid,bootedAt:o,authRequired:!0,authHeader:Be,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:u,endpoints:{chat:`${p}/v1/chat/completions`,chatStream:`${p}/v1/chat/completions`,edit:`${p}/cursorbuddy/edit`,context:`${p}/cursorbuddy/context`,control:`${p}/cursorbuddy/control`,controlStream:`${p}/cursorbuddy/control/stream`,logs:`${p}/cursorbuddy/logs`}});return}if(l.method==="GET"&&I.pathname==="/cursorbuddy/logs"){F(g,200,{ok:!0,events:s.slice(-100)});return}if(l.method==="GET"&&I.pathname==="/cursorbuddy/context"){F(g,200,{ok:!0,context:u});return}if(l.method==="GET"&&I.pathname==="/cursorbuddy/control"){let p=Number(I.searchParams.get("after")||0),A=i.filter(C=>C.id>p);F(g,200,{ok:!0,commands:A,latestId:i.at(-1)?.id||0});return}if(l.method==="GET"&&I.pathname==="/cursorbuddy/control/stream"){let p=Number(I.searchParams.get("after")||0);gn(g),a.add(g),W(g,{type:"ready",latestId:i.at(-1)?.id||0});for(let C of i.filter($=>$.id>p))W(g,{type:"command",command:C});let A=setInterval(()=>{try{W(g,{type:"ping",ts:new Date().toISOString()})}catch{a.delete(g),clearInterval(A)}},15e3);A.unref&&A.unref(),l.on("close",()=>{a.delete(g),clearInterval(A)});return}if(l.method==="POST"&&I.pathname==="/cursorbuddy/control"){try{let p=JSON.parse(await _e(l)||"{}"),A=S(p);if(!A){F(g,400,{ok:!1,error:"unsupported CursorBuddy control command"});return}let C=E(A);F(g,200,{ok:!0,command:C})}catch(p){y("control_error",{error:String(p?.message||p)}),F(g,400,{ok:!1,error:String(p?.message||p)})}return}if(l.method==="POST"&&I.pathname==="/cursorbuddy/context"){try{let p=JSON.parse(await _e(l)||"{}");u={url:String(p.url||"").slice(0,2048),title:String(p.title||"").slice(0,300),surface:String(p.surface||"").slice(0,80),instanceId:String(p.instanceId||"").slice(0,140),workspaceId:String(p.workspaceId||e.workspace||"").slice(0,120),agentId:String(p.agentId||e.agent||"").slice(0,120),runtime:p.runtime&&typeof p.runtime=="object"?p.runtime:null,page:p.page&&typeof p.page=="object"?p.page:null,client:p.client&&typeof p.client=="object"?p.client:null,project:p.project&&typeof p.project=="object"?p.project:null,manifest:p.manifest&&typeof p.manifest=="object"?p.manifest:null,selection:p.selection&&typeof p.selection=="object"?p.selection:null,updatedAt:new Date().toISOString()},y("context",{url:u.url,surface:u.surface,instanceId:u.instanceId}),F(g,200,{ok:!0,context:u})}catch(p){y("context_error",{error:String(p?.message||p)}),F(g,400,{ok:!1,error:String(p?.message||p)})}return}if(l.method==="POST"&&I.pathname==="/cursorbuddy/connect"){try{let p=JSON.parse(await _e(l)||"{}"),A=await jo(e,p,d),C=A.data||{};f={connected:!0,mode:"agensis-claimed",keyId:Po(A.key),agentId:String(C.agentId||C.agent?.id||e.agent||""),workspaceId:String(C.workspaceId||C.workspace_id||C.agent?.workspace_id||e.workspace||""),agensisUrl:A.baseUrl,handle:String(C.handle||C.agent?.handle||e.handle||""),name:String(C.agent?.name||p.name||e.name||"CursorBuddy runtime"),cwd:String(p.cwd||e.cwd||oe.cwd()),surface:String(p.surface||"browser_extension"),command:String(C.command||C.localCommand||""),updatedAt:new Date().toISOString()},u=Lo(p,f,e),y("connect",{mode:f.mode,keyId:f.keyId,agentId:f.agentId,workspaceId:f.workspaceId,url:u.url}),F(g,200,{ok:!0,connection:f,claim:C})}catch(p){y("connect_error",{error:String(p?.message||p)}),F(g,400,{ok:!1,error:String(p?.message||p)})}return}if(l.method==="POST"&&I.pathname==="/cursorbuddy/edit"){try{let p=JSON.parse(await _e(l)||"{}"),A=[{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(p,null,2)}];y("edit_request",{selector:p?.target?.selector||""});let C=await k({messages:A,model:p?.model});y("edit_done",{chars:C.content.length}),F(g,200,{ok:!0,backend:e.codingCmd,cwd:e.cwd,content:C.content})}catch(p){y("edit_error",{error:String(p?.message||p)}),F(g,500,{ok:!1,error:String(p?.message||p)})}return}if(l.method==="POST"&&I.pathname.endsWith("/chat/completions")){try{let p=JSON.parse(await _e(l)||"{}");if(y("chat_request",{messages:Array.isArray(p.messages)?p.messages.length:0,model:vn(p.model,nt(e))}),p.stream===!0){gn(g);let C=await N(p,g);y("chat_done",{chars:C.content.length,stream:!0,fast:C.fast===!0}),g.end();return}let A=await k(p);y("chat_done",{chars:A.content.length,fast:A.fast===!0}),F(g,200,{id:`agensis-cursorbuddy-${Date.now()}`,object:"chat.completion",model:A.model||p.model||e.model,choices:[{index:0,message:{role:"assistant",content:A.content},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}catch(p){y("chat_error",{error:String(p?.message||p)}),F(g,500,{error:{message:String(p?.message||p)}})}return}g.writeHead(404),g.end("CursorBuddy local bridge")});return await new Promise((l,g)=>{M.once("error",g),M.listen(n,"127.0.0.1",()=>{h=M.address().port,M.off("error",g),l()})}),y("listening",{url:`${De(h)}/cursorbuddy/health`}),{port:h,url:De(h),secret:r,authHeader:Be,close(){return new Promise(l=>M.close(()=>l()))},getContext(){return u}}}import ye from"node:fs/promises";import Fo from"node:os";import Y from"node:path";var An=200,xn=256*1024,Go=2,Ho=new Set([".md",".markdown",".txt"]);function qo(e){return String(e||"").replace(/[^a-zA-Z0-9]/g,"-")}function rt({cwd:e,memoryDir:t,homedir:n=Fo.homedir()}={}){let r=String(t||"").trim();if(r)return r.startsWith("~")?Y.join(n,r.slice(1)):Y.resolve(r);let o=String(e||"").trim();return o?Y.join(n,".claude","projects",qo(o),"memory"):null}async function ot(e){if(!e)return null;try{let t=await ye.realpath(e);return(await ye.stat(t)).isDirectory()?t:null}catch{return null}}async function Jo(e,t){if(!e)throw new Error("memory root unavailable");let n=Y.isAbsolute(String(t))?String(t):Y.join(e,String(t)),r=await ye.realpath(n),o=e.endsWith(Y.sep)?e:e+Y.sep;if(r!==e&&!r.startsWith(o))throw new Error(`path escapes memory root: ${t}`);return r}function zo(e){let t=Y.basename(e).toLowerCase();return t==="memory.md"?"index":t==="claude.md"?"instructions":"memory"}async function st(e,t,n,r){if(n>Go||r.length>=An)return;let o;try{o=await ye.readdir(t,{withFileTypes:!0})}catch{return}for(let s of o){if(r.length>=An)break;if(s.name.startsWith("."))continue;let i=Y.join(t,s.name);if(s.isDirectory())await st(e,i,n+1,r);else if(s.isFile()&&Ho.has(Y.extname(s.name).toLowerCase())){let a=Y.relative(e,i);r.push({path:a,kind:zo(a)})}}}async function Ko(e){let t=await ot(e);if(!t)return[];let n=[];return await st(t,t,0,n),n.sort((r,o)=>r.kind==="index"?-1:o.kind==="index"?1:r.path.localeCompare(o.path)),n}async function Wo(e,t){let n=await ot(e),r=await Jo(n,t),o=await ye.readFile(r),s=o.length>xn;return{content:o.subarray(0,xn).toString("utf8"),byteSize:o.length,truncated:s}}async function In(e){let t=await ot(e);if(!t)return"";let n=[];await st(t,t,0,n),n.sort((o,s)=>o.path.localeCompare(s.path));let r=[];for(let o of n)try{let s=await ye.stat(Y.join(t,o.path));r.push(`${o.path}:${s.size}:${Math.floor(s.mtimeMs)}`)}catch{}return r.join("|")}async function Cn(e){let t=await Ko(e),n=[];for(let r of t)try{let{content:o,byteSize:s}=await Wo(e,r.path);n.push({path:r.path,kind:r.kind,content:o,byteSize:s})}catch{}return n}import at from"node:fs";import se from"node:path";import Tn from"node:os";function Yo(e){try{return at.statSync(e).isDirectory()}catch{return!1}}function Vo(e){try{return at.statSync(e).isFile()}catch{return!1}}function it(e){try{return at.readdirSync(e,{withFileTypes:!0})}catch{return[]}}function Mn({home:e=Tn.homedir(),cwd:t=process.cwd()}={}){let n=[e&&se.join(e,".claude","commands"),t&&se.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 it(i)){if(a.name.startsWith("."))continue;if(a.name.endsWith(".md")){s(a.name.slice(0,-3),null);continue}let d=se.join(i,a.name);if(a.isDirectory()||a.isSymbolicLink()&&Yo(d))for(let c of it(d))c.name.startsWith(".")||c.name.endsWith(".md")&&s(c.name.slice(0,-3),a.name)}return o}function ct({home:e=Tn.homedir(),cwd:t=process.cwd()}={}){let n=[e&&se.join(e,".claude","skills"),e&&se.join(e,".codex","skills"),t&&se.join(t,".claude","skills")].filter(Boolean),r=new Map,o=(s,i)=>{!s||r.has(s)||r.set(s,{name:s,file:i||""})};for(let s of n)for(let i of it(s)){if(i.name.startsWith("."))continue;let a=se.join(s,i.name);if(i.name.endsWith(".md"))o(i.name.slice(0,-3),a);else if(i.isDirectory()||i.isSymbolicLink()){let d=se.join(a,"SKILL.md");o(i.name,Vo(d)?d:"")}}return[...r.values()].sort((s,i)=>s.name<i.name?-1:s.name>i.name?1:0)}function Nn(e={}){return ct(e).map(t=>t.name)}import ut from"node:fs/promises";var Se=64*1024,Xo=200,$n=4*1024*1024,Qo=2e3,Zo=512;function On(e,t,n=Se){let r=`
|
|
44
44
|
|
|
45
45
|
... [truncated by agensis-agent: ${t}]
|
|
46
|
-
`,o=Math.max(0,n-Buffer.byteLength(r));return`${Buffer.from(String(e||"")).subarray(0,o).toString("utf8").replace(/\uFFFD+$/,"")}${r}`}function Qo(e){let t=String(e||"").split(/\r?\n/),n="";if(t[0]?.trim()==="---")for(let r=1;r<t.length&&r<200&&t[r].trim()!=="---";r+=1){let o=/^description:\s*(.*)$/i.exec(t[r]);if(!o)continue;let s=o[1].trim();if(s&&!/^[|>][-+]?$/.test(s)){n=s.replace(/^["']|["']$/g,"");break}let i=[];for(let a=r+1;a<t.length&&a<200&&!(t[a].trim()==="---"||t[a].trim()&&!/^\s/.test(t[a]));a+=1)i.push(t[a].trim());n=i.join(" ").trim();break}if(!n){let r=t.findIndex((i,a)=>a>0&&i.trim()==="---"),s=(t[0]?.trim()==="---"&&r>0?t.slice(r+1):t).find(i=>i.trim()&&i.trim()!=="---");n=String(s||"").replace(/^#+\s*/,"").trim()}return n.slice(0,Vo)}function On(e){try{return at(e).slice(0,Yo)}catch{return[]}}async function Zo(e){let t;try{t=await ct.open(e,"r")}catch{return null}try{let n=Buffer.alloc(Se+1),{bytesRead:r}=await t.read(n,0,n.length,0);return n.subarray(0,r)}catch{return null}finally{await t.close().catch(()=>{})}}async function es(e,t){let n=await Zo(e.file);if(!n)return null;let r=n.toString("utf8"),o=Qo(r),s=n.length>Se,i=Math.min(Se,Math.max(0,t)),a=Buffer.byteLength(r)>i;if(!s&&!a)return{skill:e.name,path:e.file,summary:o,content:r,truncated:!1};let d=s?await ts(e.file):0,c=s&&!a?`the file is ${d?`${d} bytes`:`over ${Se} bytes`}; only the first ${Se} were synced`:`this sync reached its ${Nn}-byte ceiling`,l=i<Xo?Mn("",c,Number.MAX_SAFE_INTEGER):Mn(r,c,i);return{skill:e.name,path:e.file,summary:o,content:l,truncated:!0}}async function ts(e){try{return(await ct.stat(e)).size}catch{return 0}}async function lt(e={}){let t=[];for(let n of On(e)){if(!n.file){t.push(`${n.name}:-`);continue}try{let r=await ct.stat(n.file);t.push(`${n.name}:${n.file}:${r.size}:${Math.floor(r.mtimeMs)}`)}catch{t.push(`${n.name}:-`)}}return t.join("|")}async function $n(e={}){let t=[],n=0;for(let r of On(e))if(r.file)try{let o=await es(r,Nn-n);if(!o)continue;n+=Buffer.byteLength(o.content),t.push(o)}catch{}return t}import{readFile as ns}from"node:fs/promises";var rs=new Set(["127.0.0.1","localhost","::1","[::1]"]);function Dn(e,t,n){let r=Number(e);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.trunc(r))):t}function os(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(!rs.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:Dn(e.contextWindow,void 0,1e7)}:{},maxConcurrency:Dn(e.maxConcurrency,1,64),shared:!0}}async function Rn(e){if(!e)return[];let t=JSON.parse(await ns(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(os).filter(Boolean)}function Bn(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 Pn({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(w=>w.id===t?.model);if(!a)throw new Error(`Shared model '${t?.model||""}' is not available.`);let d={"content-type":"application/json"},c=a.apiKeyEnv?s[a.apiKeyEnv]:"";c&&(d.authorization=`Bearer ${c}`),n({action:"agent_inference_started",requestId:i,model:a.id});let{requestId:l,model:g,type:m,action:y,...S}=t,f=await o(`${a.baseUrl}/chat/completions`,{method:"POST",headers:d,body:JSON.stringify({...S,model:a.upstreamModel,stream:t.stream===!0}),signal:r});if(!f.ok){let w=await f.text().catch(()=>"");throw new Error(w||`Local model returned HTTP ${f.status}.`)}if(t.stream===!0){if(!f.body)throw new Error("Local model returned an empty stream.");let w=f.body.getReader(),E=new TextDecoder,_="",k,N=h=>{let T=h.trim();if(!T.startsWith("data:"))return!1;let p=T.slice(5).trim();if(!p)return!1;if(p==="[DONE]")return!0;try{let A=JSON.parse(p);A?.usage&&(k=A.usage),n({action:"agent_inference_delta",requestId:i,model:a.id,chunk:A})}catch{}return!1},M=!1;for(;!M;){let{done:h,value:T}=await w.read();_+=E.decode(T||new Uint8Array,{stream:!h});let p=_.split(/\r?\n/);_=h?"":p.pop()||"";for(let A of p)if(N(A)){M=!0;break}if(h)break}_&&N(_);let u={action:"agent_inference_result",requestId:i,model:a.id,...k?{usage:k}:{}};return n(u),u}let b=await f.json();return n({action:"agent_inference_result",requestId:i,model:a.id,response:b}),b}Ue();var Es=30*60*1e3,ks=15*1e3,er=2,As=10*1024,Is="claude-opus-4-8",ae="0.1.36";async function Fe(e={}){let t=xs(e);t.sharedModels=t.share?await Rn(t.sharedModelsFile):[];let n=!1,r=null,o=null,s=null,i=null,a=0,d=null,c=null,l="",g=null,m=!1,y=null,S=new Map,f=Jt({send:I=>P(r,I),log:O}),b=[],w=I=>{b.length>=32&&b.shift(),b.push(I),O(`Socket was gone \u2014 parked the result for job ${I.jobId} to re-send on reconnect`)},E=()=>{if(b.length!==0)for(let I of b.splice(0,b.length))P(r,I)?O(`Re-sent the result for job ${I.jobId} after reconnecting`):b.push(I)},_=null,k={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"},N=new Map,M=new Map,u=[],h=()=>k,T=()=>({connected:m&&!!t.cursorBuddyRuntime,mode:t.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:y?.agentId||y?.agent_id||t.agent,workspaceId:y?.workspaceId||y?.workspace_id||t.workspace,agensisUrl:t.url,handle:y?.handle||t.handle,name:y?.name||t.name,cwd:t.cwd,updatedAt:new Date().toISOString()}),p=()=>{_||!t.lanListener||(_=new ke.Server({port:0}),_.on("listening",()=>{let{port:I}=_.address();k={transport:"ws",listening:!0,addrs:Zs(I),auth:"hub-pairwise"},O(`Agent-mesh LAN listener on port ${I}`),Ee(r,t,h())}),_.on("connection",I=>{let R=!1,v=setTimeout(()=>{if(!R)try{I.close(1008,"peer auth required")}catch{}},5e3);I.once("message",D=>{clearTimeout(v);let U=gt(D),H=U?.type==="peer_auth"?N.get(U.ticket):null;if(!H||H.fromAgentId!==U.fromAgentId||Date.now()>H.exp){try{I.close(1008,"invalid ticket")}catch{}return}N.delete(U.ticket),R=!0,I.on("message",z=>{let L=gt(z);L?.type==="agent_job"&&L.job?.id&&c.enqueue({...L.job,key:L.job.id,lane:tr(L.job),ws:r}).accepted&&O(`Queued peer-handoff job ${L.job.id} from ${U.fromAgentId}`)})})}),_.on("error",I=>O(`LAN listener error: ${I?.message||I}`)))},A=()=>{if(_){try{_.close()}catch{}_=null}k={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"}},x=I=>new Promise((R,v)=>{if(!P(r,{action:"peer_ticket_request",targetAgentId:I})){v(new Error("hub socket not open"));return}let D=M.get(I)||[];D.push({resolve:R,reject:v}),M.set(I,D),setTimeout(()=>{let U=M.get(I)||[],H=U.findIndex(z=>z.resolve===R);H>=0&&(U.splice(H,1),v(new Error("peer ticket request timed out")))},1e4)}),$=()=>new Promise((I,R)=>{if(!P(r,{action:"peer_list_request"})){R(new Error("hub socket not open"));return}u.push(I),setTimeout(()=>{let v=u.indexOf(I);v>=0&&(u.splice(v,1),I([]))},1e4)}),V=async(I,R)=>{let v=null;try{let U=(await $()).find(L=>L.agentId===I&&L.reach?.listening&&L.reach.addrs?.length);if(!U)return!1;let H=await x(I),z=H.peer?.addrs?.[0]||U.reach.addrs[0];return!z?.host||!z?.port?!1:(v=new ke(`ws://${z.host}:${z.port}`),await new Promise((L,ze)=>{v.once("open",L),v.once("error",ze),setTimeout(()=>ze(new Error("peer connect timed out")),5e3)}),P(v,{type:"peer_auth",ticket:H.ticket,fromAgentId:t.agent}),P(v,{type:"agent_job",job:R}),!0)}catch(D){return O(`Peer handoff to ${I} failed, falling back to hub relay: ${D?.message||D}`),!1}finally{try{v?.close()}catch{}}},B=()=>{n=!0,sr(S),f.shutdown("The agent daemon shut down before this was approved."),o&&clearTimeout(o),s&&clearInterval(s),i&&clearInterval(i),g&&(g.close().catch(()=>{}),g=null),A(),zn(t,{status:"stopped",connected:!1});try{r?.close()}catch{}d&&d()};if(c=mn({concurrency:t.once?1:t.maxConcurrency,runJob:async(I,R)=>{await Gs(t,I,{...R,requestPermission:f.request}),t.once&&B()}}),t.cursorBuddyBridge)try{g=await vn(t,{port:t.cursorBuddyPort,authSecret:t.cursorBuddyBridgeSecret||void 0,log:O,connectionProvider:T}),g?.secret&&(t.cursorBuddyBridgeSecret=g.secret)}catch(I){if(ri(I)){let R=await oi(t.cursorBuddyPort);if(R?.ok){let v=R.pid?` pid ${R.pid}`:"";O(`CursorBuddy local bridge already running on http://127.0.0.1:${t.cursorBuddyPort}${v}`)}else O(`CursorBuddy local bridge port ${t.cursorBuddyPort} is in use but did not answer health`)}else O(`CursorBuddy local bridge unavailable: ${I?.message||I}`);g=null}C.once("SIGINT",B),C.once("SIGTERM",B);let J=()=>{if(n)return;let I=Ts(t.url,t.token,t);l="",O(`Connecting to ${I.replace(t.token,"redacted")}`),r=new ke(I),r.on("open",async()=>{m=!1,y=null,O(`Connected. Registering @${t.handle||"agent"} from ${t.cwd}`),P(r,{type:"auth",token:t.token});let R=await Wn(t);P(r,{action:"agent_register",workspaceId:t.workspace,agentId:t.agent,handle:t.handle,name:t.name,host:Ie.hostname(),cwd:t.cwd,...R?{identity:R}:{},metadata:{codingCmd:t.codingCmd,model:t.model,permissionMode:t.permissionMode,permissionFlags:bt(t.permissionMode),once:t.once,runtime:"agensis",version:ae}}),s=setInterval(()=>{Promise.all([mr(t,h()).catch(()=>null),ft(t).catch(()=>null)]).then(([v,D])=>{P(r,{action:"agent_heartbeat",...v?{capabilitiesHash:v.capabilitiesHash,memoryHash:v.memoryHash}:{},...v?.skillsHash?{skillsHash:v.skillsHash}:{},metadata:ht(t,c,D,ir(t)?g?.getContext?.():null,S)})})},t.heartbeatMs),s.unref&&s.unref()}),r.on("message",R=>{let v=gt(R);if(v){if(v.type==="agent_registered"){m=!0,y=v.connection||v.agent||null,nr(t,v.agent),E(),O(`Registered as ${v.connection?.name||t.name} on ${v.connection?.host||Ie.hostname()}`),t.onRegistered&&Promise.resolve(t.onRegistered(t,v)).catch(D=>{O(`Profile save failed: ${D?.message||D}`)}),mt(t,v.agent).catch(()=>{}),Qn(t).catch(()=>{}),rr(r,t),or(r,t),p(),Ee(r,t,h());return}if(v.type==="agent_config"){nr(t,v.agent),O(`Updated config for @${t.handle||"agent"}: model=${t.model}, permission=${t.permissionMode}`),mt(t,v.agent).catch(()=>{});return}if(v.type==="agent_memory_refresh"){rr(r,t),Ee(r,t,h());return}if(v.type==="agent_capabilities_refresh"){Ee(r,t,h());return}if(v.type==="agent_skills_refresh"){or(r,t);return}if(v.type==="agent_inference_cancel"){S.get(String(v.requestId||""))?.abort();return}if(v.type==="agent_job_cancel"){let D=String(v.jobId||"");D&&(f.cancelJob(D,v.reason||"Cancelled by Agensis"),c.cancel(D,v.reason||"Cancelled by Agensis")&&O(`Cancelled job ${D}`));return}if(v.type==="agent_permission_decision"){f.decide(v);return}if(v.type==="agent_inference_request"&&v.requestId){let D=String(v.requestId),U=t.sharedModels.find(L=>L.id===v.model),H=[...S.values()].filter(L=>L.model===v.model).length;if(!U){P(r,{action:"agent_inference_error",requestId:D,error:`Shared model '${v.model||""}' is not available.`});return}if(H>=U.maxConcurrency){P(r,{action:"agent_inference_error",requestId:D,error:"Shared model is at capacity.",code:"capacity_exhausted"});return}let z=new AbortController;S.set(D,{abort:()=>z.abort(),model:U.id}),P(r,{action:"agent_heartbeat",metadata:ht(t,c,null,null,S)}),Pn({models:t.sharedModels,request:v,signal:z.signal,send:L=>P(r,L)}).catch(L=>{P(r,{action:"agent_inference_error",requestId:D,error:z.signal.aborted?"Inference cancelled.":L?.message||String(L),code:z.signal.aborted?"cancelled":"inference_failed"})}).finally(()=>{S.delete(D),P(r,{action:"agent_heartbeat",metadata:ht(t,c,null,null,S)})});return}if(v.type==="peer_ticket"){let D=v.peer?.agentId,U=M.get(D)||[],H=U.shift();U.length?M.set(D,U):M.delete(D),H&&H.resolve(v);return}if(v.type==="peer_ticket_grant"){N.set(v.ticket,{fromAgentId:v.fromAgentId,exp:v.exp});return}if(v.type==="peer_list"){let D=u.shift();D&&D(Array.isArray(v.peers)?v.peers:[]);return}if(v.type==="agent_reach_disable"){A(),Ee(r,t,h());return}if(v.type==="error"){O(`Server rejected request: ${v.message||"unknown error"}`);return}if(v.type==="agent_disabled"){m=!1,y=null,O(`Agent disabled by Agensis: ${v.reason||"deactivated"}`),B();return}if(v.type==="agent_job"&&v.job?.id){let D=c.enqueue({...v.job,key:v.job.id,lane:tr(v.job),get ws(){return r},parkResult:w});D.accepted&&(a+=1,O(`Queued job ${v.job.id} at position ${D.position}`),t.once&&c.idle().then(()=>B()))}}}),r.on("close",(R,v)=>{sr(S),f.shutdown(),m=!1,y=null;let D=String(v||"");if(O(`Socket closed (${R||"no-code"}${D?`: ${D}`:""})`),s&&(clearInterval(s),s=null),R===1008&&/agent deactivated|authentication failed/i.test(D)){O("Stopping daemon because Agensis rejected this agent connection."),B();return}if(l==="ECONNREFUSED"&&Ns(t.url)){O("Local agent backend is not running on 127.0.0.1:3142."),O("Start it in another terminal with: npm run backend"),O("Then rerun this connect command."),B();return}t.once&&a>0&&c.active()===0&&c.size()===0&&B(),!(n||t.once)&&(o=setTimeout(J,2e3),o.unref&&o.unref())}),r.on("error",R=>{l=R?.code||"",O(`Socket error: ${R?.message||R}`)})},X=async()=>{let I=await ft(t).catch(()=>null);await Jn(t,{busy:c.active()>0,active:c.active(),queueSize:c.size(),connected:r?.readyState===ke.OPEN,agentStatus:I?.status,agentNote:I?.note}).catch(()=>{})};X(),i=setInterval(()=>{X()},t.heartbeatMs),i.unref&&i.unref(),J(),await new Promise(I=>{let R=setInterval(async()=>{t.once&&a>0&&c.active()===0&&c.size()===0&&B(),n&&B()},500);d=()=>{clearInterval(R),I()}}),d=null,C.off("SIGINT",B),C.off("SIGTERM",B)}function xs(e){let t=Cs(e.cursorBuddyBridge),n=e.noCoding===!0||C.env.AGENSIS_NO_CODING==="1",o=!se(e.fullCliContext,se(C.env.AGENSIS_FULL_CLI_CONTEXT,!1))&&se(e.leanCli,!0),s={url:String(e.url||e.baseUrl||C.env.AGENSIS_URL||"").trim(),token:String(e.token||C.env.AGENSIS_TOKEN||"").trim(),workspace:String(e.workspace||e.workspaceId||C.env.AGENSIS_WORKSPACE||C.env.AGENSIS_WORKSPACE_ID||"").trim(),agent:String(e.agent||e.agentId||C.env.AGENSIS_AGENT||C.env.AGENSIS_AGENT_ID||"").trim(),handle:hr(e.handle||C.env.AGENSIS_HANDLE||e.name||C.env.AGENSIS_NAME||"agent"),name:String(e.name||C.env.AGENSIS_NAME||e.handle||C.env.AGENSIS_HANDLE||"agensis Agent").trim(),cwd:String(e.cwd||C.env.AGENSIS_CWD||C.cwd()).trim(),codingCmd:n?"":String(e.codingCmd||C.env.AGENSIS_CODING_CMD||C.env.CODING_CMD||"claude -p").trim(),ampCmd:String(e.ampCmd||C.env.AGENSIS_AMP_CMD||"amp").trim()||"amp",model:wt(e.model||C.env.AGENSIS_MODEL||C.env.CLAUDE_MODEL||""),permissionMode:Ge(e.permissionMode||e.permission_mode||e.permission||C.env.AGENSIS_PERMISSION_MODE||"default"),timeoutMs:Number(e.timeoutMs||C.env.AGENSIS_TIMEOUT_MS||Es),heartbeatMs:Number(e.heartbeatMs||C.env.AGENSIS_HEARTBEAT_MS||ks),maxConcurrency:Math.max(1,Number(e.maxConcurrency||C.env.AGENSIS_MAX_CONCURRENCY||er)||er),once:!!(e.once||C.env.AGENSIS_ONCE==="1"),exitOnOnce:!!e.exitOnOnce,onRegistered:typeof e.onRegistered=="function"?e.onRegistered:null,primaryDaemon:!!(e.primaryDaemon||C.env.AGENSIS_PRIMARY_DAEMON==="1"),cursorBuddyRuntime:!!(e.cursorBuddyRuntime||C.env.AGENSIS_CURSORBUDDY_RUNTIME==="1"),cursorBuddyBridge:t,cursorBuddyPort:Number(e.cursorBuddyPort||C.env.AGENSIS_CURSORBUDDY_PORT||8787),cursorBuddyBridgeSecret:String(e.cursorBuddyBridgeSecret||C.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),cursorBuddyModel:String(e.cursorBuddyModel||C.env.AGENSIS_CURSORBUDDY_MODEL||"haiku-4.5").trim(),lanListener:!!(e.lanListener||e.lan||C.env.AGENSIS_LAN==="1"),share:!!(e.share||C.env.AGENSIS_SHARE==="1"),sharedModelsFile:String(e.sharedModelsFile||C.env.AGENSIS_SHARED_MODELS_FILE||"").trim(),noCoding:n,leanCli:o,fastConnection:se(e.fastConnection,se(C.env.AGENSIS_FAST_CONNECTION,!0)),syncMemory:se(e.syncMemory,C.env.AGENSIS_SYNC_MEMORY==="1"),syncSkills:se(e.syncSkills,se(C.env.AGENSIS_SYNC_SKILLS,!0)),hostFolders:ur(e.hostFolders??e.host_folders??C.env.AGENSIS_HOST_FOLDERS)};s.sharedModelsFile&&!me.isAbsolute(s.sharedModelsFile)&&(s.sharedModelsFile=me.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 Cs(e){let t=C.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 Ts(e,t,n={}){let r=St(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 St(e){let t=new URL(e);return Ms(t)&&(t.protocol="http:",t.hostname="127.0.0.1",t.port="3142"),t}function Ms(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 Ns(e){try{let t=St(e);return(t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="0.0.0.0")&&t.port==="3142"}catch{return!1}}function tr(e){let t=String(e?.sessionId||""),n=String(e?.threadParentId||"");return`${t}::${n}`}var Os=/\b(cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b/i,$s=[/\b(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:say|speak)\s+(.+)$/i];function Ds(e){return String(e||"").trim().replace(/^[`"'“”‘’]+|[`"'“”‘’?.!]+$/g,"").trim().slice(0,1200)}function Rs(e){for(let t of $s){let n=String(e||"").match(t),r=Ds(n?.[1]||"");if(r)return r}return""}function Bs(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 Ps(e){let t=String(e||"").replace(/\s+/g," ").trim(),r=Bs(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 Ls(e){let t=Ps(e);if(!t)return null;let n=/^(open|show|hide|hush|close|dismiss)\b/i.test(t),r=Os.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=Rs(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 Us(e,t){let r=`http://127.0.0.1:${Number(e.cursorBuddyPort||8787)}/cursorbuddy/control`,o=String(e.cursorBuddyBridgeSecret||C.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 js(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 ir(e={}){return e.cursorBuddyBridge===!1?!1:!!(e.cursorBuddyRuntime||e.primaryDaemon)}async function Fs(e,t,n,r){let o="cursorbuddy-control",s="native",i=[],a=(l="")=>{P(t.ws,{action:"agent_job_delta",jobId:t.id,content:l,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i})};a("");let d="",c="";try{await Us(e,n),d=js(n),a(d)}catch(l){c=String(l?.message||l),d=`CursorBuddy control failed: ${c}`,a(d)}_t(t,{action:"agent_job_result",jobId:t.id,response:d,error:c,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i}),O(`Finished native CursorBuddy ${n.action} job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`)}async function Gs(e,t,{signal:n,requestPermission:r=null}){let o=Date.now();if(O(`Starting job ${t.id}`),an(t)){await Hs(e,t,{signal:n,started:o}),e.once&&(O("One-shot Amp job complete; exiting."),setTimeout(()=>C.exit(0),150));return}let s=Ls(t.prompt);if(s&&ir(e)){await Fs(e,t,s,o),e.once&&(O("One-shot CursorBuddy control job complete; exiting."),setTimeout(()=>C.exit(0),150));return}let i=zs(e,t),a=await qs(e,t),d="",c="",l=0,g=(h="")=>{P(t.ws,{action:"agent_job_delta",jobId:t.id,content:h,elapsedMs:Date.now()-o,model:i.model,permissionMode:i.permissionMode,permissionFlags:i.permissionFlags})},m=h=>{P(t.ws,{action:"agent_job_step",jobId:t.id,kind:h.kind,name:h.name,detail:h.detail,elapsedMs:Date.now()-o})},y=h=>{P(t.ws,{action:"agent_job_segment",jobId:t.id,text:h.text,elapsedMs:Date.now()-o})};g("");let S=i.streamJson?ar({onStep:m,onSegment:y}):null,f=setInterval(()=>g(d),1e3);f.unref&&f.unref();let b=!/[\\/]/.test(i.cmd),w=e.fastConnection&&b?fr(i.cmd)?"claude":pr(i.cmd)?"codex":null:null,_=await on(t,{family:w}).run({cmd:i.cmd,args:[...i.args,a],env:i.env,cwd:t.cwd||e.cwd,timeoutMs:e.timeoutMs,heartbeatMs:e.heartbeatMs,label:"agent job",signal:n,job:t,prompt:a,model:i.model,permissionMode:i.permissionMode,hostFolders:dr(e,t),leanCli:e.leanCli,mcp:e.leanCli?yt(e):null,sessionKey:`${t.workspaceId||e.workspace||""}:${e.agent||e.handle||""}`,clientVersion:ae,requestPermission:r,onData:h=>{S?(S.feed(h),d=S.live):(d+=String(h||""),c=ni(`${c}
|
|
47
|
-
${
|
|
48
|
-
${a}`:"",
|
|
46
|
+
`,o=Math.max(0,n-Buffer.byteLength(r));return`${Buffer.from(String(e||"")).subarray(0,o).toString("utf8").replace(/\uFFFD+$/,"")}${r}`}function es(e){let t=String(e||"").split(/\r?\n/),n="";if(t[0]?.trim()==="---")for(let r=1;r<t.length&&r<200&&t[r].trim()!=="---";r+=1){let o=/^description:\s*(.*)$/i.exec(t[r]);if(!o)continue;let s=o[1].trim();if(s&&!/^[|>][-+]?$/.test(s)){n=s.replace(/^["']|["']$/g,"");break}let i=[];for(let a=r+1;a<t.length&&a<200&&!(t[a].trim()==="---"||t[a].trim()&&!/^\s/.test(t[a]));a+=1)i.push(t[a].trim());n=i.join(" ").trim();break}if(!n){let r=t.findIndex((i,a)=>a>0&&i.trim()==="---"),s=(t[0]?.trim()==="---"&&r>0?t.slice(r+1):t).find(i=>i.trim()&&i.trim()!=="---");n=String(s||"").replace(/^#+\s*/,"").trim()}return n.slice(0,Qo)}function Rn(e){try{return ct(e).slice(0,Xo)}catch{return[]}}async function ts(e){let t;try{t=await ut.open(e,"r")}catch{return null}try{let n=Buffer.alloc(Se+1),{bytesRead:r}=await t.read(n,0,n.length,0);return n.subarray(0,r)}catch{return null}finally{await t.close().catch(()=>{})}}async function ns(e,t){let n=await ts(e.file);if(!n)return null;let r=n.toString("utf8"),o=es(r),s=n.length>Se,i=Math.min(Se,Math.max(0,t)),a=Buffer.byteLength(r)>i;if(!s&&!a)return{skill:e.name,path:e.file,summary:o,content:r,truncated:!1};let d=s?await rs(e.file):0,c=s&&!a?`the file is ${d?`${d} bytes`:`over ${Se} bytes`}; only the first ${Se} were synced`:`this sync reached its ${$n}-byte ceiling`,u=i<Zo?On("",c,Number.MAX_SAFE_INTEGER):On(r,c,i);return{skill:e.name,path:e.file,summary:o,content:u,truncated:!0}}async function rs(e){try{return(await ut.stat(e)).size}catch{return 0}}async function lt(e={}){let t=[];for(let n of Rn(e)){if(!n.file){t.push(`${n.name}:-`);continue}try{let r=await ut.stat(n.file);t.push(`${n.name}:${n.file}:${r.size}:${Math.floor(r.mtimeMs)}`)}catch{t.push(`${n.name}:-`)}}return t.join("|")}async function Dn(e={}){let t=[],n=0;for(let r of Rn(e))if(r.file)try{let o=await ns(r,$n-n);if(!o)continue;n+=Buffer.byteLength(o.content),t.push(o)}catch{}return t}import{readFile as os}from"node:fs/promises";var ss=new Set(["127.0.0.1","localhost","::1","[::1]"]);function Bn(e,t,n){let r=Number(e);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.trunc(r))):t}function is(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(!ss.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:Bn(e.contextWindow,void 0,1e7)}:{},maxConcurrency:Bn(e.maxConcurrency,1,64),shared:!0}}async function Pn(e){if(!e)return[];let t=JSON.parse(await os(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(is).filter(Boolean)}function Ln(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 Un({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"},c=a.apiKeyEnv?s[a.apiKeyEnv]:"";c&&(d.authorization=`Bearer ${c}`),n({action:"agent_inference_started",requestId:i,model:a.id});let{requestId:u,model:h,type:f,action:y,...b}=t,m=await o(`${a.baseUrl}/chat/completions`,{method:"POST",headers:d,body:JSON.stringify({...b,model:a.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,_="",k,N=g=>{let I=g.trim();if(!I.startsWith("data:"))return!1;let p=I.slice(5).trim();if(!p)return!1;if(p==="[DONE]")return!0;try{let A=JSON.parse(p);A?.usage&&(k=A.usage),n({action:"agent_inference_delta",requestId:i,model:a.id,chunk:A})}catch{}return!1},M=!1;for(;!M;){let{done:g,value:I}=await S.read();_+=E.decode(I||new Uint8Array,{stream:!g});let p=_.split(/\r?\n/);_=g?"":p.pop()||"";for(let A of p)if(N(A)){M=!0;break}if(g)break}_&&N(_);let l={action:"agent_inference_result",requestId:i,model:a.id,...k?{usage:k}:{}};return n(l),l}let w=await m.json();return n({action:"agent_inference_result",requestId:i,model:a.id,response:w}),w}Ue();var As=30*60*1e3,xs=15*1e3,nr=2,Is=10*1024,Cs="claude-opus-4-8",ce="0.1.38";async function Fe(e={}){let t=Ts(e);t.sharedModels=t.share?await Pn(t.sharedModelsFile):[];let n=!1,r=null,o=null,s=null,i=null,a=0,d=null,c=null,u="",h=null,f=!1,y=null,b=new Map,m=Wt({send:x=>P(r,x),log:O}),w=[],S=x=>{w.length>=32&&w.shift(),w.push(x),O(`Socket was gone \u2014 parked the result for job ${x.jobId} to re-send on reconnect`)},E=()=>{if(w.length!==0)for(let x of w.splice(0,w.length))P(r,x)?O(`Re-sent the result for job ${x.jobId} after reconnecting`):w.push(x)},_=null,k={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"},N=new Map,M=new Map,l=[],g=()=>k,I=()=>({connected:f&&!!t.cursorBuddyRuntime,mode:t.cursorBuddyRuntime?"agensis-cli":"agensis-cli-unclaimed",agentId:y?.agentId||y?.agent_id||t.agent,workspaceId:y?.workspaceId||y?.workspace_id||t.workspace,agensisUrl:t.url,handle:y?.handle||t.handle,name:y?.name||t.name,cwd:t.cwd,updatedAt:new Date().toISOString()}),p=()=>{_||!t.lanListener||(_=new ke.Server({port:0}),_.on("listening",()=>{let{port:x}=_.address();k={transport:"ws",listening:!0,addrs:ri(x),auth:"hub-pairwise"},O(`Agent-mesh LAN listener on port ${x}`),Ee(r,t,g())}),_.on("connection",x=>{let D=!1,v=setTimeout(()=>{if(!D)try{x.close(1008,"peer auth required")}catch{}},5e3);x.once("message",R=>{clearTimeout(v);let U=yt(R),H=U?.type==="peer_auth"?N.get(U.ticket):null;if(!H||H.fromAgentId!==U.fromAgentId||Date.now()>H.exp){try{x.close(1008,"invalid ticket")}catch{}return}N.delete(U.ticket),D=!0,x.on("message",z=>{let L=yt(z);L?.type==="agent_job"&&L.job?.id&&c.enqueue({...L.job,key:L.job.id,lane:rr(L.job),ws:r}).accepted&&O(`Queued peer-handoff job ${L.job.id} from ${U.fromAgentId}`)})})}),_.on("error",x=>O(`LAN listener error: ${x?.message||x}`)))},A=()=>{if(_){try{_.close()}catch{}_=null}k={transport:"ws",listening:!1,addrs:[],auth:"hub-pairwise"}},C=x=>new Promise((D,v)=>{if(!P(r,{action:"peer_ticket_request",targetAgentId:x})){v(new Error("hub socket not open"));return}let R=M.get(x)||[];R.push({resolve:D,reject:v}),M.set(x,R),setTimeout(()=>{let U=M.get(x)||[],H=U.findIndex(z=>z.resolve===D);H>=0&&(U.splice(H,1),v(new Error("peer ticket request timed out")))},1e4)}),$=()=>new Promise((x,D)=>{if(!P(r,{action:"peer_list_request"})){D(new Error("hub socket not open"));return}l.push(x),setTimeout(()=>{let v=l.indexOf(x);v>=0&&(l.splice(v,1),x([]))},1e4)}),V=async(x,D)=>{let v=null;try{let U=(await $()).find(L=>L.agentId===x&&L.reach?.listening&&L.reach.addrs?.length);if(!U)return!1;let H=await C(x),z=H.peer?.addrs?.[0]||U.reach.addrs[0];return!z?.host||!z?.port?!1:(v=new ke(`ws://${z.host}:${z.port}`),await new Promise((L,ze)=>{v.once("open",L),v.once("error",ze),setTimeout(()=>ze(new Error("peer connect timed out")),5e3)}),P(v,{type:"peer_auth",ticket:H.ticket,fromAgentId:t.agent}),P(v,{type:"agent_job",job:D}),!0)}catch(R){return O(`Peer handoff to ${x} failed, falling back to hub relay: ${R?.message||R}`),!1}finally{try{v?.close()}catch{}}},B=()=>{n=!0,ar(b),m.shutdown("The agent daemon shut down before this was approved."),o&&clearTimeout(o),s&&clearInterval(s),i&&clearInterval(i),h&&(h.close().catch(()=>{}),h=null),A(),Wn(t,{status:"stopped",connected:!1});try{r?.close()}catch{}d&&d()};if(c=pn({concurrency:t.once?1:t.maxConcurrency,runJob:async(x,D)=>{await qs(t,x,{...D,requestPermission:m.request}),t.once&&B()}}),t.cursorBuddyBridge)try{h=await kn(t,{port:t.cursorBuddyPort,authSecret:t.cursorBuddyBridgeSecret||void 0,log:O,connectionProvider:I}),h?.secret&&(t.cursorBuddyBridgeSecret=h.secret)}catch(x){if(ii(x)){let D=await ai(t.cursorBuddyPort);if(D?.ok){let v=D.pid?` pid ${D.pid}`:"";O(`CursorBuddy local bridge already running on http://127.0.0.1:${t.cursorBuddyPort}${v}`)}else O(`CursorBuddy local bridge port ${t.cursorBuddyPort} is in use but did not answer health`)}else O(`CursorBuddy local bridge unavailable: ${x?.message||x}`);h=null}T.once("SIGINT",B),T.once("SIGTERM",B);let J=()=>{if(n)return;let x=Ns(t.url,t.token,t);u="",O(`Connecting to ${x.replace(t.token,"redacted")}`),r=new ke(x),r.on("open",async()=>{f=!1,y=null,O(`Connected. Registering @${t.handle||"agent"} from ${t.cwd}`),P(r,{type:"auth",token:t.token});let D=await Vn(t);P(r,{action:"agent_register",workspaceId:t.workspace,agentId:t.agent,handle:t.handle,name:t.name,host:xe.hostname(),cwd:t.cwd,...D?{identity:D}:{},metadata:{codingCmd:t.codingCmd,model:t.model,permissionMode:t.permissionMode,permissionFlags:_t(t.permissionMode),once:t.once,runtime:"agensis",executionRuntime:t.runtime,version:ce}}),s=setInterval(()=>{Promise.all([hr(t,g()).catch(()=>null),pt(t).catch(()=>null)]).then(([v,R])=>{P(r,{action:"agent_heartbeat",...v?{capabilitiesHash:v.capabilitiesHash,memoryHash:v.memoryHash}:{},...v?.skillsHash?{skillsHash:v.skillsHash}:{},metadata:gt(t,c,R,cr(t)?h?.getContext?.():null,b)})})},t.heartbeatMs),s.unref&&s.unref()}),r.on("message",D=>{let v=yt(D);if(v){if(v.type==="agent_registered"){f=!0,y=v.connection||v.agent||null,or(t,v.agent),E(),O(`Registered as ${v.connection?.name||t.name} on ${v.connection?.host||xe.hostname()}`),t.onRegistered&&Promise.resolve(t.onRegistered(t,v)).catch(R=>{O(`Profile save failed: ${R?.message||R}`)}),ft(t,v.agent).catch(()=>{}),er(t).catch(()=>{}),sr(r,t),ir(r,t),p(),Ee(r,t,g());return}if(v.type==="agent_config"){or(t,v.agent),O(`Updated config for @${t.handle||"agent"}: model=${t.model}, permission=${t.permissionMode}`),ft(t,v.agent).catch(()=>{});return}if(v.type==="agent_memory_refresh"){sr(r,t),Ee(r,t,g());return}if(v.type==="agent_capabilities_refresh"){Ee(r,t,g());return}if(v.type==="agent_skills_refresh"){ir(r,t);return}if(v.type==="agent_inference_cancel"){b.get(String(v.requestId||""))?.abort();return}if(v.type==="agent_job_cancel"){let R=String(v.jobId||"");R&&(m.cancelJob(R,v.reason||"Cancelled by Agensis"),c.cancel(R,v.reason||"Cancelled by Agensis")&&O(`Cancelled job ${R}`));return}if(v.type==="agent_permission_decision"){m.decide(v);return}if(v.type==="agent_inference_request"&&v.requestId){let R=String(v.requestId),U=t.sharedModels.find(L=>L.id===v.model),H=[...b.values()].filter(L=>L.model===v.model).length;if(!U){P(r,{action:"agent_inference_error",requestId:R,error:`Shared model '${v.model||""}' is not available.`});return}if(H>=U.maxConcurrency){P(r,{action:"agent_inference_error",requestId:R,error:"Shared model is at capacity.",code:"capacity_exhausted"});return}let z=new AbortController;b.set(R,{abort:()=>z.abort(),model:U.id}),P(r,{action:"agent_heartbeat",metadata:gt(t,c,null,null,b)}),Un({models:t.sharedModels,request:v,signal:z.signal,send:L=>P(r,L)}).catch(L=>{P(r,{action:"agent_inference_error",requestId:R,error:z.signal.aborted?"Inference cancelled.":L?.message||String(L),code:z.signal.aborted?"cancelled":"inference_failed"})}).finally(()=>{b.delete(R),P(r,{action:"agent_heartbeat",metadata:gt(t,c,null,null,b)})});return}if(v.type==="peer_ticket"){let R=v.peer?.agentId,U=M.get(R)||[],H=U.shift();U.length?M.set(R,U):M.delete(R),H&&H.resolve(v);return}if(v.type==="peer_ticket_grant"){N.set(v.ticket,{fromAgentId:v.fromAgentId,exp:v.exp});return}if(v.type==="peer_list"){let R=l.shift();R&&R(Array.isArray(v.peers)?v.peers:[]);return}if(v.type==="agent_reach_disable"){A(),Ee(r,t,g());return}if(v.type==="error"){O(`Server rejected request: ${v.message||"unknown error"}`);return}if(v.type==="agent_disabled"){f=!1,y=null,O(`Agent disabled by Agensis: ${v.reason||"deactivated"}`),B();return}if(v.type==="agent_job"&&v.job?.id){let R=c.enqueue({...v.job,key:v.job.id,lane:rr(v.job),get ws(){return r},parkResult:S});R.accepted&&(a+=1,O(`Queued job ${v.job.id} at position ${R.position}`),t.once&&c.idle().then(()=>B()))}}}),r.on("close",(D,v)=>{ar(b),m.shutdown(),f=!1,y=null;let R=String(v||"");if(O(`Socket closed (${D||"no-code"}${R?`: ${R}`:""})`),s&&(clearInterval(s),s=null),D===1008&&/agent deactivated|authentication failed/i.test(R)){O("Stopping daemon because Agensis rejected this agent connection."),B();return}if(u==="ECONNREFUSED"&&$s(t.url)){O("Local agent backend is not running on 127.0.0.1:3142."),O("Start it in another terminal with: npm run backend"),O("Then rerun this connect command."),B();return}t.once&&a>0&&c.active()===0&&c.size()===0&&B(),!(n||t.once)&&(o=setTimeout(J,2e3),o.unref&&o.unref())}),r.on("error",D=>{u=D?.code||"",O(`Socket error: ${D?.message||D}`)})},X=async()=>{let x=await pt(t).catch(()=>null);await Kn(t,{busy:c.active()>0,active:c.active(),queueSize:c.size(),connected:r?.readyState===ke.OPEN,agentStatus:x?.status,agentNote:x?.note}).catch(()=>{})};X(),i=setInterval(()=>{X()},t.heartbeatMs),i.unref&&i.unref(),J(),await new Promise(x=>{let D=setInterval(async()=>{t.once&&a>0&&c.active()===0&&c.size()===0&&B(),n&&B()},500);d=()=>{clearInterval(D),x()}}),d=null,T.off("SIGINT",B),T.off("SIGTERM",B)}function Ts(e){let t=Ms(e.cursorBuddyBridge),n=e.noCoding===!0||T.env.AGENSIS_NO_CODING==="1",o=!ie(e.fullCliContext,ie(T.env.AGENSIS_FULL_CLI_CONTEXT,!1))&&ie(e.leanCli,!0),s=String(e.runtime||T.env.AGENSIS_RUNTIME||"").trim().toLowerCase();if(s&&!["claude","codex","amp"].includes(s))throw new Error("--runtime must be one of: claude, codex, amp");let i=s==="codex"?"codex exec":"claude -p",a=n||s==="amp"?"":String(e.codingCmd||T.env.AGENSIS_CODING_CMD||T.env.CODING_CMD||i).trim(),d=s||Ys(a),c={url:String(e.url||e.baseUrl||T.env.AGENSIS_URL||"").trim(),token:String(e.token||T.env.AGENSIS_TOKEN||"").trim(),workspace:String(e.workspace||e.workspaceId||T.env.AGENSIS_WORKSPACE||T.env.AGENSIS_WORKSPACE_ID||"").trim(),agent:String(e.agent||e.agentId||T.env.AGENSIS_AGENT||T.env.AGENSIS_AGENT_ID||"").trim(),handle:yr(e.handle||T.env.AGENSIS_HANDLE||e.name||T.env.AGENSIS_NAME||"agent"),name:String(e.name||T.env.AGENSIS_NAME||e.handle||T.env.AGENSIS_HANDLE||"agensis Agent").trim(),cwd:String(e.cwd||T.env.AGENSIS_CWD||T.cwd()).trim(),codingCmd:a,runtime:d,runtimeLocked:!!s,ampCmd:String(e.ampCmd||T.env.AGENSIS_AMP_CMD||"amp").trim()||"amp",model:bt(e.model||T.env.AGENSIS_MODEL||T.env.CLAUDE_MODEL||"",d),permissionMode:Ge(e.permissionMode||e.permission_mode||e.permission||T.env.AGENSIS_PERMISSION_MODE||"default"),timeoutMs:Number(e.timeoutMs||T.env.AGENSIS_TIMEOUT_MS||As),heartbeatMs:Number(e.heartbeatMs||T.env.AGENSIS_HEARTBEAT_MS||xs),maxConcurrency:Math.max(1,Number(e.maxConcurrency||T.env.AGENSIS_MAX_CONCURRENCY||nr)||nr),once:!!(e.once||T.env.AGENSIS_ONCE==="1"),exitOnOnce:!!e.exitOnOnce,onRegistered:typeof e.onRegistered=="function"?e.onRegistered:null,primaryDaemon:!!(e.primaryDaemon||T.env.AGENSIS_PRIMARY_DAEMON==="1"),cursorBuddyRuntime:!!(e.cursorBuddyRuntime||T.env.AGENSIS_CURSORBUDDY_RUNTIME==="1"),cursorBuddyBridge:t,cursorBuddyPort:Number(e.cursorBuddyPort||T.env.AGENSIS_CURSORBUDDY_PORT||8787),cursorBuddyBridgeSecret:String(e.cursorBuddyBridgeSecret||T.env.AGENSIS_CURSORBUDDY_BRIDGE_SECRET||"").trim(),cursorBuddyModel:String(e.cursorBuddyModel||T.env.AGENSIS_CURSORBUDDY_MODEL||"haiku-4.5").trim(),lanListener:!!(e.lanListener||e.lan||T.env.AGENSIS_LAN==="1"),share:!!(e.share||T.env.AGENSIS_SHARE==="1"),sharedModelsFile:String(e.sharedModelsFile||T.env.AGENSIS_SHARED_MODELS_FILE||"").trim(),noCoding:n,leanCli:o,fastConnection:ie(e.fastConnection,ie(T.env.AGENSIS_FAST_CONNECTION,!0)),syncMemory:ie(e.syncMemory,T.env.AGENSIS_SYNC_MEMORY==="1"),syncSkills:ie(e.syncSkills,ie(T.env.AGENSIS_SYNC_SKILLS,!0)),hostFolders:fr(e.hostFolders??e.host_folders??T.env.AGENSIS_HOST_FOLDERS)};c.sharedModelsFile&&!me.isAbsolute(c.sharedModelsFile)&&(c.sharedModelsFile=me.resolve(c.cwd,c.sharedModelsFile));let u=[];if(c.url||u.push("--url"),c.token||u.push("--token"),c.workspace||u.push("--workspace"),c.agent||u.push("--agent"),c.share&&!c.sharedModelsFile&&u.push("--shared-models-file"),u.length)throw new Error(`Missing required option(s): ${u.join(", ")}`);return c}function ie(e,t){return e==null||e===""?t:typeof e=="boolean"?e:!/^(0|false|off|no)$/i.test(String(e).trim())}function Ms(e){let t=T.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 Ns(e,t,n={}){let r=wt(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 wt(e){let t=new URL(e);return Os(t)&&(t.protocol="http:",t.hostname="127.0.0.1",t.port="3142"),t}function Os(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 $s(e){try{let t=wt(e);return(t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="0.0.0.0")&&t.port==="3142"}catch{return!1}}function rr(e){let t=String(e?.sessionId||""),n=String(e?.threadParentId||"");return`${t}::${n}`}var Rs=/\b(cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\b/i,Ds=[/\b(?:make|have|tell)\s+(?:the\s+)?(?:cursorbuddy|cursor buddy|avatar|buddy|pet|character|him|guy)\s+(?:say|speak)\s+(.+)$/i];function Bs(e){return String(e||"").trim().replace(/^[`"'“”‘’]+|[`"'“”‘’?.!]+$/g,"").trim().slice(0,1200)}function Ps(e){for(let t of Ds){let n=String(e||"").match(t),r=Bs(n?.[1]||"");if(r)return r}return""}function Ls(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 Us(e){let t=String(e||"").replace(/\s+/g," ").trim(),r=Ls(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 js(e){let t=Us(e);if(!t)return null;let n=/^(open|show|hide|hush|close|dismiss)\b/i.test(t),r=Rs.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=Ps(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 Fs(e,t){let r=`http://127.0.0.1:${Number(e.cursorBuddyPort||8787)}/cursorbuddy/control`,o=String(e.cursorBuddyBridgeSecret||T.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 Gs(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 cr(e={}){return e.cursorBuddyBridge===!1?!1:!!(e.cursorBuddyRuntime||e.primaryDaemon)}async function Hs(e,t,n,r){let o="cursorbuddy-control",s="native",i=[],a=(u="")=>{P(t.ws,{action:"agent_job_delta",jobId:t.id,content:u,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i})};a("");let d="",c="";try{await Fs(e,n),d=Gs(n),a(d)}catch(u){c=String(u?.message||u),d=`CursorBuddy control failed: ${c}`,a(d)}kt(t,{action:"agent_job_result",jobId:t.id,response:d,error:c,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i}),O(`Finished native CursorBuddy ${n.action} job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s`)}async function qs(e,t,{signal:n,requestPermission:r=null}){let o=Date.now();O(`Starting job ${t.id}`);let s=ur(e,t);if(e.runtimeLocked&&s!==e.runtime){let I=`Executor runtime ${e.runtime} cannot accept job runtime ${s}.`;P(t.ws,{action:"agent_job_result",jobId:t.id,response:"",error:I,errorCode:"runtime_mismatch",elapsedMs:Date.now()-o,metadata:{executionRuntime:e.runtime}}),O(`Job ${t.id} refused: runtime mismatch (${e.runtime} != ${s})`);return}if(Ze(t)){await Js(e,t,{signal:n,started:o}),e.once&&(O("One-shot Amp job complete; exiting."),setTimeout(()=>T.exit(0),150));return}let i=js(t.prompt);if(i&&cr(e)){await Hs(e,t,i,o),e.once&&(O("One-shot CursorBuddy control job complete; exiting."),setTimeout(()=>T.exit(0),150));return}let a=Ws(e,t),d=await zs(e,t),c="",u="",h=0,f=(I="")=>{P(t.ws,{action:"agent_job_delta",jobId:t.id,content:I,elapsedMs:Date.now()-o,model:a.model,permissionMode:a.permissionMode,permissionFlags:a.permissionFlags})},y=I=>{P(t.ws,{action:"agent_job_step",jobId:t.id,kind:I.kind,name:I.name,detail:I.detail,elapsedMs:Date.now()-o})},b=I=>{P(t.ws,{action:"agent_job_segment",jobId:t.id,text:I.text,elapsedMs:Date.now()-o})};f("");let m=a.streamJson?lr({onStep:y,onSegment:b}):null,w=setInterval(()=>f(c),1e3);w.unref&&w.unref();let S=!/[\\/]/.test(a.cmd),E=e.fastConnection&&S?vt(a.cmd)?"claude":Et(a.cmd)?"codex":null:null,k=await cn(t,{family:E}).run({cmd:a.cmd,args:[...a.args,d],env:a.env,cwd:t.cwd||e.cwd,timeoutMs:e.timeoutMs,heartbeatMs:e.heartbeatMs,label:"agent job",signal:n,job:t,prompt:d,model:a.model,permissionMode:a.permissionMode,hostFolders:pr(e,t),leanCli:e.leanCli,mcp:e.leanCli?St(e):null,sessionKey:`${t.workspaceId||e.workspace||""}:${e.agent||e.handle||""}`,clientVersion:ce,requestPermission:r,onData:I=>{m?(m.feed(I),c=m.live):(c+=String(I||""),u=si(`${u}
|
|
47
|
+
${I}`));let p=Date.now();p-h>150&&(h=p,f(c))}});clearInterval(w),m&&(m.end(),c=m.live,f(c));let N=String(k.stdout||"").trim(),M=String(k.stderr||"").trim(),l=k.error?k.error.message:k.status===0?"":M||`Command exited with status ${k.status}`,g=m?m.result||(l?"":M):N||(l?"":M)||u||"";kt(t,{action:"agent_job_result",jobId:t.id,response:g,error:l,elapsedMs:Date.now()-o,model:a.model,permissionMode:a.permissionMode,permissionFlags:a.permissionFlags}),O(`Finished job ${t.id} in ${Math.round((Date.now()-o)/1e3)}s`),e.once&&(O("One-shot job complete; exiting."),setTimeout(()=>T.exit(0),150))}async function Js(e,t,{signal:n,started:r=Date.now()}={}){let o="amp-orb",s="amp-managed",i=[],a=(l="")=>P(t.ws,{action:"agent_job_delta",jobId:t.id,content:l,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i}),d=l=>P(t.ws,{action:"agent_job_step",jobId:t.id,kind:l.kind,name:l.name,detail:l.detail,elapsedMs:Date.now()-r}),c=l=>P(t.ws,{action:"agent_job_segment",jobId:t.id,text:l.text,elapsedMs:Date.now()-r}),u=({response:l="",error:g="",errorCode:I="",threadId:p=""}={})=>{let A=he(p);kt(t,{action:"agent_job_result",jobId:t.id,response:l,error:g,errorCode:I||void 0,elapsedMs:Date.now()-r,model:o,permissionMode:s,permissionFlags:i,metadata:{runtime:"amp",...A?{ampThreadId:A,ampThreadUrl:`https://ampcode.com/threads/${A}`}:{},...I?{ampErrorCode:I}:{}}})};a("");let h=me.resolve(String(t.cwd||e.cwd)),f=[e.cwd,...e.hostFolders||[]];try{await mn({cwd:h,allowedRoots:f});let l=await et({cwd:h,executable:e.ampCmd,signal:n});if(!l.available)throw ee(l.reason||"amp_cli_crashed")}catch(l){let g=n?.aborted?"amp_turn_cancelled":String(l?.code||"amp_cli_crashed");u({error:l?.message||ee(g).message,errorCode:g}),O(`Amp job ${t.id} refused: ${g}`);return}let y=String(t?.runtime?.threadId||t?.ampThreadId||t?.metadata?.ampThreadId||"").trim(),b=he(y);if(t?.runtime?.continuationRequired===!0&&!b||y&&!b){let l=ee("amp_thread_not_found");u({error:l.message,errorCode:l.code}),O(`Amp job ${t.id} refused: ${l.code}`);return}let m=ln({executable:e.ampCmd,prompt:String(t.prompt||""),threadId:b}),w=lr({onStep:d,onSegment:c}),S=dn(),E="",_=0,k=setInterval(()=>a(E),1e3);k.unref&&k.unref();let N=await Z({cmd:m.cmd,args:m.args,cwd:h,timeoutMs:e.timeoutMs,heartbeatMs:e.heartbeatMs,label:"Amp orb turn",signal:n,onData:l=>{w.feed(l),S.feed(l),E=w.live;let g=Date.now();g-_>150&&(_=g,a(E))}});clearInterval(k),w.end(),S.end(),E=w.live,a(E);let M=S.threadId||b;if(N.status!==0||N.error){let l=fn(N);u({error:l.message,errorCode:l.code,threadId:M}),O(`Amp job ${t.id} failed: ${l.code}`);return}if(!M){let l=ee("amp_stream_invalid");u({error:l.message,errorCode:l.code}),O(`Amp job ${t.id} failed: ${l.code}`);return}u({response:w.result||"",threadId:M}),O(`Finished Amp job ${t.id} in ${Math.round((Date.now()-r)/1e3)}s (${M})`)}async function zs(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=dr(e,t),i=mr(e,t),a=await tr(e).catch(()=>null),d=a?`Heartbeat (recurring instructions \u2014 edit at ${zn(e)}):
|
|
48
|
+
${a}`:"",u=["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:
|
|
49
49
|
${n.description}`:"",n.soul?`Soul:
|
|
50
50
|
${n.soul}`:"",n.system_prompt?`System instructions:
|
|
51
51
|
${n.system_prompt}`:"",n.instructions?`Additional instructions:
|
|
52
52
|
${n.instructions}`:"",o?`Enabled tools:
|
|
53
53
|
${o}`:"",r?`Enabled skills:
|
|
54
|
-
${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 ${
|
|
54
|
+
${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 ${Jn(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.`,`Identity file: you can declare how you appear \u2014 avatar, description, soul, and voice ({"cartesia_voice_id","speed","emotion"}) \u2014 by writing JSON to ${ht(e)}, e.g. {"avatar":"FX","description":"...","voice":{"emotion":"calm"}}. Your daemon sends it the next time it connects; anything a human has set in the app always wins, and "name" only applies to brand-new agents.`,d,"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(`
|
|
55
55
|
|
|
56
|
-
`);return e.leanCli?
|
|
56
|
+
`);return e.leanCli?Ks(u,Is):u}function Ks(e,t){let n=String(e||"");if(Buffer.byteLength(n,"utf8")<=t)return n;let r=`[... older or optional Agensis context omitted ...]
|
|
57
57
|
|
|
58
|
-
`,o=Math.max(0,t-Buffer.byteLength(r,"utf8")),s=[...n],i=0,a=s.length;for(;i<a;){let d=Math.ceil((i+a)/2),c=s.slice(s.length-d).join("");Buffer.byteLength(c,"utf8")<=o?i=d:a=d-1}return r+s.slice(s.length-i).join("")}function
|
|
59
|
-
`))>=0;)
|
|
60
|
-
${me.resolve(e.cwd)}`;if(
|
|
61
|
-
`)}function
|
|
62
|
-
`,{mode:384}),await
|
|
63
|
-
`)}import
|
|
64
|
-
`,{mode:384}),await Ce.rename(s,r),await Ce.chmod(r,384).catch(()=>{})}function
|
|
58
|
+
`,o=Math.max(0,t-Buffer.byteLength(r,"utf8")),s=[...n],i=0,a=s.length;for(;i<a;){let d=Math.ceil((i+a)/2),c=s.slice(s.length-d).join("");Buffer.byteLength(c,"utf8")<=o?i=d:a=d-1}return r+s.slice(s.length-i).join("")}function Ws(e,t){let{cmd:n,args:r}=gr(e.codingCmd),o=dr(e,t),s=mr(e,t),i=oi(r),a=_t(s),d=pr(e,t);if(vt(n)){let c=[...i];o&&c.push("--model",o);let u;if(e.leanCli){let b=St(e);c.push("--no-session-persistence","--safe-mode","--mcp-config",JSON.stringify({mcpServers:{agensis:{type:"http",url:b.url,headers:{Authorization:"Bearer ${AGENSIS_MCP_TOKEN}"}}}}),"--strict-mcp-config"),u=b.env}if(s==="accept_edits"&&c.push("--permission-mode","acceptEdits"),s==="yolo"){let b=t&&t.agent&&t.agent.run_mode==="sandbox",m=typeof T.getuid=="function"&&T.getuid()===0,w=b||Qs(),S=T.env.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1";w||!m||S?c.push("--dangerously-skip-permissions"):(a=[],O("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 h=i.some(b=>b==="--output-format"||String(b).startsWith("--output-format=")),f=i.includes("-p")||i.includes("--print"),y=!1;!h&&f?(c.push("--output-format","stream-json","--include-partial-messages"),i.includes("--verbose")||c.push("--verbose"),y=!0):h&&(y=i.some(b=>/stream-json/.test(String(b))));for(let b of d)c.push("--add-dir",b);return{cmd:n,args:c,model:o,permissionMode:s,permissionFlags:a,streamJson:y,env:u}}if(Et(n)){let c=[...i];o&&c.push("--model",o);let u;if(e.leanCli&&i.includes("exec")){let h=St(e);c.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(h.url)}`,"-c",'mcp_servers.agensis.bearer_token_env_var="AGENSIS_MCP_TOKEN"'),u=h.env}return s==="yolo"&&c.push("--sandbox","danger-full-access","--ask-for-approval","never"),{cmd:n,args:c,model:o,permissionMode:s,permissionFlags:a,env:u}}return{cmd:n,args:r,model:o,permissionMode:s,permissionFlags:a}}function Ys(e){if(!String(e||"").trim())return"custom";let t;try{({cmd:t}=gr(e))}catch{return"custom"}return vt(t)?"claude":Et(t)?"codex":"custom"}function ur(e,t){if(Ze(t))return"amp";let n=String(t?.agent?.metadata?.executionRuntime||t?.agent?.metadata?.runtime||"").trim().toLowerCase();return["claude","codex","amp","custom"].includes(n)?n:e.runtime==="amp"?"custom":e.runtime}function St(e){let t=wt(e.url);return t.pathname="/backend/mcp",t.search="",t.hash="",{url:t.toString(),env:{AGENSIS_MCP_TOKEN:e.token}}}function lr({onStep:e,onSegment:t}={}){let n="",r="",o=!1,s="",i="",a=null,d=!1,c=!1,u=new Set,h=m=>{if(!(typeof e!="function"||!m.name))try{e(m)}catch{}},f=m=>{if(typeof t=="function"){i+=o?r:s,r="",s="";try{t(m)}catch{}}},y=m=>{if(!m||typeof m!="object")return;if(m.type==="agensis_step"){let S=m.step;S&&typeof S=="object"&&(d=!0,h({kind:S.kind||"tool",name:String(S.name||""),detail:String(S.detail||"")}));return}if(m.type==="agensis_segment"){let S=m.segment;S&&typeof S=="object"&&(c=!0,f({text:String(S.text||"")}));return}let w=m.event&&m.event.delta||m.delta;if(w&&w.type==="text_delta"&&typeof w.text=="string"){o=!0,r+=w.text;return}if(m.type==="result"&&typeof m.result=="string"){a=m.result;return}if(m.type==="assistant"&&m.message&&Array.isArray(m.message.content)){let S=m.message.content.filter(E=>E&&E.type==="text"&&typeof E.text=="string").map(E=>E.text).join("");if(S&&(s+=S),S&&!c&&f({text:S}),!d)for(let E of m.message.content){if(!E||E.type!=="tool_use")continue;let _=typeof E.id=="string"?E.id:"";if(_){if(u.has(_))continue;u.add(_)}h({kind:"tool",name:String(E.name||""),detail:Ne(E.input)})}}},b=m=>{let w=String(m).trim();if(w)try{y(JSON.parse(w))}catch{}};return{feed(m){n+=String(m||"");let w;for(;(w=n.indexOf(`
|
|
59
|
+
`))>=0;)b(n.slice(0,w)),n=n.slice(w+1)},end(){n&&(b(n),n="")},get live(){return o?r:s},get result(){return a??i+(o?r:s)}}}function dr(e,t){return bt(t?.agent?.model||t?.model||e.model,ur(e,t))}function Vs(e){let t=String(e||"").trim();return!t||t==="auto"||t==="claude-fable-5"?Cs:t}function bt(e,t){let n=String(e||"").trim();return t==="codex"||t==="amp"?!n||n==="auto"?"":n:Vs(n)}function mr(e,t){return Ge(t?.agent?.permissionMode||t?.agent?.permission_mode||t?.permissionMode||t?.permission_mode||e.permissionMode)}function Ge(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 _t(e){return Ge(e)==="yolo"?["--no-sandbox","--yolo"]:[]}function fr(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 Xs(e,t){let n=t?.agent?.metadata?.host_folders??t?.agent?.hostFolders??t?.hostFolders??t?.host_folders,r=fr(n);return r.length>0?r:e.hostFolders||[]}function pr(e,t){let n=Xs(e,t),r=K({workspace:e.workspace,agent:e.agent});return r&&!n.includes(r)?[...n,r]:n}var de;function Qs(){if(de!==void 0)return de;let e=T.env;if(e.AGENSIS_ALLOW_ROOT_SKIP_PERMISSIONS==="1"||e.AGENSIS_SANDBOX_HOST==="1"||e.IS_SANDBOX==="1")return de=!0;if(e.AGENSIS_NO_SANDBOX_AUTODETECT==="1")return de=!1;try{if(Ae.existsSync("/.dockerenv")||Ae.existsSync("/run/.containerenv"))return de=!0}catch{}try{let t=Ae.readFileSync("/proc/1/cgroup","utf8");if(/docker|kubepods|containerd|lxc|podman/i.test(t))return de=!0}catch{}return de=!1}function gt(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:_t(e.permissionMode),daemon:{runtime:"agensis-cli",version:ce,pid:T.pid,node:T.version,platform:T.platform,arch:T.arch,host:xe.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=Zs(r)),n?.status&&(s.agentStatus=n.status),n?.note&&(s.agentNote=n.note),(n?.status||n?.note)&&(s.agentStatusAt=new Date().toISOString()),s}function Zs(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 or(e,t){if(!t||typeof t!="object")return;t.name&&(e.name=String(t.name).trim()||e.name),(t.handle||t.name)&&(e.handle=yr(t.handle||t.name||e.handle)),t.model&&(e.model=bt(t.model,e.runtime));let n=t.permissionMode||t.permission_mode;n&&(e.permissionMode=Ge(n)),(t.memory_dir!==void 0||t.memoryDir!==void 0)&&(e.memoryDir=String(t.memory_dir??t.memoryDir??"").trim())}function ei(){let e=["amp","claude","codex","gh","node","npm","python3","git","fly","vercel"],t=(T.env.PATH||"").split(me.delimiter).filter(Boolean);return e.filter(n=>t.some(r=>{try{return Ae.existsSync(me.join(r,n))}catch{return!1}}))}function ti(){try{let e=Ae.readFileSync(me.join(xe.homedir(),".claude.json"),"utf8"),n=JSON.parse(e)?.mcpServers;if(n&&typeof n=="object")return Object.keys(n).sort()}catch{}return[]}function je(e){return ks.createHash("sha1").update(String(e)).digest("hex").slice(0,16)}async function hr(e,t=null){let n=Nn({cwd:e.cwd}),r=Mn({cwd:e.cwd}),o=ei(),s=ti(),i=e.syncMemory&&rt({cwd:e.cwd,memoryDir:e.memoryDir})||null,a=Ln(e.sharedModels),d=await ni(e),c={claude:{id:"claude",label:"Claude",available:o.includes("claude")},codex:{id:"codex",label:"Codex",available:o.includes("codex")},amp:{...d,label:"Amp"}},u=je(JSON.stringify({skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:a,runtimes:c,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null})),h=je(await In(i)),f=e.syncSkills?je(await lt({cwd:e.cwd})):null;return{skills:n,commands:r,clis:o,mcpServers:s,memoryRoot:i,sharedModels:a,runtimes:c,codingRoute:!!e.codingCmd,shared:e.share,reach:t||null,capabilitiesHash:u,memoryHash:h,skillsHash:f}}var ae=null;async function ni(e){let t=`${e.ampCmd}
|
|
60
|
+
${me.resolve(e.cwd)}`;if(ae?.key===t&&Date.now()-ae.at<6e4)return ae.value??ae.pending;let n=et({cwd:e.cwd,executable:e.ampCmd});ae={key:t,at:Date.now(),pending:n};try{let r=await n;return ae={key:t,at:Date.now(),value:r},r}catch(r){throw ae?.pending===n&&(ae=null),r}}async function Ee(e,t,n=null){try{let r=await hr(t,n);P(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,runtimes:r.runtimes,codingRoute:r.codingRoute,shared:r.shared,memoryRoot:r.memoryRoot,reach:r.reach||void 0,hash:r.capabilitiesHash,memoryHash:r.memoryHash,skillsHash:r.skillsHash}),O(`Capabilities synced \u2014 skills:${r.skills.length} commands:${r.commands.length} clis:${r.clis.length} mcp:${r.mcpServers.length}`)}catch(r){O(`Capabilities sync skipped: ${r?.message||r}`)}}function ri(e){let t=xe.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 sr(e,t){try{if(!t.syncMemory)return;let n=rt({cwd:t.cwd,memoryDir:t.memoryDir});if(!n)return;let r=await Cn(n);P(e,{action:"agent_memory_sync",workspaceId:t.workspace,agentId:t.agent,root:n,files:r}),O(`Synced ${r.length} memory file${r.length===1?"":"s"} from ${n}`)}catch(n){O(`Memory sync skipped: ${n?.message||n}`)}}async function ir(e,t){try{if(!t.syncSkills)return;let n=je(await lt({cwd:t.cwd})),r=await Dn({cwd:t.cwd});P(e,{action:"agent_skill_sync",workspaceId:t.workspace,agentId:t.agent,hash:n,skills:r});let o=r.filter(s=>s.truncated).length;O(`Synced ${r.length} skill document${r.length===1?"":"s"}${o?` (${o} truncated)`:""}`)}catch(n){O(`Skill sync skipped: ${n?.message||n}`)}}function oi(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 vt(e){return/(^|\/)claude(?:$|\.)/.test(String(e||""))}function Et(e){return/(^|\/)codex(?:$|\.)/.test(String(e||""))}function gr(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 yt(e){try{return JSON.parse(String(e))}catch{return null}}function P(e,t){return!e||e.readyState!==ke.OPEN?!1:(e.send(JSON.stringify(t)),!0)}function kt(e,t){return P(e.ws,t)?!0:(e.parkResult?.(t),!1)}function si(e){return String(e||"").split(/\r?\n/).map(t=>t.trim()).filter(Boolean).slice(-1)[0]||""}function yr(e){return String(e||"").trim().toLowerCase().replace(/^@+/,"").replace(/[^a-z0-9_.-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function ii(e){return e?.code==="EADDRINUSE"||/\bEADDRINUSE\b/.test(String(e?.message||e))}async function ai(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 O(e){T.stderr.write(`[agensis] ${e}
|
|
61
|
+
`)}function ar(e){if(e instanceof Map)for(let t of e.values())try{t?.abort?.()}catch{}}import ci from"node:crypto";import Ie from"node:fs/promises";import ui from"node:os";import Sr from"node:path";var fe="default",wr=2,li=/^[a-zA-Z0-9_.-]{1,64}$/,di=["url","token","workspace","agent","handle","name","cwd","runtime","codingCmd","ampCmd","model","permissionMode","timeoutMs","heartbeatMs","maxConcurrency","share","sharedModelsFile","noCoding","leanCli","fullCliContext","syncMemory","syncSkills","lanListener","primaryDaemon","cursorBuddyBridge","cursorBuddyPort","hostFolders"];function Q(e=fe){let t=String(e||fe).trim();if(!li.test(t))throw new Error("Daemon profile names may only contain letters, numbers, dot, dash, and underscore.");return t}function br(e=fe,t={}){let n=t.homedir||ui.homedir();return Sr.join(n,".agensis","daemon-profiles",`${Q(e)}.json`)}function At(e={}){let t={};for(let n of di){let r=e[n];r!=null&&r!==""&&(t[n]=r)}return t}function ue(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 _r(e={}){return!!(ue(e,["url","baseUrl"],["AGENSIS_URL"])||ue(e,["token"],["AGENSIS_TOKEN"])||ue(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])||ue(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}function xt(e={}){return!!(ue(e,["url","baseUrl"],["AGENSIS_URL"])&&ue(e,["token"],["AGENSIS_TOKEN"])&&ue(e,["workspace","workspaceId"],["AGENSIS_WORKSPACE","AGENSIS_WORKSPACE_ID"])&&ue(e,["agent","agentId"],["AGENSIS_AGENT","AGENSIS_AGENT_ID"]))}async function It(e=fe,t={}){let n=br(e,t),r;try{r=await Ie.readFile(n,"utf8")}catch(a){if(a?.code==="ENOENT")return null;throw a}let o;try{o=JSON.parse(r)}catch(a){throw new Error(`Daemon profile "${Q(e)}" is unreadable: ${a?.message||a}`)}let s=o?.config;if(!s?.url||!s?.token||!s?.workspace||!s?.agent)return null;let i=At(s);return Number(o.version||1)<wr&&Number(i.maxConcurrency)===8&&(i.maxConcurrency=2),i}async function He(e=fe,t={},n={}){let r=At(t);if(!r.url||!r.token||!r.workspace||!r.agent)return null;let o=br(e,n),s=Sr.dirname(o);await Ie.mkdir(s,{recursive:!0,mode:448});let i=`${o}.${process.pid}.${Date.now()}.tmp`,a={version:wr,savedAt:new Date().toISOString(),profile:Q(e),tokenHash:ci.createHash("sha256").update(r.token).digest("hex"),config:r};return await Ie.writeFile(i,`${JSON.stringify(a,null,2)}
|
|
62
|
+
`,{mode:384}),await Ie.rename(i,o),await Ie.chmod(o,384).catch(()=>{}),o}function vr(e,t={}){let n={...e,...At(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 Ct(e=fe){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===fe?"":` --profile ${t}`}`].join(`
|
|
63
|
+
`)}import mi from"node:crypto";import Ce from"node:fs/promises";import Er from"node:os";import Tt from"node:path";import Mt from"node:process";var fi=/^cbk_[a-z0-9_]+_[A-Z2-9]{18}$/;function pi(e={}){return String(e.url||e.baseUrl||Mt.env.AGENSIS_URL||"https://agensis.io").trim().replace(/\/+$/,"")}function kr(e,t={}){let n=t.homedir||Er.homedir(),r=mi.createHash("sha256").update(String(e)).digest("hex");return Tt.join(n,".agensis","cursorbuddy","connection-keys",`${r}.json`)}function hi(){return new Error("Missing or invalid --key. Create a CursorBuddy connection key in Agensis first.")}function Nt(e){let t=String(e||"").trim();if(!fi.test(t))throw hi();return t}function gi(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,...c}=e;return{...c,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 yi(e,t={}){Nt(e);let n=kr(e,t),r;try{r=await Ce.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 Si(e,t,n={}){if(Nt(e),!t?.token||!t?.workspace||!t?.agent||!t?.url)return;let r=kr(e,n),o=Tt.dirname(r);await Ce.mkdir(o,{recursive:!0,mode:448});let s=`${r}.${Mt.pid}.${Date.now()}.tmp`,i={version:1,savedAt:new Date().toISOString(),keyHash:Tt.basename(r,".json"),daemonArgs:t};await Ce.writeFile(s,`${JSON.stringify(i,null,2)}
|
|
64
|
+
`,{mode:384}),await Ce.rename(s,r),await Ce.chmod(r,384).catch(()=>{})}function wi(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 bi(e,t){return t?.error?.message||t?.message||`CursorBuddy key claim failed with HTTP ${e.status}`}async function _i(e){return e.json().catch(()=>({}))}async function Ar(e,t={}){let n=Nt(e?.key),r=pi(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||Mt.cwd(),i=t.hostname||Er.hostname(),a=t.version||ce,d={homedir:t.homedir},c=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})}),u=await _i(c);if(!c.ok){let f=bi(c,u);if(c.status===409||/already been claimed/i.test(f)){let y=await yi(n,d);if(y)return wi(y,e,s);throw new Error(`${f}. 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(f)}let h=gi(e,u?.data||u,r,s);return await Si(n,h,d),h}import vi from"node:crypto";import Ei from"node:http";import ki from"node:os";import te from"node:process";import{spawn as Ai}from"node:child_process";var xi="https://agensis.io",Ii=10*60*1e3;function qe(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 Ci(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 Ti(e){let t=String(e||te.env.AGENSIS_URL||xi).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 Mi(e){let t=te.platform==="darwin"?"open":te.platform==="win32"?"cmd":"xdg-open",n=te.platform==="win32"?["/c","start","",e]:[e],r=Ai(t,n,{detached:!0,stdio:"ignore"});r.on("error",()=>{}),r.unref()}function Ni(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 Oi(e,t,n){let r=new URL(Ti(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",ki.hostname()),r.searchParams.set("cwd",String(e.cwd||te.cwd())),e.handle&&r.searchParams.set("handle",String(e.handle)),e.name&&r.searchParams.set("name",String(e.name)),r.toString()}async function xr(e={}){let t=Q(e.profile||"default"),n=vi.randomBytes(24).toString("base64url"),r=Number(e.setupTimeoutMs||te.env.AGENSIS_SETUP_TIMEOUT_MS||Ii),o,s=new Promise((c,u)=>{let h=setTimeout(()=>u(new Error("Agensis setup timed out waiting for browser login.")),r);h.unref&&h.unref(),o=Ei.createServer(async(f,y)=>{if(y.setHeader("access-control-allow-origin","*"),y.setHeader("access-control-allow-methods","POST, OPTIONS"),y.setHeader("access-control-allow-headers","content-type"),f.method==="OPTIONS"){y.writeHead(204),y.end();return}if(f.method!=="POST"||f.url!=="/agensis/setup-callback"){qe(y,404,{ok:!1,error:"Unknown Agensis setup callback route"});return}try{let b=JSON.parse(await Ci(f)||"{}");if(b?.state!==n){qe(y,403,{ok:!1,error:"Setup state did not match"});return}let m={...Ni(b),primaryDaemon:!0,cursorBuddyBridge:e.cursorBuddyBridge!==!1};await He(t,m),clearTimeout(h),qe(y,200,{ok:!0,profile:t}),c(m)}catch(b){qe(y,400,{ok:!1,error:String(b?.message||b)})}}),o.once("error",u)});await new Promise((c,u)=>{o.listen(0,"127.0.0.1",h=>h?u(h):c())});let{port:i}=o.address(),a=`http://127.0.0.1:${i}/agensis/setup-callback`,d=Oi(e,a,n);te.stdout.write(`[agensis] Opening Agensis to sign in and connect this machine.
|
|
65
65
|
`),te.stdout.write(`[agensis] If the browser did not open, visit:
|
|
66
66
|
${d}
|
|
67
|
-
`),
|
|
68
|
-
`),c}finally{await new Promise(c=>o.close(()=>c())).catch(()=>{})}}function
|
|
67
|
+
`),Mi(d);try{let c=await s;return te.stdout.write(`[agensis] Saved daemon profile "${t}". Starting primary agent daemon.
|
|
68
|
+
`),c}finally{await new Promise(c=>o.close(()=>c())).catch(()=>{})}}function zi(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,(u,h)=>h.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==="fullCliContext"){t.fullCliContext=!0;continue}if(d==="syncMemory"){t.syncMemory=!0;continue}if(d==="noSyncSkills"){t.syncSkills=!1;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 u=a!==void 0?a:n[++o];if(u==null||u.startsWith("--"))throw new Error(`Missing value for --${i}`);t.hostFolders=[...t.hostFolders||[],u];continue}let c=a!==void 0?a:n[++o];if(c==null||c.startsWith("--"))throw new Error(`Missing value for --${i}`);t[d]=c}return t}function Ki(){return`agensis agent daemon
|
|
69
69
|
|
|
70
70
|
Usage:
|
|
71
71
|
agensis --url <workspace-url> --token <token> --workspace <id> --agent <id> [options]
|
|
@@ -86,6 +86,7 @@ Options:
|
|
|
86
86
|
--handle <name> Mention handle used in channels
|
|
87
87
|
--name <name> Display name
|
|
88
88
|
--cwd <path> Folder where the coding CLI runs
|
|
89
|
+
--runtime <runtime> Executor runtime: claude, codex, or amp
|
|
89
90
|
--host-folder <path> Extra folder the coding CLI may read/write (repeatable; passed as --add-dir)
|
|
90
91
|
--coding-cmd <command> Command used for jobs, default: claude -p
|
|
91
92
|
--amp-cmd <path> Amp CLI executable, default: amp
|
|
@@ -124,7 +125,7 @@ agensis supervise [--profile <name>] [--poll-ms <ms>]
|
|
|
124
125
|
"agensis connect" once first). Recommended under a process manager with its
|
|
125
126
|
own restart policy (systemd Restart=always, launchd KeepAlive, pm2) so the
|
|
126
127
|
supervisor itself is recovered if it's ever killed.
|
|
127
|
-
`}async function
|
|
128
|
-
`)}}:e}async function
|
|
129
|
-
`);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
|
|
128
|
+
`}async function Wi(e){let t=e.profile!==void 0,n=e.handle||e.name,r=Q(e.profile||(xt(e)&&n?n:"default"));if(!_r(e)){let o=await It(r);if(!o)throw new Error(Ct(r));return vr(o,e)}return xt(e)?{...e,cursorBuddyBridge:e.cursorBuddyBridge===!0,onRegistered:async o=>{await He(r,o);let s=t||r!=="default"?`agensis connect --profile ${r}`:"agensis connect";ne.stdout.write(`[agensis] Saved daemon profile "${r}". Restart with: ${s}
|
|
129
|
+
`)}}:e}async function Yi(){let e=zi(ne.argv.slice(2));if(e.help){ne.stdout.write(Ki());return}if(e.version){ne.stdout.write(`${ce}
|
|
130
|
+
`);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 Ar(e);n.cursorBuddyBridge=e.cursorBuddyBridge!==!1,n.cursorBuddyRuntime=!0,n.exitOnOnce=!0,await Fe(n),n.once&&ne.exit(0);return}if(e.command==="supervise"){let n=Q(e.profile||"default"),r=await It(n);if(!r)throw new Error(Ct(n));let{runSupervisor:o}=await Promise.resolve().then(()=>($r(),Or)),s=e.pollMs?Number(e.pollMs):void 0;await o({config:r,runningVersion:ce,profileName:n,pollIntervalMs:s});return}if(e.command==="setup"){let n=await xr(e);n.exitOnOnce=!0,await Fe({...e,...n}),n.once&&ne.exit(0);return}if(e.command!=="connect")throw new Error(`Unknown command "${e.command}". Use "agensis setup", "agensis connect --url ...", "agensis supervise", or "agensis buddy connect --key ...".`);let t=await Wi(e);t.exitOnOnce=!0,await Fe(t),t.once&&ne.exit(0)}Yi().catch(e=>{ne.stderr.write(`${e?.message||e}
|
|
130
131
|
`),ne.exitCode=1});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agensis/agensis-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
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": {
|