eve 0.22.2 → 0.22.4

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 (123) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/src/chunks/{use-eve-agent-CM24ZUEI.js → use-eve-agent-CFBTHlPx.js} +43 -14
  3. package/dist/src/chunks/{use-eve-agent-CxcKypLZ.js → use-eve-agent-dEGV09g_.js} +43 -14
  4. package/dist/src/cli/dev/url.js +1 -1
  5. package/dist/src/client/agent-host.d.ts +4 -0
  6. package/dist/src/client/agent-host.js +1 -0
  7. package/dist/src/client/client-error.d.ts +5 -1
  8. package/dist/src/client/client-error.js +1 -1
  9. package/dist/src/client/client.js +1 -1
  10. package/dist/src/client/open-stream.js +1 -1
  11. package/dist/src/client/session.js +1 -1
  12. package/dist/src/client/types.d.ts +2 -1
  13. package/dist/src/client/url.js +1 -1
  14. package/dist/src/compiler/manifest.d.ts +44 -6
  15. package/dist/src/compiler/manifest.js +1 -1
  16. package/dist/src/compiler/module-map.js +2 -2
  17. package/dist/src/compiler/normalize-extension.d.ts +68 -0
  18. package/dist/src/compiler/normalize-extension.js +1 -0
  19. package/dist/src/compiler/normalize-manifest.js +2 -2
  20. package/dist/src/compiler/normalize-subagent.js +1 -1
  21. package/dist/src/compiler/remote-agent-node.d.ts +1 -1
  22. package/dist/src/compiler/remote-agent-node.js +1 -1
  23. package/dist/src/compiler/workspace-resources.js +1 -1
  24. package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
  25. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  26. package/dist/src/discover/discover-agent.d.ts +14 -1
  27. package/dist/src/discover/discover-agent.js +1 -1
  28. package/dist/src/discover/extension-specifier.d.ts +15 -0
  29. package/dist/src/discover/extension-specifier.js +1 -0
  30. package/dist/src/discover/extensions.d.ts +109 -0
  31. package/dist/src/discover/extensions.js +1 -0
  32. package/dist/src/discover/filesystem.d.ts +2 -2
  33. package/dist/src/discover/filesystem.js +1 -1
  34. package/dist/src/discover/grammar.d.ts +27 -0
  35. package/dist/src/discover/grammar.js +1 -1
  36. package/dist/src/discover/manifest.d.ts +46 -0
  37. package/dist/src/discover/manifest.js +1 -1
  38. package/dist/src/discover/project.js +1 -1
  39. package/dist/src/evals/assertions/run.d.ts +3 -2
  40. package/dist/src/evals/assertions/run.js +2 -2
  41. package/dist/src/evals/index.d.ts +1 -1
  42. package/dist/src/evals/loaders/yaml.js +1 -1
  43. package/dist/src/evals/match.d.ts +11 -6
  44. package/dist/src/execution/sandbox/bindings/microsandbox-network.js +1 -1
  45. package/dist/src/internal/application/package.js +1 -1
  46. package/dist/src/internal/authored-module-loader.d.ts +14 -0
  47. package/dist/src/internal/authored-module-loader.js +2 -2
  48. package/dist/src/internal/authored-module-map-loader.js +1 -1
  49. package/dist/src/internal/bundler/extension-scope-plugin.d.ts +37 -0
  50. package/dist/src/internal/bundler/extension-scope-plugin.js +3 -0
  51. package/dist/src/internal/helpers/gray-matter.d.ts +25 -0
  52. package/dist/src/internal/helpers/gray-matter.js +1 -0
  53. package/dist/src/internal/helpers/markdown.js +1 -1
  54. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  55. package/dist/src/internal/nitro/host/build-application.js +1 -1
  56. package/dist/src/internal/nitro/host/build-extension.d.ts +24 -0
  57. package/dist/src/internal/nitro/host/build-extension.js +4 -0
  58. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  59. package/dist/src/internal/workflow-bundle/eve-service-route-output.d.ts +1 -2
  60. package/dist/src/internal/workflow-bundle/eve-service-route-output.js +1 -54
  61. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  62. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  63. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  64. package/dist/src/public/channels/slack/api.js +1 -1
  65. package/dist/src/public/channels/slack/mrkdwn.d.ts +0 -2
  66. package/dist/src/public/channels/slack/mrkdwn.js +1 -1
  67. package/dist/src/public/definitions/extension.d.ts +68 -0
  68. package/dist/src/public/definitions/extension.js +1 -0
  69. package/dist/src/public/definitions/remote-agent.d.ts +11 -2
  70. package/dist/src/public/extension/index.d.ts +10 -0
  71. package/dist/src/public/extension/index.js +1 -0
  72. package/dist/src/public/index.d.ts +1 -1
  73. package/dist/src/public/next/index.d.ts +38 -3
  74. package/dist/src/public/next/index.js +1 -1
  75. package/dist/src/public/next/server.d.ts +1 -0
  76. package/dist/src/public/next/server.js +2 -1
  77. package/dist/src/public/next/vercel-output-config.d.ts +12 -3
  78. package/dist/src/public/next/vercel-output-config.js +1 -1
  79. package/dist/src/react/use-eve-agent.d.ts +8 -1
  80. package/dist/src/react/use-eve-agent.js +1 -1
  81. package/dist/src/runtime/connections/openapi-client.js +1 -1
  82. package/dist/src/runtime/connections/openapi-spec.js +1 -1
  83. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  84. package/dist/src/runtime/resolve-dynamic-skill.js +1 -1
  85. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  86. package/dist/src/runtime/types.d.ts +10 -0
  87. package/dist/src/services/dev-client/vercel-auth-error.d.ts +2 -2
  88. package/dist/src/services/dev-client/vercel-auth-error.js +3 -3
  89. package/dist/src/setup/scaffold/connections/catalog.js +1 -1
  90. package/dist/src/setup/scaffold/create/project.js +3 -3
  91. package/dist/src/svelte/index.js +1 -1
  92. package/dist/src/svelte/use-eve-agent.d.ts +8 -1
  93. package/dist/src/svelte/use-eve-agent.js +1 -1
  94. package/dist/src/vue/index.js +1 -1
  95. package/dist/src/vue/use-eve-agent.d.ts +8 -1
  96. package/dist/src/vue/use-eve-agent.js +1 -1
  97. package/docs/channels/custom.mdx +2 -2
  98. package/docs/channels/linear.mdx +1 -1
  99. package/docs/channels/slack.mdx +2 -0
  100. package/docs/concepts/context-control.md +1 -1
  101. package/docs/connections/openapi.mdx +3 -1
  102. package/docs/evals/assertions.mdx +4 -2
  103. package/docs/extensions.md +176 -0
  104. package/docs/guides/client/overview.mdx +1 -1
  105. package/docs/guides/dev-tui.md +4 -0
  106. package/docs/guides/dynamic-capabilities.md +3 -3
  107. package/docs/guides/frontend/nextjs.mdx +32 -7
  108. package/docs/guides/frontend/overview.mdx +7 -1
  109. package/docs/guides/hooks.md +9 -0
  110. package/docs/guides/instrumentation.md +1 -1
  111. package/docs/guides/remote-agents.md +23 -8
  112. package/docs/guides/state.md +3 -3
  113. package/docs/instructions.mdx +1 -1
  114. package/docs/patterns/dynamic-scheduling.md +11 -11
  115. package/docs/patterns/multi-tenant-approvals.md +6 -6
  116. package/docs/patterns/multi-tenant-auth.md +13 -13
  117. package/docs/patterns/multi-tenant-memory.md +9 -9
  118. package/docs/schedules.mdx +1 -1
  119. package/docs/tutorial/guard-the-spend.mdx +2 -2
  120. package/docs/tutorial/query-sample-data.mdx +1 -1
  121. package/docs/tutorial/remember-definitions.mdx +2 -2
  122. package/docs/tutorial/ship-it.mdx +1 -1
  123. package/package.json +6 -1
