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
|
@@ -10,6 +10,15 @@ export interface PackageManagerConfigurationResult {
|
|
|
10
10
|
readonly filesSkipped: readonly string[];
|
|
11
11
|
readonly filesWritten: readonly string[];
|
|
12
12
|
}
|
|
13
|
+
/** Context for manager-owned project configuration. */
|
|
14
|
+
export interface PackageManagerConfigurationOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Final project path used to discover ancestor workspaces. This differs from
|
|
17
|
+
* `projectRoot` only when a scaffold is staged in a temporary directory
|
|
18
|
+
* before being moved into place.
|
|
19
|
+
*/
|
|
20
|
+
readonly workspaceProbeRoot?: string;
|
|
21
|
+
}
|
|
13
22
|
export interface PackageManagerInstallOptions {
|
|
14
23
|
/** Disables the manager's minimum-release-age cooldown for this run when supported. */
|
|
15
24
|
readonly bypassMinimumReleaseAge?: boolean;
|
|
@@ -30,7 +39,7 @@ export interface PackageManagerStrategy {
|
|
|
30
39
|
/** Manager-owned files included when creating a fresh project. */
|
|
31
40
|
readonly scaffoldFiles: Readonly<Record<string, string>>;
|
|
32
41
|
/** Adds or reconciles manager-owned configuration in an existing project. */
|
|
33
|
-
applyProjectConfiguration(projectRoot: string): Promise<PackageManagerConfigurationResult>;
|
|
42
|
+
applyProjectConfiguration(projectRoot: string, options?: PackageManagerConfigurationOptions): Promise<PackageManagerConfigurationResult>;
|
|
34
43
|
/** Arguments that run the project-local eve development command. */
|
|
35
44
|
devArguments(): readonly string[];
|
|
36
45
|
/** Arguments that install project dependencies. */
|
|
@@ -17,15 +17,18 @@ declare const VercelProjectReferenceSchema: z.ZodObject<{
|
|
|
17
17
|
export type VercelProjectReference = z.infer<typeof VercelProjectReferenceSchema>;
|
|
18
18
|
/** Parses the complete Vercel owner and project environment pair. */
|
|
19
19
|
export declare function projectReferenceFromEnvironment(environment: Readonly<Record<string, string | undefined>>): VercelProjectReference | undefined;
|
|
20
|
-
/**
|
|
20
|
+
/** Rejects Vercel's unsupported legacy link directory before link mutation. */
|
|
21
|
+
export declare function assertNoLegacyProjectLinkDirectory(projectRoot: string): Promise<void>;
|
|
22
|
+
/** Reads a validated project reference from Vercel's link metadata directory. */
|
|
21
23
|
export declare function readProjectLink(projectPath: string): Promise<VercelProjectReference | undefined>;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
/** Cancellation options shared by Vercel project read/operation helpers. */
|
|
25
|
+
export interface VercelProjectOperationOptions {
|
|
26
|
+
readonly signal?: AbortSignal;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* Reads local Vercel link metadata and checks whether the linked project has a production alias.
|
|
27
30
|
*/
|
|
28
|
-
export declare function detectDeployment(projectPath: string, options?:
|
|
31
|
+
export declare function detectDeployment(projectPath: string, options?: VercelProjectOperationOptions): Promise<DeploymentInfo>;
|
|
29
32
|
/** Human-readable identity of a linked Vercel project, for the dashboard status bar. */
|
|
30
33
|
export interface ProjectIdentity {
|
|
31
34
|
projectName: string;
|
|
@@ -43,7 +46,7 @@ export interface ProjectIdentity {
|
|
|
43
46
|
*
|
|
44
47
|
* @param projectPath Absolute path of the linked project directory.
|
|
45
48
|
*/
|
|
46
|
-
export declare function detectProjectIdentity(projectPath: string, options?:
|
|
49
|
+
export declare function detectProjectIdentity(projectPath: string, options?: VercelProjectOperationOptions): Promise<ProjectIdentity | undefined>;
|
|
47
50
|
export type ProjectResolution = {
|
|
48
51
|
kind: "unresolved";
|
|
49
52
|
} | {
|
|
@@ -59,7 +62,7 @@ export declare function projectResolutionFromDeployment(deployment: DeploymentIn
|
|
|
59
62
|
* Side-effect-free fact gathering after a link: reads `.vercel/project.json`
|
|
60
63
|
* to resolve the project. The on-disk link is the single source of truth.
|
|
61
64
|
*/
|
|
62
|
-
export declare function detectProjectResolution(projectRoot: string, options?:
|
|
65
|
+
export declare function detectProjectResolution(projectRoot: string, options?: VercelProjectOperationOptions): Promise<ProjectResolution>;
|
|
63
66
|
export declare function mergeProjectResolution(current: ProjectResolution, next: ProjectResolution): ProjectResolution;
|
|
64
67
|
export declare function projectResolutionFromDeployResult(project: ProjectResolution, deploy: {
|
|
65
68
|
deployed: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
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{captureVercel}from"./primitives/run-vercel.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const VercelProjectReferenceSchema=object({projectId:string().min(1),orgId:string().min(1),projectName:string().min(1).optional()}),VercelProjectEnvironmentSchema=object({VERCEL_ORG_ID:VercelProjectReferenceSchema.shape.orgId,VERCEL_PROJECT_ID:VercelProjectReferenceSchema.shape.projectId});function projectReferenceFromEnvironment(e){let t=VercelProjectEnvironmentSchema.safeParse(e);if(t.success)return{orgId:t.data.VERCEL_ORG_ID,projectId:t.data.VERCEL_PROJECT_ID}}async function readProjectLink(e){try{let t=await readFile(join(e,`.vercel`,`project.json`),`utf8`),n=VercelProjectReferenceSchema.safeParse(JSON.parse(t));return n.success?n.data:void 0}catch{return}}function pickShortestAlias(e){if(!Array.isArray(e))return;let t;for(let n of e)typeof n!=`string`||n.length===0||(t===void 0||n.length<t.length)&&(t=n);return t}async function fetchProductionAlias(e,t,r,i){let a=await captureVercel([`api`,`/v9/projects/${e}?teamId=${t}`,`--scope`,t],{cwd:r,signal:i.signal});if(a.ok)try{let e=pickShortestAlias(JSON.parse(a.stdout).targets?.production?.alias);return e?`https://${e}`:void 0}catch{return}}async function detectDeployment(e,t={}){t.signal?.throwIfAborted();let n=await readProjectLink(e);if(n===void 0)return{state:`unlinked`};let r=await fetchProductionAlias(n.projectId,n.orgId,e,t);return t.signal?.throwIfAborted(),{state:r?`deployed`:`linked`,projectId:n.projectId,orgId:n.orgId,productionUrl:r}}async function fetchVercelName(e,t,r,i){let a=await captureVercel([`api`,e,`--scope`,t],{cwd:r,signal:i.signal});if(a.ok)try{let e=JSON.parse(a.stdout);return typeof e.name==`string`&&e.name.length>0?e.name:typeof e.slug==`string`&&e.slug.length>0?e.slug:void 0}catch{return}}async function detectProjectIdentity(e,t={}){t.signal?.throwIfAborted();let n=await readProjectLink(e);if(n===void 0)return;let[r,i]=await Promise.all([fetchVercelName(`/v9/projects/${n.projectId}?teamId=${n.orgId}`,n.orgId,e,t).then(e=>e??n.projectId),n.orgId.startsWith(`team_`)?fetchVercelName(`/v2/teams/${n.orgId}`,n.orgId,e,t):Promise.resolve(void 0)]);return t.signal?.throwIfAborted(),{projectName:r,teamName:i}}function projectResolutionFromDeployment(e){return e.state===`unlinked`||e.projectId===void 0?{kind:`unresolved`}:e.state===`deployed`&&e.productionUrl!==void 0?{kind:`deployed`,projectId:e.projectId,productionUrl:e.productionUrl}:{kind:`linked`,projectId:e.projectId}}async function detectProjectResolution(e,t={}){return projectResolutionFromDeployment(await detectDeployment(e,t))}function mergeProjectResolution(e,t){return t.kind===`unresolved`||e.kind===`deployed`&&e.projectId===t.projectId?e:t}function projectResolutionFromDeployResult(e,t){return e.kind===`unresolved`||!t.deployed||t.productionUrl===void 0?e:{kind:`deployed`,projectId:e.projectId,productionUrl:t.productionUrl}}function isProjectResolved(e){return e.kind!==`unresolved`}function projectProductionUrlFromResolution(e){return e.kind===`deployed`?e.productionUrl:void 0}export{detectDeployment,detectProjectIdentity,detectProjectResolution,isProjectResolved,mergeProjectResolution,projectProductionUrlFromResolution,projectReferenceFromEnvironment,projectResolutionFromDeployResult,projectResolutionFromDeployment,readProjectLink};
|
|
1
|
+
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{captureVercel}from"./primitives/run-vercel.js";import{join}from"node:path";import{readFile,stat}from"node:fs/promises";const VercelProjectReferenceSchema=object({projectId:string().min(1),orgId:string().min(1),projectName:string().min(1).optional()}),VercelProjectEnvironmentSchema=object({VERCEL_ORG_ID:VercelProjectReferenceSchema.shape.orgId,VERCEL_PROJECT_ID:VercelProjectReferenceSchema.shape.projectId});function projectReferenceFromEnvironment(e){let t=VercelProjectEnvironmentSchema.safeParse(e);if(t.success)return{orgId:t.data.VERCEL_ORG_ID,projectId:t.data.VERCEL_PROJECT_ID}}async function assertNoLegacyProjectLinkDirectory(e){try{if(!(await stat(join(e,`.now`))).isDirectory())return}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}throw Error("Legacy Vercel link directory `.now` is not supported. Remove `.now` before linking this project.")}async function readProjectLink(e){await assertNoLegacyProjectLinkDirectory(e);try{let t=await readFile(join(e,`.vercel`,`project.json`),`utf8`),n=VercelProjectReferenceSchema.safeParse(JSON.parse(t));return n.success?n.data:void 0}catch{return}}function pickShortestAlias(e){if(!Array.isArray(e))return;let t;for(let n of e)typeof n!=`string`||n.length===0||(t===void 0||n.length<t.length)&&(t=n);return t}async function fetchProductionAlias(e,t,r,i){let a=await captureVercel([`api`,`/v9/projects/${e}?teamId=${t}`,`--scope`,t],{cwd:r,signal:i.signal});if(a.ok)try{let e=pickShortestAlias(JSON.parse(a.stdout).targets?.production?.alias);return e?`https://${e}`:void 0}catch{return}}async function detectDeployment(e,t={}){t.signal?.throwIfAborted();let n=await readProjectLink(e);if(n===void 0)return{state:`unlinked`};let r=await fetchProductionAlias(n.projectId,n.orgId,e,t);return t.signal?.throwIfAborted(),{state:r?`deployed`:`linked`,projectId:n.projectId,orgId:n.orgId,productionUrl:r}}async function fetchVercelName(e,t,r,i){let a=await captureVercel([`api`,e,`--scope`,t],{cwd:r,signal:i.signal});if(a.ok)try{let e=JSON.parse(a.stdout);return typeof e.name==`string`&&e.name.length>0?e.name:typeof e.slug==`string`&&e.slug.length>0?e.slug:void 0}catch{return}}async function detectProjectIdentity(e,t={}){t.signal?.throwIfAborted();let n=await readProjectLink(e);if(n===void 0)return;let[r,i]=await Promise.all([fetchVercelName(`/v9/projects/${n.projectId}?teamId=${n.orgId}`,n.orgId,e,t).then(e=>e??n.projectId),n.orgId.startsWith(`team_`)?fetchVercelName(`/v2/teams/${n.orgId}`,n.orgId,e,t):Promise.resolve(void 0)]);return t.signal?.throwIfAborted(),{projectName:r,teamName:i}}function projectResolutionFromDeployment(e){return e.state===`unlinked`||e.projectId===void 0?{kind:`unresolved`}:e.state===`deployed`&&e.productionUrl!==void 0?{kind:`deployed`,projectId:e.projectId,productionUrl:e.productionUrl}:{kind:`linked`,projectId:e.projectId}}async function detectProjectResolution(e,t={}){return projectResolutionFromDeployment(await detectDeployment(e,t))}function mergeProjectResolution(e,t){return t.kind===`unresolved`||e.kind===`deployed`&&e.projectId===t.projectId?e:t}function projectResolutionFromDeployResult(e,t){return e.kind===`unresolved`||!t.deployed||t.productionUrl===void 0?e:{kind:`deployed`,projectId:e.projectId,productionUrl:t.productionUrl}}function isProjectResolved(e){return e.kind!==`unresolved`}function projectProductionUrlFromResolution(e){return e.kind===`deployed`?e.productionUrl:void 0}export{assertNoLegacyProjectLinkDirectory,detectDeployment,detectProjectIdentity,detectProjectResolution,isProjectResolved,mergeProjectResolution,projectProductionUrlFromResolution,projectReferenceFromEnvironment,projectResolutionFromDeployResult,projectResolutionFromDeployment,readProjectLink};
|
|
@@ -88,11 +88,24 @@ export interface SelectCommonOptions<T extends PrompterValue> {
|
|
|
88
88
|
/** Outcome lines from earlier laps of a looping menu. */
|
|
89
89
|
notices?: readonly SelectNotice[];
|
|
90
90
|
}
|
|
91
|
+
/** A selectable action appended after local matches for a non-empty query. */
|
|
92
|
+
export interface SearchAction<T extends PrompterValue> {
|
|
93
|
+
label(query: string): string;
|
|
94
|
+
value(query: string): T;
|
|
95
|
+
/**
|
|
96
|
+
* Loads replacement rows without closing a repainting picker. Plain CLI
|
|
97
|
+
* prompts still return {@link value}; the TUI keeps the search input open
|
|
98
|
+
* and shows the wait beside it.
|
|
99
|
+
*/
|
|
100
|
+
load?(query: string): Promise<readonly SelectOption<T>[]>;
|
|
101
|
+
}
|
|
91
102
|
/** Single-select form: navigate, then enter picks the highlighted option. */
|
|
92
103
|
export interface SingleSelectOptions<T extends PrompterValue> extends SelectCommonOptions<T> {
|
|
93
104
|
multiple?: false;
|
|
94
105
|
/** Pre-position the cursor on the option whose value matches. */
|
|
95
106
|
initialValue?: T;
|
|
107
|
+
/** Appended after local matches for each non-empty query. Requires `search: true`. */
|
|
108
|
+
searchAction?: SearchAction<T>;
|
|
96
109
|
}
|
|
97
110
|
/** Multi-select form: space or enter toggles rows; enter on the trailing Submit row confirms the marked set. */
|
|
98
111
|
export interface MultiSelectOptions<T extends PrompterValue> extends SelectCommonOptions<T> {
|
|
@@ -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{WizardCancelledError}from"./step.js";import{h,ht,q}from"../node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js";import{initialQuitGuardState,quitHintNote,reduceQuitGuard}from"./quit-guard.js";import{cornerFor,createRailLog,formatPromptCancellation,formatPromptHeader,formatPromptOpener,formatPromptOutro,formatPromptSubmission,formatRailLine,railFor,runSelectComponent}from"#setup/cli/index.js";var import_picocolors=__toESM(require_picocolors(),1);function guardCancel(e){if(q(e))throw process.stdout.write(formatPromptCancellation(`Setup cancelled.`,import_picocolors.default)),new WizardCancelledError;return e}let escapeCancelDisabled=!1;function disableEscapeCancel(){escapeCancelDisabled||=(h.aliases.delete(`escape`),!0)}function attachQuitGuard(e){let t=initialQuitGuardState;return e.on(`key`,(n,r)=>{let{state:i,action:a}=reduceQuitGuard(t,r?.name===`escape`?{type:`escape`}:{type:`other-key`});t=i,a===`quit`&&(e.state=`cancel`)}),{note:()=>quitHintNote(t,import_picocolors.default)}}function toPromptState(e){return e}function railForState(e){return railFor(toPromptState(e),import_picocolors.default)}function cornerForState(e){return cornerFor(toPromptState(e),import_picocolors.default)}function header(e,t,n){return formatPromptHeader(toPromptState(e),t,{colors:import_picocolors.default,leadingRail:n===0?`white`:`green`})}const REDACTED_DISPLAY=`••••••••`;function textPrompt(e,t){let n,r=new ht({validate:t.validate?e=>t.validate?.(e??``):void 0,placeholder:t.placeholder,defaultValue:t.defaultValue,render(){let r=header(this.state,t.message,e),i=t.placeholder?import_picocolors.default.inverse(t.placeholder[0])+import_picocolors.default.dim(t.placeholder.slice(1)):import_picocolors.default.inverse(import_picocolors.default.hidden(`_`)),a=this.value?`•`.repeat(this.value.length):i,o=i;switch(t.mask?o=a:this.value&&(o=this.userInputWithCursor),this.state){case`error`:return`${r.trim()}\n${railForState(this.state)} ${o}\n${cornerForState(this.state)} ${import_picocolors.default.red(this.error)}\n`;case`submit`:{let n=this.value||t.placeholder||``;return t.mask&&(n=this.value?REDACTED_DISPLAY:t.placeholder??``),formatPromptSubmission(this.state,t.message,n,{colors:import_picocolors.default,leadingRail:e===0?`white`:`green`})}case`cancel`:return`${r}${railForState(this.state)} ${import_picocolors.default.strikethrough(import_picocolors.default.dim(t.mask&&this.value?REDACTED_DISPLAY:this.value??``))}${this.value?.trim()?`\n${railForState(this.state)}`:``}`;default:return`${r}${railForState(this.state)} ${o}\n${cornerForState(this.state)}${cornerNote(n?.note())}\n`}}});return n=attachQuitGuard(r),r.prompt()}function cornerNote(e){return e?` ${e}`:``}function createPrompter(){disableEscapeCancel();let e=0,t=createRailLog({colors:import_picocolors.default,output:process.stdout});function printNotices(e){for(let n of e??[])n.tone===`success`?t.success(n.text):n.tone===`warning`?t.warning(n.text):n.tone===`error`?t.error(n.text):t.message(n.text)}return{async text(n){t.settle(),printNotices(n.notices);let r=guardCancel(await textPrompt(e,n));return e+=1,r??``},async password(n){t.settle();let r=guardCancel(await textPrompt(e,{message:n.message,mask:!0,validate:n.validate}));return e+=1,r??``},async select(n){t.settle(),printNotices(n.notices);let r=guardCancel(await runSelectComponent({message:n.message,options:n.options,multiple:n.multiple===!0,search:n.search??!1,required:n.required??!1,placeholder:n.placeholder,defaultValue:n.multiple===!0?void 0:n.initialValue,initialValues:n.multiple===!0?n.initialValues:void 0,leadingRail:e===0?`white`:`green`,attachGuard:e=>attachQuitGuard(e)}));return e+=1,r},async acknowledge(e){t.settle(),process.stdout.write(formatRailLine(import_picocolors.default.bold(e.message),import_picocolors.default,process.stdout));for(let t of e.lines??[])process.stdout.write(formatRailLine(import_picocolors.default.dim(t),import_picocolors.default,process.stdout))},note(e,n,r){t.settle();let i=r?.tone===`success`?import_picocolors.default.green:import_picocolors.default.red;n&&process.stdout.write(formatRailLine(i(import_picocolors.default.bold(n)),import_picocolors.default,process.stdout)),process.stdout.write(formatRailLine(i(e),import_picocolors.default,process.stdout))},intro(e,n=`Production-grade agent framework.`){t.settle(),process.stdout.write(formatPromptOpener(e,n,import_picocolors.default))},outro(e){t.settle(),process.stdout.write(formatPromptOutro(e,import_picocolors.default))},log:t}}export{createPrompter};
|
|
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{WizardCancelledError}from"./step.js";import{h,ht,q}from"../node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js";import{initialQuitGuardState,quitHintNote,reduceQuitGuard}from"./quit-guard.js";import{cornerFor,createRailLog,formatPromptCancellation,formatPromptHeader,formatPromptOpener,formatPromptOutro,formatPromptSubmission,formatRailLine,railFor,runSelectComponent}from"#setup/cli/index.js";var import_picocolors=__toESM(require_picocolors(),1);function guardCancel(e){if(q(e))throw process.stdout.write(formatPromptCancellation(`Setup cancelled.`,import_picocolors.default)),new WizardCancelledError;return e}let escapeCancelDisabled=!1;function disableEscapeCancel(){escapeCancelDisabled||=(h.aliases.delete(`escape`),!0)}function attachQuitGuard(e){let t=initialQuitGuardState;return e.on(`key`,(n,r)=>{let{state:i,action:a}=reduceQuitGuard(t,r?.name===`escape`?{type:`escape`}:{type:`other-key`});t=i,a===`quit`&&(e.state=`cancel`)}),{note:()=>quitHintNote(t,import_picocolors.default)}}function toPromptState(e){return e}function railForState(e){return railFor(toPromptState(e),import_picocolors.default)}function cornerForState(e){return cornerFor(toPromptState(e),import_picocolors.default)}function header(e,t,n){return formatPromptHeader(toPromptState(e),t,{colors:import_picocolors.default,leadingRail:n===0?`white`:`green`})}const REDACTED_DISPLAY=`••••••••`;function textPrompt(e,t){let n,r=new ht({validate:t.validate?e=>t.validate?.(e??``):void 0,placeholder:t.placeholder,defaultValue:t.defaultValue,render(){let r=header(this.state,t.message,e),i=t.placeholder?import_picocolors.default.inverse(t.placeholder[0])+import_picocolors.default.dim(t.placeholder.slice(1)):import_picocolors.default.inverse(import_picocolors.default.hidden(`_`)),a=this.value?`•`.repeat(this.value.length):i,o=i;switch(t.mask?o=a:this.value&&(o=this.userInputWithCursor),this.state){case`error`:return`${r.trim()}\n${railForState(this.state)} ${o}\n${cornerForState(this.state)} ${import_picocolors.default.red(this.error)}\n`;case`submit`:{let n=this.value||t.placeholder||``;return t.mask&&(n=this.value?REDACTED_DISPLAY:t.placeholder??``),formatPromptSubmission(this.state,t.message,n,{colors:import_picocolors.default,leadingRail:e===0?`white`:`green`})}case`cancel`:return`${r}${railForState(this.state)} ${import_picocolors.default.strikethrough(import_picocolors.default.dim(t.mask&&this.value?REDACTED_DISPLAY:this.value??``))}${this.value?.trim()?`\n${railForState(this.state)}`:``}`;default:return`${r}${railForState(this.state)} ${o}\n${cornerForState(this.state)}${cornerNote(n?.note())}\n`}}});return n=attachQuitGuard(r),r.prompt()}function cornerNote(e){return e?` ${e}`:``}function createPrompter(){disableEscapeCancel();let e=0,t=createRailLog({colors:import_picocolors.default,output:process.stdout});function printNotices(e){for(let n of e??[])n.tone===`success`?t.success(n.text):n.tone===`warning`?t.warning(n.text):n.tone===`error`?t.error(n.text):t.message(n.text)}return{async text(n){t.settle(),printNotices(n.notices);let r=guardCancel(await textPrompt(e,n));return e+=1,r??``},async password(n){t.settle();let r=guardCancel(await textPrompt(e,{message:n.message,mask:!0,validate:n.validate}));return e+=1,r??``},async select(n){t.settle(),printNotices(n.notices);let r=guardCancel(await runSelectComponent({message:n.message,options:n.options,multiple:n.multiple===!0,search:n.search??!1,searchAction:n.multiple===!0?void 0:n.searchAction,required:n.required??!1,placeholder:n.placeholder,defaultValue:n.multiple===!0?void 0:n.initialValue,initialValues:n.multiple===!0?n.initialValues:void 0,leadingRail:e===0?`white`:`green`,attachGuard:e=>attachQuitGuard(e)}));return e+=1,r},async acknowledge(e){t.settle(),process.stdout.write(formatRailLine(import_picocolors.default.bold(e.message),import_picocolors.default,process.stdout));for(let t of e.lines??[])process.stdout.write(formatRailLine(import_picocolors.default.dim(t),import_picocolors.default,process.stdout))},note(e,n,r){t.settle();let i=r?.tone===`success`?import_picocolors.default.green:import_picocolors.default.red;n&&process.stdout.write(formatRailLine(i(import_picocolors.default.bold(n)),import_picocolors.default,process.stdout)),process.stdout.write(formatRailLine(i(e),import_picocolors.default,process.stdout))},intro(e,n=`Production-grade agent framework.`){t.settle(),process.stdout.write(formatPromptOpener(e,n,import_picocolors.default))},outro(e){t.settle(),process.stdout.write(formatPromptOutro(e,import_picocolors.default))},log:t}}export{createPrompter};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"../update/package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{agentTemplateFiles,formatEveDependencySpecifier,resolveEvePackageContract}from"./project.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=i.packageManager??`pnpm`,o=join(i.projectRoot,`package.json`);if(!await pathExists(o))throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let s=agentTemplateFiles(i.model),c=[];for(let t of Object.keys(s))await pathExists(join(i.projectRoot,t))&&c.push(t);if(c.length===0&&await pathExists(join(i.projectRoot,`agent`))&&c.push(`agent/`),c.length>0)throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it already has: ${c.join(`, `)}.`);let l=resolveEvePackageContract(i.evePackage),u=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`7.0.0-beta.178`),d=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.2.2`),f=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),p=[];for(let[e,n]of Object.entries(s)){let r=join(i.projectRoot,e);await writeTextFile(r,n),p.push(r)}let m=JSON.parse(await readFile(o,`utf8`)),h={"@vercel/connect":d,ai:u,eve:formatEveDependencySpecifier(l.version),zod:f},g={};for(let[e,t]of Object.entries(h))hasDeclaredDependency(m,e)||(g[e]=t);let _={};Object.keys(g).length>0&&(_.dependencies=g),isPackageManagerWorkspaceMember(a,i.projectRoot)||(_.nodeEngineRequirement=l.nodeEngine);let v=await patchPackageJson(o,_),y=(await patchWorkspaceRootPackageJson(a,i.projectRoot,{aiPackageVersion:u,nodeEngineRequirement:l.nodeEngine})).nodeEngineOverride??v.nodeEngineOverride;return await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:i.projectRoot}),{filesWritten:p,dependenciesAdded:Object.keys(g).sort(),nodeEngineOverride:y}}export{addAgentToProject};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PackageManagerKind } from "../../package-manager.js";
|
|
2
|
+
import { type WorkspaceRootMutation } from "../workspace-root.js";
|
|
2
3
|
export declare const CURRENT_DIRECTORY_PROJECT_NAME = ".";
|
|
3
4
|
export declare const DEFAULT_AI_PACKAGE_VERSION = "__AI_SDK_VERSION__";
|
|
4
5
|
export declare const DEFAULT_CONNECT_PACKAGE_VERSION = "__VERCEL_CONNECT_VERSION__";
|
|
@@ -58,6 +59,13 @@ export interface ScaffoldBaseProjectOptions {
|
|
|
58
59
|
connectPackageVersion?: string;
|
|
59
60
|
zodPackageVersion?: string;
|
|
60
61
|
typescriptPackageVersion?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Final project path used to discover ancestor workspaces. This differs from
|
|
64
|
+
* the write target only when the CLI stages a scaffold before moving it into
|
|
65
|
+
* place.
|
|
66
|
+
*/
|
|
67
|
+
workspaceProbeDirectory?: string;
|
|
68
|
+
onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
61
69
|
/**
|
|
62
70
|
* Scaffold an inline provider `byok` block in `agent.ts` that reads the
|
|
63
71
|
* provider key from `process.env` instead of relying on the managed Vercel
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`7.0.0-beta.178`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.13.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
5
5
|
});
|
|
6
|
-
`;function packageJsonTemplate(){return`{
|
|
6
|
+
`;function packageJsonTemplate(e){return`{
|
|
7
7
|
"name": "__EVE_INIT_APP_NAME__",
|
|
8
8
|
"version": "0.0.0",
|
|
9
9
|
"type": "module",
|
|
@@ -26,7 +26,9 @@ export default defineAgent({
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "__EVE_INIT_TYPES_NODE_VERSION__",
|
|
28
28
|
"typescript": "__EVE_INIT_TYPESCRIPT_VERSION__"
|
|
29
|
-
}
|
|
29
|
+
}${e?ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX:``}
|
|
30
|
+
}
|
|
31
|
+
`}const ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX=`,
|
|
30
32
|
"overrides": {
|
|
31
33
|
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
32
34
|
},
|
|
@@ -36,8 +38,7 @@ export default defineAgent({
|
|
|
36
38
|
"engines": {
|
|
37
39
|
"node": "__EVE_INIT_NODE_ENGINE__"
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
`}const AGENT_INSTRUCTIONS_TEMPLATE=`# Identity
|
|
41
|
+
`,AGENT_INSTRUCTIONS_TEMPLATE=`# Identity
|
|
41
42
|
|
|
42
43
|
You are a helpful assistant.
|
|
43
44
|
`,SHARED_TEMPLATE_FILES={"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE,"tsconfig.json":`{
|
|
@@ -76,7 +77,7 @@ dist
|
|
|
76
77
|
|
|
77
78
|
This project uses the eve framework. Before writing code, always read the relevant guide in \`node_modules/eve/docs/\`.
|
|
78
79
|
`,"CLAUDE.md":`@AGENTS.md
|
|
79
|
-
`};function templateFiles(t
|
|
80
|
+
`};function templateFiles(e,t){return{"agent/agent.ts":e?`import { defineAgent } from "eve";
|
|
80
81
|
|
|
81
82
|
export default defineAgent({
|
|
82
83
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -90,4 +91,4 @@ export default defineAgent({
|
|
|
90
91
|
},
|
|
91
92
|
},
|
|
92
93
|
});
|
|
93
|
-
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate()
|
|
94
|
+
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(t)}}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(o){let s=resolve(o.targetDirectory??process.cwd(),o.projectName),c=o.projectName===`.`,l=o.overwriteExisting??!1,u=o.byokProvider??!1,d=o.packageManager??`pnpm`,f=resolveEvePackageContract(o.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine),m=resolve(o.workspaceProbeDirectory??s),h=isPackageManagerWorkspaceMember(d,m);if(c)await assertCanCreateInPlace(s,l);else if(await pathExists(s))throw Error(`Cannot create project because "${s}" already exists.`);let g={appName:basename(s),model:o.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,o.aiPackageVersion??`7.0.0-beta.178`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,o.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,o.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,o.typescriptPackageVersion??`7.0.1-rc`),nodeTypesVersion:p,nodeEngine:p};await mkdir(s,{recursive:!0});for(let[e,r]of Object.entries(templateFiles(u,!h))){let i=`${s}/${e}`,a=await pathExists(i);await writeTextFile(i,renderTemplate(r,g),{force:c&&l}),a&&await o.onOverwriteFile?.(i)}return await applyPackageManagerWorkspaceConfiguration({packageManager:d,projectRoot:s,workspaceProbeRoot:m,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(d,m,{aiPackageVersion:g.aiPackageVersion,nodeEngineRequirement:f.nodeEngine,onWorkspaceRootMutation:o.onWorkspaceRootMutation}),s}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PackageManagerKind } from "../../package-manager.js";
|
|
2
2
|
import { type NodeEngineOverride } from "../../node-engine.js";
|
|
3
|
+
import { type WorkspaceRootMutation } from "../workspace-root.js";
|
|
3
4
|
import { type EvePackageContract } from "../create/project.js";
|
|
4
5
|
export declare const SLACK_CHANNEL_DEFAULT_ROUTE = "/eve/v1/slack";
|
|
5
6
|
export declare const DEFAULT_SLACK_CONNECTOR_SLUG = "my-agent";
|
|
@@ -76,6 +77,12 @@ export interface EnsureChannelOptions {
|
|
|
76
77
|
kind: ChannelKind;
|
|
77
78
|
/** Manager that owns generated project configuration. Defaults to pnpm. */
|
|
78
79
|
packageManager?: PackageManagerKind;
|
|
80
|
+
/**
|
|
81
|
+
* Final project path used to discover ancestor workspaces. This differs from
|
|
82
|
+
* `projectRoot` only when scaffolding writes into a temporary staging
|
|
83
|
+
* directory before moving the project into place.
|
|
84
|
+
*/
|
|
85
|
+
workspaceProbeDirectory?: string;
|
|
79
86
|
force?: boolean;
|
|
80
87
|
/** Exact UID returned by Vercel Connect; takes precedence over the derived slug. */
|
|
81
88
|
slackConnectorUid?: string;
|
|
@@ -84,6 +91,7 @@ export interface EnsureChannelOptions {
|
|
|
84
91
|
webPackageVersions?: WebPackageVersions;
|
|
85
92
|
/** When false, Web Chat leaves Vercel Services config unwritten for preview-only scaffolds. */
|
|
86
93
|
configureVercelServices?: boolean;
|
|
94
|
+
onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
87
95
|
}
|
|
88
96
|
export interface WebPackageVersions {
|
|
89
97
|
evePackage?: EvePackageContract;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"./package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{DEFAULT_EVE_PACKAGE_CONTRACT,resolveEvePackageContract}from"../create/project.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,VERCEL_HOST_FRAMEWORK_PACKAGE_NAMES=[`@sveltejs/kit`,NEXT_PACKAGE_NAME,`nuxt`,`nuxt3`,`nuxt-edge`,`nuxt-nightly`],PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},eve:{buildCommand:`eve build`,entrypoint:`.`,framework:`eve`,routePrefix:`/_eve_internal/eve`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,n){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,n)}async function hasAnyPackageDependency(e,n){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)?n.some(e=>packageJsonHasDependency(r,e)):!1}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}async function hasVercelHostFramework(e){return hasAnyPackageDependency(join(e,`package.json`),VERCEL_HOST_FRAMEWORK_PACKAGE_NAMES)}async function ensurePackageDependency(e,n,i){return!await pathExists(e)||await readDependencyVersion(e,n)===i?[]:(await patchPackageJson(e,{dependencies:{[n]:i}}),[{path:e,dependencies:[n],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`7.0.0-beta.178`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(n,a,c,l,u){let f=join(n,`package.json`);if(!await pathExists(f))return{mutations:[]};let m=resolveEvePackageContract(l.evePackage),h=pinnedNodeEngineMajor(m.nodeEngine),g={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,l.aiPackageVersion),eve:formatEveDependencySpecifier(m.version),next:resolveVersionToken(`nextPackageVersion`,l.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,l.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,l.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,l.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,l.zodPackageVersion)},_={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":h,"@types/react":resolveVersionToken(`typesReactPackageVersion`,l.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,l.typesReactDomPackageVersion),typescript:`6.0.3`},v=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,y=isPackageManagerWorkspaceMember(a,c),b={dependencies:g,devDependencies:_,scripts:v};y||(b.nodeEngineRequirement=m.nodeEngine);let x=await patchPackageJson(f,b),S=(await patchWorkspaceRootPackageJson(a,c,{aiPackageVersion:g.ai,nodeEngineRequirement:m.nodeEngine,onWorkspaceRootMutation:u})).nodeEngineOverride??x.nodeEngineOverride;return{mutations:[{path:f,dependencies:Object.keys(g),devDependencies:Object.keys(_),scripts:Object.keys(v)}],nodeEngineOverride:S}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { slackChannel } from "eve/channels/slack";
|
|
3
3
|
|
|
4
4
|
export default slackChannel({
|
|
5
5
|
credentials: connectSlackCredentials(${JSON.stringify(e)}),
|
|
6
6
|
});
|
|
7
|
-
`}function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}function withWebVercelServices(e){let t=JSON.parse(e);if(!isJsonObject(t))throw Error(`${WEB_VERCEL_JSON_PATH} must contain a JSON object.`);let n=t.experimentalServices;if(n!==void 0&&!isJsonObject(n))throw Error(`${WEB_VERCEL_JSON_PATH} experimentalServices must contain a JSON object.`);let r={...t,$schema:typeof t.$schema==`string`?t.$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:{...n,web:n?.web??WEB_DEFAULT_VERCEL_SERVICES.web,eve:n?.eve??WEB_DEFAULT_VERCEL_SERVICES.eve}};return JSON.stringify(t)===JSON.stringify(r)?e:`${JSON.stringify(r,null,2)}\n`}async function ensureWebVercelServices(e){if(!await pathExists(e))return await writeTextFile(e,`${JSON.stringify({$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:WEB_DEFAULT_VERCEL_SERVICES},null,2)}\n`,{force:!0}),`written`;let
|
|
7
|
+
`}function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}function withWebVercelServices(e){let t=JSON.parse(e);if(!isJsonObject(t))throw Error(`${WEB_VERCEL_JSON_PATH} must contain a JSON object.`);let n=t.experimentalServices;if(n!==void 0&&!isJsonObject(n))throw Error(`${WEB_VERCEL_JSON_PATH} experimentalServices must contain a JSON object.`);let r={...t,$schema:typeof t.$schema==`string`?t.$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:{...n,web:n?.web??WEB_DEFAULT_VERCEL_SERVICES.web,eve:n?.eve??WEB_DEFAULT_VERCEL_SERVICES.eve}};return JSON.stringify(t)===JSON.stringify(r)?e:`${JSON.stringify(r,null,2)}\n`}async function ensureWebVercelServices(e){if(!await pathExists(e))return await writeTextFile(e,`${JSON.stringify({$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:WEB_DEFAULT_VERCEL_SERVICES},null,2)}\n`,{force:!0}),`written`;let r=await readFile(e,`utf8`),i=withWebVercelServices(r);return i===r?`skipped`:(await writeFile(e,i,`utf8`),`written`)}async function findCompetingNextConfigFiles(e){let n=[];for(let r of WEB_COMPETING_NEXT_CONFIG_PATHS){let i=join(e,r);await pathExists(i)&&n.push(i)}return n}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let r=join(e.projectRoot,`package.json`),i=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[r],packageJsonUpdated:[]};let o=resolveWebPackageVersions(e.webPackageVersions),s=e.packageManager??`pnpm`,c=resolve(e.workspaceProbeDirectory??e.projectRoot),l=await patchWebPackageJson(e.projectRoot,s,c,o,e.onWorkspaceRootMutation),d=[],f=[],p=[],g=[],_=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,WEB_VERCEL_JSON_PATH);await ensureWebVercelServices(t)===`written`?d.push(t):g.push(t)}let v=await applyPackageManagerWorkspaceConfiguration({packageManager:s,projectRoot:e.projectRoot,workspaceProbeRoot:c,onWorkspaceRootMutation:e.onWorkspaceRootMutation});d.push(...v.filesWritten),g.push(...v.filesSkipped);for(let[r,i]of Object.entries(WEB_APP_TEMPLATE_FILES)){let a=join(e.projectRoot,r);if(r===`agent/channels/eve.ts`&&!e.force&&await pathExists(a)){g.push(a);continue}let o=await pathExists(a);await writeTextFile(a,renderWebAppTemplate(i,_),{force:!0}),d.push(a),o&&f.push(a)}p.push(...await findCompetingNextConfigFiles(e.projectRoot));let y=[...new Set(d)],b=[...new Set(g)].filter(e=>!y.includes(e)),x={kind:`web`,action:i?`overwritten`:`created`,filesWritten:y,filesSkipped:b,packageJsonUpdated:l.mutations};return f.length>0&&(x.filesOverwritten=f),p.length>0&&(x.competingNextConfigFiles=p),l.nodeEngineOverride!==void 0&&(x.nodeEngineOverride=l.nodeEngineOverride),x}async function ensureSlackChannel(e){let r=join(e.projectRoot,`agent/channels/slack.ts`),a=await pathExists(r);if(!e.force&&a)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[r],packageJsonUpdated:[]};let o=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),s=await ensurePackageDependency(join(e.projectRoot,`package.json`),`@vercel/connect`,o),c=e.slackConnectorSlug??await deriveSlackConnectorSlug(e.projectRoot);await writeTextFile(r,buildSlackTemplate(e.slackConnectorUid??`slack/${c}`),{force:e.force});let l={kind:`slack`,action:a?`overwritten`:`created`,filesWritten:[r],filesSkipped:[],packageJsonUpdated:s,slackConnectorSlug:c};return a&&(l.filesOverwritten=[r]),l}async function listAuthoredChannels(e){let t=join(e,`agent/channels`),n;try{n=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let r=[];for(let e of n){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&r.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&r.push(e.name)}catch{}}return r.sort()}export{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug};
|
|
@@ -2,6 +2,8 @@ import { type NodeEngineOverride } from "../../node-engine.js";
|
|
|
2
2
|
export interface PackageJsonPatch {
|
|
3
3
|
dependencies?: Record<string, string>;
|
|
4
4
|
devDependencies?: Record<string, string>;
|
|
5
|
+
overrides?: Record<string, string>;
|
|
6
|
+
resolutions?: Record<string, string>;
|
|
5
7
|
scripts?: Record<string, string>;
|
|
6
8
|
/**
|
|
7
9
|
* eve's required Node.js range (e.g. `">=24"`). When the target's
|
|
@@ -12,6 +14,7 @@ export interface PackageJsonPatch {
|
|
|
12
14
|
nodeEngineRequirement?: string;
|
|
13
15
|
}
|
|
14
16
|
export interface PackageJsonPatchResult {
|
|
17
|
+
changed: boolean;
|
|
15
18
|
nodeEngineOverride?: NodeEngineOverride;
|
|
16
19
|
}
|
|
17
20
|
export declare function patchPackageJson(path: string, patch: PackageJsonPatch): Promise<PackageJsonPatchResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.scripts!==void 0&&(o.scripts={...o.scripts,...i.scripts},s=!0),i.nodeEngineRequirement!==void 0){let t=isJsonObject(o.engines)?o.engines:{},n=reconcileNodeEngine(t.node,i.nodeEngineRequirement);(n.kind===`added`||n.kind===`overridden`)&&(o.engines={...t,node:n.next},s=!0),n.kind===`overridden`&&(c=n)}return s&&await writeFile(r,`${JSON.stringify(o,null,2)}\n`,`utf8`),{nodeEngineOverride:c}}export{patchPackageJson};
|
|
1
|
+
import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.overrides!==void 0&&(o.overrides={...isJsonObject(o.overrides)?o.overrides:{},...i.overrides},s=!0),i.resolutions!==void 0&&(o.resolutions={...isJsonObject(o.resolutions)?o.resolutions:{},...i.resolutions},s=!0),i.scripts!==void 0&&(o.scripts={...o.scripts,...i.scripts},s=!0),i.nodeEngineRequirement!==void 0){let t=isJsonObject(o.engines)?o.engines:{},n=reconcileNodeEngine(t.node,i.nodeEngineRequirement);(n.kind===`added`||n.kind===`overridden`)&&(o.engines={...t,node:n.next},s=!0),n.kind===`overridden`&&(c=n)}return s&&await writeFile(r,`${JSON.stringify(o,null,2)}\n`,`utf8`),{changed:s,nodeEngineOverride:c}}export{patchPackageJson};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function workspaceRelativePath(workspaceRoot: string, projectRoot: string): string;
|
|
2
|
+
export declare function isPathInside(parentPath: string, childPath: string): boolean;
|
|
3
|
+
export declare function workspacePatternForProject(workspaceRoot: string, projectRoot: string): string;
|
|
4
|
+
export declare function workspacePatternClaimsRelativePath(pattern: string, relativePath: string): boolean;
|
|
5
|
+
export declare function workspacePatternsClaimProject(patterns: readonly string[], workspaceRoot: string, projectRoot: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isAbsolute,relative,resolve,sep}from"node:path";function escapeRegex(e){return e.replace(/[\\^$+?.()|[\]{}]/gu,`\\$&`)}function workspacePatternToRegex(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\/+/u,``),n=`^`;for(let e=0;e<t.length;e+=1){let r=t[e];r===`*`?t[e+1]===`*`?(n+=`.*`,e+=1):n+=`[^/]*`:n+=escapeRegex(r??``)}return n+=`$`,new RegExp(n,`u`)}function workspaceRelativePath(e,i){return relative(e,resolve(i)).split(sep).join(`/`)}function isPathInside(r,i){let a=relative(resolve(r),resolve(i));return a===``||!a.startsWith(`..`)&&!isAbsolute(a)}function workspacePatternForProject(e,t){let n=workspaceRelativePath(e,t);if(n.length===0)return`.`;let r=n.split(`/`);return r.length===1?n:`${r.slice(0,-1).join(`/`)}/*`}function workspacePatternClaimsRelativePath(e,t){let n=e.replaceAll(`\\`,`/`).replace(/^\.\/+/u,``);return n===`.`||n===t?!0:workspacePatternToRegex(n).test(t)}function workspacePatternsClaimProject(e,t,n){let r=workspaceRelativePath(t,n),i=e.filter(e=>!e.startsWith(`!`)),a=e.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1));return i.some(e=>workspacePatternClaimsRelativePath(e,r))?!a.some(e=>workspacePatternClaimsRelativePath(e,r)):!1}export{isPathInside,workspacePatternClaimsRelativePath,workspacePatternForProject,workspacePatternsClaimProject,workspaceRelativePath};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NodeEngineOverride } from "../node-engine.js";
|
|
2
|
+
import type { PackageManagerKind } from "../package-manager.js";
|
|
3
|
+
import type { PackageJsonPatchResult } from "./update/package-json.js";
|
|
4
|
+
export interface WorkspaceRootMutation {
|
|
5
|
+
kind: "package-json" | "workspace-config";
|
|
6
|
+
nodeEngineOverride?: NodeEngineOverride;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkspaceRootPackageJsonPatchResult extends PackageJsonPatchResult {
|
|
10
|
+
/** Root package.json path when an ancestor workspace root was eligible for patching. */
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function isPackageManagerWorkspaceMember(packageManager: PackageManagerKind, projectRoot: string): boolean;
|
|
14
|
+
/** Applies root-only package.json fields to an ancestor workspace package.json. */
|
|
15
|
+
export declare function patchWorkspaceRootPackageJson(packageManager: PackageManagerKind, projectRoot: string, input: {
|
|
16
|
+
readonly aiPackageVersion?: string;
|
|
17
|
+
readonly nodeEngineRequirement?: string;
|
|
18
|
+
readonly onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
19
|
+
}): Promise<WorkspaceRootPackageJsonPatchResult>;
|
|
20
|
+
/** Applies manager-owned project files and reports ancestor workspace mutations. */
|
|
21
|
+
export declare function applyPackageManagerWorkspaceConfiguration(input: {
|
|
22
|
+
readonly packageManager: PackageManagerKind;
|
|
23
|
+
readonly projectRoot: string;
|
|
24
|
+
readonly workspaceProbeRoot?: string;
|
|
25
|
+
readonly onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
filesSkipped: string[];
|
|
28
|
+
filesWritten: string[];
|
|
29
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{existsSync,readFileSync}from"node:fs";import{dirname,join,resolve}from"node:path";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}function packageManagerRootOnlyPackageJsonPatch(e,t){let n={};if(t.nodeEngineRequirement!==void 0&&(n.nodeEngineRequirement=t.nodeEngineRequirement),t.aiPackageVersion!==void 0)switch(e){case`bun`:case`npm`:n.overrides={ai:t.aiPackageVersion};break;case`yarn`:n.resolutions={ai:t.aiPackageVersion};break;case`pnpm`:break}return n}async function patchWorkspaceRootPackageJson(e,t,n){if(!isPackageManagerWorkspaceMember(e,t))return{changed:!1};let r=workspaceRootPackageJsonPath(e,t);if(r===void 0||!existsSync(r))return{changed:!1};let i=await patchPackageJson(r,packageManagerRootOnlyPackageJsonPatch(e,n));return i.changed&&await n.onWorkspaceRootMutation?.({kind:`package-json`,nodeEngineOverride:i.nodeEngineOverride,path:r}),{...i,path:r}}async function applyPackageManagerWorkspaceConfiguration(t){let n=resolve(t.workspaceProbeRoot??t.projectRoot),r=t.packageManager===`pnpm`?void 0:await ensurePackageManagerWorkspaceIncludesProject(t.packageManager,n),i=await getPackageManagerStrategy(t.packageManager).applyProjectConfiguration(t.projectRoot,{workspaceProbeRoot:n}),o=[...r===void 0?[]:[r],...i.filesWritten],s=[...i.filesSkipped];for(let n of o)isPathInside(t.projectRoot,n)||await t.onWorkspaceRootMutation?.({kind:`workspace-config`,path:n});return{filesSkipped:s,filesWritten:o}}export{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson};
|
|
@@ -37,7 +37,7 @@ export interface ArgsHeadlessProject {
|
|
|
37
37
|
skipVercel?: boolean;
|
|
38
38
|
/** Vercel team slug (scope). Undefined = the current vercel scope. */
|
|
39
39
|
team?: string;
|
|
40
|
-
/** Existing project
|
|
40
|
+
/** Existing project name or ID to link. Undefined = create a project named after the agent. */
|
|
41
41
|
project?: string;
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
@@ -61,6 +61,11 @@ export type ProvisioningMode = {
|
|
|
61
61
|
} | {
|
|
62
62
|
headless: false;
|
|
63
63
|
};
|
|
64
|
+
/** Stable identity of an existing Vercel project selected for linking. */
|
|
65
|
+
export interface VercelProjectIdentity {
|
|
66
|
+
projectId: string;
|
|
67
|
+
projectName: string;
|
|
68
|
+
}
|
|
64
69
|
/**
|
|
65
70
|
* Resolved project decision, fully concrete. The variant determines whether
|
|
66
71
|
* the flow creates a project, links an existing one, or avoids Vercel project
|
|
@@ -74,7 +79,7 @@ export type ResolvedVercelProject = {
|
|
|
74
79
|
team: string;
|
|
75
80
|
} | {
|
|
76
81
|
kind: "existing";
|
|
77
|
-
project:
|
|
82
|
+
project: VercelProjectIdentity;
|
|
78
83
|
team: string;
|
|
79
84
|
};
|
|
80
85
|
/** A concrete project to ensure exists and link. */
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { VercelCaptureFailure, VercelCaptureResult } from "#setup/primitives/index.js";
|
|
2
|
+
/** Treats a structured API error as a failure even when `vercel api --raw` exits zero. */
|
|
3
|
+
export declare function normalizeVercelApiResult(result: VercelCaptureResult): VercelCaptureResult;
|
|
4
|
+
/** Whether a Vercel API failure proves that the requested resource does not exist. */
|
|
5
|
+
export declare function isNotFoundApiFailure(failure: VercelCaptureFailure): boolean;
|
|
6
|
+
/** Whether a Vercel API failure proves that the requested resource already exists. */
|
|
7
|
+
export declare function isConflictApiFailure(failure: VercelCaptureFailure): boolean;
|
|
8
|
+
/** Whether a scoped Vercel API request was denied. */
|
|
9
|
+
export declare function isForbiddenApiFailure(failure: VercelCaptureFailure): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{number,object,string,union}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";const VercelApiErrorSchema=object({error:object({code:union([string(),number()]).optional(),message:string().optional()}).optional()});function apiErrorFromStdout(e){try{let t=VercelApiErrorSchema.safeParse(JSON.parse(e));return t.success?t.data.error:void 0}catch{return}}function apiFailureText(e){let t=apiErrorFromStdout(e.stdout);return`${String(t?.code??``)} ${t?.message??``} ${e.stderr}`.toLowerCase()}function normalizeVercelApiResult(e){if(!e.ok)return e;let t=apiErrorFromStdout(e.stdout);if(t===void 0)return e;let n=t.message??(t.code===void 0?void 0:String(t.code));return{ok:!1,failure:{stdout:e.stdout,stderr:``,message:`Vercel API request failed${n===void 0?``:`: ${n}`}.`}}}function isNotFoundApiFailure(e){return/(^|\W)(404|not_found)(\W|$)|not found/.test(apiFailureText(e))}function isConflictApiFailure(e){return/(^|\W)(409|conflict)(\W|$)|already exists/.test(apiFailureText(e))}function isForbiddenApiFailure(e){return/(^|\W)(403|forbidden|not_authorized|team_unauthorized|sso|saml)(\W|$)|not authorized/.test(apiFailureText(e))}export{isConflictApiFailure,isForbiddenApiFailure,isNotFoundApiFailure,normalizeVercelApiResult};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
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{isNotFoundApiFailure,normalizeVercelApiResult}from"./vercel-api-failure.js";import{projectReferenceFromEnvironment,readProjectLink}from"#setup/project-resolution.js";import{captureVercel}from"#setup/primitives/index.js";const VercelDeploymentSchema=object({projectId:string().min(1),name:string().min(1),target:string().nullable().optional(),customEnvironment:object({slug:string().min(1)}).nullable().optional()}),verifiedVercelTargetBrand=Symbol(`VerifiedVercelTarget`),defaultDeps={captureVercel,readProjectLink};function environmentForDeployment(e){return e.customEnvironment!==null&&e.customEnvironment!==void 0?e.customEnvironment.slug:e.target===`production`?`production`:`preview`}async function resolveVercelDeployment(e){let t={...defaultDeps,...e.deps},n=e.source??projectReferenceFromEnvironment(process.env)??await t.readProjectLink(e.workspaceRoot);if(n===void 0)return{kind:`unscoped`};let r=normalizeVercelApiResult(await t.captureVercel([`api`,`/v13/deployments/${encodeURIComponent(e.host)}`,`--scope`,n.orgId,`--raw`],{cwd:e.workspaceRoot,nonInteractive:!0,signal:e.signal,timeoutMs:1e4}));if(!r.ok)return e.signal?.aborted===!0||r.failure.errno===`ABORT_ERR`?{kind:`cancelled`}:isNotFoundApiFailure(r.failure)?{kind:`not-found`}:{kind:`failed`,failure:{cause:`vercel`,failure:r.failure}};let i;try{i=JSON.parse(r.stdout)}catch{return{kind:`failed`,failure:{cause:`invalid-json`,message:`Vercel returned invalid deployment JSON.`}}}let a=VercelDeploymentSchema.safeParse(i);if(!a.success)return{kind:`failed`,failure:{cause:`invalid-shape`,message:`Vercel returned an invalid deployment response.`}};if(a.data.projectId!==n.projectId)return{kind:`project-mismatch`,expectedProjectId:n.projectId,actualProjectId:a.data.projectId};let o=`https://${new URL(`https://${e.host}`).host}`;return{kind:`resolved`,target:{[verifiedVercelTargetBrand]:!0,origin:o,deployment:{provider:`vercel`,ownerId:n.orgId,projectId:a.data.projectId,projectName:a.data.name,environment:environmentForDeployment(a.data)}}}}export{resolveVercelDeployment};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type VercelCaptureFailure } from "#setup/primitives/index.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { VercelProjectOperationOptions } from "./project-resolution.js";
|
|
4
|
+
export type { VercelProjectOperationOptions };
|
|
5
|
+
declare const VercelTeamListEntrySchema: z.ZodObject<{
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
slug: z.ZodString;
|
|
8
|
+
current: z.ZodBoolean;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type VercelTeamListEntry = z.infer<typeof VercelTeamListEntrySchema>;
|
|
11
|
+
declare const VercelProjectListEntrySchema: z.ZodObject<{
|
|
12
|
+
name: z.ZodString;
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type VercelProjectListEntry = z.infer<typeof VercelProjectListEntrySchema>;
|
|
16
|
+
/** Parses one JSON response captured from the Vercel CLI. */
|
|
17
|
+
export declare function parseVercelJson(stdout: string, description: string): unknown;
|
|
18
|
+
/** Converts a scoped API denial into the Vercel re-authentication action. */
|
|
19
|
+
export declare function requireVercelTeamAccess(failure: VercelCaptureFailure): never;
|
|
20
|
+
/** Lists every Vercel scope available to the current CLI user. */
|
|
21
|
+
export declare function listTeams(projectRoot: string, options?: VercelProjectOperationOptions): Promise<VercelTeamListEntry[]>;
|
|
22
|
+
/** Lists the 20 most recent Vercel projects in one account scope. */
|
|
23
|
+
export declare function listRecentProjects(projectRoot: string, team: string, options?: VercelProjectOperationOptions): Promise<VercelProjectListEntry[]>;
|
|
24
|
+
/** Searches every matching Vercel project page in one account scope. */
|
|
25
|
+
export declare function searchProjects(projectRoot: string, team: string, query: string, options?: VercelProjectOperationOptions): Promise<VercelProjectListEntry[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{array,boolean,number,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{isForbiddenApiFailure}from"./vercel-api-failure.js";import{captureVercel}from"#setup/primitives/index.js";import{HumanActionRequiredError}from"#setup/human-action.js";const VercelTeamListEntrySchema=object({name:string(),slug:string(),current:boolean()}),VercelProjectListEntrySchema=object({name:string(),id:string()}),VercelPaginationSchema=object({next:number().int().nonnegative().nullable().optional()}),VercelTeamPageSchema=object({teams:array(VercelTeamListEntrySchema),pagination:VercelPaginationSchema.optional()}).transform(e=>({items:e.teams,next:e.pagination?.next??void 0})),VercelProjectPageSchema=object({projects:array(VercelProjectListEntrySchema),pagination:VercelPaginationSchema.optional()}).transform(e=>({items:e.projects,next:e.pagination?.next??void 0}));function parseVercelJson(e,t){try{return JSON.parse(e)}catch{throw Error(`Could not parse ${t} JSON from Vercel CLI output.`)}}async function drainPages(e,t,n){let r=new Map,i=new Set,a;for(;;){let o=await n(a);for(let e of o.items)r.set(t(e),e);if(o.next===void 0)return[...r.values()];if(i.has(o.next))throw Error(`Vercel returned a repeated pagination cursor for ${e}.`);i.add(o.next),a=o.next}}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 fetchTeamPage(e,t,n){let r=[`teams`,`ls`,`--format`,`json`];n!==void 0&&r.push(`--next`,String(n));let i=await captureVercel(r,{cwd:e,signal:t.signal});if(t.signal?.throwIfAborted(),!i.ok)throw isForbiddenApiFailure(i.failure)&&requireVercelTeamAccess(i.failure),Error(`Could not list Vercel teams. ${i.failure.message}`);let s=VercelTeamPageSchema.safeParse(parseVercelJson(i.stdout,`teams`));if(!s.success)throw Error(`Could not read teams from Vercel CLI JSON output.`);return s.data}async function listTeams(e,t={}){return drainPages(`Vercel teams`,e=>e.slug,n=>fetchTeamPage(e,t,n))}async function fetchProjectPage(e,t,n){let r=[`project`,`ls`,`--format`,`json`,`--scope`,t];n.search!==void 0&&r.push(`--filter`,n.search),n.next!==void 0&&r.push(`--next`,String(n.next));let i=await captureVercel(r,{cwd:e,signal:n.signal,timeoutMs:15e3});if(n.signal?.throwIfAborted(),!i.ok)throw isForbiddenApiFailure(i.failure)&&requireVercelTeamAccess(i.failure),Error(`Could not list Vercel projects in ${t}. ${i.failure.message}`);let s=VercelProjectPageSchema.safeParse(parseVercelJson(i.stdout,`projects`));if(!s.success)throw Error(`Could not read projects from Vercel CLI JSON output.`);return s.data}async function listRecentProjects(e,t,n={}){return(await fetchProjectPage(e,t,n)).items}async function searchProjects(e,t,n,r={}){let i=n.trim();if(i.length===0)throw Error(`Project search query cannot be empty.`);return drainPages(`project search in ${t}`,e=>e.id,n=>fetchProjectPage(e,t,{...r,search:i,next:n}))}export{listRecentProjects,listTeams,parseVercelJson,requireVercelTeamAccess,searchProjects};
|
|
@@ -1,28 +1,9 @@
|
|
|
1
1
|
import { createPromptCommandOutput } from "#setup/cli/index.js";
|
|
2
2
|
import { type VercelCaptureFailure } from "#setup/primitives/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import type { ProjectResolution } from "./project-resolution.js";
|
|
3
|
+
import { type ProjectResolution } from "./project-resolution.js";
|
|
5
4
|
import type { Prompter } from "./prompter.js";
|
|
6
|
-
import type { ResolvedVercelProjectSpec } from "./state.js";
|
|
7
|
-
|
|
8
|
-
name: z.ZodString;
|
|
9
|
-
slug: z.ZodString;
|
|
10
|
-
current: z.ZodBoolean;
|
|
11
|
-
}, z.core.$strip>;
|
|
12
|
-
type VercelTeamListEntry = z.infer<typeof VercelTeamListEntrySchema>;
|
|
13
|
-
declare const VercelProjectListEntrySchema: z.ZodObject<{
|
|
14
|
-
name: z.ZodString;
|
|
15
|
-
id: z.ZodString;
|
|
16
|
-
}, z.core.$strip>;
|
|
17
|
-
type VercelProjectListEntry = z.infer<typeof VercelProjectListEntrySchema>;
|
|
18
|
-
declare const VercelProjectReferenceSchema: z.ZodObject<{
|
|
19
|
-
id: z.ZodString;
|
|
20
|
-
name: z.ZodString;
|
|
21
|
-
}, z.core.$strip>;
|
|
22
|
-
type VercelProjectReference = z.infer<typeof VercelProjectReferenceSchema>;
|
|
23
|
-
export interface VercelProjectOperationOptions {
|
|
24
|
-
signal?: AbortSignal;
|
|
25
|
-
}
|
|
5
|
+
import type { ResolvedVercelProjectSpec, VercelProjectIdentity } from "./state.js";
|
|
6
|
+
import { type VercelProjectOperationOptions } from "./vercel-project-api.js";
|
|
26
7
|
export interface PickProjectOptions extends VercelProjectOperationOptions {
|
|
27
8
|
/** Whether an empty project list may fall back to entering a name to create. */
|
|
28
9
|
allowCreateWhenEmpty?: boolean;
|
|
@@ -30,12 +11,8 @@ export interface PickProjectOptions extends VercelProjectOperationOptions {
|
|
|
30
11
|
export declare function unresolvedProject(): ProjectResolution;
|
|
31
12
|
/** Resolves the linked project id from a resolution, if any. */
|
|
32
13
|
export declare function projectIdFromResolution(project: ProjectResolution): string | undefined;
|
|
33
|
-
/** Lists the Vercel scopes available to the current CLI user. */
|
|
34
|
-
export declare function listTeams(projectRoot: string, options?: VercelProjectOperationOptions): Promise<VercelTeamListEntry[]>;
|
|
35
|
-
/** Lists Vercel projects available under an explicit team or personal scope. */
|
|
36
|
-
export declare function listProjects(projectRoot: string, team: string, options?: VercelProjectOperationOptions): Promise<VercelProjectListEntry[]>;
|
|
37
14
|
/** Resolves one project by exact name or id through the Vercel API. */
|
|
38
|
-
export declare function resolveProjectByNameOrId(projectRoot: string, team: string, projectNameOrId: string, options?: VercelProjectOperationOptions): Promise<
|
|
15
|
+
export declare function resolveProjectByNameOrId(projectRoot: string, team: string, projectNameOrId: string, options?: VercelProjectOperationOptions): Promise<VercelProjectIdentity | null>;
|
|
39
16
|
export declare function assertNewProjectNameAvailable(projectRoot: string, team: string, projectName: string, options?: VercelProjectOperationOptions): Promise<void>;
|
|
40
17
|
/**
|
|
41
18
|
* Throws the login action. When the underlying `vercel whoami` failure is
|
|
@@ -63,14 +40,6 @@ export type VercelAuthStatus = "authenticated" | "logged-out" | "cli-missing" |
|
|
|
63
40
|
/** Returns the user-facing reason Vercel-backed setup is unavailable. */
|
|
64
41
|
export declare function vercelAuthBlockerReason(authStatus: VercelAuthStatus): string | undefined;
|
|
65
42
|
export declare function getVercelAuthStatus(projectRoot: string, options?: VercelProjectOperationOptions): Promise<VercelAuthStatus>;
|
|
66
|
-
/**
|
|
67
|
-
* Throws the re-auth action for a forbidden scope. The session is logged in,
|
|
68
|
-
* but a scoped command was denied — the SSO/SAML or non-membership case. The
|
|
69
|
-
* remedy is still `vercel login` (it completes the team's SSO and refreshes the
|
|
70
|
-
* token), so the dev TUI routes it to `/login`; the reason names the membership
|
|
71
|
-
* fallback for the case re-auth cannot fix.
|
|
72
|
-
*/
|
|
73
|
-
export declare function requireVercelTeamAccess(failure: VercelCaptureFailure): never;
|
|
74
43
|
/**
|
|
75
44
|
* Ensures Vercel authentication before any provisioning. `vercel whoami` exits
|
|
76
45
|
* non-zero when not logged in; any other failure (a missing CLI, a transient
|
|
@@ -106,25 +75,14 @@ export declare function validateTeam(prompter: Prompter, projectRoot: string, te
|
|
|
106
75
|
* user filters and chooses from the list with a single-selection picker.
|
|
107
76
|
*/
|
|
108
77
|
export declare function pickTeam(prompter: Prompter, projectRoot: string, presetTeam: string | undefined, options?: VercelProjectOperationOptions): Promise<string>;
|
|
109
|
-
/**
|
|
110
|
-
* A picked Vercel project. `exists` distinguishes a project the user selected
|
|
111
|
-
* from the existing list (link it) from a name they typed because none exist
|
|
112
|
-
* yet (create it), so the caller can build the right `new` vs `existing` plan.
|
|
113
|
-
*/
|
|
114
|
-
export interface ArgsPickedProject {
|
|
115
|
-
/** Project slug: an existing project's name, or a name to create. */
|
|
116
|
-
project: string;
|
|
117
|
-
/** True for a selected existing project; false for a typed-in name to create. */
|
|
118
|
-
exists: boolean;
|
|
119
|
-
}
|
|
120
78
|
/** Picks an existing project under a team, or a name to create when none exist. */
|
|
121
|
-
export declare function pickProject(prompter: Prompter, projectRoot: string, team: string, options?: PickProjectOptions): Promise<
|
|
79
|
+
export declare function pickProject(prompter: Prompter, projectRoot: string, team: string, options?: PickProjectOptions): Promise<ResolvedVercelProjectSpec>;
|
|
122
80
|
/** Returns a project name for a new Vercel project, prompting when the default exists. */
|
|
123
81
|
export declare function pickNewProjectName(prompter: Prompter, projectRoot: string, team: string, defaultProjectName: string, options?: VercelProjectOperationOptions): Promise<string>;
|
|
124
82
|
/**
|
|
125
83
|
* Ensures the concrete project exists (creating it for a `new` plan) and links
|
|
126
|
-
* this directory to it.
|
|
127
|
-
*
|
|
84
|
+
* this directory to it. Acts on a fully-resolved spec — never prompts for a
|
|
85
|
+
* team or project. Returns the linked project, or undefined if `vercel link`
|
|
86
|
+
* did not complete.
|
|
128
87
|
*/
|
|
129
|
-
export declare function linkProject(prompter: Prompter, projectRoot: string, spec: ResolvedVercelProjectSpec, onOutput: ReturnType<typeof createPromptCommandOutput>, options?: VercelProjectOperationOptions): Promise<
|
|
130
|
-
export {};
|
|
88
|
+
export declare function linkProject(prompter: Prompter, projectRoot: string, spec: ResolvedVercelProjectSpec, onOutput: ReturnType<typeof createPromptCommandOutput>, options?: VercelProjectOperationOptions): Promise<VercelProjectIdentity | undefined>;
|