eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 3.79 kB
JavaScript
import{withLoginProgress}from"./model-login-progress.js";import{isObject}from"#shared/guards.js";import{rememberModelTeamSlug}from"#internal/model-auth/vercel-team.js";import{setTimeout}from"node:timers/promises";import{openUrl}from"#setup/primitives/open-url.js";import{writeVercelSession}from"#internal/model-auth/store.js";import{readVercelCliTeam}from"#internal/model-auth/vercel-cli.js";import{VERCEL_MODEL_CLIENT_ID,VERCEL_OAUTH_ISSUER,authJson,sessionFromToken,validateVercelAccess,vercelApiJson,vercelOAuthEndpoints}from"#internal/model-auth/vercel.js";async function loginVercelModel(e,t,n){let{endpoints:r,device:i}=await withLoginProgress(e,`Opening Vercel sign-in…`,async()=>{let e=await vercelOAuthEndpoints(t);return{endpoints:e,device:await authJson(e.device,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,scope:`openid offline_access`}),signal:t})}});if(typeof i.device_code!=`string`||typeof i.verification_uri!=`string`||typeof i.user_code!=`string`)throw Error(`Could not start Vercel sign-in. Retry /login.`);let a=typeof i.verification_uri_complete==`string`?i.verification_uri_complete:i.verification_uri;if(URL.parse(a)?.origin!==VERCEL_OAUTH_ISSUER)throw Error(`Vercel returned an unexpected sign-in URL. Retry /login.`);e.log.info(`Open ${a} · code ${i.user_code}`),openUrl(a);let o=typeof i.interval==`number`?Math.max(1,Math.min(30,i.interval)):5,s=typeof i.expires_in==`number`?Math.min(600,i.expires_in):300,c=Date.now()+s*1e3,l=e.log.spinner?.(`Finish signing in to Vercel in your browser`,{kind:`external-action`,emphasis:`your browser`}),u;try{for(;Date.now()<c;){await setTimeout(o*1e3,void 0,{signal:t});let e=await authJson(r.token,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,grant_type:`urn:ietf:params:oauth:grant-type:device_code`,device_code:i.device_code}),signal:t});if(e.error!==`authorization_pending`){if(e.error===`slow_down`){o=Math.min(30,o+5);continue}if(e.error)throw Error(`Vercel sign-in was declined or expired. Retry /login.`);u=sessionFromToken(e);break}}}finally{l?.stop()}if(!u)throw Error(`Vercel sign-in timed out. Retry /login.`);let[d,f]=await withLoginProgress(e,`Loading Vercel teams…`,()=>Promise.all([loadTeams(u.accessToken,t),readVercelCliTeam()])),p=d.find(e=>e.id===n)??d.find(e=>e.id===f),m=d.length===1?d[0]:void 0;for(;;){if(!m){let t=await e.select({message:`Choose a Vercel team`,search:!0,initialValue:p?.id,options:d.map(e=>({value:e.id,label:e.name}))});m=d.find(e=>e.id===t)}if(!m)throw Error(`That Vercel team is no longer available. Retry /login.`);let n=m;try{await withLoginProgress(e,`Checking AI Gateway access for ${m.slug??m.name}…`,()=>validateVercelAccess(u.accessToken,n.id,t));break}catch(n){if(t?.throwIfAborted(),d.length===1)throw n;e.log.warning(`AI Gateway is unavailable for that team. Choose another team or press Esc to return.`),m=void 0}}return u.teamId=m.id,u.teamName=m.name,t?.throwIfAborted(),await writeVercelSession(u,VERCEL_MODEL_CLIENT_ID),m.slug&&rememberModelTeamSlug(m.id,m.slug),{teamId:m.id,teamName:m.name}}async function loadTeams(e,t){let n=[],r;for(let i=0;i<20;i++){let i=await vercelApiJson(`https://api.vercel.com/v2/teams?limit=100${r===void 0?``:`&until=${r}`}`,{headers:{authorization:`Bearer ${e}`},signal:t});if(!Array.isArray(i.teams))throw Error(`Could not list Vercel teams. Retry /login.`);for(let e of i.teams)isObject(e)&&typeof e.id==`string`&&typeof e.name==`string`&&n.push({id:e.id,name:e.name,slug:typeof e.slug==`string`?e.slug:void 0});if(r=isObject(i.pagination)&&typeof i.pagination.next==`number`?i.pagination.next:void 0,r===void 0)break}if(n.length===0)throw Error(`No Vercel team is available. Join a team or choose another connection in /login.`);return n}export{loginVercelModel};