UNPKG

eve

Version:

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

4 lines 4.95 kB
import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{getVercelAuthStatus,vercelAuthBlockerReason}from"../vercel-project.js";import{WizardCancelledError}from"../step.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";import{HumanActionRequiredError}from"#setup/human-action.js";const PROVIDER_QUESTION=`Which model provider do you want to use?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${AI_GATEWAY_API_KEY_ENV_FILE} — e.g. ANTHROPIC_API_KEY or OPENAI_API_KEY.`,'In agent/agent.ts, set `model` to a provider-authored model — e.g. `anthropic("claude-opus-4.8")` from `@ai-sdk/anthropic`.',`See https://eve.dev/docs/agent-config for details.`,"A running `eve dev` reloads env files automatically — no restart needed."];function projectConnectionOption(e,t){let n={value:`ai-gateway-project`,label:`AI Gateway via Project`,hint:`Authenticates with AI Gateway automatically in a new or existing project. No keys to manage.`};if(e===`unavailable`)return{...n,hint:`Couldn't reach Vercel — select to retry`};if(t&&e===`logged-out`)return{...n,hint:`Log in to Vercel — select to retry`};if(t&&e===`cli-missing`)return{...n,hint:`Install the Vercel CLI — select to retry`};let r=e===void 0?void 0:vercelAuthBlockerReason(e);return r===void 0?n:{...n,disabled:!0,disabledReason:r,disabledReasonTone:`warning`}}function providerOptions(e,t,n,r){let i=projectConnectionOption(e,r);n&&t===`ai-gateway-project`&&e!==`unavailable`&&(!r||e!==`logged-out`&&e!==`cli-missing`)&&(i={...i,checked:!0,hint:`Current`});let a={value:`ai-gateway-key`,label:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`,hint:`⎿ type your key`};return n&&t===`ai-gateway-key`&&(a={...a,checked:!0,hint:`Current`}),[i,a,{value:`chatgpt`,label:`ChatGPT subscription`,hint:n&&t===`chatgpt`?`Current`:`Sign in with your ChatGPT account`,checked:n&&t===`chatgpt`||void 0},{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider via OPENAI_API_KEY or ANTHROPIC_API_KEY.`}]}async function selectProvider(e){let t={message:PROVIDER_QUESTION,options:e.options,initialValue:e.initialValue,validateInlineKey:e.validateInlineKey};if(e.picker===void 0)throw Error(`The provider flow requires the Dev TUI provider picker.`);let n=await e.picker(t);if(n===void 0)throw new WizardCancelledError;return n}async function runProviderFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={getVercelAuthStatus,runLinkFlow,appendEnv,validateGatewayApiKey,...e.deps},a,{availableProviders:o,selectedProvider:s}=e,c=s,l;try{for(;;){let u=await selectProvider({picker:e.picker,options:providerOptions(a,s,e.selectionExplicit!==!1,e.recoverHumanAction!==void 0),initialValue:c,validateInlineKey:(e,t)=>i.validateGatewayApiKey(e,r===void 0?t:AbortSignal.any([r,t]))});if(u.kind===`external`)return n.acknowledge?await n.acknowledge({message:EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,lines:EXTERNAL_PROVIDER_INSTRUCTIONS}):n.note(EXTERNAL_PROVIDER_INSTRUCTIONS.join(` `),EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE),{kind:`external-provider`};if(u.kind===`chatgpt`)return u;if(u.kind===`ai-gateway-key`){l=u;break}if(s!==`ai-gateway-project`&&o.includes(`ai-gateway-project`))return u;for(;;){let o=await withSpinner(n,`Checking your Vercel login…`,()=>i.getVercelAuthStatus(t,{signal:r}));if(r?.throwIfAborted(),a=o,o===`authenticated`)break;let s=o===`cli-missing`?`vercel-cli-missing`:o===`logged-out`?`vercel-login`:void 0;if(s===void 0||e.recoverHumanAction===void 0){c=o===`unavailable`?`ai-gateway-project`:`ai-gateway-key`;break}if(await e.recoverHumanAction(new HumanActionRequiredError({kind:s,command:o===`cli-missing`?`npm i -g vercel@latest`:`vercel login`,reason:o===`cli-missing`?`AI Gateway via Project requires the Vercel CLI.`:`AI Gateway via Project requires a Vercel login.`}))===`cancel`){c=`ai-gateway-project`;break}}if(a===`authenticated`)for(;;)try{let e=await i.runLinkFlow({appRoot:t,prompter:n,signal:r,projectSelection:`create-or-link`});return e.kind===`cancelled`?e:{kind:`ai-gateway-project`}}catch(t){if(!(t instanceof HumanActionRequiredError)||e.recoverHumanAction===void 0)throw t;if(await e.recoverHumanAction(t)===`cancel`){c=`ai-gateway-key`;break}}}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}let u=l.key.trim(),d=l.validation;r?.throwIfAborted(),d.kind===`inconclusive`&&n.log.warning(`Couldn't reach the gateway to validate (${d.message}). Saving the key anyway.`);let f=await writeAiGatewayApiKey({projectRoot:t,apiKey:u,appendEnv:i.appendEnv});return n.log.success(`${f.envKey} set.`),{kind:`ai-gateway-key`}}export{EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runProviderFlow};