UNPKG

eve

Version:

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

1 lines 4.25 kB
import{mkdir,readFile,writeFile}from"node:fs/promises";import{z}from"#compiled/zod/index.js";import{join}from"node:path";import{AI_GATEWAY_MODELS_CATALOG_URL,vercelGatewayFetch}from"#internal/gateway.js";import{catalogModelProviderSchema,catalogModelSchema,catalogModelSchema as catalogModelSchema$1,findCatalogModelByProviderModelId,findCatalogModelBySlug,modelCatalogLimitsFromProvider,modelCatalogResponseSchema,modelCatalogResponseSchema as modelCatalogResponseSchema$1,normalizeCatalogModelId}from"#internal/model-catalog.js";const COMPILED_RUNTIME_MODEL_CATALOG_CACHE_KIND=`eve-model-catalog-cache`;z.object({contextWindowTokens:z.number().int().positive(),maxOutputTokens:z.number().int().positive().optional()}).strict();const compiledRuntimeModelCatalogCacheSchema=z.object({fetchedAt:z.string(),kind:z.literal(COMPILED_RUNTIME_MODEL_CATALOG_CACHE_KIND),models:z.array(catalogModelSchema$1),providerAliases:z.record(z.string(),z.string()),version:z.literal(2)}).strict(),builtInCompiledRuntimeModelLimitsById=new Map([[`anthropic/claude-opus-4.7`,{contextWindowTokens:2e5,maxOutputTokens:32e3}],[`openai/gpt-5.4`,{contextWindowTokens:4e5,maxOutputTokens:128e3}],[`openai/gpt-5.4-mini`,{contextWindowTokens:4e5,maxOutputTokens:128e3}]]);function resolveCompiledRuntimeModelCatalogCachePath(e){return join(e,`.eve`,`cache`,`model-catalog.json`)}function createCompiledRuntimeModelCatalogLoader(e){let t=null,n=null,r=null,getCachedCatalog=async()=>(t??=readModelCatalogCache(e),await t),getFetchedCatalog=async()=>{if(n!==null)throw n;if(r!==null)return await r;r=fetchAndPersistModelCatalog(e).then(e=>(t=Promise.resolve(e),e));try{return await r}catch(e){throw n=e,e}},resolveModelsFromCacheOrFetch=async e=>{let t=await getCachedCatalog();if(e?.forceRefresh!==!0&&t!==null&&isCacheFresh(t))return t;try{return await getFetchedCatalog()}catch(e){if(t!==null)return t;throw e}};return{async getModelLimits(e){let t=builtInCompiledRuntimeModelLimitsById.get(e)??builtInCompiledRuntimeModelLimitsById.get(normalizeCatalogModelId(e));if(t!==void 0)return t;let n=await resolveModelsFromCacheOrFetch();if(n===null)return null;let r=findCatalogModelBySlug(n.models,e);if(r===void 0){if(n=await resolveModelsFromCacheOrFetch({forceRefresh:!0}),n===null)return null;r=findCatalogModelBySlug(n.models,e)}if(r!==void 0)for(let e of r.providers){let t=modelCatalogLimitsFromProvider(e);if(t!==null)return t}return null},async getByProviderModelId(e,t){let n=await resolveModelsFromCacheOrFetch();if(n===null)return null;let r=findCatalogModelByProviderModelId({models:n.models,provider:e,providerAliases:n.providerAliases,providerModelId:t});if(r===null){if(n=await resolveModelsFromCacheOrFetch({forceRefresh:!0}),n===null)return null;r=findCatalogModelByProviderModelId({models:n.models,provider:e,providerAliases:n.providerAliases,providerModelId:t})}if(r!==null){let e=modelCatalogLimitsFromProvider(r.provider);if(e!==null)return{slug:r.model.slug,limits:e}}return null}}}async function fetchAndPersistModelCatalog(e){let t=await vercelGatewayFetch(AI_GATEWAY_MODELS_CATALOG_URL);if(!t.ok)throw Error(`AI Gateway model catalog request failed with HTTP ${t.status} ${t.statusText}.`);let n=modelCatalogResponseSchema$1.safeParse(await t.json());if(!n.success)throw Error(`AI Gateway model catalog response did not match the expected schema.`);let r={fetchedAt:new Date().toISOString(),kind:COMPILED_RUNTIME_MODEL_CATALOG_CACHE_KIND,models:n.data.models,providerAliases:n.data.providerAliases,version:2};try{let t=resolveCompiledRuntimeModelCatalogCachePath(e);await mkdir(join(e,`.eve`,`cache`),{recursive:!0}),await writeFile(t,`${JSON.stringify(r,null,2)}\n`,`utf8`)}catch{}return r}async function readModelCatalogCache(e){try{let t=await readFile(resolveCompiledRuntimeModelCatalogCachePath(e),`utf8`),n=compiledRuntimeModelCatalogCacheSchema.safeParse(JSON.parse(t));return n.success?n.data:null}catch(e){return e instanceof Error&&`code`in e&&typeof e.code==`string`&&e.code,null}}function isCacheFresh(e){let t=Date.parse(e.fetchedAt);return Number.isFinite(t)?Date.now()-t<=3e5:!1}export{catalogModelProviderSchema,catalogModelSchema,createCompiledRuntimeModelCatalogLoader,modelCatalogResponseSchema,resolveCompiledRuntimeModelCatalogCachePath};