eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 2.76 kB
JavaScript
import{createLogger}from"#internal/logging.js";import{DynamicSkillManifestKey,SandboxKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{ALLOWED_DYNAMIC_SKILL_EVENTS,isBrandedSkillEntry}from"#shared/dynamic-tool-definition.js";import{normalizeSkillPackage,writeSkillPackageToSandbox}from"#shared/skill-package.js";import{ContextKey}from"#context/key.js";import{buildResolveContext}from"#context/dynamic-resolve-context.js";import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";const log=createLogger(`dynamic-skills`);function qualifyDynamicSkillNames(e,t,n){let r=Object.keys(n),i=[];if(r.length===0)return i;if(t)return i.push({name:e,entryKey:r[0],entry:n[r[0]]}),i;for(let e of r)i.push({name:e,entryKey:e,entry:n[e]});return i}function formatDynamicSkillAnnouncement(e){return formatAvailableSkillsSection(Object.values(e).flat())??``}const PendingSkillAnnouncementKey=new ContextKey(`eve.pendingSkillAnnouncement`);async function dispatchDynamicSkillEvent(e){let{ctx:a,resolvers:o,event:s,messages:c}=e;if(a.get(PendingSkillAnnouncementKey)===void 0){let e=a.get(DynamicSkillManifestKey);e!==void 0&&Object.keys(e).length>0&&a.setVirtualContext(PendingSkillAnnouncementKey,formatDynamicSkillAnnouncement(e))}if(!ALLOWED_DYNAMIC_SKILL_EVENTS.has(s.type))return;let l=o.filter(e=>e.eventNames.includes(s.type));if(l.length===0)return;let u=buildResolveContext(a,c),d=a.get(DynamicSkillManifestKey)??{},f=[],p=await Promise.allSettled(l.map(async e=>{let t=e.events[s.type];if(t===void 0)return null;let n=await t(s,u);if(n==null)return{resolver:e,named:[]};let r,i;return isBrandedSkillEntry(n)?(r={_single:n},i=!0):(r=n,i=!1),{resolver:e,named:qualifyDynamicSkillNames(e.slug,i,r)}}));for(let e of p){if(e.status===`rejected`){log.error(`Dynamic skill resolver (${s.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}e.value!==null&&f.push({resolver:e.value.resolver,skills:e.value.named.map(({name:e,entry:t})=>normalizeSkillPackage({...t,name:e}))})}if(f.length===0)return;let m={...d};for(let{resolver:e,skills:t}of f)t.length===0?delete m[e.slug]:m[e.slug]=t.map(e=>({description:e.description,name:e.name}));let h=new Map;for(let[e,t]of Object.entries(m))for(let{name:n}of t){let t=h.get(n);if(t!==void 0)throw Error(`Dynamic skill "${n}" from resolver "${e}" collides with dynamic resolver "${t}". Namespace the map key manually, e.g. "${e}__${n}".`);h.set(n,e)}let g=await a.require(SandboxKey).get();if(g!==null)for(let{skills:e}of f)for(let t of e)await writeSkillPackageToSandbox({sandbox:g,skill:t});a.set(DynamicSkillManifestKey,m),a.setVirtualContext(PendingSkillAnnouncementKey,formatDynamicSkillAnnouncement(m))}export{PendingSkillAnnouncementKey,dispatchDynamicSkillEvent};