anyray-connect 0.11.178 → 0.11.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- 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<ZM;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 zM(e,r.raw,o))return"written"}catch{return"failed"}}return"failed"},rv=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 rv(e))for(let r of await rv(re(e,n)))t.push(re(e,n,r));return t},qM=e=>Array.isArray(e.skills)?e.skills.filter(t=>it(t)&&ci(t.name)&&t.creatorType==="user"&&t.syncManaged===!1):[],QM=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 qM(o.value))n.push({account:a,packageDir:r,entry:s})}return n},eB=async e=>{let t=await uo(re(e,".claude-plugin","plugin.json"));return!!t&&ci(t.value.name)},tB=(e,t)=>{let n=Pm(t)?Xt(t):Xt(e,t);if(!cv(e,n)||n===Xt(e))return;let r=Zl(Xt(e),n);return r.length>0?{absolute:n,relative:r}:void 0},nB=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=tB(o,l.installPath);!d||!await eB(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},rB=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)))},uv=async e=>{let[t,n,r]=await Promise.all([QM(e),nB(e),rB(e)]);return{skills:t,plugins:n,localMcpServers:r}},Lm=async e=>{let t=await uv(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)}},ov=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)},oB=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?sv:ii)}}};await t(e),await V.chmod(e,Cn)},pv=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 pv(re(e,s),re(t,s)))return!1}return!0}catch{return!1}},fv=e=>`${e}.anyray-incomplete`,mv=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(!dv(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)<=Dm)return}let u=re(e,lv(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{}})()},iv);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{}}}},hv=async e=>{let t=await mv(e,!1);t&&await t.complete()},aB=async(e,t,n)=>{let r=fv(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 hv(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 mv(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(y){if(!vt(y)||y.code!=="EEXIST")throw y;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,jM.COPYFILE_EXCL);let m=await V.stat(f);await V.chmod(p,(m.mode&73)!==0?sv:ii)}catch(m){if(!vt(m)||m.code!=="EEXIST")throw m;if(!await pv(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")},yv=async(e,t,n,r)=>{if(!await ov(e))return"invalid";try{let a=await V.lstat(t);if(!a.isDirectory()||a.isSymbolicLink())return"conflict";if(await Jl(e,t))return await hv(fv(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 ov(o)?(await oB(o),await n?.(t),await aB(o,t,r)):"invalid"}catch{return"failed"}finally{try{await V.rm(o,{recursive:!0,force:!0})}catch{}}},av=(e,t,n)=>n||!t?e:e.filter(r=>r.account.startsWith(t)),sB=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"}},iB=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"}},cB=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 yv(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(y=>it(y)&&typeof y.name=="string"&&y.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}},gv=(e,t)=>({...e,installPath:t}),lB=(e,t,n,r,o)=>{if(typeof r.installPath!="string")return!1;let a=Pm(r.installPath)?Xt(r.installPath):Xt(o,r.installPath),s=gv(e,Zl(Xt(t),Xt(n))),i={...r,installPath:Zl(Xt(o),a)};return Xl(s,i)},dB=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}}})},uB=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(!cv(a,l)){n.invalid+=1;continue}let d=await yv(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 y=it(m.plugins)?m.plugins:{},g=y[c.id],h=Array.isArray(g)?g:[],w=h.find(k=>it(k)&&k.scope==="user");if(w){u=lB(c.entry,wa(c.settingsFile),c.packageDir,w,t),f=!u;return}let b=gv(c.entry,l);return{...m,version:typeof m.version=="number"?m.version:2,plugins:{...y,[c.id]:[...h,b]}}})==="failed"?n.failed+=1:f?n.conflicts+=1:await dB(c.settingsFile,i,c.id)==="failed"?n.failed+=1:u||d==="present"?n.alreadyPresent+=1:n.migrated+=1}},pB=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}},wv=async(e,t,n={})=>{let r=await uv(e),o=_m("skill"),a=_m("plugin"),s=_m("local-mcp"),i=[],c=[],l=av(r.skills,n.account,n.allAccounts),d=av(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 sB(t);f.state==="found"?await cB(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 iB(t);f.state==="found"?await uB(d,f.path,a,n.beforeDirectoryPublish,n.afterDirectoryClaim):f.state==="missing"?i.push("plugin"):(a.conflicts+=d.length,c.push("plugin"))}await pB(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 hB=async e=>{try{return await St.access(e),!0}catch{return!1}},bv=448,yB=384,Cv={code:"claude-code-sessions",cowork:"local-agent-mode-sessions"},gB=["code","cowork"],Mm=(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.",Nm=e=>({lane:e,migrated:0,alreadyPresent:0,skippedNoTranscript:0,failed:0}),kv=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},wB=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[]}},bB=async(e,t)=>{let n=await kv(zt(e,Cv[t])),r=[];for(let o of n){let a=await wB(o);a.length>0&&r.push({dir:o,ids:a,account:o.split(mB).slice(-2)[0]})}return r},AB=async(e,t)=>{if(t==="cowork"){let r=await Ol(e);return r.ok?{dir:r.dir}:{missing:r.reason}}let n=await kv(zt(e,Cv.code));return n.length===1?{dir:n[0]}:{missing:n.length===0?"no-account":"ambiguous"}},CB=async(e,t)=>{let n=`${t}.anyray-tmp-${process.pid}`;await St.copyFile(e,n),await St.chmod(n,yB),await St.rename(n,t)},kB=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",em(r),`${o}.jsonl`)),!0)}catch{return!1}},vB=async(e,t,n,r)=>{let o=Nm(e),a=await tm(n);for(let s of t)await SB(e,s,n,r,a,o);return o},SB=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 kB(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:bv});for(let f of u)await St.cp(zt(l,f),zt(d,f),{recursive:!0,force:!1,errorOnExist:!0});await St.chmod(d,bv)}await CB(c,zt(n,i)),o.add(s),a.migrated+=1}catch{a.failed+=1}}},Av=(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
|
`)}},$m=e=>new Set(e.flatMap(t=>t.sources.map(n=>n.account))),vv=async e=>{let t=[];for(let n of gB)t.push({lane:n,sources:await bB(e,n)});return t},Sv=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([vv(t),Lm(t)]),o=n.reduce((s,i)=>s+i.sources.reduce((c,l)=>c+l.ids.length,0),0),a=$m(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??fB)(),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([vv(n),Lm(n)]),s;if(e.account){let p=e.account;for(let g of o)g.sources=g.sources.filter(h=>h.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 y=$m(o);for(let g of m)y.add(g);if(y.size>1)return Av(o,e.command??"anyray-connect desktop --migrate",`"${p}" matches ${y.size} accounts`,m);s=[...y]}else if(!e.allAccounts){let p=$m(o);for(let m of a.accounts)p.add(m);if(p.size>1)return Av(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 hB(r),l=await wv(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(Nm(p));continue}let y=await AB(r,p);if("missing"in y){u.push({lane:p,reason:y.missing,waiting:m.reduce((g,h)=>g+h.ids.length,0)}),d.push(Nm(p));continue}d.push(await vB(p,m,y.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:Mm(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 EB=e=>[Le(e)],Ev=e=>({id:e.id,title:e.title,automatic:!1,async detect(){let t=[...EB(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 Iv="1.21459.0",OB=RB(IB),TB=async e=>{try{let{stdout:t}=await OB("/usr/bin/plutil",["-extract","CFBundleShortVersionString","raw","-o","-",e],{timeout:2e3,maxBuffer:4096});return String(t).trim()||void 0}catch{return}},_B=async e=>{try{return await xB(e)}catch{return}},xv="No native config was written; use Developer \u2192 Configure Third-Party Inference \u2192 Apply locally.",PB=["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?(Rv??=Ov({}),Rv):Ov(e),Rv,Ov=async e=>{let t=(e.home??di)(),n=["/Applications/Claude.app",kn(t,"Applications","Claude.app")],r=e.readClaudeAppVersion??TB,o=e.readClaudeAppBundle??_B;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} ${xv}`}),c=xl(s,Iv);if(c===void 0)return i("its version string could not be interpreted.");if(c<0)return i(`automatic local setup requires ${Iv} or newer.`);let l=await o(kn(a,"Contents","Resources","app.asar"));return l?uk.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. ${xv}`}},ed="anyray",Pv="--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")},Hm=(e={})=>kn((e.home??di)(),"Library","Application Support","Claude","claude_desktop_config.json"),Dv=()=>{let e=Ge("profile");return{command:e.command,args:[...e.args,Pv]}},fo=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Lv=(e,t)=>{let n=Object.keys(e).sort(),r=[...t].sort();return n.length===r.length&&n.every((o,a)=>o===r[a])},DB=(e,t)=>Array.isArray(e)&&e.length===t.length&&e.every((n,r)=>typeof n=="string"&&n===t[r]),LB=e=>{if(!fo(e)||!Lv(e,["command","args"]))return!1;let t=Dv();return e.command===t.command&&DB(e.args,t.args)},NB=e=>fo(e)&&Array.isArray(e.args)&&e.args.at(-1)===Pv,$B=e=>{if(!fo(e)||!Lv(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))},MB=e=>e===void 0?"absent":LB(e)?"exact":NB(e)||$B(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:MB(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.`)},Nv=(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},Fm=async(e,t)=>{if(Bm(e.entry,t))return;let n=await mo(e.path);if(!Bm(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,Nv(n.json,t)),{reading:e,afterEntry:t}},Wm=async e=>{let t=await mo(e.reading.path);if(!Bm(t.entry,e.afterEntry))throw new Fe(`The MCP configuration in ${e.reading.path} changed before rollback; the newer value was preserved.`);let n=Nv(t.json,e.reading.entry);await Wn(e.reading.path,n)},BB=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=Hm(e),r=(e.platform??Er)()==="darwin"&&n!==t.path?await mo(n):void 0;return r&&nd(r),{active:t,...r?{legacy:r}:{}}},Tv=async e=>{let t=await mo(td(e));nd(t);let n=Hm(e),r=(e.platform??Er)()==="darwin"&&n!==t.path?await mo(n):void 0;return r&&nd(r),{active:t,...r?{legacy:r}:{}}},FB=async e=>{let t=[];try{let n=await Fm(e.active,Dv());if(n&&t.push(n),e.legacy&&e.legacy.ownership!=="absent"){let r=await Fm(e.legacy,void 0);r&&t.push(r)}}catch(n){let r=[];for(let o of[...t].reverse())await Wm(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 Wm(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)}}},WB=async e=>{let t=[];try{for(let n of[e.active,e.legacy].filter(r=>!!r)){if(n.ownership==="absent")continue;let r=await Fm(n,void 0);r&&t.push(r)}}catch(n){let r=[];for(let o of[...t].reverse())await Wm(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)},_v=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)."]},UB={darwinAppName:"Claude",darwinBundleId:"com.anthropic.claudefordesktop",win32Image:"Claude.exe",win32Install:[{root:"localAppData",path:"Programs\\Claude\\Claude.exe"}]},rd="claude-desktop",Um="migrate",$v=new Set(["app-running","store-missing"]),HB={code:{one:"Claude Code session",many:"Claude Code sessions"},cowork:{one:"Cowork task",many:"Cowork tasks"}},GB={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"}},VB="Claude Desktop machine policy could not be read; Connect left inference and retrieval configuration unchanged.",Mv=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"}},Bv=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=HB[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.`:"")},Fv=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=GB[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=Mv(e),r=await(e.pendingDesktopMigrationCount??Sv)(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=Bv(a.lanes),l=Fv(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,Um);let y=f.reduce((w,b)=>w+b.waiting,0),g=[y>0?`${y} more session${y===1?"":"s"}`:"",p.length>0?`${p.length} extension ${p.length===1?"store":"stores"}`:""].filter(Boolean),h=[...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]:[],...h]}if(!$v.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,Um);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."]}},KB=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."]}},jB=e=>Ev({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:",..._v(t)]:["Claude desktop org/API lane:",..._v(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`."]}),ZB=(e={})=>{let t=jB(e),n=()=>(e.platform??Er)()==="darwin",r=()=>(e.platform??Er)()==="win32",o=(s,i)=>n()?bk(s,i,e):zk(s,s.clientKey??"",i,e),a=s=>n()?Ak(s,e):qk(s,e);return{...t,automatic:!0,changesOrgManagement:!0,quitGated:{isRunning:()=>(e.appRunning??ga((e.platform??Er)()))(),quitTarget:UB,needsTarget:()=>!1,async complete(s){if(s!==Um)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)(Mv(e));if(i.ok){let c=Bv(i.lanes),l=Fv(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(y=>y.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(y=>!!y):["No portable Claude Desktop data was left to bring across."]}}return $v.has(i.kind)?{status:"queued",messages:[i.reason]}:{status:"manual",messages:[i.reason,i.remedy]}}},async usesDynamicCredential(s){return n()?kk(s,e):r()?tv(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:[um(p),...await li(e,i)]}}if(r()){let f;try{f=await Sr(e.runReg??Hn)}catch{return{status:"manual",manualAudience:"admin",messages:[VB,...await li(e,i)]}}if(f)return{status:"manual",manualAudience:"admin",messages:[Rm(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 BB(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 FB(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()?PB:[]],changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])]}},async revert(s){let i=td(e),c=await KB(s),l=y=>c.length===0?y:{...y,messages:[...y.messages,...c]};if(!n()&&!r())return l(await t.revert(s));let d;try{d=await Tv(e)}catch(y){return l({status:"manual",messages:[y instanceof Fe?y.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 y=d.legacy;return l({...u,messages:[...u.messages,...d.active.ownership!=="absent"?[`Would remove the owned Anyray retrieval MCP server from ${i}.`]:[],...y&&y.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${y.path}.`]:[]]})}let f=await a({dryRun:!1});if(f.status==="manual"){let y=r()?Mt(e):void 0;if(!(y!==void 0&&f.changedFiles?.includes(y)===!0&&!await x(y)))return l(f)}let p;try{p=await WB(await Tv(e))}catch(y){let g=y instanceof Fe?y.changedFiles:[];return l({status:"manual",changedFiles:[...new Set([...f.changedFiles??[],...g])],messages:[...f.messages,y instanceof Fe?y.message:"Restored Claude Desktop inference, but could not safely remove its retrieval MCP registration. Re-run revert."]})}await ce(i);let m=Hm(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?fm(s,e):!1:r()?ev(s,e):!1},async inferenceAuthLanes(){try{if(n()){if(!(await ba(e)).supported)return["unknown"];let s=await Ck(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}}}},Wv=ZB();import{homedir as CF}from"node:os";import{join as kF}from"node:path";import{rm as pd}from"node:fs/promises";import{constants as Uv,accessSync as YB,statSync as JB}from"node:fs";import{platform as Gm}from"node:os";import{delimiter as XB,posix as zB,resolve as qB,win32 as QB}from"node:path";var eF="0.59.0",tF="1.1.4",Gn="Anyray \xB7 Claude",Vn="Anyray \xB7 Codex",od="__anyray-acp-agent",Hv=(e,t,n)=>{let{command:r,args:o}=nn([od,e,t,n]);return{command:r,args:o,env:{}}},ad=(e=Gm())=>e==="win32"?"npx.cmd":"npx",sd=(e=process.env.PATH,t=Gm())=>{if(!e)return;let n=ad(t);for(let r of e.split(XB)){let o=r.trim().replace(/^"|"$/g,"");if(!o)continue;let a=qB(o,n);try{if(!JB(a).isFile())continue;return YB(a,t==="win32"?Uv.F_OK:Uv.X_OK),a}catch{}}},id=(e,t=Gm())=>{let n=t==="win32"?QB:zB;return!n.isAbsolute(e)||n.basename(e).toLowerCase()!==ad(t)?!1:t!=="win32"||!/["&|<>^%!\r\n]/.test(e)},nF="https://chatgpt.com/backend-api/codex",rF="chatgpt-account-id,originator,session_id,user-agent,x-codex-turn-metadata,x-codex-window-id,x-client-request-id",Gv="ANYRAY_ACP_CODEX_AUTHORIZATION",Vv="ANYRAY_ACP_CODEX_CLIENT_KEY",Kv="ANYRAY_ACP_CODEX_METADATA",jv=e=>fe({...e.metadata,tool:e.metadata.tool??"codex",intent:e.metadata.intent??"jetbrains-acp",intentLabel:e.metadata.intentLabel??"JetBrains / Devin via Codex ACP"}),oF=(e,t={})=>{let n=ee(e,"openai"),r=n?{"x-anyray-auth-mode":"passthrough","x-anyray-custom-host":nF,"x-anyray-forward-headers":rF}:{},o=n?{...e.clientKey?{"x-anyray-api-key":Vv}:{}}:{Authorization:Gv};return jv(e)&&(o["x-anyray-metadata"]=Kv),{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}}}:{}}},aF=e=>{let t=ee(e,"openai"),n=jv(e);return{...t?e.clientKey?{[Vv]:e.clientKey}:{}:{[Gv]:`Bearer ${e.clientKey??e.placeholderKey}`},...n?{[Kv]:n}:{}}},Zv=(e,t=ad(),n={})=>({[Gn]:{command:t,args:["--yes",`@agentclientprotocol/claude-agent-acp@${eF}`],env:rn(e).env},[Vn]:{command:t,args:["--yes",`@agentclientprotocol/codex-acp@${tF}`],env:{CODEX_CONFIG:JSON.stringify(oF(e,n)),...aF(e)}}}),ui=(e=ad(),t="jetbrains")=>({[Gn]:Hv("claude",e,t),[Vn]:Hv("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 sF}from"node:zlib";import{open as iF,readFile as Ym,readdir as ud}from"node:fs/promises";import{dirname as Yv,join as me}from"node:path";import{homedir as qv,platform as Jm}from"node:os";var ld="2025.3.2",Aa="253.30387.147",pi="com.intellij.ml.llm",Vm=new Set(["ml-llm","llm","aia","ai-assistant","jetbrains-ai-assistant"]),cF=1e4,lF=256*1024*1024,dF=16*1024*1024,Km=1024*1024,jm=22,uF=jm+65535,Zm=xl,pF=()=>{let e=qv(),t=me(e,".cache","JetBrains","RemoteDev");switch(Jm()){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"}]}},fF=()=>Jm()==="linux"?me(qv(),".local","share","JetBrains"):Le("JetBrains"),mF=()=>Jm()==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),hF=async(e,t=cF)=>{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)]},yF=e=>{let t=Yv(e);return t.endsWith(`${me("Contents","Resources")}`)?Yv(t):t},gF=async e=>{try{let t=JSON.parse(await Ym(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:yF(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},wF=async(e,t)=>{let n;try{n=await iF(e,"r");let{size:r}=await n.stat();if(r<jm||r>lF)return;let o=Math.min(r,uF),a=await dd(n,o,r-o);if(!a)return;let s=-1;for(let u=a.length-jm;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>dF||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),y=l.readUInt16LE(d+30),g=l.readUInt16LE(d+32),h=l.readUInt32LE(d+42),w=d+46+m+y+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>Km||p>Km)return;let k=await dd(n,30,h);if(!k||k.readUInt32LE(0)!==67324752)return;let C=k.readUInt16LE(26),S=k.readUInt16LE(28),E=await dd(n,f,h+30+C+S);return E?u===0?E.toString("utf8"):u===8?sF(E,{maxOutputLength:Km}).toString("utf8"):void 0:void 0}return}catch{return}finally{await n?.close().catch(()=>{})}},Jv=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}},bF=async(e,t)=>{let n=me(e,"META-INF","plugin.xml");if(await x(n))try{let o=Jv(await Ym(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 wF(o,"META-INF/plugin.xml"),s=a?Jv(a):void 0;if(s?.id===pi)return{present:!0,descriptor:s}}return{present:t&&r.length>0}},Xv=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=Vm.has(o.name.toLowerCase()),i=Vm.has(a.name.toLowerCase());return Number(i)-Number(s)}).slice(0,512),r=!1;for(let o of n){let a=Vm.has(o.name.toLowerCase());if(!a){let i=me(e,o.name,"META-INF","plugin.xml");if(!await x(i))continue}let s=await bF(me(e,o.name),a);if(s.descriptor)return s;s.present&&(r=!0)}return{present:r}},AF=async e=>{try{return(await Ym(me(e,"disabled_plugins.txt"),"utf8")).split(/\r?\n/).map(n=>n.trim()).includes(pi)}catch{return!1}},zv=e=>e.reduce((t,n)=>t?(Zm(n,t)??-1)>0?n:t:n,void 0),Qv=async(e={})=>{let t=e.configRoot??Le("JetBrains"),n=e.userPluginsRoot??fF(),r=await hF(e.productRoots?e.productRoots.map(m=>({path:m,layout:"recursive"})):pF(),e.scanBudget),o=(await Promise.all(r.map(m=>gF(m)))).filter(m=>m!==void 0),a=o.length>0||await x(t);if(e.wsl??mF())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=>(Zm(m.version,ld)??-1)>=0),i=[],c=!1,l=!1,d=!1;for(let m of s){let y=me(t,m.dataDirectoryName);if(!await x(y)){d=!0;continue}let g=[me(y,"plugins"),me(n,m.dataDirectoryName),me(n,m.dataDirectoryName,"plugins")],h;for(let w of[...new Set(g)]){let b=await Xv(w);if(b.present){h=b;break}}if(h??=await Xv(me(m.root,"plugins")),h.present&&!h.descriptor){l=!0;continue}if(!(!h.descriptor||h.descriptor.id!==pi)){if(i.push(h.descriptor.version),await AF(y)){c=!0;continue}if(!((Zm(h.descriptor.version,Aa)??-1)<0))return{installed:!0,capable:!0,detail:`JetBrains IDE ${m.version}; AI Assistant ${h.descriptor.version}; ACP supported`,ideVersion:m.version,pluginVersion:h.descriptor.version}}}let u=zv(o.map(m=>m.version)),f=zv(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 vF=[Gn,Vn],Xm=()=>kF(CF(),".jetbrains","acp.json"),yo=()=>`${Xm()}.anyray-state`,SF=(e,t,n="npx")=>{let r=ho(e.agent_servers)?{...e.agent_servers}:{};return Object.assign(r,ui(n,"jetbrains")),{...e,agent_servers:r}},EF=(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 vF)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}},IF=(e=Qv)=>({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=Xm(),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:SF(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=Xm(),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=EF(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)}}),eS=IF();import{homedir as md}from"node:os";import{join as hd}from"node:path";import{rm as zm}from"node:fs/promises";var qm="1.0.0",yd=["anyray-claude-acp","anyray-codex-acp"],xF=["darwin-aarch64","darwin-x86_64","linux-aarch64","linux-x86_64","windows-aarch64","windows-x86_64"],Qm=()=>hd(md(),".windsurf","acp","registry.json"),eh=()=>hd(md(),".windsurf-next","acp","registry.json"),Ca=e=>`${e}.anyray-state`,tS=e=>({binary:Object.fromEntries(xF.map(t=>[t,{archive:"",cmd:e.command,args:e.args}]))}),rS=(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:tS(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:tS(t[Vn])}]},fd=e=>!Array.isArray(e)||e.some(t=>!ho(t)||typeof t.id!="string")?null:e,RF=(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)),...rS(t)],extensions:e.extensions??[]}},OF=(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}},nS=async()=>{let e=[];return(await x(eh())||await x(hd(md(),".windsurf-next")))&&e.push(eh()),(await x(Qm())||await x(hd(md(),".windsurf"))||await x(Le("Devin"))||await x(Le("Windsurf")))&&e.push(Qm()),e},oS={id:"windsurf",title:"Devin Desktop",automatic:!0,async detect(){let e=await nS();return e.length?{installed:!0,detail:e.join(", ")}:{installed:!1,detail:"Devin Desktop not found"}},async apply(e,t){let n=await nS();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=RF(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=rS(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=[Qm(),eh()],n=[],r=[],o=!1;for(let a of t){let s=async()=>{if(!await x(a)){e.dryRun||(await ce(a),await zm(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=OF(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 zm(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 zm(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,Xw,Os,qA,EC,MC,VC,eS,Wv,oS,ob],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 th=5e3,aS=3e4,TF=1440*60*1e3,_F=e=>new Promise(t=>setTimeout(t,e)),PF=async(e=P,t=yn)=>(await We(e,t))?.target,DF=e=>ut(e)?.quitGated,sS=async(e,t={})=>{let n=e[0];if(!n)return 0;let r=t.resolveSeam??DF,o=t.readPending??Kc,a=t.clearPending??Wp,s=t.targetFromProfile??PF,i=t.sleep??_F,c=t.now??Date.now,l=t.maxWaitMs??TF;try{let d=r(n);if(!d?.complete)return await a(n),0;let u=d.complete.bind(d),f=c(),p=th;for(;;){let m=await o(n);if(!m||c()-f>l)return 0;if(d.isRunning()){await i(p),p=Math.min(aS,p*2);continue}let y;if(d.needsTarget?.(m.op)&&(y=await s(),!y)){if(await a(n,m)!=="superseded")return 0;await i(p),p=th;continue}if((await u(m.op,y,{dryRun:!1,preservePendingOp:!0})).status==="queued"){await i(p),p=Math.min(aS,p*2);continue}if(await a(n,m)!=="superseded")return 0;await i(p),p=th}}catch{return 0}};import{writeFileSync as CW}from"node:fs";import{chmod as fh,stat as kW}from"node:fs/promises";import{platform as MS}from"node:os";import{dirname as BS,isAbsolute as vW}from"node:path";var LF="https://app.anyray.ai",NF=new Set(["localhost","::1","[::1]"]),$F=/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,MF=e=>NF.has(e)||$F.test(e),nh=e=>{let t;try{t=new URL(e)}catch{return!1}return t.protocol==="https:"?!0:t.protocol==="http:"&&MF(t.hostname)},BF=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||!nh(e)?LF:BF(e)};import{createHash as zF,generateKeyPairSync as qF,randomBytes as ah}from"node:crypto";import{createPrivateKey as FF,sign as WF}from"node:crypto";var Ir=async(e,t)=>{let n=FF(t);return WF(null,new TextEncoder().encode(e),n).toString("base64url")};var UF=["HTTPS_PROXY","https_proxy"],iS=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"]),cS=new Set(["CERT_HAS_EXPIRED","CERT_NOT_YET_VALID","ERR_TLS_CERT_ALTNAME_INVALID","ERR_SSL_WRONG_VERSION_NUMBER","EPROTO"]),lS=new Set(["ENOTFOUND","EAI_AGAIN"]),dS=new Set(["ECONNREFUSED","ECONNRESET","EPIPE","ENETDOWN","ENETUNREACH","EHOSTUNREACH","EHOSTDOWN"]),uS=new Set(["ETIMEDOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT"]),HF=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 GF(e)},GF=e=>{let t=e?.message;if(!(typeof t!="string"||!t)){for(let n of[...iS,...cS,...lS,...dS,...uS])if(t.includes(n))return n}},VF=e=>e?.name==="AbortError"||e?.name==="TimeoutError",KF=e=>UF.filter(t=>(e[t]??"").trim()!==""),jF=(e,t=process.env)=>{let n=HF(e),r=KF(t);return{kind:n&&iS.has(n)?"tls-unknown-issuer":n&&cS.has(n)?"tls-invalid-cert":n&&lS.has(n)?"dns":VF(e)||n&&uS.has(n)?"timeout":n&&dS.has(n)?"refused":"unknown",...n?{code:n}:{},proxyVars:r}},ZF=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)=>ZF(jF(e,t));var YF="enl_",pS="enp_",fS=e=>e.startsWith(YF)||e.startsWith(pS),rh=e=>e.startsWith(pS),JF=[{prefix:"tnt_",flag:"--sso",what:"an SSO link"},{prefix:"sdc_",flag:"--claim",what:"a one-time enrollment code"}],oh=e=>JF.find(t=>e.startsWith(t.prefix)),mS=/^\/enroll\/([^/]+)\/?$/,hS=/^\/i\/([^/]+)\/?$/,yS=e=>{let t=e.match(mS);if(t)return oh(t[1])?void 0:t[1];let n=e.match(hS);return n&&fS(n[1])?n[1]:void 0},XF=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=yS(n.pathname);return r?{cpOrigin:n.origin,token:r}:void 0}if(!oh(t))return{cpOrigin:Kn(),token:t}},gS=e=>{let t=e.trim();if(!t)return;let n=t;try{let o=new URL(t),a=o.pathname.match(mS)??o.pathname.match(hS);if(!a)return;n=a[1]}catch{}let r=oh(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:yS(n.pathname)!==void 0}catch{return fS(t)}},ka=class extends Error{constructor(t){super(t),this.name="EnrollmentPermanentError"}},fi=e=>typeof e=="string"&&e.trim()?e.trim():void 0,wS=async(e,t={})=>{let n=t.timeoutMs??XF,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.178";var sh=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(",")}}`,bS="stable-key-heartbeat-v1",AS="key-heartbeat",QF=["reapply_config","remint","revert"],ih=(e,t)=>t&&e.payload.source==="mdm"?{machineUuid:t}:{};var CS=e=>zF("sha256").update(e).digest("hex"),je=e=>typeof e=="string"&&e.trim()?e.trim():void 0,eW=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"&&/^[a-z0-9-]{1,64}$/.test(t)):[],kS={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"},tW=e=>`This organization requires a managed (MDM-enrolled) device for this enrollment: ${kS[e]}. Ask your IT admin.`,nW=e=>typeof e=="string"&&e in kS,ch=async e=>{try{let t=await e.json(),n=je(t?.message),r=je(t?.error),o=nW(t?.reason)?t.reason:void 0;if(r==="managed_device_required"&&o)return{message:tW(o),code:r,reason:o};if(n)return{message:n,...r?{code:r}:{}}}catch{}return{message:`gateway responded ${e.status}`}},rW=async e=>(await ch(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}},vS=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}},lh=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}=qF("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??sh,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:ah(16).toString("hex"),...ih(t,r.machineUuid)},c=await lh(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 ch(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 y=je(p.user);if(!y)throw new Error("developer verification failed: the gateway response is missing the user");let g=oW(p.directive),h=eW(p.capabilities);return{key:m,user:y,team:je(p.team),expiresAt:je(p.expiresAt),...h.length>0?{capabilities:h}:{},...g?{directive:g}:{}}},SS=async(e,t,n,r,o={})=>{let a=o.timeoutMs??sh,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:ah(16).toString("hex"),purpose:AS,...ih(n,o.machineUuid)},l=await lh(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(y){let g=y instanceof Error&&y.name==="AbortError"?` no response within ${a}ms.`:pt(y);throw new Error(`could not reach the gateway at ${s}.${g}`,{cause:y})}finally{clearTimeout(u)}if(!f.ok)throw new va(f.status,await ch(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!==bS||p.key!==void 0)throw new Error("developer heartbeat failed: the gateway returned an unexpected response");return{expiresAt:m,credentialMode:bS}},ES=async(e,t,n,r,o,a={})=>{let s=a.timeoutMs??sh,i=`${e.replace(/\/$/,"")}/connect/machine`,c=je(n?.payload?.deploymentId);if(!c||!o)return!1;let l={deploymentId:c,issuedAt:new Date().toISOString(),nonce:ah(16).toString("hex"),purpose:AS,...ih(n,o)},d=await lh(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)}},oW=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"||!QF.includes(r)?null:{id:n,kind:r}},aW=1e4,sW=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)},iW=async(e,t,n,r={},o={})=>{let a=o.timeoutMs??aW,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 rW(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(!sW(d))throw new Error("enrollment failed: the control plane returned an unexpected cert shape");return d},IS=(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())},xS=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 iW(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 dh=1e4,cW=900*1e3,OS="tnt_",lW=/^\/sso\/([^/]+)\/?$/,dW=/^\/i\/([^/]+)\/?$/,uW=e=>{let t=e.match(lW);if(t)return t[1];let n=e.match(dW);return n?.[1].startsWith(OS)?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=uW(n.pathname);return r?{cpOrigin:n.origin,tenantId:r}:void 0}if(t.startsWith(OS))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}},uh=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)}},pW=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 uh(`${e.cpOrigin}/sso/device`,{tenantId:e.tenantId,devPublicKey:r},dh,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,y=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 (${y}). 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??cW,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}`),fW(f.verificationUriComplete,e.cpOrigin)&&e.open?.(f.verificationUriComplete),f},fW=(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??pW,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 uh(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.deviceCode,devPublicKey:e.publicKeyPem},dh,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 RS="sdc_",TS=e=>{let t=e.trim();if(!t)return;if(t.startsWith(RS))return{cpOrigin:Kn(),claim:t};let n;try{n=new URL(t)}catch{return}if(!nh(n.origin))return;let r=n.searchParams.get("claim")?.trim();if(!(!r||!r.startsWith(RS)))return{cpOrigin:n.origin,claim:r}},_S=async e=>{let t=e.fetch??fetch,{publicKeyPem:n,privateKeyPem:r}=(e.generateKeypair??wd)(),o;try{o=await uh(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.claim,devPublicKey:n},dh,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 mW}from"node:fs/promises";import{isAbsolute as hW,posix as PS,win32 as ph}from"node:path";var hi=(e=process.platform,t=process.env)=>e==="darwin"?PS.join("/Library","Application Support","Anyray","bootstrap.json"):e==="win32"?ph.join(t.ProgramData??"C:\\ProgramData","Anyray","bootstrap.json"):PS.join("/etc","anyray","bootstrap.json"),yW=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),DS=e=>typeof e=="string"&&e.length>0&&e.length<=512&&[...e].every(t=>{let n=t.charCodeAt(0);return n>=32&&n!==127})&&(hW(e)||ph.isAbsolute(e))&&!/ark_[A-Za-z0-9_-]{20,}|-----BEGIN/.test(e),gW=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 mW(e,"utf-8");if(t.length>4096)return;let n=JSON.parse(t);if(!yW(n)||n.v!==1||typeof n.sso!="string")return;let r=Et(n.sso);if(!r)return;let o=gW(n.gateway)?n.gateway:void 0,a=DS(n.bin)?n.bin:void 0;return{sso:`${r.cpOrigin}/sso/${r.tenantId}`,gateway:o,bin:a}}catch{return}},LS=(e,t,n)=>{let r=Et(e);if(!r)throw new Error("invalid --sso link");if(n!==void 0&&!DS(n))throw new Error("--bin must be an absolute fleet-stable path");if(n!==void 0&&ph.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,Um);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."]}},KB=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."]}},jB=e=>Ev({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:",..._v(t)]:["Claude desktop org/API lane:",..._v(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`."]}),ZB=(e={})=>{let t=jB(e),n=()=>(e.platform??Er)()==="darwin",r=()=>(e.platform??Er)()==="win32",o=(s,i)=>n()?bk(s,i,e):zk(s,s.clientKey??"",i,e),a=s=>n()?Ak(s,e):qk(s,e);return{...t,automatic:!0,changesOrgManagement:!0,quitGated:{isRunning:()=>(e.appRunning??ga((e.platform??Er)()))(),quitTarget:UB,needsTarget:()=>!1,async complete(s){if(s!==Um)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)(Mv(e));if(i.ok){let c=Bv(i.lanes),l=Fv(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(y=>y.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(y=>!!y):["No portable Claude Desktop data was left to bring across."]}}return $v.has(i.kind)?{status:"queued",messages:[i.reason]}:{status:"manual",messages:[i.reason,i.remedy]}}},async usesDynamicCredential(s){return n()?kk(s,e):r()?tv(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:[um(p),...await li(e,i)]}}if(r()){let f;try{f=await Sr(e.runReg??Hn)}catch{return{status:"manual",manualAudience:"admin",messages:[VB,...await li(e,i)]}}if(f)return{status:"manual",manualAudience:"admin",messages:[Rm(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 BB(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 FB(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()?PB:[]],changedFiles:[...new Set([...u.changedFiles??[],...d.changedFiles])]}},async revert(s){let i=td(e),c=await KB(s),l=y=>c.length===0?y:{...y,messages:[...y.messages,...c]};if(!n()&&!r())return l(await t.revert(s));let d;try{d=await Tv(e)}catch(y){return l({status:"manual",messages:[y instanceof Fe?y.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 y=d.legacy;return l({...u,messages:[...u.messages,...d.active.ownership!=="absent"?[`Would remove the owned Anyray retrieval MCP server from ${i}.`]:[],...y&&y.ownership!=="absent"?[`Would remove the legacy owned Anyray MCP registration from ${y.path}.`]:[]]})}let f=await a({dryRun:!1});if(f.status==="manual"){let y=r()?Mt(e):void 0;if(!(y!==void 0&&f.changedFiles?.includes(y)===!0&&!await x(y)))return l(f)}let p;try{p=await WB(await Tv(e))}catch(y){let g=y instanceof Fe?y.changedFiles:[];return l({status:"manual",changedFiles:[...new Set([...f.changedFiles??[],...g])],messages:[...f.messages,y instanceof Fe?y.message:"Restored Claude Desktop inference, but could not safely remove its retrieval MCP registration. Re-run revert."]})}await ce(i);let m=Hm(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?fm(s,e):!1:r()?ev(s,e):!1},async inferenceAuthLanes(){try{if(n()){if(!(await ba(e)).supported)return["unknown"];let s=await Ck(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}}}},Wv=ZB();import{homedir as CF}from"node:os";import{join as kF}from"node:path";import{rm as pd}from"node:fs/promises";import{constants as Uv,accessSync as YB,statSync as JB}from"node:fs";import{platform as Gm}from"node:os";import{delimiter as XB,posix as zB,resolve as qB,win32 as QB}from"node:path";var eF="0.59.0",tF="1.1.4",Gn="Anyray \xB7 Claude",Vn="Anyray \xB7 Codex",od="__anyray-acp-agent",Hv=(e,t,n)=>{let{command:r,args:o}=nn([od,e,t,n]);return{command:r,args:o,env:{}}},ad=(e=Gm())=>e==="win32"?"npx.cmd":"npx",sd=(e=process.env.PATH,t=Gm())=>{if(!e)return;let n=ad(t);for(let r of e.split(XB)){let o=r.trim().replace(/^"|"$/g,"");if(!o)continue;let a=qB(o,n);try{if(!JB(a).isFile())continue;return YB(a,t==="win32"?Uv.F_OK:Uv.X_OK),a}catch{}}},id=(e,t=Gm())=>{let n=t==="win32"?QB:zB;return!n.isAbsolute(e)||n.basename(e).toLowerCase()!==ad(t)?!1:t!=="win32"||!/["&|<>^%!\r\n]/.test(e)},nF="https://chatgpt.com/backend-api/codex",rF="chatgpt-account-id,originator,session_id,user-agent,x-codex-turn-metadata,x-codex-window-id,x-client-request-id",Gv="ANYRAY_ACP_CODEX_AUTHORIZATION",Vv="ANYRAY_ACP_CODEX_CLIENT_KEY",Kv="ANYRAY_ACP_CODEX_METADATA",jv=e=>fe({...e.metadata,tool:e.metadata.tool??"codex",intent:e.metadata.intent??"jetbrains-acp",intentLabel:e.metadata.intentLabel??"JetBrains / Devin via Codex ACP"}),oF=(e,t={})=>{let n=ee(e,"openai"),r=n?{"x-anyray-auth-mode":"passthrough","x-anyray-custom-host":nF,"x-anyray-forward-headers":rF}:{},o=n?{...e.clientKey?{"x-anyray-api-key":Vv}:{}}:{Authorization:Gv};return jv(e)&&(o["x-anyray-metadata"]=Kv),{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}}}:{}}},aF=e=>{let t=ee(e,"openai"),n=jv(e);return{...t?e.clientKey?{[Vv]:e.clientKey}:{}:{[Gv]:`Bearer ${e.clientKey??e.placeholderKey}`},...n?{[Kv]:n}:{}}},Zv=(e,t=ad(),n={})=>({[Gn]:{command:t,args:["--yes",`@agentclientprotocol/claude-agent-acp@${eF}`],env:rn(e).env},[Vn]:{command:t,args:["--yes",`@agentclientprotocol/codex-acp@${tF}`],env:{CODEX_CONFIG:JSON.stringify(oF(e,n)),...aF(e)}}}),ui=(e=ad(),t="jetbrains")=>({[Gn]:Hv("claude",e,t),[Vn]:Hv("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 sF}from"node:zlib";import{open as iF,readFile as Ym,readdir as ud}from"node:fs/promises";import{dirname as Yv,join as me}from"node:path";import{homedir as qv,platform as Jm}from"node:os";var ld="2025.3.2",Aa="253.30387.147",pi="com.intellij.ml.llm",Vm=new Set(["ml-llm","llm","aia","ai-assistant","jetbrains-ai-assistant"]),cF=1e4,lF=256*1024*1024,dF=16*1024*1024,Km=1024*1024,jm=22,uF=jm+65535,Zm=xl,pF=()=>{let e=qv(),t=me(e,".cache","JetBrains","RemoteDev");switch(Jm()){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"}]}},fF=()=>Jm()==="linux"?me(qv(),".local","share","JetBrains"):Le("JetBrains"),mF=()=>Jm()==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),hF=async(e,t=cF)=>{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)]},yF=e=>{let t=Yv(e);return t.endsWith(`${me("Contents","Resources")}`)?Yv(t):t},gF=async e=>{try{let t=JSON.parse(await Ym(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:yF(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},wF=async(e,t)=>{let n;try{n=await iF(e,"r");let{size:r}=await n.stat();if(r<jm||r>lF)return;let o=Math.min(r,uF),a=await dd(n,o,r-o);if(!a)return;let s=-1;for(let u=a.length-jm;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>dF||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),y=l.readUInt16LE(d+30),g=l.readUInt16LE(d+32),h=l.readUInt32LE(d+42),w=d+46+m+y+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>Km||p>Km)return;let k=await dd(n,30,h);if(!k||k.readUInt32LE(0)!==67324752)return;let C=k.readUInt16LE(26),S=k.readUInt16LE(28),E=await dd(n,f,h+30+C+S);return E?u===0?E.toString("utf8"):u===8?sF(E,{maxOutputLength:Km}).toString("utf8"):void 0:void 0}return}catch{return}finally{await n?.close().catch(()=>{})}},Jv=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}},bF=async(e,t)=>{let n=me(e,"META-INF","plugin.xml");if(await x(n))try{let o=Jv(await Ym(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 wF(o,"META-INF/plugin.xml"),s=a?Jv(a):void 0;if(s?.id===pi)return{present:!0,descriptor:s}}return{present:t&&r.length>0}},Xv=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=Vm.has(o.name.toLowerCase()),i=Vm.has(a.name.toLowerCase());return Number(i)-Number(s)}).slice(0,512),r=!1;for(let o of n){let a=Vm.has(o.name.toLowerCase());if(!a){let i=me(e,o.name,"META-INF","plugin.xml");if(!await x(i))continue}let s=await bF(me(e,o.name),a);if(s.descriptor)return s;s.present&&(r=!0)}return{present:r}},AF=async e=>{try{return(await Ym(me(e,"disabled_plugins.txt"),"utf8")).split(/\r?\n/).map(n=>n.trim()).includes(pi)}catch{return!1}},zv=e=>e.reduce((t,n)=>t?(Zm(n,t)??-1)>0?n:t:n,void 0),Qv=async(e={})=>{let t=e.configRoot??Le("JetBrains"),n=e.userPluginsRoot??fF(),r=await hF(e.productRoots?e.productRoots.map(m=>({path:m,layout:"recursive"})):pF(),e.scanBudget),o=(await Promise.all(r.map(m=>gF(m)))).filter(m=>m!==void 0),a=o.length>0||await x(t);if(e.wsl??mF())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=>(Zm(m.version,ld)??-1)>=0),i=[],c=!1,l=!1,d=!1;for(let m of s){let y=me(t,m.dataDirectoryName);if(!await x(y)){d=!0;continue}let g=[me(y,"plugins"),me(n,m.dataDirectoryName),me(n,m.dataDirectoryName,"plugins")],h;for(let w of[...new Set(g)]){let b=await Xv(w);if(b.present){h=b;break}}if(h??=await Xv(me(m.root,"plugins")),h.present&&!h.descriptor){l=!0;continue}if(!(!h.descriptor||h.descriptor.id!==pi)){if(i.push(h.descriptor.version),await AF(y)){c=!0;continue}if(!((Zm(h.descriptor.version,Aa)??-1)<0))return{installed:!0,capable:!0,detail:`JetBrains IDE ${m.version}; AI Assistant ${h.descriptor.version}; ACP supported`,ideVersion:m.version,pluginVersion:h.descriptor.version}}}let u=zv(o.map(m=>m.version)),f=zv(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 vF=[Gn,Vn],Xm=()=>kF(CF(),".jetbrains","acp.json"),yo=()=>`${Xm()}.anyray-state`,SF=(e,t,n="npx")=>{let r=ho(e.agent_servers)?{...e.agent_servers}:{};return Object.assign(r,ui(n,"jetbrains")),{...e,agent_servers:r}},EF=(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 vF)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}},IF=(e=Qv)=>({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=Xm(),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:SF(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=Xm(),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=EF(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)}}),eS=IF();import{homedir as md}from"node:os";import{join as hd}from"node:path";import{rm as zm}from"node:fs/promises";var qm="1.0.0",yd=["anyray-claude-acp","anyray-codex-acp"],xF=["darwin-aarch64","darwin-x86_64","linux-aarch64","linux-x86_64","windows-aarch64","windows-x86_64"],Qm=()=>hd(md(),".windsurf","acp","registry.json"),eh=()=>hd(md(),".windsurf-next","acp","registry.json"),Ca=e=>`${e}.anyray-state`,tS=e=>({binary:Object.fromEntries(xF.map(t=>[t,{archive:"",cmd:e.command,args:e.args}]))}),rS=(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:tS(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:tS(t[Vn])}]},fd=e=>!Array.isArray(e)||e.some(t=>!ho(t)||typeof t.id!="string")?null:e,RF=(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)),...rS(t)],extensions:e.extensions??[]}},OF=(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}},nS=async()=>{let e=[];return(await x(eh())||await x(hd(md(),".windsurf-next")))&&e.push(eh()),(await x(Qm())||await x(hd(md(),".windsurf"))||await x(Le("Devin"))||await x(Le("Windsurf")))&&e.push(Qm()),e},oS={id:"windsurf",title:"Devin Desktop",automatic:!0,async detect(){let e=await nS();return e.length?{installed:!0,detail:e.join(", ")}:{installed:!1,detail:"Devin Desktop not found"}},async apply(e,t){let n=await nS();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=RF(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=rS(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=[Qm(),eh()],n=[],r=[],o=!1;for(let a of t){let s=async()=>{if(!await x(a)){e.dryRun||(await ce(a),await zm(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=OF(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 zm(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 zm(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,Xw,Os,qA,EC,MC,VC,eS,Wv,oS,ob],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 th=5e3,aS=3e4,TF=1440*60*1e3,_F=e=>new Promise(t=>setTimeout(t,e)),PF=async(e=P,t=yn)=>(await We(e,t))?.target,DF=e=>ut(e)?.quitGated,sS=async(e,t={})=>{let n=e[0];if(!n)return 0;let r=t.resolveSeam??DF,o=t.readPending??Kc,a=t.clearPending??Wp,s=t.targetFromProfile??PF,i=t.sleep??_F,c=t.now??Date.now,l=t.maxWaitMs??TF;try{let d=r(n);if(!d?.complete)return await a(n),0;let u=d.complete.bind(d),f=c(),p=th;for(;;){let m=await o(n);if(!m||c()-f>l)return 0;if(d.isRunning()){await i(p),p=Math.min(aS,p*2);continue}let y;if(d.needsTarget?.(m.op)&&(y=await s(),!y)){if(await a(n,m)!=="superseded")return 0;await i(p),p=th;continue}if((await u(m.op,y,{dryRun:!1,preservePendingOp:!0})).status==="queued"){await i(p),p=Math.min(aS,p*2);continue}if(await a(n,m)!=="superseded")return 0;await i(p),p=th}}catch{return 0}};import{writeFileSync as CW}from"node:fs";import{chmod as fh,stat as kW}from"node:fs/promises";import{platform as MS}from"node:os";import{dirname as BS,isAbsolute as vW}from"node:path";var LF="https://app.anyray.ai",NF=new Set(["localhost","::1","[::1]"]),$F=/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,MF=e=>NF.has(e)||$F.test(e),nh=e=>{let t;try{t=new URL(e)}catch{return!1}return t.protocol==="https:"?!0:t.protocol==="http:"&&MF(t.hostname)},BF=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||!nh(e)?LF:BF(e)};import{createHash as zF,generateKeyPairSync as qF,randomBytes as ah}from"node:crypto";import{createPrivateKey as FF,sign as WF}from"node:crypto";var Ir=async(e,t)=>{let n=FF(t);return WF(null,new TextEncoder().encode(e),n).toString("base64url")};var UF=["HTTPS_PROXY","https_proxy"],iS=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"]),cS=new Set(["CERT_HAS_EXPIRED","CERT_NOT_YET_VALID","ERR_TLS_CERT_ALTNAME_INVALID","ERR_SSL_WRONG_VERSION_NUMBER","EPROTO"]),lS=new Set(["ENOTFOUND","EAI_AGAIN"]),dS=new Set(["ECONNREFUSED","ECONNRESET","EPIPE","ENETDOWN","ENETUNREACH","EHOSTUNREACH","EHOSTDOWN"]),uS=new Set(["ETIMEDOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT"]),HF=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 GF(e)},GF=e=>{let t=e?.message;if(!(typeof t!="string"||!t)){for(let n of[...iS,...cS,...lS,...dS,...uS])if(t.includes(n))return n}},VF=e=>e?.name==="AbortError"||e?.name==="TimeoutError",KF=e=>UF.filter(t=>(e[t]??"").trim()!==""),jF=(e,t=process.env)=>{let n=HF(e),r=KF(t);return{kind:n&&iS.has(n)?"tls-unknown-issuer":n&&cS.has(n)?"tls-invalid-cert":n&&lS.has(n)?"dns":VF(e)||n&&uS.has(n)?"timeout":n&&dS.has(n)?"refused":"unknown",...n?{code:n}:{},proxyVars:r}},ZF=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)=>ZF(jF(e,t));var YF="enl_",pS="enp_",fS=e=>e.startsWith(YF)||e.startsWith(pS),rh=e=>e.startsWith(pS),JF=[{prefix:"tnt_",flag:"--sso",what:"an SSO link"},{prefix:"sdc_",flag:"--claim",what:"a one-time enrollment code"}],oh=e=>JF.find(t=>e.startsWith(t.prefix)),mS=/^\/enroll\/([^/]+)\/?$/,hS=/^\/i\/([^/]+)\/?$/,yS=e=>{let t=e.match(mS);if(t)return oh(t[1])?void 0:t[1];let n=e.match(hS);return n&&fS(n[1])?n[1]:void 0},XF=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=yS(n.pathname);return r?{cpOrigin:n.origin,token:r}:void 0}if(!oh(t))return{cpOrigin:Kn(),token:t}},gS=e=>{let t=e.trim();if(!t)return;let n=t;try{let o=new URL(t),a=o.pathname.match(mS)??o.pathname.match(hS);if(!a)return;n=a[1]}catch{}let r=oh(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:yS(n.pathname)!==void 0}catch{return fS(t)}},ka=class extends Error{constructor(t){super(t),this.name="EnrollmentPermanentError"}},fi=e=>typeof e=="string"&&e.trim()?e.trim():void 0,wS=async(e,t={})=>{let n=t.timeoutMs??XF,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.179";var sh=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(",")}}`,bS="stable-key-heartbeat-v1",AS="key-heartbeat",QF=["reapply_config","remint","revert"],ih=(e,t)=>t&&e.payload.source==="mdm"?{machineUuid:t}:{};var CS=e=>zF("sha256").update(e).digest("hex"),je=e=>typeof e=="string"&&e.trim()?e.trim():void 0,eW=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"&&/^[a-z0-9-]{1,64}$/.test(t)):[],kS={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"},tW=e=>`This organization requires a managed (MDM-enrolled) device for this enrollment: ${kS[e]}. Ask your IT admin.`,nW=e=>typeof e=="string"&&e in kS,ch=async e=>{try{let t=await e.json(),n=je(t?.message),r=je(t?.error),o=nW(t?.reason)?t.reason:void 0;if(r==="managed_device_required"&&o)return{message:tW(o),code:r,reason:o};if(n)return{message:n,...r?{code:r}:{}}}catch{}return{message:`gateway responded ${e.status}`}},rW=async e=>(await ch(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}},vS=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}},lh=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}=qF("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??sh,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:ah(16).toString("hex"),...ih(t,r.machineUuid)},c=await lh(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 ch(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 y=je(p.user);if(!y)throw new Error("developer verification failed: the gateway response is missing the user");let g=oW(p.directive),h=eW(p.capabilities);return{key:m,user:y,team:je(p.team),expiresAt:je(p.expiresAt),...h.length>0?{capabilities:h}:{},...g?{directive:g}:{}}},SS=async(e,t,n,r,o={})=>{let a=o.timeoutMs??sh,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:ah(16).toString("hex"),purpose:AS,...ih(n,o.machineUuid)},l=await lh(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(y){let g=y instanceof Error&&y.name==="AbortError"?` no response within ${a}ms.`:pt(y);throw new Error(`could not reach the gateway at ${s}.${g}`,{cause:y})}finally{clearTimeout(u)}if(!f.ok)throw new va(f.status,await ch(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!==bS||p.key!==void 0)throw new Error("developer heartbeat failed: the gateway returned an unexpected response");return{expiresAt:m,credentialMode:bS}},ES=async(e,t,n,r,o,a={})=>{let s=a.timeoutMs??sh,i=`${e.replace(/\/$/,"")}/connect/machine`,c=je(n?.payload?.deploymentId);if(!c||!o)return!1;let l={deploymentId:c,issuedAt:new Date().toISOString(),nonce:ah(16).toString("hex"),purpose:AS,...ih(n,o)},d=await lh(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)}},oW=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"||!QF.includes(r)?null:{id:n,kind:r}},aW=1e4,sW=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)},iW=async(e,t,n,r={},o={})=>{let a=o.timeoutMs??aW,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 rW(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(!sW(d))throw new Error("enrollment failed: the control plane returned an unexpected cert shape");return d},IS=(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())},xS=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 iW(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 dh=1e4,cW=900*1e3,OS="tnt_",lW=/^\/sso\/([^/]+)\/?$/,dW=/^\/i\/([^/]+)\/?$/,uW=e=>{let t=e.match(lW);if(t)return t[1];let n=e.match(dW);return n?.[1].startsWith(OS)?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=uW(n.pathname);return r?{cpOrigin:n.origin,tenantId:r}:void 0}if(t.startsWith(OS))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}},uh=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)}},pW=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 uh(`${e.cpOrigin}/sso/device`,{tenantId:e.tenantId,devPublicKey:r},dh,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,y=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 (${y}). 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??cW,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}`),fW(f.verificationUriComplete,e.cpOrigin)&&e.open?.(f.verificationUriComplete),f},fW=(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??pW,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 uh(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.deviceCode,devPublicKey:e.publicKeyPem},dh,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 RS="sdc_",TS=e=>{let t=e.trim();if(!t)return;if(t.startsWith(RS))return{cpOrigin:Kn(),claim:t};let n;try{n=new URL(t)}catch{return}if(!nh(n.origin))return;let r=n.searchParams.get("claim")?.trim();if(!(!r||!r.startsWith(RS)))return{cpOrigin:n.origin,claim:r}},_S=async e=>{let t=e.fetch??fetch,{publicKeyPem:n,privateKeyPem:r}=(e.generateKeypair??wd)(),o;try{o=await uh(`${e.cpOrigin}/sso/device/token`,{deviceCode:e.claim,devPublicKey:n},dh,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 mW}from"node:fs/promises";import{isAbsolute as hW,posix as PS,win32 as ph}from"node:path";var hi=(e=process.platform,t=process.env)=>e==="darwin"?PS.join("/Library","Application Support","Anyray","bootstrap.json"):e==="win32"?ph.join(t.ProgramData??"C:\\ProgramData","Anyray","bootstrap.json"):PS.join("/etc","anyray","bootstrap.json"),yW=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),DS=e=>typeof e=="string"&&e.length>0&&e.length<=512&&[...e].every(t=>{let n=t.charCodeAt(0);return n>=32&&n!==127})&&(hW(e)||ph.isAbsolute(e))&&!/ark_[A-Za-z0-9_-]{20,}|-----BEGIN/.test(e),gW=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 mW(e,"utf-8");if(t.length>4096)return;let n=JSON.parse(t);if(!yW(n)||n.v!==1||typeof n.sso!="string")return;let r=Et(n.sso);if(!r)return;let o=gW(n.gateway)?n.gateway:void 0,a=DS(n.bin)?n.bin:void 0;return{sso:`${r.cpOrigin}/sso/${r.tenantId}`,gateway:o,bin:a}}catch{return}},LS=(e,t,n)=>{let r=Et(e);if(!r)throw new Error("invalid --sso link");if(n!==void 0&&!DS(n))throw new Error("--bin must be an absolute fleet-stable path");if(n!==void 0&&ph.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),NS=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),wW=e=>Ea("32",e,Cd),bW=e=>Ea("33",e,NS),AW=e=>Ea("31",e,NS),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(`${wW("\u2713")} ${e}`),_=e=>console.error(`${bW("!")} ${e}`),R=e=>console.error(`${AW("\u2717")} ${e}`);var mh=`${j("anyray-connect managed")} \u2014 fleet-wide Claude Code routing via managed-settings.json
|
|
264
264
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anyray-connect",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.179",
|
|
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": {
|