eve 0.12.3 → 0.13.0
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/CHANGELOG.md +11 -0
- package/dist/src/cli/commands/deploy.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/link.d.ts +2 -2
- package/dist/src/cli/commands/link.js +1 -1
- package/dist/src/cli/dev/tui/setup-flow.d.ts +5 -0
- package/dist/src/cli/dev/tui/setup-panel.d.ts +4 -1
- package/dist/src/cli/dev/tui/setup-panel.js +1 -1
- package/dist/src/cli/dev/tui/setup-selection-input.d.ts +2 -1
- package/dist/src/cli/dev/tui/setup-selection-input.js +2 -2
- package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
- package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/tool-auth.d.ts +16 -39
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/public/channels/github/api.d.ts +5 -0
- package/dist/src/public/channels/github/api.js +1 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/pr-context.d.ts +10 -0
- package/dist/src/public/channels/github/pr-context.js +2 -2
- package/dist/src/public/definitions/tool.d.ts +3 -48
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/runtime/types.d.ts +0 -10
- package/dist/src/setup/boxes/link-project.d.ts +8 -14
- package/dist/src/setup/boxes/link-project.js +1 -1
- package/dist/src/setup/boxes/resolve-provisioning.d.ts +2 -1
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/cli/select-component.d.ts +7 -1
- package/dist/src/setup/cli/select-component.js +1 -1
- package/dist/src/setup/cli/select-option-codec.d.ts +1 -0
- package/dist/src/setup/cli/select-option-codec.js +1 -1
- package/dist/src/setup/cli/select-state.d.ts +14 -1
- package/dist/src/setup/cli/select-state.js +1 -1
- package/dist/src/setup/flows/model.d.ts +2 -2
- package/dist/src/setup/index.d.ts +1 -1
- package/dist/src/setup/package-manager.d.ts +2 -1
- package/dist/src/setup/package-manager.js +1 -1
- package/dist/src/setup/primitives/pm/index.d.ts +1 -1
- package/dist/src/setup/primitives/pm/pnpm.d.ts +11 -1
- package/dist/src/setup/primitives/pm/pnpm.js +5 -2
- package/dist/src/setup/primitives/pm/types.d.ts +10 -1
- package/dist/src/setup/project-resolution.d.ts +9 -6
- package/dist/src/setup/project-resolution.js +1 -1
- package/dist/src/setup/prompter.d.ts +13 -0
- package/dist/src/setup/prompter.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.d.ts +8 -0
- package/dist/src/setup/scaffold/create/project.js +8 -7
- package/dist/src/setup/scaffold/update/channels.d.ts +8 -0
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/package-json.d.ts +3 -0
- package/dist/src/setup/scaffold/update/package-json.js +1 -1
- package/dist/src/setup/scaffold/workspace-glob.d.ts +5 -0
- package/dist/src/setup/scaffold/workspace-glob.js +1 -0
- package/dist/src/setup/scaffold/workspace-root.d.ts +29 -0
- package/dist/src/setup/scaffold/workspace-root.js +1 -0
- package/dist/src/setup/state.d.ts +7 -2
- package/dist/src/setup/vercel-api-failure.d.ts +9 -0
- package/dist/src/setup/vercel-api-failure.js +1 -0
- package/dist/src/setup/vercel-deployment.js +1 -1
- package/dist/src/setup/vercel-project-api.d.ts +25 -0
- package/dist/src/setup/vercel-project-api.js +1 -0
- package/dist/src/setup/vercel-project.d.ts +9 -51
- package/dist/src/setup/vercel-project.js +1 -1
- package/docs/guides/auth-and-route-protection.md +2 -4
- package/docs/guides/dev-tui.md +1 -1
- package/docs/reference/cli.md +1 -1
- package/docs/reference/typescript-api.md +0 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{boolean,object,record,string,unknown}from"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{withSpinner}from"./with-spinner.js";import{hasVercelHostFramework}from"#setup/scaffold/index.js";import{captureVercel,runVercel}from"#setup/primitives/index.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{whimsyFor}from"#setup/cli/index.js";var import_picocolors=__toESM(require_picocolors(),1);const JsonObjectSchema=record(string(),unknown()),VercelTeamListEntrySchema=object({name:string(),slug:string(),current:boolean()}),VercelProjectListEntrySchema=object({name:string(),id:string()}),VercelProjectReferenceSchema=object({id:string(),name:string()}),VercelApiErrorSchema=object({error:object({code:string().optional(),message:string().optional()}).optional()});function unresolvedProject(){return{kind:`unresolved`}}function projectIdFromResolution(e){return e.kind===`unresolved`?void 0:e.projectId}function parseJson(e,t){try{return JSON.parse(e)}catch{throw Error(`Could not parse ${t} JSON from Vercel CLI output.`)}}function parseVercelJsonList(e,t,n){let r=parseJson(e,t),i=JsonObjectSchema.safeParse(r);if(!i.success)throw Error(`Could not read ${t} from Vercel CLI JSON output.`);let a=i.data[t];if(!Array.isArray(a))throw Error(`Vercel CLI JSON output did not include ${t}.`);let o=[];for(let e of a){let t=n.safeParse(e);t.success&&o.push(t.data)}return o}function parseTeamList(e){return e===void 0?[]:parseVercelJsonList(e,`teams`,VercelTeamListEntrySchema)}async function listTeams(e,t={}){let n=await captureVercel([`teams`,`ls`,`--format`,`json`],{cwd:e,signal:t.signal});if(!n.ok)throw isForbiddenApiFailure(n.failure)&&requireVercelTeamAccess(n.failure),Error(`Could not list Vercel teams. ${n.failure.message}`);return parseTeamList(n.stdout)}function parseProjectList(e){return e===void 0?[]:parseVercelJsonList(e,`projects`,VercelProjectListEntrySchema)}async function listProjects(e,t,n={}){let r=await captureVercel([`project`,`ls`,`--format`,`json`,`--scope`,t],{cwd:e,signal:n.signal});if(!r.ok)throw isForbiddenApiFailure(r.failure)&&requireVercelTeamAccess(r.failure),Error(`Could not list Vercel projects in ${t}. ${r.failure.message}`);return parseProjectList(r.stdout)}function isNotFoundApiFailure(e){if(e.code===404)return!0;let t=VercelApiErrorSchema.safeParse(safeParseJson(e.stdout)),n=t.success?t.data.error:void 0,r=`${n?.code??``} ${n?.message??``} ${e.stderr}`.toLowerCase();return r.includes(`not_found`)||r.includes(`not found`)||r.includes(`404`)}function isConflictApiFailure(e){let t=VercelApiErrorSchema.safeParse(safeParseJson(e.stdout)),n=t.success?t.data.error:void 0,r=`${n?.code??``} ${n?.message??``} ${e.stdout} ${e.stderr}`.toLowerCase();return r.includes(`409`)||r.includes(`conflict`)||r.includes(`already exists`)}function isForbiddenApiFailure(e){let t=VercelApiErrorSchema.safeParse(safeParseJson(e.stdout)),n=t.success?t.data.error:void 0,r=`${n?.code??``} ${n?.message??``} ${e.stdout} ${e.stderr}`.toLowerCase();return r.includes(`403`)||r.includes(`forbidden`)||r.includes(`not_authorized`)||r.includes(`not authorized`)||r.includes(`sso`)||r.includes(`saml`)}function safeParseJson(e){try{return JSON.parse(e)}catch{return}}function parseProjectReference(e,t){let n=VercelProjectReferenceSchema.safeParse(parseJson(e,t));if(!n.success)throw Error(`Could not read Vercel project identity from ${t}.`);return n.data}async function resolveProjectByNameOrId(e,t,n,r={}){let i=await captureVercel([`api`,`/v9/projects/${encodeURIComponent(n)}`,`--scope`,t,`--raw`],{cwd:e,signal:r.signal});if(i.ok)return parseProjectReference(i.stdout,`project ${n}`);if(isNotFoundApiFailure(i.failure))return null;throw isForbiddenApiFailure(i.failure)&&requireVercelTeamAccess(i.failure),Error(`Could not resolve project "${n}" in ${t}. ${i.failure.message}`)}async function createProject(e,t,n,r,i){let a=[`api`,`/v10/projects`,`--scope`,t,`--method`,`POST`,`--raw-field`,`name=${n}`];await hasVercelHostFramework(e)||a.push(`--raw-field`,`framework=eve`),a.push(`--raw`);let o=await captureVercel(a,{cwd:e,onOutput:r,signal:i.signal});if(o.ok)return parseProjectReference(o.stdout,`created project ${n}`);throw isConflictApiFailure(o.failure)?Error(projectNameCollisionMessage(n,t)):(isForbiddenApiFailure(o.failure)&&requireVercelTeamAccess(o.failure),Error(`Could not create Vercel project "${n}" in ${t}. ${o.failure.message}`))}function projectNameCollisionMessage(e,t){return`Vercel project "${e}" already exists in ${t}. Pass --project ${e} to link it, or choose a different project name.`}async function assertNewProjectNameAvailable(e,t,n,r={}){if(await resolveProjectByNameOrId(e,t,n,r)!==null)throw Error(projectNameCollisionMessage(n,t))}function requireVercelLogin(e){let t=`Provisioning a Vercel project requires you to be logged in to Vercel.`,n=e?.stderr.trim();throw new HumanActionRequiredError({kind:`vercel-login`,command:`vercel login`,reason:e?`${t} The Vercel CLI check did not succeed: ${e.message}${n?` ${n}`:``}`:t})}function probeWhoami(e,t){return captureVercel([`whoami`],{cwd:e,signal:t.signal,timeoutMs:1e4})}function isLoggedOutFailure(e){let t=`${e.stdout} ${e.stderr}`.toLowerCase();return t.includes(`credentials`)||t.includes(`not authenticated`)||t.includes(`not logged in`)}function requireVercelAuth(e){if(e.errno===`ENOENT`)throw new HumanActionRequiredError({kind:`vercel-cli-missing`,command:`npm i -g vercel@latest`,reason:e.message});isLoggedOutFailure(e)&&requireVercelLogin(e);let t=e.stderr.trim();throw Error(`Couldn't verify your Vercel login: ${e.message}${t?` ${t}`:``}`)}function vercelAuthBlockerReason(e){switch(e){case`authenticated`:return;case`cli-missing`:return`Vercel CLI not found, see /vc`;case`logged-out`:return`Log in to Vercel first, see /login`;case`unavailable`:return`Couldn't reach Vercel, check your connection`;default:return e}}async function getVercelAuthStatus(e,t={}){let n=await probeWhoami(e,t);return t.signal?.throwIfAborted(),n.ok?`authenticated`:n.failure.errno===`ENOENT`?`cli-missing`:isLoggedOutFailure(n.failure)?`logged-out`:`unavailable`}function requireVercelTeamAccess(e){let t=e.stderr.trim();throw new HumanActionRequiredError({kind:`vercel-forbidden`,command:`vercel login`,reason:`Vercel denied access to this scope.${t?` ${t}`:``} Re-authenticate (for example to complete a team's SSO) or switch to a team you can access.`})}async function requireAuth(e,t,n={}){let check=async()=>{let t=await probeWhoami(e,n);n.signal?.throwIfAborted(),t.ok||requireVercelAuth(t.failure)};if(t===void 0){await check();return}await withSpinner(t,whimsyFor(`auth`),check)}async function isVercelAuthenticated(e,t={}){return await getVercelAuthStatus(e,t)===`authenticated`}async function whoamiScope(e,t){let n=await probeWhoami(e,t);return t.signal?.throwIfAborted(),n.ok||requireVercelAuth(n.failure),n.stdout.trim()}async function resolveTeam(e,t,n={}){return t===void 0?(await listTeams(e,n)).find(e=>e.current)?.slug??await whoamiScope(e,n):t}async function validateTeam(e,t,n,r={}){if(n===void 0)return;let i=await listTeams(t,r);if(i.length>0&&!i.some(e=>e.slug===n))throw Error(`Team "${n}" was not found in \`vercel teams ls\`. Pass a valid team slug or omit --team.`)}async function pickTeam(e,t,n,r={}){if(n!==void 0)return await validateTeam(e,t,n,r),resolveTeam(t,n,r);let i=await withSpinner(e,whimsyFor(`teams`),()=>listTeams(t,r));return i.length<=1?i.find(e=>e.current)?.slug??await whoamiScope(t,r):e.select({message:`Select your team`,search:!0,placeholder:`type to search teams`,options:i.map(e=>({value:e.slug,label:e.current?`${e.name} (current)`:e.name})),initialValue:i.find(e=>e.current)?.slug})}async function pickProject(e,t,n,r={}){let i=await withSpinner(e,whimsyFor(`projects`,n),()=>listProjects(t,n,r));if(i.length===0){if(r.allowCreateWhenEmpty===!1)throw Error(`No existing Vercel projects found in ${n}. Create one in Vercel, then try again.`);return{project:await e.text({message:`No projects found in ${n}. Enter a project name to create`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}),exists:!1}}return{project:await e.select({message:`Project to link`,search:!0,placeholder:`type to filter projects`,options:i.map(e=>({value:e.name,label:e.name}))}),exists:!0}}async function pickNewProjectName(e,t,n,r,i={}){let a=await withSpinner(e,whimsyFor(`project-name`,n),()=>resolveProjectByNameOrId(t,n,r.trim(),i)),o=r.trim();for(;a!==null;)o=(await e.text({message:`New project name`,defaultValue:`${o}-2`,notices:[{tone:`warning`,text:`${import_picocolors.default.yellow(`Project named`)} '${import_picocolors.default.blue(o)}' ${import_picocolors.default.yellow(`already exists in`)} '${import_picocolors.default.blue(n)}'`}],validate:e=>{if(e.trim().length===0)return`Project name cannot be empty.`}})).trim(),a=await resolveProjectByNameOrId(t,n,o,i);return o}async function linkProject(e,t,n,r,i={}){let a=[`--scope`,n.team],o;if(n.kind===`new`)o=await withSpinner(e,`Creating Vercel project "${n.project}" in ${n.team}...`,async()=>(await assertNewProjectNameAvailable(t,n.team,n.project,i),createProject(t,n.team,n.project,r,i)));else{let e=await resolveProjectByNameOrId(t,n.team,n.project,i);if(e===null)throw Error(`Vercel project "${n.project}" was not found in ${n.team}.`);o=e}return withSpinner(e,`Linking this directory to Vercel project "${o.name}"...`,()=>runVercel([`link`,`--project`,o.id,...a,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,signal:i.signal}))}export{assertNewProjectNameAvailable,getVercelAuthStatus,isVercelAuthenticated,linkProject,listProjects,listTeams,pickNewProjectName,pickProject,pickTeam,projectIdFromResolution,requireAuth,requireVercelAuth,requireVercelLogin,requireVercelTeamAccess,resolveProjectByNameOrId,resolveTeam,unresolvedProject,validateTeam,vercelAuthBlockerReason};
|
|
1
|
+
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{object,string}from"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{assertNoLegacyProjectLinkDirectory}from"./project-resolution.js";import{withSpinner}from"./with-spinner.js";import{isConflictApiFailure,isForbiddenApiFailure,isNotFoundApiFailure,normalizeVercelApiResult}from"./vercel-api-failure.js";import{listRecentProjects,listTeams,parseVercelJson,requireVercelTeamAccess,searchProjects}from"./vercel-project-api.js";import{hasVercelHostFramework}from"#setup/scaffold/index.js";import{captureVercel,runVercel}from"#setup/primitives/index.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{whimsyFor}from"#setup/cli/index.js";var import_picocolors=__toESM(require_picocolors(),1);const VercelProjectReferenceSchema=object({id:string().min(1),name:string().min(1)});function unresolvedProject(){return{kind:`unresolved`}}function projectIdFromResolution(e){return e.kind===`unresolved`?void 0:e.projectId}function parseProjectReference(e,t){let n=VercelProjectReferenceSchema.safeParse(parseVercelJson(e,t));if(!n.success)throw Error(`Could not read Vercel project identity from ${t}.`);return{projectId:n.data.id,projectName:n.data.name}}async function resolveProjectByNameOrId(e,t,n,r={}){let i=normalizeVercelApiResult(await captureVercel([`api`,`/v9/projects/${encodeURIComponent(n)}`,`--scope`,t,`--raw`],{cwd:e,signal:r.signal}));if(i.ok)return parseProjectReference(i.stdout,`project ${n}`);if(isNotFoundApiFailure(i.failure))return null;throw isForbiddenApiFailure(i.failure)&&requireVercelTeamAccess(i.failure),Error(`Could not resolve project "${n}" in ${t}. ${i.failure.message}`)}async function createProject(e,t,n,r,i){let a=[`api`,`/v10/projects`,`--scope`,t,`--method`,`POST`,`--raw-field`,`name=${n}`];await hasVercelHostFramework(e)||a.push(`--raw-field`,`framework=eve`),a.push(`--raw`);let c=normalizeVercelApiResult(await captureVercel(a,{cwd:e,onOutput:r,signal:i.signal}));if(c.ok)return parseProjectReference(c.stdout,`created project ${n}`);throw isConflictApiFailure(c.failure)?Error(projectNameCollisionMessage(n,t)):(isForbiddenApiFailure(c.failure)&&requireVercelTeamAccess(c.failure),Error(`Could not create Vercel project "${n}" in ${t}. ${c.failure.message}`))}function projectNameCollisionMessage(e,t){return`Vercel project "${e}" already exists in ${t}. Pass --project ${e} to link it, or choose a different project name.`}async function assertNewProjectNameAvailable(e,t,n,r={}){if(await resolveProjectByNameOrId(e,t,n,r)!==null)throw Error(projectNameCollisionMessage(n,t))}function requireVercelLogin(e){let t=`Provisioning a Vercel project requires you to be logged in to Vercel.`,n=e?.stderr.trim();throw new HumanActionRequiredError({kind:`vercel-login`,command:`vercel login`,reason:e?`${t} The Vercel CLI check did not succeed: ${e.message}${n?` ${n}`:``}`:t})}function probeWhoami(e,t){return captureVercel([`whoami`],{cwd:e,signal:t.signal,timeoutMs:1e4})}function isLoggedOutFailure(e){let t=`${e.stdout} ${e.stderr}`.toLowerCase();return t.includes(`credentials`)||t.includes(`not authenticated`)||t.includes(`not logged in`)}function requireVercelAuth(e){if(e.errno===`ENOENT`)throw new HumanActionRequiredError({kind:`vercel-cli-missing`,command:`npm i -g vercel@latest`,reason:e.message});isLoggedOutFailure(e)&&requireVercelLogin(e);let t=e.stderr.trim();throw Error(`Couldn't verify your Vercel login: ${e.message}${t?` ${t}`:``}`)}function vercelAuthBlockerReason(e){switch(e){case`authenticated`:return;case`cli-missing`:return`Vercel CLI not found, see /vc`;case`logged-out`:return`Log in to Vercel first, see /login`;case`unavailable`:return`Couldn't reach Vercel, check your connection`;default:return e}}async function getVercelAuthStatus(e,t={}){let n=await probeWhoami(e,t);return t.signal?.throwIfAborted(),n.ok?`authenticated`:n.failure.errno===`ENOENT`?`cli-missing`:isLoggedOutFailure(n.failure)?`logged-out`:`unavailable`}async function requireAuth(e,t,n={}){let check=async()=>{let t=await probeWhoami(e,n);n.signal?.throwIfAborted(),t.ok||requireVercelAuth(t.failure)};if(t===void 0){await check();return}await withSpinner(t,whimsyFor(`auth`),check)}async function isVercelAuthenticated(e,t={}){return await getVercelAuthStatus(e,t)===`authenticated`}async function whoamiScope(e,t){let n=await probeWhoami(e,t);return t.signal?.throwIfAborted(),n.ok||requireVercelAuth(n.failure),n.stdout.trim()}async function resolveTeam(e,t,n={}){return t===void 0?(await listTeams(e,n)).find(e=>e.current)?.slug??await whoamiScope(e,n):t}async function validateTeam(e,t,n,r={}){if(n===void 0)return;let i=await listTeams(t,r);if(i.length>0&&!i.some(e=>e.slug===n))throw Error(`Team "${n}" was not found in \`vercel teams ls\`. Pass a valid team slug or omit --team.`)}async function pickTeam(e,t,n,r={}){if(n!==void 0)return await validateTeam(e,t,n,r),resolveTeam(t,n,r);let i=await withSpinner(e,whimsyFor(`teams`),()=>listTeams(t,r));return i.length<=1?i.find(e=>e.current)?.slug??await whoamiScope(t,r):e.select({message:`Select your team`,search:!0,placeholder:`type to search teams`,options:i.map(e=>({value:e.slug,label:e.current?`${e.name} (current)`:e.name})),initialValue:i.find(e=>e.current)?.slug})}const SEARCH_PROJECT_PREFIX=`\0search-project:`;function appendProjects(e,t){return[...new Map([...e,...t].map(e=>[e.id,e])).values()]}async function pickProject(e,t,n,r={}){let i=await withSpinner(e,whimsyFor(`projects`,n),()=>listRecentProjects(t,n,r));if(i.length===0){if(r.allowCreateWhenEmpty===!1)throw Error(`No existing Vercel projects found in ${n}. Create one in Vercel, then try again.`);return{kind:`new`,project:await e.text({message:`No projects found in ${n}. Enter a project name to create`,validate:e=>e.trim().length===0?`Project name cannot be empty.`:void 0}),team:n}}for(;;){let o=await e.select({message:`Project to link`,search:!0,placeholder:`type to filter projects`,searchAction:{label:e=>`Search for '${e}'`,value:e=>`${SEARCH_PROJECT_PREFIX}${e}`,load:async e=>{let a=await searchProjects(t,n,e,{signal:r.signal});return i=appendProjects(i,a),i.map(e=>({value:e.id,label:e.name}))}},options:i.map(e=>({value:e.id,label:e.name})),initialValue:i[0]?.id}),s=o.startsWith(SEARCH_PROJECT_PREFIX)?o.slice(16):void 0;if(s===void 0){let e=i.find(e=>e.id===o);if(e===void 0)throw Error(`Selected Vercel project is not available.`);return{kind:`existing`,project:{projectId:e.id,projectName:e.name},team:n}}let c=await withSpinner(e,`Searching ${n} for "${s}"...`,()=>searchProjects(t,n,s,{signal:r.signal}));if(c.length===0){e.note(`No projects matched "${s}" in ${n}.`);continue}i=appendProjects(i,c)}}async function pickNewProjectName(e,t,n,r,i={}){let o=await withSpinner(e,whimsyFor(`project-name`,n),()=>resolveProjectByNameOrId(t,n,r.trim(),i)),s=r.trim();for(;o!==null;)s=(await e.text({message:`New project name`,defaultValue:`${s}-2`,notices:[{tone:`warning`,text:`${import_picocolors.default.yellow(`Project named`)} '${import_picocolors.default.blue(s)}' ${import_picocolors.default.yellow(`already exists in`)} '${import_picocolors.default.blue(n)}'`}],validate:e=>{if(e.trim().length===0)return`Project name cannot be empty.`}})).trim(),o=await resolveProjectByNameOrId(t,n,s,i);return s}async function linkProject(e,t,n,r,o={}){await assertNoLegacyProjectLinkDirectory(t);let s=[`--scope`,n.team],c;return c=n.kind===`new`?await withSpinner(e,`Creating Vercel project "${n.project}" in ${n.team}...`,async()=>(await assertNewProjectNameAvailable(t,n.team,n.project,o),createProject(t,n.team,n.project,r,o))):n.project,await withSpinner(e,`Linking this directory to Vercel project "${c.projectName}"...`,()=>runVercel([`link`,`--project`,c.projectId,...s,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,signal:o.signal}))?c:void 0}export{assertNewProjectNameAvailable,getVercelAuthStatus,isVercelAuthenticated,linkProject,pickNewProjectName,pickProject,pickTeam,projectIdFromResolution,requireAuth,requireVercelAuth,requireVercelLogin,resolveProjectByNameOrId,resolveTeam,unresolvedProject,validateTeam,vercelAuthBlockerReason};
|
|
@@ -313,16 +313,14 @@ const githubAuth = connect({
|
|
|
313
313
|
|
|
314
314
|
The tool's `ctx` exposes provider-scoped auth accessors:
|
|
315
315
|
|
|
316
|
-
- `ctx.getToken(provider, options?)` resolves an inline provider such as `connect("github/myagent")`. It uses the same cache, callback, and sign-in machinery as connection auth, scoped to that provider
|
|
316
|
+
- `ctx.getToken(provider, options?)` resolves an inline provider such as `connect("github/myagent")`. It uses the same cache, callback, and sign-in machinery as connection auth, scoped to that provider's tool-qualified auth key.
|
|
317
317
|
- `ctx.requireAuth(provider, options?)` evicts the cached token for that inline provider and starts a fresh authorization challenge. Use it after a downstream `401` rejects a token returned by `ctx.getToken(provider)`.
|
|
318
318
|
|
|
319
319
|
Throw `ConnectionAuthorizationRequiredError` from an inline provider's `getToken` to trigger the consent flow for that provider. If a downstream request later rejects an already-resolved token, call `ctx.requireAuth(provider)` to evict and re-authorize it.
|
|
320
320
|
|
|
321
321
|
Vercel Connect providers usually supply their own display name in the authorization challenge. Set `displayName` in the inline options only when you need to override what users see, for example `ctx.getToken(customAuth, { displayName: "Salesforce" })`. It is presentation-only.
|
|
322
322
|
|
|
323
|
-
Inline providers derive a stable tool-qualified auth key from Vercel Connect metadata when available. If you pass multiple custom providers that do not carry provider metadata, give each one an explicit auth key, for example `ctx.getToken(auth, { authKey: "github" })`. This `authKey` controls
|
|
324
|
-
|
|
325
|
-
Older tools may still declare a top-level `auth` field and call `ctx.getToken()` or `ctx.requireAuth()` without arguments. That compatibility path is deprecated; prefer inline providers for new tools.
|
|
323
|
+
Inline providers derive a stable tool-qualified auth key from Vercel Connect metadata when available. If you pass multiple custom providers that do not carry provider metadata, give each one an explicit auth key, for example `ctx.getToken(auth, { authKey: "github" })`. This `authKey` controls eve's cache and callback keys; it is not an OAuth scope.
|
|
326
324
|
|
|
327
325
|
## What to read next
|
|
328
326
|
|
package/docs/guides/dev-tui.md
CHANGED
|
@@ -48,7 +48,7 @@ Each command echoes as an invocation line, asks through a bordered panel that ta
|
|
|
48
48
|
|
|
49
49
|
Bare `/model` opens the configure menu. When no provider is configured, it opens the provider questions directly; Esc returns to the configure menu. "Change model" runs the same searchable model picker setup uses (the Vercel AI Gateway catalog, pre-selected on the model the runtime is serving). A model change is written into your agent's authored source, and the command reports success only after eve confirms the new id. `/model <provider/model-id>` applies one directly, skipping the menu.
|
|
50
50
|
|
|
51
|
-
The provider row opens the provider questions: which model provider to use, and how to connect. Picking something other than Vercel AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched. For Vercel AI Gateway, you either paste your own `AI_GATEWAY_API_KEY` (saved straight to `.env.local`) or connect via a project. Connecting via a project asks for a Vercel team, opens that team's
|
|
51
|
+
The provider row opens the provider questions: which model provider to use, and how to connect. Picking something other than Vercel AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched. For Vercel AI Gateway, you either paste your own `AI_GATEWAY_API_KEY` (saved straight to `.env.local`) or connect via a project. Connecting via a project asks for a Vercel team, opens that team's recent projects, and lets you search all projects for older matches. Vercel links the selected project, eve verifies its project ID, then pulls its environment into `.env.local`. The dev TUI reloads env files, re-reads the runtime's model endpoint, and clears the setup warning automatically; no restart is needed.
|
|
52
52
|
|
|
53
53
|
The provider row demands attention (a bold yellow "Configure provider" with "Required to enable the agent") until a link or gateway credential is detected, then names the connection afterward (for example "AI Gateway (Linked to my-project in my-team)"). Each action's latest outcome stays visible beneath the menu (for example "✓ Model changed to openai/gpt-5.5"). When a turn fails because AI Gateway authentication is missing or stale, the error points you at `/model` directly.
|
|
54
54
|
|
package/docs/reference/cli.md
CHANGED
|
@@ -119,7 +119,7 @@ Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snaps
|
|
|
119
119
|
eve link
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
Links the current directory to an existing Vercel project. You select a team and then a project
|
|
122
|
+
Links the current directory to an existing Vercel project. You select a team and then one of its recent projects; type a project name and choose **Search for '<name>'** to search the rest of that team's projects. Vercel links the selected project, eve verifies its project ID, and then pulls the project's environment so an AI Gateway credential (`VERCEL_OIDC_TOKEN` or `AI_GATEWAY_API_KEY`) lands in `.env.local`. Running it again re-links: the pickers always run, and the new choice wins. The command is interactive only; in CI, use `vercel link --project <name> --yes --non-interactive` instead. A running `eve dev` reloads env files automatically, so you don't need to restart after the pull.
|
|
123
123
|
|
|
124
124
|
## `eve deploy`
|
|
125
125
|
|
|
@@ -63,8 +63,6 @@ A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWo
|
|
|
63
63
|
| `ctx.getSkill(identifier)` | Handle for a named skill visible to the current agent |
|
|
64
64
|
| `ctx.getToken(provider)` | Resolve a bearer token for an inline auth provider such as `connect("...")` |
|
|
65
65
|
| `ctx.requireAuth(provider)` | Evict and re-authorize an inline provider, commonly after a downstream `401` |
|
|
66
|
-
| `ctx.getToken()` | Deprecated compatibility path for a tool's legacy top-level `auth` |
|
|
67
|
-
| `ctx.requireAuth()` | Deprecated compatibility path for a tool's legacy top-level `auth` |
|
|
68
66
|
|
|
69
67
|
## Imports at a glance
|
|
70
68
|
|