UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

86 lines (85 loc) 4.54 kB
import { i as normalizeProviderId } from "./provider-id-Dq06Bcx6.js"; import { existsSync, readdirSync } from "node:fs"; import path from "node:path"; //#region src/agents/plugin-model-catalog.ts /** * Generated plugin model catalog discovery. * * Catalog files live under agent profiles and let provider discovery reuse plugin-owned catalogs without loading runtimes. */ const PLUGIN_MODEL_CATALOG_FILE = "catalog.json"; const PLUGIN_MODEL_CATALOG_GENERATED_BY = "openclaw-plugin-model-catalog-v1"; /** Encodes the profile-relative path for a plugin-owned generated model catalog. */ function encodePluginModelCatalogRelativePath(pluginId) { return `plugins/${encodeURIComponent(pluginId)}/${PLUGIN_MODEL_CATALOG_FILE}`; } /** Returns true only for canonical profile-relative generated catalog paths. */ function isPluginModelCatalogRelativePath(relativePath) { const parts = relativePath.split(/[\\/]/); return !path.isAbsolute(relativePath) && parts.length === 3 && parts[0] === "plugins" && parts[1] !== "" && parts[1] !== "." && parts[1] !== ".." && parts[2] === "catalog.json"; } /** Decodes the plugin id from a canonical generated catalog path. */ function decodePluginModelCatalogRelativePathPluginId(relativePath) { if (!isPluginModelCatalogRelativePath(relativePath)) return; const encodedPluginId = relativePath.split(/[\\/]/)[1]; try { return decodeURIComponent(encodedPluginId); } catch { return; } } /** Lists deterministic generated catalog paths present in an agent profile. */ function listPluginModelCatalogRelativePaths(agentDir) { const pluginsDir = path.join(agentDir, "plugins"); let pluginDirs; try { pluginDirs = readdirSync(pluginsDir, { withFileTypes: true }); } catch { return []; } return pluginDirs.filter((entry) => entry.isDirectory()).map((entry) => path.join("plugins", entry.name, PLUGIN_MODEL_CATALOG_FILE)).filter(isPluginModelCatalogRelativePath).toSorted((left, right) => left.localeCompare(right)); } /** Lists existing generated catalog files with decoded plugin ownership. */ function listPluginModelCatalogFiles(agentDir) { return listPluginModelCatalogRelativePaths(agentDir).map((relativePath) => { const pluginId = decodePluginModelCatalogRelativePathPluginId(relativePath); return pluginId ? { path: path.join(agentDir, relativePath), pluginId, relativePath } : void 0; }).filter((entry) => entry !== void 0).filter((entry) => existsSync(entry.path)); } /** Detects model catalogs generated by OpenClaw rather than user-authored JSON. */ function isGeneratedPluginModelCatalog(value) { return typeof value === "object" && value !== null && !Array.isArray(value) && value.generatedBy === "openclaw-plugin-model-catalog-v1"; } /** Resolves the sole enabled plugin that owns a provider's model catalog. */ function resolvePluginModelCatalogOwnerPluginId(params) { const snapshot = params.pluginMetadataSnapshot; const owners = snapshot?.owners; if (!owners) return; const providerId = normalizeProviderId(params.providerId); const candidates = [ owners.modelCatalogProviders.get(providerId), owners.providers.get(providerId), owners.setupProviders.get(providerId) ].find((entry) => Array.isArray(entry) && entry.length > 0); const pluginId = candidates?.length === 1 ? candidates[0] : void 0; if (!pluginId) return; if (!snapshot?.index) return pluginId; const normalizedPluginId = snapshot.normalizePluginId?.(pluginId) ?? pluginId; return snapshot.index.plugins.some((plugin) => plugin.pluginId === normalizedPluginId && plugin.enabled) ? normalizedPluginId : void 0; } /** Keeps generated catalog providers only when the catalog plugin still owns them. */ function filterGeneratedPluginModelCatalogProviders(params) { if (!params.catalogPluginId || !params.pluginMetadataSnapshot || params.parsedCatalog !== void 0 && !isGeneratedPluginModelCatalog(params.parsedCatalog)) return {}; return Object.fromEntries(Object.entries(params.providers).filter(([providerId]) => { return resolvePluginModelCatalogOwnerPluginId({ providerId, pluginMetadataSnapshot: params.pluginMetadataSnapshot }) === params.catalogPluginId; })); } //#endregion export { isGeneratedPluginModelCatalog as a, listPluginModelCatalogRelativePaths as c, filterGeneratedPluginModelCatalogProviders as i, resolvePluginModelCatalogOwnerPluginId as l, decodePluginModelCatalogRelativePathPluginId as n, isPluginModelCatalogRelativePath as o, encodePluginModelCatalogRelativePath as r, listPluginModelCatalogFiles as s, PLUGIN_MODEL_CATALOG_GENERATED_BY as t };