eve 0.79.2 → 0.80.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/src/compiled/.vendor-stamp.json +6 -6
  3. package/dist/src/compiled/@chat-adapter/slack/api.d.ts +6 -0
  4. package/dist/src/compiled/@chat-adapter/slack/api.js +1 -1
  5. package/dist/src/compiled/@chat-adapter/slack/blocks.js +1 -1
  6. package/dist/src/compiled/@chat-adapter/slack/format.js +1 -1
  7. package/dist/src/compiled/@chat-adapter/slack/index.d.ts +14 -8
  8. package/dist/src/compiled/@chat-adapter/slack/index.js +33 -32
  9. package/dist/src/compiled/@chat-adapter/twilio/index.d.ts +37 -1
  10. package/dist/src/compiled/@chat-adapter/twilio/index.js +2 -2
  11. package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.js +1 -1
  12. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
  13. package/dist/src/compiled/@vercel/connect/index.js +5 -5
  14. package/dist/src/compiled/@vercel/connect/token.d.ts +11 -1
  15. package/dist/src/compiled/_chunks/node/chunk-NBSLXVG3-Bt7pDfyn.js +12 -0
  16. package/dist/src/compiled/_chunks/node/dist-BKsV21Vu.js +6 -0
  17. package/dist/src/compiled/_chunks/node/dist-CO_n_hUa.js +98 -0
  18. package/dist/src/compiled/chat/index.js +1 -1
  19. package/dist/src/compiler/extension-compatibility.d.ts +6 -6
  20. package/dist/src/compiler/extension-compatibility.js +1 -1
  21. package/dist/src/compiler/manifest.d.ts +8 -4
  22. package/dist/src/compiler/manifest.js +1 -1
  23. package/dist/src/compiler/normalize-connection.js +1 -1
  24. package/dist/src/compiler/normalize-manifest.js +1 -1
  25. package/dist/src/context/schedule-collection-tools.js +1 -1
  26. package/dist/src/execution/catalog/connection-auth.d.ts +4 -2
  27. package/dist/src/execution/catalog/connection-auth.js +1 -1
  28. package/dist/src/execution/catalog/connection-entry.js +1 -1
  29. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  30. package/dist/src/execution/session/entry.js +1 -1
  31. package/dist/src/execution/session-event-stream.js +1 -1
  32. package/dist/src/execution/stable-workflow-names.d.ts +2 -0
  33. package/dist/src/execution/stable-workflow-names.js +1 -1
  34. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  35. package/dist/src/execution/web-fetch/execute.js +1 -1
  36. package/dist/src/execution/workflow-runtime.d.ts +6 -0
  37. package/dist/src/execution/workflow-runtime.js +1 -1
  38. package/dist/src/extensions/git/extension/extension.d.ts +3 -1
  39. package/dist/src/extensions/git/extension/extension.js +1 -1
  40. package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
  41. package/dist/src/extensions/git/extension/lib/github-shell.d.ts +14 -0
  42. package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
  43. package/dist/src/harness/model-call/call.js +1 -1
  44. package/dist/src/harness/model-call/errors.d.ts +2 -2
  45. package/dist/src/harness/model-call/recovery.d.ts +2 -3
  46. package/dist/src/instrumentation/session-init.d.ts +2 -1
  47. package/dist/src/instrumentation/session-init.js +1 -1
  48. package/dist/src/internal/application/stamped-package-version.js +1 -1
  49. package/dist/src/internal/authored-definition/connection.js +1 -1
  50. package/dist/src/internal/authored-definition/schedule-collection.js +1 -1
  51. package/dist/src/internal/nitro/host/application-route-registry.d.ts +7 -2
  52. package/dist/src/internal/nitro/host/application-route-registry.js +1 -1
  53. package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
  54. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +3 -1
  55. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  56. package/dist/src/internal/nitro/routes/connection-events.d.ts +5 -0
  57. package/dist/src/internal/nitro/routes/connection-events.js +1 -0
  58. package/dist/src/internal/workflow-bundle/builder.js +1 -1
  59. package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
  60. package/dist/src/public/channels/slack/blocks.js +2 -2
  61. package/dist/src/public/connections/index.d.ts +1 -0
  62. package/dist/src/public/definitions/connections/events.d.ts +43 -0
  63. package/dist/src/public/definitions/connections/events.js +1 -0
  64. package/dist/src/public/definitions/connections/mcp.d.ts +3 -0
  65. package/dist/src/public/schedules/subscription.d.ts +4 -3
  66. package/dist/src/runtime/connections/events/actions.d.ts +17 -0
  67. package/dist/src/runtime/connections/events/actions.js +1 -0
  68. package/dist/src/runtime/connections/events/delivery.d.ts +10 -0
  69. package/dist/src/runtime/connections/events/delivery.js +1 -0
  70. package/dist/src/runtime/connections/events/dispatch-step.d.ts +20 -0
  71. package/dist/src/runtime/connections/events/dispatch-step.js +1 -0
  72. package/dist/src/runtime/connections/events/lifecycle-step.d.ts +42 -0
  73. package/dist/src/runtime/connections/events/lifecycle-step.js +1 -0
  74. package/dist/src/runtime/connections/events/owner.d.ts +38 -0
  75. package/dist/src/runtime/connections/events/owner.js +1 -0
  76. package/dist/src/runtime/connections/events/path.d.ts +4 -0
  77. package/dist/src/runtime/connections/events/path.js +1 -0
  78. package/dist/src/runtime/connections/events/state.d.ts +37 -0
  79. package/dist/src/runtime/connections/events/state.js +1 -0
  80. package/dist/src/runtime/connections/events/workflow.d.ts +28 -0
  81. package/dist/src/runtime/connections/events/workflow.js +1 -0
  82. package/dist/src/runtime/connections/mcp-client.d.ts +4 -2
  83. package/dist/src/runtime/connections/mcp-client.js +1 -1
  84. package/dist/src/runtime/connections/openapi-client.js +1 -1
  85. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  86. package/dist/src/runtime/resolve-connection.js +1 -1
  87. package/dist/src/runtime/schedules/collection-client.d.ts +0 -2
  88. package/dist/src/runtime/schedules/collection-client.js +1 -1
  89. package/dist/src/runtime/types.d.ts +11 -0
  90. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  91. package/dist/src/setup/scaffold/create/project.js +2 -2
  92. package/dist/src/setup/scaffold/update/channels.js +1 -1
  93. package/dist/src/setup/scaffold/update/connections.js +2 -2
  94. package/dist/src/setup/scaffold/version-tokens.d.ts +1 -1
  95. package/dist/src/setup/scaffold/version-tokens.js +1 -1
  96. package/dist/src/shared/agent-definition.d.ts +12 -4
  97. package/dist/src/shared/connection-events.d.ts +84 -0
  98. package/dist/src/shared/connection-events.js +1 -0
  99. package/dist/src/shared/connection-types.d.ts +10 -0
  100. package/dist/src/shared/validate-authorization.js +1 -1
  101. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  102. package/dist/src/tools/provided/no-reply.d.ts +5 -0
  103. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  104. package/dist/src/tracing/eve/connection-events.d.ts +25 -0
  105. package/dist/src/tracing/eve/connection-events.js +1 -0
  106. package/dist/src/tracing/eve/install-instrumentation-runtime.js +1 -1
  107. package/dist/src/tracing/eve/mcp.d.ts +1 -0
  108. package/dist/src/tracing/eve/mcp.js +1 -1
  109. package/dist/src/tracing/eve/otel-declaration.d.ts +5 -0
  110. package/docs/agent-config.md +38 -13
  111. package/docs/code-extension.mdx +28 -0
  112. package/docs/concepts/built-in-tools.md +2 -0
  113. package/docs/connections/mcp.mdx +105 -0
  114. package/docs/guides/instrumentation/otel.mdx +10 -0
  115. package/docs/sandbox/vercel.mdx +46 -0
  116. package/package.json +7 -7
  117. package/dist/src/compiled/_chunks/node/chunk-6QHBXN7B-gl4n6nmi.js +0 -12
  118. package/dist/src/compiled/_chunks/node/dist-DYDVZ-FS.js +0 -98
  119. package/dist/src/compiled/_chunks/node/dist-iEFkK9qw.js +0 -6
