UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

188 lines (187 loc) 8.82 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import { c as normalizeOptionalLowercaseString } from "./string-coerce-CIXf7egm.js"; import { i as listAgentEntries } from "./agent-scope-config-DcbEhP0R.js"; import { m as tryReadJsonSync } from "./json-files-Bq1lIlQB.js"; import { i as resolveBundledPluginsDir } from "./bundled-dir-BEfbEeCF.js"; import { n as BUNDLED_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_ENTRIES } from "./official-external-plugin-bundled-catalogs-dAuKwD3c.js"; import { r as loadInstalledPluginIndexInstallRecords } from "./installed-plugin-index-record-reader-SXWwf_BU.js"; import "./agent-scope-DbtJyKUL.js"; import { t as collectConfiguredSpeechProviderIds } from "./gateway-startup-speech-providers-C1sqNf-9.js"; import { t as resolveConfiguredGenericEmbeddingProviderId } from "./embedding-provider-config-B7oW9g2j.js"; import { i as collectConfiguredRuntimePluginIds } from "./configured-runtime-plugin-installs-DWgjbBZ4.js"; import { r as collectConfiguredProviderSelectionIds } from "./configured-provider-selection-ids-ClDBppbl.js"; import fs from "node:fs"; import path from "node:path"; //#region src/plugins/bundled-plugin-startup-metadata.ts const DOCTOR_CONTRACT_BASENAMES = ["doctor-contract-api", "contract-api"]; const MODULE_EXTENSIONS = [ "js", "cjs", "mjs", "ts", "cts", "mts" ]; function hasDoctorContractArtifact(pluginRoot) { return [pluginRoot, path.join(pluginRoot, "dist")].some((root) => DOCTOR_CONTRACT_BASENAMES.some((basename) => MODULE_EXTENSIONS.some((extension) => fs.existsSync(path.join(root, `${basename}.${extension}`))))); } /** Inspects one manifest-owned plugin root without loading its runtime or doctor contract. */ function inspectPluginStartupMetadata(params) { const manifest = tryReadJsonSync(path.join(params.rootDir, "openclaw.plugin.json")); if (!isRecord(manifest) || manifest.id !== params.pluginId) return; return { hasDoctorContract: hasDoctorContractArtifact(params.rootDir) }; } /** Resolves one exact bundled id without scanning or materializing the full plugin catalog. */ function inspectBundledPluginStartupMetadata(params) { const bundledPluginsDir = resolveBundledPluginsDir(params.env); if (!bundledPluginsDir) return; return inspectPluginStartupMetadata({ pluginId: params.pluginId, rootDir: path.join(bundledPluginsDir, params.pluginId) }); } //#endregion //#region src/plugins/official-external-plugin-targets.ts const STATIC_ENTRIES = BUNDLED_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_ENTRIES; function normalizeIds(values) { return new Set([...values].map((value) => normalizeOptionalLowercaseString(value)).filter((value) => Boolean(value))); } function envHasAny(env, names) { return names?.some((name) => Boolean(env[name]?.trim())) ?? false; } function envHasChannelCandidate(env, channel) { const allOf = channel?.configuredState?.env?.allOf ?? []; const anyOf = channel?.configuredState?.env?.anyOf ?? []; return envHasAny(env, [ ...channel?.envVars ?? [], ...allOf, ...anyOf ]); } function hasOfficialExternalProviderTarget(params) { const providerIds = normalizeIds(params.providerIds); return STATIC_ENTRIES.some((entry) => entry.openclaw?.providers?.some((provider) => envHasAny(params.env, provider.envVars) || [provider.id, ...provider.aliases ?? []].some((providerId) => { const normalized = normalizeOptionalLowercaseString(providerId); return normalized ? providerIds.has(normalized) : false; }))); } function hasOfficialExternalContractTarget(params) { const providerIds = normalizeIds(params.providerIds); if (providerIds.size === 0) return false; return STATIC_ENTRIES.some((entry) => entry.openclaw?.contracts?.[params.contract]?.some((providerId) => { const normalized = normalizeOptionalLowercaseString(providerId); return normalized ? providerIds.has(normalized) : false; })); } function hasOfficialExternalWebContractEnvTarget(params) { return STATIC_ENTRIES.some((entry) => { const manifest = entry.openclaw; const contractIds = normalizeIds(manifest?.contracts?.[params.contract] ?? []); return manifest?.webSearchProviders?.some((provider) => { const providerId = normalizeOptionalLowercaseString(provider.id); return Boolean(providerId && contractIds.has(providerId) && envHasAny(params.env, provider.envVars)); }); }); } function hasOfficialExternalChannelTarget(params) { const channels = isRecord(params.config.channels) ? params.config.channels : void 0; return STATIC_ENTRIES.some((entry) => { const channel = entry.openclaw?.channel; const channelId = normalizeOptionalLowercaseString(channel?.id); if (!channelId) return false; const channelConfig = channels?.[channelId]; return isRecord(channelConfig) && channelConfig.enabled !== false || envHasChannelCandidate(params.env, channel); }); } function hasOfficialExternalWebSearchTarget(params) { const configuredId = normalizeOptionalLowercaseString(params.providerId); return STATIC_ENTRIES.some((entry) => entry.openclaw?.webSearchProviders?.some((provider) => { const providerId = normalizeOptionalLowercaseString(provider.id); return configuredId !== void 0 && providerId === configuredId || envHasAny(params.env, provider.envVars); })); } //#endregion //#region src/commands/doctor/shared/startup-plugin-convergence-plan.ts function hasPotentialPluginConfig(config, env) { if (config.plugins?.enabled === false) return false; const entries = config.plugins?.entries; if (!isRecord(entries)) return false; return Object.entries(entries).some(([pluginId, entry]) => { if (isRecord(entry) && entry.enabled === false) return false; return !inspectBundledPluginStartupMetadata({ pluginId, env }); }); } function collectConfiguredMemoryEmbeddingProviderIds(config) { const providerIds = /* @__PURE__ */ new Set(); const add = (value) => { const providerId = normalizeOptionalLowercaseString(value); if (!providerId || providerId === "none" || providerId === "auto") return; providerIds.add(providerId); const ownerId = resolveConfiguredGenericEmbeddingProviderId(providerId, config); if (ownerId) providerIds.add(ownerId); }; const defaults = config.memory?.search; if (defaults?.enabled !== false) { add(defaults?.provider); add(defaults?.fallback); } for (const agent of listAgentEntries(config)) { const override = agent.memory?.search; if (override?.enabled === false) continue; add(override?.provider ?? defaults?.provider); add(override?.fallback ?? defaults?.fallback); } return providerIds; } function hasConfiguredCapabilityPlugin(config, env) { const memoryEmbeddingProviderIds = collectConfiguredMemoryEmbeddingProviderIds(config); if (memoryEmbeddingProviderIds.size > 0) { if (hasOfficialExternalContractTarget({ contract: "embeddingProviders", providerIds: memoryEmbeddingProviderIds })) return true; } if (hasOfficialExternalContractTarget({ contract: "speechProviders", providerIds: collectConfiguredSpeechProviderIds(config) })) return true; const webFetchProviderId = normalizeOptionalLowercaseString(config.tools?.web?.fetch?.provider); if (webFetchProviderId && hasOfficialExternalContractTarget({ contract: "webFetchProviders", providerIds: /* @__PURE__ */ new Set([webFetchProviderId]) })) return true; return hasOfficialExternalWebContractEnvTarget({ contract: "webFetchProviders", env }); } /** True when config or environment state can require a missing managed plugin repair. */ function configMayRequireStartupPluginConvergence(params) { if (params.config.plugins?.enabled === false) return false; if (hasPotentialPluginConfig(params.config, params.env)) return true; if (collectConfiguredRuntimePluginIds(params.config).length > 0) return true; if (hasOfficialExternalProviderTarget({ providerIds: collectConfiguredProviderSelectionIds(params.config), env: params.env })) return true; if (hasOfficialExternalChannelTarget(params)) return true; const webSearchProvider = params.config.tools?.web?.search?.provider; if (params.config.tools?.web?.search?.enabled !== false && hasOfficialExternalWebSearchTarget({ providerId: typeof webSearchProvider === "string" ? webSearchProvider : void 0, env: params.env })) return true; return hasConfiguredCapabilityPlugin(params.config, params.env); } /** Carries the canonical install-record snapshot into the expensive convergence pass. */ async function planStartupPluginConvergence(params) { const installRecords = await loadInstalledPluginIndexInstallRecords({ env: params.env }); return { required: Object.keys(installRecords).length > 0 || configMayRequireStartupPluginConvergence(params), installRecords }; } //#endregion export { inspectPluginStartupMetadata as i, planStartupPluginConvergence as n, inspectBundledPluginStartupMetadata as r, configMayRequireStartupPluginConvergence as t };