eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 3.33 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,removeSkillPackageFromSandbox,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";import{resolveSandboxSkillRoot}from"#shared/skill-paths.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.slug,entryKey:r[0],entry:n[r[0]]}),i;let a=e.extensionNamespace===void 0?``:`${e.extensionNamespace}__`;for(let e of r)i.push({name:`${a}${e}`,entryKey:e,entry:n[e]});return i}async function formatDynamicSkillAnnouncement(e){let t=await e.ctx.require(SandboxKey).get(),r=t===null?void 0:await resolveSandboxSkillRoot({sandbox:t});return formatAvailableSkillsSection(Object.values(e.manifest).flat(),{skillRoot:r})??``}const PendingSkillAnnouncementKey=new ContextKey(`eve.pendingSkillAnnouncement`);async function dispatchDynamicSkillEvent(e){let{ctx:o,resolvers:s,event:c,messages:l}=e;if(o.get(PendingSkillAnnouncementKey)===void 0){let e=o.get(DynamicSkillManifestKey);e!==void 0&&Object.keys(e).length>0&&o.setVirtualContext(PendingSkillAnnouncementKey,await formatDynamicSkillAnnouncement({ctx:o,manifest:e}))}if(!ALLOWED_DYNAMIC_SKILL_EVENTS.has(c.type))return;let u=s.filter(e=>e.eventNames.includes(c.type));if(u.length===0)return;let d=buildResolveContext(o,l),f=o.get(DynamicSkillManifestKey)??{},p=[],m=await Promise.allSettled(u.map(async e=>{let t=e.events[c.type];if(t===void 0)return null;let n=await t(c,d);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,i,r)}}));for(let e of m){if(e.status===`rejected`){log.error(`Dynamic skill resolver (${c.type}) threw — skipping.`,{error:toErrorMessage(e.reason)});continue}e.value!==null&&p.push({resolver:e.value.resolver,skills:e.value.named.map(({name:e,entry:t})=>normalizeSkillPackage({...t,name:e}))})}if(p.length===0)return;let h={...f};for(let{resolver:e,skills:t}of p)t.length===0?delete h[e.slug]:h[e.slug]=t.map(e=>({description:e.description,name:e.name}));let g=new Map;for(let[e,t]of Object.entries(h))for(let{name:n}of t){let t=g.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}".`);g.set(n,e)}let _=await o.require(SandboxKey).get();if(_!==null){let e=new Set(Object.values(h).flat().map(e=>e.name)),t=new Set;for(let{resolver:n}of p)for(let r of f[n.slug]??[])e.has(r.name)||t.add(r.name);for(let e of t)await removeSkillPackageFromSandbox({name:e,sandbox:_});for(let{skills:e}of p)for(let t of e)await writeSkillPackageToSandbox({sandbox:_,skill:t})}o.set(DynamicSkillManifestKey,h),o.setVirtualContext(PendingSkillAnnouncementKey,await formatDynamicSkillAnnouncement({ctx:o,manifest:h}))}export{PendingSkillAnnouncementKey,dispatchDynamicSkillEvent};