@@ -1 +1 @@
1
- import{dirname,join,relative}from"node:path";import{mkdir,readFile,writeFile}from"node:fs/promises";import{findClosestLinkedVercelDirectory,findClosestVercelOutputDirectory}from"#shared/vercel-output-directory.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,VERCEL_OUTPUT_CONFIG_FILE_NAME=`.vercel/output/config.json`,EVE_SERVICE_ROUTE_SRC=`^/eve/v1/(.*)$`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasServices(e){return e!==void 0&&Object.keys(e).length>0}function resolveRelativeEntrypoint(e,t){let r=relative(e,t);return r.length===0?`.`:r.replaceAll(`\\`,`/`)}async function resolveVercelOutputConfigLocation(n){let r=await findClosestLinkedVercelDirectory(n),i=r===void 0?n:dirname(r),a=await findClosestVercelOutputDirectory(n);return a===void 0?r===void 0?{canWriteGeneratedOutput:!!process.env.VERCEL,outputConfigPath:join(n,VERCEL_OUTPUT_CONFIG_FILE_NAME),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(r,`output`,`config.json`),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(a,`config.json`),projectRoot:i}}function normalizeVercelServicesConfig(e,t){if(!isRecord(e))throw Error(`${t} must contain a JSON object.`);let n=e.services;if(n!==void 0&&!isRecord(n))throw Error(`${t} services must be a JSON object.`);let r=e.routes;if(r!==void 0&&!Array.isArray(r))throw Error(`${t} routes must be an array.`);return e}async function readVercelServicesConfig(e,t){try{return normalizeVercelServicesConfig(JSON.parse(await readFile(e,`utf8`)),t)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findServiceByFramework(e,t){return findServiceEntryByFramework(e,t)?.service}function findServiceEntryByFramework(e,t){return Object.entries(e).map(([e,t])=>({name:e,service:t})).find(e=>e.service.framework===t)}function resolveServicePrefix(e){if(e!==void 0){if(typeof e.routePrefix==`string`&&e.routePrefix.trim().length>0)return e.routePrefix.trim();if(typeof e.mount==`string`&&e.mount.trim().length>0)return e.mount.trim();if(isRecord(e.mount)&&typeof e.mount.path==`string`&&e.mount.path.trim().length>0)return e.mount.path.trim()}}function resolveConfiguredServicePrefix(e){return resolveServicePrefix(findServiceByFramework(e.services,`eve`))??e.servicePrefix}function assertRootServicesIncludeEve(e){let t=findServiceByFramework(e.services,`eve`);if(t!==void 0)return resolveServicePrefix(t)??e.servicePrefix;throw Error(`${VERCEL_JSON_FILE_NAME} already defines services, so withEve cannot add a generated eve service through ${VERCEL_OUTPUT_CONFIG_FILE_NAME}. Add the eve service to ${VERCEL_JSON_FILE_NAME}, or remove services from ${VERCEL_JSON_FILE_NAME}.`)}function isEveServiceRoute(e,t){let n=e.destination;return e.src===EVE_SERVICE_ROUTE_SRC&&isRecord(n)&&n.type===`service`&&n.service===t}function createEveServiceRoute(e){return{destination:{service:e,type:`service`},src:EVE_SERVICE_ROUTE_SRC}}function insertEveServiceRoute(e,t){let n=e.find(e=>isEveServiceRoute(e,t)),r=e.filter(e=>!isEveServiceRoute(e,t)),i=r.findIndex(e=>e.handle===`filesystem`),a=n??createEveServiceRoute(t);return i===-1?[a,...r]:[...r.slice(0,i),a,...r.slice(i)]}async function ensureEveVercelOutputConfig(n){let{canWriteGeneratedOutput:i,outputConfigPath:o,projectRoot:s}=await resolveVercelOutputConfigLocation(n.nextRoot),c=(await readVercelServicesConfig(join(s,VERCEL_JSON_FILE_NAME),VERCEL_JSON_FILE_NAME)).services;if(hasServices(c))return{servicePrefix:assertRootServicesIncludeEve({services:c,servicePrefix:n.servicePrefix})};let l=await readVercelServicesConfig(o,VERCEL_OUTPUT_CONFIG_FILE_NAME),u=resolveRelativeEntrypoint(n.nextRoot,n.appRoot),d=l.services??{},f=findServiceEntryByFramework(d,`eve`),p=resolveConfiguredServicePrefix({services:d,servicePrefix:n.servicePrefix});if(!i)return{servicePrefix:p};let m={...d},h=f?.name??`eve`;f===void 0&&(m.eve={buildCommand:n.eveBuildCommand,entrypoint:`package.json`,framework:`eve`,root:u},h=`eve`);let{services:g,..._}=l,v={..._,routes:insertEveServiceRoute(l.routes??[],h),services:m,version:3};return JSON.stringify(l)!==JSON.stringify(v)&&(await mkdir(dirname(o),{recursive:!0}),await writeFile(o,`${JSON.stringify(v,null,2)}\n`)),{servicePrefix:p}}export{ensureEveVercelOutputConfig};
1
+ import{dirname,join,relative}from"node:path";import{mkdir,readFile,writeFile}from"node:fs/promises";import{findClosestLinkedVercelDirectory,findClosestVercelOutputDirectory}from"#shared/vercel-output-directory.js";const VERCEL_JSON_FILE_NAME=`vercel.json`,VERCEL_OUTPUT_CONFIG_FILE_NAME=`.vercel/output/config.json`;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasServices(e){return e!==void 0&&Object.keys(createServiceConfigRecord(e)).length>0}function isNamedServiceConfigArray(e){return Array.isArray(e)}function createServiceConfigRecord(e){if(e===void 0)return{};if(isNamedServiceConfigArray(e)){let t={};for(let n of e)if(typeof n.name==`string`&&n.name.trim().length>0){let{name:e,...r}=n;t[e]=r}return t}return e}function resolveRelativeEntrypoint(e,t){let r=relative(e,t);return r.length===0?`.`:r.replaceAll(`\\`,`/`)}async function resolveVercelOutputConfigLocation(n){let r=await findClosestLinkedVercelDirectory(n),i=r===void 0?n:dirname(r),a=await findClosestVercelOutputDirectory(n);return a===void 0?r===void 0?{canWriteGeneratedOutput:!!process.env.VERCEL,outputConfigPath:join(n,VERCEL_OUTPUT_CONFIG_FILE_NAME),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(r,`output`,`config.json`),projectRoot:i}:{canWriteGeneratedOutput:!0,outputConfigPath:join(a,`config.json`),projectRoot:i}}function normalizeVercelServicesConfig(e,t){if(!isRecord(e))throw Error(`${t} must contain a JSON object.`);let n=e.services;if(n!==void 0&&!isRecord(n)&&!(Array.isArray(n)&&n.every(e=>isRecord(e)&&typeof e.name==`string`&&e.name.trim().length>0)))throw Error(`${t} services must be a JSON object or named service array.`);let r=e.routes;if(r!==void 0&&!Array.isArray(r))throw Error(`${t} routes must be an array.`);return e}async function readVercelServicesConfig(e,t){try{return normalizeVercelServicesConfig(JSON.parse(await readFile(e,`utf8`)),t)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}}function findServiceEntryByFramework(e,t){return Object.entries(e).map(([e,t])=>({name:e,service:t})).find(e=>e.service.framework===t)}function findServiceEntryByName(e,t){let n=e[t];return n===void 0?void 0:{name:t,service:n}}function resolveServicePrefix(e){if(e!==void 0){if(typeof e.routePrefix==`string`&&e.routePrefix.trim().length>0)return e.routePrefix.trim();if(typeof e.mount==`string`&&e.mount.trim().length>0)return e.mount.trim();if(isRecord(e.mount)&&typeof e.mount.path==`string`&&e.mount.path.trim().length>0)return e.mount.path.trim()}}function resolveConfiguredServicePrefix(e){let t=findConfiguredEveServiceEntry(e.services,e.agent)?.service;return resolveServicePrefix(t)??e.agent.servicePrefix}function findConfiguredEveServiceEntry(e,t){if(t.name!==void 0){let n=findServiceEntryByName(e,createEveServiceName(t.name));if(n?.service.framework===`eve`)return n}return t.name===void 0?findServiceEntryByFramework(e,`eve`):void 0}function assertRootServicesIncludeEve(e){let t=[];for(let n of e.agents){let r=findConfiguredEveServiceEntry(e.services,n)?.service;if(r===void 0)throw Error(`${VERCEL_JSON_FILE_NAME} already defines services, so withEve cannot add generated eve services through ${VERCEL_OUTPUT_CONFIG_FILE_NAME}. Add the eve service for ${n.name??`the default agent`} to ${VERCEL_JSON_FILE_NAME}, or remove services from ${VERCEL_JSON_FILE_NAME}.`);t.push({name:n.name,servicePrefix:resolveServicePrefix(r)??n.servicePrefix})}return t}function createEveServiceRouteSrc(e){return e.length===0?`^/eve/v1/(.*)$`:`^${escapeRegExp(e.startsWith(`/`)?e:`/${e}`)}/eve/v1/(.*)$`}function escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function createEveServiceName(e){return e===void 0?`eve`:`eve-${e}`}function isEveServiceRoute(e,t,n){let r=e.destination;return e.src===n&&isRecord(r)&&r.type===`service`&&r.service===t}function createEveServiceRoute(e,t){return{destination:{service:e,type:`service`},src:t}}function isEveServiceRequestPathRoute(e,t){return e.src===t}function createEveServiceRequestPathRoute(e){return{src:e,transforms:[{args:`/eve/v1/$1`,op:`set`,type:`request.path`}]}}function insertEveServiceRequestPathRoute(e,t){let n=(e??[]).filter(e=>!isEveServiceRequestPathRoute(e,t));return[createEveServiceRequestPathRoute(t),...n]}function insertEveServiceRoutes(e,t){let n=e.filter(e=>!t.some(t=>isEveServiceRoute(e,t.serviceName,t.routeSrc))),r=n.findIndex(e=>e.handle===`filesystem`),i=t.map(e=>createEveServiceRoute(e.serviceName,e.routeSrc));return r===-1?[...i,...n]:[...n.slice(0,r),...i,...n.slice(r)]}async function ensureEveVercelOutputConfig(n){let{canWriteGeneratedOutput:i,outputConfigPath:o,projectRoot:s}=await resolveVercelOutputConfigLocation(n.nextRoot),c=(await readVercelServicesConfig(join(s,VERCEL_JSON_FILE_NAME),VERCEL_JSON_FILE_NAME)).services;if(hasServices(c))return{agents:assertRootServicesIncludeEve({agents:n.agents,services:createServiceConfigRecord(c)})};let l=await readVercelServicesConfig(o,VERCEL_OUTPUT_CONFIG_FILE_NAME),u=createServiceConfigRecord(l.services),d=n.agents.map(e=>({name:e.name,servicePrefix:resolveConfiguredServicePrefix({agent:e,services:u})}));if(!i)return{agents:d};let f={...u},p=[];for(let e of n.agents){let t=findConfiguredEveServiceEntry(u,e),r=t?.name??createEveServiceName(e.name),i=createEveServiceRouteSrc(e.publicRoutePrefix);if(t===void 0){let t={buildCommand:e.buildCommand,framework:`eve`,routes:insertEveServiceRequestPathRoute(void 0,i),root:resolveRelativeEntrypoint(n.nextRoot,e.appRoot)};e.publicRoutePrefix.length>0&&(t.routePrefix=e.publicRoutePrefix),f[r]=t}else f[r]={...t.service,routes:insertEveServiceRequestPathRoute(t.service.routes,i)};p.push({routeSrc:i,serviceName:r})}let{services:m,...h}=l,g={...h,routes:insertEveServiceRoutes(l.routes??[],p),services:f,version:3};return JSON.stringify(l)!==JSON.stringify(g)&&(await mkdir(dirname(o),{recursive:!0}),await writeFile(o,`${JSON.stringify(g,null,2)}\n`)),{agents:d}}export{ensureEveVercelOutputConfig};
@@ -42,10 +42,17 @@ export interface UseEveAgentHelpers<TData> extends UseEveAgentSnapshot<TData> {
42
42
  * values to `auth` or `headers`; the client resolves those before each request.
43
43
  */
44
44
  export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData> {
45
+ /**
46
+ * Named agent mounted by a framework integration such as `withEve({ agents })`.
47
+ *
48
+ * `agent: "support"` targets same-origin routes under
49
+ * `/eve/agents/support/eve/v1/...`. Do not combine with `host`.
50
+ */
51
+ readonly agent?: string;
45
52
  readonly auth?: ClientAuth;
46
53
  readonly headers?: HeadersValue;
47
54
  /**
48
- * Base URL for eve client requests.
55
+ * Base URL for eve client requests. Do not combine with `agent`.
49
56
  *
50
57
  * Defaults to same-origin eve routes such as `/eve/v1/...`. Pass a same-origin
51
58
  * prefix such as `/api` for an app-owned proxy, or an absolute origin to talk
@@ -1 +1 @@
1
- import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useCallback,useMemo,useRef,useSyncExternalStore}from"react";function useEveAgent(n={}){let r=useRef(void 0);if(!r.current){let t=n.reducer??defaultMessageReducer();r.current=new EveAgentStore({auth:n.auth,headers:n.headers,host:n.host,initialEvents:n.initialEvents,initialSession:n.initialSession,maxReconnectAttempts:n.maxReconnectAttempts,optimistic:n.optimistic,reducer:t,session:n.session})}let i=r.current;i.setCallbacks({onError:n.onError,onEvent:n.onEvent,onFinish:n.onFinish,onSessionChange:n.onSessionChange,prepareSend:n.prepareSend});let a=useSyncExternalStore(useCallback(e=>i.subscribe(e),[i]),()=>i.snapshot,()=>i.snapshot),o=useCallback(()=>i.reset(),[i]),s=useCallback(e=>i.send(e),[i]),c=useCallback(()=>i.stop(),[i]);return useMemo(()=>({...a,reset:o,send:s,stop:c}),[o,s,a,c])}export{useEveAgent};
1
+ import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{useCallback,useMemo,useRef,useSyncExternalStore}from"react";import{resolveEveAgentHost}from"#client/agent-host.js";function useEveAgent(n={}){let r=useRef(void 0);if(!r.current){let t=n.reducer??defaultMessageReducer();r.current=new EveAgentStore({auth:n.auth,headers:n.headers,host:resolveEveAgentHost({agent:n.agent,host:n.host}),initialEvents:n.initialEvents,initialSession:n.initialSession,maxReconnectAttempts:n.maxReconnectAttempts,optimistic:n.optimistic,reducer:t,session:n.session})}let i=r.current;i.setCallbacks({onError:n.onError,onEvent:n.onEvent,onFinish:n.onFinish,onSessionChange:n.onSessionChange,prepareSend:n.prepareSend});let a=useSyncExternalStore(useCallback(e=>i.subscribe(e),[i]),()=>i.snapshot,()=>i.snapshot),o=useCallback(()=>i.reset(),[i]),s=useCallback(e=>i.send(e),[i]),c=useCallback(()=>i.stop(),[i]);return useMemo(()=>({...a,reset:o,send:s,stop:c}),[o,s,a,c])}export{useEveAgent};
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{jsonSchema,tool}from"ai";import{passesToolFilter,resolveHeaders}from"#runtime/connections/mcp-client.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async getTools(){return(await this.#r()).tools}async executeTool(t,n,r){let i=await this.#r(),a=i.operations.get(t);if(a===void 0)throw Error(`Tool "${t}" not found in connection "${this.#n.connectionName}".`);return this.#f(a,i.baseUrl,isObject(n)?n:{},{abortSignal:r?.abortSignal})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let i=await this.#o(),a=this.#a(i),o=this.#s(i),s=this.#n.tools,c=s===void 0?o:o.filter(e=>passesToolFilter(e.toolName,s)),l=[],u=new Map,d={};for(let r of c)u.set(r.toolName,r),l.push({description:r.description,inputSchema:r.inputSchema,name:r.toolName}),d[r.toolName]=tool({description:r.description,inputSchema:jsonSchema(r.inputSchema),execute:async(t,n)=>this.#f(r,a,isObject(t)?t:{},{abortSignal:n?.abortSignal})});return{metadata:l,operations:u,tools:d,baseUrl:a}}#a(e){let t=this.#n.url;if(typeof t==`string`&&t.trim().length>0)return t;let n=extractServerUrl(e,this.#n.spec);if(n!==void 0)return n;throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`)}async#o(){let t=this.#n.spec;if(t===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof t!=`string`)return t;let n;try{n=await fetch(t,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(e){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${t}": ${String(e)}`)}if(!n.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${t}": HTTP ${n.status}.`);let r=await n.text(),i;try{i=parseSpecDocument(r)}catch(e){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${t}" could not be parsed as JSON or YAML: ${String(e)}`)}if(!isObject(i))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${t}" is not an OpenAPI document object.`);return i}#s(t){let n=t.paths;if(!isObject(n))return[];let r=[],i=new Set;for(let[u,d]of Object.entries(n)){if(!isObject(d))continue;let n=isArray(d.parameters)?d.parameters:[];for(let f of HTTP_METHODS){let a=d[f];if(!isObject(a))continue;let p=uniqueName(operationName(a,f,u),i),m=isArray(a.parameters)?a.parameters:[],h=[...n,...m],g=this.#c(t,h),_=this.#l(t,a.requestBody,h);r.push({toolName:p,method:f,pathTemplate:u,description:operationDescription(a),parameters:g,requestBody:_,inputSchema:buildInputSchema(g,_),security:resolveSecurity(t,a)})}}return r}#c(t,n){let r=[];for(let i of n){let n=isObject(i)?deref(t,i):i;if(!isObject(n))continue;let a=n.in;if(a!==`path`&&a!==`query`&&a!==`header`&&a!==`cookie`||typeof n.name!=`string`)continue;let o=this.#u(t,n);r.push({name:n.name,location:a,required:n.required===!0||a===`path`,schema:o,description:typeof n.description==`string`?n.description:void 0})}return r}#l(t,n,r=[]){if(isObject(n)){let r=deref(t,n);if(isObject(r)&&isObject(r.content)){let n=r.content,i=`application/json`in n?`application/json`:Object.keys(n)[0];if(i!==void 0){let a=n[i],o=isObject(a)&&isObject(a.schema)?derefSchema(t,a.schema):{};return{required:r.required===!0,contentType:i,schema:o}}}}return this.#d(t,r)}#u(t,n){if(isObject(n.schema))return derefSchema(t,n.schema);let r={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)n[e]!==void 0&&(r[e]=n[e]);return derefSchema(t,r)}#d(t,n){for(let r of n){let n=isObject(r)?deref(t,r):r;if(!isObject(n)||n.in!==`body`)continue;let i=isObject(n.schema)?derefSchema(t,n.schema):{};return{required:n.required===!0,contentType:`application/json`,schema:i}}}async#f(e,t,n,r){let a=await resolveHeaders(this.#n),o=e.pathTemplate,s=new URLSearchParams,c=[];for(let t of e.parameters){let e=n[t.name];e!=null&&(t.location===`path`?o=o.replace(`{${t.name}}`,encodeURIComponent(String(e))):t.location===`query`?appendQuery(s,t.name,e):t.location===`cookie`?c.push(`${t.name}=${encodeURIComponent(String(e))}`):a[t.name]=String(e))}if(applySecurity(e.security,this.#n,a,s,c),c.length>0){let e=a.cookie??a.Cookie;delete a.Cookie,a.cookie=[e,...c].filter(e=>!!e).join(`; `)}let l=new URL(joinPath(t,o));l.search=s.toString();let u;e.requestBody!==void 0&&n.body!==void 0&&(u=JSON.stringify(n.body),a[`content-type`]=e.requestBody.contentType);let d=await fetch(l,{method:e.method.toUpperCase(),headers:a,body:u,signal:r?.abortSignal});return{status:d.status,statusText:d.statusText,body:await readResponseBody(d)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
1
+ import{isLoopbackHostname}from"#shared/network-address.js";import{isObject}from"#shared/guards.js";import{jsonSchema,tool}from"ai";import{passesToolFilter,resolveHeaders}from"#runtime/connections/mcp-client.js";import{HTTP_METHODS,operationDescription,operationName,uniqueName}from"#runtime/connections/openapi-operations.js";import{buildInputSchema,deref,derefSchema,isArray}from"#runtime/connections/openapi-schema.js";import{applySecurity,resolveSecurity}from"#runtime/connections/openapi-security.js";import{extractServerUrl,parseSpecDocument}from"#runtime/connections/openapi-spec.js";const SWAGGER_PARAMETER_SCHEMA_KEYS=[`default`,`enum`,`exclusiveMaximum`,`exclusiveMinimum`,`format`,`items`,`maximum`,`maxItems`,`maxLength`,`minimum`,`minItems`,`minLength`,`multipleOf`,`pattern`,`type`,`uniqueItems`];var OpenApiConnectionClient=class{#e;#t;#n;constructor(e){this.#n=e}async connect(){return this.#r()}async getToolMetadata(){return(await this.#r()).metadata}async getTools(){return(await this.#r()).tools}async executeTool(e,n,r){let i=await this.#r(),a=i.operations.get(e);if(a===void 0)throw Error(`Tool "${e}" not found in connection "${this.#n.connectionName}".`);return this.#f(a,i.baseUrl,isObject(n)?n:{},{abortSignal:r?.abortSignal})}async close(){this.#e=void 0,this.#t=void 0}async#r(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#i();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#i(){let e=await this.#o(),a=this.#a(e),o=this.#s(e),s=this.#n.tools,c=s===void 0?o:o.filter(e=>passesToolFilter(e.toolName,s)),l=[],u=new Map,d={};for(let e of c)u.set(e.toolName,e),l.push({description:e.description,inputSchema:e.inputSchema,name:e.toolName}),d[e.toolName]=tool({description:e.description,inputSchema:jsonSchema(e.inputSchema),execute:async(n,r)=>this.#f(e,a,isObject(n)?n:{},{abortSignal:r?.abortSignal})});return{metadata:l,operations:u,tools:d,baseUrl:a}}#a(e){let t=this.#n.url,n=typeof t==`string`&&t.trim().length>0?t:extractServerUrl(e,this.#n.spec);if(n===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" has no base URL: set "baseUrl" or ensure the document declares an absolute "servers" entry or Swagger "host".`);return assertSecureUrl(n,this.#n.connectionName,`base`),n}async#o(){let e=this.#n.spec;if(e===void 0)throw Error(`OpenAPI connection "${this.#n.connectionName}" is missing its "spec" source.`);if(typeof e!=`string`)return e;assertSecureUrl(e,this.#n.connectionName,`spec`);let n;try{n=await fetch(e,{headers:{accept:`application/json, application/yaml, text/yaml, */*`}})}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": ${String(t)}`)}if(n.redirected&&assertSecureUrl(n.url,this.#n.connectionName,`spec`),!n.ok)throw Error(`OpenAPI connection "${this.#n.connectionName}" failed to fetch its spec from "${e}": HTTP ${n.status}.`);let r=await n.text(),i;try{i=parseSpecDocument(r)}catch(t){throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" could not be parsed as JSON or YAML: ${String(t)}`)}if(!isObject(i))throw Error(`OpenAPI connection "${this.#n.connectionName}" spec at "${e}" is not an OpenAPI document object.`);return i}#s(e){let n=e.paths;if(!isObject(n))return[];let r=[],i=new Set;for(let[a,d]of Object.entries(n)){if(!isObject(d))continue;let n=isArray(d.parameters)?d.parameters:[];for(let f of HTTP_METHODS){let o=d[f];if(!isObject(o))continue;let p=uniqueName(operationName(o,f,a),i),m=isArray(o.parameters)?o.parameters:[],h=[...n,...m],g=this.#c(e,h),_=this.#l(e,o.requestBody,h);r.push({toolName:p,method:f,pathTemplate:a,description:operationDescription(o),parameters:g,requestBody:_,inputSchema:buildInputSchema(g,_),security:resolveSecurity(e,o)})}}return r}#c(e,n){let r=[];for(let i of n){let n=isObject(i)?deref(e,i):i;if(!isObject(n))continue;let a=n.in;if(a!==`path`&&a!==`query`&&a!==`header`&&a!==`cookie`||typeof n.name!=`string`)continue;let o=this.#u(e,n);r.push({name:n.name,location:a,required:n.required===!0||a===`path`,schema:o,description:typeof n.description==`string`?n.description:void 0})}return r}#l(e,n,r=[]){if(isObject(n)){let r=deref(e,n);if(isObject(r)&&isObject(r.content)){let n=r.content,i=`application/json`in n?`application/json`:Object.keys(n)[0];if(i!==void 0){let a=n[i],o=isObject(a)&&isObject(a.schema)?derefSchema(e,a.schema):{};return{required:r.required===!0,contentType:i,schema:o}}}}return this.#d(e,r)}#u(e,n){if(isObject(n.schema))return derefSchema(e,n.schema);let r={};for(let e of SWAGGER_PARAMETER_SCHEMA_KEYS)n[e]!==void 0&&(r[e]=n[e]);return derefSchema(e,r)}#d(e,n){for(let r of n){let n=isObject(r)?deref(e,r):r;if(!isObject(n)||n.in!==`body`)continue;let i=isObject(n.schema)?derefSchema(e,n.schema):{};return{required:n.required===!0,contentType:`application/json`,schema:i}}}async#f(e,t,n,r){let i=await resolveHeaders(this.#n),o=e.pathTemplate,s=new URLSearchParams,c=[];for(let t of e.parameters){let e=n[t.name];e!=null&&(t.location===`path`?o=o.replace(`{${t.name}}`,encodeURIComponent(String(e))):t.location===`query`?appendQuery(s,t.name,e):t.location===`cookie`?c.push(`${t.name}=${encodeURIComponent(String(e))}`):i[t.name]=String(e))}if(applySecurity(e.security,this.#n,i,s,c),c.length>0){let e=i.cookie??i.Cookie;delete i.Cookie,i.cookie=[e,...c].filter(e=>!!e).join(`; `)}let l=new URL(joinPath(t,o));l.search=s.toString();let u;e.requestBody!==void 0&&n.body!==void 0&&(u=JSON.stringify(n.body),i[`content-type`]=e.requestBody.contentType);let d=await fetch(l,{method:e.method.toUpperCase(),headers:i,body:u,signal:r?.abortSignal});return{status:d.status,statusText:d.statusText,body:await readResponseBody(d)}}};function appendQuery(e,t,n){if(isArray(n)){for(let r of n)e.append(t,String(r));return}e.append(t,String(n))}function joinPath(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function assertSecureUrl(t,n,r){let i;try{i=new URL(t)}catch{throw Error(`OpenAPI connection "${n}" has an invalid ${r} URL "${t}".`)}if(i.protocol!==`https:`&&!(i.protocol===`http:`&&isLoopbackHostname(i.hostname)))throw Error(`OpenAPI connection "${n}" must use https for its ${r} (got "${i.protocol}//${i.host}").`)}async function readResponseBody(e){let t=await e.text();if(t.length===0)return null;if((e.headers.get(`content-type`)??``).includes(`application/json`))try{return JSON.parse(t)}catch{return t}return t}export{OpenApiConnectionClient};
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import matter from"#compiled/gray-matter/index.js";import{isArray}from"#runtime/connections/openapi-schema.js";function parseSpecDocument(e){try{return JSON.parse(e)}catch{}let n=e.replace(/^\uFEFF/,``);return matter(n.trimStart().startsWith(`---`)?n:`---\n${n}\n---`).data??{}}function extractServerUrl(e,t){let n=extractOpenApiServerUrl(e,t);return n===void 0?extractSwaggerBaseUrl(e,t):n}function extractOpenApiServerUrl(t,r){let i=t.servers;if(isArray(i))for(let t of i){if(!isObject(t)||typeof t.url!=`string`||t.url.length===0)continue;let n=isObject(t.variables)?substituteServerVariables(t.url,t.variables):t.url;if(n.startsWith(`http://`)||n.startsWith(`https://`))return n;if(typeof r==`string`&&URL.canParse(r))try{return new URL(n,r).toString()}catch{}}}function extractSwaggerBaseUrl(e,t){let n=typeof e.basePath==`string`?e.basePath:``,r=typeof e.host==`string`&&e.host.length>0?e.host:``,i=typeof t==`string`&&URL.canParse(t)?new URL(t):void 0,a=extractSwaggerScheme(e)??i?.protocol.replace(/:$/,``)??`https`;if(r.length>0)return`${a}://${r}${normalizeBasePath(n)}`;if(i!==void 0){let e=new URL(normalizeBasePath(n)||`/`,i.origin).toString();return e.endsWith(`/`)&&normalizeBasePath(n).length===0?e.slice(0,-1):e}}function extractSwaggerScheme(e){let t=e.schemes;if(isArray(t)){for(let e of t)if(e===`https`||e===`http`)return e}}function normalizeBasePath(e){let t=e.trim();return t.length===0||t===`/`?``:t.startsWith(`/`)?t:`/${t}`}function substituteServerVariables(t,n){return t.replace(/\{([^}]+)\}/g,(t,r)=>{let i=n[r];return isObject(i)&&typeof i.default==`string`?i.default:t})}export{extractServerUrl,parseSpecDocument};
1
+ import{isObject}from"#shared/guards.js";import{parseFrontmatter}from"#internal/helpers/gray-matter.js";import{isArray}from"#runtime/connections/openapi-schema.js";function parseSpecDocument(e){try{return JSON.parse(e)}catch{}let n=e.replace(/^\uFEFF/,``);return parseFrontmatter(n.trimStart().startsWith(`---`)?n:`---\n${n}\n---`).data}function extractServerUrl(e,t){let n=extractOpenApiServerUrl(e,t);return n===void 0?extractSwaggerBaseUrl(e,t):n}function extractOpenApiServerUrl(t,r){let i=t.servers;if(isArray(i))for(let t of i){if(!isObject(t)||typeof t.url!=`string`||t.url.length===0)continue;let n=isObject(t.variables)?substituteServerVariables(t.url,t.variables):t.url;if(n.startsWith(`http://`)||n.startsWith(`https://`))return n;if(typeof r==`string`&&URL.canParse(r))try{return new URL(n,r).toString()}catch{}}}function extractSwaggerBaseUrl(e,t){let n=typeof e.basePath==`string`?e.basePath:``,r=typeof e.host==`string`&&e.host.length>0?e.host:``,i=typeof t==`string`&&URL.canParse(t)?new URL(t):void 0,a=extractSwaggerScheme(e)??i?.protocol.replace(/:$/,``)??`https`;if(r.length>0)return`${a}://${r}${normalizeBasePath(n)}`;if(i!==void 0){let e=new URL(normalizeBasePath(n)||`/`,i.origin).toString();return e.endsWith(`/`)&&normalizeBasePath(n).length===0?e.slice(0,-1):e}}function extractSwaggerScheme(e){let t=e.schemes;if(isArray(t)){for(let e of t)if(e===`https`||e===`http`)return e}}function normalizeBasePath(e){let t=e.trim();return t.length===0||t===`/`?``:t.startsWith(`/`)?t:`/${t}`}function substituteServerVariables(t,n){return t.replace(/\{([^}]+)\}/g,(t,r)=>{let i=n[r];return isObject(i)&&typeof i.default==`string`?i.default:t})}export{extractServerUrl,parseSpecDocument};
@@ -1 +1 @@
1
- import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{WORKFLOW_TOOL_NAME}from"#shared/workflow-sandbox.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let a=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),o=a.connections.length>0,s=getFrameworkToolDefinitions({hasConnections:o}),c=new Set(s.map(e=>e.name)),l=getAllFrameworkToolNames(),u=new Set(a.tools.map(e=>e.name));for(let n of a.disabledFrameworkTools)if(!l.has(n))throw new ResolveRuntimeAgentGraphError(`agent/tools/${n}.ts exports disableTool() but "${n}" is not a framework tool. Rename the file to one of: ${[...l].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let d=new Set(a.disabledFrameworkTools),f=await createRuntimeToolRegistry({tools:[...s.filter(e=>!u.has(e.name)&&!d.has(e.name)),...a.tools]},{reservedToolNames:[WORKFLOW_TOOL_NAME,...c.has(LOAD_SKILL_TOOL_NAME)||u.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),p=new Set(a.channels.map(e=>e.name)),m=getAllFrameworkChannelNames();for(let n of a.disabledFrameworkChannels)if(!m.has(n))throw new ResolveRuntimeAgentGraphError(`agent/channels/${n}.ts exports disableRoute() but "${n}" is not a framework channel. Rename the file to one of: ${[...m].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let h=new Set(a.disabledFrameworkChannels),g=[...getFrameworkChannelDefinitions().filter(e=>!p.has(e.name)&&!h.has(e.name)),...a.channels],_=createRuntimeSandboxRegistry({authoredSandbox:a.sandbox,workspaceResourceRoot:a.workspaceResourceRoot}),v=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...f.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),y=o?{...a,dynamicToolResolvers:[...a.dynamicToolResolvers,createConnectionSearchResolver()]}:a,b={agent:y,channels:g,hookRegistry:createRuntimeHookRegistry(y.hooks),nodeId:t,sandboxRegistry:_,sourceId:e.sourceId,subagentRegistry:v,toolRegistry:f,turnAgent:createResolvedRuntimeTurnAgent({agent:y,nodeId:t,tools:[...f.preparedTools,...v.preparedTools]})};return e.nodesByNodeId.set(t,b),b}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:t.sourceRef.url};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
1
+ import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{WORKFLOW_TOOL_NAME}from"#shared/workflow-sandbox.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let a=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),o=a.connections.length>0,s=getFrameworkToolDefinitions({hasConnections:o}),c=new Set(s.map(e=>e.name)),l=getAllFrameworkToolNames(),u=new Set(a.tools.map(e=>e.name));for(let n of a.disabledFrameworkTools)if(!l.has(n))throw new ResolveRuntimeAgentGraphError(`agent/tools/${n}.ts exports disableTool() but "${n}" is not a framework tool. Rename the file to one of: ${[...l].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let d=new Set(a.disabledFrameworkTools),f=await createRuntimeToolRegistry({tools:[...s.filter(e=>!u.has(e.name)&&!d.has(e.name)),...a.tools]},{reservedToolNames:[WORKFLOW_TOOL_NAME,...c.has(LOAD_SKILL_TOOL_NAME)||u.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),p=new Set(a.channels.map(e=>e.name)),m=getAllFrameworkChannelNames();for(let n of a.disabledFrameworkChannels)if(!m.has(n))throw new ResolveRuntimeAgentGraphError(`agent/channels/${n}.ts exports disableRoute() but "${n}" is not a framework channel. Rename the file to one of: ${[...m].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let h=new Set(a.disabledFrameworkChannels),g=[...getFrameworkChannelDefinitions().filter(e=>!p.has(e.name)&&!h.has(e.name)),...a.channels],_=createRuntimeSandboxRegistry({authoredSandbox:a.sandbox,workspaceResourceRoot:a.workspaceResourceRoot}),v=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...f.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),y=o?{...a,dynamicToolResolvers:[...a.dynamicToolResolvers,createConnectionSearchResolver()]}:a,b={agent:y,channels:g,hookRegistry:createRuntimeHookRegistry(y.hooks),nodeId:t,sandboxRegistry:_,sourceId:e.sourceId,subagentRegistry:v,toolRegistry:f,turnAgent:createResolvedRuntimeTurnAgent({agent:y,nodeId:t,tools:[...f.preparedTools,...v.preparedTools]})};return e.nodesByNodeId.set(t,b),b}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:await resolveRemoteAgentUrl({bakedUrl:t.sourceRef.url,logicalPath:t.sourceRef.logicalPath,resolvedUrl:n.url})};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}async function resolveRemoteAgentUrl(e){if(typeof e.resolvedUrl==`function`){let t=await e.resolvedUrl();if(typeof t!=`string`||t.length===0)throw Error(`Remote agent "${e.logicalPath}" url function must return a non-empty string.`);return t}let t=e.bakedUrl??(typeof e.resolvedUrl==`string`?e.resolvedUrl:``);if(t.length===0)throw Error(`Remote agent "${e.logicalPath}" is missing a url.`);return t}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
@@ -1 +1 @@
1
- import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function resolveDynamicSkillDefinition(i,a,o){try{let n=expectObjectRecord(expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-skill`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)).events,describe(i,`to provide an events object`)),r={};for(let t of i.eventNames)r[t]=expectFunction(n[t],describe(i,`to provide a handler for event "${t}"`));return{eventNames:[...i.eventNames],events:r,exportName:i.exportName,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic skill from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic skill export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicSkillDefinition};
1
+ import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function resolveDynamicSkillDefinition(i,a,o){try{let n=expectObjectRecord(expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-skill`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)).events,describe(i,`to provide an events object`)),r={};for(let t of i.eventNames)r[t]=expectFunction(n[t],describe(i,`to provide a handler for event "${t}"`));return{eventNames:[...i.eventNames],events:r,exportName:i.exportName,extensionNamespace:i.extensionNamespace,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic skill from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic skill export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicSkillDefinition};
@@ -1 +1 @@
1
- import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveDynamicToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r=expectObjectRecord(n.events,describe(i,`to provide an events object`)),s={};for(let t of i.eventNames)s[t]=expectFunction(r[t],describe(i,`to provide a handler for event "${t}"`));let c=`dynamic-tool-source:${i.sourceId}`;return stampDefinitionKey(n,c),registerDefinitionSource(c,{kind:`tool`,logicalPath:i.logicalPath,name:i.slug}),{eventNames:[...i.eventNames],events:s,exportName:i.exportName,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic tool from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicToolDefinition};
1
+ import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveDynamicToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`dynamic-tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r=expectObjectRecord(n.events,describe(i,`to provide an events object`)),s={};for(let t of i.eventNames)s[t]=expectFunction(r[t],describe(i,`to provide a handler for event "${t}"`));let c=`dynamic-tool-source:${i.sourceId}`;return stampDefinitionKey(n,c),registerDefinitionSource(c,{kind:`tool`,logicalPath:i.logicalPath,name:i.slug}),{eventNames:[...i.eventNames],events:s,exportName:i.exportName,extensionNamespace:i.extensionNamespace,logicalPath:i.logicalPath,slug:i.slug,sourceId:i.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to resolve dynamic tool from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function describe(e,t){return`Expected the dynamic tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}export{resolveDynamicToolDefinition};
@@ -278,6 +278,11 @@ export interface ResolvedDynamicToolResolver extends Readonly<ModuleSourceRef> {
278
278
  readonly slug: string;
279
279
  readonly eventNames: readonly string[];
280
280
  readonly events: Readonly<Record<string, (event: unknown, ctx: unknown) => unknown | Promise<unknown>>>;
281
+ /**
282
+ * Mount namespace when this resolver comes from an extension. Names of tools
283
+ * the resolver produces are prefixed with `${extensionNamespace}__`.
284
+ */
285
+ readonly extensionNamespace?: string;
281
286
  }
