anyray-connect 0.11.180 → 0.11.182

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.
Files changed (2) hide show
  1. package/dist/index.js +2 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -258,7 +258,7 @@ try {
258
258
  `,{mode:ii,flag:"wx"}),await V.rename(a,e)}catch(s){try{await V.rm(a,{force:!0})}catch{}throw s}return!0}finally{await r()}},ql=async(e,t)=>{for(let n=0;n<JM;n+=1){let r=await uo(e);if(!r)return"failed";let o=t(r.value);if(!o||Xl(o,r.value))return"unchanged";try{if(await QM(e,r.raw,o))return"written"}catch{return"failed"}}return"failed"},av=async e=>{try{return(await V.readdir(e,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{return[]}},Ql=async e=>{let t=[];for(let n of await av(e))for(let r of await av(re(e,n)))t.push(re(e,n,r));return t},eB=e=>Array.isArray(e.skills)?e.skills.filter(t=>it(t)&&ci(t.name)&&t.creatorType==="user"&&t.syncManaged===!1):[],tB=async e=>{let t=re(e,"local-agent-mode-sessions","skills-plugin"),n=[];for(let r of await Ql(t)){let o=await uo(re(r,"manifest.json"));if(!o)continue;let a=r.split(si).at(-1)??"";for(let s of eB(o.value))n.push({account:a,packageDir:r,entry:s})}return n},nB=async e=>{let t=await uo(re(e,".claude-plugin","plugin.json"));return!!t&&ci(t.value.name)},rB=(e,t)=>{let n=Dm(t)?Xt(t):Xt(e,t);if(!dv(e,n)||n===Xt(e))return;let r=Zl(Xt(e),n);return r.length>0?{absolute:n,relative:r}:void 0},oB=async e=>{let t=await Ql(re(e,"local-agent-mode-sessions")),n=[];for(let r of t){if(r.split(si).includes("skills-plugin"))continue;let o=re(r,"cowork_plugins"),a=await uo(re(o,"installed_plugins.json"));if(!a||!it(a.value.plugins))continue;let s=r.split(si).at(-2)??"";for(let[i,c]of Object.entries(a.value.plugins))if(!(!ci(i)||!Array.isArray(c)))for(let l of c){if(!it(l)||l.scope!=="user"||typeof l.installPath!="string")continue;let d=rB(o,l.installPath);!d||!await nB(d.absolute)||n.push({account:s,id:i,entry:l,packageDir:d.absolute,relativeInstallPath:d.relative,settingsFile:re(r,"cowork_account_settings.json")})}}return n},aB=async e=>{let t=await uo(re(e,"claude_desktop_config.json"));return!t||!it(t.value.mcpServers)?{}:Object.fromEntries(Object.entries(t.value.mcpServers).filter(([n,r])=>ci(n)&&n.toLowerCase()!=="anyray"&&it(r)))},fv=async e=>{let[t,n,r]=await Promise.all([tB(e),oB(e),aB(e)]);return{skills:t,plugins:n,localMcpServers:r}},Nm=async e=>{let t=await fv(e);return{skills:t.skills.length,plugins:t.plugins.length,localMcpServers:Object.keys(t.localMcpServers).length,accounts:[...new Set([...t.skills.map(n=>n.account),...t.plugins.map(n=>n.account)])].filter(n=>n.length>0)}},sv=async e=>{try{let n=await V.lstat(e);if(!n.isDirectory()||n.isSymbolicLink())return!1}catch{return!1}let t=async n=>{let r;try{r=await V.readdir(n,{withFileTypes:!0})}catch{return!1}for(let o of r){if(!ci(o.name))return!1;let a=re(n,o.name);if(o.isSymbolicLink())return!1;if(o.isDirectory()){if(!await t(a))return!1}else if(!o.isFile())return!1}return!0};return t(e)},sB=async e=>{let t=async n=>{let r=await V.readdir(n,{withFileTypes:!0});for(let o of r){let a=re(n,o.name);if(o.isDirectory())await t(a),await V.chmod(a,Cn);else if(o.isFile()){let s=await V.stat(a);await V.chmod(a,(s.mode&73)!==0?cv:ii)}}};await t(e),await V.chmod(e,Cn)},mv=async(e,t)=>{try{let[n,r]=await Promise.all([V.readFile(e),V.readFile(t)]);return n.equals(r)}catch{return!1}},Jl=async(e,t)=>{try{let[n,r]=await Promise.all([V.readdir(e,{withFileTypes:!0}),V.readdir(t,{withFileTypes:!0})]),o=n.map(s=>s.name).sort(),a=r.map(s=>s.name).sort();if(!Xl(o,a))return!1;for(let s of o){let i=n.find(l=>l.name===s),c=r.find(l=>l.name===s);if(!i||!c||i.isDirectory()!==c.isDirectory()||i.isFile()!==c.isFile())return!1;if(i.isDirectory()){if(!await Jl(re(e,s),re(t,s)))return!1}else if(!i.isFile()||!await mv(re(e,s),re(t,s)))return!1}return!0}catch{return!1}},hv=e=>`${e}.anyray-incomplete`,yv=async(e,t)=>{let n=!1;if(t){await V.mkdir(wa(e),{recursive:!0,mode:Cn});try{await V.mkdir(e,{mode:Cn}),n=!0}catch(l){if(!vt(l)||l.code!=="EEXIST")return}}else try{let l=await V.lstat(e);if(!l.isDirectory()||l.isSymbolicLink())return}catch{return}let r=zl(),o;for(let l=0;l<3&&!o;l+=1){let d=0;if(!n){let f;try{f=await Yl(e)}catch{return}if(f){if(!pv(f)||!Number.isSafeInteger(f.generation+1))return;d=f.generation+1}else if(await V.stat(e).then(m=>Date.now()-m.mtimeMs).catch(()=>0)<=Lm)return}let u=re(e,uv(d));try{await V.writeFile(u,`${JSON.stringify({pid:process.pid,nonce:r,createdAt:Date.now()})}
259
259
  `,{flag:"wx",mode:ii}),o=u}catch(f){if(vt(f)&&f.code==="EEXIST"){n=!1;continue}n&&await V.rm(e,{recursive:!0,force:!0}).catch(()=>{});return}}if(!o)return;let a=o,s=setInterval(()=>{(async()=>{try{let l=JSON.parse(await V.readFile(a,"utf8"));if(!it(l)||l.nonce!==r)return;let d=new Date;await V.utimes(a,d,d)}catch{}})()},lv);s.unref();let i=!1,c=()=>{i||(i=!0,clearInterval(s))};return{abandon:c,complete:async()=>{c();try{(await Yl(e))?.nonce===r&&await V.rm(e,{recursive:!0,force:!0})}catch{}}}},gv=async e=>{let t=await yv(e,!1);t&&await t.complete()},iB=async(e,t,n)=>{let r=hv(t),o=!1;try{let c=await V.lstat(t);if(!c.isDirectory()||c.isSymbolicLink())return"conflict";if(o=!0,await Jl(e,t))return await gv(r),"present"}catch(c){if(!vt(c)||c.code!=="ENOENT")return"failed"}if(o)try{let c=await V.lstat(r);if(!c.isDirectory()||c.isSymbolicLink())return"conflict"}catch{return"conflict"}let a=await yv(r,!o);if(!a)return"failed";try{await n?.(t)}catch{return a.abandon(),"failed"}if(!o)try{await V.mkdir(t,{mode:Cn})}catch(c){if(!vt(c)||c.code!=="EEXIST")return a.abandon(),"failed";try{let l=await V.lstat(t);if(!l.isDirectory()||l.isSymbolicLink())return await a.complete(),"conflict"}catch{return a.abandon(),"failed"}}let s=async(c,l)=>{let d;try{d=await V.readdir(c,{withFileTypes:!0})}catch{return"failed"}for(let u of d){let f=re(c,u.name),p=re(l,u.name);try{if(u.isDirectory()){try{await V.mkdir(p,{mode:Cn})}catch(h){if(!vt(h)||h.code!=="EEXIST")throw h;let g=await V.lstat(p);if(!g.isDirectory()||g.isSymbolicLink())return"conflict"}let m=await s(f,p);if(m!=="copied")return m}else if(u.isFile())try{await V.copyFile(f,p,YM.COPYFILE_EXCL);let m=await V.stat(f);await V.chmod(p,(m.mode&73)!==0?cv:ii)}catch(m){if(!vt(m)||m.code!=="EEXIST")throw m;if(!await mv(f,p))return"conflict"}else return"failed"}catch(m){return vt(m)&&m.code==="EEXIST"?"conflict":"failed"}}return"copied"},i=await s(e,t);return i==="failed"?(a.abandon(),"failed"):i==="conflict"?(await a.complete(),"conflict"):await Jl(e,t)?(await a.complete(),"copied"):(await a.complete(),"conflict")},wv=async(e,t,n,r)=>{if(!await sv(e))return"invalid";try{let a=await V.lstat(t);if(!a.isDirectory()||a.isSymbolicLink())return"conflict";if(await Jl(e,t))return await gv(hv(t)),"present"}catch(a){if(!vt(a)||a.code!=="ENOENT")return"failed"}await V.mkdir(wa(t),{recursive:!0,mode:Cn});let o=re(wa(t),`.anyray-stage-${zl()}`);try{return await V.cp(e,o,{recursive:!0,force:!1,errorOnExist:!0}),await sv(o)?(await sB(o),await n?.(t),await iB(o,t,r)):"invalid"}catch{return"failed"}finally{try{await V.rm(o,{recursive:!0,force:!0})}catch{}}},iv=(e,t,n)=>n||!t?e:e.filter(r=>r.account.startsWith(t)),cB=async e=>{let t=await Ql(re(e,"local-agent-mode-sessions","skills-plugin")),n=[];for(let r of t)(await uo(re(r,"manifest.json")))?.raw!==void 0&&n.push(r);return n.length===1?{state:"found",path:n[0]}:{state:n.length===0?"missing":"ambiguous"}},lB=async e=>{let t=await Ql(re(e,"local-agent-mode-sessions")),n=[];for(let r of t)if(!r.split(si).includes("skills-plugin"))try{await V.access(re(r,"cowork_account_settings.json")),n.push(r)}catch{}return n.length===1?{state:"found",path:n[0]}:{state:n.length===0?"missing":"ambiguous"}},dB=async(e,t,n,r,o)=>{let a=re(t,"manifest.json");for(let s of e){let i=re(s.packageDir,"skills",s.entry.name);try{await V.access(re(i,"SKILL.md"))}catch{n.invalid+=1;continue}let c=re(t,"skills",s.entry.name),l=await wv(i,c,r,o);if(l==="conflict"){n.conflicts+=1;continue}if(l==="invalid"){n.invalid+=1;continue}if(l==="failed"){n.failed+=1;continue}let d=!1;await ql(a,f=>{let p=Array.isArray(f.skills)?f.skills:[];if(p.find(h=>it(h)&&typeof h.name=="string"&&h.name.toLowerCase()===s.entry.name.toLowerCase())){d=!0;return}return{...f,skills:[...p,s.entry]}})==="failed"?n.failed+=1:d||l==="present"?n.alreadyPresent+=1:n.migrated+=1}},bv=(e,t)=>({...e,installPath:t}),uB=(e,t,n,r,o)=>{if(typeof r.installPath!="string")return!1;let a=Dm(r.installPath)?Xt(r.installPath):Xt(o,r.installPath),s=bv(e,Zl(Xt(t),Xt(n))),i={...r,installPath:Zl(Xt(o),a)};return Xl(s,i)},pB=async(e,t,n)=>{let r=await uo(e);if(!r||!it(r.value.enabledPlugins))return"unchanged";let o=r.value.enabledPlugins[n];return typeof o!="boolean"?"unchanged":ql(t,a=>{let s=it(a.enabledPlugins)?a.enabledPlugins:{};if(!(n in s))return{...a,enabledPlugins:{...s,[n]:o}}})},fB=async(e,t,n,r,o)=>{let a=re(t,"cowork_plugins"),s=re(a,"installed_plugins.json"),i=re(t,"cowork_account_settings.json");for(let c of e){let l=re(a,c.relativeInstallPath);if(!dv(a,l)){n.invalid+=1;continue}let d=await wv(c.packageDir,l,r,o);if(d==="conflict"){n.conflicts+=1;continue}if(d==="invalid"){n.invalid+=1;continue}if(d==="failed"){n.failed+=1;continue}let u=!1,f=!1;await ql(s,m=>{let h=it(m.plugins)?m.plugins:{},g=h[c.id],y=Array.isArray(g)?g:[],w=y.find(k=>it(k)&&k.scope==="user");if(w){u=uB(c.entry,wa(c.settingsFile),c.packageDir,w,t),f=!u;return}let b=bv(c.entry,l);return{...m,version:typeof m.version=="number"?m.version:2,plugins:{...h,[c.id]:[...y,b]}}})==="failed"?n.failed+=1:f?n.conflicts+=1:await pB(c.settingsFile,i,c.id)==="failed"?n.failed+=1:u||d==="present"?n.alreadyPresent+=1:n.migrated+=1}},mB=async(e,t,n)=>{let r=re(t,"claude_desktop_config.json");for(let[o,a]of Object.entries(e)){let s={value:"migrated"};await ql(r,c=>{let l=it(c.mcpServers)?c.mcpServers:{};if(o in l){s.value=Xl(l[o],a)?"present":"conflict";return}return{...c,mcpServers:{...l,[o]:a}}})==="failed"?n.failed+=1:s.value==="present"?n.alreadyPresent+=1:s.value==="conflict"?n.conflicts+=1:n.migrated+=1}},Av=async(e,t,n={})=>{let r=await fv(e),o=Pm("skill"),a=Pm("plugin"),s=Pm("local-mcp"),i=[],c=[],l=iv(r.skills,n.account,n.allAccounts),d=iv(r.plugins,n.account,n.allAccounts);if(n.allowedAccounts&&!n.allAccounts){let f=new Set(n.allowedAccounts);if([...new Set([...l.map(m=>m.account),...d.map(m=>m.account)])].some(m=>!f.has(m)))return{outcomes:[o,a,s],blocked:i,ambiguous:c,sourceChanged:!0,retryable:[]}}if(l.length>0){let f=await cB(t);f.state==="found"?await dB(l,f.path,o,n.beforeDirectoryPublish,n.afterDirectoryClaim):f.state==="missing"?i.push("skill"):(o.conflicts+=l.length,c.push("skill"))}if(d.length>0){let f=await lB(t);f.state==="found"?await fB(d,f.path,a,n.beforeDirectoryPublish,n.afterDirectoryClaim):f.state==="missing"?i.push("plugin"):(a.conflicts+=d.length,c.push("plugin"))}await mB(r.localMcpServers,t,s);let u=[o,a,s];return{outcomes:u,blocked:i,ambiguous:c,sourceChanged:!1,retryable:u.filter(f=>f.failed>0).map(f=>f.kind)}};var gB=async e=>{try{return await St.access(e),!0}catch{return!1}},Cv=448,wB=384,vv={code:"claude-code-sessions",cowork:"local-agent-mode-sessions"},bB=["code","cowork"],Bm=(e,t,n,r=!1)=>r?"Claude Desktop has not been set up on Anyray yet \u2014 run `anyray-connect desktop` first, then open Claude Desktop once and fully quit it.":e==="ambiguous"?`Claude Desktop's third-party profile holds more than one ${t} store, so which one to fill is your call \u2014 re-run \`${n}\` with \`--account <id>\`.`:t==="cowork"?"Open Claude Desktop, sign in, and open the Cowork tab once \u2014 that is what creates the store \u2014 then fully quit it and run this again.":"Open Claude Desktop, sign in, and start a Claude Code session once \u2014 that is what creates the store \u2014 then fully quit it and run this again.",$m=e=>({lane:e,migrated:0,alreadyPresent:0,skippedNoTranscript:0,failed:0}),Sv=async e=>{let t;try{t=(await St.readdir(e,{withFileTypes:!0})).filter(r=>r.isDirectory()&&aa(r.name)).map(r=>r.name)}catch{return[]}let n=[];for(let r of t)try{let o=(await St.readdir(zt(e,r),{withFileTypes:!0})).filter(a=>a.isDirectory()&&aa(a.name)).map(a=>a.name);for(let a of o)n.push(zt(e,r,a))}catch{}return n},AB=async e=>{try{return(await St.readdir(e)).filter(t=>t.startsWith(Fn)&&t.endsWith(".json")).map(t=>t.slice(Fn.length,-5)).filter(aa)}catch{return[]}},CB=async(e,t)=>{let n=await Sv(zt(e,vv[t])),r=[];for(let o of n){let a=await AB(o);a.length>0&&r.push({dir:o,ids:a,account:o.split(yB).slice(-2)[0]})}return r},kB=async(e,t)=>{if(t==="cowork"){let r=await Ol(e);return r.ok?{dir:r.dir}:{missing:r.reason}}let n=await Sv(zt(e,vv.code));return n.length===1?{dir:n[0]}:{missing:n.length===0?"no-account":"ambiguous"}},vB=async(e,t)=>{let n=`${t}.anyray-tmp-${process.pid}`;await St.copyFile(e,n),await St.chmod(n,wB),await St.rename(n,t)},SB=async(e,t)=>{try{let n=JSON.parse(await St.readFile(e,"utf8"));if(!n||typeof n!="object")return!1;let{cwd:r,cliSessionId:o}=n;return typeof r!="string"||typeof o!="string"||r.length===0||!aa(o)?!1:(await St.access(zt(t,".claude","projects",tm(r),`${o}.jsonl`)),!0)}catch{return!1}},EB=async(e,t,n,r)=>{let o=$m(e),a=await nm(n);for(let s of t)await IB(e,s,n,r,a,o);return o},IB=async(e,t,n,r,o,a)=>{for(let s of t.ids){if(o.has(s)){a.alreadyPresent+=1;continue}let i=`${Fn}${s}.json`,c=zt(t.dir,i);try{if(e==="code"){if(!await SB(c,r)){a.skippedNoTranscript+=1;continue}}else{let l=zt(t.dir,`${Fn}${s}`),d=zt(n,`${Fn}${s}`),u=await St.readdir(l);await St.mkdir(d,{mode:Cv});for(let f of u)await St.cp(zt(l,f),zt(d,f),{recursive:!0,force:!1,errorOnExist:!0});await St.chmod(d,Cv)}await vB(c,zt(n,i)),o.add(s),a.migrated+=1}catch{a.failed+=1}}},kv=(e,t,n,r=[])=>{let o=new Map;for(let{sources:s}of e)for(let i of s){let c=o.get(i.account)??{sessions:0,portable:!1};c.sessions+=i.ids.length,o.set(i.account,c)}for(let s of r){let i=o.get(s)??{sessions:0,portable:!1};i.portable=!0,o.set(s,i)}let a=[...o.entries()].sort((s,i)=>i[1].sessions-s[1].sessions).map(([s,i])=>{let c=i.sessions===0?"portable configuration":`${i.sessions} session${i.sessions===1?"":"s"}${i.portable?" plus portable configuration":""}`;return` ${t} --account ${s.slice(0,8)} (${c})`});return{ok:!1,kind:"account-ambiguous",reason:n,remedy:["Pick the one you want, or take everything:",...a,` ${t} --all-accounts`].join(`
260
260
  `)}},Mm=e=>new Set(e.flatMap(t=>t.sources.map(n=>n.account))),Ev=async e=>{let t=[];for(let n of bB)t.push({lane:n,sources:await CB(e,n)});return t},Iv=async(e={})=>{let t=(e.firstPartyRoot??(()=>Ys()))();if(!t)return{sessions:0,accounts:0,userSkills:0,userPlugins:0,localMcpServers:0};let[n,r]=await Promise.all([Ev(t),Nm(t)]),o=n.reduce((s,i)=>s+i.sources.reduce((c,l)=>c+l.ids.length,0),0),a=Mm(n);for(let s of r.accounts)a.add(s);return{sessions:o,accounts:a.size,userSkills:r.skills,userPlugins:r.plugins,localMcpServers:r.localMcpServers}},po=async(e={})=>{let t=(e.home??hB)(),n=(e.firstPartyRoot??(()=>Ys()))(),r=(e.thirdPartyRoot??(()=>so()))();if(!n||!r)return{ok:!1,kind:"platform-unsupported",reason:"this platform has no Claude Desktop third-party profile",remedy:"Migration applies to macOS and Windows, where Desktop runs third-party mode in its own profile."};if((e.appRunning??ga())())return{ok:!1,kind:"app-running",reason:"Claude Desktop is running",remedy:"Fully quit Claude Desktop and run this again \u2014 it rewrites its session list on exit, which would undo the migration."};let[o,a]=await Promise.all([Ev(n),Nm(n)]),s;if(e.account){let p=e.account;for(let g of o)g.sources=g.sources.filter(y=>y.account.startsWith(p));let m=a.accounts.filter(g=>g.startsWith(p));if(o.every(g=>g.sources.length===0)&&m.length===0)return{ok:!1,kind:"account-unmatched",reason:`no account in the previous profile starts with "${p}"`,remedy:`Run \`${e.command??"anyray-connect desktop --migrate"}\` with no flags to list the accounts.`};let h=Mm(o);for(let g of m)h.add(g);if(h.size>1)return kv(o,e.command??"anyray-connect desktop --migrate",`"${p}" matches ${h.size} accounts`,m);s=[...h]}else if(!e.allAccounts){let p=Mm(o);for(let m of a.accounts)p.add(m);if(p.size>1)return kv(o,e.command??"anyray-connect desktop --migrate",`the previous Claude Desktop profile holds local data for ${p.size} accounts`,a.accounts);s=[...p]}let i=e.command??"anyray-connect desktop --migrate",c=!await gB(r),l=await Av(n,r,{account:e.account,allAccounts:e.allAccounts,allowedAccounts:s});if(l.sourceChanged)return{ok:!1,kind:"account-ambiguous",reason:"the previous Claude Desktop profile changed during migration and now holds local data for another account",remedy:`Re-run \`${i}\` so the account choice is made from a fresh snapshot.`};let d=[],u=[];for(let{lane:p,sources:m}of o){if(m.length===0){d.push($m(p));continue}let h=await kB(r,p);if("missing"in h){u.push({lane:p,reason:h.missing,waiting:m.reduce((g,y)=>g+y.ids.length,0)}),d.push($m(p));continue}d.push(await EB(p,m,h.dir,t))}if(!(d.some(p=>p.migrated>0||p.alreadyPresent>0)||l.outcomes.some(p=>p.migrated>0||p.alreadyPresent>0||p.conflicts>0))&&(u.length>0||l.blocked.length>0)){let p=u[0];return p?{ok:!1,kind:p.reason==="ambiguous"?"account-ambiguous":"store-missing",reason:p.reason==="ambiguous"?`Claude Desktop's third-party profile holds more than one ${p.lane} store`:`Claude Desktop has no ${p.lane} store in its third-party profile yet`,remedy:Bm(p.reason,p.lane,i,c)}:{ok:!1,kind:"store-missing",reason:"Claude Desktop's third-party profile has no extension store yet",remedy:"Open Claude Desktop once after connecting it to Anyray, then fully quit it so the portable extensions can be copied safely."}}return{ok:!0,lanes:d,portableAssets:l.outcomes,...u.length>0?{blocked:u}:{},...l.blocked.length>0?{blockedAssets:l.blocked}:{},...l.ambiguous.length>0?{ambiguousAssets:l.ambiguous}:{},...l.retryable.length>0?{retryableAssets:l.retryable}:{}}};var xB=e=>[Le(e)],xv=e=>({id:e.id,title:e.title,automatic:!1,async detect(){let t=[...xB(e.appDir),...e.detectPaths?.()??[]];for(let n of t)if(await x(n))return{installed:!0,detail:n};return{installed:!1,detail:`${e.appDir} not found`}},async apply(t){return{status:"manual",messages:e.steps(t)}},async revert(t){return{status:"manual",messages:e.revertMessages??[`${e.title}: clear the custom OpenAI base URL / key in its settings to revert.`]}}});var Rv="1.21459.0",_B=TB(RB),PB=async e=>{try{let{stdout:t}=await _B("/usr/bin/plutil",["-extract","CFBundleShortVersionString","raw","-o","-",e],{timeout:2e3,maxBuffer:4096});return String(t).trim()||void 0}catch{return}},DB=async e=>{try{return await OB(e)}catch{return}},Ov="No native config was written; use Developer \u2192 Configure Third-Party Inference \u2192 Apply locally.",LB=["Admin policy setup (no JSON): open Developer \u2192 Configure Third-Party Inference; the Anyray connection is already filled in.",'Add approved remote MCP connectors under "Connectors & extensions" and use "Test this connection"; add approved Git marketplaces under "Plugins & skills".',`Choose "Apply locally" to test. For Jamf, first select IT's fleet-wide credential-helper path, then choose Export \u2192 .mobileconfig and deploy the complete profile.`,"If Claude Desktop is already MDM-managed, this window is read-only. Author and export on an unmanaged admin Mac, then redeploy through Jamf."],ba=async(e={})=>!e.home&&!e.readClaudeAppVersion&&!e.readClaudeAppBundle?(Tv??=_v({}),Tv):_v(e),Tv,_v=async e=>{let t=(e.home??di)(),n=["/Applications/Claude.app",kn(t,"Applications","Claude.app")],r=e.readClaudeAppVersion??PB,o=e.readClaudeAppBundle??DB;for(let a of n){let s=await r(kn(a,"Contents","Info.plist"));if(!s)continue;let i=d=>({supported:!1,detectedVersion:s,appPath:a,message:`Claude Desktop ${s} is installed, but ${d} ${Ov}`}),c=xl(s,Rv);if(c===void 0)return i("its version string could not be interpreted.");if(c<0)return i(`automatic local setup requires ${Rv} or newer.`);let l=await o(kn(a,"Contents","Resources","app.asar"));return l?fk.some(d=>!l.includes(d))?i("its local config seam no longer matches the shape Connect writes."):{supported:!0,detectedVersion:s,appPath:a}:i("its app bundle could not be read to verify the local config seam.")}return{supported:!1,message:`Could not verify the installed Claude Desktop version. ${Ov}`}},ed="anyray",Lv="--anyray-owner=claude-desktop-v1",td=(e={})=>{let t=(e.platform??Er)(),n=(e.home??di)();return t==="darwin"?Yt(e).appConfig:t==="win32"?kn(process.env.APPDATA??kn(n,"AppData","Roaming"),"Claude","claude_desktop_config.json"):kn(n,".config","Claude","claude_desktop_config.json")},Gm=(e={})=>kn((e.home??di)(),"Library","Application Support","Claude","claude_desktop_config.json"),Nv=()=>{let e=Ge("profile");return{command:e.command,args:[...e.args,Lv]}},fo=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),$v=(e,t)=>{let n=Object.keys(e).sort(),r=[...t].sort();return n.length===r.length&&n.every((o,a)=>o===r[a])},NB=(e,t)=>Array.isArray(e)&&e.length===t.length&&e.every((n,r)=>typeof n=="string"&&n===t[r]),$B=e=>{if(!fo(e)||!$v(e,["command","args"]))return!1;let t=Nv();return e.command===t.command&&NB(e.args,t.args)},MB=e=>fo(e)&&Array.isArray(e.args)&&e.args.at(-1)===Lv,BB=e=>{if(!fo(e)||!$v(e,["command","args"])||typeof e.command!="string"||!Array.isArray(e.args)||!e.args.every(a=>typeof a=="string")||et(e.command))return!1;let t=e.args;if(!(t.length>=2&&t.at(-2)===er&&t.at(-1)==="profile"))return!1;let r=e.command.replaceAll("\\","/");if(/(?:^|\/)anyray-connect(?:\.exe)?$/.test(r))return t.length===2;if(!/(?:^|\/)node(?:\.exe)?$/.test(r)||t.length!==3)return!1;let o=t[0].replaceAll("\\","/");return!et(t[0])&&(/(?:^|\/)anyray-connect(?:\/|$)/.test(o)||/(?:^|\/)\.anyray\/bin\/connect-runtime-[0-9A-Za-z][0-9A-Za-z.-]*\/dist\/index\.js$/.test(o))},FB=e=>e===void 0?"absent":$B(e)?"exact":MB(e)||BB(e)?"stale-owned":"foreign",Fe=class extends Error{changedFiles;constructor(t,n=[]){super(t),this.changedFiles=n}},mo=async e=>{let t=await x(e),n;try{n=await M(e)}catch{throw new Fe(`Could not parse ${e}; it was left unchanged.`)}if("mcpServers"in n&&!fo(n.mcpServers))throw new Fe(`Could not update ${e} because mcpServers is not an object; it was left unchanged.`);let o=(fo(n.mcpServers)?n.mcpServers:void 0)?.[ed];return{path:e,fileExisted:t,json:n,entry:o,ownership:FB(o)}},nd=e=>{if(e.ownership==="foreign")throw new Fe(`MCP name conflict in ${e.path}: mcpServers.${ed} is not owned by Anyray Connect, so it was left untouched. Rename that existing server, then re-run Connect.`)},Mv=(e,t)=>{let n={...e},r=fo(e.mcpServers)?{...e.mcpServers}:{};return t===void 0?delete r[ed]:r[ed]=t,Object.keys(r).length===0?delete n.mcpServers:n.mcpServers=r,n},Wm=async(e,t)=>{if(Fm(e.entry,t))return;let n=await mo(e.path);if(!Fm(n.entry,e.entry))throw new Fe(`The MCP configuration in ${e.path} changed during setup; it was left untouched. Re-run Connect.`);return await Wn(e.path,Mv(n.json,t)),{reading:e,afterEntry:t}},Um=async e=>{let t=await mo(e.reading.path);if(!Fm(t.entry,e.afterEntry))throw new Fe(`The MCP configuration in ${e.reading.path} changed before rollback; the newer value was preserved.`);let n=Mv(t.json,e.reading.entry);await Wn(e.reading.path,n)},WB=async e=>{if(!ne())throw new Fe(`A durable anyray-connect runtime is required for Claude Desktop retrieval (${_e()} is temporary); no inference setting was changed.`);let t=await mo(td(e));nd(t);let n=Gm(e),r=(e.platform??Er)()==="darwin"&&n!==t.path?await mo(n):void 0;return r&&nd(r),{active:t,...r?{legacy:r}:{}}},Pv=async e=>{let t=await mo(td(e));nd(t);let n=Gm(e),r=(e.platform??Er)()==="darwin"&&n!==t.path?await mo(n):void 0;return r&&nd(r),{active:t,...r?{legacy:r}:{}}},UB=async e=>{let t=[];try{let n=await Wm(e.active,Nv());if(n&&t.push(n),e.legacy&&e.legacy.ownership!=="absent"){let r=await Wm(e.legacy,void 0);r&&t.push(r)}}catch(n){let r=[];for(let o of[...t].reverse())await Um(o).catch(()=>{r.push(o.reading.path)});throw r.length>0?new Fe(`Claude Desktop MCP setup failed and could not restore ${r.join(", ")}. Re-run \`anyray-connect desktop disconnect\` to recover safely.`,r):n}return{changedFiles:t.map(n=>n.reading.path),async rollback(){let n=[];for(let r of[...t].reverse())await Um(r).catch(()=>{n.push(r.reading.path)});if(n.length>0)throw new Fe(`Claude Desktop MCP rollback could not restore ${n.join(", ")}. Newer values were preserved; re-run revert after resolving the conflict.`,n)}}},HB=async e=>{let t=[];try{for(let n of[e.active,e.legacy].filter(r=>!!r)){if(n.ownership==="absent")continue;let r=await Wm(n,void 0);r&&t.push(r)}}catch(n){let r=[];for(let o of[...t].reverse())await Um(o).catch(()=>{r.push(o.reading.path)});throw r.length>0?new Fe(`Claude Desktop MCP cleanup failed and could not restore ${r.join(", ")}. Re-run revert after resolving the file conflict.`,r):n}return t.map(n=>n.reading.path)},Dv=e=>{let t=e.clientKey?`${e.clientKey} (your personal gateway key - keep it private)`:`${e.placeholderKey} (placeholder - the gateway holds the real key)`;return["Step 1 - Turn on Developer Mode."," In the menu bar at the VERY TOP of the screen (NOT the in-app help panel):"," Help -> Troubleshooting -> Enable Developer Mode"," (Windows: open the menu at the top-left of the sign-in screen.)",' A "Developer" menu then appears in that same top-of-screen menu bar.',"","Step 2 - Open the Developer MENU in the menu bar (shown below) - NOT Settings:",""," +----------------------------------------------------------------+"," | Claude File Edit View Window [Developer] Help | <- macOS menu bar (very top of screen)"," +-------------------------------------^--------------------------+"," |",' click Developer -> "Configure Third-Party Inference..."',"",' Heads up: use the "Developer" MENU in the bar above - NOT',' Settings -> Developer, which is the "Local MCP servers" pane'," (that's where Anyray's retrieval server appears, not inference)."," A separate setup window then opens.","","Step 3 - In that window's Connection section, paste:",""," Inference provider: Gateway",` Gateway base URL: ${e.anthropicBaseUrl}`," Auth scheme: Bearer",` API key: ${t}`,"",'Step 4 - Click "Apply locally", then fully quit and reopen Claude'," (the config is read once at launch).","","Billing: this route uses an Anyray gateway credential and provider/API billing, not a Claude subscription allowance.","Fleet/MDM: generate a managed profile with `anyray-connect desktop claude --mobileconfig` (applies with no Developer Mode and no paste)."]},GB={darwinAppName:"Claude",darwinBundleId:"com.anthropic.claudefordesktop",win32Image:"Claude.exe",win32Install:[{root:"localAppData",path:"Programs\\Claude\\Claude.exe"}]},rd="claude-desktop",Hm="migrate",Bv=new Set(["app-running","store-missing"]),VB={code:{one:"Claude Code session",many:"Claude Code sessions"},cowork:{one:"Cowork task",many:"Cowork tasks"}},KB={skill:{one:"user-created skill",many:"user-created skills"},plugin:{one:"user-installed plugin",many:"user-installed plugins"},"local-mcp":{one:"local MCP server",many:"local MCP servers"}},jB="Claude Desktop machine policy could not be read; Connect left inference and retrieval configuration unchanged.",Fv=e=>{let t=(e.platform??Er)(),n=e.home??di;return{home:n,appRunning:e.appRunning??ga(t),firstPartyRoot:()=>Ys({home:n,runtimePlatform:t}),thirdPartyRoot:()=>so({home:n,runtimePlatform:t}),command:"anyray-connect migrate"}},Wv=e=>{let t=e.filter(a=>a.migrated>0);if(t.length===0)return;let n=e.reduce((a,s)=>a+s.skippedNoTranscript,0),r=e.reduce((a,s)=>a+s.failed,0);return`Brought your existing Claude Desktop sessions into its third-party profile: ${t.map(a=>{let s=VB[a.lane];return`${a.migrated} ${a.migrated===1?s.one:s.many}`}).join(", ")}.`+(n>0?` ${n} skipped \u2014 the transcript is no longer on disk.`:"")+(r>0?` ${r} could not be copied.`:"")},Uv=e=>{let t=e.filter(s=>s.migrated>0),n=e.reduce((s,i)=>s+i.conflicts,0),r=e.reduce((s,i)=>s+i.invalid,0),o=e.reduce((s,i)=>s+i.failed,0);if(t.length===0&&n+r+o===0)return;let a=t.map(s=>{let i=KB[s.kind];return`${s.migrated} ${s.migrated===1?i.one:i.many}`});return(a.length>0?`Brought your portable Claude Desktop configuration across: ${a.join(", ")}.`:"Portable Claude Desktop configuration was checked; existing target entries were kept.")+(n>0?` ${n} conflicting target ${n===1?"entry was":"entries were"} preserved.`:"")+(r>0?` ${r} unsafe or incomplete ${r===1?"entry was":"entries were"} skipped.`:"")+(o>0?` ${o} could not be copied.`:"")},li=async(e,t)=>{if(!t.reportsToUser)return[];try{let n=Fv(e),r=await(e.pendingDesktopMigrationCount??Iv)(n),o=r.userSkills+r.userPlugins+r.localMcpServers;if(r.sessions+o===0)return[];if(t.dryRun)return[`Would bring ${[r.sessions>0?`${r.sessions} existing Claude Desktop session${r.sessions===1?"":"s"}`:"",o>0?`${o} portable configuration ${o===1?"entry":"entries"}`:""].filter(Boolean).join(" and ")} into Claude Desktop's third-party profile, now or automatically the next time Claude Desktop is fully quit.`];let a=await(e.migrateDesktopProfile??po)(n);if(a.ok){let c=Wv(a.lanes),l=Uv(a.portableAssets),d=a.ambiguousAssets??[],u=d.length>0?`Claude Desktop has more than one target ${d.join(" and ")} store. No store was chosen and every target was preserved. Leave only the intended third-party account/workspace active, then run the migration again.`:void 0,f=(a.blocked??[]).filter(w=>w.reason!=="ambiguous"),p=a.blockedAssets??[],m=a.retryableAssets??[];if(f.length===0&&p.length===0&&m.length===0)return[c,l,u].filter(w=>!!w);if(t.preservePendingOp)return[c,l,u].filter(w=>!!w);await Ss(rd,Hm);let h=f.reduce((w,b)=>w+b.waiting,0),g=[h>0?`${h} more session${h===1?"":"s"}`:"",p.length>0?`${p.length} extension ${p.length===1?"store":"stores"}`:""].filter(Boolean),y=[...g.length>0?[`Queued: ${g.join(" and ")} move across once Claude Desktop creates the required third-party stores and the app is fully quit.`]:[],...m.length>0?[`Queued: ${m.length} portable configuration ${m.length===1?"type":"types"} will retry automatically after a recoverable local-copy interruption.`]:[]];return[...c?[c]:[],...l?[l]:[],...u?[u]:[],...y]}if(!Bv.has(a.kind))return[`Your existing Claude Desktop local data was left where it is: ${a.reason}.
261
- ${a.remedy}`];if(t.preservePendingOp)return[];await Ss(rd,Hm);let s=r.sessions+o,i=`${s} Claude Desktop local ${s===1?"item":"items"}`;return[a.kind==="store-missing"?`Queued: the ${i} still in your previous profile move across once Claude Desktop's new profile has been signed in to and the app is fully quit.`:`Queued: the ${i} still in your previous profile will move across the next time you fully quit Claude Desktop.`]}catch{return["Could not check whether Claude Desktop had existing sessions to bring across; run `anyray-connect migrate` if its lists look empty."]}},ZB=async e=>{if(!e.fullRevert||e.dryRun)return[];try{return await ur(rd),[]}catch{return["Could not clear Claude Desktop's queued profile-migration marker; a background watcher may still be waiting for the app to quit. Delete it by hand if it persists."]}},YB=e=>xv({id:rd,title:"Claude desktop",appDir:"Claude",detectPaths:()=>{let t=(e.platform??Er)(),n=(e.home??di)();return t==="darwin"?["/Applications/Claude.app",kn(n,"Applications","Claude.app")]:t==="win32"?[kn(process.env.LOCALAPPDATA??kn(n,"AppData","Local"),"Programs","Claude","Claude.exe")]:[]},steps:t=>ee(t,"anthropic")?["Claude Desktop subscription routing requires automatic setup on a verified macOS build and a Claude Code sign-in in Keychain.","This platform/build has no verified subscription helper seam, so Connect left inference unchanged instead of silently switching you to API billing.","To opt into the API-billed Gateway lane instead, re-run Connect in org/API mode and use:",...Dv(t)]:["Claude desktop org/API lane:",...Dv(t),"This Gateway route uses provider/API billing. On verified macOS builds, subscription mode instead installs the Keychain-backed Claude Code credential helper automatically."],revertMessages:["Claude Desktop third-party inference: switch back to the first-party Claude provider in Developer settings (or remove the managed profile). Native setup is restored automatically by `--revert`."]}),JB=(e={})=>{let t=YB(e),n=()=>(e.platform??Er)()==="darwin",r=()=>(e.platform??Er)()==="win32",o=(s,i)=>n()?Ck(s,i,e):Qk(s,s.clientKey??"",i,e),a=s=>n()?kk(s,e):ev(s,e);return{...t,automatic:!0,changesOrgManagement:!0,quitGated:{isRunning:()=>(e.appRunning??ga((e.platform??Er)()))(),quitTarget:GB,needsTarget:()=>!1,async complete(s){if(s!==Hm)return{status:"manual",messages:[`Claude Desktop could not service a queued "${s}" operation it does not recognise; the queue entry was dropped.`]};let i=await(e.migrateDesktopProfile??po)(Fv(e));if(i.ok){let c=Wv(i.lanes),l=Uv(i.portableAssets),d=i.ambiguousAssets??[];if(d.length>0)return{status:"manual",messages:[...c?[c]:[],...l?[l]:[],`Claude Desktop has more than one target ${d.join(" and ")} store. No store was chosen and every target was preserved. Leave only the intended third-party account/workspace active, then run the migration again.`]};let f=(i.blocked??[]).filter(h=>h.reason!=="ambiguous"),p=i.blockedAssets??[],m=i.retryableAssets??[];return f.length>0||p.length>0||m.length>0?{status:"queued",messages:[...c?[c]:[],...l?[l]:[],...f.length>0||p.length>0?["Still waiting on Claude Desktop to create the remaining third-party stores, which appear the first time those parts of the app are opened."]:[],...m.length>0?["A recoverable local-copy interruption remains; the migration will retry automatically."]:[]]}:{status:"configured",messages:c||l?[c,l].filter(h=>!!h):["No portable Claude Desktop data was left to bring across."]}}return Bv.has(i.kind)?{status:"queued",messages:[i.reason]}:{status:"manual",messages:[i.reason,i.remedy]}}},async usesDynamicCredential(s){return n()?Sk(s,e):r()?rv(s,e):!1},async apply(s,i){if(!n()&&!r())return t.apply(s,i);if(n()){let f=Yt(e),p=await co(f,e);if(p)return{status:"manual",manualAudience:"admin",messages:[pm(p),...await li(e,i)]}}if(r()){let f;try{f=await Sr(e.runReg??Hn)}catch{return{status:"manual",manualAudience:"admin",messages:[jB,...await li(e,i)]}}if(f)return{status:"manual",manualAudience:"admin",messages:[Om(f),...await li(e,i)]}}if(r()&&ee(s,"anthropic"))return{status:"manual",messages:["Claude Desktop subscription routing is not available on Windows: Connect could not verify a supported Claude subscription credential source, so inference was left unchanged instead of switching to API billing.","Use org/API mode for the Windows Gateway lane, or run subscription mode on a verified macOS build after signing in to Claude Code."]};if(n()){let f=await ba(e);if(!f.supported)return{status:"manual",messages:[f.message??"Claude Desktop version is unsupported."]}}let c;try{c=await WB(e)}catch(f){let p=f instanceof Fe?f.changedFiles:[];return{status:"manual",...p.length>0?{changedFiles:p}:{},messages:[f instanceof Fe?f.message:"Could not safely inspect Claude Desktop's retrieval MCP configuration; no inference setting was changed."]}}let l=await o(s,{dryRun:!0});if(l.status!=="configured")return l;if(i.dryRun){let f=c.legacy;return{...l,messages:[...l.messages,`Would register the ownership-marked Anyray retrieval MCP server in ${c.active.path}.`,...f&&f.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${f.path}.`]:[],...await li(e,i)]}}let d;try{d=await UB(c)}catch(f){let p=f instanceof Fe?f.changedFiles:[];return{status:"manual",...p.length>0?{changedFiles:p}:{},messages:[f instanceof Fe?f.message:"Could not safely register Claude Desktop retrieval; the inference route was left unchanged."]}}let u;try{u=await o(s,{dryRun:!1})}catch{u={status:"manual",messages:["Claude Desktop inference setup failed before it returned a result."]}}if(u.status!=="configured")try{return await d.rollback(),{...u,changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])],messages:[...u.messages,"Restored the prior Claude Desktop MCP registration because inference setup did not complete. A config file that was absent before setup may remain as an inert object to avoid racing unrelated concurrent writes."]}}catch{return{status:"manual",changedFiles:[...u.changedFiles??[],...d.changedFiles],messages:[...u.messages,"Inference setup did not complete, and the prior MCP registration could not be fully restored. Re-run `anyray-connect desktop disconnect` to recover safely."]}}return{...u,messages:[...u.messages,"Registered the Anyray retrieval MCP server (anyray_retrieve / anyray_recall) with an ownership marker.",...await li(e,i),...!i.dryRun&&i.reportsToUser&&i.explicit&&n()?LB:[]],changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])]}},async revert(s){let i=td(e),c=await ZB(s),l=h=>c.length===0?h:{...h,messages:[...h.messages,...c]};if(!n()&&!r())return l(await t.revert(s));let d;try{d=await Pv(e)}catch(h){return l({status:"manual",messages:[h instanceof Fe?h.message:"Could not safely inspect Claude Desktop's retrieval MCP configuration; no setting was removed."]})}let u=await a({dryRun:!0});if(s.dryRun){let h=d.legacy;return l({...u,messages:[...u.messages,...d.active.ownership!=="absent"?[`Would remove the owned Anyray retrieval MCP server from ${i}.`]:[],...h&&h.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${h.path}.`]:[]]})}let f=await a({dryRun:!1});if(f.status==="manual"){let h=r()?Mt(e):void 0;if(!(h!==void 0&&f.changedFiles?.includes(h)===!0&&!await x(h)))return l(f)}let p;try{p=await HB(await Pv(e))}catch(h){let g=h instanceof Fe?h.changedFiles:[];return l({status:"manual",changedFiles:[...new Set([...f.changedFiles??[],...g])],messages:[...f.messages,h instanceof Fe?h.message:"Restored Claude Desktop inference, but could not safely remove its retrieval MCP registration. Re-run revert."]})}await ce(i);let m=Gm(e);return n()&&m!==i&&await ce(m),l({...f,messages:[...f.messages,...p.length>0?["Removed the Anyray retrieval MCP server (anyray_retrieve / anyray_recall)."]:[]],changedFiles:[...new Set([...f.changedFiles??[],...p])]})},async mcpStatus(){if(!ne())return{registered:!1,command:null,reason:"ephemeral-runtime"};try{let s=await mo(td(e));return s.ownership!=="exact"||!fo(s.entry)?{registered:!1,command:null,reason:s.fileExisted?s.ownership==="absent"?"absent":s.ownership==="stale-owned"?"stale":"foreign":"no-config"}:{registered:!0,command:typeof s.entry.command=="string"?s.entry.command:null}}catch{return{registered:!1,command:null,reason:"unreadable"}}},async pointsAt(s){return n()?(await ba(e)).supported?mm(s,e):!1:r()?nv(s,e):!1},async inferenceAuthLanes(){try{if(n()){if(!(await ba(e)).supported)return["unknown"];let s=await vk(e);return s?[s]:["unknown"]}if(r())return await x(Mt(e))?await Sr(e.runReg??Hn)?["unknown"]:["api_key"]:["unknown"]}catch{}return["unknown"]},async automaticRepairAllowed(){try{if(n()){let s=Yt(e);return!await x(s.journal)||await co(s,e)?!1:(await ba(e)).supported}return r()&&await x(Mt(e))?!await Sr(e.runReg??Hn):!1}catch{return!1}}}},Hv=JB();import{homedir as vF}from"node:os";import{join as SF}from"node:path";import{rm as pd}from"node:fs/promises";import{constants as Gv,accessSync as XB,statSync as zB}from"node:fs";import{platform as Vm}from"node:os";import{delimiter as qB,posix as QB,resolve as eF,win32 as tF}from"node:path";var nF="0.59.0",rF="1.1.4",Gn="Anyray \xB7 Claude",Vn="Anyray \xB7 Codex",od="__anyray-acp-agent",Vv=(e,t,n)=>{let{command:r,args:o}=nn([od,e,t,n]);return{command:r,args:o,env:{}}},ad=(e=Vm())=>e==="win32"?"npx.cmd":"npx",sd=(e=process.env.PATH,t=Vm())=>{if(!e)return;let n=ad(t);for(let r of e.split(qB)){let o=r.trim().replace(/^"|"$/g,"");if(!o)continue;let a=eF(o,n);try{if(!zB(a).isFile())continue;return XB(a,t==="win32"?Gv.F_OK:Gv.X_OK),a}catch{}}},id=(e,t=Vm())=>{let n=t==="win32"?tF:QB;return!n.isAbsolute(e)||n.basename(e).toLowerCase()!==ad(t)?!1:t!=="win32"||!/["&|<>^%!\r\n]/.test(e)},oF="https://chatgpt.com/backend-api/codex",aF="chatgpt-account-id,originator,session_id,user-agent,x-codex-turn-metadata,x-codex-window-id,x-client-request-id",Kv="ANYRAY_ACP_CODEX_AUTHORIZATION",jv="ANYRAY_ACP_CODEX_CLIENT_KEY",Zv="ANYRAY_ACP_CODEX_METADATA",Yv=e=>fe({...e.metadata,tool:e.metadata.tool??"codex",intent:e.metadata.intent??"jetbrains-acp",intentLabel:e.metadata.intentLabel??"JetBrains / Devin via Codex ACP"}),sF=(e,t={})=>{let n=ee(e,"openai"),r=n?{"x-anyray-auth-mode":"passthrough","x-anyray-custom-host":oF,"x-anyray-forward-headers":aF}:{},o=n?{...e.clientKey?{"x-anyray-api-key":jv}:{}}:{Authorization:Kv};return Yv(e)&&(o["x-anyray-metadata"]=Zv),{model_provider:"anyray",model_providers:{anyray:{name:"Anyray Gateway",base_url:e.openaiBaseUrl,wire_api:"responses",...n?{requires_openai_auth:!0}:{},http_headers:r,env_http_headers:o}},...t.mcpServer?{mcp_servers:{anyray:{command:t.mcpServer.command,args:t.mcpServer.args}}}:{}}},iF=e=>{let t=ee(e,"openai"),n=Yv(e);return{...t?e.clientKey?{[jv]:e.clientKey}:{}:{[Kv]:`Bearer ${e.clientKey??e.placeholderKey}`},...n?{[Zv]:n}:{}}},Jv=(e,t=ad(),n={})=>({[Gn]:{command:t,args:["--yes",`@agentclientprotocol/claude-agent-acp@${nF}`],env:rn(e).env},[Vn]:{command:t,args:["--yes",`@agentclientprotocol/codex-acp@${rF}`],env:{CODEX_CONFIG:JSON.stringify(sF(e,n)),...iF(e)}}}),ui=(e=ad(),t="jetbrains")=>({[Gn]:Vv("claude",e,t),[Vn]:Vv("codex",e,t)}),ho=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),cd=(e,t)=>JSON.stringify(e)===JSON.stringify(t);import{inflateRawSync as cF}from"node:zlib";import{open as lF,readFile as Jm,readdir as ud}from"node:fs/promises";import{dirname as Xv,join as me}from"node:path";import{homedir as eS,platform as Xm}from"node:os";var ld="2025.3.2",Aa="253.30387.147",pi="com.intellij.ml.llm",Km=new Set(["ml-llm","llm","aia","ai-assistant","jetbrains-ai-assistant"]),dF=1e4,uF=256*1024*1024,pF=16*1024*1024,jm=1024*1024,Zm=22,fF=Zm+65535,Ym=xl,mF=()=>{let e=eS(),t=me(e,".cache","JetBrains","RemoteDev");switch(Xm()){case"darwin":return[{path:"/Applications",layout:"app-bundles"},{path:me(e,"Applications"),layout:"app-bundles"},{path:me(e,"Library","Application Support","JetBrains","Toolbox"),layout:"recursive"},{path:t,layout:"recursive"}];case"win32":return[{path:me(process.env.LOCALAPPDATA??me(e,"AppData","Local"),"Programs"),layout:"children"},{path:me(process.env.LOCALAPPDATA??me(e,"AppData","Local"),"JetBrains","Toolbox"),layout:"recursive"},{path:me(process.env.ProgramFiles??"C:\\Program Files","JetBrains"),layout:"children"}];default:return[{path:"/opt",layout:"children"},{path:me(e,".local","share","JetBrains","Toolbox"),layout:"recursive"},{path:t,layout:"recursive"}]}},hF=()=>Xm()==="linux"?me(eS(),".local","share","JetBrains"):Le("JetBrains"),yF=()=>Xm()==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),gF=async(e,t=dF)=>{let n=[];for(let r of e){if(r.layout!=="recursive"){let s;try{s=await ud(r.path,{withFileTypes:!0})}catch{continue}for(let i of s.slice(0,t)){if(!i.isDirectory()&&!i.isSymbolicLink())continue;let c=me(r.path,i.name),l=r.layout==="app-bundles"?me(c,"Contents","Resources","product-info.json"):me(c,"product-info.json");await x(l)&&n.push(l)}continue}let o=0,a=async(s,i)=>{if(i<0||o>=t)return;let c=me(s,"product-info.json"),l=me(s,"Contents","Resources","product-info.json");if(await x(c)){n.push(c);return}if(await x(l)){n.push(l);return}let d;try{d=await ud(s,{withFileTypes:!0})}catch{return}for(let u of d){if(o>=t)return;o+=1;let f=me(s,u.name);(u.isDirectory()||u.isSymbolicLink())&&!["bin","jbr","lib","plugins","Contents"].includes(u.name)&&await a(f,i-1)}};await a(r.path,7)}return[...new Set(n)]},wF=e=>{let t=Xv(e);return t.endsWith(`${me("Contents","Resources")}`)?Xv(t):t},bF=async e=>{try{let t=JSON.parse(await Jm(e,"utf8"));if(!t||typeof t!="object"||typeof t.version!="string"||typeof t.dataDirectoryName!="string")return;let n=t;return!js(n.version)||!/^[A-Za-z0-9._-]+$/.test(n.dataDirectoryName)?void 0:{version:n.version,dataDirectoryName:n.dataDirectoryName,root:wF(e)}}catch{return}},dd=async(e,t,n)=>{let r=Buffer.alloc(t),{bytesRead:o}=await e.read(r,0,t,n);return o===t?r:void 0},AF=async(e,t)=>{let n;try{n=await lF(e,"r");let{size:r}=await n.stat();if(r<Zm||r>uF)return;let o=Math.min(r,fF),a=await dd(n,o,r-o);if(!a)return;let s=-1;for(let u=a.length-Zm;u>=0;u-=1)if(a.readUInt32LE(u)===101010256){s=u;break}if(s<0)return;let i=a.readUInt32LE(s+12),c=a.readUInt32LE(s+16);if(i>pF||c+i>r)return;let l=await dd(n,i,c);if(!l)return;let d=0;for(;d+46<=l.length;){if(l.readUInt32LE(d)!==33639248)return;let u=l.readUInt16LE(d+10),f=l.readUInt32LE(d+20),p=l.readUInt32LE(d+24),m=l.readUInt16LE(d+28),h=l.readUInt16LE(d+30),g=l.readUInt16LE(d+32),y=l.readUInt32LE(d+42),w=d+46+m+h+g;if(w>l.length)return;let b=l.subarray(d+46,d+46+m).toString("utf8");if(d=w,b!==t)continue;if(f===4294967295||p===4294967295||f>jm||p>jm)return;let k=await dd(n,30,y);if(!k||k.readUInt32LE(0)!==67324752)return;let C=k.readUInt16LE(26),S=k.readUInt16LE(28),E=await dd(n,f,y+30+C+S);return E?u===0?E.toString("utf8"):u===8?cF(E,{maxOutputLength:jm}).toString("utf8"):void 0:void 0}return}catch{return}finally{await n?.close().catch(()=>{})}},zv=e=>{let t=e.match(/<id>\s*([^<]+?)\s*<\/id>/)?.[1]?.trim(),n=e.match(/<version>\s*([^<]+?)\s*<\/version>/)?.[1]?.trim();if(!(!t||!n||!js(n)))return{id:t,version:n}},CF=async(e,t)=>{let n=me(e,"META-INF","plugin.xml");if(await x(n))try{let o=zv(await Jm(n,"utf8"));return{present:o?.id===pi||t,descriptor:o?.id===pi?o:void 0}}catch{return{present:t}}let r=[];try{r=(await ud(me(e,"lib"),{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".jar")&&/(?:^|[-_.])(ml-?llm|llm|aia|ai[-_.]?assistant)(?:[-_.]|$)/i.test(o.name)).slice(0,32).map(o=>me(e,"lib",o.name))}catch{return{present:!1}}for(let o of r){let a=await AF(o,"META-INF/plugin.xml"),s=a?zv(a):void 0;if(s?.id===pi)return{present:!0,descriptor:s}}return{present:t&&r.length>0}},qv=async e=>{let t;try{t=await ud(e,{withFileTypes:!0})}catch{return{present:!1}}let n=t.filter(o=>o.isDirectory()||o.isSymbolicLink()).sort((o,a)=>{let s=Km.has(o.name.toLowerCase()),i=Km.has(a.name.toLowerCase());return Number(i)-Number(s)}).slice(0,512),r=!1;for(let o of n){let a=Km.has(o.name.toLowerCase());if(!a){let i=me(e,o.name,"META-INF","plugin.xml");if(!await x(i))continue}let s=await CF(me(e,o.name),a);if(s.descriptor)return s;s.present&&(r=!0)}return{present:r}},kF=async e=>{try{return(await Jm(me(e,"disabled_plugins.txt"),"utf8")).split(/\r?\n/).map(n=>n.trim()).includes(pi)}catch{return!1}},Qv=e=>e.reduce((t,n)=>t?(Ym(n,t)??-1)>0?n:t:n,void 0),tS=async(e={})=>{let t=e.configRoot??Le("JetBrains"),n=e.userPluginsRoot??hF(),r=await gF(e.productRoots?e.productRoots.map(m=>({path:m,layout:"recursive"})):mF(),e.scanBudget),o=(await Promise.all(r.map(m=>bF(m)))).filter(m=>m!==void 0),a=o.length>0||await x(t);if(e.wsl??yF())return{installed:a,capable:!1,detail:"JetBrains AI Assistant does not support ACP in WSL; no ACP config was written."};let s=o.filter(m=>(Ym(m.version,ld)??-1)>=0),i=[],c=!1,l=!1,d=!1;for(let m of s){let h=me(t,m.dataDirectoryName);if(!await x(h)){d=!0;continue}let g=[me(h,"plugins"),me(n,m.dataDirectoryName),me(n,m.dataDirectoryName,"plugins")],y;for(let w of[...new Set(g)]){let b=await qv(w);if(b.present){y=b;break}}if(y??=await qv(me(m.root,"plugins")),y.present&&!y.descriptor){l=!0;continue}if(!(!y.descriptor||y.descriptor.id!==pi)){if(i.push(y.descriptor.version),await kF(h)){c=!0;continue}if(!((Ym(y.descriptor.version,Aa)??-1)<0))return{installed:!0,capable:!0,detail:`JetBrains IDE ${m.version}; AI Assistant ${y.descriptor.version}; ACP supported`,ideVersion:m.version,pluginVersion:y.descriptor.version}}}let u=Qv(o.map(m=>m.version)),f=Qv(i),p;return a?u?s.length===0?p=`JetBrains IDE ${u} is below the ACP minimum ${ld}; no ACP config was written.`:d?p=`Could not prove that JetBrains AI Assistant is enabled for this user; start IDE ${ld}+ once, enable AI Assistant ${Aa}+, then run Connect again. No ACP config was written.`:c?p=`JetBrains AI Assistant is disabled; enable version ${Aa}+ and run Connect again. No ACP config was written.`:f?p=`JetBrains AI Assistant ${f} is below the ACP minimum ${Aa}; no ACP config was written.`:l?p=`Could not verify the local JetBrains AI Assistant version; require ${Aa}+ before running Connect. No ACP config was written.`:p=`JetBrains AI Assistant ${Aa}+ was not found; install or enable it, then run Connect again. No ACP config was written.`:p=`Could not prove JetBrains IDE ${ld}+ from local product-info.json; no ACP config was written.`:p="JetBrains IDE config or installation not found",{installed:a,capable:!1,detail:p,ideVersion:u,pluginVersion:f}};var EF=[Gn,Vn],zm=()=>SF(vF(),".jetbrains","acp.json"),yo=()=>`${zm()}.anyray-state`,IF=(e,t,n="npx")=>{let r=ho(e.agent_servers)?{...e.agent_servers}:{};return Object.assign(r,ui(n,"jetbrains")),{...e,agent_servers:r}},xF=(e,t,n)=>{if(!ho(e.agent_servers))return{next:e,removed:[],conflicts:[]};let r={...e.agent_servers},o=ho(t.agent_servers)?t.agent_servers:{},a=[],s=[];for(let c of EF)if(c in r){if(!cd(r[c],n[c])){s.push(c);continue}c in o?r[c]=o[c]:delete r[c],a.push(c)}let i={...e};return Object.keys(r).length>0?i.agent_servers=r:delete i.agent_servers,{next:i,removed:a,conflicts:s}},RF=(e=tS)=>({id:"jetbrains",title:"JetBrains AI Assistant",automatic:!0,async detect(){let t=await e();return{installed:t.installed,detail:t.detail}},async apply(t,n){let r=zm(),o=await e();if(!o.capable)return{status:o.installed?"manual":"not-found",messages:[o.detail]};let a=sd();if(!a)return{status:"manual",messages:["JetBrains ACP requires Node.js with npm/npx. Install that prerequisite, then run Connect again; no ACP config was written."]};let s=[`${r} \u2190 documented JetBrains ACP custom-agent configuration`,`${o.detail}.`,"Registered Claude and Codex ACP agents with Anyray routing; no IDE proxy, certificate, DNS, or private Copilot endpoint is changed.","Claude keeps Anthropic subscription auth when selected; Codex keeps ChatGPT subscription auth when selected. Org/API mode uses the enrolled personal gateway key.","The agents appear in AI Chat after the IDE reloads. Their first launch may ask for the provider sign-in if that seat is not already authenticated.","JetBrains Copilot remains a separate closed client; its content-free usage is covered by the Copilot usage connector, not endpoint interception."];if(n.dryRun)return{status:"configured",messages:s};let i=await x(r),c;try{c=await M(r)}catch{return{status:"manual",messages:[`Refused to overwrite malformed ${r}; fix or replace the file, then run Connect again.`]}}let l=ui(a,"jetbrains");return await qi({configPath:r,current:c,next:IF(c,t,a),journalPath:yo(),journal:{version:2,fileExisted:i,entries:l},fileExisted:i}),{status:"configured",messages:s,changedFiles:[r,yo()]}},async revert(t){let n=zm(),r=async()=>{if(!await x(n))return t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:"reverted",messages:["No JetBrains ACP config to remove."]};let o;try{o=await M(n)}catch{return t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:"manual",messages:[`Could not parse ${n}; remove the two \u201CAnyray \xB7 \u2026\u201D agent entries manually.`]}}let a={},s=!1,i=!1;try{let u=await M(yo());(u.version===1||u.version===2)&&ho(u.entries)&&(a=u.entries,s=u.version===2&&u.fileExisted===!1,i=u.version===2&&u.fileExisted===!0)}catch{}let c;if(i){let u=`${n}.anyray-bak`;if(!await x(u))return{status:"manual",messages:[`Refused to remove JetBrains ACP entries because the original backup for ${n} is missing. Restore or remove the entries manually.`]};try{c=await M(u)}catch{return{status:"manual",messages:[`Refused to remove JetBrains ACP entries because the original backup for ${n} is malformed. Repair it or remove the entries manually.`]}}}else c=await $r(n);let l=xF(o,c,a),d=[];return l.removed.length&&d.push(`Removed ${l.removed.join(", ")} from ${n}.`),l.conflicts.length&&d.push(`Preserved user-modified ACP entries: ${l.conflicts.join(", ")}.`),!t.dryRun&&l.removed.length&&(s&&Object.keys(l.next).length===0?await pd(n,{force:!0}):await J(n,l.next,{backup:!1})),t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:l.conflicts.length?"manual":"reverted",messages:d.length?d:["No Anyray ACP entries found."],changedFiles:!t.dryRun&&l.removed.length?[n]:void 0}};return t.dryRun?r():zi(n,yo(),r)}}),nS=RF();import{homedir as md}from"node:os";import{join as hd}from"node:path";import{rm as qm}from"node:fs/promises";var Qm="1.0.0",yd=["anyray-claude-acp","anyray-codex-acp"],OF=["darwin-aarch64","darwin-x86_64","linux-aarch64","linux-x86_64","windows-aarch64","windows-x86_64"],eh=()=>hd(md(),".windsurf","acp","registry.json"),th=()=>hd(md(),".windsurf-next","acp","registry.json"),Ca=e=>`${e}.anyray-state`,rS=e=>({binary:Object.fromEntries(OF.map(t=>[t,{archive:"",cmd:e.command,args:e.args}]))}),aS=(e="npx")=>{let t=ui(e,"windsurf");return[{id:yd[0],name:Gn,version:"1.0.0",description:"Claude through the Anyray gateway via ACP",authors:["Anyray","Agent Client Protocol"],license:"Apache-2.0",distribution:rS(t[Gn])},{id:yd[1],name:Vn,version:"1.0.0",description:"Codex through the Anyray gateway via ACP",authors:["Anyray","Agent Client Protocol"],license:"Apache-2.0",distribution:rS(t[Vn])}]},fd=e=>!Array.isArray(e)||e.some(t=>!ho(t)||typeof t.id!="string")?null:e,TF=(e,t="npx")=>{if(e.version!==void 0&&e.version!==Qm||e.extensions!==void 0&&!Array.isArray(e.extensions))return null;let n=e.agents===void 0?[]:fd(e.agents);if(!n)return null;let r=new Set(yd);return{...e,version:typeof e.version=="string"?e.version:Qm,agents:[...n.filter(o=>!r.has(o.id)),...aS(t)],extensions:e.extensions??[]}},_F=(e,t,n)=>{let r=fd(e.agents);if(!r)return null;let o=fd(t.agents)??[],a=new Map((fd(n)??[]).map(u=>[u.id,u])),s=new Map(o.map(u=>[u.id,u])),i=[],c=[],l=[];for(let u of r){if(!yd.includes(u.id)){l.push(u);continue}if(!cd(u,a.get(u.id))){c.push(u.id),l.push(u);continue}let f=s.get(u.id);f&&l.push(f),i.push(u.id)}let d={...e,agents:l};return!Object.prototype.hasOwnProperty.call(t,"agents")&&l.length===0&&delete d.agents,!Object.prototype.hasOwnProperty.call(t,"version")&&d.version===Qm&&delete d.version,!Object.prototype.hasOwnProperty.call(t,"extensions")&&Array.isArray(d.extensions)&&d.extensions.length===0&&delete d.extensions,{next:d,removed:i,conflicts:c}},oS=async()=>{let e=[];return(await x(th())||await x(hd(md(),".windsurf-next")))&&e.push(th()),(await x(eh())||await x(hd(md(),".windsurf"))||await x(Le("Devin"))||await x(Le("Windsurf")))&&e.push(eh()),e},sS={id:"windsurf",title:"Devin Desktop",automatic:!0,async detect(){let e=await oS();return e.length?{installed:!0,detail:e.join(", ")}:{installed:!1,detail:"Devin Desktop not found"}},async apply(e,t){let n=await oS();if(!n.length)return{status:"not-found",messages:["Devin Desktop is not installed; no ACP registry was written."]};let r=sd();if(!r)return{status:"manual",messages:["Devin ACP requires Node.js with npm/npx. Install that prerequisite, then run Connect again; no ACP registry was written."]};let o=[],a=[];for(let s of n){let i;try{i=await M(s)}catch{o.push(`Refused to overwrite malformed ${s}; fix or replace the file, then run Connect again.`);continue}let c=TF(i,r);if(!c){o.push(`Refused unrecognized ACP registry shape in ${s}.`);continue}if(o.push(`${s} \u2190 registered Anyray Claude and Codex ACP agents.`),!t.dryRun){let l=await x(s),d=aS(r);await qi({configPath:s,current:i,next:c,journalPath:Ca(s),journal:{version:2,fileExisted:l,agents:d},fileExisted:l}),a.push(s,Ca(s))}}return o.push("Devin requires a one-time vendor UI enablement for local registry agents: Devin Settings \u2192 Agents \u2192 enable the two Anyray agents, then restart Devin Desktop."),o.push("Native Devin/Cascade subscription requests are not redirected. The official enterprise consumption connector imports content-free usage instead."),o.push("No proxy, certificate, DNS, DEVIN_API_URL, or private first-party endpoint was changed."),{status:"manual",messages:o,changedFiles:a.length?a:void 0}},async revert(e){let t=[eh(),th()],n=[],r=[],o=!1;for(let a of t){let s=async()=>{if(!await x(a)){e.dryRun||(await ce(a),await qm(Ca(a),{force:!0}).catch(()=>{}));return}let i;try{i=await M(a)}catch{n.push(`Could not parse ${a}; remove the anyray-* ACP agents manually.`),o=!0;return}let c=[],l=!1,d=!1;try{let p=await M(Ca(a));(p.version===1||p.version===2)&&Array.isArray(p.agents)&&(c=p.agents,l=p.version===2&&p.fileExisted===!1,d=p.version===2&&p.fileExisted===!0)}catch{}let u;if(d){let p=`${a}.anyray-bak`;if(!await x(p)){n.push(`Refused to remove Devin ACP agents because the original backup for ${a} is missing. Restore it or remove the agents manually.`),o=!0;return}try{u=await M(p)}catch{n.push(`Refused to remove Devin ACP agents because the original backup for ${a} is malformed. Repair it or remove the agents manually.`),o=!0;return}}else u=await $r(a);let f=_F(i,u,c);if(!f){n.push(`Unrecognized ACP registry shape in ${a}; left it unchanged.`),o=!0;return}f.removed.length&&(n.push(`Removed ${f.removed.join(", ")} from ${a}.`),e.dryRun||(l&&Object.keys(f.next).length===0?await qm(a,{force:!0}):await J(a,f.next,{backup:!1}),r.push(a))),f.conflicts.length?(n.push(`Preserved user-modified agents: ${f.conflicts.join(", ")}.`),o=!0):e.dryRun||(await ce(a),await qm(Ca(a),{force:!0}).catch(()=>{}))};e.dryRun?await s():await zi(a,Ca(a),s)}return{status:o?"manual":"reverted",messages:n.length?n:["No Anyray Devin ACP agents found."],changedFiles:r.length?r:void 0}}};var pe=[rr,qw,Os,eC,xC,FC,jC,nS,Hv,sS,sb],ut=e=>pe.find(t=>t.id===e);var We=async(e=P,t=yn)=>{let n=await e();if(!n.gateway||!n.clientKey)return;let r=await t().catch(()=>{});return{target:Oe({origin:n.gateway,clientKey:n.clientKey,subscription:n.authMode==="subscription",placeholder:n.authMode==="placeholder",byoUpstream:n.byoUpstream,seat:r,user:n.name,team:n.team})}};var nh=5e3,iS=3e4,PF=1440*60*1e3,DF=e=>new Promise(t=>setTimeout(t,e)),LF=async(e=P,t=yn)=>(await We(e,t))?.target,NF=e=>ut(e)?.quitGated,cS=async(e,t={})=>{let n=e[0];if(!n)return 0;let r=t.resolveSeam??NF,o=t.readPending??Kc,a=t.clearPending??Up,s=t.targetFromProfile??LF,i=t.sleep??DF,c=t.now??Date.now,l=t.maxWaitMs??PF;try{let d=r(n);if(!d?.complete)return await a(n),0;let u=d.complete.bind(d),f=c(),p=nh;for(;;){let m=await o(n);if(!m||c()-f>l)return 0;if(d.isRunning()){await i(p),p=Math.min(iS,p*2);continue}let h;if(d.needsTarget?.(m.op)&&(h=await s(),!h)){if(await a(n,m)!=="superseded")return 0;await i(p),p=nh;continue}if((await u(m.op,h,{dryRun:!1,preservePendingOp:!0})).status==="queued"){await i(p),p=Math.min(iS,p*2);continue}if(await a(n,m)!=="superseded")return 0;await i(p),p=nh}}catch{return 0}};import{writeFileSync as vW}from"node:fs";import{chmod as mh,stat as SW}from"node:fs/promises";import{platform as FS}from"node:os";import{dirname as WS,isAbsolute as EW}from"node:path";var $F="https://app.anyray.ai",MF=new Set(["localhost","::1","[::1]"]),BF=/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,FF=e=>MF.has(e)||BF.test(e),rh=e=>{let t;try{t=new URL(e)}catch{return!1}return t.protocol==="https:"?!0:t.protocol==="http:"&&FF(t.hostname)},WF=e=>{let t=e.length;for(;t>0&&e[t-1]==="/";)t-=1;return e.slice(0,t)},Kn=()=>{let e=process.env.ANYRAY_CP_ORIGIN?.trim();return!e||!rh(e)?$F:WF(e)};import{createHash as QF,generateKeyPairSync as eW,randomBytes as sh}from"node:crypto";import{createPrivateKey as UF,sign as HF}from"node:crypto";var Ir=async(e,t)=>{let n=UF(t);return HF(null,new TextEncoder().encode(e),n).toString("base64url")};var GF=["HTTPS_PROXY","https_proxy"],lS=new Set(["SELF_SIGNED_CERT_IN_CHAIN","DEPTH_ZERO_SELF_SIGNED_CERT","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED"]),dS=new Set(["CERT_HAS_EXPIRED","CERT_NOT_YET_VALID","ERR_TLS_CERT_ALTNAME_INVALID","ERR_SSL_WRONG_VERSION_NUMBER","EPROTO"]),uS=new Set(["ENOTFOUND","EAI_AGAIN"]),pS=new Set(["ECONNREFUSED","ECONNRESET","EPIPE","ENETDOWN","ENETUNREACH","EHOSTUNREACH","EHOSTDOWN"]),fS=new Set(["ETIMEDOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT"]),VF=e=>{let t=e;for(let n=0;n<5&&t;n++){let r=t.code;if(typeof r=="string"&&r)return r;t=t.cause}return KF(e)},KF=e=>{let t=e?.message;if(!(typeof t!="string"||!t)){for(let n of[...lS,...dS,...uS,...pS,...fS])if(t.includes(n))return n}},jF=e=>e?.name==="AbortError"||e?.name==="TimeoutError",ZF=e=>GF.filter(t=>(e[t]??"").trim()!==""),YF=(e,t=process.env)=>{let n=VF(e),r=ZF(t);return{kind:n&&lS.has(n)?"tls-unknown-issuer":n&&dS.has(n)?"tls-invalid-cert":n&&uS.has(n)?"dns":jF(e)||n&&fS.has(n)?"timeout":n&&pS.has(n)?"refused":"unknown",...n?{code:n}:{},proxyVars:r}},JF=e=>{let t=e.proxyVars.length>0?` ${e.proxyVars.join(" and ")} ${e.proxyVars.length>1?"are":"is"} set \u2014 if that proxy is stale or unreachable, unset it and re-run.`:"";switch(e.kind){case"tls-unknown-issuer":return` (TLS certificate signed by an unknown authority: ${e.code}). Your network appears to inspect TLS traffic. curl trusts your system keychain and this binary does not, which is why the download worked and this step did not. Point NODE_EXTRA_CA_CERTS at your organization root certificate (PEM) and re-run.`+t;case"tls-invalid-cert":return` (TLS certificate rejected: ${e.code}). Check this machine's clock and date, and whether a proxy is rewriting HTTPS traffic, then re-run.`+t;case"dns":return` (DNS lookup failed: ${e.code}). Check your VPN or DNS, then re-run.`+t;case"refused":return` (connection failed: ${e.code}).`+(t||" Check your network or firewall, then re-run.");case"timeout":return" (timed out before the control plane answered)."+(t||" Check your connection and re-run.");default:return e.code?` (${e.code}).${t}`:t}},pt=(e,t=process.env)=>JF(YF(e,t));var XF="enl_",mS="enp_",hS=e=>e.startsWith(XF)||e.startsWith(mS),oh=e=>e.startsWith(mS),zF=[{prefix:"tnt_",flag:"--sso",what:"an SSO link"},{prefix:"sdc_",flag:"--claim",what:"a one-time enrollment code"}],ah=e=>zF.find(t=>e.startsWith(t.prefix)),yS=/^\/enroll\/([^/]+)\/?$/,gS=/^\/i\/([^/]+)\/?$/,wS=e=>{let t=e.match(yS);if(t)return ah(t[1])?void 0:t[1];let n=e.match(gS);return n&&hS(n[1])?n[1]:void 0},qF=1e4,gd=e=>{let t=e.trim();if(!t)return;let n;try{n=new URL(t)}catch{n=void 0}if(n){if(n.protocol!=="http:"&&n.protocol!=="https:")return;let r=wS(n.pathname);return r?{cpOrigin:n.origin,token:r}:void 0}if(!ah(t))return{cpOrigin:Kn(),token:t}},bS=e=>{let t=e.trim();if(!t)return;let n=t;try{let o=new URL(t),a=o.pathname.match(yS)??o.pathname.match(gS);if(!a)return;n=a[1]}catch{}let r=ah(n);return r?{flag:r.flag,what:r.what}:void 0},mi=e=>{let t=e.trim();if(!t)return!1;try{let n=new URL(t);return n.protocol!=="http:"&&n.protocol!=="https:"?!1:wS(n.pathname)!==void 0}catch{return hS(t)}},ka=class extends Error{constructor(t){super(t),this.name="EnrollmentPermanentError"}},fi=e=>typeof e=="string"&&e.trim()?e.trim():void 0,AS=async(e,t={})=>{let n=t.timeoutMs??qF,r=`${e.cpOrigin}/enroll-info/${e.token}`,o=new AbortController,a=setTimeout(()=>o.abort(),n),s;try{s=await fetch(r,{method:"GET",signal:o.signal})}catch(u){let f=u instanceof Error&&u.name==="AbortError"?` no response within ${n}ms.`:pt(u);throw new Error(`could not reach the enrollment page at ${e.cpOrigin}.${f}`)}finally{clearTimeout(a)}if(!s.ok){let u=`enrollment link lookup failed: ${e.cpOrigin} responded ${s.status} \u2014 the link may be expired or revoked; ask your admin for a fresh one.`;throw s.status>=400&&s.status<500&&s.status!==429?new ka(u):new Error(u)}let i;try{i=await s.json()}catch{throw new Error(`enrollment link lookup failed: ${e.cpOrigin} returned a malformed response`)}let l=(Array.isArray(i?.gateways)?i.gateways:[]).find(u=>u!==null&&typeof u=="object"&&fi(u.url)!==void 0),d=fi(l?.url);if(!d)throw new Error(i.connected===!0?"this enrollment link's gateway is running but hasn't advertised its public URL yet \u2014 ask your admin to set ANYRAY_GATEWAY_PUBLIC_URL (Helm: gateway.publicUrl), then re-run.":"this enrollment link has no gateway configured yet \u2014 ask your admin to confirm the gateway is deployed, then re-run.");return{gatewayUrl:d,deploymentId:fi(l?.deploymentId),org:fi(i.org),email:fi(i.email),seatMode:i.seatMode===!0,...i.provisioningKind==="manual"||i.provisioningKind==="mdm"?{provisioningKind:i.provisioningKind}:{},...i.provisioningProofMode==="managed-preference"?{provisioningProofMode:i.provisioningProofMode}:{},...Array.isArray(i.allowedDomains)?{allowedDomains:i.allowedDomains.filter(u=>typeof u=="string"&&u.length>0)}:{}}};var ke="0.11.180";var ih=1e4,go=e=>e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(go).join(",")}]`:`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${go(e[n])}`).join(",")}}`,CS="stable-key-heartbeat-v1",kS="key-heartbeat",tW=["reapply_config","remint","revert"],ch=(e,t)=>t&&e.payload.source==="mdm"?{machineUuid:t}:{};var vS=e=>QF("sha256").update(e).digest("hex"),je=e=>typeof e=="string"&&e.trim()?e.trim():void 0,nW=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"&&/^[a-z0-9-]{1,64}$/.test(t)):[],SS={no_mdm_server_registered:"no MDM server is registered in the Anyray console",agent_missing:"the Anyray endpoint agent is not reporting for this machine",mdm_not_verified:"this machine is not enrolled in the registered MDM",endpoint_unreachable:"the endpoint service could not be reached"},rW=e=>`This organization requires a managed (MDM-enrolled) device for this enrollment: ${SS[e]}. Ask your IT admin.`,oW=e=>typeof e=="string"&&e in SS,lh=async e=>{try{let t=await e.json(),n=je(t?.message),r=je(t?.error),o=oW(t?.reason)?t.reason:void 0;if(r==="managed_device_required"&&o)return{message:rW(o),code:r,reason:o};if(n)return{message:n,...r?{code:r}:{}}}catch{}return{message:`gateway responded ${e.status}`}},aW=async e=>(await lh(e)).message,ct=class extends Error{status;policyCode;reason;constructor(t,n){let r=typeof n=="string"?{message:n}:n;super(r.code==="managed_device_required"?r.message:`the gateway rejected this enrollment (HTTP ${t}): ${r.message}`),this.name="GatewayVerifyError",this.status=t,this.policyCode=r.code,this.reason=r.reason}},ES=e=>e instanceof ka||e instanceof ct&&e.policyCode==="sso_required",va=class extends Error{status;policyCode;reason;constructor(t,n){let r=typeof n=="string"?{message:n}:n;super(r.code==="managed_device_required"?r.message:`the gateway rejected this credential heartbeat (HTTP ${t}): ${r.message}`),this.name="GatewayHeartbeatError",this.status=t,this.policyCode=r.code,this.reason=r.reason}},dh=async(e,t,n,r)=>{try{return await r(go(e),t)}catch{throw new Error(`developer ${n} failed: could not sign the challenge with the provided private key`)}},wd=()=>{let{publicKey:e,privateKey:t}=eW("ed25519",{publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem"}});return{publicKeyPem:e,privateKeyPem:t}},qt=async(e,t,n,r={})=>{let o=r.timeoutMs??ih,a=`${e}/connect/verify`,s=je(t?.payload?.deploymentId);if(!s)throw new Error("developer verification failed: the cert is missing payload.deploymentId");let i={deploymentId:s,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),...ch(t,r.machineUuid)},c=await dh(i,n,"verification",r.signer??Ir),l=new AbortController,d=setTimeout(()=>l.abort(),o),u;try{u=await fetch(a,{method:"POST",headers:{"content-type":"application/json","x-anyray-connect-version":ke},body:JSON.stringify({cert:t,challenge:i,sig:c,...r.health?{health:r.health}:{},...r.ack?{ack:r.ack}:{},...r.telemetryOnly?{telemetryOnly:!0}:{}}),signal:l.signal})}catch(w){let b=w instanceof Error&&w.name==="AbortError"?` no response within ${o}ms.`:pt(w);throw new Error(`could not reach the gateway at ${a}.${b}`,{cause:w})}finally{clearTimeout(d)}if(!u.ok)throw new ct(u.status,await lh(u));let f;try{f=await u.text()}catch{f=""}let p;try{p=JSON.parse(f)}catch{let w=u.headers.get("content-type")??"",b=/\btext\/html\b/i.test(w)||/^\s*<(?:!doctype|html)/i.test(f);throw new Error(b?`developer verification failed: ${a} returned an HTML page, not the gateway \u2014 /connect/* is being routed to the console/proxy. Ask your admin to route /connect/* to the gateway service (:8787), the same as /v1/*.`:"developer verification failed: the gateway returned a malformed response")}let m=je(p?.key);if(!m)throw new Error("developer verification failed: the gateway response is missing the key");if(!/^[A-Za-z0-9._-]{1,256}$/.test(m))throw new Error("developer verification failed: the gateway returned a malformed key");let h=je(p.user);if(!h)throw new Error("developer verification failed: the gateway response is missing the user");let g=sW(p.directive),y=nW(p.capabilities);return{key:m,user:h,team:je(p.team),expiresAt:je(p.expiresAt),...y.length>0?{capabilities:y}:{},...g?{directive:g}:{}}},IS=async(e,t,n,r,o={})=>{let a=o.timeoutMs??ih,s=`${e}/connect/key/heartbeat`,i=je(n?.payload?.deploymentId);if(!i)throw new Error("developer heartbeat failed: the cert is missing payload.deploymentId");let c={deploymentId:i,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),purpose:kS,...ch(n,o.machineUuid)},l=await dh(c,r,"heartbeat",o.signer??Ir),d=new AbortController,u=setTimeout(()=>d.abort(),a),f;try{f=await fetch(s,{method:"POST",headers:{"content-type":"application/json","x-anyray-api-key":t,"x-anyray-connect-version":ke},body:JSON.stringify({cert:n,challenge:c,sig:l}),signal:d.signal})}catch(h){let g=h instanceof Error&&h.name==="AbortError"?` no response within ${a}ms.`:pt(h);throw new Error(`could not reach the gateway at ${s}.${g}`,{cause:h})}finally{clearTimeout(u)}if(!f.ok)throw new va(f.status,await lh(f));let p;try{p=await f.json()}catch{throw new Error("developer heartbeat failed: the gateway returned a malformed response")}let m=je(p.expiresAt);if(!m||!Number.isFinite(Date.parse(m))||p.credentialMode!==CS||p.key!==void 0)throw new Error("developer heartbeat failed: the gateway returned an unexpected response");return{expiresAt:m,credentialMode:CS}},xS=async(e,t,n,r,o,a={})=>{let s=a.timeoutMs??ih,i=`${e.replace(/\/$/,"")}/connect/machine`,c=je(n?.payload?.deploymentId);if(!c||!o)return!1;let l={deploymentId:c,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),purpose:kS,...ch(n,o)},d=await dh(l,r,"heartbeat",a.signer??Ir),u=new AbortController,f=setTimeout(()=>u.abort(),s);try{return(await fetch(i,{method:"POST",headers:{"content-type":"application/json","x-anyray-api-key":t,"x-anyray-connect-version":ke},body:JSON.stringify({cert:n,challenge:l,sig:d,machineUuid:o}),signal:u.signal})).ok}catch(p){return console.error("connect machine report skipped:",p instanceof Error?p.name:"error"),!1}finally{clearTimeout(f)}},sW=e=>{if(e===null||typeof e!="object")return null;let t=e,n=je(t.id),r=t.kind;return!n||!/^[A-Za-z0-9_-]{1,128}$/.test(n)||typeof r!="string"||!tW.includes(r)?null:{id:n,kind:r}},iW=1e4,cW=e=>{if(e===null||typeof e!="object")return!1;let t=e;if(t.alg!=="Ed25519"||!je(t.sig))return!1;let n=t.payload;if(n===null||typeof n!="object")return!1;let r=n;return typeof r.v=="number"&&!!je(r.deploymentId)&&!!je(r.user)&&!!je(r.devPublicKey)&&!!je(r.issuedAt)&&!!je(r.expiresAt)},lW=async(e,t,n,r={},o={})=>{let a=o.timeoutMs??iW,s=`${e}/v1/enroll`,i=new AbortController,c=setTimeout(()=>i.abort(),a),l;try{l=await fetch(s,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({token:t,devPublicKey:n,...r.email?{email:r.email}:{},...r.team?{team:r.team}:{},...r.machineId?{machineId:r.machineId}:{},...r.deploymentId?{deploymentId:r.deploymentId}:{}}),signal:i.signal})}catch(u){let f=u instanceof Error&&u.name==="AbortError"?` no response within ${a}ms.`:pt(u);throw new Error(`could not reach the control plane at ${s}.${f}`)}finally{clearTimeout(c)}if(!l.ok){let u=`enrollment failed: ${await aW(l)}`;throw l.status>=400&&l.status<500&&l.status!==429?new ka(u):new Error(u)}let d;try{d=await l.json()}catch{throw new Error("enrollment failed: the control plane returned a malformed response")}if(!cW(d))throw new Error("enrollment failed: the control plane returned an unexpected cert shape");return d},RS=(e,t,n,r,o,a,s)=>{if(!e)return!1;let i=t?Date.parse(t):NaN;return!(!Number.isFinite(i)||i<=r||n&&e.payload.deploymentId!==n||o&&o!==a||s&&e.payload.user.trim().toLowerCase()!==s.trim().toLowerCase())},OS=async e=>{let t={timeoutMs:e.timeoutMs,machineUuid:e.machineUuid,signer:e.signer},{cert:n,privateKeyPem:r,publicKeyPem:o}=e.reuse?e.reuse:await(async()=>{let s=wd();return{cert:await lW(e.cpOrigin,e.token,s.publicKeyPem,{email:e.email,team:e.team,machineId:e.machineId,deploymentId:e.deploymentId},t),...s}})(),a=await qt(e.gatewayOrigin,n,r,t);return{clientKey:a.key,user:a.user,team:a.team,expiresAt:a.expiresAt,...a.capabilities?{capabilities:a.capabilities}:{},cert:n,privateKeyPem:r,publicKeyPem:o}};var uh=1e4,dW=900*1e3,_S="tnt_",uW=/^\/sso\/([^/]+)\/?$/,pW=/^\/i\/([^/]+)\/?$/,fW=e=>{let t=e.match(uW);if(t)return t[1];let n=e.match(pW);return n?.[1].startsWith(_S)?n[1]:void 0},Et=e=>{let t=e.trim();if(!t)return;let n;try{n=new URL(t)}catch{n=void 0}if(n){if(n.protocol!=="http:"&&n.protocol!=="https:")return;let r=fW(n.pathname);return r?{cpOrigin:n.origin,tenantId:r}:void 0}if(t.startsWith(_S))return{cpOrigin:Kn(),tenantId:t}},wo=class extends Error{kind;status;constructor(t,n,r){super(n),this.name="SsoStartError",this.kind=t,this.status=r}},Bt=class extends Error{kind;constructor(t,n){super(n),this.name="SsoPollError",this.kind=t}},ph=async(e,t,n,r)=>{let o=new AbortController,a=setTimeout(()=>o.abort(),n);try{let s=await r(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:o.signal}),i={};try{i=await s.json()}catch{}return{status:s.status,json:i}}finally{clearTimeout(a)}},mW=e=>new Promise(t=>setTimeout(t,e)),bd=async e=>{let t=e.now??Date.now,n=e.fetch??fetch,{publicKeyPem:r,privateKeyPem:o}=(e.generateKeypair??wd)(),a;try{a=await ph(`${e.cpOrigin}/sso/device`,{tenantId:e.tenantId,devPublicKey:r},uh,n)}catch(m){throw new wo("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(m)}`)}if(a.status!==200){let m=a.status===404,h=typeof a.json.error=="string"?a.json.error:`status ${a.status}`;throw new wo(m?"sso-unavailable":"cp-unreachable",`SSO is not available for this organization (${h}). Ask your admin to confirm SSO is configured.`,a.status)}let s=a.json;if(!s.device_code||!s.user_code||!s.verification_uri_complete)throw new wo("cp-unreachable","SSO start failed: the control plane returned an incomplete response.");let i=t(),c=e.deadlineMs??dW,l=typeof s.expires_in=="number"&&s.expires_in>0?s.expires_in*1e3:c,d=typeof s.verification_uri=="string"?s.verification_uri:void 0,u=e.gatewayUrl??(typeof s.gateway_url=="string"?s.gateway_url:void 0),f={cpOrigin:e.cpOrigin,tenantId:e.tenantId,deviceCode:s.device_code,userCode:s.user_code,verificationUri:d,verificationUriComplete:s.verification_uri_complete,intervalMs:Math.max(1,s.interval||5)*1e3,grantExpiresAt:i+Math.min(c,l),startedAt:i,privateKeyPem:o,publicKeyPem:r,gatewayUrl:u},p=e.log??(()=>{});return p("To finish, sign in with your organization at:"),p(` ${f.verificationUriComplete}`),p(`Confirm this code matches your browser: ${f.userCode}`),hW(f.verificationUriComplete,e.cpOrigin)&&e.open?.(f.verificationUriComplete),f},hW=(e,t)=>{try{return new URL(e).origin===new URL(t).origin}catch{return!1}},Ad=async(e,t={})=>{let n=t.now??Date.now,r=t.sleep??mW,o=t.fetch??fetch,a=t.pollIntervalMs??e.intervalMs;for(;n()<e.grantExpiresAt&&(await r(Math.min(a,e.grantExpiresAt-n())),!(n()>=e.grantExpiresAt));){let s;try{s=await ph(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.deviceCode,devPublicKey:e.publicKeyPem},uh,o)}catch(c){throw new Bt("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(c)}`)}if(s.status===200&&s.json.cert)return{cert:s.json.cert,privateKeyPem:e.privateKeyPem,gatewayUrl:t.gatewayUrl??(typeof s.json.gatewayUrl=="string"?s.json.gatewayUrl:e.gatewayUrl),deploymentId:typeof s.json.deploymentId=="string"?s.json.deploymentId:""};let i=typeof s.json.error=="string"?s.json.error:"";if(i!=="authorization_pending"){if(i==="slow_down"){a+=5e3;continue}throw i==="expired_token"?new Bt("expired","SSO sign-in timed out before you finished. Re-run anyray-connect --sso to try again."):new Bt("denied","SSO sign-in was not completed. Re-run anyray-connect --sso to try again.")}}throw new Bt("expired","SSO sign-in timed out. Re-run anyray-connect --sso to try again.")};var TS="sdc_",PS=e=>{let t=e.trim();if(!t)return;if(t.startsWith(TS))return{cpOrigin:Kn(),claim:t};let n;try{n=new URL(t)}catch{return}if(!rh(n.origin))return;let r=n.searchParams.get("claim")?.trim();if(!(!r||!r.startsWith(TS)))return{cpOrigin:n.origin,claim:r}},DS=async e=>{let t=e.fetch??fetch,{publicKeyPem:n,privateKeyPem:r}=(e.generateKeypair??wd)(),o;try{o=await ph(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.claim,devPublicKey:n},uh,t)}catch(s){throw new Bt("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(s)}`)}if(o.status===200&&o.json.cert)return{cert:o.json.cert,privateKeyPem:r,gatewayUrl:e.gatewayUrl??(typeof o.json.gatewayUrl=="string"?o.json.gatewayUrl:void 0),deploymentId:typeof o.json.deploymentId=="string"?o.json.deploymentId:"",...typeof o.json.ssoLink=="string"&&o.json.ssoLink?{ssoLink:o.json.ssoLink}:{}};let a=typeof o.json.error=="string"?o.json.error:"";throw a==="expired_token"?new Bt("expired","This enrollment link has expired. Open your organization\u2019s Anyray link again to get a new one."):a==="authorization_pending"?new Bt("denied","This enrollment link is not ready yet. Finish signing in in your browser, then run the command it gives you."):new Bt("denied","This enrollment link was already used or is not valid. Open your organization\u2019s Anyray link again to get a new one.")};import{readFile as yW}from"node:fs/promises";import{isAbsolute as gW,posix as LS,win32 as fh}from"node:path";var hi=(e=process.platform,t=process.env)=>e==="darwin"?LS.join("/Library","Application Support","Anyray","bootstrap.json"):e==="win32"?fh.join(t.ProgramData??"C:\\ProgramData","Anyray","bootstrap.json"):LS.join("/etc","anyray","bootstrap.json"),wW=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),NS=e=>typeof e=="string"&&e.length>0&&e.length<=512&&[...e].every(t=>{let n=t.charCodeAt(0);return n>=32&&n!==127})&&(gW(e)||fh.isAbsolute(e))&&!/ark_[A-Za-z0-9_-]{20,}|-----BEGIN/.test(e),bW=e=>{if(typeof e!="string"||e.length===0||e.length>512)return!1;try{let t=new URL(e);return(t.protocol==="https:"||t.protocol==="http:")&&!t.username&&!t.password}catch{return!1}},xr=async(e=hi())=>{try{let t=await yW(e,"utf-8");if(t.length>4096)return;let n=JSON.parse(t);if(!wW(n)||n.v!==1||typeof n.sso!="string")return;let r=Et(n.sso);if(!r)return;let o=bW(n.gateway)?n.gateway:void 0,a=NS(n.bin)?n.bin:void 0;return{sso:`${r.cpOrigin}/sso/${r.tenantId}`,gateway:o,bin:a}}catch{return}},$S=(e,t,n)=>{let r=Et(e);if(!r)throw new Error("invalid --sso link");if(n!==void 0&&!NS(n))throw new Error("--bin must be an absolute fleet-stable path");if(n!==void 0&&fh.isAbsolute(n)&&/^[A-Za-z]:\\/.test(n)&&!/^[A-Za-z]:\\Program Files( \(x86\))?\\/i.test(n))throw new Error("--bin on Windows must live under Program Files (admin-only writable)");return`${JSON.stringify({v:1,sso:`${r.cpOrigin}/sso/${r.tenantId}`,...t?{gateway:t}:{},...n?{bin:n}:{}},null,2)}
261
+ ${a.remedy}`];if(t.preservePendingOp)return[];await Ss(rd,Hm);let s=r.sessions+o,i=`${s} Claude Desktop local ${s===1?"item":"items"}`;return[a.kind==="store-missing"?`Queued: the ${i} still in your previous profile move across once Claude Desktop's new profile has been signed in to and the app is fully quit.`:`Queued: the ${i} still in your previous profile will move across the next time you fully quit Claude Desktop.`]}catch{return["Could not check whether Claude Desktop had existing sessions to bring across; run `anyray-connect migrate` if its lists look empty."]}},ZB=async e=>{if(!e.fullRevert||e.dryRun)return[];try{return await ur(rd),[]}catch{return["Could not clear Claude Desktop's queued profile-migration marker; a background watcher may still be waiting for the app to quit. Delete it by hand if it persists."]}},YB=e=>xv({id:rd,title:"Claude desktop",appDir:"Claude",detectPaths:()=>{let t=(e.platform??Er)(),n=(e.home??di)();return t==="darwin"?["/Applications/Claude.app",kn(n,"Applications","Claude.app")]:t==="win32"?[kn(process.env.LOCALAPPDATA??kn(n,"AppData","Local"),"Programs","Claude","Claude.exe")]:[]},steps:t=>ee(t,"anthropic")?["Claude Desktop subscription routing requires automatic setup on a verified macOS build and a Claude Code sign-in in Keychain.","This platform/build has no verified subscription helper seam, so Connect left inference unchanged instead of silently switching you to API billing.","To opt into the API-billed Gateway lane instead, re-run Connect in org/API mode and use:",...Dv(t)]:["Claude desktop org/API lane:",...Dv(t),"This Gateway route uses provider/API billing. On verified macOS builds, subscription mode instead installs the Keychain-backed Claude Code credential helper automatically."],revertMessages:["Claude Desktop third-party inference: switch back to the first-party Claude provider in Developer settings (or remove the managed profile). Native setup is restored automatically by `--revert`."]}),JB=(e={})=>{let t=YB(e),n=()=>(e.platform??Er)()==="darwin",r=()=>(e.platform??Er)()==="win32",o=(s,i)=>n()?Ck(s,i,e):Qk(s,s.clientKey??"",i,e),a=s=>n()?kk(s,e):ev(s,e);return{...t,automatic:!0,changesOrgManagement:!0,quitGated:{isRunning:()=>(e.appRunning??ga((e.platform??Er)()))(),quitTarget:GB,needsTarget:()=>!1,async complete(s){if(s!==Hm)return{status:"manual",messages:[`Claude Desktop could not service a queued "${s}" operation it does not recognise; the queue entry was dropped.`]};let i=await(e.migrateDesktopProfile??po)(Fv(e));if(i.ok){let c=Wv(i.lanes),l=Uv(i.portableAssets),d=i.ambiguousAssets??[];if(d.length>0)return{status:"manual",messages:[...c?[c]:[],...l?[l]:[],`Claude Desktop has more than one target ${d.join(" and ")} store. No store was chosen and every target was preserved. Leave only the intended third-party account/workspace active, then run the migration again.`]};let f=(i.blocked??[]).filter(h=>h.reason!=="ambiguous"),p=i.blockedAssets??[],m=i.retryableAssets??[];return f.length>0||p.length>0||m.length>0?{status:"queued",messages:[...c?[c]:[],...l?[l]:[],...f.length>0||p.length>0?["Still waiting on Claude Desktop to create the remaining third-party stores, which appear the first time those parts of the app are opened."]:[],...m.length>0?["A recoverable local-copy interruption remains; the migration will retry automatically."]:[]]}:{status:"configured",messages:c||l?[c,l].filter(h=>!!h):["No portable Claude Desktop data was left to bring across."]}}return Bv.has(i.kind)?{status:"queued",messages:[i.reason]}:{status:"manual",messages:[i.reason,i.remedy]}}},async usesDynamicCredential(s){return n()?Sk(s,e):r()?rv(s,e):!1},async apply(s,i){if(!n()&&!r())return t.apply(s,i);if(n()){let f=Yt(e),p=await co(f,e);if(p)return{status:"manual",manualAudience:"admin",messages:[pm(p),...await li(e,i)]}}if(r()){let f;try{f=await Sr(e.runReg??Hn)}catch{return{status:"manual",manualAudience:"admin",messages:[jB,...await li(e,i)]}}if(f)return{status:"manual",manualAudience:"admin",messages:[Om(f),...await li(e,i)]}}if(r()&&ee(s,"anthropic"))return{status:"manual",messages:["Claude Desktop subscription routing is not available on Windows: Connect could not verify a supported Claude subscription credential source, so inference was left unchanged instead of switching to API billing.","Use org/API mode for the Windows Gateway lane, or run subscription mode on a verified macOS build after signing in to Claude Code."]};if(n()){let f=await ba(e);if(!f.supported)return{status:"manual",messages:[f.message??"Claude Desktop version is unsupported."]}}let c;try{c=await WB(e)}catch(f){let p=f instanceof Fe?f.changedFiles:[];return{status:"manual",...p.length>0?{changedFiles:p}:{},messages:[f instanceof Fe?f.message:"Could not safely inspect Claude Desktop's retrieval MCP configuration; no inference setting was changed."]}}let l=await o(s,{dryRun:!0});if(l.status!=="configured")return l;if(i.dryRun){let f=c.legacy;return{...l,messages:[...l.messages,`Would register the ownership-marked Anyray retrieval MCP server in ${c.active.path}.`,...f&&f.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${f.path}.`]:[],...await li(e,i)]}}let d;try{d=await UB(c)}catch(f){let p=f instanceof Fe?f.changedFiles:[];return{status:"manual",...p.length>0?{changedFiles:p}:{},messages:[f instanceof Fe?f.message:"Could not safely register Claude Desktop retrieval; the inference route was left unchanged."]}}let u;try{u=await o(s,{dryRun:!1})}catch{u={status:"manual",messages:["Claude Desktop inference setup failed before it returned a result."]}}if(u.status!=="configured")try{return await d.rollback(),{...u,changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])],messages:[...u.messages,"Restored the prior Claude Desktop MCP registration because inference setup did not complete. A config file that was absent before setup may remain as an inert object to avoid racing unrelated concurrent writes."]}}catch{return{status:"manual",changedFiles:[...u.changedFiles??[],...d.changedFiles],messages:[...u.messages,"Inference setup did not complete, and the prior MCP registration could not be fully restored. Re-run `anyray-connect desktop disconnect` to recover safely."]}}return{...u,messages:[...u.messages,"Registered the Anyray retrieval MCP server (anyray_retrieve / anyray_recall) with an ownership marker.",...await li(e,i),...!i.dryRun&&i.reportsToUser&&i.explicit&&n()?LB:[]],changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])]}},async revert(s){let i=td(e),c=await ZB(s),l=h=>c.length===0?h:{...h,messages:[...h.messages,...c]};if(!n()&&!r())return l(await t.revert(s));let d;try{d=await Pv(e)}catch(h){return l({status:"manual",messages:[h instanceof Fe?h.message:"Could not safely inspect Claude Desktop's retrieval MCP configuration; no setting was removed."]})}let u=await a({dryRun:!0});if(s.dryRun){let h=d.legacy;return l({...u,messages:[...u.messages,...d.active.ownership!=="absent"?[`Would remove the owned Anyray retrieval MCP server from ${i}.`]:[],...h&&h.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${h.path}.`]:[]]})}let f=await a({dryRun:!1});if(f.status==="manual"){let h=r()?Mt(e):void 0;if(!(h!==void 0&&f.changedFiles?.includes(h)===!0&&!await x(h)))return l(f)}let p;try{p=await HB(await Pv(e))}catch(h){let g=h instanceof Fe?h.changedFiles:[];return l({status:"manual",changedFiles:[...new Set([...f.changedFiles??[],...g])],messages:[...f.messages,h instanceof Fe?h.message:"Restored Claude Desktop inference, but could not safely remove its retrieval MCP registration. Re-run revert."]})}await ce(i);let m=Gm(e);return n()&&m!==i&&await ce(m),l({...f,messages:[...f.messages,...p.length>0?["Removed the Anyray retrieval MCP server (anyray_retrieve / anyray_recall)."]:[]],changedFiles:[...new Set([...f.changedFiles??[],...p])]})},async mcpStatus(){if(!ne())return{registered:!1,command:null,reason:"ephemeral-runtime"};try{let s=await mo(td(e));return s.ownership!=="exact"||!fo(s.entry)?{registered:!1,command:null,reason:s.fileExisted?s.ownership==="absent"?"absent":s.ownership==="stale-owned"?"stale":"foreign":"no-config"}:{registered:!0,command:typeof s.entry.command=="string"?s.entry.command:null}}catch{return{registered:!1,command:null,reason:"unreadable"}}},async pointsAt(s){return n()?(await ba(e)).supported?mm(s,e):!1:r()?nv(s,e):!1},async inferenceAuthLanes(){try{if(n()){if(!(await ba(e)).supported)return["unknown"];let s=await vk(e);return s?[s]:["unknown"]}if(r())return await x(Mt(e))?await Sr(e.runReg??Hn)?["unknown"]:["api_key"]:["unknown"]}catch{}return["unknown"]},async automaticRepairAllowed(){try{if(n()){let s=Yt(e);return!await x(s.journal)||await co(s,e)?!1:(await ba(e)).supported}return r()&&await x(Mt(e))?!await Sr(e.runReg??Hn):!1}catch{return!1}}}},Hv=JB();import{homedir as vF}from"node:os";import{join as SF}from"node:path";import{rm as pd}from"node:fs/promises";import{constants as Gv,accessSync as XB,statSync as zB}from"node:fs";import{platform as Vm}from"node:os";import{delimiter as qB,posix as QB,resolve as eF,win32 as tF}from"node:path";var nF="0.59.0",rF="1.1.4",Gn="Anyray \xB7 Claude",Vn="Anyray \xB7 Codex",od="__anyray-acp-agent",Vv=(e,t,n)=>{let{command:r,args:o}=nn([od,e,t,n]);return{command:r,args:o,env:{}}},ad=(e=Vm())=>e==="win32"?"npx.cmd":"npx",sd=(e=process.env.PATH,t=Vm())=>{if(!e)return;let n=ad(t);for(let r of e.split(qB)){let o=r.trim().replace(/^"|"$/g,"");if(!o)continue;let a=eF(o,n);try{if(!zB(a).isFile())continue;return XB(a,t==="win32"?Gv.F_OK:Gv.X_OK),a}catch{}}},id=(e,t=Vm())=>{let n=t==="win32"?tF:QB;return!n.isAbsolute(e)||n.basename(e).toLowerCase()!==ad(t)?!1:t!=="win32"||!/["&|<>^%!\r\n]/.test(e)},oF="https://chatgpt.com/backend-api/codex",aF="chatgpt-account-id,originator,session_id,user-agent,x-codex-turn-metadata,x-codex-window-id,x-client-request-id",Kv="ANYRAY_ACP_CODEX_AUTHORIZATION",jv="ANYRAY_ACP_CODEX_CLIENT_KEY",Zv="ANYRAY_ACP_CODEX_METADATA",Yv=e=>fe({...e.metadata,tool:e.metadata.tool??"codex",intent:e.metadata.intent??"jetbrains-acp",intentLabel:e.metadata.intentLabel??"JetBrains / Devin via Codex ACP"}),sF=(e,t={})=>{let n=ee(e,"openai"),r=n?{"x-anyray-auth-mode":"passthrough","x-anyray-custom-host":oF,"x-anyray-forward-headers":aF}:{},o=n?{...e.clientKey?{"x-anyray-api-key":jv}:{}}:{Authorization:Kv};return Yv(e)&&(o["x-anyray-metadata"]=Zv),{model_provider:"anyray",model_providers:{anyray:{name:"Anyray Gateway",base_url:e.openaiBaseUrl,wire_api:"responses",...n?{requires_openai_auth:!0}:{},http_headers:r,env_http_headers:o}},...t.mcpServer?{mcp_servers:{anyray:{command:t.mcpServer.command,args:t.mcpServer.args}}}:{}}},iF=e=>{let t=ee(e,"openai"),n=Yv(e);return{...t?e.clientKey?{[jv]:e.clientKey}:{}:{[Kv]:`Bearer ${e.clientKey??e.placeholderKey}`},...n?{[Zv]:n}:{}}},Jv=(e,t=ad(),n={})=>({[Gn]:{command:t,args:["--yes",`@agentclientprotocol/claude-agent-acp@${nF}`],env:rn(e).env},[Vn]:{command:t,args:["--yes",`@agentclientprotocol/codex-acp@${rF}`],env:{CODEX_CONFIG:JSON.stringify(sF(e,n)),...iF(e)}}}),ui=(e=ad(),t="jetbrains")=>({[Gn]:Vv("claude",e,t),[Vn]:Vv("codex",e,t)}),ho=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),cd=(e,t)=>JSON.stringify(e)===JSON.stringify(t);import{inflateRawSync as cF}from"node:zlib";import{open as lF,readFile as Jm,readdir as ud}from"node:fs/promises";import{dirname as Xv,join as me}from"node:path";import{homedir as eS,platform as Xm}from"node:os";var ld="2025.3.2",Aa="253.30387.147",pi="com.intellij.ml.llm",Km=new Set(["ml-llm","llm","aia","ai-assistant","jetbrains-ai-assistant"]),dF=1e4,uF=256*1024*1024,pF=16*1024*1024,jm=1024*1024,Zm=22,fF=Zm+65535,Ym=xl,mF=()=>{let e=eS(),t=me(e,".cache","JetBrains","RemoteDev");switch(Xm()){case"darwin":return[{path:"/Applications",layout:"app-bundles"},{path:me(e,"Applications"),layout:"app-bundles"},{path:me(e,"Library","Application Support","JetBrains","Toolbox"),layout:"recursive"},{path:t,layout:"recursive"}];case"win32":return[{path:me(process.env.LOCALAPPDATA??me(e,"AppData","Local"),"Programs"),layout:"children"},{path:me(process.env.LOCALAPPDATA??me(e,"AppData","Local"),"JetBrains","Toolbox"),layout:"recursive"},{path:me(process.env.ProgramFiles??"C:\\Program Files","JetBrains"),layout:"children"}];default:return[{path:"/opt",layout:"children"},{path:me(e,".local","share","JetBrains","Toolbox"),layout:"recursive"},{path:t,layout:"recursive"}]}},hF=()=>Xm()==="linux"?me(eS(),".local","share","JetBrains"):Le("JetBrains"),yF=()=>Xm()==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),gF=async(e,t=dF)=>{let n=[];for(let r of e){if(r.layout!=="recursive"){let s;try{s=await ud(r.path,{withFileTypes:!0})}catch{continue}for(let i of s.slice(0,t)){if(!i.isDirectory()&&!i.isSymbolicLink())continue;let c=me(r.path,i.name),l=r.layout==="app-bundles"?me(c,"Contents","Resources","product-info.json"):me(c,"product-info.json");await x(l)&&n.push(l)}continue}let o=0,a=async(s,i)=>{if(i<0||o>=t)return;let c=me(s,"product-info.json"),l=me(s,"Contents","Resources","product-info.json");if(await x(c)){n.push(c);return}if(await x(l)){n.push(l);return}let d;try{d=await ud(s,{withFileTypes:!0})}catch{return}for(let u of d){if(o>=t)return;o+=1;let f=me(s,u.name);(u.isDirectory()||u.isSymbolicLink())&&!["bin","jbr","lib","plugins","Contents"].includes(u.name)&&await a(f,i-1)}};await a(r.path,7)}return[...new Set(n)]},wF=e=>{let t=Xv(e);return t.endsWith(`${me("Contents","Resources")}`)?Xv(t):t},bF=async e=>{try{let t=JSON.parse(await Jm(e,"utf8"));if(!t||typeof t!="object"||typeof t.version!="string"||typeof t.dataDirectoryName!="string")return;let n=t;return!js(n.version)||!/^[A-Za-z0-9._-]+$/.test(n.dataDirectoryName)?void 0:{version:n.version,dataDirectoryName:n.dataDirectoryName,root:wF(e)}}catch{return}},dd=async(e,t,n)=>{let r=Buffer.alloc(t),{bytesRead:o}=await e.read(r,0,t,n);return o===t?r:void 0},AF=async(e,t)=>{let n;try{n=await lF(e,"r");let{size:r}=await n.stat();if(r<Zm||r>uF)return;let o=Math.min(r,fF),a=await dd(n,o,r-o);if(!a)return;let s=-1;for(let u=a.length-Zm;u>=0;u-=1)if(a.readUInt32LE(u)===101010256){s=u;break}if(s<0)return;let i=a.readUInt32LE(s+12),c=a.readUInt32LE(s+16);if(i>pF||c+i>r)return;let l=await dd(n,i,c);if(!l)return;let d=0;for(;d+46<=l.length;){if(l.readUInt32LE(d)!==33639248)return;let u=l.readUInt16LE(d+10),f=l.readUInt32LE(d+20),p=l.readUInt32LE(d+24),m=l.readUInt16LE(d+28),h=l.readUInt16LE(d+30),g=l.readUInt16LE(d+32),y=l.readUInt32LE(d+42),w=d+46+m+h+g;if(w>l.length)return;let b=l.subarray(d+46,d+46+m).toString("utf8");if(d=w,b!==t)continue;if(f===4294967295||p===4294967295||f>jm||p>jm)return;let k=await dd(n,30,y);if(!k||k.readUInt32LE(0)!==67324752)return;let C=k.readUInt16LE(26),S=k.readUInt16LE(28),E=await dd(n,f,y+30+C+S);return E?u===0?E.toString("utf8"):u===8?cF(E,{maxOutputLength:jm}).toString("utf8"):void 0:void 0}return}catch{return}finally{await n?.close().catch(()=>{})}},zv=e=>{let t=e.match(/<id>\s*([^<]+?)\s*<\/id>/)?.[1]?.trim(),n=e.match(/<version>\s*([^<]+?)\s*<\/version>/)?.[1]?.trim();if(!(!t||!n||!js(n)))return{id:t,version:n}},CF=async(e,t)=>{let n=me(e,"META-INF","plugin.xml");if(await x(n))try{let o=zv(await Jm(n,"utf8"));return{present:o?.id===pi||t,descriptor:o?.id===pi?o:void 0}}catch{return{present:t}}let r=[];try{r=(await ud(me(e,"lib"),{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".jar")&&/(?:^|[-_.])(ml-?llm|llm|aia|ai[-_.]?assistant)(?:[-_.]|$)/i.test(o.name)).slice(0,32).map(o=>me(e,"lib",o.name))}catch{return{present:!1}}for(let o of r){let a=await AF(o,"META-INF/plugin.xml"),s=a?zv(a):void 0;if(s?.id===pi)return{present:!0,descriptor:s}}return{present:t&&r.length>0}},qv=async e=>{let t;try{t=await ud(e,{withFileTypes:!0})}catch{return{present:!1}}let n=t.filter(o=>o.isDirectory()||o.isSymbolicLink()).sort((o,a)=>{let s=Km.has(o.name.toLowerCase()),i=Km.has(a.name.toLowerCase());return Number(i)-Number(s)}).slice(0,512),r=!1;for(let o of n){let a=Km.has(o.name.toLowerCase());if(!a){let i=me(e,o.name,"META-INF","plugin.xml");if(!await x(i))continue}let s=await CF(me(e,o.name),a);if(s.descriptor)return s;s.present&&(r=!0)}return{present:r}},kF=async e=>{try{return(await Jm(me(e,"disabled_plugins.txt"),"utf8")).split(/\r?\n/).map(n=>n.trim()).includes(pi)}catch{return!1}},Qv=e=>e.reduce((t,n)=>t?(Ym(n,t)??-1)>0?n:t:n,void 0),tS=async(e={})=>{let t=e.configRoot??Le("JetBrains"),n=e.userPluginsRoot??hF(),r=await gF(e.productRoots?e.productRoots.map(m=>({path:m,layout:"recursive"})):mF(),e.scanBudget),o=(await Promise.all(r.map(m=>bF(m)))).filter(m=>m!==void 0),a=o.length>0||await x(t);if(e.wsl??yF())return{installed:a,capable:!1,detail:"JetBrains AI Assistant does not support ACP in WSL; no ACP config was written."};let s=o.filter(m=>(Ym(m.version,ld)??-1)>=0),i=[],c=!1,l=!1,d=!1;for(let m of s){let h=me(t,m.dataDirectoryName);if(!await x(h)){d=!0;continue}let g=[me(h,"plugins"),me(n,m.dataDirectoryName),me(n,m.dataDirectoryName,"plugins")],y;for(let w of[...new Set(g)]){let b=await qv(w);if(b.present){y=b;break}}if(y??=await qv(me(m.root,"plugins")),y.present&&!y.descriptor){l=!0;continue}if(!(!y.descriptor||y.descriptor.id!==pi)){if(i.push(y.descriptor.version),await kF(h)){c=!0;continue}if(!((Ym(y.descriptor.version,Aa)??-1)<0))return{installed:!0,capable:!0,detail:`JetBrains IDE ${m.version}; AI Assistant ${y.descriptor.version}; ACP supported`,ideVersion:m.version,pluginVersion:y.descriptor.version}}}let u=Qv(o.map(m=>m.version)),f=Qv(i),p;return a?u?s.length===0?p=`JetBrains IDE ${u} is below the ACP minimum ${ld}; no ACP config was written.`:d?p=`Could not prove that JetBrains AI Assistant is enabled for this user; start IDE ${ld}+ once, enable AI Assistant ${Aa}+, then run Connect again. No ACP config was written.`:c?p=`JetBrains AI Assistant is disabled; enable version ${Aa}+ and run Connect again. No ACP config was written.`:f?p=`JetBrains AI Assistant ${f} is below the ACP minimum ${Aa}; no ACP config was written.`:l?p=`Could not verify the local JetBrains AI Assistant version; require ${Aa}+ before running Connect. No ACP config was written.`:p=`JetBrains AI Assistant ${Aa}+ was not found; install or enable it, then run Connect again. No ACP config was written.`:p=`Could not prove JetBrains IDE ${ld}+ from local product-info.json; no ACP config was written.`:p="JetBrains IDE config or installation not found",{installed:a,capable:!1,detail:p,ideVersion:u,pluginVersion:f}};var EF=[Gn,Vn],zm=()=>SF(vF(),".jetbrains","acp.json"),yo=()=>`${zm()}.anyray-state`,IF=(e,t,n="npx")=>{let r=ho(e.agent_servers)?{...e.agent_servers}:{};return Object.assign(r,ui(n,"jetbrains")),{...e,agent_servers:r}},xF=(e,t,n)=>{if(!ho(e.agent_servers))return{next:e,removed:[],conflicts:[]};let r={...e.agent_servers},o=ho(t.agent_servers)?t.agent_servers:{},a=[],s=[];for(let c of EF)if(c in r){if(!cd(r[c],n[c])){s.push(c);continue}c in o?r[c]=o[c]:delete r[c],a.push(c)}let i={...e};return Object.keys(r).length>0?i.agent_servers=r:delete i.agent_servers,{next:i,removed:a,conflicts:s}},RF=(e=tS)=>({id:"jetbrains",title:"JetBrains AI Assistant",automatic:!0,async detect(){let t=await e();return{installed:t.installed,detail:t.detail}},async apply(t,n){let r=zm(),o=await e();if(!o.capable)return{status:o.installed?"manual":"not-found",messages:[o.detail]};let a=sd();if(!a)return{status:"manual",messages:["JetBrains ACP requires Node.js with npm/npx. Install that prerequisite, then run Connect again; no ACP config was written."]};let s=[`${r} \u2190 documented JetBrains ACP custom-agent configuration`,`${o.detail}.`,"Registered Claude and Codex ACP agents with Anyray routing; no IDE proxy, certificate, DNS, or private Copilot endpoint is changed.","Claude keeps Anthropic subscription auth when selected; Codex keeps ChatGPT subscription auth when selected. Org/API mode uses the enrolled personal gateway key.","The agents appear in AI Chat after the IDE reloads. Their first launch may ask for the provider sign-in if that seat is not already authenticated.","JetBrains Copilot remains a separate closed client; its content-free usage is covered by the Copilot usage connector, not endpoint interception."];if(n.dryRun)return{status:"configured",messages:s};let i=await x(r),c;try{c=await M(r)}catch{return{status:"manual",messages:[`Refused to overwrite malformed ${r}; fix or replace the file, then run Connect again.`]}}let l=ui(a,"jetbrains");return await qi({configPath:r,current:c,next:IF(c,t,a),journalPath:yo(),journal:{version:2,fileExisted:i,entries:l},fileExisted:i}),{status:"configured",messages:s,changedFiles:[r,yo()]}},async revert(t){let n=zm(),r=async()=>{if(!await x(n))return t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:"reverted",messages:["No JetBrains ACP config to remove."]};let o;try{o=await M(n)}catch{return t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:"manual",messages:[`Could not parse ${n}; remove the two \u201CAnyray \xB7 \u2026\u201D agent entries manually.`]}}let a={},s=!1,i=!1;try{let u=await M(yo());(u.version===1||u.version===2)&&ho(u.entries)&&(a=u.entries,s=u.version===2&&u.fileExisted===!1,i=u.version===2&&u.fileExisted===!0)}catch{}let c;if(i){let u=`${n}.anyray-bak`;if(!await x(u))return{status:"manual",messages:[`Refused to remove JetBrains ACP entries because the original backup for ${n} is missing. Restore or remove the entries manually.`]};try{c=await M(u)}catch{return{status:"manual",messages:[`Refused to remove JetBrains ACP entries because the original backup for ${n} is malformed. Repair it or remove the entries manually.`]}}}else c=await $r(n);let l=xF(o,c,a),d=[];return l.removed.length&&d.push(`Removed ${l.removed.join(", ")} from ${n}.`),l.conflicts.length&&d.push(`Preserved user-modified ACP entries: ${l.conflicts.join(", ")}.`),!t.dryRun&&l.removed.length&&(s&&Object.keys(l.next).length===0?await pd(n,{force:!0}):await J(n,l.next,{backup:!1})),t.dryRun||(await ce(n),await pd(yo(),{force:!0}).catch(()=>{})),{status:l.conflicts.length?"manual":"reverted",messages:d.length?d:["No Anyray ACP entries found."],changedFiles:!t.dryRun&&l.removed.length?[n]:void 0}};return t.dryRun?r():zi(n,yo(),r)}}),nS=RF();import{homedir as md}from"node:os";import{join as hd}from"node:path";import{rm as qm}from"node:fs/promises";var Qm="1.0.0",yd=["anyray-claude-acp","anyray-codex-acp"],OF=["darwin-aarch64","darwin-x86_64","linux-aarch64","linux-x86_64","windows-aarch64","windows-x86_64"],eh=()=>hd(md(),".windsurf","acp","registry.json"),th=()=>hd(md(),".windsurf-next","acp","registry.json"),Ca=e=>`${e}.anyray-state`,rS=e=>({binary:Object.fromEntries(OF.map(t=>[t,{archive:"",cmd:e.command,args:e.args}]))}),aS=(e="npx")=>{let t=ui(e,"windsurf");return[{id:yd[0],name:Gn,version:"1.0.0",description:"Claude through the Anyray gateway via ACP",authors:["Anyray","Agent Client Protocol"],license:"Apache-2.0",distribution:rS(t[Gn])},{id:yd[1],name:Vn,version:"1.0.0",description:"Codex through the Anyray gateway via ACP",authors:["Anyray","Agent Client Protocol"],license:"Apache-2.0",distribution:rS(t[Vn])}]},fd=e=>!Array.isArray(e)||e.some(t=>!ho(t)||typeof t.id!="string")?null:e,TF=(e,t="npx")=>{if(e.version!==void 0&&e.version!==Qm||e.extensions!==void 0&&!Array.isArray(e.extensions))return null;let n=e.agents===void 0?[]:fd(e.agents);if(!n)return null;let r=new Set(yd);return{...e,version:typeof e.version=="string"?e.version:Qm,agents:[...n.filter(o=>!r.has(o.id)),...aS(t)],extensions:e.extensions??[]}},_F=(e,t,n)=>{let r=fd(e.agents);if(!r)return null;let o=fd(t.agents)??[],a=new Map((fd(n)??[]).map(u=>[u.id,u])),s=new Map(o.map(u=>[u.id,u])),i=[],c=[],l=[];for(let u of r){if(!yd.includes(u.id)){l.push(u);continue}if(!cd(u,a.get(u.id))){c.push(u.id),l.push(u);continue}let f=s.get(u.id);f&&l.push(f),i.push(u.id)}let d={...e,agents:l};return!Object.prototype.hasOwnProperty.call(t,"agents")&&l.length===0&&delete d.agents,!Object.prototype.hasOwnProperty.call(t,"version")&&d.version===Qm&&delete d.version,!Object.prototype.hasOwnProperty.call(t,"extensions")&&Array.isArray(d.extensions)&&d.extensions.length===0&&delete d.extensions,{next:d,removed:i,conflicts:c}},oS=async()=>{let e=[];return(await x(th())||await x(hd(md(),".windsurf-next")))&&e.push(th()),(await x(eh())||await x(hd(md(),".windsurf"))||await x(Le("Devin"))||await x(Le("Windsurf")))&&e.push(eh()),e},sS={id:"windsurf",title:"Devin Desktop",automatic:!0,async detect(){let e=await oS();return e.length?{installed:!0,detail:e.join(", ")}:{installed:!1,detail:"Devin Desktop not found"}},async apply(e,t){let n=await oS();if(!n.length)return{status:"not-found",messages:["Devin Desktop is not installed; no ACP registry was written."]};let r=sd();if(!r)return{status:"manual",messages:["Devin ACP requires Node.js with npm/npx. Install that prerequisite, then run Connect again; no ACP registry was written."]};let o=[],a=[];for(let s of n){let i;try{i=await M(s)}catch{o.push(`Refused to overwrite malformed ${s}; fix or replace the file, then run Connect again.`);continue}let c=TF(i,r);if(!c){o.push(`Refused unrecognized ACP registry shape in ${s}.`);continue}if(o.push(`${s} \u2190 registered Anyray Claude and Codex ACP agents.`),!t.dryRun){let l=await x(s),d=aS(r);await qi({configPath:s,current:i,next:c,journalPath:Ca(s),journal:{version:2,fileExisted:l,agents:d},fileExisted:l}),a.push(s,Ca(s))}}return o.push("Devin requires a one-time vendor UI enablement for local registry agents: Devin Settings \u2192 Agents \u2192 enable the two Anyray agents, then restart Devin Desktop."),o.push("Native Devin/Cascade subscription requests are not redirected. The official enterprise consumption connector imports content-free usage instead."),o.push("No proxy, certificate, DNS, DEVIN_API_URL, or private first-party endpoint was changed."),{status:"manual",messages:o,changedFiles:a.length?a:void 0}},async revert(e){let t=[eh(),th()],n=[],r=[],o=!1;for(let a of t){let s=async()=>{if(!await x(a)){e.dryRun||(await ce(a),await qm(Ca(a),{force:!0}).catch(()=>{}));return}let i;try{i=await M(a)}catch{n.push(`Could not parse ${a}; remove the anyray-* ACP agents manually.`),o=!0;return}let c=[],l=!1,d=!1;try{let p=await M(Ca(a));(p.version===1||p.version===2)&&Array.isArray(p.agents)&&(c=p.agents,l=p.version===2&&p.fileExisted===!1,d=p.version===2&&p.fileExisted===!0)}catch{}let u;if(d){let p=`${a}.anyray-bak`;if(!await x(p)){n.push(`Refused to remove Devin ACP agents because the original backup for ${a} is missing. Restore it or remove the agents manually.`),o=!0;return}try{u=await M(p)}catch{n.push(`Refused to remove Devin ACP agents because the original backup for ${a} is malformed. Repair it or remove the agents manually.`),o=!0;return}}else u=await $r(a);let f=_F(i,u,c);if(!f){n.push(`Unrecognized ACP registry shape in ${a}; left it unchanged.`),o=!0;return}f.removed.length&&(n.push(`Removed ${f.removed.join(", ")} from ${a}.`),e.dryRun||(l&&Object.keys(f.next).length===0?await qm(a,{force:!0}):await J(a,f.next,{backup:!1}),r.push(a))),f.conflicts.length?(n.push(`Preserved user-modified agents: ${f.conflicts.join(", ")}.`),o=!0):e.dryRun||(await ce(a),await qm(Ca(a),{force:!0}).catch(()=>{}))};e.dryRun?await s():await zi(a,Ca(a),s)}return{status:o?"manual":"reverted",messages:n.length?n:["No Anyray Devin ACP agents found."],changedFiles:r.length?r:void 0}}};var pe=[rr,qw,Os,eC,xC,FC,jC,nS,Hv,sS,sb],ut=e=>pe.find(t=>t.id===e);var We=async(e=P,t=yn)=>{let n=await e();if(!n.gateway||!n.clientKey)return;let r=await t().catch(()=>{});return{target:Oe({origin:n.gateway,clientKey:n.clientKey,subscription:n.authMode==="subscription",placeholder:n.authMode==="placeholder",byoUpstream:n.byoUpstream,seat:r,user:n.name,team:n.team})}};var nh=5e3,iS=3e4,PF=1440*60*1e3,DF=e=>new Promise(t=>setTimeout(t,e)),LF=async(e=P,t=yn)=>(await We(e,t))?.target,NF=e=>ut(e)?.quitGated,cS=async(e,t={})=>{let n=e[0];if(!n)return 0;let r=t.resolveSeam??NF,o=t.readPending??Kc,a=t.clearPending??Up,s=t.targetFromProfile??LF,i=t.sleep??DF,c=t.now??Date.now,l=t.maxWaitMs??PF;try{let d=r(n);if(!d?.complete)return await a(n),0;let u=d.complete.bind(d),f=c(),p=nh;for(;;){let m=await o(n);if(!m||c()-f>l)return 0;if(d.isRunning()){await i(p),p=Math.min(iS,p*2);continue}let h;if(d.needsTarget?.(m.op)&&(h=await s(),!h)){if(await a(n,m)!=="superseded")return 0;await i(p),p=nh;continue}if((await u(m.op,h,{dryRun:!1,preservePendingOp:!0})).status==="queued"){await i(p),p=Math.min(iS,p*2);continue}if(await a(n,m)!=="superseded")return 0;await i(p),p=nh}}catch{return 0}};import{writeFileSync as vW}from"node:fs";import{chmod as mh,stat as SW}from"node:fs/promises";import{platform as FS}from"node:os";import{dirname as WS,isAbsolute as EW}from"node:path";var $F="https://app.anyray.ai",MF=new Set(["localhost","::1","[::1]"]),BF=/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,FF=e=>MF.has(e)||BF.test(e),rh=e=>{let t;try{t=new URL(e)}catch{return!1}return t.protocol==="https:"?!0:t.protocol==="http:"&&FF(t.hostname)},WF=e=>{let t=e.length;for(;t>0&&e[t-1]==="/";)t-=1;return e.slice(0,t)},Kn=()=>{let e=process.env.ANYRAY_CP_ORIGIN?.trim();return!e||!rh(e)?$F:WF(e)};import{createHash as QF,generateKeyPairSync as eW,randomBytes as sh}from"node:crypto";import{createPrivateKey as UF,sign as HF}from"node:crypto";var Ir=async(e,t)=>{let n=UF(t);return HF(null,new TextEncoder().encode(e),n).toString("base64url")};var GF=["HTTPS_PROXY","https_proxy"],lS=new Set(["SELF_SIGNED_CERT_IN_CHAIN","DEPTH_ZERO_SELF_SIGNED_CERT","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED"]),dS=new Set(["CERT_HAS_EXPIRED","CERT_NOT_YET_VALID","ERR_TLS_CERT_ALTNAME_INVALID","ERR_SSL_WRONG_VERSION_NUMBER","EPROTO"]),uS=new Set(["ENOTFOUND","EAI_AGAIN"]),pS=new Set(["ECONNREFUSED","ECONNRESET","EPIPE","ENETDOWN","ENETUNREACH","EHOSTUNREACH","EHOSTDOWN"]),fS=new Set(["ETIMEDOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT"]),VF=e=>{let t=e;for(let n=0;n<5&&t;n++){let r=t.code;if(typeof r=="string"&&r)return r;t=t.cause}return KF(e)},KF=e=>{let t=e?.message;if(!(typeof t!="string"||!t)){for(let n of[...lS,...dS,...uS,...pS,...fS])if(t.includes(n))return n}},jF=e=>e?.name==="AbortError"||e?.name==="TimeoutError",ZF=e=>GF.filter(t=>(e[t]??"").trim()!==""),YF=(e,t=process.env)=>{let n=VF(e),r=ZF(t);return{kind:n&&lS.has(n)?"tls-unknown-issuer":n&&dS.has(n)?"tls-invalid-cert":n&&uS.has(n)?"dns":jF(e)||n&&fS.has(n)?"timeout":n&&pS.has(n)?"refused":"unknown",...n?{code:n}:{},proxyVars:r}},JF=e=>{let t=e.proxyVars.length>0?` ${e.proxyVars.join(" and ")} ${e.proxyVars.length>1?"are":"is"} set \u2014 if that proxy is stale or unreachable, unset it and re-run.`:"";switch(e.kind){case"tls-unknown-issuer":return` (TLS certificate signed by an unknown authority: ${e.code}). Your network appears to inspect TLS traffic. curl trusts your system keychain and this binary does not, which is why the download worked and this step did not. Point NODE_EXTRA_CA_CERTS at your organization root certificate (PEM) and re-run.`+t;case"tls-invalid-cert":return` (TLS certificate rejected: ${e.code}). Check this machine's clock and date, and whether a proxy is rewriting HTTPS traffic, then re-run.`+t;case"dns":return` (DNS lookup failed: ${e.code}). Check your VPN or DNS, then re-run.`+t;case"refused":return` (connection failed: ${e.code}).`+(t||" Check your network or firewall, then re-run.");case"timeout":return" (timed out before the control plane answered)."+(t||" Check your connection and re-run.");default:return e.code?` (${e.code}).${t}`:t}},pt=(e,t=process.env)=>JF(YF(e,t));var XF="enl_",mS="enp_",hS=e=>e.startsWith(XF)||e.startsWith(mS),oh=e=>e.startsWith(mS),zF=[{prefix:"tnt_",flag:"--sso",what:"an SSO link"},{prefix:"sdc_",flag:"--claim",what:"a one-time enrollment code"}],ah=e=>zF.find(t=>e.startsWith(t.prefix)),yS=/^\/enroll\/([^/]+)\/?$/,gS=/^\/i\/([^/]+)\/?$/,wS=e=>{let t=e.match(yS);if(t)return ah(t[1])?void 0:t[1];let n=e.match(gS);return n&&hS(n[1])?n[1]:void 0},qF=1e4,gd=e=>{let t=e.trim();if(!t)return;let n;try{n=new URL(t)}catch{n=void 0}if(n){if(n.protocol!=="http:"&&n.protocol!=="https:")return;let r=wS(n.pathname);return r?{cpOrigin:n.origin,token:r}:void 0}if(!ah(t))return{cpOrigin:Kn(),token:t}},bS=e=>{let t=e.trim();if(!t)return;let n=t;try{let o=new URL(t),a=o.pathname.match(yS)??o.pathname.match(gS);if(!a)return;n=a[1]}catch{}let r=ah(n);return r?{flag:r.flag,what:r.what}:void 0},mi=e=>{let t=e.trim();if(!t)return!1;try{let n=new URL(t);return n.protocol!=="http:"&&n.protocol!=="https:"?!1:wS(n.pathname)!==void 0}catch{return hS(t)}},ka=class extends Error{constructor(t){super(t),this.name="EnrollmentPermanentError"}},fi=e=>typeof e=="string"&&e.trim()?e.trim():void 0,AS=async(e,t={})=>{let n=t.timeoutMs??qF,r=`${e.cpOrigin}/enroll-info/${e.token}`,o=new AbortController,a=setTimeout(()=>o.abort(),n),s;try{s=await fetch(r,{method:"GET",signal:o.signal})}catch(u){let f=u instanceof Error&&u.name==="AbortError"?` no response within ${n}ms.`:pt(u);throw new Error(`could not reach the enrollment page at ${e.cpOrigin}.${f}`)}finally{clearTimeout(a)}if(!s.ok){let u=`enrollment link lookup failed: ${e.cpOrigin} responded ${s.status} \u2014 the link may be expired or revoked; ask your admin for a fresh one.`;throw s.status>=400&&s.status<500&&s.status!==429?new ka(u):new Error(u)}let i;try{i=await s.json()}catch{throw new Error(`enrollment link lookup failed: ${e.cpOrigin} returned a malformed response`)}let l=(Array.isArray(i?.gateways)?i.gateways:[]).find(u=>u!==null&&typeof u=="object"&&fi(u.url)!==void 0),d=fi(l?.url);if(!d)throw new Error(i.connected===!0?"this enrollment link's gateway is running but hasn't advertised its public URL yet \u2014 ask your admin to set ANYRAY_GATEWAY_PUBLIC_URL (Helm: gateway.publicUrl), then re-run.":"this enrollment link has no gateway configured yet \u2014 ask your admin to confirm the gateway is deployed, then re-run.");return{gatewayUrl:d,deploymentId:fi(l?.deploymentId),org:fi(i.org),email:fi(i.email),seatMode:i.seatMode===!0,...i.provisioningKind==="manual"||i.provisioningKind==="mdm"?{provisioningKind:i.provisioningKind}:{},...i.provisioningProofMode==="managed-preference"?{provisioningProofMode:i.provisioningProofMode}:{},...Array.isArray(i.allowedDomains)?{allowedDomains:i.allowedDomains.filter(u=>typeof u=="string"&&u.length>0)}:{}}};var ke="0.11.182";var ih=1e4,go=e=>e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(go).join(",")}]`:`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${go(e[n])}`).join(",")}}`,CS="stable-key-heartbeat-v1",kS="key-heartbeat",tW=["reapply_config","remint","revert"],ch=(e,t)=>t&&e.payload.source==="mdm"?{machineUuid:t}:{};var vS=e=>QF("sha256").update(e).digest("hex"),je=e=>typeof e=="string"&&e.trim()?e.trim():void 0,nW=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"&&/^[a-z0-9-]{1,64}$/.test(t)):[],SS={no_mdm_server_registered:"no MDM server is registered in the Anyray console",agent_missing:"the Anyray endpoint agent is not reporting for this machine",mdm_not_verified:"this machine is not enrolled in the registered MDM",endpoint_unreachable:"the endpoint service could not be reached"},rW=e=>`This organization requires a managed (MDM-enrolled) device for this enrollment: ${SS[e]}. Ask your IT admin.`,oW=e=>typeof e=="string"&&e in SS,lh=async e=>{try{let t=await e.json(),n=je(t?.message),r=je(t?.error),o=oW(t?.reason)?t.reason:void 0;if(r==="managed_device_required"&&o)return{message:rW(o),code:r,reason:o};if(n)return{message:n,...r?{code:r}:{}}}catch{}return{message:`gateway responded ${e.status}`}},aW=async e=>(await lh(e)).message,ct=class extends Error{status;policyCode;reason;constructor(t,n){let r=typeof n=="string"?{message:n}:n;super(r.code==="managed_device_required"?r.message:`the gateway rejected this enrollment (HTTP ${t}): ${r.message}`),this.name="GatewayVerifyError",this.status=t,this.policyCode=r.code,this.reason=r.reason}},ES=e=>e instanceof ka||e instanceof ct&&e.policyCode==="sso_required",va=class extends Error{status;policyCode;reason;constructor(t,n){let r=typeof n=="string"?{message:n}:n;super(r.code==="managed_device_required"?r.message:`the gateway rejected this credential heartbeat (HTTP ${t}): ${r.message}`),this.name="GatewayHeartbeatError",this.status=t,this.policyCode=r.code,this.reason=r.reason}},dh=async(e,t,n,r)=>{try{return await r(go(e),t)}catch{throw new Error(`developer ${n} failed: could not sign the challenge with the provided private key`)}},wd=()=>{let{publicKey:e,privateKey:t}=eW("ed25519",{publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem"}});return{publicKeyPem:e,privateKeyPem:t}},qt=async(e,t,n,r={})=>{let o=r.timeoutMs??ih,a=`${e}/connect/verify`,s=je(t?.payload?.deploymentId);if(!s)throw new Error("developer verification failed: the cert is missing payload.deploymentId");let i={deploymentId:s,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),...ch(t,r.machineUuid)},c=await dh(i,n,"verification",r.signer??Ir),l=new AbortController,d=setTimeout(()=>l.abort(),o),u;try{u=await fetch(a,{method:"POST",headers:{"content-type":"application/json","x-anyray-connect-version":ke},body:JSON.stringify({cert:t,challenge:i,sig:c,...r.health?{health:r.health}:{},...r.ack?{ack:r.ack}:{},...r.telemetryOnly?{telemetryOnly:!0}:{}}),signal:l.signal})}catch(w){let b=w instanceof Error&&w.name==="AbortError"?` no response within ${o}ms.`:pt(w);throw new Error(`could not reach the gateway at ${a}.${b}`,{cause:w})}finally{clearTimeout(d)}if(!u.ok)throw new ct(u.status,await lh(u));let f;try{f=await u.text()}catch{f=""}let p;try{p=JSON.parse(f)}catch{let w=u.headers.get("content-type")??"",b=/\btext\/html\b/i.test(w)||/^\s*<(?:!doctype|html)/i.test(f);throw new Error(b?`developer verification failed: ${a} returned an HTML page, not the gateway \u2014 /connect/* is being routed to the console/proxy. Ask your admin to route /connect/* to the gateway service (:8787), the same as /v1/*.`:"developer verification failed: the gateway returned a malformed response")}let m=je(p?.key);if(!m)throw new Error("developer verification failed: the gateway response is missing the key");if(!/^[A-Za-z0-9._-]{1,256}$/.test(m))throw new Error("developer verification failed: the gateway returned a malformed key");let h=je(p.user);if(!h)throw new Error("developer verification failed: the gateway response is missing the user");let g=sW(p.directive),y=nW(p.capabilities);return{key:m,user:h,team:je(p.team),expiresAt:je(p.expiresAt),...y.length>0?{capabilities:y}:{},...g?{directive:g}:{}}},IS=async(e,t,n,r,o={})=>{let a=o.timeoutMs??ih,s=`${e}/connect/key/heartbeat`,i=je(n?.payload?.deploymentId);if(!i)throw new Error("developer heartbeat failed: the cert is missing payload.deploymentId");let c={deploymentId:i,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),purpose:kS,...ch(n,o.machineUuid)},l=await dh(c,r,"heartbeat",o.signer??Ir),d=new AbortController,u=setTimeout(()=>d.abort(),a),f;try{f=await fetch(s,{method:"POST",headers:{"content-type":"application/json","x-anyray-api-key":t,"x-anyray-connect-version":ke},body:JSON.stringify({cert:n,challenge:c,sig:l}),signal:d.signal})}catch(h){let g=h instanceof Error&&h.name==="AbortError"?` no response within ${a}ms.`:pt(h);throw new Error(`could not reach the gateway at ${s}.${g}`,{cause:h})}finally{clearTimeout(u)}if(!f.ok)throw new va(f.status,await lh(f));let p;try{p=await f.json()}catch{throw new Error("developer heartbeat failed: the gateway returned a malformed response")}let m=je(p.expiresAt);if(!m||!Number.isFinite(Date.parse(m))||p.credentialMode!==CS||p.key!==void 0)throw new Error("developer heartbeat failed: the gateway returned an unexpected response");return{expiresAt:m,credentialMode:CS}},xS=async(e,t,n,r,o,a={})=>{let s=a.timeoutMs??ih,i=`${e.replace(/\/$/,"")}/connect/machine`,c=je(n?.payload?.deploymentId);if(!c||!o)return!1;let l={deploymentId:c,issuedAt:new Date().toISOString(),nonce:sh(16).toString("hex"),purpose:kS,...ch(n,o)},d=await dh(l,r,"heartbeat",a.signer??Ir),u=new AbortController,f=setTimeout(()=>u.abort(),s);try{return(await fetch(i,{method:"POST",headers:{"content-type":"application/json","x-anyray-api-key":t,"x-anyray-connect-version":ke},body:JSON.stringify({cert:n,challenge:l,sig:d,machineUuid:o}),signal:u.signal})).ok}catch(p){return console.error("connect machine report skipped:",p instanceof Error?p.name:"error"),!1}finally{clearTimeout(f)}},sW=e=>{if(e===null||typeof e!="object")return null;let t=e,n=je(t.id),r=t.kind;return!n||!/^[A-Za-z0-9_-]{1,128}$/.test(n)||typeof r!="string"||!tW.includes(r)?null:{id:n,kind:r}},iW=1e4,cW=e=>{if(e===null||typeof e!="object")return!1;let t=e;if(t.alg!=="Ed25519"||!je(t.sig))return!1;let n=t.payload;if(n===null||typeof n!="object")return!1;let r=n;return typeof r.v=="number"&&!!je(r.deploymentId)&&!!je(r.user)&&!!je(r.devPublicKey)&&!!je(r.issuedAt)&&!!je(r.expiresAt)},lW=async(e,t,n,r={},o={})=>{let a=o.timeoutMs??iW,s=`${e}/v1/enroll`,i=new AbortController,c=setTimeout(()=>i.abort(),a),l;try{l=await fetch(s,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({token:t,devPublicKey:n,...r.email?{email:r.email}:{},...r.team?{team:r.team}:{},...r.machineId?{machineId:r.machineId}:{},...r.deploymentId?{deploymentId:r.deploymentId}:{}}),signal:i.signal})}catch(u){let f=u instanceof Error&&u.name==="AbortError"?` no response within ${a}ms.`:pt(u);throw new Error(`could not reach the control plane at ${s}.${f}`)}finally{clearTimeout(c)}if(!l.ok){let u=`enrollment failed: ${await aW(l)}`;throw l.status>=400&&l.status<500&&l.status!==429?new ka(u):new Error(u)}let d;try{d=await l.json()}catch{throw new Error("enrollment failed: the control plane returned a malformed response")}if(!cW(d))throw new Error("enrollment failed: the control plane returned an unexpected cert shape");return d},RS=(e,t,n,r,o,a,s)=>{if(!e)return!1;let i=t?Date.parse(t):NaN;return!(!Number.isFinite(i)||i<=r||n&&e.payload.deploymentId!==n||o&&o!==a||s&&e.payload.user.trim().toLowerCase()!==s.trim().toLowerCase())},OS=async e=>{let t={timeoutMs:e.timeoutMs,machineUuid:e.machineUuid,signer:e.signer},{cert:n,privateKeyPem:r,publicKeyPem:o}=e.reuse?e.reuse:await(async()=>{let s=wd();return{cert:await lW(e.cpOrigin,e.token,s.publicKeyPem,{email:e.email,team:e.team,machineId:e.machineId,deploymentId:e.deploymentId},t),...s}})(),a=await qt(e.gatewayOrigin,n,r,t);return{clientKey:a.key,user:a.user,team:a.team,expiresAt:a.expiresAt,...a.capabilities?{capabilities:a.capabilities}:{},cert:n,privateKeyPem:r,publicKeyPem:o}};var uh=1e4,dW=900*1e3,_S="tnt_",uW=/^\/sso\/([^/]+)\/?$/,pW=/^\/i\/([^/]+)\/?$/,fW=e=>{let t=e.match(uW);if(t)return t[1];let n=e.match(pW);return n?.[1].startsWith(_S)?n[1]:void 0},Et=e=>{let t=e.trim();if(!t)return;let n;try{n=new URL(t)}catch{n=void 0}if(n){if(n.protocol!=="http:"&&n.protocol!=="https:")return;let r=fW(n.pathname);return r?{cpOrigin:n.origin,tenantId:r}:void 0}if(t.startsWith(_S))return{cpOrigin:Kn(),tenantId:t}},wo=class extends Error{kind;status;constructor(t,n,r){super(n),this.name="SsoStartError",this.kind=t,this.status=r}},Bt=class extends Error{kind;constructor(t,n){super(n),this.name="SsoPollError",this.kind=t}},ph=async(e,t,n,r)=>{let o=new AbortController,a=setTimeout(()=>o.abort(),n);try{let s=await r(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:o.signal}),i={};try{i=await s.json()}catch{}return{status:s.status,json:i}}finally{clearTimeout(a)}},mW=e=>new Promise(t=>setTimeout(t,e)),bd=async e=>{let t=e.now??Date.now,n=e.fetch??fetch,{publicKeyPem:r,privateKeyPem:o}=(e.generateKeypair??wd)(),a;try{a=await ph(`${e.cpOrigin}/sso/device`,{tenantId:e.tenantId,devPublicKey:r},uh,n)}catch(m){throw new wo("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(m)}`)}if(a.status!==200){let m=a.status===404,h=typeof a.json.error=="string"?a.json.error:`status ${a.status}`;throw new wo(m?"sso-unavailable":"cp-unreachable",`SSO is not available for this organization (${h}). Ask your admin to confirm SSO is configured.`,a.status)}let s=a.json;if(!s.device_code||!s.user_code||!s.verification_uri_complete)throw new wo("cp-unreachable","SSO start failed: the control plane returned an incomplete response.");let i=t(),c=e.deadlineMs??dW,l=typeof s.expires_in=="number"&&s.expires_in>0?s.expires_in*1e3:c,d=typeof s.verification_uri=="string"?s.verification_uri:void 0,u=e.gatewayUrl??(typeof s.gateway_url=="string"?s.gateway_url:void 0),f={cpOrigin:e.cpOrigin,tenantId:e.tenantId,deviceCode:s.device_code,userCode:s.user_code,verificationUri:d,verificationUriComplete:s.verification_uri_complete,intervalMs:Math.max(1,s.interval||5)*1e3,grantExpiresAt:i+Math.min(c,l),startedAt:i,privateKeyPem:o,publicKeyPem:r,gatewayUrl:u},p=e.log??(()=>{});return p("To finish, sign in with your organization at:"),p(` ${f.verificationUriComplete}`),p(`Confirm this code matches your browser: ${f.userCode}`),hW(f.verificationUriComplete,e.cpOrigin)&&e.open?.(f.verificationUriComplete),f},hW=(e,t)=>{try{return new URL(e).origin===new URL(t).origin}catch{return!1}},Ad=async(e,t={})=>{let n=t.now??Date.now,r=t.sleep??mW,o=t.fetch??fetch,a=t.pollIntervalMs??e.intervalMs;for(;n()<e.grantExpiresAt&&(await r(Math.min(a,e.grantExpiresAt-n())),!(n()>=e.grantExpiresAt));){let s;try{s=await ph(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.deviceCode,devPublicKey:e.publicKeyPem},uh,o)}catch(c){throw new Bt("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(c)}`)}if(s.status===200&&s.json.cert)return{cert:s.json.cert,privateKeyPem:e.privateKeyPem,gatewayUrl:t.gatewayUrl??(typeof s.json.gatewayUrl=="string"?s.json.gatewayUrl:e.gatewayUrl),deploymentId:typeof s.json.deploymentId=="string"?s.json.deploymentId:""};let i=typeof s.json.error=="string"?s.json.error:"";if(i!=="authorization_pending"){if(i==="slow_down"){a+=5e3;continue}throw i==="expired_token"?new Bt("expired","SSO sign-in timed out before you finished. Re-run anyray-connect --sso to try again."):new Bt("denied","SSO sign-in was not completed. Re-run anyray-connect --sso to try again.")}}throw new Bt("expired","SSO sign-in timed out. Re-run anyray-connect --sso to try again.")};var TS="sdc_",PS=e=>{let t=e.trim();if(!t)return;if(t.startsWith(TS))return{cpOrigin:Kn(),claim:t};let n;try{n=new URL(t)}catch{return}if(!rh(n.origin))return;let r=n.searchParams.get("claim")?.trim();if(!(!r||!r.startsWith(TS)))return{cpOrigin:n.origin,claim:r}},DS=async e=>{let t=e.fetch??fetch,{publicKeyPem:n,privateKeyPem:r}=(e.generateKeypair??wd)(),o;try{o=await ph(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.claim,devPublicKey:n},uh,t)}catch(s){throw new Bt("cp-unreachable",`could not reach the control plane at ${e.cpOrigin}${pt(s)}`)}if(o.status===200&&o.json.cert)return{cert:o.json.cert,privateKeyPem:r,gatewayUrl:e.gatewayUrl??(typeof o.json.gatewayUrl=="string"?o.json.gatewayUrl:void 0),deploymentId:typeof o.json.deploymentId=="string"?o.json.deploymentId:"",...typeof o.json.ssoLink=="string"&&o.json.ssoLink?{ssoLink:o.json.ssoLink}:{}};let a=typeof o.json.error=="string"?o.json.error:"";throw a==="expired_token"?new Bt("expired","This enrollment link has expired. Open your organization\u2019s Anyray link again to get a new one."):a==="authorization_pending"?new Bt("denied","This enrollment link is not ready yet. Finish signing in in your browser, then run the command it gives you."):new Bt("denied","This enrollment link was already used or is not valid. Open your organization\u2019s Anyray link again to get a new one.")};import{readFile as yW}from"node:fs/promises";import{isAbsolute as gW,posix as LS,win32 as fh}from"node:path";var hi=(e=process.platform,t=process.env)=>e==="darwin"?LS.join("/Library","Application Support","Anyray","bootstrap.json"):e==="win32"?fh.join(t.ProgramData??"C:\\ProgramData","Anyray","bootstrap.json"):LS.join("/etc","anyray","bootstrap.json"),wW=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),NS=e=>typeof e=="string"&&e.length>0&&e.length<=512&&[...e].every(t=>{let n=t.charCodeAt(0);return n>=32&&n!==127})&&(gW(e)||fh.isAbsolute(e))&&!/ark_[A-Za-z0-9_-]{20,}|-----BEGIN/.test(e),bW=e=>{if(typeof e!="string"||e.length===0||e.length>512)return!1;try{let t=new URL(e);return(t.protocol==="https:"||t.protocol==="http:")&&!t.username&&!t.password}catch{return!1}},xr=async(e=hi())=>{try{let t=await yW(e,"utf-8");if(t.length>4096)return;let n=JSON.parse(t);if(!wW(n)||n.v!==1||typeof n.sso!="string")return;let r=Et(n.sso);if(!r)return;let o=bW(n.gateway)?n.gateway:void 0,a=NS(n.bin)?n.bin:void 0;return{sso:`${r.cpOrigin}/sso/${r.tenantId}`,gateway:o,bin:a}}catch{return}},$S=(e,t,n)=>{let r=Et(e);if(!r)throw new Error("invalid --sso link");if(n!==void 0&&!NS(n))throw new Error("--bin must be an absolute fleet-stable path");if(n!==void 0&&fh.isAbsolute(n)&&/^[A-Za-z]:\\/.test(n)&&!/^[A-Za-z]:\\Program Files( \(x86\))?\\/i.test(n))throw new Error("--bin on Windows must live under Program Files (admin-only writable)");return`${JSON.stringify({v:1,sso:`${r.cpOrigin}/sso/${r.tenantId}`,...t?{gateway:t}:{},...n?{bin:n}:{}},null,2)}
262
262
  `};var Sa=(e,t)=>t.NO_COLOR?!1:t.FORCE_COLOR&&t.FORCE_COLOR!=="0"?!0:!!e.isTTY,Cd=Sa(process.stdout,process.env),MS=Sa(process.stderr,process.env),Ea=(e,t,n)=>n?`\x1B[${e}m${t}\x1B[0m`:t,j=e=>Ea("1",e,Cd),v=e=>Ea("2",e,Cd),AW=e=>Ea("32",e,Cd),CW=e=>Ea("33",e,MS),kW=e=>Ea("31",e,MS),ze=e=>Ea("36",e,Cd),A=e=>console.log(e),H=e=>console.log(`
263
263
  ${j(e)}`),N=e=>console.log(v(e)),B=e=>console.log(`${AW("\u2713")} ${e}`),_=e=>console.error(`${CW("!")} ${e}`),R=e=>console.error(`${kW("\u2717")} ${e}`);var hh=`${j("anyray-connect managed")} \u2014 fleet-wide Claude Code routing via managed-settings.json
264
264
 
@@ -800,7 +800,7 @@ Exit codes:
800
800
  `)}
801
801
  `;switch(e.kind){case"ssh":return{command:"ssh",args:["-T","--",e.name,"sh","-s"],stdin:n};case"devcontainer":return{command:"docker",args:["exec","-i",e.name,"sh","-s"],stdin:n};case"wsl":return{command:"wsl.exe",args:["-d",e.name,"--","sh","-s"],stdin:n};case"codespace":return{command:"gh",args:["codespace","ssh","-c",e.name,"--","sh -s"],stdin:n}}},s5=(e,t,n)=>{let r=[n,"--yes","--key-stdin","--gateway",t.gateway,...t.user!==void 0?["--user",t.user]:[],...t.team!==void 0?["--team",t.team]:[]],o=[Ja(n),"--yes","--key-stdin","--gateway",Ja(t.gateway),...t.user!==void 0?["--user",Ja(t.user)]:[],...t.team!==void 0?["--team",Ja(t.team)]:[]].join(" "),a=`${t.clientKey}
802
802
  `;switch(e.kind){case"ssh":return{command:"ssh",args:["-T","--",e.name,o],stdin:a};case"devcontainer":return{command:"docker",args:["exec","-i",e.name,...r],stdin:a};case"wsl":return{command:"wsl.exe",args:["-d",e.name,"--",...r],stdin:a};case"codespace":return{command:"gh",args:["codespace","ssh","-c",e.name,"--",o],stdin:a}}},i5=n5(e5),c5=async(e,t)=>(await i5(e,[...t],{encoding:"utf8"})).stdout.toString(),Ag=async(e,t={})=>{let n=typeof e=="string"?{name:e}:e,r=n.ref??(/[/\\]/.test(n.name)?n.name:void 0);if(!r)throw new Error("Cannot resolve a dev container by its bare name; use its full host path.");let a=(await(t.exec??c5)("docker",["ps","--filter",`label=devcontainer.local_folder=${r}`,"--format","{{.ID}}"])).split(`
803
- `).map(s=>s.trim()).find(Boolean);if(!a)throw new Error("No running dev container matches the discovered workspace.");return a},FR=(e,t,n)=>new Promise(r=>{let o;try{o=t(e.command,e.args,{stdio:["pipe",n?"pipe":"inherit","inherit"]})}catch{r({code:1,stdout:""});return}let a="",s=!1,i=c=>{s||(s=!0,r({code:c,stdout:a}))};if(o.stdout?.on("data",c=>{a+=c.toString("utf-8")}),o.once("error",()=>i(1)),o.once("close",c=>i(c??1)),!o.stdin){i(1);return}o.stdin.end(e.stdin)}),Cg=async(e,t,n={})=>{let r=n.spawn??t5,o=e.kind==="devcontainer"&&e.ref?{...e,name:await Ag(e,n)}:e,a=await FR(a5(o),r,!0);if(a.code!==0)return a.code;let s=a.stdout.split(`
803
+ `).map(s=>s.trim()).filter(Boolean);if(a.length===0)throw new Error("No running dev container matches the discovered workspace.");if(a.length>1)throw new Error(`${a.length} running dev containers match this workspace; stop the stale one (docker ps --filter label=devcontainer.local_folder=...) and re-run.`);return a[0]},FR=(e,t,n)=>new Promise(r=>{let o;try{o=t(e.command,e.args,{stdio:["pipe",n?"pipe":"inherit","inherit"]})}catch{r({code:1,stdout:""});return}let a="",s=!1,i=c=>{s||(s=!0,r({code:c,stdout:a}))};if(o.stdout?.on("data",c=>{a+=c.toString("utf-8")}),o.once("error",()=>i(1)),o.once("close",c=>i(c??1)),!o.stdin){i(1);return}o.stdin.end(e.stdin)}),Cg=async(e,t,n={})=>{let r=n.spawn??t5,o=e.kind==="devcontainer"&&e.ref?{...e,name:await Ag(e,n)}:e,a=await FR(a5(o),r,!0);if(a.code!==0)return a.code;let s=a.stdout.split(`
804
804
  `).map(c=>c.trim()).filter(Boolean).at(-1);return s?(await FR(s5(o,t,s),r,!1)).code:1};import{spawnSync as l5}from"node:child_process";import{platform as xu}from"node:os";import{basename as d5}from"node:path";import{createInterface as u5}from"node:readline";var UR=`${j("anyray-connect")} \u2014 point your local coding tools at the Anyray gateway
805
805
 
806
806
  ${j("Usage")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anyray-connect",
3
- "version": "0.11.180",
3
+ "version": "0.11.182",
4
4
  "description": "Anyray connect \u2014 points local coding tools (Claude Code, Cursor, Windsurf, SDKs) at the Anyray gateway through supported configuration and enrolled personal authentication.",
5
5
  "type": "module",
6
6
  "bin": {