UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

304 lines (303 loc) 13.5 kB
import { a as addTimerTimeoutGraceMs } from "./number-coercion-CLj0HTDM.js"; import { n as collectUniqueCommandDescriptors } from "./command-descriptor-utils-DII8rwLT.js"; import { f as withPluginCache, i as createPluginCache } from "./plugin-cache-DGWspMEc.js"; import { t as stableStringify } from "./stable-stringify-C8X7niaI.js"; import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js"; import { y as uniqueStrings } from "./string-normalization-DsCfAx8q.js"; import { t as createLazyImportLoader } from "./lazy-promise-DGqyc4Y4.js"; import { n as getRuntimeConfig } from "./io.runtime-B9iJRs3w.js"; import { w as resolveStateDir } from "./paths-D2sRr1a_.js"; import { t as createSubsystemLogger } from "./subsystem-Dy2tqXOS.js"; import { r as getCurrentPluginMetadataSnapshotState } from "./current-plugin-metadata-state-B1UoAr4G.js"; import { f as resolvePluginMetadataEnvFingerprint } from "./current-plugin-metadata-snapshot-CmSX4G3W.js"; import { c as resolvePluginMetadataSnapshot } from "./plugin-metadata-snapshot-w-4EjxI4.js"; import { n as resolvePluginControlPlaneWorkspace } from "./control-plane-workspace-BWhgt2gz.js"; import { n as cloneEnvWithPlatformSemantics } from "./config-env-vars-DUfQlcAk.js"; import { n as resolveManifestActivationPluginIds } from "./activation-planner-ByTGTikc.js"; import { t as resolvePluginActivationSourceConfig } from "./activation-source-config-DnARnJdS.js"; import { u as normalizeOperatorScopeList } from "./operator-scopes-Dw7Gu2cA.js"; import { i as GATEWAY_CLIENT_NAMES, r as GATEWAY_CLIENT_MODES } from "./client-info-B1bPgeKr.js"; import "./config-Cs0XXL3x.js"; import { t as createEmptyPluginRegistry } from "./registry-empty-55wlVNzO.js"; import { a as getPluginRuntimeGatewayRequestScope } from "./gateway-request-scope-BCMYlsDI.js"; import { a as loadOpenClawPluginCliRegistry, n as loadPluginRegistryHandle } from "./loader-DPiOPJjR.js"; import { r as createPluginRuntimeLoaderLogger, t as buildPluginRuntimeLoadOptions } from "./load-context-BdeWeJHL.js"; import { t as resolvePluginRuntimeLoadContext } from "./load-context.resolve-O967gh1f.js"; import { randomUUID } from "node:crypto"; //#region src/plugins/cli-gateway-nodes-runtime.ts /** Provides plugin CLI node APIs by forwarding calls to the Gateway. */ const gatewayCallModuleLoader = createLazyImportLoader(() => import("./call-Bo4Qx1ax.js")); /** Adds Gateway timer grace for plugin CLI node invoke calls. */ function resolvePluginCliNodeInvokeGatewayTimeoutMs(timeoutMs) { return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? addTimerTimeoutGraceMs(timeoutMs) : void 0; } function canPluginCliRuntimeRequestScopes() { const scope = getPluginRuntimeGatewayRequestScope(); return Boolean(scope?.pluginId && (scope.pluginOrigin === "bundled" || scope.pluginTrustedOfficialInstall === true)); } function resolvePluginCliRuntimeNodeInvokeScopes(scopes) { const normalizedScopes = normalizeOperatorScopeList(scopes); return normalizedScopes && canPluginCliRuntimeRequestScopes() ? normalizedScopes : void 0; } /** Creates the `runtime.nodes` implementation exposed to CLI plugin code. */ function createPluginCliGatewayNodesRuntime() { return { async list(params) { const { callGateway } = await gatewayCallModuleLoader.load(); const payload = await callGateway({ method: "node.list", params: {}, clientName: GATEWAY_CLIENT_NAMES.CLI, mode: GATEWAY_CLIENT_MODES.CLI }); const nodes = Array.isArray(payload?.nodes) ? payload.nodes : []; return { nodes: params?.connected === true ? nodes.filter((node) => node !== null && typeof node === "object" && node.connected === true) : nodes }; }, async invoke(params) { const { callGateway } = await gatewayCallModuleLoader.load(); const scopes = resolvePluginCliRuntimeNodeInvokeScopes(params.scopes); return await callGateway({ method: "node.invoke", params: { nodeId: params.nodeId, command: params.command, ...params.params !== void 0 && { params: params.params }, timeoutMs: params.timeoutMs, idempotencyKey: params.idempotencyKey || randomUUID(), ...params.sessionKey ? { sessionKey: params.sessionKey } : {} }, timeoutMs: resolvePluginCliNodeInvokeGatewayTimeoutMs(params.timeoutMs), clientName: GATEWAY_CLIENT_NAMES.CLI, mode: GATEWAY_CLIENT_MODES.CLI, ...scopes ? { scopes } : {}, ...params.signal ? { signal: params.signal } : {} }); }, async openDuplex() { throw new Error("Node duplex is unavailable in the CLI; run this plugin inside the Gateway."); } }; } //#endregion //#region src/plugins/cli-registry-loader.ts /** Loads plugin CLI registrations lazily for the command tree and plugin-owned subcommands. */ const log = createSubsystemLogger("plugins/cli-registry-loader"); /** Invocation authority closes before actions; its package generation lives through them. */ function createPluginCliLoadSession(cache = createPluginCache()) { const withCache = (run) => withPluginCache(cache, run); let closed = false; let revision = getCurrentPluginMetadataSnapshotState().revision; let current; const assertOpen = () => { if (closed) throw new Error("Plugin CLI preparation is closed; start a new registration operation."); }; const refreshRevision = () => { assertOpen(); const next = getCurrentPluginMetadataSnapshotState().revision; if (next !== revision) { revision = next; current = void 0; } }; const assertRevision = (captured) => { assertOpen(); if (captured !== getCurrentPluginMetadataSnapshotState().revision) throw new Error("Plugin CLI preparation was invalidated; start a new registration operation."); }; return { withCache, readConfig: async (read) => { refreshRevision(); const captured = revision; const result = await withCache(read); assertRevision(captured); return result; }, close: () => { closed = true; current = void 0; }, resolve: (params) => withCache(() => { refreshRevision(); const config = params.cfg ?? getRuntimeConfig(); const activationSourceConfig = resolvePluginActivationSourceConfig({ config }); const env = params.env ?? process.env; const inputKey = () => stableStringify([ config, resolvePluginActivationSourceConfig({ config }), env, resolvePluginControlPlaneWorkspace({ config, env }), resolvePluginMetadataEnvFingerprint(env), resolveStateDir(env), params.primaryCommand ]); const key = inputKey(); const sdk = params.loaderOptions?.pluginSdkResolution; if (current?.key === key && current.logger === params.logger && current.env === env && current.sdk === sdk && current.prepared.context.rawConfig === config && current.prepared.context.activationSourceConfig === activationSourceConfig) return current.prepared; const preparedEnv = cloneEnvWithPlatformSemantics(env); const { workspaceDir } = resolvePluginControlPlaneWorkspace({ config, env: preparedEnv }); const metadataSnapshot = resolvePluginMetadataSnapshot({ config, env: preparedEnv, workspaceDir, allowCurrent: false }); const context = resolvePluginRuntimeLoadContext({ config, activationSourceConfig, env: preparedEnv, workspaceDir, metadataSnapshot, logger: params.logger ?? createPluginCliLogger() }); const captured = revision; const prepared = { context, withCache, assertCurrent() { assertRevision(captured); if (current?.prepared !== prepared || key !== inputKey() || params.cfg !== void 0 && params.cfg !== config || (params.env ?? process.env) !== env || activationSourceConfig !== resolvePluginActivationSourceConfig({ config }) || current.sdk !== params.loaderOptions?.pluginSdkResolution || current.logger !== params.logger) throw new Error("Plugin CLI preparation inputs changed; start a new registration operation."); } }; current = { key, sdk, logger: params.logger, env, prepared }; prepared.assertCurrent(); return prepared; }) }; } function resolvePreparedPluginCliLoad(params) { return (params.session ?? createPluginCliLoadSession()).resolve(params); } /** Creates the default plugin CLI logger shared with runtime loading. */ function createPluginCliLogger() { return createPluginRuntimeLoaderLogger(); } function resolvePrimaryCommandManifestPluginIds(context, primaryCommand) { const normalizedPrimary = normalizeLowercaseStringOrEmpty(primaryCommand); if (!normalizedPrimary) return; return resolveManifestActivationPluginIds({ trigger: { kind: "command", command: normalizedPrimary }, config: context.activationSourceConfig, workspaceDir: context.workspaceDir, env: context.env, manifestRecords: context.manifestRegistry?.plugins }); } function listPluginCliRootOwnerIds(registry, primaryCommand) { const normalizedPrimary = normalizeLowercaseStringOrEmpty(primaryCommand); if (!normalizedPrimary) return []; return uniqueStrings(registry.cliRegistrars.filter((entry) => { const parentPath = entry.parentPath ?? []; return (parentPath.length > 0 ? [parentPath[0]] : [...entry.commands, ...entry.descriptors.map((descriptor) => descriptor.name)]).includes(normalizedPrimary); }).map((entry) => entry.pluginId)); } async function resolvePrimaryCommandPluginIds(prepared, primaryCommand, loaderOptions) { prepared.assertCurrent(); const { context } = prepared; const normalizedPrimary = normalizeLowercaseStringOrEmpty(primaryCommand); if (!normalizedPrimary) return; const manifestPluginIds = resolvePrimaryCommandManifestPluginIds(context, normalizedPrimary); if (manifestPluginIds && manifestPluginIds.length > 0) return manifestPluginIds; const registry = await loadPluginCliMetadataRegistryWithContext(prepared, { primaryCommand: normalizedPrimary }, loaderOptions); prepared.assertCurrent(); return listPluginCliRootOwnerIds(registry, normalizedPrimary); } async function loadPluginCliMetadataRegistryWithContext(prepared, params, loaderOptions) { const onlyPluginIds = resolvePrimaryCommandManifestPluginIds(prepared.context, params?.primaryCommand); prepared.assertCurrent(); const registry = await (prepared.metadataRegistry ??= prepared.withCache(() => loadOpenClawPluginCliRegistry(buildPluginRuntimeLoadOptions(prepared.context, { ...loaderOptions, cache: false, ...onlyPluginIds && onlyPluginIds.length > 0 ? { onlyPluginIds } : {} })))); prepared.assertCurrent(); return registry; } async function loadPluginCliCommandRegistryWithContext(params) { const { context } = params.prepared; let onlyPluginIds; try { onlyPluginIds = await resolvePrimaryCommandPluginIds(params.prepared, params.primaryCommand, params.loaderOptions); } catch { onlyPluginIds = resolvePrimaryCommandManifestPluginIds(context, params.primaryCommand); } params.prepared.assertCurrent(); if (onlyPluginIds && onlyPluginIds.length === 0) return createEmptyPluginRegistry(); return params.prepared.withCache(() => loadPluginRegistryHandle(buildPluginRuntimeLoadOptions(context, { ...params.loaderOptions, ...onlyPluginIds && onlyPluginIds.length > 0 ? { onlyPluginIds } : {}, cache: false, channelPluginLoadIntent: "full", runtimeOptions: { nodes: createPluginCliGatewayNodesRuntime() } }))); } function buildPluginCliCommandGroupEntries(params) { return params.registry.cliRegistrars.map((entry) => ({ pluginId: entry.pluginId, parentPath: entry.parentPath ?? [], placeholders: entry.descriptors, names: entry.commands, register: async (program) => { params.assertCurrent(); await params.withCache(() => entry.register({ program, parentPath: entry.parentPath ?? [], config: params.config, workspaceDir: params.workspaceDir, logger: params.logger })); params.assertCurrent(); } })); } async function loadPluginCliDescriptors(params) { try { const registry = await loadPluginCliMetadataRegistryWithContext(resolvePreparedPluginCliLoad(params), { primaryCommand: params.primaryCommand }, params.loaderOptions); return collectUniqueCommandDescriptors(registry.cliRegistrars.filter((entry) => (entry.parentPath ?? []).length === 0).map((entry) => entry.descriptors)); } catch (error) { log.warn(`plugin CLI descriptor load failed: ${String(error)}`); return []; } } async function loadPluginCliRegistrationEntriesWithDefaults(params) { const prepared = resolvePreparedPluginCliLoad(params); const entries = await (prepared.entries ??= loadPluginCliCommandRegistryWithContext({ prepared, primaryCommand: params.primaryCommand, loaderOptions: params.loaderOptions }).then((registry) => { prepared.assertCurrent(); return buildPluginCliCommandGroupEntries({ ...prepared.context, registry, assertCurrent: prepared.assertCurrent, withCache: prepared.withCache }); })); prepared.assertCurrent(); return entries; } async function resolvePluginCliRootOwnerIds(params) { const primaryCommand = normalizeLowercaseStringOrEmpty(params.primaryCommand); if (!primaryCommand) return null; const prepared = resolvePreparedPluginCliLoad(params); const ownerIds = await resolvePrimaryCommandPluginIds(prepared, primaryCommand, params.loaderOptions); prepared.assertCurrent(); return ownerIds ?? null; } //#endregion export { resolvePluginCliRootOwnerIds as a, loadPluginCliRegistrationEntriesWithDefaults as i, createPluginCliLogger as n, loadPluginCliDescriptors as r, createPluginCliLoadSession as t };