282
287
  /**
283
288
  * Runtime resolver for dynamic skills declared via `defineDynamic({ events })`
@@ -288,6 +293,11 @@ export interface ResolvedDynamicSkillResolver extends Readonly<ModuleSourceRef>
288
293
  readonly slug: string;
289
294
  readonly eventNames: readonly string[];
290
295
  readonly events: Readonly<Record<string, (event: unknown, ctx: unknown) => unknown | Promise<unknown>>>;
296
+ /**
297
+ * Mount namespace when this resolver comes from an extension. Names of skills
298
+ * a map resolver produces are prefixed with `${extensionNamespace}__`.
299
+ */
300
+ readonly extensionNamespace?: string;
291
301
  }
292
302
  /**
293
303
  * Runtime resolver for dynamic instructions declared via
@@ -17,10 +17,10 @@ import type { DevelopmentOidcTokenFailure } from "#services/dev-client/request-h
17
17
  /** Returns the stable Trusted Sources code embedded in a Vercel error message. */
18
18
  export declare function vercelTrustedSourcesErrorCode(message: string): string | undefined;
19
19
  /**
20
- * Returns `true` for an HTTP 401 carrying Vercel's protection challenge.
20
+ * Returns `true` for a Vercel Deployment Protection challenge.
21
21
  *
22
22
  * Accepts both real {@link ClientError} instances and structurally
23
- * compatible duck-typed errors (`{ status: number, body: string }`)
23
+ * compatible duck-typed errors (`{ status, body, headers }`)
24
24
  * so callers can detect the challenge regardless of whether the
25
25
  * error survived a network/IPC boundary.
26
26
  */
