UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

1 lines 3.7 kB
import{extractCodexAccountIdFromToken,isFreshCodexAccessToken,readCodexAuthCredentials,writeCodexAuthCredentials}from"./auth.js";import{z}from"#compiled/zod/index.js";const CODEX_API_ENDPOINT=`https://chatgpt.com/backend-api/codex/responses`,codexRefreshResponseSchema=z.object({access_token:z.string().trim().min(1),id_token:z.string().trim().min(1).optional(),refresh_token:z.string().trim().min(1)}).passthrough();function createCodexFetch(e={}){let r=e.fetch??fetch,i=e.readCredentials??readCodexAuthCredentials,o=e.now??Date.now,s=e.writeCredentials??createDefaultCodexCredentialsWriter(o),c=e.issuer??`https://auth.openai.com`,l=e.clientId??`app_EMoamEEZ73f0CkXaXp7hrann`,u=e.codexApiEndpoint??CODEX_API_ENDPOINT,d;return async(e,n)=>{let a=await i(),f=cloneHeaders(n?.headers??(e instanceof Request?e.headers:void 0));if(f.delete(`authorization`),f.delete(`Authorization`),f.set(`originator`,`eve`),a.kind===`api-key`)return f.set(`authorization`,`Bearer ${a.apiKey}`),r(e,fetchInit(e,n,f));let p=await authenticateChatGpt();return f.set(`authorization`,`Bearer ${p.accessToken}`),p.accountId!==void 0&&f.set(`ChatGPT-Account-Id`,p.accountId),r(rewriteCodexEndpoint(requestUrl(e),u),fetchInit(e,n,f));async function authenticateChatGpt(){if(a.kind!==`chatgpt`)throw Error(`Expected ChatGPT Codex credentials.`);if(a.accessToken!==void 0&&isFreshCodexAccessToken(a.accessToken,o()))return{...a,accessToken:a.accessToken};let e=a.refreshToken;if(e===void 0)throw Error(`Codex ChatGPT login state at ${a.authPath} does not include a refresh token. Run \`codex login\` again before using experimental_chatgpt.`);d===void 0&&(d=refreshChatGptCredentials({clientId:l,credentials:{...a,refreshToken:e},fetch:r,issuer:c,writeCredentials:s}).finally(()=>{d=void 0}));let n=await d;if(n.accessToken===void 0)throw Error(`Codex token refresh did not return an access token.`);return{...n,accessToken:n.accessToken}}}}function rewriteCodexEndpoint(e,t=CODEX_API_ENDPOINT){let n=new URL(e);return n.pathname.includes(`/v1/responses`)||n.pathname.includes(`/chat/completions`)?t:e}async function refreshChatGptCredentials(t){let n=await t.fetch(`${t.issuer}/oauth/token`,{body:new URLSearchParams({client_id:t.clientId,grant_type:`refresh_token`,refresh_token:t.credentials.refreshToken}).toString(),headers:{"Content-Type":`application/x-www-form-urlencoded`},method:`POST`});if(!n.ok)throw Error(`Codex token refresh failed with status ${n.status}. Run \`codex login\` again.`);let r=parseRefreshResponse(await n.json());return t.writeCredentials({credentials:t.credentials,tokens:{...r,accountId:r.accountId??t.credentials.accountId??extractCodexAccountIdFromToken(r.idToken)??extractCodexAccountIdFromToken(r.accessToken)}})}function parseRefreshResponse(t){let n=codexRefreshResponseSchema.safeParse(t);if(!n.success)throw Error(`Codex token refresh did not return access_token and refresh_token.`);let r=n.data.access_token,i=n.data.refresh_token,a=n.data.id_token;return{accessToken:r,refreshToken:i,...a!==void 0&&{idToken:a},accountId:extractCodexAccountIdFromToken(a)??extractCodexAccountIdFromToken(r)}}function createDefaultCodexCredentialsWriter(e){return t=>writeCodexAuthCredentials({...t,now:()=>new Date(e())})}function cloneHeaders(e){return new Headers(e)}function requestUrl(e){return e instanceof Request?e.url:e.toString()}function fetchInit(e,t,n){return t===void 0?e instanceof Request?{body:e.body,cache:e.cache,credentials:e.credentials,headers:n,integrity:e.integrity,keepalive:e.keepalive,method:e.method,mode:e.mode,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy,signal:e.signal}:{headers:n}:{...t,headers:n}}export{createCodexFetch,rewriteCodexEndpoint};