eve 0.8.6 → 0.9.1
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 +18 -1
- package/bin/eve.d.ts +5 -0
- package/bin/eve.js +15 -13
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +5 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +1 -0
- package/dist/src/cli/dev/tui/terminal-renderer.js +9 -6
- package/dist/src/compiled/.vendor-stamp.json +2 -1
- package/dist/src/compiled/semver/LICENSE +15 -0
- package/dist/src/compiled/semver/index.d.ts +23 -0
- package/dist/src/compiled/semver/index.js +1 -0
- package/dist/src/execution/sandbox/bindings/docker-cli.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/docker-cli.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-network.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-options.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/docker-options.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-options.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-platform.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-platform.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.d.ts +4 -4
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/ensure.d.ts +1 -1
- package/dist/src/execution/sandbox/lazy-backend.d.ts +2 -2
- package/dist/src/execution/sandbox/logging-session.js +2 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/sandbox.d.ts +1 -1
- package/dist/src/internal/authored-definition/sandbox.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.d.ts +1 -1
- package/dist/src/internal/nitro/host/dev-watcher-log.d.ts +3 -0
- package/dist/src/internal/nitro/host/dev-watcher-log.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.js +2 -1
- package/dist/src/public/sandbox/backends/default.d.ts +10 -10
- package/dist/src/public/sandbox/backends/default.js +1 -1
- package/dist/src/public/sandbox/backends/docker.d.ts +1 -1
- package/dist/src/public/sandbox/backends/docker.js +1 -1
- package/dist/src/public/sandbox/backends/just-bash.d.ts +1 -1
- package/dist/src/public/sandbox/backends/just-bash.js +1 -1
- package/dist/src/public/sandbox/backends/microsandbox.d.ts +1 -1
- package/dist/src/public/sandbox/backends/microsandbox.js +1 -1
- package/dist/src/public/sandbox/backends/vercel.d.ts +1 -1
- package/dist/src/public/sandbox/backends/vercel.js +1 -1
- package/dist/src/public/sandbox/docker-sandbox.d.ts +2 -2
- package/dist/src/public/sandbox/docker.d.ts +2 -0
- package/dist/src/public/sandbox/docker.js +1 -0
- package/dist/src/public/sandbox/index.d.ts +1 -9
- package/dist/src/public/sandbox/index.js +1 -1
- package/dist/src/public/sandbox/just-bash-sandbox.d.ts +1 -1
- package/dist/src/public/sandbox/just-bash.d.ts +2 -0
- package/dist/src/public/sandbox/just-bash.js +1 -0
- package/dist/src/public/sandbox/microsandbox-sandbox.d.ts +1 -1
- package/dist/src/public/sandbox/microsandbox.d.ts +2 -0
- package/dist/src/public/sandbox/microsandbox.js +1 -0
- package/dist/src/public/sandbox/vercel-sandbox.d.ts +1 -1
- package/dist/src/public/sandbox/vercel.d.ts +2 -0
- package/dist/src/public/sandbox/vercel.js +1 -0
- package/dist/src/runtime/resolve-sandbox.d.ts +1 -1
- package/dist/src/runtime/resolve-sandbox.js +1 -1
- package/dist/src/runtime/sandbox/registry.d.ts +2 -2
- package/dist/src/runtime/sandbox/registry.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -2
- package/dist/src/setup/boxes/add-channels.d.ts +4 -6
- package/dist/src/setup/boxes/add-channels.js +1 -1
- package/dist/src/setup/boxes/scaffold.d.ts +2 -2
- package/dist/src/setup/boxes/scaffold.js +1 -1
- package/dist/src/setup/node-engine.d.ts +31 -0
- package/dist/src/setup/node-engine.js +1 -0
- package/dist/src/setup/onboarding.d.ts +3 -2
- package/dist/src/setup/onboarding.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.d.ts +10 -5
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.d.ts +17 -4
- package/dist/src/setup/scaffold/create/project.js +9 -5
- package/dist/src/setup/scaffold/index.d.ts +1 -1
- package/dist/src/setup/scaffold/update/channels.d.ts +4 -2
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/package-json.d.ts +12 -1
- package/dist/src/setup/scaffold/update/package-json.js +1 -1
- package/dist/src/setup/scaffold/version-tokens.js +1 -1
- package/dist/src/shared/sandbox-backend.d.ts +4 -4
- package/dist/src/shared/sandbox-definition.d.ts +4 -4
- package/docs/getting-started.mdx +2 -2
- package/docs/guides/deployment.md +4 -3
- package/docs/reference/cli.md +2 -0
- package/docs/sandbox.mdx +21 -19
- package/package.json +27 -5
|
@@ -7,7 +7,7 @@ import type { ResolvedSandboxDefinition } from "#runtime/types.js";
|
|
|
7
7
|
* (when present) attached from the authored module.
|
|
8
8
|
*
|
|
9
9
|
* If the authored module omits `backend`, the resolver substitutes
|
|
10
|
-
* {@link
|
|
10
|
+
* {@link defaultSandbox} so the rest of the runtime can rely on a
|
|
11
11
|
* non-null backend value.
|
|
12
12
|
*/
|
|
13
13
|
export declare function resolveSandboxDefinition(definition: CompiledSandboxDefinition, moduleMap: CompiledModuleMap, nodeId: string | undefined): Promise<ResolvedSandboxDefinition>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{lazyBackend}from"#execution/sandbox/lazy-backend.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{
|
|
1
|
+
import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{lazyBackend}from"#execution/sandbox/lazy-backend.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{defaultSandbox}from"#public/sandbox/backends/default.js";async function resolveSandboxDefinition(n,i,a){try{let t=expectObjectRecord(await loadResolvedModuleExport({definition:n,kindLabel:`sandbox`,moduleMap:i,nodeId:a}),`Expected the sandbox export "${n.exportName??`default`}" from "${n.logicalPath}" to return an object.`);return{backend:resolveBackend(t.backend,n.logicalPath),bootstrap:t.bootstrap,description:n.description,exportName:n.exportName,logicalPath:n.logicalPath,onSession:t.onSession,revalidationKey:n.revalidationKey,sourceHash:n.sourceHash,sourceId:n.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the sandbox lifecycle handlers from "${n.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:n.logicalPath,sourceId:n.sourceId})}}function resolveBackend(e,t){if(e===void 0)return defaultSandbox();if(typeof e==`function`)return lazyBackend(e);if(typeof e!=`object`||!e)throw new ResolveAgentError(`Sandbox "${t}" exposed a non-object "backend" field. Use docker(), vercel(), another factory that returns a SandboxBackend value, or a zero-arg callback returning one.`,{logicalPath:t});let r=e;if(typeof r.name!=`string`||r.name.length===0)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a non-empty string "name" identifier.`,{logicalPath:t});if(typeof r.create!=`function`)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a "create" function.`,{logicalPath:t});return r}export{resolveSandboxDefinition};
|
|
@@ -51,9 +51,9 @@ export declare function createRuntimeSandboxRegistry(input: {
|
|
|
51
51
|
* Builds the framework default sandbox definition used when no agent
|
|
52
52
|
* authored override is present.
|
|
53
53
|
*
|
|
54
|
-
* The `backend` is resolved through {@link
|
|
54
|
+
* The `backend` is resolved through {@link defaultSandbox} on each
|
|
55
55
|
* call so the framework default picks up the same environment-aware
|
|
56
|
-
* fallback as authored sandboxes that omit `backend` (`
|
|
56
|
+
* fallback as authored sandboxes that omit `backend` (`vercel()`
|
|
57
57
|
* on hosted Vercel, then Docker, microsandbox, or just-bash by availability). Implemented as
|
|
58
58
|
* a factory rather than a constant so the environment is read at
|
|
59
59
|
* graph-resolution time rather than at module-load time.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{defaultSandbox}from"#public/sandbox/backends/default.js";const DEFAULT_SANDBOX_SOURCE_ID=`eve:default-sandbox`;function createRuntimeSandboxRegistry(e){return{sandbox:{definition:e.authoredSandbox??createFrameworkSandboxDefinition(),workspaceResourceRoot:e.workspaceResourceRoot}}}function createFrameworkSandboxDefinition(){return{backend:defaultSandbox(),logicalPath:`eve:framework/default-sandbox`,sourceId:DEFAULT_SANDBOX_SOURCE_ID,sourceKind:`module`}}export{DEFAULT_SANDBOX_SOURCE_ID,createFrameworkSandboxDefinition,createRuntimeSandboxRegistry};
|
|
@@ -96,8 +96,8 @@ export interface ResolvedConnectionDefinition extends ResolvedModuleSourceRef {
|
|
|
96
96
|
* The resolved `backend` is non-optional: every sandbox in the runtime
|
|
97
97
|
* graph carries a concrete SandboxBackend value, even when the
|
|
98
98
|
* authored definition omits `backend`. The unauthored case is filled
|
|
99
|
-
* in by `
|
|
100
|
-
* `
|
|
99
|
+
* in by `defaultSandbox()` (which itself selects between
|
|
100
|
+
* `vercel()`, `docker()`, `microsandbox()`, and `justbash()` based on the current
|
|
101
101
|
* environment).
|
|
102
102
|
*/
|
|
103
103
|
export type ResolvedSandboxDefinition = ResolvedModuleSourceRef & {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deriveSlackConnectorSlug, ensureChannel, type ChannelKind } from "#setup/scaffold/index.js";
|
|
1
|
+
import { deriveSlackConnectorSlug, ensureChannel, type ChannelKind, type EvePackageContract } from "#setup/scaffold/index.js";
|
|
2
2
|
import { detectPackageManager } from "#setup/package-manager.js";
|
|
3
3
|
import { runPackageManagerInstall } from "#setup/primitives/pm/run.js";
|
|
4
4
|
import { runVercel } from "#setup/primitives/run-vercel.js";
|
|
@@ -35,12 +35,10 @@ export interface AddChannelsOptions {
|
|
|
35
35
|
*/
|
|
36
36
|
headless?: boolean;
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* `webPackageVersions` at all, so every version comes from its build-stamped
|
|
41
|
-
* defaults.
|
|
38
|
+
* Eve package metadata for the scaffolded web `package.json`. When omitted,
|
|
39
|
+
* every package value comes from the build-stamped defaults.
|
|
42
40
|
*/
|
|
43
|
-
|
|
41
|
+
evePackage?: EvePackageContract;
|
|
44
42
|
/** Skip the "Create slackbot?" prompt and use this answer. */
|
|
45
43
|
presetCreateSlackbot?: boolean;
|
|
46
44
|
/** Overwrite existing channel files (`eve channels add --force`). */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{SkippedSignal,confirm}from"../ask.js";import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployment}from"../project-resolution.js";import{provisionSlackbot,reconcileSlackUid}from"../slackbot.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{WizardCancelledError}from"../step.js";import{deriveSlackConnectorSlug,ensureChannel}from"#setup/scaffold/index.js";import{detectPackageManager}from"#setup/package-manager.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{runPackageManagerInstall}from"#setup/primitives/pm/run.js";import{runVercel}from"#setup/primitives/run-vercel.js";const SLACKBOT_NOT_ATTACHED_ERROR=`Slackbot provisioning did not attach this project. Slack channel was not added.`;function slackbotFailureCopy(e){switch(e.state){case`not-installed`:return{reason:`Slackbot is not connected to a Slack workspace. Slack channel was not added.`,followUp:"Continuing without Slack — the install timed out and was cleaned up; re-run `eve channels add slack` to try again."};case`cleanup-failed`:return{reason:`The abandoned Slack connector could not be removed. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the cleanup warning above before trying again.`};case`connector-lookup-failed`:return{reason:`Existing Slack connectors could not be inspected. Slack channel was not added.`,followUp:"Continuing without Slack — restore Vercel CLI access, then re-run `eve channels add slack`."};case`installation-check-failed`:return{reason:`Slack workspace installation could not be verified. Slack channel was not added.`,followUp:"Continuing without Slack — verify Vercel Connect is reachable, then re-run `eve channels add slack`."};case`existing-not-installed`:return{reason:`The existing Slack connector is not connected to a Slack workspace. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the existing connector warning above before trying again.`};case`detach-failed`:return{reason:`Slackbot provisioning could not replace the existing trigger destination. Slack channel was not added.`,followUp:"Continuing without Slack — run the `vercel connect detach` and `vercel connect attach` commands above."};case`attach-failed`:return{reason:SLACKBOT_NOT_ATTACHED_ERROR,followUp:"Continuing without Slack — finish event delivery with the `vercel connect attach` command above."};case`create-failed`:return{reason:`Slackbot creation failed.`,followUp:"Continuing without Slack — add it later with `eve channels add slack`."}}}function warnOverwrittenFiles(e,t){for(let n of t??[])e.warning(`Overwrote ${n}`)}function warnCompetingNextConfigFiles(e,t){for(let n of t??[])e.warning(`Found competing Next.js config at ${n}; merge any needed settings into next.config.ts and remove it before starting the preview, or Next.js may ignore the generated Eve rewrite.`)}function addChannels(l){let u=l.deps??{ensureChannel,deriveSlackConnectorSlug,provisionSlackbot,reconcileSlackUid,detectPackageManager,runPackageManagerInstall,runVercel,detectDeployment};async function scaffoldSlackChannel(e,t,n,r,i,a){let o=!1;if(!t.slackScaffolded){let t=await u.ensureChannel({projectRoot:n,kind:`slack`,slackConnectorUid:a,slackConnectorSlug:r,force:l.force});warnOverwrittenFiles(e,t.filesOverwritten),t.action===`created`||t.action===`overwritten`?e.success(`Scaffolded channel: slack`):e.info(`Channel "slack" already exists. Skipping file creation.`),o=t.action!==`skipped`,i.slackScaffolded=!0}return i.channelsAdded.push(`slack`),o}async function linkProjectForSlackbot(e,t,n,o,s){if(o)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Slackbot creation needs this directory linked to a Vercel project.`});if(e.message(`Linking this directory to a Vercel project...`),!await u.runVercel([`link`],{cwd:t,signal:s}))throw s?.throwIfAborted(),Error(`Vercel project linking failed. Slackbot creation did not start.`);let c=mergeProjectResolution(n,projectResolutionFromDeployment(s===void 0?await u.detectDeployment(t):await u.detectDeployment(t,{signal:s})));if(!isProjectResolved(c))throw Error(`Vercel project linking failed. Slackbot creation did not start.`);return c}async function addWebChannelToPayload(e,t,n,r,i,a){if(!t.channelSelection.includes(`web`))return;if(t.webScaffolded){i.channelsAdded.push(`web`);return}e.message(`Scaffolding Web Chat channel files...`);let o={projectRoot:n,kind:`web`,packageManager:r,force:l.force,configureVercelServices:l.configureVercelServices??hasVercelProject(t)};l.
|
|
1
|
+
import{SkippedSignal,confirm}from"../ask.js";import{detectDeployment,isProjectResolved,mergeProjectResolution,projectResolutionFromDeployment}from"../project-resolution.js";import{provisionSlackbot,reconcileSlackUid}from"../slackbot.js";import{hasVercelProject,requireProjectPath}from"../state.js";import{WizardCancelledError}from"../step.js";import{deriveSlackConnectorSlug,ensureChannel}from"#setup/scaffold/index.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectPackageManager}from"#setup/package-manager.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{runPackageManagerInstall}from"#setup/primitives/pm/run.js";import{runVercel}from"#setup/primitives/run-vercel.js";const SLACKBOT_NOT_ATTACHED_ERROR=`Slackbot provisioning did not attach this project. Slack channel was not added.`;function slackbotFailureCopy(e){switch(e.state){case`not-installed`:return{reason:`Slackbot is not connected to a Slack workspace. Slack channel was not added.`,followUp:"Continuing without Slack — the install timed out and was cleaned up; re-run `eve channels add slack` to try again."};case`cleanup-failed`:return{reason:`The abandoned Slack connector could not be removed. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the cleanup warning above before trying again.`};case`connector-lookup-failed`:return{reason:`Existing Slack connectors could not be inspected. Slack channel was not added.`,followUp:"Continuing without Slack — restore Vercel CLI access, then re-run `eve channels add slack`."};case`installation-check-failed`:return{reason:`Slack workspace installation could not be verified. Slack channel was not added.`,followUp:"Continuing without Slack — verify Vercel Connect is reachable, then re-run `eve channels add slack`."};case`existing-not-installed`:return{reason:`The existing Slack connector is not connected to a Slack workspace. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the existing connector warning above before trying again.`};case`detach-failed`:return{reason:`Slackbot provisioning could not replace the existing trigger destination. Slack channel was not added.`,followUp:"Continuing without Slack — run the `vercel connect detach` and `vercel connect attach` commands above."};case`attach-failed`:return{reason:SLACKBOT_NOT_ATTACHED_ERROR,followUp:"Continuing without Slack — finish event delivery with the `vercel connect attach` command above."};case`create-failed`:return{reason:`Slackbot creation failed.`,followUp:"Continuing without Slack — add it later with `eve channels add slack`."}}}function warnOverwrittenFiles(e,t){for(let n of t??[])e.warning(`Overwrote ${n}`)}function warnCompetingNextConfigFiles(e,t){for(let n of t??[])e.warning(`Found competing Next.js config at ${n}; merge any needed settings into next.config.ts and remove it before starting the preview, or Next.js may ignore the generated Eve rewrite.`)}function addChannels(l){let u=l.deps??{ensureChannel,deriveSlackConnectorSlug,provisionSlackbot,reconcileSlackUid,detectPackageManager,runPackageManagerInstall,runVercel,detectDeployment};async function scaffoldSlackChannel(e,t,n,r,i,a){let o=!1;if(!t.slackScaffolded){let t=await u.ensureChannel({projectRoot:n,kind:`slack`,slackConnectorUid:a,slackConnectorSlug:r,force:l.force});warnOverwrittenFiles(e,t.filesOverwritten),t.action===`created`||t.action===`overwritten`?e.success(`Scaffolded channel: slack`):e.info(`Channel "slack" already exists. Skipping file creation.`),o=t.action!==`skipped`,i.slackScaffolded=!0}return i.channelsAdded.push(`slack`),o}async function linkProjectForSlackbot(e,t,n,o,s){if(o)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Slackbot creation needs this directory linked to a Vercel project.`});if(e.message(`Linking this directory to a Vercel project...`),!await u.runVercel([`link`],{cwd:t,signal:s}))throw s?.throwIfAborted(),Error(`Vercel project linking failed. Slackbot creation did not start.`);let c=mergeProjectResolution(n,projectResolutionFromDeployment(s===void 0?await u.detectDeployment(t):await u.detectDeployment(t,{signal:s})));if(!isProjectResolved(c))throw Error(`Vercel project linking failed. Slackbot creation did not start.`);return c}async function addWebChannelToPayload(e,t,n,r,i,a){if(!t.channelSelection.includes(`web`))return;if(t.webScaffolded){i.channelsAdded.push(`web`);return}e.message(`Scaffolding Web Chat channel files...`);let o={projectRoot:n,kind:`web`,packageManager:r,force:l.force,configureVercelServices:l.configureVercelServices??hasVercelProject(t)};l.evePackage!==void 0&&(o.webPackageVersions={evePackage:l.evePackage});let s=await u.ensureChannel(o);if(a?.throwIfAborted(),warnOverwrittenFiles(e,s.filesOverwritten),s.kind===`web`&&s.action!==`skipped`&&s.nodeEngineOverride!==void 0&&e.warning(formatNodeEngineOverrideWarning(s.nodeEngineOverride)),warnCompetingNextConfigFiles(e,`competingNextConfigFiles`in s?s.competingNextConfigFiles:void 0),s.action===`created`||s.action===`overwritten`){e.success(`Scaffolded channel: web`),i.webScaffolded=!0,i.channelsAdded.push(`web`);return}e.info(`Next.js project detected. Skipping Web Chat scaffolding.`)}function assertSlackProjectReady(e){if(l.ensureLinkedProject===void 0){if(!hasVercelProject(e))throw Error(`Slack requires a Vercel project. Re-run and choose to deploy to Vercel to add Slack.`);if(!isProjectResolved(e.project))throw Error(`Expected a linked Vercel project for Slack, but none was resolved.`)}}async function provisionSlackbotWithControls(e,t,n,r){if(r===void 0&&l.prompter.awaitChoice===void 0)return u.provisionSlackbot(e,t,n);let i={};return r!==void 0&&(i.signal=r),l.prompter.awaitChoice!==void 0&&(i.awaitChoice=l.prompter.awaitChoice),u.provisionSlackbot(e,t,n,void 0,i)}async function scaffoldAttachedSlackChannel(e,t,n,r,i,a){if(!await scaffoldSlackChannel(e,t,n,r,i,a.connectorUid)&&!await u.reconcileSlackUid(e,n,a,`slack/${r}`))throw Error(`Slack connector UID update is required before deployment.`)}async function addSlackChannelToPayload(e,t,n,i,a,o){if(!t.channelSelection.includes(`slack`))return;assertSlackProjectReady(t);let s=await u.deriveSlackConnectorSlug(i,t.agentName);if(t.slackbotCreated){if(!t.slackbotAttached)throw Error(SLACKBOT_NOT_ATTACHED_ERROR);if(!t.deploymentPending)return;let n=t.slackConnectorUid;if(n===void 0)throw Error(`Slack connector UID was not resolved. Slack deployment did not start.`);await scaffoldAttachedSlackChannel(e,t,i,s,a,{state:`attached`,connectorUid:n});return}if(n.createSlackbot!==!0){e.info(`Slack channel was not added because Slackbot setup was skipped.`);return}isProjectResolved(a.project)||(a.project=await linkProjectForSlackbot(e,i,a.project,n.headless,o));let c=await provisionSlackbotWithControls(e,i,s,o);if(o?.throwIfAborted(),c.state===`cancelled`)throw new WizardCancelledError;if(c.state!==`attached`){let t=slackbotFailureCopy(c);if(l.slackbotFailure!==`warn-and-continue`)throw Error(t.reason);e.warning(`${t.reason} ${t.followUp}`);return}a.slackbot={connectorUid:c.connectorUid,chatUrl:c.chatUrl,workspaceName:c.workspaceName},await scaffoldAttachedSlackChannel(e,t,i,s,a,c)}async function installChannelDependencies(e,t,n,r,i){if(r.channelsAdded.length!==0){if(await withPhase(e,`Installing channel dependencies (${n} install)...`,()=>u.runPackageManagerInstall(n,t,{onOutput:createPromptCommandOutput(e),signal:i}))){r.dependenciesInstalled=!0;return}e.warning(`Dependency installation failed. The new channels stay unloadable until \`${n} install\` or a deploy succeeds.`)}}async function performAddChannels(e,t,n){n?.throwIfAborted();let r=l.prompter.log,i=requireProjectPath(e),a={channelsAdded:[],webScaffolded:e.webScaffolded,slackScaffolded:e.slackScaffolded,dependenciesInstalled:!1,project:e.project},o=await u.detectPackageManager(i);return await addWebChannelToPayload(r,e,i,o.kind,a,n),await addSlackChannelToPayload(r,e,t,i,a,n),await installChannelDependencies(r,i,o.kind,a,n),a}return{id:`add-channels`,async gather({state:n}){let r=l.headless??!1;if(r&&n.channelSelection.includes(`slack`))throw Error("Slack setup is interactive. Run `eve channels add slack` from an interactive terminal.");if(!n.channelSelection.includes(`slack`)||l.presetCreateSlackbot!==void 0||n.slackbotCreated)return{headless:r,createSlackbot:l.presetCreateSlackbot};try{return{headless:r,createSlackbot:await l.asker.ask(confirm({key:`create-slackbot`,message:`Do you want to create your slackbot?`}))}}catch(t){if(t instanceof SkippedSignal)return{headless:r,createSlackbot:!1};throw t}},async perform({state:e,input:t,signal:n}){try{return await performAddChannels(e,t,n)}catch(e){if(!(e instanceof WizardCancelledError)){let t=e instanceof Error?e.message:String(e),n=t.split(`
|
|
2
2
|
`)[0]?.trim()??t;l.prompter.log.error(n)}throw e}},apply(e,t){let n=[...e.channels];for(let e of t.channelsAdded)n.includes(e)||n.push(e);let r={...e,channels:n,webScaffolded:t.webScaffolded,slackScaffolded:t.slackScaffolded,deploymentPending:e.deploymentPending||t.channelsAdded.length>0,deploymentDependenciesInstalled:t.channelsAdded.length>0?t.dependenciesInstalled:e.deploymentDependenciesInstalled,project:mergeProjectResolution(e.project,t.project)};return t.slackbot===void 0?r:{...r,slackbotCreated:!0,slackbotAttached:!0,slackConnectorUid:t.slackbot.connectorUid,slackChatUrl:t.slackbot.chatUrl,slackWorkspaceName:t.slackbot.workspaceName}}}}export{addChannels};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isEveProject, scaffoldBaseProject } from "#setup/scaffold/index.js";
|
|
1
|
+
import { isEveProject, scaffoldBaseProject, type EvePackageContract } from "#setup/scaffold/index.js";
|
|
2
2
|
import type { Prompter } from "../prompter.js";
|
|
3
3
|
import { type SetupState } from "../state.js";
|
|
4
4
|
import type { SetupBox } from "../step.js";
|
|
@@ -10,7 +10,7 @@ export interface ScaffoldDeps {
|
|
|
10
10
|
export interface ScaffoldOptions {
|
|
11
11
|
/** Reports scaffold progress and overwrite warnings. The box never prompts. */
|
|
12
12
|
prompter: Prompter;
|
|
13
|
-
|
|
13
|
+
evePackage?: EvePackageContract;
|
|
14
14
|
/** Parent directory the project folder is created inside. Defaults to cwd. */
|
|
15
15
|
targetDirectory?: string;
|
|
16
16
|
/** Allow the in-place scaffold to replace Eve scaffold files that already exist. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CURRENT_DIRECTORY_PROJECT_NAME,requireProjectPath}from"../state.js";import{isEveProject,scaffoldBaseProject}from"#setup/scaffold/index.js";function scaffold(i){let a=i.deps??{scaffoldBaseProject,isEveProject};return{id:`scaffold`,async gather(){return{headless:i.headless??!1}},async perform({state:n,input:r}){let{prompter:o}=i,s=n.projectPath.inPlace?CURRENT_DIRECTORY_PROJECT_NAME:n.agentName,c=requireProjectPath(n);if(r.headless&&!i.overwriteExisting&&await a.isEveProject(c))return o.log.message(`Existing Eve project detected; continuing setup...`),c;o.log.message(`Scaffolding project files...`);let l=await a.scaffoldBaseProject({projectName:s,model:n.modelId,byokProvider:n.modelWiring===`self`,targetDirectory:i.targetDirectory,overwriteExisting:i.overwriteExisting,onOverwriteFile:e=>o.log.warning(`Overwrote ${e}`),
|
|
1
|
+
import{CURRENT_DIRECTORY_PROJECT_NAME,requireProjectPath}from"../state.js";import{isEveProject,scaffoldBaseProject}from"#setup/scaffold/index.js";function scaffold(i){let a=i.deps??{scaffoldBaseProject,isEveProject};return{id:`scaffold`,async gather(){return{headless:i.headless??!1}},async perform({state:n,input:r}){let{prompter:o}=i,s=n.projectPath.inPlace?CURRENT_DIRECTORY_PROJECT_NAME:n.agentName,c=requireProjectPath(n);if(r.headless&&!i.overwriteExisting&&await a.isEveProject(c))return o.log.message(`Existing Eve project detected; continuing setup...`),c;o.log.message(`Scaffolding project files...`);let l=await a.scaffoldBaseProject({projectName:s,model:n.modelId,byokProvider:n.modelWiring===`self`,targetDirectory:i.targetDirectory,overwriteExisting:i.overwriteExisting,onOverwriteFile:e=>o.log.warning(`Overwrote ${e}`),evePackage:i.evePackage});return o.log.success(`Scaffolded project at ${l}`),l},apply(e,t){return{...e,projectPath:{kind:`resolved`,inPlace:e.projectPath.inPlace,path:t}}}}}export{scaffold};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** An authored Node.js engine value replaced by Eve's selected scaffold major. */
|
|
2
|
+
export interface NodeEngineOverride {
|
|
3
|
+
previous: unknown;
|
|
4
|
+
next: string;
|
|
5
|
+
}
|
|
6
|
+
export type NodeEngineReconciliation = {
|
|
7
|
+
kind: "added";
|
|
8
|
+
next: string;
|
|
9
|
+
} | ({
|
|
10
|
+
kind: "overridden";
|
|
11
|
+
} & NodeEngineOverride) | {
|
|
12
|
+
kind: "unchanged";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The single-major `engines.node` value a generated project should declare,
|
|
16
|
+
* derived from Eve's required range — e.g. `">=24"` → `"24.x"`. A scaffolded
|
|
17
|
+
* app is a deployment artifact, not a library: Vercel reads `engines.node` to
|
|
18
|
+
* pick the build's Node and resolves an open range to the newest *supported*
|
|
19
|
+
* major, so `">=24"` would float onto a future major as Vercel widens its set,
|
|
20
|
+
* whereas `"24.x"` stays on major 24 while still taking minor/patch updates.
|
|
21
|
+
* Eve's own package keeps the open range; only generated apps pin.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pinnedNodeEngineMajor(requiredRange: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Reconciles an authored `engines.node` value with the single Node.js major
|
|
26
|
+
* selected for scaffolded Eve projects. Existing ranges are preserved only
|
|
27
|
+
* when every version they permit remains inside that selected major.
|
|
28
|
+
*/
|
|
29
|
+
export declare function reconcileNodeEngine(existingValue: unknown, requiredRange: string): NodeEngineReconciliation;
|
|
30
|
+
/** Formats the warning shown when Eve replaces an incompatible Node.js engine value. */
|
|
31
|
+
export declare function formatNodeEngineOverrideWarning(override: NodeEngineOverride): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import semver from"#compiled/semver/index.js";const{Range,intersects,minVersion,subset,validRange}=semver;function isNonEmptySubset(e,t){let r=validRange(e);return r!==null&&intersects(r,t)&&subset(r,t)}function nextAllowedMajor(e,n){let i=`>=${n+1}.0.0`,a;for(let n of new Range(e).set){let e=minVersion([...n.map(e=>e.value).filter(Boolean),i].join(` `));e!==null&&(a===void 0||e.major<a)&&(a=e.major)}return a}function pinnedNodeEngineMajor(e){let t=validRange(e);if(t===null)throw Error(`Eve declares an invalid Node.js engine range: "${e}".`);let n=minVersion(t);if(n===null)throw Error(`Eve declares an empty Node.js engine range: "${e}".`);let i=n.major;for(;i!==void 0;){let e=`${i}.x`;if(isNonEmptySubset(e,t))return e;i=nextAllowedMajor(t,i)}throw Error(`Eve's Node.js engine range "${e}" cannot be represented by a major pin without widening it.`)}function reconcileNodeEngine(e,t){let n=pinnedNodeEngineMajor(t);return e===void 0?{kind:`added`,next:n}:typeof e==`string`&&isNonEmptySubset(e,n)?{kind:`unchanged`}:{kind:`overridden`,previous:e,next:n}}function formatPackageJsonValue(e){return JSON.stringify(e)??String(e)}function formatNodeEngineOverrideWarning(e){return`Overrode package.json engines.node from ${formatPackageJsonValue(e.previous)} to "${e.next}" because the previous value was not confined to the Node.js major selected by Eve.`}export{formatNodeEngineOverrideWarning,pinnedNodeEngineMajor,reconcileNodeEngine};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Prompter } from "./prompter.js";
|
|
2
2
|
import type { AnySetupBox } from "./runner.js";
|
|
3
|
+
import type { EvePackageContract } from "./scaffold/index.js";
|
|
3
4
|
import type { ArgsHeadlessAiGateway, ArgsHeadlessProject, ChannelKind, ChatPreference, SetupMode, SetupState } from "./state.js";
|
|
4
5
|
/**
|
|
5
6
|
* Options for {@link composeOnboardingBoxes}. These carry exactly what the
|
|
@@ -41,8 +42,8 @@ export interface OnboardingBoxesOptions {
|
|
|
41
42
|
* setup remains an interactive/onboarding handoff, not a headless flow.
|
|
42
43
|
*/
|
|
43
44
|
headless?: boolean;
|
|
44
|
-
/**
|
|
45
|
-
|
|
45
|
+
/** Eve package metadata baked into the scaffolded `package.json`. */
|
|
46
|
+
evePackage?: EvePackageContract;
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Composes the full programmatic onboarding flow.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{headlessAsker,interactiveAsker}from"./ask.js";import{addChannels}from"./boxes/add-channels.js";import{selectConnections}from"./boxes/select-connections.js";import{addConnections}from"./boxes/add-connections.js";import{detectAiGateway}from"./boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"./boxes/apply-ai-gateway-credential.js";import{deployProject}from"./boxes/deploy-project.js";import{linkVercelProject}from"./boxes/link-project.js";import{oneShotNextSteps}from"./boxes/one-shot-next-steps.js";import{preflight}from"./boxes/preflight.js";import{resolveProvisioning}from"./boxes/resolve-provisioning.js";import{resolveTarget}from"./boxes/resolve-target.js";import{scaffold}from"./boxes/scaffold.js";import{selectChannels}from"./boxes/select-channels.js";import{selectChat}from"./boxes/select-chat.js";import{selectModel}from"./boxes/select-model.js";import{selectSetupMode}from"./boxes/select-setup-mode.js";import{resolve}from"node:path";function onlyWhen(e,t){return{...t,shouldRun:n=>e(n)&&(t.shouldRun?.(n)??!0)}}function completeSetupOnly(e){return onlyWhen(e=>e.setupMode===`complete`,e)}function composeOnboardingBoxes(r){let i=r.headless?{headless:!0,project:r.provisioning?.project??{},aiGateway:r.provisioning?.aiGateway??{}}:{headless:!1},a=r.headless?headlessAsker():interactiveAsker(r.prompter);return[resolveTarget({asker:a,notify:e=>r.prompter.note(e),presetName:r.presetName,targetDirectory:r.targetDirectory,inPlace:r.inPlace,resumeExisting:r.headless}),selectSetupMode({asker:a,presetMode:r.presetMode,presetModel:r.presetModel}),...[selectModel({asker:a,presetModel:r.presetModel}),selectChannels({asker:a,presetChannels:r.presetChannels,variant:`onboarding`}),selectConnections({asker:a,presetConnections:r.presetConnections,headless:r.headless}),resolveProvisioning({asker:a,prompter:r.prompter,targetDirectory:r.targetDirectory,mode:i})].map(completeSetupOnly),preflight({cwd:resolve(r.targetDirectory??process.cwd()),headless:r.headless}),scaffold({prompter:r.prompter,
|
|
1
|
+
import{headlessAsker,interactiveAsker}from"./ask.js";import{addChannels}from"./boxes/add-channels.js";import{selectConnections}from"./boxes/select-connections.js";import{addConnections}from"./boxes/add-connections.js";import{detectAiGateway}from"./boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"./boxes/apply-ai-gateway-credential.js";import{deployProject}from"./boxes/deploy-project.js";import{linkVercelProject}from"./boxes/link-project.js";import{oneShotNextSteps}from"./boxes/one-shot-next-steps.js";import{preflight}from"./boxes/preflight.js";import{resolveProvisioning}from"./boxes/resolve-provisioning.js";import{resolveTarget}from"./boxes/resolve-target.js";import{scaffold}from"./boxes/scaffold.js";import{selectChannels}from"./boxes/select-channels.js";import{selectChat}from"./boxes/select-chat.js";import{selectModel}from"./boxes/select-model.js";import{selectSetupMode}from"./boxes/select-setup-mode.js";import{resolve}from"node:path";function onlyWhen(e,t){return{...t,shouldRun:n=>e(n)&&(t.shouldRun?.(n)??!0)}}function completeSetupOnly(e){return onlyWhen(e=>e.setupMode===`complete`,e)}function composeOnboardingBoxes(r){let i=r.headless?{headless:!0,project:r.provisioning?.project??{},aiGateway:r.provisioning?.aiGateway??{}}:{headless:!1},a=r.headless?headlessAsker():interactiveAsker(r.prompter);return[resolveTarget({asker:a,notify:e=>r.prompter.note(e),presetName:r.presetName,targetDirectory:r.targetDirectory,inPlace:r.inPlace,resumeExisting:r.headless}),selectSetupMode({asker:a,presetMode:r.presetMode,presetModel:r.presetModel}),...[selectModel({asker:a,presetModel:r.presetModel}),selectChannels({asker:a,presetChannels:r.presetChannels,variant:`onboarding`}),selectConnections({asker:a,presetConnections:r.presetConnections,headless:r.headless}),resolveProvisioning({asker:a,prompter:r.prompter,targetDirectory:r.targetDirectory,mode:i})].map(completeSetupOnly),preflight({cwd:resolve(r.targetDirectory??process.cwd()),headless:r.headless}),scaffold({prompter:r.prompter,evePackage:r.evePackage,targetDirectory:r.targetDirectory,overwriteExisting:r.overwriteExisting,headless:r.headless}),...[detectAiGateway(),linkVercelProject({prompter:r.prompter}),applyAiGatewayCredential({prompter:r.prompter}),addChannels({asker:a,prompter:r.prompter,evePackage:r.evePackage,presetCreateSlackbot:r.presetCreateSlackbot,headless:r.headless,slackbotFailure:`warn-and-continue`}),addConnections({prompter:r.prompter})].map(completeSetupOnly),completeSetupOnly(onlyWhen(e=>e.slackScaffolded,deployProject({prompter:r.prompter,skip:r.presetNoDeploy,headless:r.headless}))),completeSetupOnly(selectChat({asker:a,presetPreference:r.presetChatPreference})),oneShotNextSteps({prompter:r.prompter})]}export{composeOnboardingBoxes};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { PackageManagerKind } from "../../package-manager.js";
|
|
2
|
+
import type { NodeEngineOverride } from "../../node-engine.js";
|
|
3
|
+
import { type EvePackageContract } from "./project.js";
|
|
2
4
|
export interface AddAgentToProjectOptions {
|
|
3
5
|
projectRoot: string;
|
|
4
6
|
model: string;
|
|
@@ -7,7 +9,7 @@ export interface AddAgentToProjectOptions {
|
|
|
7
9
|
* generated project configuration. Defaults to pnpm.
|
|
8
10
|
*/
|
|
9
11
|
packageManager?: PackageManagerKind;
|
|
10
|
-
|
|
12
|
+
evePackage?: EvePackageContract;
|
|
11
13
|
aiPackageVersion?: string;
|
|
12
14
|
connectPackageVersion?: string;
|
|
13
15
|
zodPackageVersion?: string;
|
|
@@ -16,12 +18,15 @@ export interface AddAgentToProjectResult {
|
|
|
16
18
|
filesWritten: string[];
|
|
17
19
|
/** Dependencies added to package.json; ones the project already declares anywhere are left untouched. */
|
|
18
20
|
dependenciesAdded: string[];
|
|
21
|
+
/** Present when an incompatible package.json engines.node value was replaced. */
|
|
22
|
+
nodeEngineOverride?: NodeEngineOverride;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* Adds an Eve agent to an existing package: writes the `agent/` files, adds
|
|
22
|
-
*
|
|
23
|
-
* the selected package manager's project
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* missing runtime dependencies, reconciles `engines.node` with Eve's
|
|
27
|
+
* requirement, and applies the selected package manager's project
|
|
28
|
+
* configuration. Other host configuration (tsconfig, scripts, ignore files)
|
|
29
|
+
* remains untouched. All conflicts are gathered and reported before anything
|
|
30
|
+
* is written.
|
|
26
31
|
*/
|
|
27
32
|
export declare function addAgentToProject(options: AddAgentToProjectOptions): Promise<AddAgentToProjectResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"../update/package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{agentTemplateFiles,formatEveDependencySpecifier}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=join(i.projectRoot,`package.json`);if(!await pathExists(a))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 o=agentTemplateFiles(i.model),s=[];for(let e of Object.keys(o))await pathExists(join(i.projectRoot,e))&&s.push(e);if(s.length===0&&await pathExists(join(i.projectRoot,`agent`))&&s.push(`agent/`),s.length>0)throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it already has: ${s.join(`, `)}. Move them aside first.`);let c=
|
|
1
|
+
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"../update/package-json.js";import{resolveVersionToken}from"../version-tokens.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=join(i.projectRoot,`package.json`);if(!await pathExists(a))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 o=agentTemplateFiles(i.model),s=[];for(let e of Object.keys(o))await pathExists(join(i.projectRoot,e))&&s.push(e);if(s.length===0&&await pathExists(join(i.projectRoot,`agent`))&&s.push(`agent/`),s.length>0)throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it already has: ${s.join(`, `)}. Move them aside first.`);let c=resolveEvePackageContract(i.evePackage),l=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`>=7.0.0-beta.177`),u=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.2.2`),d=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),f=[];for(let[e,t]of Object.entries(o)){let r=join(i.projectRoot,e);await writeTextFile(r,t),f.push(r)}let p=JSON.parse(await readFile(a,`utf8`)),m={"@vercel/connect":u,ai:l,eve:formatEveDependencySpecifier(c.version),zod:d},h={};for(let[e,t]of Object.entries(m))hasDeclaredDependency(p,e)||(h[e]=t);let g={nodeEngineRequirement:c.nodeEngine};Object.keys(h).length>0&&(g.dependencies=h);let _=await patchPackageJson(a,g);return await getPackageManagerStrategy(i.packageManager??`pnpm`).applyProjectConfiguration(i.projectRoot),{filesWritten:f,dependenciesAdded:Object.keys(h).sort(),nodeEngineOverride:_.nodeEngineOverride}}export{addAgentToProject};
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import type { PackageManagerKind } from "../../package-manager.js";
|
|
2
2
|
export declare const CURRENT_DIRECTORY_PROJECT_NAME = ".";
|
|
3
|
-
export declare const DEFAULT_EVE_PACKAGE_VERSION = "__EVE_PACKAGE_VERSION__";
|
|
4
3
|
export declare const DEFAULT_AI_PACKAGE_VERSION = "__AI_SDK_VERSION__";
|
|
5
4
|
export declare const DEFAULT_CONNECT_PACKAGE_VERSION = "__VERCEL_CONNECT_VERSION__";
|
|
6
5
|
export declare const DEFAULT_ZOD_PACKAGE_VERSION = "__ZOD_VERSION__";
|
|
6
|
+
/**
|
|
7
|
+
* The Eve package metadata that generated projects consume together. Keeping
|
|
8
|
+
* the dependency version and Node.js requirement in one value prevents a
|
|
9
|
+
* scaffold from installing one Eve release while declaring another release's
|
|
10
|
+
* runtime contract.
|
|
11
|
+
*/
|
|
12
|
+
export interface EvePackageContract {
|
|
13
|
+
/** Eve dependency version or npm specifier written to the generated package. */
|
|
14
|
+
version: string;
|
|
15
|
+
/** The matching Eve release's authored `package.json` `engines.node` value. */
|
|
16
|
+
nodeEngine: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_EVE_PACKAGE_CONTRACT: EvePackageContract;
|
|
19
|
+
/** Resolves a stamped or explicitly supplied Eve package contract. */
|
|
20
|
+
export declare function resolveEvePackageContract(contract?: EvePackageContract): EvePackageContract;
|
|
7
21
|
/**
|
|
8
22
|
* Provider slug a gateway model id routes through: the segment before the
|
|
9
23
|
* first "/" (e.g. `anthropic/claude-sonnet-4.6` → `anthropic`). The slug is
|
|
@@ -39,16 +53,15 @@ export interface ScaffoldBaseProjectOptions {
|
|
|
39
53
|
targetDirectory?: string;
|
|
40
54
|
overwriteExisting?: boolean;
|
|
41
55
|
onOverwriteFile?: (filePath: string) => void | Promise<void>;
|
|
42
|
-
|
|
56
|
+
evePackage?: EvePackageContract;
|
|
43
57
|
aiPackageVersion?: string;
|
|
44
58
|
connectPackageVersion?: string;
|
|
45
59
|
zodPackageVersion?: string;
|
|
46
60
|
tsgoPackageVersion?: string;
|
|
47
|
-
typesNodePackageVersion?: string;
|
|
48
61
|
/**
|
|
49
62
|
* Scaffold an inline provider `byok` block in `agent.ts` that reads the
|
|
50
63
|
* provider key from `process.env` instead of relying on the managed Vercel
|
|
51
|
-
* AI Gateway.
|
|
64
|
+
* AI Gateway. `process` is typed by the `@types/node` every scaffold ships.
|
|
52
65
|
*/
|
|
53
66
|
byokProvider?: boolean;
|
|
54
67
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.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`]),
|
|
1
|
+
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.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.177`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.9.1`,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_TSGO_VERSION__`,t.tsgoPackageVersion).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(
|
|
6
|
+
`;function packageJsonTemplate(){return`{
|
|
7
7
|
"name": "__EVE_INIT_APP_NAME__",
|
|
8
8
|
"version": "0.0.0",
|
|
9
9
|
"type": "module",
|
|
@@ -24,14 +24,17 @@ export default defineAgent({
|
|
|
24
24
|
"zod": "__EVE_INIT_ZOD_VERSION__"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
|
|
28
|
-
"@typescript/native-preview": "__EVE_INIT_TSGO_VERSION__"
|
|
27
|
+
"@types/node": "__EVE_INIT_TYPES_NODE_VERSION__",
|
|
28
|
+
"@typescript/native-preview": "__EVE_INIT_TSGO_VERSION__"
|
|
29
29
|
},
|
|
30
30
|
"overrides": {
|
|
31
31
|
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
32
32
|
},
|
|
33
33
|
"resolutions": {
|
|
34
34
|
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": "__EVE_INIT_NODE_ENGINE__"
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
`}const AGENT_INSTRUCTIONS_TEMPLATE=`# Identity
|
|
@@ -42,6 +45,7 @@ You are a helpful assistant.
|
|
|
42
45
|
"target": "ES2022",
|
|
43
46
|
"module": "NodeNext",
|
|
44
47
|
"moduleResolution": "NodeNext",
|
|
48
|
+
"types": ["node"],
|
|
45
49
|
"strict": true,
|
|
46
50
|
"esModuleInterop": true,
|
|
47
51
|
"skipLibCheck": true,
|
|
@@ -86,4 +90,4 @@ export default defineAgent({
|
|
|
86
90
|
},
|
|
87
91
|
},
|
|
88
92
|
});
|
|
89
|
-
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(
|
|
93
|
+
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(),...getPackageManagerStrategy(n).scaffoldFiles}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!t){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(e){let a=resolve(e.targetDirectory??process.cwd(),e.projectName),o=e.projectName===`.`,c=e.overwriteExisting??!1,u=e.byokProvider??!1,d=e.packageManager??`pnpm`,f=resolveEvePackageContract(e.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine);if(o)await assertCanCreateInPlace(a,c);else if(await pathExists(a))throw Error(`Cannot create project because "${a}" already exists.`);let m={appName:basename(a),model:e.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`>=7.0.0-beta.177`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.4.3`),tsgoPackageVersion:resolveVersionToken(`tsgoPackageVersion`,e.tsgoPackageVersion??`7.0.0-dev.20260523.1`),nodeTypesVersion:p,nodeEngine:p};await mkdir(a,{recursive:!0});for(let[t,i]of Object.entries(templateFiles(u,d))){let s=`${a}/${t}`,l=await pathExists(s);await writeTextFile(s,renderTemplate(i,m),{force:o&&c}),l&&await e.onOverwriteFile?.(s)}return a}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,4 +1,4 @@
|
|
|
1
|
-
export { byokProviderEnvVar, CURRENT_DIRECTORY_PROJECT_NAME, isEveProject, scaffoldBaseProject, type ScaffoldBaseProjectOptions, } from "./create/project.js";
|
|
1
|
+
export { byokProviderEnvVar, CURRENT_DIRECTORY_PROJECT_NAME, isEveProject, scaffoldBaseProject, type EvePackageContract, type ScaffoldBaseProjectOptions, } from "./create/project.js";
|
|
2
2
|
export { DEFAULT_SLACK_CONNECTOR_SLUG, SLACK_CHANNEL_DEFAULT_ROUTE, deriveSlackConnectorSlug, ensureChannel, isNextJsProject, listAuthoredChannels, normalizeSlackConnectorSlug, type ChannelKind, type ChannelMutationResult, type EnsureChannelOptions, type SlackConnectorSlug, type WebPackageVersions, } from "./update/channels.js";
|
|
3
3
|
export { SCAFFOLDABLE_CHANNELS, type ScaffoldableChannel } from "./channels-catalog.js";
|
|
4
4
|
export { ensureConnection, listAuthoredConnections, type ConnectionInput, type ConnectionMutationAction, type ConnectionMutationResult, type EnsureConnectionOptions, } from "./update/connections.js";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { PackageManagerKind } from "../../package-manager.js";
|
|
2
|
+
import { type NodeEngineOverride } from "../../node-engine.js";
|
|
3
|
+
import { type EvePackageContract } from "../create/project.js";
|
|
2
4
|
export declare const SLACK_CHANNEL_DEFAULT_ROUTE = "/eve/v1/slack";
|
|
3
5
|
export declare const DEFAULT_SLACK_CONNECTOR_SLUG = "my-agent";
|
|
4
6
|
declare const slackConnectorSlugBrand: unique symbol;
|
|
@@ -38,6 +40,7 @@ interface WebChannelWrittenResult {
|
|
|
38
40
|
filesWritten: string[];
|
|
39
41
|
filesOverwritten?: string[];
|
|
40
42
|
competingNextConfigFiles?: string[];
|
|
43
|
+
nodeEngineOverride?: NodeEngineOverride;
|
|
41
44
|
filesSkipped: string[];
|
|
42
45
|
packageJsonUpdated: PackageJsonMutation[];
|
|
43
46
|
}
|
|
@@ -76,7 +79,7 @@ export interface EnsureChannelOptions {
|
|
|
76
79
|
configureVercelServices?: boolean;
|
|
77
80
|
}
|
|
78
81
|
export interface WebPackageVersions {
|
|
79
|
-
|
|
82
|
+
evePackage?: EvePackageContract;
|
|
80
83
|
aiPackageVersion?: string;
|
|
81
84
|
nextPackageVersion?: string;
|
|
82
85
|
reactPackageVersion?: string;
|
|
@@ -84,7 +87,6 @@ export interface WebPackageVersions {
|
|
|
84
87
|
streamdownPackageVersion?: string;
|
|
85
88
|
zodPackageVersion?: string;
|
|
86
89
|
tsgoPackageVersion?: string;
|
|
87
|
-
typesNodePackageVersion?: string;
|
|
88
90
|
typesReactPackageVersion?: string;
|
|
89
91
|
typesReactDomPackageVersion?: string;
|
|
90
92
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"./package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import"../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`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],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,
|
|
1
|
+
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";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{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`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],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,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),`next`)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`>=7.0.0-beta.177`,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`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,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(e,r){if(!await pathExists(e))return{mutations:[]};let o=resolveEvePackageContract(r.evePackage),s=pinnedNodeEngineMajor(o.nodeEngine),c={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,r.aiPackageVersion),eve:formatEveDependencySpecifier(o.version),next:resolveVersionToken(`nextPackageVersion`,r.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,r.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,r.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,r.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,r.zodPackageVersion)},u={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":s,"@types/react":resolveVersionToken(`typesReactPackageVersion`,r.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,r.typesReactDomPackageVersion),"@typescript/native-preview":resolveVersionToken(`tsgoPackageVersion`,r.tsgoPackageVersion)},f=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,p=await patchPackageJson(e,{dependencies:c,devDependencies:u,scripts:f,nodeEngineRequirement:o.nodeEngine});return{mutations:[{path:e,dependencies:Object.keys(c),devDependencies:Object.keys(u),scripts:Object.keys(f)}],nodeEngineOverride:p.nodeEngineOverride}}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,n){let r=n?``:`, { configureVercelOutput: false }`;return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,r)}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,n){let r=n?``:`, { configureVercelOutput: false }`;return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,r)}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 t=await readFile(e,`utf8`),i=withWebVercelServices(t);return i===t?`skipped`:(await writeFile(e,i,`utf8`),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let r of WEB_COMPETING_NEXT_CONFIG_PATHS){let i=join(e,r);await pathExists(i)&&t.push(i)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(t){let i=join(t.projectRoot,`package.json`),a=await pathExists(join(t.projectRoot,`app/page.tsx`));if(!t.force&&await isNextJsProject(t.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[i],packageJsonUpdated:[]};let o=await patchWebPackageJson(i,resolveWebPackageVersions(t.webPackageVersions)),s=[],l=[],u=[],d=[],m=basename(resolve(t.projectRoot)),h=t.configureVercelServices??!0;if(h){let e=join(t.projectRoot,WEB_VERCEL_JSON_PATH);await ensureWebVercelServices(e)===`written`?s.push(e):d.push(e)}let g=await getPackageManagerStrategy(t.packageManager??`pnpm`).applyProjectConfiguration(t.projectRoot);s.push(...g.filesWritten),d.push(...g.filesSkipped);for(let[e,i]of Object.entries(WEB_APP_TEMPLATE_FILES)){let a=join(t.projectRoot,e);if(e===`agent/channels/eve.ts`&&!t.force&&await pathExists(a)){d.push(a);continue}let o=await pathExists(a);await writeTextFile(a,renderWebAppTemplate(i,m,h),{force:!0}),s.push(a),o&&l.push(a)}u.push(...await findCompetingNextConfigFiles(t.projectRoot));let _={kind:`web`,action:a?`overwritten`:`created`,filesWritten:s,filesSkipped:d,packageJsonUpdated:o.mutations};return l.length>0&&(_.filesOverwritten=l),u.length>0&&(_.competingNextConfigFiles=u),o.nodeEngineOverride!==void 0&&(_.nodeEngineOverride=o.nodeEngineOverride),_}async function ensureSlackChannel(e){let t=join(e.projectRoot,`agent/channels/slack.ts`),i=await pathExists(t);if(!e.force&&i)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[t],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(t,buildSlackTemplate(e.slackConnectorUid??`slack/${c}`),{force:e.force});let l={kind:`slack`,action:i?`overwritten`:`created`,filesWritten:[t],filesSkipped:[],packageJsonUpdated:s,slackConnectorSlug:c};return i&&(l.filesOverwritten=[t]),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,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug};
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
import { type NodeEngineOverride } from "../../node-engine.js";
|
|
1
2
|
export interface PackageJsonPatch {
|
|
2
3
|
dependencies?: Record<string, string>;
|
|
3
4
|
devDependencies?: Record<string, string>;
|
|
4
5
|
scripts?: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Eve's required Node.js range (e.g. `">=24"`). When the target's
|
|
8
|
+
* `engines.node` is absent or is not confined to the scaffolded major, it is
|
|
9
|
+
* set to that pinned major (e.g. `"24.x"`). Existing ranges within the same
|
|
10
|
+
* major are left untouched.
|
|
11
|
+
*/
|
|
12
|
+
nodeEngineRequirement?: string;
|
|
5
13
|
}
|
|
6
|
-
export
|
|
14
|
+
export interface PackageJsonPatchResult {
|
|
15
|
+
nodeEngineOverride?: NodeEngineOverride;
|
|
16
|
+
}
|
|
17
|
+
export declare function patchPackageJson(path: string, patch: PackageJsonPatch): Promise<PackageJsonPatchResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile,writeFile}from"node:fs/promises";async function 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.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 +1 @@
|
|
|
1
|
-
import{dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}const TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TSGO`)]:{kind:`catalog`,packageName:`@typescript/native-preview`},[versionToken(`
|
|
1
|
+
import{dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TSGO`)]:{kind:`catalog`,packageName:`@typescript/native-preview`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let o=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let i=join(o,`package.json`);if(existsSync(i)&&JSON.parse(readFileSync(i,`utf8`)).name===`eve`)return o;let a=dirname(o);if(a===o)return;o=a}}function findWorkspaceManifest(r){let i=r;for(;;){let r=join(i,`pnpm-workspace.yaml`);if(existsSync(r))return r;let a=dirname(i);if(a===i)return;i=a}}function readCatalogVersion(e,t){let n=readFileSync(e,`utf8`).split(/\r?\n/),i=!1;for(let e of n){if(/^catalog:\s*$/.test(e)){i=!0;continue}if(!i)continue;if(/^\S/.test(e))break;let n=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(n&&(n[1]??n[2])===t)return n[3]}}function resolveTokenFromDevTree(e){let i=TOKEN_SOURCES[e];if(i!==void 0)try{let e=findEvePackageRoot();if(e===void 0||!existsSync(join(e,`scripts/stamp-version-tokens.mjs`)))return;if(i.kind===`eve-version`){let n=JSON.parse(readFileSync(join(e,`package.json`),`utf8`));return typeof n.version==`string`?n.version:void 0}if(i.kind===`eve-node-engine`){let n=JSON.parse(readFileSync(join(e,`package.json`),`utf8`)).engines?.node;return typeof n==`string`?n:void 0}let a=findWorkspaceManifest(e);return a===void 0?void 0:readCatalogVersion(a,i.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{resolveVersionToken};
|
|
@@ -114,10 +114,10 @@ export interface SandboxBackendPrewarmResult {
|
|
|
114
114
|
*
|
|
115
115
|
* A `SandboxBackend` is a value an author attaches to a
|
|
116
116
|
* {@link SandboxDefinition} to choose which underlying runtime hosts the
|
|
117
|
-
* sandbox. Eve ships built-in backends (`
|
|
118
|
-
* `
|
|
119
|
-
* `
|
|
120
|
-
* `
|
|
117
|
+
* sandbox. Eve ships built-in backends (`docker()`,
|
|
118
|
+
* `justbash()`, `microsandbox()`,
|
|
119
|
+
* `vercel()`, and the availability-aware
|
|
120
|
+
* `defaultSandbox()`), but the interface is public so authors can write
|
|
121
121
|
* their own.
|
|
122
122
|
*
|
|
123
123
|
* A backend implements the full two-phase lifecycle:
|
|
@@ -48,7 +48,7 @@ export type SandboxRevalidationKeyFn = () => Promise<string> | string;
|
|
|
48
48
|
*
|
|
49
49
|
* Each agent (and each subagent) owns exactly one sandbox. When the
|
|
50
50
|
* module file is absent the framework auto-provides a default sandbox
|
|
51
|
-
* via `
|
|
51
|
+
* via `defaultSandbox()`. Authors override lifecycle and backend by
|
|
52
52
|
* creating `agent/sandbox.ts` (or `agent/sandbox/sandbox.ts` when they
|
|
53
53
|
* also want a workspace folder); subagents override independently via
|
|
54
54
|
* `subagents/<name>/sandbox.ts` (or the folder form) and do not inherit
|
|
@@ -69,12 +69,12 @@ interface SandboxDefinitionBase<BO = Record<string, never>, SO = Record<string,
|
|
|
69
69
|
*
|
|
70
70
|
* ```ts
|
|
71
71
|
* defineSandbox({
|
|
72
|
-
* backend: () =>
|
|
72
|
+
* backend: () => vercel({ env: { TOKEN: process.env.TOKEN ?? "" } }),
|
|
73
73
|
* });
|
|
74
74
|
* ```
|
|
75
75
|
*
|
|
76
|
-
* When this field is omitted, Eve substitutes `
|
|
77
|
-
* runtime, which picks the best available backend: `
|
|
76
|
+
* When this field is omitted, Eve substitutes `defaultSandbox()` at
|
|
77
|
+
* runtime, which picks the best available backend: `vercel()`
|
|
78
78
|
* on hosted Vercel (where `process.env.VERCEL` is set), then Docker,
|
|
79
79
|
* microsandbox, or just-bash
|
|
80
80
|
* everywhere else. Set `backend` explicitly to pin the sandbox to a
|
package/docs/getting-started.mdx
CHANGED
|
@@ -24,14 +24,14 @@ You also need a model credential. Set the provider or gateway key your model str
|
|
|
24
24
|
|
|
25
25
|
## Manual installation
|
|
26
26
|
|
|
27
|
-
The quick start uses `eve init` for a guided scaffold. The target can also be an existing project directory (`eve init .`): the project must have a `package.json`, the `agent/` files must not exist yet, and the missing `eve`, `ai`, and `zod` dependencies
|
|
27
|
+
The quick start uses `eve init` for a guided scaffold. The target can also be an existing project directory (`eve init .`): the project must have a `package.json`, the `agent/` files must not exist yet, and `eve init` adds the missing `eve`, `ai`, and `zod` dependencies. The generated Eve dependency and Node engine come from the same Eve release; the engine is the lowest complete major supported by that release (e.g. `24.x`). An existing range is kept only when every version it permits stays within that major; otherwise Eve replaces it with the pinned major and prints a warning. Either way the final handoff runs the `eve dev` binary through the project's package manager, never the project's own `dev` script.
|
|
28
28
|
|
|
29
29
|
To wire Eve into an existing app yourself instead, make sure the app declares a compatible Node runtime in `package.json`:
|
|
30
30
|
|
|
31
31
|
```json
|
|
32
32
|
{
|
|
33
33
|
"engines": {
|
|
34
|
-
"node": "
|
|
34
|
+
"node": "24.x"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
```
|