@@ -1,9 +1,9 @@
1
1
  import{isObject}from"#shared/guards.js";import{ClientError}from"#client/client-error.js";const VERCEL_AUTH_CHALLENGE_MARKERS=[`vercel.com/sso-api`,`<title>Authentication Required</title>`],TRUSTED_SOURCES_ERROR_CODE=/^TRUSTED_SOURCES_[A-Z0-9_]+$/u;function vercelTrustedSourcesErrorCode(e){for(let t of e.replaceAll(`\r
2
2
  `,`
3
3
  `).trim().split(`
4
- `)){let e=t.trim();if(TRUSTED_SOURCES_ERROR_CODE.test(e))return e}}function bodyLooksLikeVercelAuthChallenge(e){return e.length>0&&VERCEL_AUTH_CHALLENGE_MARKERS.every(t=>e.includes(t))}function isVercelAuthChallenge(n){return n instanceof ClientError?n.status===401&&bodyLooksLikeVercelAuthChallenge(n.body):isObject(n)&&n.status===401&&typeof n.body==`string`&&bodyLooksLikeVercelAuthChallenge(n.body)}function formatVercelAuthChallengeMessage(e){let t=[`Vercel Deployment Protection blocked the request to ${e.serverUrl}.`];return e.oidcTokenFailure!==void 0&&t.push(``,formatDevelopmentOidcTokenFailure(e.oidcTokenFailure)),t.push(``,"To access the deployment from `eve dev`, do one of:"," • Run `vercel link` in this project so the CLI can mint an OIDC",` token for the deployment automatically.`,` • Set VERCEL_AUTOMATION_BYPASS_SECRET to a Protection Bypass for`,` Automation token (Project Settings → Deployment Protection).`,` • Disable Deployment Protection on the target deployment.`,``,`Docs: https://vercel.com/docs/deployment-protection`),t.join(`
4
+ `)){let e=t.trim();if(TRUSTED_SOURCES_ERROR_CODE.test(e))return e}}function bodyLooksLikeVercelAuthChallenge(e){return e.length>0&&VERCEL_AUTH_CHALLENGE_MARKERS.every(t=>e.includes(t))}function isVercelSsoUrl(e){let t=URL.parse(e);return t?.origin===`https://vercel.com`&&t.pathname===`/sso-api`&&t.searchParams.has(`url`)}function isVercelSsoRedirect(e,t){if(e<300||e>=400||t===void 0)return!1;for(let[e,n]of Object.entries(t))if(e.toLowerCase()===`location`&&typeof n==`string`)return isVercelSsoUrl(n);return!1}function isVercelUnauthorized(e,t){if(e!==401||t===void 0)return!1;for(let[e,n]of Object.entries(t))if(e.toLowerCase()===`x-vercel-error`&&n===`UNAUTHORIZED`)return!0;return!1}function bodyLooksLikeStructuredVercelAuthChallenge(t){let n;try{n=JSON.parse(t)}catch{return!1}if(!isObject(n)||!isObject(n.error)||!isObject(n.protection))return!1;let r=n.error.code,i=n.protection.vercel_auth_callback;return(r===401||r===`401`)&&n.error.message===`Protected deployment`&&typeof i==`string`&&isVercelSsoUrl(i)}function isVercelAuthChallenge(n){let r=n instanceof ClientError||isObject(n)?n:void 0;if(r===void 0||typeof r.status!=`number`||typeof r.body!=`string`)return!1;let i=isObject(r.headers)?r.headers:void 0;return isVercelSsoRedirect(r.status,i)||isVercelUnauthorized(r.status,i)||r.status===401&&(bodyLooksLikeVercelAuthChallenge(r.body)||bodyLooksLikeStructuredVercelAuthChallenge(r.body))}function formatVercelAuthChallengeMessage(e){let t=[`Vercel Deployment Protection blocked the request to ${e.serverUrl}.`];return e.oidcTokenFailure!==void 0&&t.push(``,formatDevelopmentOidcTokenFailure(e.oidcTokenFailure)),t.push(``,"To access the deployment from `eve dev`, do one of:"," • Run `vercel link` in this project so the CLI can mint an OIDC",` token for the deployment automatically.`,` • Set VERCEL_AUTOMATION_BYPASS_SECRET to a Protection Bypass for`,` Automation token (Project Settings → Deployment Protection).`,` • Disable Deployment Protection on the target deployment.`,``,`Docs: https://vercel.com/docs/deployment-protection`),t.join(`
5
5
  `)}function formatDevelopmentOidcTokenFailure(e){switch(e.kind){case`resolution-failed`:return`The local Vercel OIDC token could not be resolved: ${e.message}`;case`malformed-token`:return e.reason===`missing-payload`?`Vercel returned a local OIDC token without a JWT payload.`:`Vercel returned a local OIDC token whose payload is not valid JSON.`;case`invalid-claims`:return`The local Vercel OIDC token has invalid claims: ${e.invalidClaims.join(`, `)}.`;case`target-mismatch`:return`The local Vercel OIDC token does not match the resolved deployment: ${e.mismatchedClaims.join(`, `)}.`;default:return e}}function formatVercelTrustedSourcesFailure(e){let t=e.replaceAll(`\r
6
6
  `,`
7
7
  `).trim().split(`
8
- `),n=t.findIndex(e=>TRUSTED_SOURCES_ERROR_CODE.test(e.trim()));if(n<0)return e;let r=t[n].trim(),i=t.slice(0,n).join(`
9
- `).trim();return i.length===0?e:`${i}\n\n${r}`}export{formatDevelopmentOidcTokenFailure,formatVercelAuthChallengeMessage,formatVercelTrustedSourcesFailure,isVercelAuthChallenge,vercelTrustedSourcesErrorCode};
8
+ `),n=t.findIndex(e=>TRUSTED_SOURCES_ERROR_CODE.test(e.trim()));if(n<0)return e;let i=t[n].trim(),a=t.slice(0,n).join(`
9
+ `).trim();return a.length===0?e:`${a}\n\n${i}`}export{formatDevelopmentOidcTokenFailure,formatVercelAuthChallengeMessage,formatVercelTrustedSourcesFailure,isVercelAuthChallenge,vercelTrustedSourcesErrorCode};
@@ -1 +1 @@
1
- import{connectionEntries,connectionProtocols}from"../../../packages/eve-catalog/src/index.js";const SUPPORTED_PROTOCOLS=[`mcp`],CUSTOM_CONNECTION_SLUG=`custom`,CONNECTION_AUTH={linear:{kind:`connect`,connector:`linear`,service:`mcp.linear.app`},notion:{kind:`connect`,connector:`notion`,service:`mcp.notion.com`},datadog:{kind:`connect`,connector:`datadog`,service:`mcp.datadoghq.com`},honeycomb:{kind:`connect`,connector:`honeycomb`,service:`mcp.honeycomb.io`}};function buildCatalogEntry(e,n,r){let i=CONNECTION_AUTH[e];if(i===void 0)throw Error(`Connection "${e}" is in the catalog but has no scaffolder auth overlay.`);let a={slug:e,label:n,protocols:connectionProtocols(r),description:r.description,auth:i};return r.mcp&&(a.mcp={url:r.mcp.url}),r.openapi&&(a.openapi={spec:r.openapi.spec,baseUrl:r.openapi.baseUrl}),a}const CONNECTION_CATALOG=connectionEntries().map(e=>{if(e.connection===void 0)throw Error(`Catalog connection "${e.slug}" is missing its connection identity.`);return buildCatalogEntry(e.slug,e.name,e.connection)}),CATALOG_BY_SLUG=new Map(CONNECTION_CATALOG.map(e=>[e.slug,e]));function getCatalogEntry(e){return CATALOG_BY_SLUG.get(e)}function catalogSlugs(){return CONNECTION_CATALOG.map(e=>e.slug)}function effectiveProtocols(e){let t=e===void 0||e.length===0?SUPPORTED_PROTOCOLS:e;return SUPPORTED_PROTOCOLS.filter(e=>t.includes(e))}const CONNECTION_SLUG_PATTERN=/^[a-z][a-z0-9-]{0,63}$/;function isValidConnectionSlug(e){return CONNECTION_SLUG_PATTERN.test(e)}function connectorServiceForEntry(e){if(e.auth.kind===`connect`)return e.auth.service?e.auth.service:mcpServiceHost(e.mcp?.url)}function canonicalConnectorNameForEntry(e){if(e.auth?.kind!==`connect`)return;let t=e.auth.connector.trim();return t.length>0?t:void 0}function mcpServiceHost(e){if(e)try{return new URL(e).host||void 0}catch{return}}function endpointForProtocol(e,t){return t===`mcp`?e.mcp??null:e.openapi??null}export{CONNECTION_CATALOG,CUSTOM_CONNECTION_SLUG,SUPPORTED_PROTOCOLS,canonicalConnectorNameForEntry,catalogSlugs,connectorServiceForEntry,effectiveProtocols,endpointForProtocol,getCatalogEntry,isValidConnectionSlug,mcpServiceHost};
1
+ import{connectionEntries,connectionProtocols}from"../../../packages/eve-catalog/src/index.js";const SUPPORTED_PROTOCOLS=[`mcp`],CUSTOM_CONNECTION_SLUG=`custom`,CONNECTION_AUTH={linear:{kind:`connect`,connector:`linear`,service:`mcp.linear.app`},notion:{kind:`connect`,connector:`notion`,service:`mcp.notion.com`},datadog:{kind:`connect`,connector:`datadog`,service:`mcp.datadoghq.com`},honeycomb:{kind:`connect`,connector:`honeycomb`,service:`mcp.honeycomb.io`}};function buildCatalogEntry(e,n,r){let i=CONNECTION_AUTH[e];if(i===void 0)throw Error(`Connection "${e}" is in the catalog but has no scaffolder auth overlay.`);let a={slug:e,label:n,protocols:connectionProtocols(r),description:r.description,auth:i};return r.mcp&&(a.mcp={url:r.mcp.url}),r.openapi&&(a.openapi={spec:r.openapi.spec,baseUrl:r.openapi.baseUrl}),a}const CONNECTION_CATALOG=connectionEntries().filter(e=>e.surfaces.scaffoldable).map(e=>{if(e.connection===void 0)throw Error(`Catalog connection "${e.slug}" is missing its connection identity.`);return buildCatalogEntry(e.slug,e.name,e.connection)}),CATALOG_BY_SLUG=new Map(CONNECTION_CATALOG.map(e=>[e.slug,e]));function getCatalogEntry(e){return CATALOG_BY_SLUG.get(e)}function catalogSlugs(){return CONNECTION_CATALOG.map(e=>e.slug)}function effectiveProtocols(e){let t=e===void 0||e.length===0?SUPPORTED_PROTOCOLS:e;return SUPPORTED_PROTOCOLS.filter(e=>t.includes(e))}const CONNECTION_SLUG_PATTERN=/^[a-z][a-z0-9-]{0,63}$/;function isValidConnectionSlug(e){return CONNECTION_SLUG_PATTERN.test(e)}function connectorServiceForEntry(e){if(e.auth.kind===`connect`)return e.auth.service?e.auth.service:mcpServiceHost(e.mcp?.url)}function canonicalConnectorNameForEntry(e){if(e.auth?.kind!==`connect`)return;let t=e.auth.connector.trim();return t.length>0?t:void 0}function mcpServiceHost(e){if(e)try{return new URL(e).host||void 0}catch{return}}function endpointForProtocol(e,t){return t===`mcp`?e.mcp??null:e.openapi??null}export{CONNECTION_CATALOG,CUSTOM_CONNECTION_SLUG,SUPPORTED_PROTOCOLS,canonicalConnectorNameForEntry,catalogSlugs,connectorServiceForEntry,effectiveProtocols,endpointForProtocol,getCatalogEntry,isValidConnectionSlug,mcpServiceHost};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.22.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){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.22.4`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -44,8 +44,8 @@ You are a helpful assistant.
44
44
  `,SHARED_TEMPLATE_FILES={"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE,"tsconfig.json":`{
45
45
  "compilerOptions": {
46
46
  "target": "ES2022",
47
- "module": "NodeNext",
48
- "moduleResolution": "NodeNext",
47
+ "module": "esnext",
48
+ "moduleResolution": "bundler",
49
49
  "types": ["node"],
50
50
  "strict": true,
51
51
  "esModuleInterop": true,
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CxcKypLZ.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-dEGV09g_.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -51,6 +51,13 @@ export interface UseEveAgentReturn<TData> {
51
51
  * the client resolves before each HTTP request.
52
52
  */
53
53
  export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData> {
54
+ /**
55
+ * Named agent mounted by a framework integration such as `withEve({ agents })`.
56
+ *
57
+ * `agent: "support"` targets same-origin routes under
58
+ * `/eve/agents/support/eve/v1/...`. Do not combine with `host`.
59
+ */
60
+ readonly agent?: string;
54
61
  /**
55
62
  * Credentials for the auto-created session. Pass function values to refresh
56
63
  * per request. Ignored when `session` is supplied.
@@ -62,7 +69,7 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
62
69
  */
63
70
  readonly headers?: HeadersValue;
64
71
  /**
65
- * Base URL for eve client requests. Empty targets same-origin eve routes
72
+ * Base URL for eve client requests. Do not combine with `agent`. Empty targets same-origin eve routes
66
73
  * such as `/eve/v1/...`; a same-origin prefix like `/api` routes through an
67
74
  * app-owned proxy; an absolute origin hits an eve server directly.
68
75
  *
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-CxcKypLZ.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-dEGV09g_.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CM24ZUEI.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CFBTHlPx.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -54,12 +54,19 @@ export interface UseEveAgentReturn<TData> {
54
54
  * every render.
55
55
  */
56
56
  export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData> {
57
+ /**
58
+ * Named agent mounted by a framework integration such as `withEve({ agents })`.
59
+ *
60
+ * `agent: "support"` targets same-origin routes under
61
+ * `/eve/agents/support/eve/v1/...`. Do not combine with `host`.
62
+ */
63
+ readonly agent?: string;
57
64
  /** Authentication configuration; a function value is resolved per request. */
58
65
  readonly auth?: ClientAuth;
59
66
  /** Custom headers; a function value is resolved per request. */
60
67
  readonly headers?: HeadersValue;
61
68
  /**
62
- * Base URL used for eve client requests.
69
+ * Base URL used for eve client requests. Do not combine with `agent`.
63
70
  *
64
71
  * By default, requests target same-origin eve routes such as `/eve/v1/...`.
65
72
  * Pass a same-origin prefix such as `/api` to use an app-owned proxy, or an
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-CM24ZUEI.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-CFBTHlPx.js";
2
2
 
3
3
  export { useEveAgent };
@@ -121,7 +121,7 @@ Route handlers can start a session on a different channel via `args.receive(chan
121
121
 
122
122
  ```ts
123
123
  import { defineChannel, POST } from "eve/channels";
124
- import slack from "./slack.js";
124
+ import slack from "./slack";
125
125
 
126
126
  export default defineChannel({
127
127
  routes: [
@@ -220,7 +220,7 @@ The `context(state, session)` config option builds the per-step `channel` argume
220
220
  ```ts
221
221
  import { defineChannel } from "eve/channels";
222
222
 
223
- import { mintRef } from "./refs.js";
223
+ import { mintRef } from "./refs";
224
224
 
225
225
  defineChannel<{ ref: string | null }>({
226
226
  state: { ref: null },
@@ -164,7 +164,7 @@ Use the channel's `receive` target to continue an existing Agent Session or crea
164
164
  ```ts
165
165
  import { defineSchedule } from "eve/schedules";
166
166
 
167
- import linear from "../channels/linear.js";
167
+ import linear from "../channels/linear";
168
168
 
169
169
  export default defineSchedule({
170
170
  cron: "0 14 * * 1",
@@ -101,6 +101,8 @@ when you need the bearer token itself.
101
101
 
102
102
  The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and an action label on `actions.requested` — the tool name plus its most telling argument (`grep useEveAgent`, `read_file agent/agent.ts`), the subagent or remote-agent name for dispatched calls, and `+N more` when the model requests several actions at once. The model's own pre-tool narration, when present, takes precedence over the derived label. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
103
103
 
104
+ Outbound text preserves bare `@` tokens as literal text. To mention a user, embed Slack's `<@USER_ID>` syntax directly or use `channel.thread.mentionUser(userId)`.
105
+
104
106
  When a session starts without a `threadTs` (say, from a schedule or `receive(slack, ...)`), eve gives it a unique temporary continuation token. The first agent post anchors the session to the Slack message timestamp, and later posts and mentions resume that same session. Pass `initialMessage` with a `Card` to land a structured anchor first instead. `threadTs` and `initialMessage` are mutually exclusive.
105
107
 
106
108
  The example below overrides `onAppMention` to gate on an authored message and posts the completed reply to the thread. Event handlers receive `(eventData, channel, ctx)`, with Slack platform handles on `channel.thread` and `channel.slack`:
@@ -22,7 +22,7 @@ To build the instructions prompt from typed helpers, lib code, or environment-de
22
22
 
23
23
  ```ts title="agent/instructions.ts"
24
24
  import { defineInstructions } from "eve/instructions";
25
- import { buildInstructionsPrompt } from "./lib/prompts.js";
25
+ import { buildInstructionsPrompt } from "./lib/prompts";
26
26
 
27
27
  export default defineInstructions({
28
28
  markdown: buildInstructionsPrompt(),
@@ -23,7 +23,7 @@ export default defineOpenAPIConnection({
23
23
 
24
24
  Each operation becomes `<connection>__<operationId>`, for example `petstore__getInventory`. When an operation has no `operationId`, eve derives a deterministic `<method>_<sanitized-path>` name instead.
25
25
 
26
- `spec` can be an HTTPS URL that eve fetches at runtime, or an inline parsed OpenAPI object. Prefer a URL when the provider owns the contract and updates it; prefer an inline object for private APIs, generated specs you pin in source control, or small hand-authored contracts.
26
+ `spec` can be a URL that eve fetches at runtime, or an inline parsed OpenAPI object. A spec URL must use `https` (plain `http` is allowed only for loopback hosts such as `localhost` during local development), and eve re-checks the transport after any redirects. Prefer a URL when the provider owns the contract and updates it; prefer an inline object for private APIs, generated specs you pin in source control, or small hand-authored contracts.
27
27
 
28
28
  ## Base URL and servers
29
29
 
@@ -34,6 +34,8 @@ eve resolves operation paths against `baseUrl` when you provide one. Otherwise,
34
34
 
35
35
  Use `baseUrl` when the spec is missing server data, points at the wrong environment, uses a relative server URL you do not want, or needs to be pinned for this agent.
36
36
 
37
+ The resolved base URL must use `https` too (loopback hosts may use `http` for local development), since operation calls carry the connection's credentials.
38
+
37
39
  ```ts title="agent/connections/crm.ts"
38
40
  import { defineOpenAPIConnection } from "eve/connections";
39
41
 
@@ -77,13 +77,15 @@ Pick the cheapest builder that captures what "correct" means. When exact match i
77
77
 
78
78
  ## The matcher mini-language
79
79
 
80
- `t.calledTool` and `t.calledSubagent` take matcher objects. Tools accept `{ input, output, status, count }`; subagents accept `{ remoteUrl, output, status, count }`. Calls match `status: "completed"` by default; use `"pending"`, `"failed"`, or `"rejected"` explicitly for lifecycle checks. `count` is the exact number of calls matching every supplied constraint.
80
+ `t.calledTool` and `t.calledSubagent` take matcher objects. Tools accept `{ input, output, status, count }`; subagents accept `{ remoteUrl, output, status, count }`. Calls match `status: "completed"` by default; use `"pending"`, `"failed"`, or `"rejected"` explicitly for lifecycle checks. A numeric `count` requires an exact number of calls matching every supplied constraint. Use a predicate for ranges or other custom count requirements; it receives the observed number of matching calls.
81
81
 
82
82
  Matcher values accept a literal (objects partial-deep-match), a RegExp, or a predicate function that returns a boolean:
83
83
 
84
84
  ```ts
85
85
  t.calledTool("bash", { input: { command: /^pwd/ }, count: 1 });
86
86
 
87
+ t.calledTool("echo", { count: (count) => count >= 2 });
88
+
87
89
  t.calledTool("echo", { output: (value) => String(value).includes(marker) });
88
90
 
89
91
  parked.calledTool("guarded", { status: "pending", count: 1 });
@@ -108,7 +110,7 @@ const request = session.requireInputRequest({
108
110
 
109
111
  Beyond the raw `t.events` stream, the runner derives typed facts the assertions read: tool calls (name, input, output, lifecycle status), subagent calls, and HITL input requests. A turn that leaves the session open for a next message is the normal end state of a successful turn; parking on unanswered HITL input is tracked separately.
110
112
 
111
- Typed event matching covers presence, absence, exact counts, partial event data, and ordering:
113
+ Typed event matching covers presence, absence, numeric or predicate counts, partial event data, and ordering:
112
114
 
113
115
  ```ts
114
116
  turn.notEvent("result.completed");
@@ -0,0 +1,176 @@
1
+ ---
2
+ title: "Extensions"
3
+ description: "Package tools, connections, skills, and hooks as a reusable package and mount it into an agent."
4
+ ---
5
+
6
+ An extension packages eve capabilities — tools, connections, skills, instructions, hooks — as a reusable npm or local package. You author it as an agent-shaped directory; a consuming agent mounts it under `agent/extensions/`, and its contributions compose into the agent under a namespace. Nothing is copied — upgrades come through the package manager.
7
+
8
+ ## Authoring
9
+
10
+ An extension is an agent-shaped directory without `agent.ts` or `sandbox` (those belong to the consuming agent). Every slot works as it does in an agent, with names derived from paths.
11
+
12
+ ```
13
+ @acme/crm/
14
+ package.json
15
+ ext/
16
+ extension.ts # the extension declaration — see Configuration
17
+ tools/search.ts
18
+ connections/api.ts
19
+ skills/triage/SKILL.md
20
+ hooks/audit.ts
21
+ lib/http.ts # shared helpers, imported as ../lib/http
22
+ ```
23
+
24
+ Name tools and connections for what they do (`search`, not `crm_search`) — the mount supplies the namespace. Shared code goes in `ext/lib/`, imported by relative path — eve compiles the source, so relative imports need no `.js` extension.
25
+
26
+ ### Configuration
27
+
28
+ Declare the extension in `ext/extension.ts` with `defineExtension`; its default export is the mount factory a consumer calls. Pass `config` — any [Standard Schema](https://standardschema.dev) (a Zod object here), like a tool's `inputSchema` — to accept consumer settings:
29
+
30
+ ```ts title="ext/extension.ts"
31
+ import { defineExtension } from "eve/extension";
32
+ import { z } from "zod";
33
+
34
+ export default defineExtension({
35
+ config: z.object({
36
+ apiKey: z.string(),
37
+ baseUrl: z.string().default("https://api.acme.example"),
38
+ }),
39
+ });
40
+ ```
41
+
42
+ Config is optional — `defineExtension()` with no schema. Read it off the handle, imported from the declaration; it's typed from the schema:
43
+
44
+ ```ts title="ext/tools/search.ts"
45
+ import { defineTool } from "eve/tools";
46
+
47
+ import extension from "../extension";
48
+
49
+ export default defineTool({
50
+ description: "Search the CRM.",
51
+ inputSchema: {
52
+ /* ... */
53
+ },
54
+ async execute({ query }) {
55
+ const { apiKey, baseUrl } = extension.config; // validated, defaults applied
56
+ },
57
+ });
58
+ ```
59
+
60
+ Config is bound once when the consumer mounts the extension and stays constant for the session; per-request values belong in connection auth instead.
61
+
62
+ ### State
63
+
64
+ `defineState` is scoped to the extension's package automatically, so identically-named state never collides with the consuming agent or another extension. Author it exactly as in an agent — `defineState("budget", …)`.
65
+
66
+ ## Publishing
67
+
68
+ Point `eve.extension` at the source directory and run `eve build` (wired to `build`/`prepare`):
69
+
70
+ ```jsonc title="package.json"
71
+ {
72
+ "name": "@acme/crm",
73
+ "type": "module",
74
+ "eve": { "extension": "./ext" },
75
+ "files": ["ext", "dist"],
76
+ "peerDependencies": { "eve": "^x" },
77
+ "dependencies": { "zod": "^3" },
78
+ "scripts": { "build": "eve build", "prepare": "eve build" },
79
+ }
80
+ ```
81
+
82
+ Author the source with `moduleResolution: "bundler"` — eve compiles it, so relative imports need no `.js` extension:
83
+
84
+ ```jsonc title="tsconfig.json"
85
+ {
86
+ "compilerOptions": {
87
+ "module": "esnext",
88
+ "moduleResolution": "bundler",
89
+ "strict": true,
90
+ "noEmit": true,
91
+ "types": ["node"],
92
+ },
93
+ "include": ["ext/**/*.ts"],
94
+ }
95
+ ```
96
+
97
+ `eve build` compiles the package's entry points to plain JavaScript with type declarations — the mount factory (`dist/index.mjs`) and the tool re-exports overrides use (`dist/tools`) — and fills the `exports` map so you never hand-list it. Compiling is what lets an installed extension load directly; local and workspace packages also work without publishing.
98
+
99
+ ### Dependencies
100
+
101
+ `eve` is a **peer** dependency: one eve lives in the consuming app and the extension's `eve/*` imports resolve to it. Declare the eve versions your extension supports as the peer range (`"eve": "^1"`) — eve enforces it when the extension is mounted, failing the build with a clear error if the app's eve is out of range, rather than surfacing a confusing compile break. Everything else the extension imports (SDKs, `zod`, …) goes in `dependencies`; each extension resolves its own versions. The consumer recompiles the extension's contributions from source, so `files` must ship both `ext/` (that source) and `dist/` (the compiled entry points).
102
+
103
+ Those deps resolve from `node_modules` under `eve dev`/`eve eval` and are bundled into the deployable by `eve build`. A dependency that can't be bundled (a native addon) must be listed in the **consuming agent's** `build.externalDependencies` — an extension can't declare build config, so note it in your README.
104
+
105
+ ## Mounting
106
+
107
+ A consuming agent mounts an extension under `agent/extensions/` — a single file, or a directory when it needs [overrides](#overrides). The namespace is the file basename or directory name; contributions compose as `<namespace>__<name>` (`crm__search`, `crm__api`).
108
+
109
+ ```ts title="agent/extensions/crm.ts"
110
+ import crm from "@acme/crm";
111
+
112
+ export default crm({ apiKey: process.env.CRM_API_KEY });
113
+ ```
114
+
115
+ A no-config extension takes no factory call — mount it with a bare re-export:
116
+
117
+ ```ts title="agent/extensions/gizmo.ts"
118
+ export { default } from "@acme/gizmo";
119
+ ```
120
+
121
+ ### Overrides
122
+
123
+ To override a mounted extension's contributions, author the mount as a directory: the declaration in `extension.ts`, override slots alongside it.
124
+
125
+ ```
126
+ agent/extensions/crm/
127
+ extension.ts # export default crm({ apiKey: process.env.CRM_API_KEY })
128
+ tools/search.ts # composes as crm__search, shadowing the extension's own
129
+ ```
130
+
131
+ A file in an override slot composes under the mount namespace and wins on a name collision. Name it for the bare contribution name (`search`, not `crm__search`) — the directory supplies the prefix. To tweak the extension's own definition, import and re-define it:
132
+
133
+ ```ts title="agent/extensions/crm/tools/search.ts"
134
+ import { search } from "@acme/crm/tools";
135
+ import { defineTool } from "eve/tools";
136
+ import { always } from "eve/tools/approval";
137
+
138
+ export default defineTool({ ...search, approval: always() });
139
+ ```
140
+
141
+ Or drop it entirely by opting out of the slot with `disableTool()`:
142
+
143
+ ```ts title="agent/extensions/crm/tools/search.ts"
144
+ import { disableTool } from "eve/tools";
145
+
146
+ export default disableTool();
147
+ ```
148
+
149
+ An override targets one slot, matched by name and kind: a static file replaces the extension's static tool, a dynamic file replaces its dynamic resolver, and `disableTool()` removes whichever the extension put there. Because a dynamic tool wins over a same-named static one at runtime, replace or disable a dynamic tool through its own slot — a static file of the same name won't shadow it.
150
+
151
+ Overrides only work here — the `<namespace>__` prefix is reserved, so an agent-root contribution named `crm__…` is a build error and an extension can't be shadowed from outside its mount.
152
+
153
+ ### Typed tool results
154
+
155
+ A consuming agent can narrow a mounted extension's tool result in a hook: import the tool from the extension's `./tools` export and pass it to [`toolResultFrom`](/guides/hooks#narrowing-tool-results). It matches the namespaced result (`crm__search`) because identity keys off the tool definition, not its name.
156
+
157
+ ```ts title="agent/hooks/narrow-crm.ts"
158
+ import { defineHook } from "eve/hooks";
159
+ import { toolResultFrom } from "eve/tools";
160
+ import { search } from "@acme/crm/tools";
161
+
162
+ export default defineHook({
163
+ events: {
164
+ "action.result"(event) {
165
+ const match = toolResultFrom(event.data.result, search);
166
+ if (match) console.log(match.output); // typed as search's output
167
+ },
168
+ },
169
+ });
170
+ ```
171
+
172
+ Matching keys off the tool's description, so keep extension tool descriptions distinct — one shared with another tool makes the identity ambiguous and `toolResultFrom` stops matching.
173
+
174
+ ## Limits
175
+
176
+ An extension cannot declare a `sandbox`, agent config, schedules, or limits, and cannot mount other extensions — those are the consuming agent's to own (background scheduling, for instance, runs on the agent's deployment under its limits). An extension's tools run within the consuming agent's per-session limits.