@@ -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{readFile}from"node:fs/promises";import{join}from"node:path";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(e){let t=e.packageManager??`pnpm`,n=join(e.projectRoot,`package.json`);if(!await pathExists(n))throw Error(`Cannot add an eve agent to "${e.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Cannot add an eve agent because "${n}" is not valid JSON. No files were changed. Fix the file, then retry eve init. ${t}`)}let i=agentTemplateFiles(e.model,e.reasoning),a=[];for(let t of Object.keys(i))await pathExists(join(e.projectRoot,t))&&a.push(t);if(a.length===0&&await pathExists(join(e.projectRoot,`agent`))&&a.push(`agent/`),a.length>0)throw Error(`Cannot add an eve agent to "${e.projectRoot}" because it already has: ${a.join(`, `)}.`);let o=resolveEvePackageContract(e.evePackage),s=resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`^7.0.137`),c=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.2.0`),l=resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.5.4`),u=[];for(let[t,n]of Object.entries(i)){let r=join(e.projectRoot,t);await writeTextFile(r,n),u.push(r)}let d={"@vercel/connect":c,ai:s,eve:formatEveDependencySpecifier(o.version),zod:l},f={};for(let[e,t]of Object.entries(d))hasDeclaredDependency(r,e)||(f[e]=t);let p={};Object.keys(f).length>0&&(p.dependencies=f),isPackageManagerWorkspaceMember(t,e.projectRoot)||(p.nodeEngineRequirement=o.nodeEngine);let m=await patchPackageJson(n,p),h=await patchWorkspaceRootPackageJson(t,e.projectRoot,{nodeEngineRequirement:o.nodeEngine}),g=h.nodeEngineOverride??m.nodeEngineOverride,_=await applyPackageManagerWorkspaceConfiguration({packageManager:t,projectRoot:e.projectRoot});return{filesWritten:u,dependenciesAdded:Object.keys(f).sort(),nodeEngineOverride:g,configurationFilesChanged:[...m.changed?[n]:[],...h.changed&&h.path!==void 0?[h.path]:[],..._.filesWritten]}}export{addAgentToProject};
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{readFile}from"node:fs/promises";import{join}from"node:path";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(e){let t=e.packageManager??`pnpm`,n=join(e.projectRoot,`package.json`);if(!await pathExists(n))throw Error(`Cannot add an eve agent to "${e.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Cannot add an eve agent because "${n}" is not valid JSON. No files were changed. Fix the file, then retry eve init. ${t}`)}let i=agentTemplateFiles(e.model,e.reasoning),a=[];for(let t of Object.keys(i))await pathExists(join(e.projectRoot,t))&&a.push(t);if(a.length===0&&await pathExists(join(e.projectRoot,`agent`))&&a.push(`agent/`),a.length>0)throw Error(`Cannot add an eve agent to "${e.projectRoot}" because it already has: ${a.join(`, `)}.`);let o=resolveEvePackageContract(e.evePackage),s=resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`^7.0.137`),c=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.5.2`),l=resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.5.4`),u=[];for(let[t,n]of Object.entries(i)){let r=join(e.projectRoot,t);await writeTextFile(r,n),u.push(r)}let d={"@vercel/connect":c,ai:s,eve:formatEveDependencySpecifier(o.version),zod:l},f={};for(let[e,t]of Object.entries(d))hasDeclaredDependency(r,e)||(f[e]=t);let p={};Object.keys(f).length>0&&(p.dependencies=f),isPackageManagerWorkspaceMember(t,e.projectRoot)||(p.nodeEngineRequirement=o.nodeEngine);let m=await patchPackageJson(n,p),h=await patchWorkspaceRootPackageJson(t,e.projectRoot,{nodeEngineRequirement:o.nodeEngine}),g=h.nodeEngineOverride??m.nodeEngineOverride,_=await applyPackageManagerWorkspaceConfiguration({packageManager:t,projectRoot:e.projectRoot});return{filesWritten:u,dependenciesAdded:Object.keys(f).sort(),nodeEngineOverride:g,configurationFilesChanged:[...m.changed?[n]:[],...h.changed&&h.path!==void 0?[h.path]:[],..._.filesWritten]}}export{addAgentToProject};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.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{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{AGENT_INSTRUCTIONS_TEMPLATE}from"./instructions-template.js";import{SCAFFOLDED_AGENT_PATHS}from"./agent-paths.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.137`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.79.2`,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{[SCAFFOLDED_AGENT_PATHS.config]:renderAgentTemplate(e,t),[SCAFFOLDED_AGENT_PATHS.channel]:WEB_CHANNEL_TEMPLATES.default,[SCAFFOLDED_AGENT_PATHS.instructions]:AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):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";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.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{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{AGENT_INSTRUCTIONS_TEMPLATE}from"./instructions-template.js";import{SCAFFOLDED_AGENT_PATHS}from"./agent-paths.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.137`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.80.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{[SCAFFOLDED_AGENT_PATHS.config]:renderAgentTemplate(e,t),[SCAFFOLDED_AGENT_PATHS.channel]:WEB_CHANNEL_TEMPLATES.default,[SCAFFOLDED_AGENT_PATHS.instructions]:AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):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__",
@@ -114,4 +114,4 @@ __EVE_INIT_REASONING__ modelOptions: {
114
114
  },
115
115
  },
116
116
  });
117
- `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(e.includeRootOnlyPackageJsonFields)}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let n=await readdir(e),r=blockingCreateInPlaceEntries(n);if(r.length>0&&!t){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(e){let t=resolve(e.targetDirectory??process.cwd(),e.projectName),n=e.projectName===`.`,r=e.overwriteExisting??!1,i=e.byokProvider??!1,a=e.packageManager??`pnpm`,o=resolveEvePackageContract(e.evePackage),s=pinnedNodeEngineMajor(o.nodeEngine),c=resolve(e.workspaceProbeDirectory??t),l=isPackageManagerWorkspaceMember(a,c);if(n)await assertCanCreateInPlace(t,r);else if(await pathExists(t))throw Error(`Cannot create project because "${t}" already exists.`);let u={appName:basename(t),model:e.model,reasoning:e.reasoning,eveVersion:o.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`^7.0.137`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.2.0`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.5.4`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,e.typescriptPackageVersion??`7.0.2`),nodeTypesVersion:s,nodeEngine:s};await mkdir(t,{recursive:!0});for(let[a,o]of Object.entries(templateFiles({byokProvider:i,includeRootOnlyPackageJsonFields:!l}))){let i=`${t}/${a}`,s=await pathExists(i);await writeTextFile(i,renderTemplate(o,u),{force:n&&r}),s&&await e.onOverwriteFile?.(i)}return await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:t,workspaceProbeRoot:c,onWorkspaceRootMutation:e.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(a,c,{nodeEngineRequirement:o.nodeEngine,onWorkspaceRootMutation:e.onWorkspaceRootMutation}),t}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
117
+ `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(e.includeRootOnlyPackageJsonFields)}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let n=await readdir(e),r=blockingCreateInPlaceEntries(n);if(r.length>0&&!t){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(e){let t=resolve(e.targetDirectory??process.cwd(),e.projectName),n=e.projectName===`.`,r=e.overwriteExisting??!1,i=e.byokProvider??!1,a=e.packageManager??`pnpm`,o=resolveEvePackageContract(e.evePackage),s=pinnedNodeEngineMajor(o.nodeEngine),c=resolve(e.workspaceProbeDirectory??t),l=isPackageManagerWorkspaceMember(a,c);if(n)await assertCanCreateInPlace(t,r);else if(await pathExists(t))throw Error(`Cannot create project because "${t}" already exists.`);let u={appName:basename(t),model:e.model,reasoning:e.reasoning,eveVersion:o.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`^7.0.137`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.5.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.5.4`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,e.typescriptPackageVersion??`7.0.2`),nodeTypesVersion:s,nodeEngine:s};await mkdir(t,{recursive:!0});for(let[a,o]of Object.entries(templateFiles({byokProvider:i,includeRootOnlyPackageJsonFields:!l}))){let i=`${t}/${a}`,s=await pathExists(i);await writeTextFile(i,renderTemplate(o,u),{force:n&&r}),s&&await e.onOverwriteFile?.(i)}return await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:t,workspaceProbeRoot:c,onWorkspaceRootMutation:e.onWorkspaceRootMutation}),await patchWorkspaceRootPackageJson(a,c,{nodeEngineRequirement:o.nodeEngine,onWorkspaceRootMutation:e.onWorkspaceRootMutation}),t}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,ROOT_ONLY_PACKAGE_JSON_TEMPLATE_SUFFIX,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
@@ -4,7 +4,7 @@ import { slackChannel } from "eve/channels/slack";
4
4
  export default slackChannel({
5
5
  credentials: connectSlackCredentials(${JSON.stringify(e)}),
6
6
  });
7
- `}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=join(e.projectRoot,`app/page.tsx`),r=await pathExists(n);if(!e.force&&!e.skipDependencyMutation&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let i=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),a=e.packageManager??`pnpm`,o=resolve(e.workspaceProbeDirectory??e.projectRoot),s=await patchWebPackageJson(e.projectRoot,a,o,i,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),c=[],l=[],u=[],d=[],f=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?c.push(t):d.push(t)}let p=await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:e.projectRoot,workspaceProbeRoot:o,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(c.push(...p.filesWritten),d.push(...p.filesSkipped),!e.skipDependencyMutation){let t=WEB_CHANNEL_TEMPLATES[e.webAuthentication??`default`],n={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{},[WEB_CHANNEL_PATH]:t};for(let[t,r]of Object.entries(n)){let n=join(e.projectRoot,t);if(t===WEB_CHANNEL_PATH&&!e.force&&await pathExists(n)){d.push(n);continue}let i=await pathExists(n);await writeTextFile(n,renderWebAppTemplate(r,f),{force:!0}),c.push(n),i&&l.push(n)}}u.push(...await findCompetingNextConfigFiles(e.projectRoot));let m=[...new Set(c)],h=[...new Set(d)].filter(e=>!m.includes(e)),g={kind:`web`,action:r?`overwritten`:`created`,filesWritten:m,filesSkipped:h,packageJsonUpdated:s.mutations};return l.length>0&&(g.filesOverwritten=l),u.length>0&&(g.competingNextConfigFiles=u),s.nodeEngineOverride!==void 0&&(g.nodeEngineOverride=s.nodeEngineOverride),g}async function ensureSlackChannel(e){let t=join(e.projectRoot,`agent/channels/slack.ts`),n=await pathExists(t);if(!e.force&&n)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=e.slackCredentials??`vercel-connect`,i=e.slackConnectorSlug??await deriveSlackConnectorSlug(e.projectRoot),a,o=[],s=[t],c=[],l;if(r===`vercel-connect`){if(!e.skipDependencyMutation){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.2.0`);o=await ensurePackageDependency(join(e.projectRoot,`package.json`),`@vercel/connect`,t)}a=buildSlackConnectTemplate(e.slackConnectorUid??`slack/${i}`)}else{a=`import { slackChannel } from "eve/channels/slack";
7
+ `}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=join(e.projectRoot,`app/page.tsx`),r=await pathExists(n);if(!e.force&&!e.skipDependencyMutation&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let i=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),a=e.packageManager??`pnpm`,o=resolve(e.workspaceProbeDirectory??e.projectRoot),s=await patchWebPackageJson(e.projectRoot,a,o,i,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),c=[],l=[],u=[],d=[],f=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?c.push(t):d.push(t)}let p=await applyPackageManagerWorkspaceConfiguration({packageManager:a,projectRoot:e.projectRoot,workspaceProbeRoot:o,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(c.push(...p.filesWritten),d.push(...p.filesSkipped),!e.skipDependencyMutation){let t=WEB_CHANNEL_TEMPLATES[e.webAuthentication??`default`],n={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{},[WEB_CHANNEL_PATH]:t};for(let[t,r]of Object.entries(n)){let n=join(e.projectRoot,t);if(t===WEB_CHANNEL_PATH&&!e.force&&await pathExists(n)){d.push(n);continue}let i=await pathExists(n);await writeTextFile(n,renderWebAppTemplate(r,f),{force:!0}),c.push(n),i&&l.push(n)}}u.push(...await findCompetingNextConfigFiles(e.projectRoot));let m=[...new Set(c)],h=[...new Set(d)].filter(e=>!m.includes(e)),g={kind:`web`,action:r?`overwritten`:`created`,filesWritten:m,filesSkipped:h,packageJsonUpdated:s.mutations};return l.length>0&&(g.filesOverwritten=l),u.length>0&&(g.competingNextConfigFiles=u),s.nodeEngineOverride!==void 0&&(g.nodeEngineOverride=s.nodeEngineOverride),g}async function ensureSlackChannel(e){let t=join(e.projectRoot,`agent/channels/slack.ts`),n=await pathExists(t);if(!e.force&&n)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=e.slackCredentials??`vercel-connect`,i=e.slackConnectorSlug??await deriveSlackConnectorSlug(e.projectRoot),a,o=[],s=[t],c=[],l;if(r===`vercel-connect`){if(!e.skipDependencyMutation){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.5.2`);o=await ensurePackageDependency(join(e.projectRoot,`package.json`),`@vercel/connect`,t)}a=buildSlackConnectTemplate(e.slackConnectorUid??`slack/${i}`)}else{a=`import { slackChannel } from "eve/channels/slack";
8
8
 
9
9
  export default slackChannel();
10
10
  `;let t=join(e.environmentRoot??e.projectRoot,`.env.example`);l={path:t,...await pathExists(t)?{content:await readFile(t,`utf8`)}:{}},(await appendEnv(t,SLACK_ENV_EXAMPLE_VALUES)).written.length>0?s.push(t):c.push(t)}try{await writeTextFile(t,a,{force:e.force})}catch(e){throw l!==void 0&&(l.content===void 0?await unlink(l.path):await writeFile(l.path,l.content,`utf8`)),e}let u={kind:`slack`,action:n?`overwritten`:`created`,filesWritten:s,filesSkipped:c,packageJsonUpdated:o,slackConnectorSlug:i};return n&&(u.filesOverwritten=[t]),u}async function listAuthoredChannels(e){let t=join(e,`channels`),n;try{n=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let r=[];for(let e of n){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&r.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&r.push(e.name)}catch{}}return r.sort()}export{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset};
