UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

1 lines 7.87 kB
import{defineTool}from"eve/tools";const CATEGORIES=[`channel`,`connection`,`extension`,`instrumentation`,`memory`],INDEX_PATH=`/registry.json`,FETCH_TIMEOUT_MS=1e4,inputSchema={type:`object`,additionalProperties:!1,properties:{query:{type:`string`,maxLength:200,description:`Free-text match against integration names, titles, and descriptions.`},category:{type:`string`,enum:[...CATEGORIES],description:`Restrict results to one registry category.`},limit:{type:`integer`,minimum:1,maximum:25,description:`Maximum number of items to return (default 10, maximum 25).`},offset:{type:`integer`,minimum:0,description:`Number of matching items to skip. Use nextOffset from a prior result to retrieve the next page.`}}},outputSchema={type:`object`,additionalProperties:!1,properties:{items:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{address:{type:`string`},title:{type:`string`},description:{type:`string`},category:{type:`string`},components:{type:`array`,items:{type:`string`}},requires:{type:`string`},installed:{type:`boolean`}},required:[`address`,`title`]}},errors:{type:`array`,items:{type:`object`,additionalProperties:!1,properties:{registry:{type:`string`},message:{type:`string`}},required:[`registry`,`message`]}},total:{type:`integer`},hasMore:{type:`boolean`},nextOffset:{type:`integer`}},required:[`items`,`errors`,`total`,`hasMore`]};function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function optionalString(e){return typeof e==`string`&&e.length>0?e:void 0}function isCategory(e){return CATEGORIES.includes(e)}function categoryOf(e){let t=e.split(`/`)[0];return t!==void 0&&e.includes(`/`)&&isCategory(t)?t:void 0}function titleFromAddress(e){return(e.split(`/`).at(-1)??e).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function eveMetadata(e){let t=e.meta;if(!isRecord(t))return{};let n=t.eve;return isRecord(n)?n:{}}function componentMetadata(e){let t=e.components;if(!Array.isArray(t))return;let n=[],r=[];for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.item);if(t===void 0)continue;n.push(t),r.push(t);let i=optionalString(e.label);i!==void 0&&r.push(i);let a=optionalString(e.description);a!==void 0&&r.push(a)}return n.length>0?{addresses:n,searchTerms:r}:void 0}function authoredTargetOf(e){let t=e.files;if(Array.isArray(t))for(let e of t){if(!isRecord(e))continue;let t=optionalString(e.target);if(t?.startsWith(`agent/`)===!0)return t}}function declaredEnvVars(e){let t=e.envVars;return isRecord(t)?Object.keys(t):[]}function parseRegistryIndex(e){if(!isRecord(e)||!Array.isArray(e.items))return[];let t=[];for(let n of e.items){if(!isRecord(n))continue;let e=optionalString(n.name);if(e===void 0)continue;let r=eveMetadata(n);if(r.hidden===!0)continue;let i={address:e,title:optionalString(n.title)??titleFromAddress(e)},a=categoryOf(e);a!==void 0&&(i.category=a);let o=optionalString(n.description);o!==void 0&&(i.description=o);let s=componentMetadata(r);s!==void 0&&(i.components=s.addresses,i.componentSearchTerms=s.searchTerms);let c=optionalString(r.requires);c!==void 0&&(i.requires=c);let l=authoredTargetOf(n);l!==void 0&&(i.authoredTarget=l),r.setup!==void 0&&r.setup!==null&&(i.declaresSetup=!0);let u=declaredEnvVars(n);u.length>0&&(i.envVars=u),t.push(i)}return t}function selectIntegrations(e){return selectIntegrationPage(e).items}function selectIntegrationPage(e){let t=Math.min(Math.max(e.limit??10,1),25),n=Math.max(e.offset??0,0),r=(e.query??``).toLowerCase().split(/\s+/u).filter(e=>e.length>0),i=e.entries.map((e,t)=>{let n=`${e.address} ${e.title}`.toLowerCase();return{entry:e,haystack:[n,e.description??``,...e.componentSearchTerms??e.components??[]].join(` `).toLowerCase(),index:t,primaryTerms:n}}),a=new Map(r.map(e=>{let t=i.filter(({haystack:t})=>t.includes(e)).length;return[e,Math.log((i.length+1)/(t+1))+1]})),o=i.map(({entry:t,haystack:n,index:i,primaryTerms:o})=>{if(e.category!==void 0&&!matchesCategory(t,e.category))return;if(r.length===0)return{entry:t,index:i,score:0};let s=r.reduce((e,t)=>{let r=a.get(t)??0;return o.includes(t)?e+2*r:n.includes(t)?e+r:e},0);return s>0?{entry:t,index:i,score:s}:void 0}).filter(e=>e!==void 0).sort((e,t)=>t.score-e.score||e.index-t.index),s=(o[0]?.score??0)*.4,c=o.filter(({score:e})=>e>=s),l=c.slice(n,n+t).map(({entry:e})=>{let t={address:e.address,title:e.title};return e.category!==void 0&&(t.category=e.category),e.components!==void 0&&(t.components=e.components),e.description!==void 0&&(t.description=e.description),e.requires!==void 0&&(t.requires=e.requires),t}),u=n+l.length,d={hasMore:u<c.length,items:l,total:c.length};return u<c.length&&(d.nextOffset=u),d}function matchesCategory(e,t){return e.category===t||e.components?.some(e=>categoryOf(e)===t)===!0}function officialRegistryIndexUrl(){return`https://eve.dev/r${INDEX_PATH}`}function resolveRegistryIndexUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return officialRegistryIndexUrl();let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=`${t.pathname.replace(/\/+$/u,``)}${INDEX_PATH}`,t.toString()}let cache;function clearRegistryIndexCache(){cache=void 0}async function loadRegistryIndex(e){if(cache!==void 0&&cache.url===e.url&&e.nowMs-cache.fetchedAtMs<3e5)return cache.entries;let t=await fetch(e.url,{headers:{accept:`application/json`},signal:AbortSignal.any(e.signal===void 0?[AbortSignal.timeout(FETCH_TIMEOUT_MS)]:[e.signal,AbortSignal.timeout(FETCH_TIMEOUT_MS)])});if(!t.ok)throw Error(`Could not read the eve registry (${t.status}).`);let n=parseRegistryIndex(await t.json());return cache={entries:n,fetchedAtMs:e.nowMs,url:e.url},n}async function annotateInstalled(e){let t=new Map(e.entries.flatMap(e=>e.authoredTarget===void 0?[]:[[e.address,e.authoredTarget]]));if(e.rows.every(e=>t.get(e.address)===void 0))return e.rows;let n;try{n=await e.ctx.getSandbox()}catch{return e.rows}return await Promise.all(e.rows.map(async e=>{let r=t.get(e.address);if(r===void 0)return e;let i=`/source/${r.slice(6)}`;try{let t=await n.readTextFile({path:i});return{...e,installed:t!==null}}catch{return e}}))}var search_registry_default=defineTool({description:"Search the eve registry for integrations this project can add: channels, MCP connections, extensions, memory providers, and observability. Read-only — it installs nothing. Call it before writing an integration by hand, then pass an exact item address (for example `channel/slack`) to selfmod__registry_add.",inputSchema,outputSchema,async execute(e,t){let n=[],r;try{r=resolveRegistryIndexUrl()}catch(e){return{errors:[{message:errorMessage(e),registry:`eve`}],hasMore:!1,items:[],total:0}}let i=[];try{i=await loadRegistryIndex({nowMs:Date.now(),signal:t.abortSignal,url:r})}catch(e){n.push({message:errorMessage(e),registry:r})}let a={entries:i},o=typeof e.category==`string`?e.category:void 0;o!==void 0&&isCategory(o)&&(a.category=o),typeof e.limit==`number`&&(a.limit=e.limit),typeof e.offset==`number`&&(a.offset=e.offset),typeof e.query==`string`&&(a.query=e.query);let s=selectIntegrationPage(a),c={errors:n,hasMore:s.hasMore,items:await annotateInstalled({ctx:t,entries:i,rows:s.items}),total:s.total};return s.nextOffset!==void 0&&(c.nextOffset=s.nextOffset),c}});function errorMessage(e){return e instanceof Error?e.message:String(e)}export{clearRegistryIndexCache,search_registry_default as default,loadRegistryIndex,officialRegistryIndexUrl,parseRegistryIndex,resolveRegistryIndexUrl,selectIntegrationPage,selectIntegrations};