eve 0.35.0 → 0.37.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 +24 -0
- package/README.md +1 -0
- package/dist/src/cli/commands/agent-instructions.d.ts +4 -4
- package/dist/src/cli/commands/init-confirm.d.ts +12 -0
- package/dist/src/cli/commands/init-confirm.js +1 -0
- package/dist/src/cli/commands/init.d.ts +6 -5
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.js +3 -3
- package/dist/src/compiled/.vendor-stamp.json +2 -1
- package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +339 -0
- package/dist/src/compiled/@vercel/sandbox/api-client/index.d.ts +1 -1
- package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +25 -1
- package/dist/src/compiled/@vercel/sandbox/drive.d.ts +140 -0
- package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -2
- package/dist/src/compiled/@vercel/sandbox/index.js +13 -13
- package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +55 -18
- package/dist/src/compiled/@vercel/sandbox-stable/LICENSE +201 -0
- package/dist/src/compiled/@vercel/sandbox-stable/_async-retry.d.ts +8 -0
- package/dist/src/compiled/@vercel/sandbox-stable/_workflow-serde.d.ts +5 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/api-client.d.ts +1456 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/api-error.d.ts +29 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/base-client.d.ts +39 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/file-writer.d.ts +66 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/index.d.ts +2 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/validators.d.ts +899 -0
- package/dist/src/compiled/@vercel/sandbox-stable/api-client/with-retry.d.ts +10 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/error.d.ts +15 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/file.d.ts +18 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/index.d.ts +6 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/oauth.d.ts +111 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/poll-for-token.d.ts +28 -0
- package/dist/src/compiled/@vercel/sandbox-stable/auth/project.d.ts +40 -0
- package/dist/src/compiled/@vercel/sandbox-stable/command.d.ts +292 -0
- package/dist/src/compiled/@vercel/sandbox-stable/constants.d.ts +5 -0
- package/dist/src/compiled/@vercel/sandbox-stable/execution-context.d.ts +116 -0
- package/dist/src/compiled/@vercel/sandbox-stable/filesystem.d.ts +258 -0
- package/dist/src/compiled/@vercel/sandbox-stable/index.d.ts +12 -0
- package/dist/src/compiled/@vercel/sandbox-stable/index.js +1 -0
- package/dist/src/compiled/@vercel/sandbox-stable/network-policy.d.ts +169 -0
- package/dist/src/compiled/@vercel/sandbox-stable/proxy.d.ts +55 -0
- package/dist/src/compiled/@vercel/sandbox-stable/sandbox-user.d.ts +212 -0
- package/dist/src/compiled/@vercel/sandbox-stable/sandbox.d.ts +1216 -0
- package/dist/src/compiled/@vercel/sandbox-stable/session.d.ts +433 -0
- package/dist/src/compiled/@vercel/sandbox-stable/snapshot.d.ts +229 -0
- package/dist/src/compiled/@vercel/sandbox-stable/utils/get-credentials.d.ts +21 -0
- package/dist/src/compiled/@vercel/sandbox-stable/utils/paginator.d.ts +16 -0
- package/dist/src/compiled/@vercel/sandbox-stable/utils/resolveSignal.d.ts +15 -0
- package/dist/src/compiled/@vercel/sandbox-stable/utils/sandbox-snapshot.d.ts +11 -0
- package/dist/src/compiled/@vercel/sandbox-stable/utils/types.d.ts +11 -0
- package/dist/src/compiled/_chunks/node/{auth-BS3UoyvT.js → auth-BaNbsImr.js} +1 -1
- package/dist/src/compiled/_chunks/node/version-BYHw-SDY.js +1 -0
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/session.d.ts +1 -0
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/types.d.ts +2 -0
- package/dist/src/execution/sandbox/bindings/vercel.d.ts +2 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/harness/approval-delivery-coordinator.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/nuxt/module.js +1 -1
- package/dist/src/public/sandbox/backends/vercel.d.ts +5 -4
- package/dist/src/public/sandbox/backends/vercel.js +1 -1
- package/dist/src/public/sandbox/vercel-sandbox.d.ts +25 -1
- package/dist/src/public/sandbox/vercel.d.ts +2 -1
- package/dist/src/public/sandbox/vercel.js +1 -1
- package/dist/src/public/sveltekit/index.d.ts +6 -20
- package/dist/src/public/sveltekit/index.js +1 -1
- package/dist/src/public/sveltekit/routing.d.ts +0 -24
- package/dist/src/public/sveltekit/routing.js +1 -1
- package/dist/src/setup/boxes/select-model.d.ts +6 -6
- package/dist/src/setup/boxes/select-model.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +0 -1
- package/dist/src/shared/default-agent-model.d.ts +1 -1
- package/dist/src/shared/default-agent-model.js +1 -1
- package/dist/src/shared/sandbox-network-policy.d.ts +1 -1
- package/dist/src/{public/nuxt → shared}/vercel-services.d.ts +18 -19
- package/dist/src/shared/vercel-services.js +1 -0
- package/docs/agent-config.md +4 -1
- package/docs/channels/custom.mdx +1 -1
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/getting-started.mdx +1 -1
- package/docs/guides/client/messages.mdx +3 -1
- package/docs/guides/dynamic-capabilities.md +38 -0
- package/docs/guides/frontend/sveltekit.mdx +22 -1
- package/docs/reference/cli.md +15 -11
- package/docs/sandbox.mdx +8 -0
- package/package.json +2 -1
- package/dist/src/compiled/_chunks/node/version-Cztrk7z6.js +0 -1
- package/dist/src/public/nuxt/vercel-services.js +0 -1
- package/dist/src/public/sveltekit/vercel-json.d.ts +0 -17
- package/dist/src/public/sveltekit/vercel-json.js +0 -1
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Private route namespace for hosting eve as a separate experimental Vercel
|
|
3
|
-
* service behind the SvelteKit app.
|
|
4
|
-
*/
|
|
5
|
-
export declare const EVE_SVELTEKIT_SERVICE_PREFIX = "/_eve_internal/eve";
|
|
6
|
-
/**
|
|
7
|
-
* Normalize a user-supplied service prefix into a leading-slash, no-trailing-
|
|
8
|
-
* slash route. Throws when the prefix resolves to the root route, which would
|
|
9
|
-
* collide with the SvelteKit web service.
|
|
10
|
-
*/
|
|
11
|
-
export declare function normalizeRoutePrefix(prefix: string): string;
|
|
12
1
|
/**
|
|
13
2
|
* Join a route prefix and a path with exactly one separating slash.
|
|
14
3
|
*/
|
|
@@ -17,16 +6,3 @@ export declare function joinRoutePrefix(prefix: string, path: string): string;
|
|
|
17
6
|
* Reduce an origin string to its canonical `protocol://host[:port]` form.
|
|
18
7
|
*/
|
|
19
8
|
export declare function normalizeOrigin(origin: string): string;
|
|
20
|
-
/**
|
|
21
|
-
* A Vercel rewrite that forwards eve transport requests (`/eve/v1/**`) to the
|
|
22
|
-
* private eve service prefix (`/_eve_internal/eve/eve/v1/**`).
|
|
23
|
-
*/
|
|
24
|
-
export interface EveVercelRewrite {
|
|
25
|
-
readonly destination: string;
|
|
26
|
-
readonly source: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Build the Vercel rewrite that forwards browser eve transport requests to the
|
|
30
|
-
* sibling eve service.
|
|
31
|
-
*/
|
|
32
|
-
export declare function createEveVercelRewrite(servicePrefix: string): EveVercelRewrite;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
function joinRoutePrefix(e,t){return`${e.replace(/\/+$/,``)}/${t.replace(/^\/+/,``)}`}function normalizeOrigin(e){return new URL(e.trim()).origin}export{joinRoutePrefix,normalizeOrigin};
|
|
@@ -24,12 +24,12 @@ export declare function fetchGatewayCatalog(signal?: AbortSignal): Promise<Gatew
|
|
|
24
24
|
*/
|
|
25
25
|
export declare function parseGatewayCatalog(input: unknown): GatewayCatalogModel[];
|
|
26
26
|
/**
|
|
27
|
-
* Builds picker options from a fetched catalog
|
|
28
|
-
* with the `web-search` tag
|
|
29
|
-
*
|
|
30
|
-
* shortlist are marked `featured`, so a searchable
|
|
31
|
-
* and scrolling or filtering reaches the rest. Falls
|
|
32
|
-
* shortlist when the catalog is missing or yields nothing.
|
|
27
|
+
* Builds picker options from a fetched catalog, keeping the default model and
|
|
28
|
+
* filtering the rest to language models with the `web-search` tag. The curated
|
|
29
|
+
* shortlist comes first in its own order, followed by the rest newest-first.
|
|
30
|
+
* Catalog entries on the shortlist are marked `featured`, so a searchable
|
|
31
|
+
* picker opens on just them and scrolling or filtering reaches the rest. Falls
|
|
32
|
+
* back to a static shortlist when the catalog is missing or yields nothing.
|
|
33
33
|
*/
|
|
34
34
|
export declare function modelOptionsFromCatalog(catalog: readonly GatewayCatalogModel[] | undefined): SelectOption<string>[];
|
|
35
35
|
/** Injected for tests; defaults to the real AI Gateway catalog fetch. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{select}from"../ask.js";import{z}from"#compiled/zod/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{AI_GATEWAY_MODELS_URL,vercelGatewayFetch}from"#internal/gateway.js";const gatewayCatalogModelSchema=z.object({id:z.string(),name:z.string(),type:z.string(),owned_by:z.string(),released:z.number().finite().optional().catch(void 0),tags:z.array(z.string()).optional().catch(void 0),pricing:z.object({service_tiers:z.record(z.string(),z.unknown()).optional().catch(void 0)}).optional().catch(void 0)}),gatewayCatalogSchema=z.object({data:z.array(z.unknown())}).transform(({data:e})=>e.flatMap(e=>{let t=gatewayCatalogModelSchema.safeParse(e);return t.success?[t.data]:[]}));function modelOption(e,t,n,r=!0){return{id:e,label:t,value:e,hint:n,featured:r||void 0}}const FEATURED_MODEL_IDS=[DEFAULT_AGENT_MODEL_ID,`anthropic/claude-opus-4.8`,`openai/gpt-5.5`],FALLBACK_MODELS=[modelOption(DEFAULT_AGENT_MODEL_ID,`
|
|
1
|
+
import{select}from"../ask.js";import{z}from"#compiled/zod/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{AI_GATEWAY_MODELS_URL,vercelGatewayFetch}from"#internal/gateway.js";const gatewayCatalogModelSchema=z.object({id:z.string(),name:z.string(),type:z.string(),owned_by:z.string(),released:z.number().finite().optional().catch(void 0),tags:z.array(z.string()).optional().catch(void 0),pricing:z.object({service_tiers:z.record(z.string(),z.unknown()).optional().catch(void 0)}).optional().catch(void 0)}),gatewayCatalogSchema=z.object({data:z.array(z.unknown())}).transform(({data:e})=>e.flatMap(e=>{let t=gatewayCatalogModelSchema.safeParse(e);return t.success?[t.data]:[]}));function modelOption(e,t,n,r=!0){return{id:e,label:t,value:e,hint:n,featured:r||void 0}}const FEATURED_MODEL_IDS=[DEFAULT_AGENT_MODEL_ID,`anthropic/claude-opus-4.8`,`openai/gpt-5.5`],FALLBACK_MODELS=[modelOption(DEFAULT_AGENT_MODEL_ID,`GLM 5.2`,`Z.AI`),modelOption(`anthropic/claude-opus-4.8`,`Claude Opus 4.8`,`Anthropic`),modelOption(`openai/gpt-5.5`,`GPT-5.5`,`OpenAI`),modelOption(`google/gemini-3.5`,`Gemini 3.5`,`Google`,!1)],PROVIDER_BRANDS={openai:`OpenAI`,zai:`Z.AI`,xai:`xAI`,deepseek:`DeepSeek`,moonshotai:`Moonshot AI`};function providerLabel(e){return e.length===0?``:PROVIDER_BRANDS[e]??e.charAt(0).toUpperCase()+e.slice(1)}async function fetchGatewayCatalog(e){let t=new AbortController,n=setTimeout(()=>t.abort(),5e3);try{let n=await vercelGatewayFetch(AI_GATEWAY_MODELS_URL,{signal:e===void 0?t.signal:AbortSignal.any([e,t.signal])});if(!n.ok)throw Error(`AI Gateway model catalog request failed (${n.status}).`);return parseGatewayCatalog(await n.json())}finally{clearTimeout(n)}}function parseGatewayCatalog(e){let t=gatewayCatalogSchema.safeParse(e);if(!t.success)throw Error(`AI Gateway returned an invalid model catalog.`);return t.data}function featuredPriority(e){let t=FEATURED_MODEL_IDS.indexOf(e);return t===-1?FEATURED_MODEL_IDS.length:t}function modelOptionsFromCatalog(e){if(e===void 0)return FALLBACK_MODELS;let t=e.filter(e=>e.type===`language`&&(e.id===DEFAULT_AGENT_MODEL_ID||(e.tags??[]).includes(`web-search`))).map(e=>{let t=e.id.split(`/`)[0]??``;return{value:e.id,label:e.name,hint:providerLabel(t),provider:t,released:e.released}}).sort((e,t)=>{let n=featuredPriority(e.value)-featuredPriority(t.value);if(n!==0)return n;let r=(t.released??-1/0)-(e.released??-1/0);if(r!==0)return r;let i=e.label.localeCompare(t.label);return i===0?e.value.localeCompare(t.value):i});return t.length===0?FALLBACK_MODELS:t.map(({value:e,label:t,hint:n})=>({id:e,label:t,value:e,hint:n,featured:FEATURED_MODEL_IDS.includes(e)||void 0}))}async function buildModelOptions(e,t){try{return modelOptionsFromCatalog(await e(t))}catch{return t?.throwIfAborted(),FALLBACK_MODELS}}function selectModel(t){let r=t.deps??{fetchModels:fetchGatewayCatalog};return{id:`select-model`,async gather({signal:i}){let a=t.presetModel;if(a!==void 0&&a.length>0)return a;let o=await buildModelOptions(r.fetchModels,i),s=t.defaultModel!==void 0&&o.some(e=>e.value===t.defaultModel)?t.defaultModel:o.some(e=>e.value===DEFAULT_AGENT_MODEL_ID)?DEFAULT_AGENT_MODEL_ID:o[0]?.value;return t.asker.ask(select({key:`model`,message:`Which model should your agent use?`,options:o,recommended:s,required:!0,search:!0,placeholder:`type to search`}))},async perform({input:e}){return e},apply(e,t){return{...e,modelId:t}}}}export{fetchGatewayCatalog,modelOptionsFromCatalog,parseGatewayCatalog,selectModel};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.58`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.37.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,t){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).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__",
|
|
@@ -37,7 +37,7 @@ export declare const WEB_APP_TEMPLATE_FILES: {
|
|
|
37
37
|
readonly "tsconfig.json": '{\n "$schema": "https://json.schemastore.org/tsconfig",\n "compilerOptions": {\n "target": "ES2017",\n "lib": ["dom", "dom.iterable", "esnext"],\n "allowJs": true,\n "skipLibCheck": true,\n "strict": true,\n "noEmit": true,\n "esModuleInterop": true,\n "module": "esnext",\n "moduleResolution": "Bundler",\n "resolveJsonModule": true,\n "isolatedModules": true,\n "jsx": "react-jsx",\n "incremental": true,\n "plugins": [\n {\n "name": "next"\n }\n ],\n "paths": {\n "@/*": ["./*"]\n }\n },\n "include": [\n "next-env.d.ts",\n "**/*.ts",\n "**/*.tsx",\n ".next/types/**/*.ts",\n ".next/dev/types/**/*.ts"\n ],\n "exclude": ["node_modules"]\n}\n';
|
|
38
38
|
};
|
|
39
39
|
export declare const WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES: {
|
|
40
|
-
readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, type AuthFn, vercelOidc } from "eve/channels/auth";\nimport { auth } from "@/lib/auth";\n\nconst betterAuthSession: AuthFn<Request> = async (request) => {\n const session = await auth.api.getSession({ headers: request.headers });\n if (!session) return null;\n\n const attributes: Record<string, string> = {\n email: session.user.email,\n name: session.user.name,\n };\n if (session.user.image) {\n attributes.picture = session.user.image;\n }\n\n return {\n attributes,\n authenticator: "better-auth:vercel",\n
|
|
40
|
+
readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, type AuthFn, vercelOidc } from "eve/channels/auth";\nimport { auth } from "@/lib/auth";\n\nconst betterAuthSession: AuthFn<Request> = async (request) => {\n const session = await auth.api.getSession({ headers: request.headers });\n if (!session) return null;\n\n const attributes: Record<string, string> = {\n email: session.user.email,\n name: session.user.name,\n };\n if (session.user.image) {\n attributes.picture = session.user.image;\n }\n\n return {\n attributes,\n authenticator: "better-auth:vercel",\n principalId: session.user.id,\n principalType: "user",\n };\n};\n\nexport default eveChannel({\n auth: [betterAuthSession, vercelOidc(), localDev()],\n});\n';
|
|
41
41
|
readonly "app/_components/web-chat-auth.tsx": '"use client";\n\nimport { LogOutIcon } from "lucide-react";\nimport { useState } from "react";\nimport { Button } from "@/components/ui/button";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from "@/components/ui/dropdown-menu";\nimport { authClient } from "@/lib/auth-client";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\nexport function SignIn() {\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string>();\n\n async function signIn() {\n setPending(true);\n setError(undefined);\n try {\n const result = await authClient.signIn.social({\n callbackURL: "/",\n provider: "vercel",\n });\n if (!result.error) return;\n setPending(false);\n setError("Sign-in failed. Try again.");\n } catch {\n setPending(false);\n setError("Sign-in failed. Try again.");\n }\n }\n\n return (\n <main className="flex h-dvh items-center justify-center bg-background px-6 text-foreground">\n <div className="flex w-full max-w-sm flex-col items-center gap-6 text-center">\n <div className="space-y-2">\n <h1 className="break-words font-medium text-4xl tracking-tighter">{AGENT_NAME}</h1>\n <p className="text-muted-foreground text-sm">\n Team members can sign in with Vercel to chat.\n </p>\n </div>\n <Button disabled={pending} onClick={signIn}>\n Sign in with Vercel\n </Button>\n {error ? (\n <p className="text-destructive text-sm" role="alert">\n {error}\n </p>\n ) : null}\n </div>\n </main>\n );\n}\n\nexport function AccountControl({\n email,\n image,\n name,\n}: {\n readonly email: string;\n readonly image?: string | null;\n readonly name: string;\n}) {\n const [imageFailed, setImageFailed] = useState(false);\n const [pending, setPending] = useState(false);\n const initials = getInitials(name, email);\n\n async function signOut() {\n setPending(true);\n try {\n await authClient.signOut({\n fetchOptions: {\n onError: () => setPending(false),\n onSuccess: () => window.location.assign("/"),\n },\n });\n } catch {\n setPending(false);\n }\n }\n\n return (\n <div className="fixed top-3 right-3 z-10">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n aria-label={`Open account menu for ${name}`}\n className="size-9 cursor-pointer overflow-hidden rounded-full p-0"\n size="icon"\n variant="outline"\n >\n {image && !imageFailed ? (\n <img\n alt=""\n className="size-full object-cover"\n onError={() => setImageFailed(true)}\n src={image}\n />\n ) : (\n <span aria-hidden="true" className="font-medium text-xs">\n {initials}\n </span>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align="end" className="w-64">\n <div className="min-w-0 px-2 py-1.5 text-sm">\n <span className="block truncate font-medium leading-5" title={name}>\n {name}\n </span>\n <span className="block truncate text-muted-foreground leading-5" title={email}>\n {email}\n </span>\n </div>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className="cursor-pointer justify-between"\n disabled={pending}\n onSelect={signOut}\n >\n {pending ? "Logging out…" : "Log out"}\n <LogOutIcon aria-hidden="true" />\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n\nfunction getInitials(name: string, email: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length >= 2) {\n return `${parts[0]?.[0] ?? ""}${parts.at(-1)?.[0] ?? ""}`.toUpperCase();\n }\n return (parts[0]?.[0] ?? email[0] ?? "?").toUpperCase();\n}\n';
|
|
42
42
|
readonly "app/api/auth/[...all]/route.ts": 'import { toNextJsHandler } from "better-auth/next-js";\nimport { auth } from "@/lib/auth";\n\nexport const { GET, POST } = toNextJsHandler(auth);\n';
|
|
43
43
|
readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\n// The page and Eve routes validate the generated app\'s Better Auth session.\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const DEFAULT_AGENT_MODEL_ID=`
|
|
1
|
+
const DEFAULT_AGENT_MODEL_ID=`zai/glm-5.2`;export{DEFAULT_AGENT_MODEL_ID};
|
|
@@ -49,10 +49,10 @@ export type EveVercelGeneratedService = {
|
|
|
49
49
|
readonly root: string;
|
|
50
50
|
};
|
|
51
51
|
/**
|
|
52
|
-
* Minimal shape of
|
|
53
|
-
*
|
|
52
|
+
* Minimal shape of a Vercel Build Output config that can carry generated eve
|
|
53
|
+
* services.
|
|
54
54
|
*/
|
|
55
|
-
export interface
|
|
55
|
+
export interface VercelBuildConfig {
|
|
56
56
|
version?: number;
|
|
57
57
|
routes?: unknown[];
|
|
58
58
|
services?: Record<string, VercelServiceConfig>;
|
|
@@ -61,8 +61,8 @@ export interface NitroVercelBuildConfig {
|
|
|
61
61
|
/**
|
|
62
62
|
* Result of {@link ensureEveVercelServicesConfig}: `root` when `vercel.json`
|
|
63
63
|
* already declares stable services (the user owns routing; nothing is
|
|
64
|
-
* generated), `generated` with the service record to merge into
|
|
65
|
-
*
|
|
64
|
+
* generated), `generated` with the service record to merge into a Vercel Build
|
|
65
|
+
* Output config otherwise.
|
|
66
66
|
*/
|
|
67
67
|
export type EnsureEveVercelServicesConfigResult = {
|
|
68
68
|
readonly mode: "root";
|
|
@@ -82,36 +82,35 @@ export declare function createEveServiceRoute(serviceName?: string): EveVercelSe
|
|
|
82
82
|
*/
|
|
83
83
|
export declare function createEveServiceRequestPathRoute(): EveVercelServiceRequestPathRoute;
|
|
84
84
|
/**
|
|
85
|
-
* Resolve the stable Vercel services configuration for a
|
|
85
|
+
* Resolve the stable Vercel services configuration for a framework + eve
|
|
86
86
|
* deployment.
|
|
87
87
|
*
|
|
88
88
|
* When `vercel.json` (looked up from the linked Vercel project root, falling
|
|
89
|
-
* back to the
|
|
89
|
+
* back to the host root) already declares stable `services`, it must include
|
|
90
90
|
* an eve service and the module generates nothing. Otherwise this prepares a
|
|
91
91
|
* generated eve service — creating its isolated build root under
|
|
92
92
|
* `.eve/vercel-services/eve` so the eve build output cannot collide with the
|
|
93
|
-
*
|
|
94
|
-
* route for the caller to merge into
|
|
93
|
+
* host Build Output — and returns the service record plus the public service
|
|
94
|
+
* route for the caller to merge into its Vercel build config. A legacy
|
|
95
95
|
* `experimentalServices` field is ignored with a migration warning: Vercel no
|
|
96
96
|
* longer routes it.
|
|
97
97
|
*/
|
|
98
98
|
export declare function ensureEveVercelServicesConfig(input: {
|
|
99
99
|
readonly appRoot: string;
|
|
100
100
|
readonly eveBuildCommand?: string;
|
|
101
|
-
readonly
|
|
101
|
+
readonly frameworkName: string;
|
|
102
|
+
readonly hostRoot: string;
|
|
102
103
|
}): Promise<EnsureEveVercelServicesConfigResult>;
|
|
103
104
|
/**
|
|
104
|
-
* Merge the generated eve service and its public route into a
|
|
105
|
-
*
|
|
105
|
+
* Merge the generated eve service and its public route into a Vercel Build
|
|
106
|
+
* Output config.
|
|
106
107
|
*
|
|
107
108
|
* The service route is inserted before an existing `handle: "filesystem"`
|
|
108
|
-
* route, or prepended when none exists
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* service already configured by the user is preserved and only gains the
|
|
112
|
-
* `request.path` route; everything else passes through untouched.
|
|
109
|
+
* route, or prepended when none exists. An eve service already configured by
|
|
110
|
+
* the user is preserved and only gains the `request.path` route; everything
|
|
111
|
+
* else passes through untouched.
|
|
113
112
|
*/
|
|
114
|
-
export declare function mergeEveVercelConfig(existing:
|
|
113
|
+
export declare function mergeEveVercelConfig(existing: VercelBuildConfig | undefined, generated: Extract<EnsureEveVercelServicesConfigResult, {
|
|
115
114
|
mode: "generated";
|
|
116
|
-
}>):
|
|
115
|
+
}>): VercelBuildConfig;
|
|
117
116
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{mkdir,readFile}from"node:fs/promises";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{dirname,join,relative}from"node:path";import{EVE_INTERNAL_BUILD_OUTPUT_DIRECTORY_ENV,EVE_INTERNAL_HOST_BUILD_OUTPUT_DIRECTORY_ENV}from"#internal/application/paths.js";import{findClosestLinkedVercelDirectory}from"#shared/vercel-output-directory.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,EVE_SERVICE_ROUTE_SRC=`^${EVE_ROUTE_PREFIX}/(.*)$`,EVE_SERVICE_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/$1`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function toPosixRelative(e,t){let n=relative(e,t);return n.length===0?`.`:n.replaceAll(`\\`,`/`)}function quoteShellArgument(e){return`'${e.replaceAll(`'`,`'\\''`)}'`}function isNamedServiceConfigArray(e){return Array.isArray(e)}function createServiceConfigRecord(e){if(e===void 0)return{};if(isNamedServiceConfigArray(e)){let t={};for(let n of e)if(typeof n.name==`string`&&n.name.trim().length>0){let{name:e,...r}=n;t[e]=r}return t}return e}function normalizeVercelJsonConfig(e){if(!isRecord(e))throw Error(`${VERCEL_JSON_FILE_NAME} must contain a JSON object.`);let t=e.services;if(t!==void 0&&!isRecord(t)&&!(Array.isArray(t)&&t.every(e=>isRecord(e)&&typeof e.name==`string`&&e.name.trim().length>0)))throw Error(`${VERCEL_JSON_FILE_NAME} services must be a JSON object or named service array.`);return e}async function readVercelJsonConfig(e){try{return normalizeVercelJsonConfig(JSON.parse(await readFile(e,`utf8`)))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findEveService(e){return Object.values(e).find(e=>e.framework===`eve`)}function assertRootServicesIncludeEve(e,t){if(findEveService(e)===void 0)throw Error(`${VERCEL_JSON_FILE_NAME} already defines services, so the eve ${t} integration cannot add a generated eve service. Add an eve service (framework "eve") and a rewrite from ${EVE_ROUTE_PREFIX}/(.*) to it in ${VERCEL_JSON_FILE_NAME}, or remove services from ${VERCEL_JSON_FILE_NAME}.`)}function createEveServiceRoute(e=`eve`){return{destination:{service:e,type:`service`},src:EVE_SERVICE_ROUTE_SRC}}function createEveServiceRequestPathRoute(){return{src:EVE_SERVICE_ROUTE_SRC,transforms:[{args:EVE_SERVICE_ROUTE_PATH,op:`set`,type:`request.path`}]}}function isEveServiceRoute(e,t){let n=e.destination;return e.src===EVE_SERVICE_ROUTE_SRC&&isRecord(n)&&n.type===`service`&&n.service===t}function insertEveServiceRoute(e,t){let n=e.filter(e=>!(isRecord(e)&&isEveServiceRoute(e,t))),r=n.findIndex(e=>isRecord(e)&&e.handle===`filesystem`);return r===-1?[createEveServiceRoute(t),...n]:[...n.slice(0,r),createEveServiceRoute(t),...n.slice(r)]}function insertEveServiceRequestPathRoute(e){let t=(e??[]).filter(e=>e.src!==EVE_SERVICE_ROUTE_SRC);return[createEveServiceRequestPathRoute(),...t]}function createGeneratedServiceBuild(e){let t=join(e.hostRoot,`.eve/vercel-services`,`eve`),n=join(t,`.vercel`,`output`),r=join(e.hostRoot,`.vercel`,`output`),a=toPosixRelative(t,e.appRoot),c=toPosixRelative(e.appRoot,n),l=toPosixRelative(e.appRoot,r),u=e.eveBuildCommand??`node ${quoteShellArgument(toPosixRelative(e.appRoot,resolveEveBinaryPath(e.hostRoot)))} build`;return{buildCommand:`cd ${quoteShellArgument(a)} && export ${EVE_INTERNAL_BUILD_OUTPUT_DIRECTORY_ENV}=${quoteShellArgument(c)} && export ${EVE_INTERNAL_HOST_BUILD_OUTPUT_DIRECTORY_ENV}=${quoteShellArgument(l)} && ${u}`,root:toPosixRelative(e.hostRoot,t),rootDirectory:t}}async function ensureEveVercelServicesConfig(t){let n=await findClosestLinkedVercelDirectory(t.hostRoot),a=await readVercelJsonConfig(join(n===void 0?t.hostRoot:dirname(n),VERCEL_JSON_FILE_NAME)),o=createServiceConfigRecord(a.services);if(Object.keys(o).length>0)return assertRootServicesIncludeEve(o,t.frameworkName),{mode:`root`};a.experimentalServices!==void 0&&console.warn(`[eve] ${VERCEL_JSON_FILE_NAME} defines experimentalServices, which Vercel no longer routes. The eve ${t.frameworkName} integration now generates the stable services config automatically — remove experimentalServices from ${VERCEL_JSON_FILE_NAME}.`);let s=createGeneratedServiceBuild(t);return await mkdir(s.rootDirectory,{recursive:!0}),{mode:`generated`,services:{eve:{buildCommand:s.buildCommand,framework:`eve`,routes:[createEveServiceRequestPathRoute()],root:s.root}}}}function mergeEveVercelConfig(e,t){let n=e?.services??{},r=Object.entries(n).find(([e,t])=>e===`eve`||t.framework===`eve`),i=r?.[0]??`eve`,a=r?{...n,[i]:{...r[1],routes:insertEveServiceRequestPathRoute(r[1].routes)}}:{...n,...t.services};return{version:3,...e,routes:insertEveServiceRoute(e?.routes??[],i),services:a}}export{createEveServiceRequestPathRoute,createEveServiceRoute,ensureEveVercelServicesConfig,mergeEveVercelConfig};
|
package/docs/agent-config.md
CHANGED
|
@@ -22,7 +22,10 @@ project root with `eve set --model anthropic/claude-opus-4.8` or from the local
|
|
|
22
22
|
dev TUI with `/model anthropic/claude-opus-4.8`.
|
|
23
23
|
|
|
24
24
|
The root `agent.ts` can be omitted when no runtime config is needed. In that case, eve defaults
|
|
25
|
-
to `
|
|
25
|
+
to `zai/glm-5.2`. GLM 5.2 does not support image input; choose a
|
|
26
|
+
vision-capable model or [route image inputs to Gemini
|
|
27
|
+
Flash](./guides/dynamic-capabilities#route-image-inputs-to-a-vision-model).
|
|
28
|
+
When `agent.ts` is present, `model` is required.
|
|
26
29
|
|
|
27
30
|
`model` accepts a gateway model id string, which routes through the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway). To call a provider directly and configure the model in code, pass a provider-authored `LanguageModel`.
|
|
28
31
|
|
package/docs/channels/custom.mdx
CHANGED
|
@@ -388,7 +388,7 @@ defineChannel({
|
|
|
388
388
|
|
|
389
389
|
The `URL` object survives the queue boundary as a string and is reconstituted inside the workflow step. The staging pipeline calls `fetchFile` with the URL serialized as a string (the URL's `href`), which is why the example matches on `url.startsWith(...)`. Return bytes to stage the file to the sandbox, or `null` to let the URL pass through to the model provider.
|
|
390
390
|
|
|
391
|
-
The framework handles staging bytes to the sandbox, enforcing upload policy, hydrating files for the model call, and reconstituting `URL` objects after queue serialization.
|
|
391
|
+
The framework handles staging bytes to the sandbox, enforcing upload policy, hydrating files for the model call, and reconstituting `URL` objects after queue serialization. See [Inbound attachments](../sandbox#inbound-attachments) for the shared storage, size, and provider-input behavior.
|
|
392
392
|
|
|
393
393
|
## What to read next
|
|
394
394
|
|
|
@@ -160,7 +160,7 @@ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId> \
|
|
|
160
160
|
|
|
161
161
|
Message sends default to cancellation-backed `"steer"`; if a turn is active, eve buffers the follow-up, cancels that turn, and starts the message under a new turn ID. Channels and TypeScript `Session.send(...)` calls can select `turnPolicy: "queue"` when active work should finish first. Structured `inputResponses` never steer.
|
|
162
162
|
|
|
163
|
-
If
|
|
163
|
+
If the session is waiting on a human-in-the-loop approval, respond with the channel’s Approve or Cancel controls. Text messages do not decide an approval; unrelated text starts an ordinary turn while the approval stays pending and answerable. A later structured `inputResponses` answer keyed by its `requestId` still resumes the original tool call, even after intervening turns.
|
|
164
164
|
|
|
165
165
|
With one question-only batch, an exact option match or permitted freeform response answers `ask_question`. Any other follow-up marks the question unanswered and starts the new turn. With several approval or question batches pending, eve does not guess which batch plain text addresses: the message starts an ordinary turn and the batches stay open. Use structured responses to target requests unambiguously.
|
|
166
166
|
|
package/docs/getting-started.mdx
CHANGED
|
@@ -29,7 +29,7 @@ The command creates the project, installs dependencies, and initializes Git. If
|
|
|
29
29
|
Pass an AI Gateway model ID or reasoning effort when you do not want the defaults:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npx eve@latest init my-agent --model openai/gpt-5.
|
|
32
|
+
npx eve@latest init my-agent --model openai/gpt-5.6-terra --reasoning high
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
To add eve to a project that already has a `package.json`, run this command from its root before you create any `agent/` files:
|
|
@@ -96,7 +96,9 @@ await response.result();
|
|
|
96
96
|
|
|
97
97
|
The stream confirms the turn with `message.received`. Its `data.message` remains the flattened
|
|
98
98
|
summary for compatibility, and `data.parts` contains structured text and file metadata for clients
|
|
99
|
-
that render attachments. File parts never include raw bytes or internal sandbox paths.
|
|
99
|
+
that render attachments. File parts never include raw bytes or internal sandbox paths. See [Inbound
|
|
100
|
+
attachments](../../sandbox#inbound-attachments) for how eve stages byte-backed files in the session
|
|
101
|
+
sandbox and prepares them for each model call.
|
|
100
102
|
|
|
101
103
|
## Answer human input requests
|
|
102
104
|
|
|
@@ -21,6 +21,44 @@ resolver first selects a model, eve normalizes the selection and resolves any
|
|
|
21
21
|
omitted context-window metadata from the AI Gateway catalog. Dynamic tools,
|
|
22
22
|
skills, instructions, and subagents may return `null` to omit a capability.
|
|
23
23
|
|
|
24
|
+
### Route image inputs to a vision model
|
|
25
|
+
|
|
26
|
+
Use `step.started` when model choice depends on the current messages. This
|
|
27
|
+
keeps GLM for text and switches to Gemini Flash when user history contains an
|
|
28
|
+
image:
|
|
29
|
+
|
|
30
|
+
```ts title="agent/agent.ts"
|
|
31
|
+
import { defineAgent, defineDynamic } from "eve";
|
|
32
|
+
|
|
33
|
+
export default defineAgent({
|
|
34
|
+
model: defineDynamic({
|
|
35
|
+
events: {
|
|
36
|
+
"step.started": (_event, ctx) => {
|
|
37
|
+
const hasImage = ctx.messages.some(
|
|
38
|
+
(message) =>
|
|
39
|
+
message.role === "user" &&
|
|
40
|
+
Array.isArray(message.content) &&
|
|
41
|
+
message.content.some(
|
|
42
|
+
(part) =>
|
|
43
|
+
part.type === "image" ||
|
|
44
|
+
(part.type === "file" &&
|
|
45
|
+
(part.mediaType === "image" || part.mediaType.startsWith("image/"))),
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return hasImage ? "google/gemini-3.5-flash" : "zai/glm-5.2";
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
eve stages byte-backed `file` parts under `/workspace/attachments` before
|
|
57
|
+
`step.started`, but keeps their media type in `ctx.messages`. When an image
|
|
58
|
+
reaches the provider, vision models can process it and non-vision models reject
|
|
59
|
+
it. eve does not reroute automatically. See [Inbound
|
|
60
|
+
attachments](../sandbox#inbound-attachments).
|
|
61
|
+
|
|
24
62
|
## Dynamic subagents
|
|
25
63
|
|
|
26
64
|
Wrap a declared subagent's own `agent.ts` in `defineDynamic` when its
|
|
@@ -74,7 +74,7 @@ The browser still needs a production authentication policy. See [Authenticate br
|
|
|
74
74
|
## Dev vs deploy topology
|
|
75
75
|
|
|
76
76
|
- **Local dev.** `npm run dev` boots the eve dev server next to SvelteKit and proxies the eve routes to it, so the browser only ever hits the SvelteKit origin. `npm run build && npm run preview` behaves the same way: the preview server gets its own eve route proxy and either reuses the shared eve server or starts one.
|
|
77
|
-
- **Vercel.** The SvelteKit app and the eve runtime deploy as a single project.
|
|
77
|
+
- **Vercel.** The SvelteKit app and the eve runtime deploy as a single project. On Vercel builds the plugin adds Build Output [`services`](https://vercel.com/docs/services) for eve and a `routes` entry that sends `/eve/v1/**` to that service before filesystem routing; the SvelteKit app remains the default app. No `vercel.json` is required. By default the generated service runs the installed eve binary from the SvelteKit app's dependencies, so the agent directory does not need its own `package.json`. When the agent needs its own build step, set `eveBuildCommand`:
|
|
78
78
|
|
|
79
79
|
```ts
|
|
80
80
|
export default defineConfig({
|
|
@@ -95,6 +95,27 @@ The browser still needs a production authentication policy. See [Authenticate br
|
|
|
95
95
|
});
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
## Managing vercel.json yourself
|
|
99
|
+
|
|
100
|
+
When `vercel.json` declares [`services`](https://vercel.com/docs/services), the plugin generates nothing and your configuration owns routing. It must include the eve service (`framework: "eve"`) and a rewrite that exposes the eve transport, or the build fails:
|
|
101
|
+
|
|
102
|
+
```json title="vercel.json"
|
|
103
|
+
{
|
|
104
|
+
"services": {
|
|
105
|
+
"web": { "root": ".", "framework": "sveltekit" },
|
|
106
|
+
"eve": { "root": "agent", "framework": "eve", "buildCommand": "eve build" }
|
|
107
|
+
},
|
|
108
|
+
"rewrites": [{ "source": "/eve/v1/(.*)", "destination": { "service": "eve" } }]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Migrating from experimentalServices
|
|
113
|
+
|
|
114
|
+
Earlier versions of the plugin wrote the legacy `experimentalServices` field into `vercel.json`. Vercel no longer routes that model, so the plugin now ignores the field and warns when it sees one. Migrate either way:
|
|
115
|
+
|
|
116
|
+
- **Generated (default).** Delete `vercel.json` (or just its `experimentalServices` block) and set the project's Framework Preset back to SvelteKit. The plugin generates the eve service and its routing on every Vercel build.
|
|
117
|
+
- **Hand-maintained.** Replace `experimentalServices` with the stable `services` and `rewrites` shown above, and keep the Services Framework Preset.
|
|
118
|
+
|
|
98
119
|
## What to read next
|
|
99
120
|
|
|
100
121
|
- [`useEveAgent` (Svelte)](./use-eve-agent-svelte): the binding API
|
package/docs/reference/cli.md
CHANGED
|
@@ -3,12 +3,13 @@ title: "CLI"
|
|
|
3
3
|
description: "Reference for every eve CLI command: init, set, info, build, start, dev, logs, trace, link, deploy, eval, channels, and extension."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
The `eve` binary (`bin: eve`) runs from your app root
|
|
6
|
+
The `eve` binary (`bin: eve`) runs from your app root. Every command first loads `.env`/`.env.local` from that root. Running `eve` with no command runs `eve init` when the current directory is not an eve project, or `eve dev` when it is.
|
|
7
7
|
|
|
8
8
|
## Commands
|
|
9
9
|
|
|
10
10
|
| Command | Description |
|
|
11
11
|
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
12
|
+
| `eve` | Initialize the current directory, or start development when it is already an eve project |
|
|
12
13
|
| `eve init [target]` | Create a new agent, or add an agent to an existing project |
|
|
13
14
|
| `eve info` | Print the resolved application, including static instructions and discovered capabilities, routes, artifact paths, and diagnostics |
|
|
14
15
|
| `eve build` | Compile `.eve/` artifacts and build the host output; prints the output directory |
|
|
@@ -40,19 +41,22 @@ eve init [target] [--model <provider/model-id>] [--reasoning <effort>] [--channe
|
|
|
40
41
|
|
|
41
42
|
Creates a new agent app or adds an agent to an existing app. Always installs dependencies. New directories also initialize Git.
|
|
42
43
|
|
|
43
|
-
| Target
|
|
44
|
-
|
|
|
45
|
-
| `eve init my-agent`
|
|
46
|
-
| `eve init
|
|
47
|
-
| `eve init`
|
|
44
|
+
| Target | What happens |
|
|
45
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
46
|
+
| `eve init my-agent` | Creates an agent project in `my-agent/` |
|
|
47
|
+
| `eve init` or `eve init .` in an empty directory | Creates an agent project in the current directory |
|
|
48
|
+
| `eve init` or `eve init .` in a non-empty directory without `package.json` | Asks whether to scaffold in the current directory or a named subdirectory. Using the current directory preserves unrelated files but overwrites files at generated paths |
|
|
49
|
+
| `eve init .` in an existing project | Adds `agent/` plus missing `eve`, `ai`, and `zod` dependencies. Requires `package.json` and no existing `agent/` files |
|
|
50
|
+
|
|
51
|
+
Coding-agent launches and non-interactive terminals cannot answer the location prompt and fail before writing. Pass a new directory name, such as `eve init my-agent`, in those environments.
|
|
48
52
|
|
|
49
53
|
After scaffolding, a human terminal usually continues into `eve dev`. If a coding-agent REPL is on `PATH`, the handoff menu can open it instead or exit without starting either process. Coding-agent launches print the next steps instead of opening the TUI, so the session does not get stuck. Fresh projects use the parent workspace's package manager when there is one; otherwise they use the manager that launched `eve init`.
|
|
50
54
|
|
|
51
|
-
| Flag | Type | Default
|
|
52
|
-
| ---------------------- | ------ |
|
|
53
|
-
| `--model <model>` | string | `
|
|
54
|
-
| `--reasoning <effort>` | enum | provider default
|
|
55
|
-
| `--channel-web-nextjs` | flag | off
|
|
55
|
+
| Flag | Type | Default | Description |
|
|
56
|
+
| ---------------------- | ------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
57
|
+
| `--model <model>` | string | `zai/glm-5.2` | Set the root agent's AI Gateway model ID. |
|
|
58
|
+
| `--reasoning <effort>` | enum | provider default | Set reasoning to `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`. `provider-default` leaves the field unauthored. |
|
|
59
|
+
| `--channel-web-nextjs` | flag | off | Add the Web Chat app (Next.js). Not for existing projects — run `eve add channel/web` there instead. |
|
|
56
60
|
|
|
57
61
|
## `eve extension`
|
|
58
62
|
|
package/docs/sandbox.mdx
CHANGED
|
@@ -70,6 +70,14 @@ A `SandboxProcess` exposes `stdout`/`stderr` byte streams, `wait()` (resolves wi
|
|
|
70
70
|
|
|
71
71
|
The option types (`SandboxSpawnOptions`, `SandboxReadBinaryFileOptions`, `SandboxWriteBinaryFileOptions`, and so on) are named exports from `eve/sandbox`, alongside `SandboxProcess`.
|
|
72
72
|
|
|
73
|
+
## Inbound attachments
|
|
74
|
+
|
|
75
|
+
Before the first model step, eve writes byte-backed AI SDK `file` parts under
|
|
76
|
+
`/workspace/attachments` and stores a sandbox reference in session history.
|
|
77
|
+
For provider calls, images up to 3 MiB and PDFs up to 20 MiB are restored as
|
|
78
|
+
bytes; other files become text references to their sandbox paths. Unresolved
|
|
79
|
+
remote URLs and legacy AI SDK `image` parts are not staged.
|
|
80
|
+
|
|
73
81
|
## Seeding `/workspace`
|
|
74
82
|
|
|
75
83
|
Mount authored files into the sandbox at session start by placing them under `agent/sandbox/workspace/`. This requires the folder layout (`agent/sandbox/sandbox.ts`), not the top-level shorthand:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -325,6 +325,7 @@
|
|
|
325
325
|
"@vercel/oidc": "3.8.0",
|
|
326
326
|
"@vercel/otel": "2.1.3",
|
|
327
327
|
"@vercel/sandbox": "2.8.0",
|
|
328
|
+
"@vercel/sandbox-drives": "npm:@vercel/sandbox@2.10.0-beta.0",
|
|
328
329
|
"@vercel/sdk": "1.28.8",
|
|
329
330
|
"@workflow/core": "5.0.0-beta.41",
|
|
330
331
|
"@workflow/errors": "5.0.0-beta.16",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=`2.8.0`;export{e as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{mkdir,readFile}from"node:fs/promises";import{EVE_ROUTE_PREFIX}from"#protocol/routes.js";import{dirname,join,relative}from"node:path";import{EVE_INTERNAL_BUILD_OUTPUT_DIRECTORY_ENV,EVE_INTERNAL_HOST_BUILD_OUTPUT_DIRECTORY_ENV}from"#internal/application/paths.js";import{findClosestLinkedVercelDirectory}from"#shared/vercel-output-directory.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,EVE_SERVICE_ROUTE_SRC=`^${EVE_ROUTE_PREFIX}/(.*)$`,EVE_SERVICE_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/$1`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function toPosixRelative(e,t){let n=relative(e,t);return n.length===0?`.`:n.replaceAll(`\\`,`/`)}function quoteShellArgument(e){return`'${e.replaceAll(`'`,`'\\''`)}'`}function isNamedServiceConfigArray(e){return Array.isArray(e)}function createServiceConfigRecord(e){if(e===void 0)return{};if(isNamedServiceConfigArray(e)){let t={};for(let n of e)if(typeof n.name==`string`&&n.name.trim().length>0){let{name:e,...r}=n;t[e]=r}return t}return e}function normalizeVercelJsonConfig(e){if(!isRecord(e))throw Error(`${VERCEL_JSON_FILE_NAME} must contain a JSON object.`);let t=e.services;if(t!==void 0&&!isRecord(t)&&!(Array.isArray(t)&&t.every(e=>isRecord(e)&&typeof e.name==`string`&&e.name.trim().length>0)))throw Error(`${VERCEL_JSON_FILE_NAME} services must be a JSON object or named service array.`);return e}async function readVercelJsonConfig(e){try{return normalizeVercelJsonConfig(JSON.parse(await readFile(e,`utf8`)))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findEveService(e){return Object.values(e).find(e=>e.framework===`eve`)}function assertRootServicesIncludeEve(e){if(findEveService(e)===void 0)throw Error(`${VERCEL_JSON_FILE_NAME} already defines services, so the eve Nuxt module cannot add a generated eve service. Add an eve service (framework "eve") and a rewrite from ${EVE_ROUTE_PREFIX}/(.*) to it in ${VERCEL_JSON_FILE_NAME}, or remove services from ${VERCEL_JSON_FILE_NAME}.`)}function createEveServiceRoute(e=`eve`){return{destination:{service:e,type:`service`},src:EVE_SERVICE_ROUTE_SRC}}function createEveServiceRequestPathRoute(){return{src:EVE_SERVICE_ROUTE_SRC,transforms:[{args:EVE_SERVICE_ROUTE_PATH,op:`set`,type:`request.path`}]}}function isEveServiceRoute(e,t){let n=e.destination;return e.src===EVE_SERVICE_ROUTE_SRC&&isRecord(n)&&n.type===`service`&&n.service===t}function insertEveServiceRoute(e,t){let n=e.filter(e=>!(isRecord(e)&&isEveServiceRoute(e,t))),r=n.findIndex(e=>isRecord(e)&&e.handle===`filesystem`);return r===-1?[createEveServiceRoute(t),...n]:[...n.slice(0,r),createEveServiceRoute(t),...n.slice(r)]}function insertEveServiceRequestPathRoute(e){let t=(e??[]).filter(e=>e.src!==EVE_SERVICE_ROUTE_SRC);return[createEveServiceRequestPathRoute(),...t]}function createGeneratedServiceBuild(e){let t=join(e.nuxtRoot,`.eve/vercel-services`,`eve`),n=join(t,`.vercel`,`output`),r=join(e.nuxtRoot,`.vercel`,`output`),a=toPosixRelative(t,e.appRoot),c=toPosixRelative(e.appRoot,n),l=toPosixRelative(e.appRoot,r),u=e.eveBuildCommand??`node ${quoteShellArgument(toPosixRelative(e.appRoot,resolveEveBinaryPath(e.nuxtRoot)))} build`;return{buildCommand:`cd ${quoteShellArgument(a)} && export ${EVE_INTERNAL_BUILD_OUTPUT_DIRECTORY_ENV}=${quoteShellArgument(c)} && export ${EVE_INTERNAL_HOST_BUILD_OUTPUT_DIRECTORY_ENV}=${quoteShellArgument(l)} && ${u}`,root:toPosixRelative(e.nuxtRoot,t),rootDirectory:t}}async function ensureEveVercelServicesConfig(t){let n=await findClosestLinkedVercelDirectory(t.nuxtRoot),a=await readVercelJsonConfig(join(n===void 0?t.nuxtRoot:dirname(n),VERCEL_JSON_FILE_NAME)),o=createServiceConfigRecord(a.services);if(Object.keys(o).length>0)return assertRootServicesIncludeEve(o),{mode:`root`};a.experimentalServices!==void 0&&console.warn(`[eve] ${VERCEL_JSON_FILE_NAME} defines experimentalServices, which Vercel no longer routes. The eve Nuxt module now generates the stable services config automatically — remove experimentalServices from ${VERCEL_JSON_FILE_NAME}.`);let s=createGeneratedServiceBuild(t);return await mkdir(s.rootDirectory,{recursive:!0}),{mode:`generated`,services:{eve:{buildCommand:s.buildCommand,framework:`eve`,routes:[createEveServiceRequestPathRoute()],root:s.root}}}}function mergeEveVercelConfig(e,t){let n=e?.services??{},r=Object.entries(n).find(([e,t])=>e===`eve`||t.framework===`eve`),i=r?.[0]??`eve`,a=r?{...n,[i]:{...r[1],routes:insertEveServiceRequestPathRoute(r[1].routes)}}:{...n,...t.services};return{version:3,...e,routes:insertEveServiceRoute(e?.routes??[],i),services:a}}export{createEveServiceRequestPathRoute,createEveServiceRoute,ensureEveVercelServicesConfig,mergeEveVercelConfig};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface EnsureVercelJsonResult {
|
|
2
|
-
readonly servicePrefix: string;
|
|
3
|
-
}
|
|
4
|
-
/**
|
|
5
|
-
* Ensure `vercel.json` declares the SvelteKit web service and the eve agent
|
|
6
|
-
* service so a Vercel deployment ships both from one project.
|
|
7
|
-
*
|
|
8
|
-
* Existing services are preserved untouched; an already-configured eve
|
|
9
|
-
* service's `routePrefix` wins over {@link input.servicePrefix}. The file is
|
|
10
|
-
* only rewritten when the resulting config differs from what is on disk.
|
|
11
|
-
*/
|
|
12
|
-
export declare function ensureEveVercelJson(input: {
|
|
13
|
-
readonly appRoot: string;
|
|
14
|
-
readonly eveBuildCommand: string;
|
|
15
|
-
readonly servicePrefix: string;
|
|
16
|
-
readonly svelteKitRoot: string;
|
|
17
|
-
}): Promise<EnsureVercelJsonResult>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createEveVercelRewrite}from"./routing.js";import{readFile,writeFile}from"node:fs/promises";import{join,relative}from"node:path";const VERCEL_JSON_FILE_NAME=`vercel.json`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function resolveRelativeEntrypoint(e,t){let n=relative(e,t);return n.length===0?`.`:n.replaceAll(`\\`,`/`)}function normalizeVercelJsonConfig(e){if(!isRecord(e))throw Error(`${VERCEL_JSON_FILE_NAME} must contain a JSON object.`);let t=e.experimentalServices;if(t!==void 0&&!isRecord(t))throw Error(`${VERCEL_JSON_FILE_NAME} experimentalServices must be a JSON object.`);let n=e.rewrites;if(n!==void 0&&!Array.isArray(n))throw Error(`${VERCEL_JSON_FILE_NAME} rewrites must be an array.`);return e}async function readVercelJsonConfig(e){try{return normalizeVercelJsonConfig(JSON.parse(await readFile(e,`utf8`)))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findServiceByFramework(e,t){return Object.values(e).find(e=>e.framework===t)}function hasRewrite(e,t){return e.some(e=>e.source===t.source&&e.destination===t.destination)}async function ensureEveVercelJson(t){let r=join(t.svelteKitRoot,VERCEL_JSON_FILE_NAME),i=await readVercelJsonConfig(r),a=resolveRelativeEntrypoint(t.svelteKitRoot,t.appRoot),o=i.experimentalServices??{},s=findServiceByFramework(o,`eve`),c=findServiceByFramework(o,`sveltekit`),l=s?.routePrefix??t.servicePrefix,u={...o};c===void 0&&(u.web={entrypoint:`.`,framework:`sveltekit`,routePrefix:`/`}),s===void 0&&(u.eve={buildCommand:t.eveBuildCommand,entrypoint:a,framework:`eve`,routePrefix:l});let d=createEveVercelRewrite(l),f=i.rewrites??[],p={...i,$schema:i.$schema??`https://openapi.vercel.sh/vercel.json`,experimentalServices:u,rewrites:hasRewrite(f,d)?f:[d,...f]};return JSON.stringify(i)!==JSON.stringify(p)&&await writeFile(r,`${JSON.stringify(p,null,2)}\n`),{servicePrefix:l}}export{ensureEveVercelJson};
|