UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

376 lines (375 loc) 18.6 kB
import { f as withPluginCache, i as createPluginCache, l as getProcessPluginCache } from "./plugin-cache-DGWspMEc.js"; import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { y as resolveIsNixMode } from "./paths-D2sRr1a_.js"; import { o as redactSensitiveUrlLikeString } from "./redact-sensitive-url-BN1NZvXG.js"; import { a as getProcessGatewayPluginMetadataSnapshot } from "./current-plugin-metadata-state-B1UoAr4G.js"; import { i as isInstalledPluginEnabled, t as createInstalledPluginEnabledPredicate } from "./installed-plugin-index-wrDsjyMD.js"; import { a as projectPluginDependencyHealth, r as buildPluginDependencyStatus } from "./discovery-D_VDsZuY.js"; import { o as getOfficialExternalPluginCatalogManifest, p as listOfficialExternalPluginCatalogEntries, v as resolveOfficialExternalPluginId, x as resolveOfficialExternalPluginLabel } from "./official-external-plugin-catalog-Dzu7dwBN.js"; import { a as loadPluginMetadataSnapshot, c as resolvePluginMetadataSnapshot } from "./plugin-metadata-snapshot-w-4EjxI4.js"; import { n as resolvePluginControlPlaneWorkspace, t as appendPluginControlPlaneWorkspaceDiagnostic } from "./control-plane-workspace-BWhgt2gz.js"; import { t as createInstalledPluginOwnershipResolver } from "./installed-plugin-package-ownership-DGTVMT4h.js"; import { n as resolveConfigWidePluginMetadataSnapshot } from "./io.plugin-metadata-BruF5izX.js"; import { t as ManagedPluginLifecycleError } from "./management-lifecycle-error-BlJhejU6.js"; import { a as tracksPluginDependencyStatus } from "./official-external-plugin-repair-hints-CXeFydKX.js"; import { r as resolveManifestProviderAuthChoices } from "./provider-auth-choices-DsRM415K.js"; import { t as listRecommendedToolInstalls } from "./recommended-tool-installs-Bwv75ix-.js"; import { a as formatPluginCapabilityConsentRequired, c as resolvePluginInstallRecordIntegrity, l as resolvePluginInstallRecordTrust, n as buildPluginCapabilitySummary, r as computeDeclaredSurfaceHash, s as resolveAcceptedSurfaceCurrent, u as resolvePluginPackageDeclaredSurface } from "./capability-summary-BLe-gZ01.js"; import { i as resolvePendingPluginCapabilityReview } from "./capability-consent-DAQVy0Fy.js"; import { a as getManagedPluginCache, c as normalizeFeaturedAt, d as prepareCatalogEntry, f as resolveInstalledHostedOfficialEntry, h as withManagedPluginCache, i as firstPluginError, l as normalizeKinds, m as resolveOfficialEntryById, n as compareCatalogEntries, o as loadOfficialCatalog, p as resolveInstalledPluginPresentation, r as derivePluginCategory, s as normalizeCatalogMetadata, u as prepareCatalogEntries } from "./management-catalog-CoNziW12.js"; //#region src/plugins/management-service.ts function resolveManagedPluginDiagnostics(snapshot, config) { const dependencies = getManagedPluginCache().dependencyStatus; const isEnabled = createInstalledPluginEnabledPredicate(snapshot.index.plugins, config); const { diagnostics } = projectPluginDependencyHealth({ plugins: snapshot.index.plugins.map((record) => { const manifest = snapshot.byPluginId.get(record.pluginId); const enabled = isEnabled(record.pluginId); if (manifest && !dependencies.has(manifest) && tracksPluginDependencyStatus(record)) dependencies.set(manifest, buildPluginDependencyStatus({ rootDir: record.rootDir, dependencies: manifest.packageDependencies, optionalDependencies: manifest.packageOptionalDependencies })); return { id: record.pluginId, source: manifest?.source ?? record.source ?? record.manifestPath, enabled, status: enabled ? "loaded" : "disabled", dependencyStatus: manifest ? dependencies.get(manifest) : void 0 }; }), diagnostics: [...snapshot.diagnostics] }); return diagnostics; } function resolvePluginIconSource(params) { const normalizedPluginId = params.metadata.normalizePluginId(params.pluginId); const manifest = params.metadata.byPluginId.get(normalizedPluginId); const localIconPath = normalizeOptionalString(manifest?.iconPath); if (localIconPath && manifest) return { kind: "file", path: localIconPath, rootPath: manifest.rootDir }; } function resolveManagedPluginMetadataParams(config, env) { const workspace = resolvePluginControlPlaneWorkspace({ config, env }); return { config, env, ...workspace.workspaceDir !== void 0 ? { workspaceDir: workspace.workspaceDir } : {} }; } function resolveManagedPluginMetadata(config, env) { const boot = getProcessGatewayPluginMetadataSnapshot(); const candidate = getProcessPluginCache().desiredMetadata; return candidate && candidate.boot === boot ? candidate.snapshot : resolvePluginMetadataSnapshot(resolveManagedPluginMetadataParams(config, env)); } function loadFreshManagedPluginMetadata(config, env) { return getProcessGatewayPluginMetadataSnapshot() ? resolveConfigWidePluginMetadataSnapshot({ config, env, allowCurrent: false }) : loadPluginMetadataSnapshot({ ...resolveManagedPluginMetadataParams(config, env), allowCurrent: false }); } /** Publish desired install state for management without replacing the Gateway's boot facts. */ function refreshManagedPluginMetadata(params) { const env = params.env ?? process.env; const boot = getProcessGatewayPluginMetadataSnapshot(); const cache = createPluginCache(); const snapshot = withPluginCache(cache, () => loadFreshManagedPluginMetadata(params.config, env)); if (boot) getProcessPluginCache().desiredMetadata = { boot, cache, snapshot }; return snapshot; } /** Resolve the current package-local icon without accepting caller-provided input. */ const resolveManagedPluginIconSource = withManagedPluginCache(async (params) => { const env = params.env ?? process.env; return resolvePluginIconSource({ metadata: resolveManagedPluginMetadata(params.config, env), pluginId: params.pluginId }); }); function normalizeManagedCatalogIconUrl(value) { const normalized = normalizeOptionalString(value); if (!normalized || normalized.length > 2048) return; try { const url = new URL(normalized); return url.protocol === "https:" && url.hostname && !url.username && !url.password && !url.hash ? url.href : void 0; } catch { return; } } /** Resolve only URLs currently owned by a manifest or bundled presentation catalog. */ function resolveManagedSetupCatalogIconUrl(params) { const requested = normalizeManagedCatalogIconUrl(params.iconUrl); if (!requested) return; const env = params.env ?? process.env; return [...resolveManifestProviderAuthChoices({ config: params.config, env, includeUntrustedWorkspacePlugins: false, includeWorkspacePlugins: false }).map((choice) => choice.icon), ...listRecommendedToolInstalls().map((install) => install.icon)].some((iconUrl) => normalizeManagedCatalogIconUrl(iconUrl) === requested) ? requested : void 0; } /** Build cold installed state merged with the hosted official catalog and bundled curation. */ const listManagedPlugins = withManagedPluginCache(async (params) => { const env = params.env ?? process.env; const workspace = resolvePluginControlPlaneWorkspace({ config: params.config, env }); const metadata = params.metadata ?? resolveManagedPluginMetadata(params.config, env); const pluginDiagnostics = resolveManagedPluginDiagnostics(metadata, params.config); const officialCatalog = params.officialCatalog ?? await loadOfficialCatalog(); const officialEntries = prepareCatalogEntries(officialCatalog.entries); const bundledOfficialEntries = prepareCatalogEntries(listOfficialExternalPluginCatalogEntries()); const installedIconsById = /* @__PURE__ */ new Map(); const installedClawHubPackages = /* @__PURE__ */ new Set(); const capabilityConsentDiagnostics = []; const isEnabled = createInstalledPluginEnabledPredicate(metadata.index.plugins, params.config, env); const ownershipResolver = createInstalledPluginOwnershipResolver(metadata.index); const plugins = metadata.index.plugins.map((record) => { const enabled = isEnabled(record.pluginId); const manifest = metadata.byPluginId.get(record.pluginId); const localCatalog = normalizeCatalogMetadata(manifest?.catalog); const ownership = ownershipResolver.resolvePackage(record.pluginId); const installOwner = ownership.ok ? ownership.value.installOwner : void 0; const installRecord = installOwner ? metadata.index.installRecords[installOwner] : void 0; if (enabled && record.origin !== "bundled" && !manifest?.trustedOfficialInstall && ownership.ok && installRecord) { const declared = resolvePluginPackageDeclaredSurface(ownership.value, metadata.byPluginId); if (!declared || !resolveAcceptedSurfaceCurrent(installRecord, declared)) capabilityConsentDiagnostics.push({ level: "warn", pluginId: record.pluginId, message: formatPluginCapabilityConsentRequired(record.pluginId) }); } const { entry: officialEntry, clawhubPackage } = resolveInstalledHostedOfficialEntry({ record, ...installOwner ? { installOwner } : {}, installRecord, officialEntries, bundledOfficialEntries }); if (clawhubPackage) installedClawHubPackages.add(clawhubPackage); const officialCatalogMetadata = officialEntry ? normalizeCatalogMetadata(getOfficialExternalPluginCatalogManifest(officialEntry)?.catalog) : void 0; const catalog = clawhubPackage && officialCatalog.hostedFeaturedAuthoritative ? { ...localCatalog, ...officialCatalogMetadata, featured: officialEntry?.featured === true } : officialCatalogMetadata ? { ...localCatalog, ...officialCatalogMetadata } : localCatalog; const error = firstPluginError(pluginDiagnostics, record.pluginId); const kind = normalizeKinds(manifest?.kind); const category = derivePluginCategory(manifest); const removable = record.origin !== "bundled" && Boolean(installOwner); const hostedListingAuthoritative = Boolean(clawhubPackage) && officialCatalog.hostedFeaturedAuthoritative === true; const featuredAt = hostedListingAuthoritative && catalog?.featured === true ? normalizeFeaturedAt(officialEntry?.featuredAt) : void 0; const presentation = resolveInstalledPluginPresentation({ record, manifest, officialEntry, hostedListingAuthoritative }); const plugin = { id: record.pluginId, name: presentation.name, installed: true, enabled, state: error ? "error" : enabled ? "enabled" : "disabled", removable }; if (record.packageName) plugin.packageName = record.packageName; if (presentation.description) plugin.description = presentation.description; if (presentation.version) plugin.version = presentation.version; if (kind) plugin.kind = kind; if (record.origin) plugin.origin = record.origin; if (catalog?.featured !== void 0) plugin.featured = catalog.featured; if (featuredAt !== void 0) plugin.featuredAt = featuredAt; if (catalog?.order !== void 0) plugin.order = catalog.order; const normalizedPluginId = metadata.normalizePluginId(record.pluginId); if (!installedIconsById.has(normalizedPluginId)) installedIconsById.set(normalizedPluginId, resolvePluginIconSource({ metadata, pluginId: record.pluginId })); if (installedIconsById.get(normalizedPluginId)) plugin.hasIcon = true; if (error) plugin.error = error; if (category) plugin.category = category; return plugin; }); const installedIds = new Set(plugins.map((plugin) => plugin.id)); const installedPackageNames = new Set(plugins.flatMap((plugin) => plugin.packageName ? [plugin.packageName] : [])); for (const facts of officialEntries()) { const { entry, clawhub, npmPackage } = facts; const pluginId = resolveOfficialExternalPluginId(entry); const manifest = getOfficialExternalPluginCatalogManifest(entry); const manifestCatalog = normalizeCatalogMetadata(manifest?.catalog); const catalog = manifestCatalog || typeof entry.featured === "boolean" ? { ...manifestCatalog, ...manifestCatalog?.featured === void 0 && typeof entry.featured === "boolean" ? { featured: entry.featured } : {} } : void 0; if (!pluginId || !catalog || installedIds.has(pluginId) || clawhub && (installedPackageNames.has(clawhub.name) || installedClawHubPackages.has(clawhub.name)) || npmPackage && installedPackageNames.has(npmPackage)) continue; const kind = normalizeKinds(entry.kind); const install = facts.selectedSource?.source === "clawhub" && clawhub && !clawhub.version ? { source: "clawhub", packageName: clawhub.name } : facts.install ? { source: "official", pluginId } : void 0; const packageName = npmPackage ?? clawhub?.name; const description = normalizeOptionalString(entry.description); const version = normalizeOptionalString(entry.version); const featuredAt = catalog.featured === true ? normalizeFeaturedAt(entry.featuredAt) : void 0; plugins.push({ id: pluginId, name: resolveOfficialExternalPluginLabel(entry), ...packageName ? { packageName } : {}, ...description ? { description } : {}, ...version ? { version } : {}, ...kind ? { kind } : {}, origin: "official", installed: false, enabled: false, state: "not-installed", ...catalog.featured !== void 0 ? { featured: catalog.featured } : {}, ...featuredAt !== void 0 ? { featuredAt } : {}, ...catalog.order !== void 0 ? { order: catalog.order } : {}, ...install ? { install } : {} }); } const diagnostics = getProcessGatewayPluginMetadataSnapshot() ? [...pluginDiagnostics, ...capabilityConsentDiagnostics] : appendPluginControlPlaneWorkspaceDiagnostic([...pluginDiagnostics, ...capabilityConsentDiagnostics], workspace); if (officialCatalog.error) diagnostics.push({ level: "warn", message: `Official plugin catalog fallback: ${officialCatalog.error}` }); return { plugins: plugins.toSorted(compareCatalogEntries), diagnostics, mutationAllowed: !resolveIsNixMode(env) }; }); /** Inspect one plugin's manifest, operator grants, and recorded install provenance. */ const inspectManagedPlugin = withManagedPluginCache(async (params) => { const env = params.env ?? process.env; const metadata = resolveManagedPluginMetadata(params.config, env); const pluginId = metadata.normalizePluginId(params.pluginId); const record = metadata.index.plugins.find((candidate) => candidate.pluginId === pluginId); const enabled = isInstalledPluginEnabled(metadata.index, pluginId, params.config); const pendingReview = resolvePendingPluginCapabilityReview(pluginId); if (pendingReview) return { ok: true, plugin: { id: pluginId, name: pendingReview.name, ...pendingReview.version ? { version: pendingReview.version } : {}, ...record?.origin ? { origin: record.origin } : {}, installed: Boolean(record), enabled }, declared: pendingReview.declared, grants: pendingReview.grants, reviewToken: pendingReview.reviewToken, ...pendingReview.source ? { source: pendingReview.source } : {}, ...pendingReview.trust ? { trust: pendingReview.trust } : {} }; const officialCatalog = await loadOfficialCatalog(); if (record) { const manifest = metadata.byPluginId.get(pluginId); const ownership = createInstalledPluginOwnershipResolver(metadata.index, env).resolvePackage(pluginId); const installOwner = ownership.ok ? ownership.value.installOwner : void 0; const installRecord = installOwner ? metadata.index.installRecords[installOwner] : void 0; const { entry: officialEntry, clawhubPackage } = resolveInstalledHostedOfficialEntry({ record, ...installOwner ? { installOwner } : {}, installRecord, officialEntries: prepareCatalogEntries(officialCatalog.entries), bundledOfficialEntries: prepareCatalogEntries(listOfficialExternalPluginCatalogEntries()) }); const spec = installRecord?.resolvedSpec ?? installRecord?.spec; const packageName = installRecord?.clawhubPackage ?? record.packageName; const source = installRecord ? { kind: installRecord.source, ...spec ? { spec: redactSensitiveUrlLikeString(spec) } : {}, ...packageName ? { packageName } : {}, ...resolvePluginInstallRecordIntegrity(installRecord) } : record.origin === "bundled" ? { kind: "bundled" } : void 0; const trust = resolvePluginInstallRecordTrust(installRecord); const summary = buildPluginCapabilitySummary({ manifest: manifest ?? {}, origin: record.origin, entryConfig: params.config.plugins?.entries?.[pluginId] }); const declared = ownership.ok ? resolvePluginPackageDeclaredSurface(ownership.value, metadata.byPluginId) : summary.declared; if (!declared) throw new ManagedPluginLifecycleError(`Plugin package "${installOwner}" has incomplete manifest metadata.`); return { ok: true, plugin: { id: pluginId, ...resolveInstalledPluginPresentation({ record, manifest, officialEntry, hostedListingAuthoritative: Boolean(clawhubPackage) && officialCatalog.hostedFeaturedAuthoritative === true }), origin: record.origin, installed: true, enabled }, ...source ? { source } : {}, ...summary, declared, reviewToken: computeDeclaredSurfaceHash(declared), ...trust ? { trust } : {} }; } const entry = resolveOfficialEntryById(officialCatalog.entries, pluginId); if (!entry) throw new ManagedPluginLifecycleError(`Plugin "${pluginId}" not found.`, { kind: "invalid-request" }); const manifest = getOfficialExternalPluginCatalogManifest(entry); const { selectedSource, clawhub, npmPackage } = prepareCatalogEntry(entry); const packageName = npmPackage ?? clawhub?.name; const spec = selectedSource?.spec; const description = normalizeOptionalString(entry.description); const version = normalizeOptionalString(entry.version); const summary = buildPluginCapabilitySummary({ manifest: manifest ?? {}, origin: "official", entryConfig: params.config.plugins?.entries?.[pluginId] }); return { ok: true, plugin: { id: pluginId, name: resolveOfficialExternalPluginLabel(entry), ...version ? { version } : {}, ...description ? { description } : {}, origin: "official", installed: false, enabled: false }, source: { kind: "official-catalog", ...spec ? { spec: redactSensitiveUrlLikeString(spec) } : {}, ...packageName ? { packageName } : {}, ...selectedSource?.expectedIntegrity ? { integrity: selectedSource.expectedIntegrity, integrityKind: selectedSource.source === "clawhub" ? "sha256" : "ssri" } : {} }, ...summary, reviewToken: computeDeclaredSurfaceHash(summary.declared) }; }); //#endregion export { resolveManagedPluginIconSource as a, refreshManagedPluginMetadata as i, listManagedPlugins as n, resolveManagedSetupCatalogIconUrl as o, loadFreshManagedPluginMetadata as r, inspectManagedPlugin as t };