eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 3.26 kB
JavaScript
import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{AuthKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{readStampedConnectionProtocol}from"#public/definitions/connections/protocol.js";import{ALLOWED_DYNAMIC_CONNECTION_EVENTS}from"#dynamic/definition.js";import{ConnectionRegistryKey}from"#context/providers/connection-key.js";import{CONNECTION_SLUG_PATTERN}from"#discover/grammar.js";import{ConnectionRegistryImpl}from"#runtime/connections/registry.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{resolveDynamicConnectionValue}from"#runtime/resolve-connection.js";const log=createLogger(`dynamic-connections`);function qualifyConnectionNames(e,t){if(readStampedConnectionProtocol(t)!==void 0)return[{name:e.slug,value:t}];if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`Dynamic connection resolver "${e.logicalPath}" must return a connection definition, a map of connection definitions, or null.`);let n=e.extensionNamespace===void 0?``:`${e.extensionNamespace}__`;return Object.entries(t).map(([t,r])=>{if(!CONNECTION_SLUG_PATTERN.test(t))throw Error(`Dynamic connection resolver "${e.logicalPath}" returned illegal connection name "${t}". Expected lowercase ASCII letters, digits, and dashes only, starting with a letter, up to 64 characters.`);if(readStampedConnectionProtocol(r)===void 0)throw Error(`Dynamic connection resolver "${e.logicalPath}" returned "${t}" without defineMcpClientConnection() or defineOpenAPIConnection().`);return{name:`${n}${t}`,value:r}})}async function resolveConnections(e){let t=e.resolver.events[e.event.type];if(t===void 0)return[];let n=await t(e.event,buildConnectionResolveContext(e.ctx));return n==null?[]:qualifyConnectionNames(e.resolver,n).map(({name:t,value:n})=>resolveDynamicConnectionValue(n,{connectionName:t,exportName:e.resolver.exportName,logicalPath:e.resolver.logicalPath,sourceId:e.resolver.sourceId,sourceKind:`module`}))}async function dispatchDynamicConnectionEvent(e){if(!ALLOWED_DYNAMIC_CONNECTION_EVENTS.has(e.event.type))return;let t=e.resolvers.filter(t=>t.eventNames.includes(e.event.type));if(t.length===0)return;let n=e.ctx.get(ConnectionRegistryKey);if(!(n instanceof ConnectionRegistryImpl))throw Error(`Dynamic connection resolution requires the framework connection registry.`);let r=await Promise.allSettled(t.map(async t=>({connections:await resolveConnections({...e,resolver:t}),resolver:t}))),i=new Map,a;for(let n=0;n<r.length;n+=1){let o=r[n],s=t[n];if(o.status===`rejected`){log.error(`Dynamic connection resolver (${e.event.type}) failed.`,{error:toErrorMessage(o.reason),logicalPath:s.logicalPath}),a??=s;continue}i.set(o.value.resolver.slug,o.value.connections)}if(a!==void 0)throw Error(`Dynamic connection resolver "${a.logicalPath}" failed during "${e.event.type}".`);await n.replaceDynamicConnections(e.event.type===`session.started`?`session`:`turn`,i)}function buildConnectionResolveContext(e){let t=e.get(ChannelKey);return{session:{id:e.get(SessionIdKey)??``,auth:{current:e.get(AuthKey)??null,initiator:e.get(InitiatorAuthKey)??null}},channel:{kind:t===void 0?void 0:getAdapterKind(t)}}}export{dispatchDynamicConnectionEvent};