eve 0.27.8 → 0.27.9
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 +12 -0
- package/dist/src/cli/commands/registry.d.ts +5 -1
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/commands/trace.d.ts +32 -0
- package/dist/src/cli/commands/trace.js +6 -0
- package/dist/src/cli/run.js +2 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -1
- package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
- package/dist/src/compiled/@opentelemetry/api/index.d.ts +23 -5
- package/dist/src/compiled/@opentelemetry/otlp-transformer/LICENSE +201 -0
- package/dist/src/compiled/@opentelemetry/otlp-transformer/index.d.ts +3 -0
- package/dist/src/compiled/@opentelemetry/otlp-transformer/index.js +1 -0
- package/dist/src/compiled/@vercel/otel/LICENSE +21 -0
- package/dist/src/compiled/@vercel/otel/index.d.ts +16 -0
- package/dist/src/compiled/@vercel/otel/index.js +17 -0
- package/dist/src/compiled/@workflow/world-vercel/index.js +7 -7
- package/dist/src/compiled/_chunks/workflow/chunk-5MU5Z6L3-BYQ2wtp-.js +1 -0
- package/dist/src/compiled/_chunks/workflow/chunk-NWCAEW5Y-Dp6gZq6P.js +1 -0
- package/dist/src/compiled/_chunks/workflow/getMachineId-bsd-WEBNKY2R-Cls8BaDr.js +1 -0
- package/dist/src/compiled/_chunks/workflow/getMachineId-darwin-LT47KAXP-Bpw5H-nL.js +2 -0
- package/dist/src/compiled/_chunks/workflow/getMachineId-linux-LTVQO6VW-CpqQTfzr.js +1 -0
- package/dist/src/compiled/_chunks/workflow/getMachineId-unsupported-UKWBA27G-2_M88Nra.js +1 -0
- package/dist/src/compiled/_chunks/workflow/getMachineId-win-NLJKOPY6-D0EDY-ev.js +1 -0
- package/dist/src/compiler/extension-compatibility.d.ts +4 -4
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/web-fetch/request.d.ts +14 -0
- package/dist/src/execution/web-fetch/request.js +1 -0
- package/dist/src/execution/web-fetch/tool.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/agent-otel-provider.d.ts +49 -0
- package/dist/src/harness/agent-otel-provider.js +1 -0
- package/dist/src/harness/agent-trace-context-store.d.ts +12 -0
- package/dist/src/harness/agent-trace-context-store.js +1 -0
- package/dist/src/harness/agent-trace-span-processor.d.ts +12 -0
- package/dist/src/harness/agent-trace-span-processor.js +1 -0
- package/dist/src/harness/ai-sdk-hook-bridge.d.ts +4 -0
- package/dist/src/harness/ai-sdk-hook-bridge.js +1 -0
- package/dist/src/harness/compaction-prompt.d.ts +7 -0
- package/dist/src/harness/compaction-prompt.js +1 -1
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/instrumentation-lifecycle.d.ts +142 -0
- package/dist/src/harness/instrumentation-lifecycle.js +1 -0
- package/dist/src/harness/instrumentation-native-events.d.ts +12 -0
- package/dist/src/harness/instrumentation-native-events.js +1 -0
- package/dist/src/harness/instrumentation-runtime.d.ts +13 -0
- package/dist/src/harness/instrumentation-runtime.js +1 -0
- package/dist/src/harness/local-instrumentation-runtime.d.ts +7 -0
- package/dist/src/harness/local-instrumentation-runtime.js +1 -0
- package/dist/src/harness/local-trace-span-processor.d.ts +10 -0
- package/dist/src/harness/local-trace-span-processor.js +1 -0
- package/dist/src/harness/otel-integration.d.ts +3 -0
- package/dist/src/harness/otel-integration.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/tool-model-output.d.ts +40 -0
- package/dist/src/harness/tool-model-output.js +1 -0
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/harness/types.d.ts +6 -0
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.d.ts +1 -0
- package/dist/src/internal/nitro/host/local-tracing-runtime-plugin.js +1 -0
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +1 -1
- package/dist/src/public/tools/index.d.ts +2 -1
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/public/tools/output-builders.d.ts +53 -0
- package/dist/src/public/tools/output-builders.js +1 -0
- package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
- package/dist/src/setup/scaffold/channels-catalog.d.ts +2 -0
- package/dist/src/setup/scaffold/channels-catalog.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/shared/network-address.d.ts +6 -0
- package/dist/src/shared/network-address.js +1 -1
- package/dist/src/shared/tool-definition.d.ts +29 -0
- package/docs/channels/overview.mdx +2 -2
- package/docs/connections/overview.mdx +1 -1
- package/docs/extensions.md +1 -0
- package/docs/guides/instrumentation.md +17 -7
- package/docs/guides/state.md +1 -1
- package/docs/install-integrations.mdx +3 -1
- package/docs/patterns/multi-tenant-memory.md +1 -1
- package/docs/reference/cli.md +14 -1
- package/docs/tools/overview.mdx +29 -0
- package/package.json +8 -4
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{executeWebFetchTool}from"#execution/web-fetch/tool.js";async function executeWebFetch(e,t){return executeWebFetchTool(e,{abortSignal:t?.abortSignal})}const WEB_FETCH_INPUT_SCHEMA=z.strictObject({format:z.enum([`markdown`,`text`,`html`]).describe(`The format to return the content in (text, markdown, or html). HTML responses are automatically converted to the requested format. Defaults to "markdown".`).optional(),timeout:z.number().describe(`Optional timeout in seconds. Defaults to 30, max 120.`).optional(),url:z.string().describe(`The fully-formed URL to fetch content from. Must start with
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{executeWebFetchTool}from"#execution/web-fetch/tool.js";async function executeWebFetch(e,t){return executeWebFetchTool(e,{abortSignal:t?.abortSignal})}const WEB_FETCH_INPUT_SCHEMA=z.strictObject({format:z.enum([`markdown`,`text`,`html`]).describe(`The format to return the content in (text, markdown, or html). HTML responses are automatically converted to the requested format. Defaults to "markdown".`).optional(),timeout:z.number().describe(`Optional timeout in seconds. Defaults to 30, max 120.`).optional(),url:z.string().describe(`The fully-formed URL to fetch content from. Must start with https://.`)}),WEB_FETCH_OUTPUT_SCHEMA=z.strictObject({content:z.string(),contentType:z.string(),truncated:z.boolean(),url:z.string()}),WEB_FETCH_TOOL_DEFINITION={description:[`Fetch a webpage and return its content in the requested format. Use this to retrieve and analyze content from URLs.`,``,`Usage notes:`,`- The URL must be a fully-formed valid URL starting with https://`,`- HTML responses are automatically converted to markdown or plain text based on the requested format`,`- Format options: "markdown" (default), "text", or "html"`,`- Default timeout is 30 seconds (max 120 seconds)`,`- Maximum response size is 5 MB; content is further capped at the shared tool-output budget (50 KB / 2000 lines)`,`- This tool is read-only and does not modify any files`].join(`
|
|
2
2
|
`),execute:executeWebFetch,inputSchema:WEB_FETCH_INPUT_SCHEMA,logicalPath:`eve:framework/web-fetch`,name:`web_fetch`,outputSchema:WEB_FETCH_OUTPUT_SCHEMA,sourceId:`eve:web-fetch-tool`,sourceKind:`module`};export{WEB_FETCH_INPUT_SCHEMA,WEB_FETCH_OUTPUT_SCHEMA,WEB_FETCH_TOOL_DEFINITION};
|
|
@@ -16,6 +16,8 @@ export interface ScaffoldableChannel {
|
|
|
16
16
|
slug: string;
|
|
17
17
|
/** Internal scaffolder kind passed to `ensureChannel`. */
|
|
18
18
|
kind: ChannelKind;
|
|
19
|
+
/** Canonical item in the official eve registry. */
|
|
20
|
+
registryItem: `channel/${ChannelKind}`;
|
|
19
21
|
/** Picker label. */
|
|
20
22
|
label: string;
|
|
21
23
|
/** Optional picker hint. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{channelEntries}from"../../packages/eve-catalog/src/index.js";const CHANNEL_SCAFFOLDS=[{slug:`eve`,kind:`web`,label:`Web Chat`,hint:`Next.js app`},{slug:`slack`,kind:`slack`,label:`Slack`,hint:`Slack app mentions and DMs`}];function buildScaffoldableChannels(){let n=new Set(channelEntries().filter(e=>e.surfaces.scaffoldable).map(e=>e.slug)),r=[];for(let e of CHANNEL_SCAFFOLDS){if(!n.delete(e.slug))throw Error(`Channel overlay "${e.slug}" is not a scaffoldable channel in @vercel/eve-catalog.`);let t={slug:e.slug,kind:e.kind,label:e.label};e.hint!==void 0&&(t.hint=e.hint),r.push(t)}if(n.size>0){let e=[...n].sort().join(`, `);throw Error(`Scaffoldable catalog channels missing a scaffolder overlay: ${e}.`)}return r}const SCAFFOLDABLE_CHANNELS=buildScaffoldableChannels();export{SCAFFOLDABLE_CHANNELS};
|
|
1
|
+
import{channelEntries}from"../../packages/eve-catalog/src/index.js";const CHANNEL_SCAFFOLDS=[{slug:`eve`,kind:`web`,registryItem:`channel/web`,label:`Web Chat`,hint:`Next.js app`},{slug:`slack`,kind:`slack`,registryItem:`channel/slack`,label:`Slack`,hint:`Slack app mentions and DMs`}];function buildScaffoldableChannels(){let n=new Set(channelEntries().filter(e=>e.surfaces.scaffoldable).map(e=>e.slug)),r=[];for(let e of CHANNEL_SCAFFOLDS){if(!n.delete(e.slug))throw Error(`Channel overlay "${e.slug}" is not a scaffoldable channel in @vercel/eve-catalog.`);let t={slug:e.slug,kind:e.kind,registryItem:e.registryItem,label:e.label};e.hint!==void 0&&(t.hint=e.hint),r.push(t)}if(n.size>0){let e=[...n].sort().join(`, `);throw Error(`Scaffoldable catalog channels missing a scaffolder overlay: ${e}.`)}return r}const SCAFFOLDABLE_CHANNELS=buildScaffoldableChannels();export{SCAFFOLDABLE_CHANNELS};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"../update/package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{agentTemplateFiles,formatEveDependencySpecifier,resolveEvePackageContract}from"./project.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=i.packageManager??`pnpm`,o=join(i.projectRoot,`package.json`);if(!await pathExists(o))throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let s=agentTemplateFiles(i.model),c=[];for(let t of Object.keys(s))await pathExists(join(i.projectRoot,t))&&c.push(t);if(c.length===0&&await pathExists(join(i.projectRoot,`agent`))&&c.push(`agent/`),c.length>0)throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it already has: ${c.join(`, `)}.`);let l=resolveEvePackageContract(i.evePackage),u=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`^7.0.
|
|
1
|
+
import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"../update/package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{agentTemplateFiles,formatEveDependencySpecifier,resolveEvePackageContract}from"./project.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=i.packageManager??`pnpm`,o=join(i.projectRoot,`package.json`);if(!await pathExists(o))throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let s=agentTemplateFiles(i.model),c=[];for(let t of Object.keys(s))await pathExists(join(i.projectRoot,t))&&c.push(t);if(c.length===0&&await pathExists(join(i.projectRoot,`agent`))&&c.push(`agent/`),c.length>0)throw Error(`Cannot add an eve agent to "${i.projectRoot}" because it already has: ${c.join(`, `)}.`);let l=resolveEvePackageContract(i.evePackage),u=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`^7.0.38`),d=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.4.2`),f=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),p=[];for(let[e,n]of Object.entries(s)){let r=join(i.projectRoot,e);await writeTextFile(r,n),p.push(r)}let m=JSON.parse(await readFile(o,`utf8`)),h={"@vercel/connect":d,ai:u,eve:formatEveDependencySpecifier(l.version),zod:f},g={};for(let[e,t]of Object.entries(h))hasDeclaredDependency(m,e)||(g[e]=t);let _={};Object.keys(g).length>0&&(_.dependencies=g),isPackageManagerWorkspaceMember(a,i.projectRoot)||(_.nodeEngineRequirement=l.nodeEngine);let v=await patchPackageJson(o,_),y=(await patchWorkspaceRootPackageJson(a,i.projectRoot,{aiPackageVersion:u,nodeEngineRequirement:l.nodeEngine})).nodeEngineOverride??v.nodeEngineOverride;return await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:i.projectRoot}),{filesWritten:p,dependenciesAdded:Object.keys(g).sort(),nodeEngineOverride:y}}export{addAgentToProject};
|
|
@@ -1,4 +1,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{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.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.
|
|
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{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.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.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.27.9`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -93,4 +93,4 @@ export default defineAgent({
|
|
|
93
93
|
},
|
|
94
94
|
},
|
|
95
95
|
});
|
|
96
|
-
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate({includeRootOnlyFields:e.includeRootOnlyPackageJsonFields,packageManager:e.packageManager})}}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(t){let s=resolve(t.targetDirectory??process.cwd(),t.projectName),c=t.projectName===`.`,l=t.overwriteExisting??!1,u=t.byokProvider??!1,d=t.packageManager??`pnpm`,f=resolveEvePackageContract(t.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine),m=resolve(t.workspaceProbeDirectory??s),h=isPackageManagerWorkspaceMember(d,m);if(c)await assertCanCreateInPlace(s,l);else if(await pathExists(s))throw Error(`Cannot create project because "${s}" already exists.`);let g={appName:basename(s),model:t.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,t.aiPackageVersion??`^7.0.
|
|
96
|
+
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate({includeRootOnlyFields:e.includeRootOnlyPackageJsonFields,packageManager:e.packageManager})}}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(t){let s=resolve(t.targetDirectory??process.cwd(),t.projectName),c=t.projectName===`.`,l=t.overwriteExisting??!1,u=t.byokProvider??!1,d=t.packageManager??`pnpm`,f=resolveEvePackageContract(t.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine),m=resolve(t.workspaceProbeDirectory??s),h=isPackageManagerWorkspaceMember(d,m);if(c)await assertCanCreateInPlace(s,l);else if(await pathExists(s))throw Error(`Cannot create project because "${s}" already exists.`);let g={appName:basename(s),model:t.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,t.aiPackageVersion??`^7.0.38`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,t.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,t.typescriptPackageVersion??`7.0.2`),nodeTypesVersion:p,nodeEngine:p};await mkdir(s,{recursive:!0});for(let[e,i]of Object.entries(templateFiles({byokProvider:u,includeRootOnlyPackageJsonFields:!h,packageManager:d}))){let a=`${s}/${e}`,o=await pathExists(a);await writeTextFile(a,renderTemplate(i,g),{force:c&&l}),o&&await t.onOverwriteFile?.(a)}return await applyPackageManagerWorkspaceConfiguration({packageManager:d,projectRoot:s,workspaceProbeRoot:m,onWorkspaceRootMutation:t.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(d,m,{aiPackageVersion:g.aiPackageVersion,nodeEngineRequirement:f.nodeEngine,onWorkspaceRootMutation:t.onWorkspaceRootMutation}),s}async function isEveProject(e){for(let n of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${n}`)),!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,ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.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,unlink,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,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);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!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){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`^7.0.
|
|
1
|
+
import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.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,unlink,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,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);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!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){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`^7.0.38`,nextPackageVersion:e?.nextPackageVersion??`16.3.0-preview.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n,r,a,c){let d=join(e,`package.json`);if(!await pathExists(d))return{mutations:[]};let p=resolveEvePackageContract(a.evePackage),h=pinnedNodeEngineMajor(p.nodeEngine),g={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,a.aiPackageVersion),eve:formatEveDependencySpecifier(p.version),next:resolveVersionToken(`nextPackageVersion`,a.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,a.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,a.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,a.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,a.zodPackageVersion)},_={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":h,"@types/react":resolveVersionToken(`typesReactPackageVersion`,a.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,a.typesReactDomPackageVersion),typescript:`6.0.3`},v=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,y=isPackageManagerWorkspaceMember(n,r),b={dependencies:g,devDependencies:_,scripts:v};y||(b.nodeEngineRequirement=p.nodeEngine);let x=await patchPackageJson(d,b),S=(await patchWorkspaceRootPackageJson(n,r,{aiPackageVersion:g.ai,nodeEngineRequirement:p.nodeEngine,onWorkspaceRootMutation:c})).nodeEngineOverride??x.nodeEngineOverride;return{mutations:[{path:d,dependencies:Object.keys(g),devDependencies:Object.keys(_),scripts:Object.keys(v)}],nodeEngineOverride:S}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackConnectTemplate(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({
|
|
@@ -21,3 +21,9 @@ export declare function isLoopbackServerUrl(urlText: string): boolean;
|
|
|
21
21
|
* hostname that resolves to a private address is not caught at this layer.
|
|
22
22
|
*/
|
|
23
23
|
export declare function isReservedIpAddress(host: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether `host` is an IP literal that must not be used as the destination of
|
|
26
|
+
* an untrusted outbound request. Unlike {@link isReservedIpAddress}, this also
|
|
27
|
+
* blocks loopback addresses.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isPrivateOrReservedIpAddress(host: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{BlockList,isIP}from"node:net";const httpServerUrlSchema=z.url({protocol:/^https?$/}),reservedRanges=new BlockList;reservedRanges.addSubnet(`0.0.0.0`,8,`ipv4`),reservedRanges.addSubnet(`10.0.0.0`,8,`ipv4`),reservedRanges.addSubnet(`100.64.0.0`,10,`ipv4`),reservedRanges.addSubnet(`169.254.0.0`,16,`ipv4`),reservedRanges.addSubnet(`172.16.0.0`,12,`ipv4`),reservedRanges.addSubnet(`192.168.0.0`,16,`ipv4`),reservedRanges.addSubnet(`198.18.0.0`,15,`ipv4`),reservedRanges.addAddress(`::`,`ipv6`),reservedRanges.addSubnet(`fc00::`,7,`ipv6`),reservedRanges.addSubnet(`fe80::`,10,`ipv6`);function normalizeAddress(e){let t=e.trim().replace(/^\[(.*)\]$/u,`$1`),n=t.indexOf(`%`),r=n===-1?t:t.slice(0,n);if(r.toLowerCase().startsWith(`::ffff:`)){let e=r.slice(7);if(isIP(e)===4)return e}return r}function isLoopbackHostname(e){let t=normalizeAddress(e).toLowerCase();if(t===`localhost`||t.endsWith(`.localhost`))return!0;let n=isIP(t);return n
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{BlockList,isIP}from"node:net";const httpServerUrlSchema=z.url({protocol:/^https?$/}),reservedRanges=new BlockList;reservedRanges.addSubnet(`0.0.0.0`,8,`ipv4`),reservedRanges.addSubnet(`10.0.0.0`,8,`ipv4`),reservedRanges.addSubnet(`100.64.0.0`,10,`ipv4`),reservedRanges.addSubnet(`169.254.0.0`,16,`ipv4`),reservedRanges.addSubnet(`172.16.0.0`,12,`ipv4`),reservedRanges.addSubnet(`192.0.0.0`,24,`ipv4`),reservedRanges.addSubnet(`192.0.2.0`,24,`ipv4`),reservedRanges.addSubnet(`192.88.99.0`,24,`ipv4`),reservedRanges.addSubnet(`192.168.0.0`,16,`ipv4`),reservedRanges.addSubnet(`198.18.0.0`,15,`ipv4`),reservedRanges.addSubnet(`198.51.100.0`,24,`ipv4`),reservedRanges.addSubnet(`203.0.113.0`,24,`ipv4`),reservedRanges.addSubnet(`224.0.0.0`,4,`ipv4`),reservedRanges.addSubnet(`240.0.0.0`,4,`ipv4`),reservedRanges.addAddress(`::`,`ipv6`),reservedRanges.addSubnet(`::`,96,`ipv6`),reservedRanges.addSubnet(`64:ff9b::`,96,`ipv6`),reservedRanges.addSubnet(`64:ff9b:1::`,48,`ipv6`),reservedRanges.addSubnet(`100::`,64,`ipv6`),reservedRanges.addSubnet(`2001::`,23,`ipv6`),reservedRanges.addSubnet(`2001:db8::`,32,`ipv6`),reservedRanges.addSubnet(`2002::`,16,`ipv6`),reservedRanges.addSubnet(`fc00::`,7,`ipv6`),reservedRanges.addSubnet(`fe80::`,10,`ipv6`),reservedRanges.addSubnet(`ff00::`,8,`ipv6`);const loopbackRanges=new BlockList;loopbackRanges.addSubnet(`127.0.0.0`,8,`ipv4`),loopbackRanges.addAddress(`::1`,`ipv6`);function normalizeAddress(e){let t=e.trim().replace(/^\[(.*)\]$/u,`$1`),n=t.indexOf(`%`),r=n===-1?t:t.slice(0,n);if(r.toLowerCase().startsWith(`::ffff:`)){let e=r.slice(7);if(isIP(e)===4)return e}return r}function isLoopbackHostname(e){let t=normalizeAddress(e).toLowerCase().replace(/\.$/u,``);if(t===`localhost`||t.endsWith(`.localhost`))return!0;let n=isIP(t);return n!==0&&loopbackRanges.check(t,n===4?`ipv4`:`ipv6`)}function isLoopbackServerUrl(e){let t=httpServerUrlSchema.safeParse(e);return t.success&&isLoopbackHostname(new URL(t.data).hostname)}function isReservedIpAddress(e){let t=normalizeAddress(e);if(isLoopbackHostname(t))return!1;let n=isIP(t);return n===0?!1:reservedRanges.check(t,n===4?`ipv4`:`ipv6`)}function isPrivateOrReservedIpAddress(e){return isLoopbackHostname(e)||isReservedIpAddress(e)}export{httpServerUrlSchema,isLoopbackHostname,isLoopbackServerUrl,isPrivateOrReservedIpAddress,isReservedIpAddress};
|
|
@@ -46,6 +46,10 @@ export interface PublicToolDefinitionWithExecuteFn<TInput = unknown, TOutput = u
|
|
|
46
46
|
* eve-owned shape for the model-facing tool result produced by
|
|
47
47
|
* `toModelOutput`. Structurally compatible with the AI SDK's
|
|
48
48
|
* `ToolResultOutput` so the harness can forward it without conversion.
|
|
49
|
+
*
|
|
50
|
+
* The `content` variant carries an ordered list of
|
|
51
|
+
* {@link ToolModelOutputPart} entries, letting a tool hand the model
|
|
52
|
+
* text alongside inline files (e.g. a screenshot as vision input).
|
|
49
53
|
*/
|
|
50
54
|
export type ToolModelOutput = {
|
|
51
55
|
readonly type: "text";
|
|
@@ -53,5 +57,30 @@ export type ToolModelOutput = {
|
|
|
53
57
|
} | {
|
|
54
58
|
readonly type: "json";
|
|
55
59
|
readonly value: unknown;
|
|
60
|
+
} | {
|
|
61
|
+
readonly type: "content";
|
|
62
|
+
readonly value: readonly ToolModelOutputPart[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* One part of a `content` {@link ToolModelOutput}. Mirrors the AI SDK's
|
|
66
|
+
* `ToolResultOutput` content parts narrowed to the JSON-safe subset:
|
|
67
|
+
* file data is the SDK's tagged `FileData` union restricted to
|
|
68
|
+
* `{ type: "data" }` with a base64 string, so persisted tool results
|
|
69
|
+
* survive the durable JSON boundary. Use the `toolOutputPart` builders
|
|
70
|
+
* from `eve/tools` to construct parts without hand-writing the nesting.
|
|
71
|
+
*/
|
|
72
|
+
export type ToolModelOutputPart = {
|
|
73
|
+
readonly type: "text";
|
|
74
|
+
readonly text: string;
|
|
75
|
+
} | {
|
|
76
|
+
readonly type: "file";
|
|
77
|
+
/** Tagged file data; only JSON-safe base64 payloads are accepted. */
|
|
78
|
+
readonly data: {
|
|
79
|
+
readonly type: "data";
|
|
80
|
+
readonly data: string;
|
|
81
|
+
};
|
|
82
|
+
/** IANA media type, e.g. `image/png`. */
|
|
83
|
+
readonly mediaType: string;
|
|
84
|
+
readonly filename?: string;
|
|
56
85
|
};
|
|
57
86
|
export {};
|
|
@@ -9,7 +9,7 @@ A channel is the edge adapter between a platform and your agent. It does three t
|
|
|
9
9
|
- Owns the `continuationToken`, the resume handle for a conversation on that surface.
|
|
10
10
|
- Decides delivery, meaning how, where, and whether a response goes back.
|
|
11
11
|
|
|
12
|
-
eve ships a base HTTP channel plus first-class platform channels, and you can author your own. Browse the full set in the [Integrations](/integrations) gallery.
|
|
12
|
+
eve ships a base HTTP channel plus first-class platform channels, and you can author your own. Browse the full set in the [Integrations](/integrations?filter=channel) gallery.
|
|
13
13
|
|
|
14
14
|
After a channel normalizes input, eve runs the same agent runtime regardless of where the message came from. Tools and instructions do not need channel-specific logic.
|
|
15
15
|
|
|
@@ -70,4 +70,4 @@ Where an eve agent communicates with people, you may be required to disclose tha
|
|
|
70
70
|
- [Slack](./slack): the most common platform channel, end to end
|
|
71
71
|
- [Custom channels](./custom): build a channel for any surface with `defineChannel`
|
|
72
72
|
- [Frontend](../guides/frontend/overview): browser chat on the eve channel with `useEveAgent`
|
|
73
|
-
- [Integrations](/integrations): browse every built-in channel
|
|
73
|
+
- [Integrations](/integrations?filter=channel): browse every built-in channel in one gallery
|
|
@@ -274,6 +274,6 @@ A tool can require both sign-in (`auth`) and a human approval. The model's appro
|
|
|
274
274
|
|
|
275
275
|
- [MCP connections](/docs/connections/mcp): connect to remote MCP servers.
|
|
276
276
|
- [OpenAPI connections](/docs/connections/openapi): generate tools from OpenAPI operations.
|
|
277
|
-
- [Integrations](/integrations): browse every
|
|
277
|
+
- [Integrations](/integrations?filter=connection): browse every connection eve ships, in one gallery.
|
|
278
278
|
- [Tools](/docs/tools): authored tools live alongside connection-provided tools; the same approval helpers apply.
|
|
279
279
|
- [Security model](/docs/concepts/security-model): how connection credentials stay out of the model's reach.
|
package/docs/extensions.md
CHANGED
|
@@ -321,6 +321,7 @@ At build time, eve checks the extension's generated capability metadata. If the
|
|
|
321
321
|
|
|
322
322
|
## What to read next
|
|
323
323
|
|
|
324
|
+
- [Extension integrations](/integrations?filter=extension): browse ready-to-install extensions
|
|
324
325
|
- [Tools](/docs/tools): static tools, approval, and tool output
|
|
325
326
|
- [Dynamic capabilities](/docs/guides/dynamic-capabilities): dynamic tools, skills, and instructions
|
|
326
327
|
- [Instructions](/docs/instructions): static and TypeScript instructions
|
|
@@ -7,15 +7,25 @@ description: "Trace an agent with OpenTelemetry in instrumentation.ts, read the
|
|
|
7
7
|
|
|
8
8
|
If you intend to export telemetry, review the exporter destination, data categories, and required legal approvals before enabling telemetry.
|
|
9
9
|
|
|
10
|
+
## Zero-config local traces
|
|
11
|
+
|
|
12
|
+
When no authored `instrumentation.ts` exists, `eve dev` records agent, AI SDK, and user-created OpenTelemetry spans under `.eve/traces/v1`. Each session has one trace, rooted independently from Workflow telemetry, with turns, model steps, and tool actions represented explicitly. Spans created by application code while a model or tool is executing inherit that active agent context.
|
|
13
|
+
|
|
14
|
+
The directory is an immutable OTLP/JSON spool and remains available after `eve dev` exits. Inspection tools may build a query index from these segments, but the index is derived and can be rebuilt without changing the captured trace data.
|
|
15
|
+
|
|
16
|
+
Use `eve trace ls` to list captured traces and `eve trace <trace>` to inspect a session's span tree.
|
|
17
|
+
|
|
18
|
+
The local writer is an internal development default, not a second provider layered over authored instrumentation. When `instrumentation.ts` exists, its setup retains control and the zero-config writer is not installed.
|
|
19
|
+
|
|
10
20
|
## Three observability surfaces
|
|
11
21
|
|
|
12
22
|
eve observes an agent through three distinct surfaces. They do not all live in this file, and they write to different places:
|
|
13
23
|
|
|
14
|
-
| Surface | Configured in `instrumentation.ts`?
|
|
15
|
-
| -------------------------------- |
|
|
16
|
-
| **Workflow run tags** (`$eve.*`) | No (automatic)
|
|
17
|
-
| **OpenTelemetry export** |
|
|
18
|
-
| **Runtime context events** | Yes: `events["step.started"]`
|
|
24
|
+
| Surface | Configured in `instrumentation.ts`? | What it is |
|
|
25
|
+
| -------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| **Workflow run tags** (`$eve.*`) | No (automatic) | Framework-owned attributes on each Vercel Workflow run. Let dashboards stitch session, turn, and subagent runs into a tree and surface model and token usage. |
|
|
27
|
+
| **OpenTelemetry export** | Local: automatic. Authored: `setup` and capture settings | Where agent and AI spans are exported and what they record. |
|
|
28
|
+
| **Runtime context events** | Yes: `events["step.started"]` | Per-model-call values written into the AI SDK's runtime context, which the AI SDK carries onto its spans. |
|
|
19
29
|
|
|
20
30
|
The two configurable surfaces send AI SDK spans to your OpenTelemetry backend. Workflow run tags are a separate system, queryable in the Workflow dashboard rather than on your OTel spans. The sections below cover what you configure here; [Workflow run tags](#workflow-run-tags) documents what eve emits on its own.
|
|
21
31
|
|
|
@@ -98,9 +108,9 @@ A channel exposes its identity through `kind`. For authored channels it is `chan
|
|
|
98
108
|
|
|
99
109
|
Channel metadata is channel-owned. Built-in channels expose only the fields they choose to make observable; Slack, for example, projects `channelId`, `teamId`, `threadTs`, and `triggeringUserId` from its durable channel state. User-authored channels expose their own projection by returning `metadata(state)` from `defineChannel`. Runtime instrumentation never falls back to raw channel state.
|
|
100
110
|
|
|
101
|
-
##
|
|
111
|
+
## Authored trace hierarchy
|
|
102
112
|
|
|
103
|
-
When telemetry is enabled, each turn produces a trace like:
|
|
113
|
+
The existing authored `instrumentation.ts` path remains separate from zero-config local traces. When authored telemetry is enabled, each turn currently produces a trace like:
|
|
104
114
|
|
|
105
115
|
```text
|
|
106
116
|
ai.eve.turn {eve.session.id}
|
package/docs/guides/state.md
CHANGED
|
@@ -69,7 +69,7 @@ Every [subagent](../subagents) starts with its own fresh state, whether it's a b
|
|
|
69
69
|
|
|
70
70
|
## State vs. connection-side storage
|
|
71
71
|
|
|
72
|
-
`defineState` holds conversation-scoped working memory that lives and dies with the session, including counters, the current plan, and what the user has told you this conversation. It is the agent's short-term memory, persisted durably for the life of the session. Anything that has to outlive the session, be shared across sessions or users, or be queried independently of a turn belongs in an external store
|
|
72
|
+
`defineState` holds conversation-scoped working memory that lives and dies with the session, including counters, the current plan, and what the user has told you this conversation. It is the agent's short-term memory, persisted durably for the life of the session. Anything that has to outlive the session, be shared across sessions or users, or be queried independently of a turn belongs in an external store. Start with a packaged [memory integration](/integrations?filter=memory), a general [connection](../connections), or your own database.
|
|
73
73
|
|
|
74
74
|
## What to read next
|
|
75
75
|
|
|
@@ -12,9 +12,11 @@ Run `eve add` from an eve agent project. This installs the integration's depende
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
eve add extension/agent-browser
|
|
15
|
+
eve add connection/linear
|
|
16
|
+
eve add instrumentation/braintrust
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Extensions may create a mount under `agent/extensions/`. Connections write their initial definition under `agent/connections/` and install `@vercel/connect` when required. Instrumentation providers write `agent/instrumentation.ts`; because an agent has one instrumentation file, compose multiple exporters there by hand. Configure generated files and required environment variables before running your agent.
|
|
18
20
|
|
|
19
21
|
## Find an integration
|
|
20
22
|
|
|
@@ -3,7 +3,7 @@ title: "Multi-tenant memory"
|
|
|
3
3
|
description: "Compose dynamic instructions, authenticated session context, and ordinary tools into tenant-scoped long-term memory."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
You can add long-term memory with a packaged [memory integration](/integrations?filter=memory), or build tenant-aware memory from your own application store by composing three existing eve primitives:
|
|
7
7
|
|
|
8
8
|
1. route auth puts the tenant and user on `ctx.session.auth`;
|
|
9
9
|
2. dynamic instructions load that caller's memories before each turn;
|
package/docs/reference/cli.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "CLI"
|
|
3
|
-
description: "Reference for every eve CLI command: init, info, build, start, dev, logs, link, deploy, eval, channels, and extension."
|
|
3
|
+
description: "Reference for every eve CLI command: init, info, build, start, dev, logs, trace, link, deploy, eval, channels, and extension."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
The `eve` binary (`bin: eve`) runs from your app root, and every command first loads `.env`/`.env.local` from that root. Running `eve` with no command runs `eve dev`.
|
|
@@ -17,6 +17,8 @@ The `eve` binary (`bin: eve`) runs from your app root, and every command first l
|
|
|
17
17
|
| `eve dev <url>` | Connect the UI to an existing server URL (e.g. a remote deployment) instead of booting a local server |
|
|
18
18
|
| `eve logs [logid]` | Print an `eve dev` diagnostic log (the most recent when `logid` is omitted) |
|
|
19
19
|
| `eve logs ls` | List `eve dev` diagnostic logs, most recent first |
|
|
20
|
+
| `eve trace ls` | List locally captured agent traces, most recent first |
|
|
21
|
+
| `eve trace [trace]` | Show a local span tree (the most recent when omitted) |
|
|
20
22
|
| `eve link` | Link the directory to a Vercel project and pull AI Gateway credentials |
|
|
21
23
|
| `eve deploy` | Deploy the agent to Vercel production (links first if needed) |
|
|
22
24
|
| `eve eval` | Run evals against the local app or a remote target |
|
|
@@ -213,6 +215,17 @@ A log id is the file name without `.log` (for example `dev-2026-07-15T12-00-00.0
|
|
|
213
215
|
|
|
214
216
|
Each log has a same-named `.dump` sibling holding environment diagnostics and session stats as one JSON document. `eve logs --dump` (with or without a log id) prepends that document to the JSONL log body; the combined output is a valid JSON value stream (`eve logs --dump | jq -c .`), one self-contained report to attach to an issue. When a log has no dump, the flag is silently a no-op.
|
|
215
217
|
|
|
218
|
+
## `eve trace`
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
eve trace ls # list traces, most recent first
|
|
222
|
+
eve trace ls --json # emit machine-readable trace summaries
|
|
223
|
+
eve trace # show the most recent span tree
|
|
224
|
+
eve trace <trace> # show one span tree
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`eve trace ls` reads the immutable OTLP/JSON segments captured under `.eve/traces/v1`; `eve dev` does not need to be running. `eve trace` accepts a full trace id, an `agent.session.id`, or an unambiguous prefix of either. Malformed or incomplete segments are skipped without hiding valid spans from the same trace.
|
|
228
|
+
|
|
216
229
|
## `eve link`
|
|
217
230
|
|
|
218
231
|
```bash
|
package/docs/tools/overview.mdx
CHANGED
|
@@ -82,6 +82,35 @@ toModelOutput(output) {
|
|
|
82
82
|
|
|
83
83
|
Tool outputs must be JSON-serializable. Return plain objects, arrays, strings, numbers, booleans, or `null`; convert values like `Date`, `Map`, `Set`, `NaN`, and cyclic objects before returning them from `execute` or from a `{ type: "json" }` `toModelOutput`.
|
|
84
84
|
|
|
85
|
+
### Send images to the model with content parts
|
|
86
|
+
|
|
87
|
+
A tool that produces an image — a screenshot, a rendered chart — can hand the pixels to a vision-capable model by returning a `content` output from `toModelOutput`. Build outputs with the `toolOutput` helpers and parts with the `toolOutputPart` helpers, both from `eve/tools`:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { defineTool, toolOutput, toolOutputPart } from "eve/tools";
|
|
91
|
+
|
|
92
|
+
export default defineTool({
|
|
93
|
+
description: "Capture a screenshot of the current page",
|
|
94
|
+
inputSchema: z.object({ url: z.string() }),
|
|
95
|
+
async execute(input) {
|
|
96
|
+
const png = await captureScreenshot(input.url);
|
|
97
|
+
return { path: png.path, screenshotBase64: png.base64 };
|
|
98
|
+
},
|
|
99
|
+
toModelOutput(output) {
|
|
100
|
+
return toolOutput.content([
|
|
101
|
+
toolOutputPart.text(`Screenshot of ${output.path}:`),
|
|
102
|
+
toolOutputPart.file(output.screenshotBase64, { mediaType: "image/png" }),
|
|
103
|
+
]);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The `toolOutput.text` and `toolOutput.json` builders construct the other two output shapes; hand-written literals remain valid everywhere.
|
|
109
|
+
|
|
110
|
+
File payloads must be base64 strings — raw bytes (`Uint8Array`, `Buffer`) are rejected because they do not survive eve's durable JSON boundary. Keep payloads small: a content-part image is persisted in session history and re-sent on every subsequent model call, and eve warns above 3 MiB. Sending image parts to a model without vision support fails with that provider's error, the same as image parts in user messages.
|
|
111
|
+
|
|
112
|
+
When older turns are compacted, file payloads are dropped from the summary and replaced with a text stub naming the file and media type — the model cannot re-see a compacted image. Content parts are for "look at this now"; if the agent may need an artifact again later, write it to the [sandbox](/docs/sandbox) and return its path.
|
|
113
|
+
|
|
85
114
|
Do not return secrets, credentials, unnecessary personal data, or unbounded sensitive content from tools. Filter, minimize, and redact tool outputs before returning them.
|
|
86
115
|
|
|
87
116
|
## What to read next
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -279,7 +279,8 @@
|
|
|
279
279
|
"access": "public"
|
|
280
280
|
},
|
|
281
281
|
"dependencies": {
|
|
282
|
-
"nitro": "3.0.260610-beta"
|
|
282
|
+
"nitro": "3.0.260610-beta",
|
|
283
|
+
"undici": "7.28.0"
|
|
283
284
|
},
|
|
284
285
|
"devDependencies": {
|
|
285
286
|
"@ai-sdk/anthropic": "^4.0.18",
|
|
@@ -294,6 +295,8 @@
|
|
|
294
295
|
"@chat-adapter/twilio": "4.34.0",
|
|
295
296
|
"@clack/core": "1.3.1",
|
|
296
297
|
"@nuxt/kit": "^4.0.0",
|
|
298
|
+
"@opentelemetry/otlp-transformer": "0.214.0",
|
|
299
|
+
"@opentelemetry/sdk-trace-base": "^2.6.1",
|
|
297
300
|
"@standard-schema/spec": "1.1.0",
|
|
298
301
|
"@sveltejs/kit": "^2.0.0",
|
|
299
302
|
"@types/json-schema": "7.0.15",
|
|
@@ -301,6 +304,7 @@
|
|
|
301
304
|
"@types/react-test-renderer": "19.1.0",
|
|
302
305
|
"@vercel/detect-agent": "1.2.3",
|
|
303
306
|
"@vercel/oidc": "3.8.0",
|
|
307
|
+
"@vercel/otel": "2.1.3",
|
|
304
308
|
"@vercel/sandbox": "2.8.0",
|
|
305
309
|
"@vercel/sdk": "1.28.8",
|
|
306
310
|
"@workflow/core": "5.0.0-beta.36",
|
|
@@ -310,7 +314,7 @@
|
|
|
310
314
|
"@workflow/world": "5.0.0-beta.22",
|
|
311
315
|
"@workflow/world-local": "5.0.0-beta.30",
|
|
312
316
|
"@workflow/world-vercel": "5.0.0-beta.32",
|
|
313
|
-
"ai": "^7.0.
|
|
317
|
+
"ai": "^7.0.38",
|
|
314
318
|
"autoevals": "0.0.132",
|
|
315
319
|
"chat": "4.34.0",
|
|
316
320
|
"chokidar": "5.0.0",
|
|
@@ -342,7 +346,7 @@
|
|
|
342
346
|
},
|
|
343
347
|
"peerDependencies": {
|
|
344
348
|
"@opentelemetry/api": "^1.0.0",
|
|
345
|
-
"ai": "^7.0.
|
|
349
|
+
"ai": "^7.0.38",
|
|
346
350
|
"braintrust": "^3.0.0",
|
|
347
351
|
"just-bash": "^3.0.0",
|
|
348
352
|
"microsandbox": "^0.5.0"
|