@@ -15,7 +15,7 @@ export default defineOpenAPIConnection({
15
15
  spec: "${e.spec}",
16
16
  ${i} description: "${t}",
17
17
  ${authBlock(n)}});
18
- `}function renderTemplate(e,t,n,r){return e===`mcp`?renderMcpTemplate(t,n,r):renderOpenApiTemplate(t,n,r)}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function ensureConnectDependency(e,t){if(!await pathExists(e))return[];let n=JSON.parse(await readFile(e,`utf8`));return(isJsonObject(n)&&isJsonObject(n.dependencies)?n.dependencies[CONNECT_PACKAGE_NAME]:void 0)===t?[]:(await patchPackageJson(e,{dependencies:{[CONNECT_PACKAGE_NAME]:t}}),[{path:e,dependencies:[CONNECT_PACKAGE_NAME],devDependencies:[],scripts:[]}])}async function ensureConnectionDependencies(e){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.2.0`);return ensureConnectDependency(join(e.projectRoot,`package.json`),t)}function envKeyPresent(e,t){return RegExp(`^\\s*(?:export\\s+)?${t}\\s*=`,`m`).test(e)}async function seedEnvPlaceholders(e,t){if(t.length===0)return[];let n=``;await pathExists(e)&&(n=await readFile(e,`utf8`));let r=t.filter(e=>!envKeyPresent(n,e));if(r.length===0)return[];let i=`${n.length>0&&!n.endsWith(`
18
+ `}function renderTemplate(e,t,n,r){return e===`mcp`?renderMcpTemplate(t,n,r):renderOpenApiTemplate(t,n,r)}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function ensureConnectDependency(e,t){if(!await pathExists(e))return[];let n=JSON.parse(await readFile(e,`utf8`));return(isJsonObject(n)&&isJsonObject(n.dependencies)?n.dependencies[CONNECT_PACKAGE_NAME]:void 0)===t?[]:(await patchPackageJson(e,{dependencies:{[CONNECT_PACKAGE_NAME]:t}}),[{path:e,dependencies:[CONNECT_PACKAGE_NAME],devDependencies:[],scripts:[]}])}async function ensureConnectionDependencies(e){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.5.2`);return ensureConnectDependency(join(e.projectRoot,`package.json`),t)}function envKeyPresent(e,t){return RegExp(`^\\s*(?:export\\s+)?${t}\\s*=`,`m`).test(e)}async function seedEnvPlaceholders(e,t){if(t.length===0)return[];let n=``;await pathExists(e)&&(n=await readFile(e,`utf8`));let r=t.filter(e=>!envKeyPresent(n,e));if(r.length===0)return[];let i=`${n.length>0&&!n.endsWith(`
19
19
  `)?`
20
20
  `:``}${r.map(e=>`${e}=`).join(`
21
- `)}\n`;return await writeFile(e,n+i,`utf8`),r}async function ensureConnection(e){let t=e.slug??e.entry.slug,n=resolveAuth(e.entry),r=endpointForProtocol(e.entry,e.protocol);if(r===null)throw Error(`Connection "${t}" is missing a ${e.protocol===`mcp`?`mcp.url`:`openapi.spec`} endpoint for protocol "${e.protocol}".`);let i=join(e.projectRoot,USER_AUTHORED_CONNECTION_DIR,`${t}.ts`),a=envKeysForAuth(n),o=await pathExists(i);if(!e.force&&o)return{slug:t,protocol:e.protocol,action:`skipped`,filePath:i,filesWritten:[],filesSkipped:[i],packageJsonUpdated:[],envKeysAdded:[],envKeysRequired:a};let s=[];if(n.kind===`connect`){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.2.0`);s.push(...await ensureConnectDependency(join(e.projectRoot,`package.json`),t))}await writeTextFile(i,renderTemplate(e.protocol,r,e.entry.description,n),{force:!0});let c=await seedEnvPlaceholders(join(e.projectRoot,`.env.local`),a),l={slug:t,protocol:e.protocol,action:o?`overwritten`:`created`,filePath:i,filesWritten:[i],filesSkipped:[],packageJsonUpdated:s,envKeysAdded:c,envKeysRequired:a};return o&&(l.filesOverwritten=[i]),l}async function listAuthoredConnections(e){let t=join(e,USER_AUTHORED_CONNECTION_DIR),n;try{n=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let r=[];for(let e of n){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&r.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&r.push(e.name)}catch{}}return r.sort()}export{ensureConnection,ensureConnectionDependencies,listAuthoredConnections};
21
+ `)}\n`;return await writeFile(e,n+i,`utf8`),r}async function ensureConnection(e){let t=e.slug??e.entry.slug,n=resolveAuth(e.entry),r=endpointForProtocol(e.entry,e.protocol);if(r===null)throw Error(`Connection "${t}" is missing a ${e.protocol===`mcp`?`mcp.url`:`openapi.spec`} endpoint for protocol "${e.protocol}".`);let i=join(e.projectRoot,USER_AUTHORED_CONNECTION_DIR,`${t}.ts`),a=envKeysForAuth(n),o=await pathExists(i);if(!e.force&&o)return{slug:t,protocol:e.protocol,action:`skipped`,filePath:i,filesWritten:[],filesSkipped:[i],packageJsonUpdated:[],envKeysAdded:[],envKeysRequired:a};let s=[];if(n.kind===`connect`){let t=resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`2.5.2`);s.push(...await ensureConnectDependency(join(e.projectRoot,`package.json`),t))}await writeTextFile(i,renderTemplate(e.protocol,r,e.entry.description,n),{force:!0});let c=await seedEnvPlaceholders(join(e.projectRoot,`.env.local`),a),l={slug:t,protocol:e.protocol,action:o?`overwritten`:`created`,filePath:i,filesWritten:[i],filesSkipped:[],packageJsonUpdated:s,envKeysAdded:c,envKeysRequired:a};return o&&(l.filesOverwritten=[i]),l}async function listAuthoredConnections(e){let t=join(e,USER_AUTHORED_CONNECTION_DIR),n;try{n=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let r=[];for(let e of n){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&r.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&r.push(e.name)}catch{}}return r.sort()}export{ensureConnection,ensureConnectionDependencies,listAuthoredConnections};
@@ -1,4 +1,4 @@
1
- export declare const DEFAULT_CONNECT_PACKAGE_VERSION = "2.2.0";
1
+ export declare const DEFAULT_CONNECT_PACKAGE_VERSION = "2.5.2";
2
2
  export declare const DEFAULT_MICROSANDBOX_PACKAGE_VERSION = "0.5.5";
3
3
  /**
4
4
  * Returns a scaffold version value, resolving a build-stamp token at the point
@@ -1 +1 @@
1
- import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),DEFAULT_CONNECT_PACKAGE_VERSION=`2.2.0`,DEFAULT_MICROSANDBOX_PACKAGE_VERSION=`0.5.5`,TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[versionToken(`EVE_PACKAGE_DEPENDENCY`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let e=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let t=join(e,`package.json`);if(existsSync(t)&&JSON.parse(readFileSync(t,`utf8`)).name===`eve`)return e;let n=dirname(e);if(n===e)return;e=n}}function findWorkspaceManifest(e){let t=e;for(;;){let e=join(t,`pnpm-workspace.yaml`);if(existsSync(e))return e;let n=dirname(t);if(n===t)return;t=n}}function readCatalogVersion(e,t){let n=readFileSync(e,`utf8`).split(/\r?\n/),r=!1;for(let e of n){if(/^catalog:\s*$/.test(e)){r=!0;continue}if(!r)continue;if(/^\S/.test(e))break;let n=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(n&&(n[1]??n[2])===t)return n[3]}}function resolveTokenFromDevTree(e){let t=TOKEN_SOURCES[e];if(t!==void 0)try{let e=findEvePackageRoot();if(e===void 0||!existsSync(join(e,`scripts/stamp-version-tokens.mjs`)))return;if(t.kind===`eve-version`){let t=JSON.parse(readFileSync(join(e,`package.json`),`utf8`));return typeof t.version==`string`?t.version:void 0}if(t.kind===`eve-node-engine`){let t=JSON.parse(readFileSync(join(e,`package.json`),`utf8`)).engines?.node;return typeof t==`string`?t:void 0}let n=findWorkspaceManifest(e);return n===void 0?void 0:readCatalogVersion(n,t.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_MICROSANDBOX_PACKAGE_VERSION,resolveVersionToken};
1
+ import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),DEFAULT_CONNECT_PACKAGE_VERSION=`2.5.2`,DEFAULT_MICROSANDBOX_PACKAGE_VERSION=`0.5.5`,TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[versionToken(`EVE_PACKAGE_DEPENDENCY`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let e=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let t=join(e,`package.json`);if(existsSync(t)&&JSON.parse(readFileSync(t,`utf8`)).name===`eve`)return e;let n=dirname(e);if(n===e)return;e=n}}function findWorkspaceManifest(e){let t=e;for(;;){let e=join(t,`pnpm-workspace.yaml`);if(existsSync(e))return e;let n=dirname(t);if(n===t)return;t=n}}function readCatalogVersion(e,t){let n=readFileSync(e,`utf8`).split(/\r?\n/),r=!1;for(let e of n){if(/^catalog:\s*$/.test(e)){r=!0;continue}if(!r)continue;if(/^\S/.test(e))break;let n=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(n&&(n[1]??n[2])===t)return n[3]}}function resolveTokenFromDevTree(e){let t=TOKEN_SOURCES[e];if(t!==void 0)try{let e=findEvePackageRoot();if(e===void 0||!existsSync(join(e,`scripts/stamp-version-tokens.mjs`)))return;if(t.kind===`eve-version`){let t=JSON.parse(readFileSync(join(e,`package.json`),`utf8`));return typeof t.version==`string`?t.version:void 0}if(t.kind===`eve-node-engine`){let t=JSON.parse(readFileSync(join(e,`package.json`),`utf8`)).engines?.node;return typeof t==`string`?t:void 0}let n=findWorkspaceManifest(e);return n===void 0?void 0:readCatalogVersion(n,t.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_MICROSANDBOX_PACKAGE_VERSION,resolveVersionToken};
@@ -267,20 +267,28 @@ export interface AgentWorkflowDefinition {
267
267
  * Applied to every run that owns the session, including successors created
268
268
  * by deployment handoff.
269
269
  *
270
- * - `"default"`: same as omission. The Workflow SDK World decides.
270
+ * When omitted, eve uses the session's resolved OTel trace decision: full
271
+ * input and output capture keeps the World's default; dropped traces or
272
+ * either excluded content direction request `0`. Destination export filters
273
+ * and lifecycle-provider policies do not affect this choice.
274
+ *
275
+ * An explicit value overrides this automatic choice:
276
+ * - `"default"`: the Workflow SDK World decides, regardless of tracing.
271
277
  * On Vercel this follows your team's plan.
272
278
  * - `0`: the world deletes run payloads and stream chunks as soon as the run
273
279
  * completes or fails. Metadata such as run IDs, status, and timestamps may
274
280
  * persist up to the default period.
275
281
  *
276
- * The World you are using with the Workflow SDK might not support every
277
- * option. A World that does not recognize the value keeps the data.
282
+ * The World enforces deletion. Worlds older than spec version 4 reject `0`;
283
+ * spec version 4 Worlds without retention support keep the data. Run, step,
284
+ * and event metadata and attributes remain for the default period. Exported
285
+ * traces are not deleted.
278
286
  *
279
287
  * Note that with retention set to `0`, data deletion can race reads of a finished
280
288
  * run, so results and transcripts of completed sessions generally become
281
289
  * unreadable. Persist anything you need to keep from inside a tool.
282
290
  *
283
- * @default "default"
291
+ * @default Derived from the session's resolved trace policy.
284
292
  */
285
293
  readonly retention?: AgentWorkflowRetentionDefinition;
286
294
  /**
@@ -0,0 +1,84 @@
1
+ import type { ConnectionPrincipal } from "#shared/connection-types.js";
2
+ import type { Experimental_ConnectionEvent } from "#public/definitions/connections/events.js";
3
+ export type EventJson = string | number | boolean | null | readonly EventJson[] | EventJsonObject;
4
+ export type EventJsonObject = {
5
+ [key: string]: EventJson | undefined;
6
+ };
7
+ export interface ManagedEventSubscription {
8
+ id: string;
9
+ name: string;
10
+ arguments: EventJsonObject;
11
+ status: "pending" | "active" | "needs_auth" | "stopped" | "expired" | "failed";
12
+ expiresAt: string | null;
13
+ cleanupStatus?: "pending" | "complete" | "exhausted";
14
+ }
15
+ export type ManagedEventSubscribeInput = {
16
+ name: string;
17
+ arguments: EventJsonObject;
18
+ context?: EventJsonObject;
19
+ idempotencyKey: string;
20
+ /** Application lifetime in milliseconds, or null until explicitly stopped. */
21
+ ttlMs: number | null;
22
+ options?: {
23
+ signal?: AbortSignal;
24
+ timeout?: number;
25
+ maxTotalTimeout?: number;
26
+ };
27
+ };
28
+ export interface ConnectionEventsAdapter {
29
+ subscribe(input: ManagedEventSubscribeInput): Promise<ManagedEventSubscription>;
30
+ getSubscription(input: {
31
+ id: string;
32
+ options?: {
33
+ timeout?: number;
34
+ };
35
+ }): Promise<ManagedEventSubscription>;
36
+ unsubscribe(input: {
37
+ id: string;
38
+ options?: {
39
+ timeout?: number;
40
+ };
41
+ }): Promise<ManagedEventSubscription>;
42
+ }
43
+ export type ConnectionEventDelivery = {
44
+ version: 1;
45
+ deliveryId: string;
46
+ subscriptionId: string;
47
+ source: {
48
+ type: "mcp";
49
+ connectorId: string;
50
+ };
51
+ context: Record<string, unknown>;
52
+ } & ({
53
+ event: Experimental_ConnectionEvent;
54
+ } | {
55
+ control: {
56
+ type: "gap";
57
+ cursor: string | null;
58
+ truncated?: true;
59
+ };
60
+ } | {
61
+ control: {
62
+ type: "terminated";
63
+ error: {
64
+ code: number;
65
+ message: string;
66
+ data?: unknown;
67
+ };
68
+ };
69
+ });
70
+ export interface ConnectionEventsBackend {
71
+ createAdapter(input: {
72
+ principal: ConnectionPrincipal;
73
+ connection: {
74
+ url: string;
75
+ };
76
+ destination: {
77
+ path: string;
78
+ };
79
+ }): Promise<ConnectionEventsAdapter>;
80
+ verify(request: Request, options: {
81
+ path: string;
82
+ }): Promise<ConnectionEventDelivery>;
83
+ }
84
+ export declare function readConnectionEventsBackend(value: unknown): ConnectionEventsBackend | undefined;
@@ -0,0 +1 @@
1
+ function readConnectionEventsBackend(e){if(e!==void 0){if(typeof e!=`object`||!e||!(`createAdapter`in e)||typeof e.createAdapter!=`function`||!(`verify`in e)||typeof e.verify!=`function`)throw TypeError(`Connect experimental_events must provide createAdapter and verify methods.`);return e}}export{readConnectionEventsBackend};
@@ -1,3 +1,4 @@
1
+ import type { ConnectionEventsBackend } from "#shared/connection-events.js";
1
2
  /**
2
3
  * Protocol-agnostic interfaces for the connection system.
3
4
  *
@@ -225,6 +226,7 @@ interface AuthorizationDefinitionBase {
225
226
  * Connect side.
226
227
  */
227
228
  readonly vercelConnect?: {
229
+ readonly experimental_events?: ConnectionEventsBackend;
228
230
  readonly connector: string;
229
231
  };
230
232
  /**
@@ -405,9 +407,17 @@ export interface ConnectionToolExecuteOptions {
405
407
  }
406
408
  /** A live client for a single connection. */
407
409
  export interface ConnectionClient {
410
+ /** eve-owned event actions, separate from remote protocol tools and their filters. */
411
+ readonly eventActions?: ConnectionEventActionHandler;
408
412
  close(): Promise<void>;
409
413
  connect(): Promise<unknown>;
410
414
  executeTool(toolName: string, args: unknown, options: ConnectionToolExecuteOptions): Promise<unknown>;
411
415
  getToolMetadata(): Promise<readonly ConnectionToolMetadata[]>;
412
416
  }
417
+ export interface ConnectionEventActionHandler {
418
+ ownsName(name: string): boolean;
419
+ metadata(): Promise<readonly ConnectionToolMetadata[]>;
420
+ recoveryMetadata(): readonly ConnectionToolMetadata[];
421
+ execute(name: string, args: unknown, options: ConnectionToolExecuteOptions): Promise<unknown>;
422
+ }
413
423
  export {};
@@ -1 +1 @@
1
- import{extractVercelConnectMetadata}from"#shared/vercel-connect-metadata.js";function validateAuthorizationSpec(e,t=`auth`){if(typeof e!=`object`||!e)return`The "${t}" field must be an object with a "getToken" method.`;let n=e;if(typeof n.getToken!=`function`)return`The "${t}.getToken" field must be a function returning Promise<{ token }>.`;let r=n.startAuthorization!==void 0,i=n.completeAuthorization!==void 0,a=n.credentialOwner!==void 0,o=n.principalType!==void 0;if(a&&o)return`The "${t}" field must not provide both "credentialOwner" and "principalType".`;let s=a?`credentialOwner`:`principalType`,c=a?n.credentialOwner:n.principalType;if(c!==void 0&&c!==`app`&&c!==`user`)return`The "${t}.${s}" field must be "app" or "user".`;if(r!==i)return`The "${t}" field must provide either both "startAuthorization" and "completeAuthorization" (interactive OAuth) or neither (getToken-only). Got only "${r?`startAuthorization`:`completeAuthorization`}".`;if(r&&typeof n.startAuthorization!=`function`)return`The "${t}.startAuthorization" field must be a function when provided.`;if(i&&typeof n.completeAuthorization!=`function`)return`The "${t}.completeAuthorization" field must be a function when provided.`;if(r&&a)return`The "${t}.credentialOwner" field is only supported by getToken-only authorization. Interactive authorization is restricted to "principalType": "user" in v1.`;if(r&&n.principalType!==`user`)return`Interactive authorization (startAuthorization + completeAuthorization) is restricted to "principalType": "user" in v1. App-level credentials must use a getToken-only definition.`;if(n.displayName!==void 0&&(typeof n.displayName!=`string`||n.displayName.length===0))return`The "${t}.displayName" field must be a non-empty string when provided.`}function normalizeAuthorizationSpec(e,t,n=`auth`){let r=validateAuthorizationSpec(e,n);if(r!==void 0)throw Error(`${t} ${r}`);let i=e,a=extractVercelConnectMetadata(i.vercelConnect),o=i.displayName,s=typeof i.evict==`function`?i.evict:void 0;if(i.startAuthorization!==void 0&&i.completeAuthorization!==void 0){let e={completeAuthorization:i.completeAuthorization,getToken:i.getToken,principalType:`user`,startAuthorization:i.startAuthorization};return a!==void 0&&(e={...e,vercelConnect:a}),o!==void 0&&(e={...e,displayName:o}),s!==void 0&&(e={...e,evict:s}),e}let c={getToken:i.getToken,principalType:i.credentialOwner??i.principalType??`app`};return a!==void 0&&(c={...c,vercelConnect:a}),o!==void 0&&(c={...c,displayName:o}),s!==void 0&&(c={...c,evict:s}),c}export{normalizeAuthorizationSpec,validateAuthorizationSpec};
1
+ import{extractVercelConnectMetadata}from"#shared/vercel-connect-metadata.js";import{readConnectionEventsBackend}from"#shared/connection-events.js";function validateAuthorizationSpec(e,t=`auth`){if(typeof e!=`object`||!e)return`The "${t}" field must be an object with a "getToken" method.`;let n=e;if(typeof n.getToken!=`function`)return`The "${t}.getToken" field must be a function returning Promise<{ token }>.`;let r=n.startAuthorization!==void 0,i=n.completeAuthorization!==void 0,a=n.credentialOwner!==void 0,o=n.principalType!==void 0;if(a&&o)return`The "${t}" field must not provide both "credentialOwner" and "principalType".`;let s=a?`credentialOwner`:`principalType`,c=a?n.credentialOwner:n.principalType;if(c!==void 0&&c!==`app`&&c!==`user`)return`The "${t}.${s}" field must be "app" or "user".`;if(r!==i)return`The "${t}" field must provide either both "startAuthorization" and "completeAuthorization" (interactive OAuth) or neither (getToken-only). Got only "${r?`startAuthorization`:`completeAuthorization`}".`;if(r&&typeof n.startAuthorization!=`function`)return`The "${t}.startAuthorization" field must be a function when provided.`;if(i&&typeof n.completeAuthorization!=`function`)return`The "${t}.completeAuthorization" field must be a function when provided.`;if(r&&a)return`The "${t}.credentialOwner" field is only supported by getToken-only authorization. Interactive authorization is restricted to "principalType": "user" in v1.`;if(r&&n.principalType!==`user`)return`Interactive authorization (startAuthorization + completeAuthorization) is restricted to "principalType": "user" in v1. App-level credentials must use a getToken-only definition.`;if(n.displayName!==void 0&&(typeof n.displayName!=`string`||n.displayName.length===0))return`The "${t}.displayName" field must be a non-empty string when provided.`}function normalizeAuthorizationSpec(e,t,n=`auth`){let r=validateAuthorizationSpec(e,n);if(r!==void 0)throw Error(`${t} ${r}`);let i=e,a=extractVercelConnectMetadata(i.vercelConnect),o=readConnectionEventsBackend(i.vercelConnect?.experimental_events),s=a;o!==void 0&&a!==void 0&&(s={...a,experimental_events:o});let c=i.displayName,l=typeof i.evict==`function`?i.evict:void 0;if(i.startAuthorization!==void 0&&i.completeAuthorization!==void 0){let e={completeAuthorization:i.completeAuthorization,getToken:i.getToken,principalType:`user`,startAuthorization:i.startAuthorization};return s!==void 0&&(e={...e,vercelConnect:s}),c!==void 0&&(e={...e,displayName:c}),l!==void 0&&(e={...e,evict:l}),e}let u={getToken:i.getToken,principalType:i.credentialOwner??i.principalType??`app`};return s!==void 0&&(u={...u,vercelConnect:s}),c!==void 0&&(u={...u,displayName:c}),l!==void 0&&(u={...u,evict:l}),u}export{normalizeAuthorizationSpec,validateAuthorizationSpec};
@@ -1 +1 @@
1
- async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.79.2//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
1
+ async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.80.0//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
@@ -15,5 +15,10 @@ export interface NoReplyToolInput {
15
15
  *
16
16
  * A turn that ends with `no_reply` completes without a final message, so
17
17
  * channels and schedules post nothing. Only root sessions receive it.
18
+ * A root session also accepts a model call returning no text with
19
+ * `finishReason: "stop"` without retry. Delegated sessions still retry empty
20
+ * replies and report a failure if recovery is exhausted.
21
+ * This tool records an explicit choice to stay quiet and an optional reason
22
+ * instead of relying on blank model output.
18
23
  */
19
24
  export declare function noReply(): ToolDefinition<NoReplyToolInput, string>;
@@ -1 +1 @@
1
- import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.79.2//executeSleepTool`;export{executeSleepTool};
1
+ import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";if(t.abortSignal.aborted)return{interrupted:!0};let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.80.0//executeSleepTool`;export{executeSleepTool};
@@ -0,0 +1,25 @@
1
+ import { type SpanContext } from "#compiled/@opentelemetry/api/index.js";
2
+ import { type AlsContext } from "#context/container.js";
3
+ /** Only carry a validated W3C identity across durable steps, never baggage or content policy. */
4
+ export declare function connectionEventTraceContext(value: unknown): SpanContext | undefined;
5
+ export declare function connectionEventAttributes(input: {
6
+ connectionName: string;
7
+ sessionId?: string;
8
+ subscriptionId?: string;
9
+ deliveryId?: string;
10
+ bindingId?: string;
11
+ }): Record<string, string>;
12
+ /** Preserve diagnostic categories without logging SDK request objects or provider response bodies. */
13
+ export declare function connectionEventError(error: unknown): Error;
14
+ type EventOperation = "catalog" | "subscribe" | "get" | "unsubscribe" | "onEvent" | "onGap" | "onTerminated";
15
+ /** No model turn is needed to restore a session's trace policy in a durable event step. */
16
+ export declare function withConnectionEventSpan<T>(input: {
17
+ ctx: AlsContext;
18
+ connectionName: string;
19
+ operation: EventOperation;
20
+ subscriptionId?: string;
21
+ deliveryId?: string;
22
+ bindingId?: string;
23
+ requestTraceContext?: SpanContext;
24
+ }, execute: (reference?: SpanContext) => Promise<T>): Promise<T>;
25
+ export {};
@@ -0,0 +1 @@
1
+ import{createLogger,logError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{SessionIdKey}from"#context/keys.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{formatTraceparent}from"#protocol/traceparent.js";import{ContextAgentTraceStateStore}from"#tracing/eve/agent-trace-context-store.js";import{resolveTracePolicy}from"#shared/trace-policy.js";import{ROOT_CONTEXT,context,trace}from"#compiled/@opentelemetry/api/index.js";import{markAgentTraceContext}from"#tracing/eve/agent-trace-context.js";import{activeTraceOperation,truncateTelemetryText,withErrorContent}from"#compiled/@eve/tracing/otel.js";import{otelTelemetry}from"#compiled/@eve/tracing/index.js";import{readInstrumentationSessionContext}from"#instrumentation/session-context.js";import{getInstrumentationRuntime}from"#instrumentation/runtime-global.js";import{withChannelAudience}from"#tracing/eve/channel-audience-context.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`connection.events`);function connectionEventTraceContext(e){if(typeof e!=`object`||!e)return;let{traceId:t,spanId:n,traceFlags:r}=e;if(typeof t!=`string`||typeof n!=`string`||r!==0&&r!==1)return;let i={traceId:t,spanId:n,traceFlags:r};return formatTraceparent(i)===void 0?void 0:i}function connectionEventAttributes(e){let t={};for(let[n,r]of Object.entries({"agent.connection.name":e.connectionName,"agent.run.id":e.sessionId,"connect.subscription.id":e.subscriptionId,"connect.delivery.id":e.deliveryId,"eve.connection.event.binding.id":e.bindingId}))r!==void 0&&(t[n]=truncateTelemetryText(r,256));return t}function connectionEventError(e){let t=Error(`Connection event operation failed`);if(e instanceof Error&&[`Error`,`TypeError`,`RangeError`,`SyntaxError`,`AbortError`,`TimeoutError`,`MCPClientError`].includes(e.name)&&(t.name=e.name),typeof e!=`object`||!e)return t;let n=e,r=n.code,i=n.statusCode??n.status,a=typeof r==`number`&&Number.isFinite(r)||typeof r==`string`&&[`invalid_delivery`,`verification_unavailable`,`configuration_error`,`ETIMEDOUT`,`ECONNRESET`,`ECONNREFUSED`,`ENOTFOUND`,`EAI_AGAIN`].includes(r)?r:void 0;return a!==void 0&&Object.assign(t,{code:a}),typeof i==`number`&&Number.isInteger(i)&&i>=100&&i<=599&&Object.assign(t,{statusCode:i}),t}async function withConnectionEventSpan(e,t){return contextStorage.run(e.ctx,async()=>{let n=getInstrumentationRuntime(),r=otelTelemetry({tracerName:`eve.connection.events`,mapping:eveOutputMapping()}),i=n?.otelSettings,a=e.ctx.require(SessionIdKey),o=connectionEventAttributes({...e,sessionId:a}),run=async n=>{try{return await t(n)}catch(t){throw logError(log,`connection event operation failed`,connectionEventError(t),{...o,operation:e.operation}),t}};if(i===void 0)return r.suppressed(()=>run());let s=new ContextAgentTraceStateStore().get(`session`,a),c=readInstrumentationSessionContext(e.ctx),l=c.traceSeed?.decision??s?.decision??resolveTracePolicy(i.tracePolicy,{...c.conversation,agentName:e.ctx.require(BundleKey).resolvedAgent.config?.name??`eve`}),u=activeTraceOperation(),d=connectionEventTraceContext(e.requestTraceContext)??u?.reference??s?.context;if(l.action===`drop`||u?.capture.emit===!1||c.traceSeed!==void 0&&!(c.traceSeed.traceFlags&1)||s!==void 0&&!(s.context.traceFlags&1)||d!==void 0&&!(d.traceFlags&1))return r.suppressed(()=>run());let f=d===void 0?context.active():trace.setSpan(ROOT_CONTEXT,trace.wrapSpanContext(d)),p=markAgentTraceContext(withErrorContent(withChannelAudience(f,c.audience),!1)),m=`agent.connection.event.${e.operation}`,h=r.startSpan({type:`step`,operationId:m,name:m,kind:e.operation.startsWith(`on`)?`CONSUMER`:`INTERNAL`,attributes:{...o,"operation.name":m,"resource.name":m}},{context:p});try{let t=await r.run({type:`step`,reference:h.reference,capture:{emit:!0,recordInputs:!1,recordOutputs:!1}},()=>run(connectionEventTraceContext(h.reference)),p);if([`subscribe`,`get`,`unsubscribe`].includes(e.operation)&&typeof t==`object`&&t){let e=t;typeof e.id==`string`&&h.setAttribute(`connect.subscription.id`,truncateTelemetryText(e.id,256)),typeof e.status==`string`&&[`pending`,`active`,`needs_auth`,`stopped`,`expired`,`failed`].includes(e.status)&&h.setAttribute(`connect.subscription.status`,e.status)}return h.setAttribute(`eve.connection.event.outcome`,`completed`),h.setStatus(`OK`),t}catch(e){throw h.setAttribute(`eve.connection.event.outcome`,`failed`),h.fail(void 0,`connection_event_error`),e}finally{h.end(),await n.forceFlush().catch(()=>log.warn(`flushing connection event traces failed`))}})}export{connectionEventAttributes,connectionEventError,connectionEventTraceContext,withConnectionEventSpan};
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{ConversationIdKey}from"#context/keys.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{readConversationId}from"#shared/conversation-identity.js";import{ContextAgentTraceStateStore}from"#tracing/eve/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#instrumentation/runtime.js";import{createInstrumentationHooks}from"#instrumentation/lifecycle.js";import{AgentSpanIdGenerator,otelTelemetry}from"#compiled/@eve/tracing/index.js";import{hasConversationRelease}from"#tracing/local/traces.js";import{createAgentOtelInstrumentation}from"#tracing/eve/agent-otel-provider.js";import{registerOtel}from"#tracing/eve/otel-registration.js";import{eveOutputMapping}from"#tracing/eve/profile.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],n=[],r,i,a,runInContext=(e,t)=>t(),o;if(e.collected.declared){r=registerOtel({serviceName:e.serviceName,otel:e.collected.configuration}),o=r.idGenerator;let s=createAgentOtelInstrumentation({environment:resolveInstrumentationEnvironment(),frameworkVersion:e.frameworkVersion,telemetry:otelTelemetry({provider:r.provider,tracerName:`eve.agent`,tracerVersion:e.frameworkVersion,idGenerator:o,samplesTrace:r.samplesTrace,mapping:eveOutputMapping()}),idGenerator:o,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,stateStore:new ContextAgentTraceStateStore,tracePolicy:e.collected.settings.tracePolicy});t.push({...s.hook,stateNamespace:`internal:otel`}),i=s.prepareSessionTrace,a=s.prepareTurnTrace,runInContext=s.runInContext;let c=e.collected.configuration.spanProcessors.filter(isSpanProcessor).filter(hasConversationRelease);c.length>0&&n.push(sessionReleaseProvider(c))}else o=new AgentSpanIdGenerator;let s=[...t,...e.providers,...n],c;return registerInstrumentationRuntime({forceFlush:async()=>{await settleAll(s.map(e=>()=>e.flush?.())),await settleAll(r===void 0?[]:[r.forceFlush])},hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:n,serialBefore:t}),idGenerator:o,memoryOperations:r!==void 0||e.providers.some(hasMemoryOperationHandler),otelSettings:e.collected.declared?e.collected.settings:void 0,ownsAgentSpans:r!==void 0,prepareSessionTrace:i,prepareTurnTrace:a,runtimeContextResolvers:e.runtimeContextResolvers,runInContext,samplesTrace:r?.samplesTrace,shutdown:()=>(c??=(async()=>{await settleAll(s.map(e=>()=>e.shutdown?.())),await settleAll(r===void 0?[]:[r.shutdown])})(),c)})}function hasMemoryOperationHandler(e){return e.events?.[`memory.operation.started`]!==void 0||e.events?.[`memory.operation.completed`]!==void 0||e.events?.[`memory.operation.failed`]!==void 0}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{let n=readConversationId(contextStorage.getStore()?.get(ConversationIdKey))??t.sessionId;n===t.sessionId&&await Promise.all(e.map(e=>e.releaseConversation(n)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.conversation-release`,stateNamespace:`internal:conversation-release`}}async function settleAll(e){let t=await Promise.allSettled(e.map(async e=>e()));for(let e of t)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{ConversationIdKey}from"#context/keys.js";import{resolveInstrumentationEnvironment}from"#internal/application/dev-environment.js";import{readConversationId}from"#shared/conversation-identity.js";import{ContextAgentTraceStateStore}from"#tracing/eve/agent-trace-context-store.js";import{registerInstrumentationRuntime}from"#instrumentation/runtime.js";import{createInstrumentationHooks}from"#instrumentation/lifecycle.js";import{AgentSpanIdGenerator,otelTelemetry}from"#compiled/@eve/tracing/index.js";import{hasConversationRelease}from"#tracing/local/traces.js";import{eveOutputMapping}from"#tracing/eve/profile.js";import{createAgentOtelInstrumentation}from"#tracing/eve/agent-otel-provider.js";import{registerOtel}from"#tracing/eve/otel-registration.js";const log=createLogger(`tracing.install-instrumentation-runtime`);function installInstrumentationRuntime(e){let t=[],n=[],r,i,a,runInContext=(e,t)=>t(),o;if(e.collected.declared){r=registerOtel({serviceName:e.serviceName,otel:e.collected.configuration}),o=r.idGenerator;let s=createAgentOtelInstrumentation({environment:resolveInstrumentationEnvironment(),frameworkVersion:e.frameworkVersion,telemetry:otelTelemetry({provider:r.provider,tracerName:`eve.agent`,tracerVersion:e.frameworkVersion,idGenerator:o,samplesTrace:r.samplesTrace,mapping:eveOutputMapping()}),idGenerator:o,recordInputs:e.collected.settings.recordInputs,recordOutputs:e.collected.settings.recordOutputs,stateStore:new ContextAgentTraceStateStore,tracePolicy:e.collected.settings.tracePolicy});t.push({...s.hook,stateNamespace:`internal:otel`}),i=s.prepareSessionTrace,a=s.prepareTurnTrace,runInContext=s.runInContext;let c=e.collected.configuration.spanProcessors.filter(isSpanProcessor).filter(hasConversationRelease);c.length>0&&n.push(sessionReleaseProvider(c))}else o=new AgentSpanIdGenerator;let s=[...t,...e.providers,...n],c;return registerInstrumentationRuntime({forceFlush:async()=>{await settleAll(s.map(e=>()=>e.flush?.())),await settleAll(r===void 0?[]:[r.forceFlush])},hooks:createInstrumentationHooks({parallel:e.providers,serialAfter:n,serialBefore:t}),idGenerator:o,memoryOperations:r!==void 0||e.providers.some(hasMemoryOperationHandler),otelSettings:e.collected.declared?e.collected.settings:void 0,ownsAgentSpans:r!==void 0,prepareSessionTrace:i,prepareTurnTrace:a,runtimeContextResolvers:e.runtimeContextResolvers,runInContext,samplesTrace:r?.samplesTrace,shutdown:()=>(c??=(async()=>{await settleAll(s.map(e=>()=>e.shutdown?.())),await settleAll(r===void 0?[]:[r.shutdown])})(),c)})}function hasMemoryOperationHandler(e){return e.events?.[`memory.operation.started`]!==void 0||e.events?.[`memory.operation.completed`]!==void 0||e.events?.[`memory.operation.failed`]!==void 0}function isSpanProcessor(e){return e!==`auto`}function sessionReleaseProvider(e){let release=async t=>{let n=readConversationId(contextStorage.getStore()?.get(ConversationIdKey))??t.sessionId;n===t.sessionId&&await Promise.all(e.map(e=>e.releaseConversation(n)))};return{events:{"session.completed":release,"session.failed":release},name:`eve.conversation-release`,stateNamespace:`internal:conversation-release`}}async function settleAll(e){let t=await Promise.allSettled(e.map(async e=>e()));for(let e of t)e.status===`rejected`&&log.warn(`instrumentation drain failed`,{error:formatError(e.reason)})}export{installInstrumentationRuntime};
@@ -13,6 +13,7 @@ export declare function createMcpTraceFetch(input: {
13
13
  export declare const MCP_SERIALIZER: ContentSerializer;
14
14
  export declare function createMcpTracing(): {
15
15
  list<T>(input: {
16
+ readonly method?: "tools/list" | "events/list";
16
17
  readonly connectionName: string;
17
18
  readonly execute: () => Promise<T>;
18
19
  readonly protocolVersion?: string;
@@ -1 +1 @@
1
- import{eveOutputMapping}from"./profile.js";import{context,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation,contentAttribute,mcpLifecycle,truncateTelemetryText}from"#compiled/@eve/tracing/otel.js";import{otelTelemetry}from"#compiled/@eve/tracing/index.js";function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const MAX_MCP_TRACE_REQUEST_BYTES=1048576,MAX_MCP_TRACE_CONTEXT_BYTES=8192,utf8Encoder=new TextEncoder,traceContextSetter={set(e,t,n){e[t]=n}};function createMcpTraceFetch(e){let t=e.fetcher??((e,t)=>globalThis.fetch(e,t)),n=e.getActiveContext??(()=>context.active()),r=e.injectContext??injectOpenTelemetryTraceContext;return async(i,a)=>{let o=readJsonRpcRequest(a?.body);if(o===void 0)return await t(i,a);let s=n(),c=injectMcpTraceContext(o,s,r,e.filterCarrier),l=o.method===`tools/call`||o.method===`tools/list`&&activeTraceOperation(s)?.type===`mcp`;l&&activeTraceOperation(s)?.mcp?.update(mcpRequestMetadata({connectionName:e.connectionName,message:o,params:isObject(o.params)?o.params:{},protocolVersion:headerValue(a?.headers,`mcp-protocol-version`)??e.getProtocolVersion()}));let u=await t(i,c===void 0?a:{...a,body:JSON.stringify(c)});if(l){let e=u.headers.get(`mcp-session-id`);e!==null&&activeTraceOperation(s)?.mcp?.update({sessionId:truncateTelemetryText(e,512)})}return u}}function injectMcpTraceContext(e,t,n=injectOpenTelemetryTraceContext,r){if(!withinTraceRequestLimit(JSON.stringify(e))||e.params!==void 0&&!isObject(e.params))return;let i={};if(n(t,i),!withinTraceContextLimit(i))return;r?.(i);let a=isObject(e.params)?e.params:{},o=isObject(a._meta)?a._meta:{};return{...e,params:{...a,_meta:{...o,...i}}}}const noContent=()=>void 0,MCP_SERIALIZER={json:contentAttribute,text:noContent,inputMessages:noContent,instructions:noContent,toolDefinitions:noContent,outputMessages:noContent,toolResults:noContent};function createMcpTracing(){let e=otelTelemetry({tracerName:`eve.mcp`,mapping:eveOutputMapping()});function start(t){let n=e.startSpan({type:`mcp`,operationId:`${t.connectionName}:${t.method}`,name:t.method===`tools/call`?`tools/call ${t.toolName??`unknown`}`:t.method,kind:`CLIENT`,parent:trace.getSpan(t.executionContext)?.spanContext(),attributes:{"agent.connection.name":t.connectionName,"mcp.method.name":t.method,"network.protocol.name":`http`,"network.transport":`tcp`,"mcp.protocol.version":t.protocolVersion,"gen_ai.operation.name":t.method===`tools/call`?`execute_tool`:void 0,"gen_ai.tool.name":t.toolName}},{context:t.executionContext}),r=mcpLifecycle({serializer:MCP_SERIALIZER,...t.capture,write(e){for(let[t,r]of Object.entries(e))r!==void 0&&n.setAttribute(t,r)},error:n.fail});return{...r,end:n.end,run(i){return e.run({type:`mcp`,reference:n.reference,capture:t.capture,mcp:r},i,t.executionContext)}}}return{async list(e){let t=context.active(),n=start({method:`tools/list`,connectionName:e.connectionName,protocolVersion:e.protocolVersion,executionContext:t,capture:activeTraceOperation()?.capture??{emit:!0,recordInputs:!1,recordOutputs:!1}});try{return await n.run(async()=>{try{return await e.execute()}catch(e){let t=jsonRpcErrorCode(e);throw t!==void 0&&n.update({statusCode:t}),n.error(e,errorType(e,t)),e}})}finally{n.end()}},async call(e){let t=context.active(),n=activeTraceOperation();if(n?.type===`tool`&&n.mcp!==void 0)return n.mcp.update({...e,method:`tools/call`}),await runMcpToolCall(e,void 0);let r=start({method:`tools/call`,connectionName:e.connectionName,toolName:truncateTelemetryText(e.toolName,128),protocolVersion:e.protocolVersion,executionContext:t,capture:n?.capture??{emit:!0,recordInputs:!1,recordOutputs:!1}});try{return await r.run(()=>runMcpToolCall(e,r))}finally{r.end()}}}}function runMcpToolCall(e,t){return t!==void 0&&t.arguments(e.arguments),e.execute().then(e=>(isToolErrorResult(e)&&activeTraceOperation()?.mcp?.error(void 0,`tool_error`),t!==void 0&&t.result(e),e)).catch(e=>{let n=jsonRpcErrorCode(e);throw n!==void 0&&activeTraceOperation()?.mcp?.update({statusCode:n}),t!==void 0&&activeTraceOperation()?.mcp?.error(e,errorType(e,n)),e})}function mcpRequestMetadata(e){let t=e.method??e.message?.method,n=e.params??(isObject(e.message?.params)?e.message.params:{}),r=e.toolName??(typeof n.name==`string`?n.name:void 0),i=e.message?.id,a=n._meta,o=e.protocolVersion??(isObject(a)&&typeof a[`io.modelcontextprotocol/protocolVersion`]==`string`?a[`io.modelcontextprotocol/protocolVersion`]:void 0);return{connectionName:e.connectionName,method:t??`unknown`,toolName:r,protocolVersion:o,requestId:typeof i==`number`||typeof i==`string`?String(i):void 0}}function injectOpenTelemetryTraceContext(e,t){propagation.inject(e,t,traceContextSetter)}function readJsonRpcRequest(e){if(typeof e==`string`&&withinTraceRequestLimit(e))try{let t=JSON.parse(e);return isObject(t)&&typeof t.method==`string`?t:void 0}catch{return}}function withinTraceRequestLimit(e){return e.length<=MAX_MCP_TRACE_REQUEST_BYTES&&utf8Encoder.encode(e).byteLength<=MAX_MCP_TRACE_REQUEST_BYTES}function withinTraceContextLimit(e){let t=0;for(let[n,r]of Object.entries(e))if(n.length+r.length>MAX_MCP_TRACE_CONTEXT_BYTES||(t+=utf8Encoder.encode(n).byteLength+utf8Encoder.encode(r).byteLength+2,t>MAX_MCP_TRACE_CONTEXT_BYTES))return!1;return t>0}function headerValue(e,t){if(e!==void 0)try{return new Headers(e).get(t)??void 0}catch{return}}function isToolErrorResult(e){return isObject(e)&&e.isError===!0}function jsonRpcErrorCode(e){if(!isObject(e))return;let t=e.code;return typeof t==`number`||typeof t==`string`?String(t):void 0}function errorType(e,t){return t===void 0?e instanceof Error?e.name||`Error`:void 0:t}export{MCP_SERIALIZER,createMcpTraceFetch,createMcpTracing};
1
+ import{eveOutputMapping}from"./profile.js";import{context,propagation,trace}from"#compiled/@opentelemetry/api/index.js";import{activeTraceOperation,contentAttribute,mcpLifecycle,truncateTelemetryText}from"#compiled/@eve/tracing/otel.js";import{otelTelemetry}from"#compiled/@eve/tracing/index.js";function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const MAX_MCP_TRACE_REQUEST_BYTES=1048576,MAX_MCP_TRACE_CONTEXT_BYTES=8192,utf8Encoder=new TextEncoder,traceContextSetter={set(e,t,n){e[t]=n}};function createMcpTraceFetch(e){let t=e.fetcher??((e,t)=>globalThis.fetch(e,t)),n=e.getActiveContext??(()=>context.active()),r=e.injectContext??injectOpenTelemetryTraceContext;return async(i,a)=>{let o=readJsonRpcRequest(a?.body);if(o===void 0)return await t(i,a);let s=n(),c=injectMcpTraceContext(o,s,r,e.filterCarrier),l=o.method===`tools/call`||(o.method===`tools/list`||o.method===`events/list`)&&activeTraceOperation(s)?.type===`mcp`;l&&activeTraceOperation(s)?.mcp?.update(mcpRequestMetadata({connectionName:e.connectionName,message:o,params:isObject(o.params)?o.params:{},protocolVersion:headerValue(a?.headers,`mcp-protocol-version`)??e.getProtocolVersion()}));let u=await t(i,c===void 0?a:{...a,body:JSON.stringify(c)});if(l){let e=u.headers.get(`mcp-session-id`);e!==null&&activeTraceOperation(s)?.mcp?.update({sessionId:truncateTelemetryText(e,512)})}return u}}function injectMcpTraceContext(e,t,n=injectOpenTelemetryTraceContext,r){if(!withinTraceRequestLimit(JSON.stringify(e))||e.params!==void 0&&!isObject(e.params))return;let i={};if(n(t,i),!withinTraceContextLimit(i))return;r?.(i);let a=isObject(e.params)?e.params:{},o=isObject(a._meta)?a._meta:{};return{...e,params:{...a,_meta:{...o,...i}}}}const noContent=()=>void 0,MCP_SERIALIZER={json:contentAttribute,text:noContent,inputMessages:noContent,instructions:noContent,toolDefinitions:noContent,outputMessages:noContent,toolResults:noContent};function createMcpTracing(){let e=otelTelemetry({tracerName:`eve.mcp`,mapping:eveOutputMapping()});function start(t){let n=e.startSpan({type:`mcp`,operationId:`${t.connectionName}:${t.method}`,name:t.method===`tools/call`?`tools/call ${t.toolName??`unknown`}`:t.method,kind:`CLIENT`,parent:trace.getSpan(t.executionContext)?.spanContext(),attributes:{"agent.connection.name":t.connectionName,"mcp.method.name":t.method,"network.protocol.name":`http`,"network.transport":`tcp`,"mcp.protocol.version":t.protocolVersion,"gen_ai.operation.name":t.method===`tools/call`?`execute_tool`:void 0,"gen_ai.tool.name":t.toolName}},{context:t.executionContext}),r=mcpLifecycle({serializer:MCP_SERIALIZER,...t.capture,write(e){for(let[t,r]of Object.entries(e))r!==void 0&&n.setAttribute(t,r)},error:n.fail});return{...r,end:n.end,run(i){return e.run({type:`mcp`,reference:n.reference,capture:t.capture,mcp:r},i,t.executionContext)}}}return{async list(e){let t=context.active(),n=start({method:e.method??`tools/list`,connectionName:e.connectionName,protocolVersion:e.protocolVersion,executionContext:t,capture:activeTraceOperation()?.capture??{emit:!0,recordInputs:!1,recordOutputs:!1}});try{return await n.run(async()=>{try{return await e.execute()}catch(e){let t=jsonRpcErrorCode(e);throw t!==void 0&&n.update({statusCode:t}),n.error(e,errorType(e,t)),e}})}finally{n.end()}},async call(e){let t=context.active(),n=activeTraceOperation();if(n?.type===`tool`&&n.mcp!==void 0)return n.mcp.update({...e,method:`tools/call`}),await runMcpToolCall(e,void 0);let r=start({method:`tools/call`,connectionName:e.connectionName,toolName:truncateTelemetryText(e.toolName,128),protocolVersion:e.protocolVersion,executionContext:t,capture:n?.capture??{emit:!0,recordInputs:!1,recordOutputs:!1}});try{return await r.run(()=>runMcpToolCall(e,r))}finally{r.end()}}}}function runMcpToolCall(e,t){return t!==void 0&&t.arguments(e.arguments),e.execute().then(e=>(isToolErrorResult(e)&&activeTraceOperation()?.mcp?.error(void 0,`tool_error`),t!==void 0&&t.result(e),e)).catch(e=>{let n=jsonRpcErrorCode(e);throw n!==void 0&&activeTraceOperation()?.mcp?.update({statusCode:n}),t!==void 0&&activeTraceOperation()?.mcp?.error(e,errorType(e,n)),e})}function mcpRequestMetadata(e){let t=e.method??e.message?.method,n=e.params??(isObject(e.message?.params)?e.message.params:{}),r=e.toolName??(typeof n.name==`string`?n.name:void 0),i=e.message?.id,a=n._meta,o=e.protocolVersion??(isObject(a)&&typeof a[`io.modelcontextprotocol/protocolVersion`]==`string`?a[`io.modelcontextprotocol/protocolVersion`]:void 0);return{connectionName:e.connectionName,method:t??`unknown`,toolName:r,protocolVersion:o,requestId:typeof i==`number`||typeof i==`string`?String(i):void 0}}function injectOpenTelemetryTraceContext(e,t){propagation.inject(e,t,traceContextSetter)}function readJsonRpcRequest(e){if(typeof e==`string`&&withinTraceRequestLimit(e))try{let t=JSON.parse(e);return isObject(t)&&typeof t.method==`string`?t:void 0}catch{return}}function withinTraceRequestLimit(e){return e.length<=MAX_MCP_TRACE_REQUEST_BYTES&&utf8Encoder.encode(e).byteLength<=MAX_MCP_TRACE_REQUEST_BYTES}function withinTraceContextLimit(e){let t=0;for(let[n,r]of Object.entries(e))if(n.length+r.length>MAX_MCP_TRACE_CONTEXT_BYTES||(t+=utf8Encoder.encode(n).byteLength+utf8Encoder.encode(r).byteLength+2,t>MAX_MCP_TRACE_CONTEXT_BYTES))return!1;return t>0}function headerValue(e,t){if(e!==void 0)try{return new Headers(e).get(t)??void 0}catch{return}}function isToolErrorResult(e){return isObject(e)&&e.isError===!0}function jsonRpcErrorCode(e){if(!isObject(e))return;let t=e.code;return typeof t==`number`||typeof t==`string`?String(t):void 0}function errorType(e,t){return t===void 0?e instanceof Error?e.name||`Error`:void 0:t}export{MCP_SERIALIZER,createMcpTraceFetch,createMcpTracing};
@@ -44,6 +44,11 @@ export interface OtelOptions {
44
44
  * lifecycle providers. The policy may be invoked more than once
45
45
  * while a new session is being prepared, so it must be deterministic for
46
46
  * consistent results.
47
+ * Unless `experimental.workflow.retention` is explicit, the session's
48
+ * resolved decision also selects Workflow retention: both content directions
49
+ * use the World's default; dropped traces or either excluded direction
50
+ * request deletion on completion. This also removes completed transcripts,
51
+ * but does not delete exported traces.
47
52
  */
48
53
  readonly tracePolicy?: TraceCapturePolicy;
49
54
  /**
@@ -263,7 +263,8 @@ duration. Process restarts, ordinary messages, compaction handoffs, and failed
263
263
  or skipped handoffs keep the existing deadline. At the deadline, eve lets an active turn settle,
264
264
  then emits `session.completed` and releases every continuation address; the next
265
265
  qualifying channel message starts fresh. Set it to `false` to disable the
266
- timeout. Expiration does not delete stored session data.
266
+ timeout. Session expiration follows [run-data retention](#run-data-retention);
267
+ a zero-retention session loses its stored payloads when it ends.
267
268
 
268
269
  Input tokens, output tokens, and model token cost are checked independently.
269
270
  The model call that crosses a limit is allowed to finish because exact usage
@@ -409,11 +410,24 @@ for the retry behavior.
409
410
 
410
411
  ## Run data retention
411
412
 
412
- The runtime keeps each run's data after the run finishes: model and tool
413
- payloads, streamed output, and the event log eve replays from. How long it keeps
414
- them is the World's decision, and on Vercel that follows your team's plan. Set
415
- `experimental.workflow.retention` to `0` to have it deleted as soon as the run
416
- finishes instead:
413
+ By default, eve derives run-data retention from the session's resolved
414
+ [OpenTelemetry trace policy](./observability/otel#configure-opentelemetry):
415
+
416
+ - When the policy allows both inputs and outputs, eve uses the World's default
417
+ retention period.
418
+ - When the policy drops the trace or excludes either content direction, eve
419
+ requests deletion as soon as the run ends with Workflow's
420
+ `experimental_retention: 0`. Workflow cannot delete inputs and outputs separately.
421
+
422
+ Without a custom policy, public conversations and development sessions use the
423
+ World's default. Private and unknown-audience sessions outside development request
424
+ `0`, even when no OpenTelemetry destination is installed. This decision is made
425
+ when the session starts; destination export filters and lifecycle-provider
426
+ policies do not change it.
427
+
428
+ Set `experimental.workflow.retention` explicitly to override this behavior.
429
+ Use `0` to request deletion regardless of the tracing policy, or `"default"` to
430
+ keep run data for the World's default period regardless of the tracing policy:
417
431
 
418
432
  ```ts title="agent/agent.ts"
419
433
  import { defineAgent } from "eve";
@@ -428,18 +442,29 @@ export default defineAgent({
428
442
  });
429
443
  ```
430
444
 
431
- This applies to every run that owns the session, including successor owners
445
+ The resolved value applies to every run that owns the session, including successor owners
432
446
  started after a deployment handoff, and to the run that collects session
433
447
  activity. Runs eve starts for other purposes keep the world's default: session
434
448
  timeouts and [workflow tools](./tools/workflows).
435
449
 
436
450
  The value applies per agent. A [subagent](./subagents) that runs its own session
437
- uses its own value, unlike `experimental.workflow.world`, which is root-only.
438
-
439
- Custom Worlds used with eve might not support this feature, in which case
440
- it falls back to the World's default retention period.
441
-
442
- > ⚠️ **At `0`, a finished session's output is usually gone before you can read it.** Since data is deleted immediately before it can be read back, results and transcripts become unreadable and a client polling for a finished session's output can see it disappear.
451
+ uses its own explicit value or derives retention from its resolved trace decision,
452
+ including any inherited content ceiling. `experimental.workflow.world` is root-only.
453
+
454
+ At `0`, supporting Worlds delete run and step inputs, outputs, and errors;
455
+ event payloads; and stream contents when the run reaches a terminal state. The
456
+ data remains available while the session is active. Run, step, and event records
457
+ remain for the World's default period, including IDs, timestamps, statuses,
458
+ step names, and attributes. Attributes can contain content, including eve's
459
+ session title. This option does not delete local traces, exported telemetry, or
460
+ data stored by tools, channels, or model providers.
461
+
462
+ The Workflow World enforces deletion, not eve or the SDK. A World older than
463
+ spec version 4 rejects `0`; a spec version 4 World without retention support
464
+ keeps the data. Confirm support with your World provider. See
465
+ [Workflow data retention](https://workflow-sdk.dev/docs/observability/retention).
466
+
467
+ > ⚠️ **At `0`, completed session transcripts become unreadable.** Deletion races reads of finished runs. Depending on the World, reading deleted session history returns either an empty stream or `410` with `code: "session_expired"`. Persist anything you need to keep from inside a tool, or set `retention: "default"` to preserve completed-session reads independently of tracing.
443
468
 
444
469
  ## Other defineAgent fields
445
470
 
@@ -103,9 +103,37 @@ Configure `github` to broker GitHub access through Connect instead. The extensio
103
103
  | `github.connector` | With `github` | Connector that mints a GitHub token |
104
104
  | `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
105
105
  | `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
106
+ | `github.authorize` | No | `authorize({ auth, repository, token })` callback that allows or denies each `gh` tool invocation |
106
107
 
107
108
  The `gh` tool requests a token scoped to exactly one repository in `github.org` for each invocation. The sandbox process receives a placeholder `GH_TOKEN`, and the firewall exchanges it on matching GitHub requests. Your `github.broker` callback receives the header-transform rules for the command, then `null` to remove the lease. The callback must preserve your other network rules. GitHub authentication has no command-delivery option.
108
109
 
110
+ `github.authorize` runs during each `gh` tool execution, not when the session starts. The order is: validate the command and repository, mint the repository-scoped app token, await `authorize({ auth, repository, token })`, install the credential lease, then run the command. `auth` is the session's current caller at tool invocation, or `null`. Returning `false` stops execution before the lease is installed or the command runs. The decision applies to that invocation only; it is neither cached for the session nor repeated for each GitHub API request.
111
+
112
+ For example, use the token to check collaborator status (allowed commands still use the app token's permissions, not the collaborator's):
113
+
114
+ ```ts title="agent/extensions/git.ts"
115
+ import git from "eve/extensions/git";
116
+
117
+ import { brokerGitHubLease } from "../lib/github";
118
+
119
+ export default git({
120
+ github: {
121
+ connector: "github/my-agent",
122
+ org: "acme",
123
+ broker: brokerGitHubLease,
124
+ // GitHub channel sessions carry the commenter's login as `auth.subject`.
125
+ async authorize({ auth, repository, token }) {
126
+ if (auth?.authenticator !== "github-webhook" || !auth.subject) return false;
127
+ const response = await fetch(
128
+ `https://api.github.com/repos/${repository}/collaborators/${auth.subject}`,
129
+ { headers: { authorization: `Bearer ${token}` } },
130
+ );
131
+ return response.status === 204;
132
+ },
133
+ },
134
+ });
135
+ ```
136
+
109
137
  ### Migrate from `code({ github })`
110
138
 
111
139
  `code({ github })` is deprecated. While it is set, the code extension still contributes `code__gh`, its GitHub instructions, and the signed-commit `code__pr` skill. Without it, the code extension contributes no GitHub tool, instructions, or pull request skill. Move the `github` option to `git({ github })`, and import `gh` and the GitHub sandbox helpers from `eve/extensions/git/tools` and `eve/extensions/git/sandbox`.
@@ -422,6 +422,8 @@ export default noReply();
422
422
 
423
423
  `no_reply` is a `defineTool` tool with [`endsTurn: true`](/docs/tools#end-the-turn-after-a-tool-call), so the turn ends only when no other tool runs in the same step. Only root sessions receive it. Slack clears the thread status when the turn completes. Remove the file to remove the tool.
424
424
 
425
+ A root session also accepts a successful model call that returns no text with `finishReason: "stop"`, without retrying or reporting a model-call failure. A turn that settles with no text completes without a final message. Use `no_reply` when the agent should record an explicit choice to stay quiet, including an optional reason. Delegated sessions still retry an empty reply once and report a failure if it remains empty, so the caller can act on the failure.
426
+
425
427
  ### `sleep`
426
428
 
427
429
  `sleep` pauses and durably resumes the current turn. The model calls it with `{ seconds }`; the wait does not hold an application runtime open. Concurrent calls run in parallel, and the turn resumes after the longest wait. A steering message, the default for a new message, ends the wait early: `sleep` returns `{ interrupted: true }`, which the model reads as `Stopped early because a new message arrived.`, followed by the message. Add it: