openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
184 lines (183 loc) • 8.31 kB
JavaScript
import { o as redactSensitiveUrlLikeString } from "./redact-sensitive-url-BN1NZvXG.js";
import { t as PLUGIN_DECLARED_SURFACE_GROUPS } from "./plugin-declared-surface-groups-CaZZpMBC.js";
import { n as resolvePromptInjectionAllowed, t as resolveConversationAccessAllowed } from "./hook-policy-decisions-DL3kOjGW.js";
import { createHash } from "node:crypto";
//#region src/plugins/capability-summary.ts
const REVIEWED_MANIFEST_CONTRACT_FAMILIES = [
"embeddedExtensionFactories",
"agentToolResultMiddleware",
"trustedToolPolicies",
"externalAuthProviders",
"embeddingProviders",
"speechProviders",
"realtimeTranscriptionProviders",
"realtimeVoiceProviders",
"mediaUnderstandingProviders",
"transcriptSourceProviders",
"documentExtractors",
"imageGenerationProviders",
"videoGenerationProviders",
"musicGenerationProviders",
"webContentExtractors",
"webFetchProviders",
"webSearchProviders",
"workerProviders",
"usageProviders",
"migrationProviders",
"gatewayMethodDispatch",
"tools"
];
function diffDeclaredSurfaceWidening(previous, next) {
const widened = {};
for (const group of PLUGIN_DECLARED_SURFACE_GROUPS) {
const previousValues = new Set(previous[group]);
const added = next[group].filter((value) => !previousValues.has(value)).toSorted();
if (added.length > 0) widened[group] = added;
}
return {
widened,
hasWidening: Object.keys(widened).length > 0
};
}
function mergePluginDeclaredSurfaces(surfaces) {
const merged = {
channels: [],
providers: [],
tools: [],
contracts: [],
hooks: [],
mcpServers: [],
cliCommands: [],
cliBackends: [],
skills: [],
dangerousConfigFlags: []
};
for (const surface of surfaces) for (const group of PLUGIN_DECLARED_SURFACE_GROUPS) merged[group].push(...surface[group]);
for (const group of PLUGIN_DECLARED_SURFACE_GROUPS) merged[group] = [...new Set(merged[group])].toSorted();
return merged;
}
/** Acceptance belongs to the package; missing siblings must never shrink its review. */
function resolvePluginPackageDeclaredSurface(ownership, manifests) {
const surfaces = [];
for (const pluginId of ownership.pluginIds) {
const manifest = manifests.get(pluginId);
if (!manifest) return;
surfaces.push(buildPluginCapabilitySummary({
manifest,
origin: manifest.origin
}).declared);
}
return mergePluginDeclaredSurfaces(surfaces);
}
function computeDeclaredSurfaceHash(declared) {
const canonical = Object.fromEntries(PLUGIN_DECLARED_SURFACE_GROUPS.map((group) => [group, declared[group].toSorted()]));
return createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
}
function resolvePluginInstallRecordIntegrity(record) {
const npmIntegrity = record.integrity ?? record.npmIntegrity;
if (npmIntegrity) return {
integrity: npmIntegrity,
integrityKind: "ssri"
};
if (record.clawpackSha256) return {
integrity: record.clawpackSha256,
integrityKind: "sha256"
};
return record.gitCommit ? {
integrity: record.gitCommit,
integrityKind: "git-commit"
} : void 0;
}
function resolveAcceptedSurfaceCurrent(record, declared) {
return record.acceptedSurface !== void 0 && record.acceptedSurfaceHash !== void 0 && record.acceptedSurfaceHash === computeDeclaredSurfaceHash(record.acceptedSurface) && record.acceptedSurfaceHash === computeDeclaredSurfaceHash(declared) && record.acceptedSurfaceIntegrity === resolvePluginInstallRecordIntegrity(record)?.integrity;
}
function formatPluginCapabilityConsentRequired(pluginId) {
return `Plugin "${pluginId}" requires capability consent; disable and re-enable it or run \`openclaw plugins enable ${pluginId} --accept-capabilities\`.`;
}
function buildHookGrant(effective, configured) {
return {
effective,
...typeof configured === "boolean" ? { configured } : {}
};
}
function buildPluginCapabilitySummary(params) {
const { manifest, entryConfig } = params;
const hooks = entryConfig?.hooks;
const llm = entryConfig?.llm;
const subagent = entryConfig?.subagent;
return {
declared: {
channels: (manifest.channels ?? (manifest.channel?.id ? [manifest.channel.id] : [])).toSorted(),
providers: (manifest.providers ?? []).flatMap((provider) => typeof provider === "string" ? [provider] : provider.id ? [provider.id] : []).toSorted(),
tools: [.../* @__PURE__ */ new Set([...manifest.contracts?.tools ?? [], ...Object.keys(manifest.toolMetadata ?? {})])].toSorted(),
contracts: [...new Set(REVIEWED_MANIFEST_CONTRACT_FAMILIES.flatMap((family) => (manifest.contracts?.[family] ?? []).map((id) => `${family}: ${id}`)))].toSorted(),
hooks: (manifest.hooks ?? []).toSorted(),
mcpServers: Object.keys(manifest.mcpServers ?? {}).toSorted(),
cliCommands: (manifest.cliCommands ?? []).map((command) => command.name).toSorted(),
cliBackends: (manifest.cliBackends ?? []).toSorted(),
skills: (manifest.skills ?? []).toSorted(),
dangerousConfigFlags: (manifest.configContracts?.dangerousFlags ?? []).map((flag) => flag.path).toSorted()
},
grants: {
hooks: {
allowPromptInjection: buildHookGrant(resolvePromptInjectionAllowed(hooks), hooks?.allowPromptInjection),
allowConversationAccess: buildHookGrant(resolveConversationAccessAllowed(params.origin, hooks), hooks?.allowConversationAccess)
},
...llm ? { llm: {
...llm.allowModelOverride !== void 0 ? { allowModelOverride: llm.allowModelOverride } : {},
...llm.allowedModels ? { allowedModels: llm.allowedModels.toSorted() } : {},
...llm.allowedCompletionModels ? { allowedCompletionModels: llm.allowedCompletionModels.toSorted() } : {},
...llm.allowAuthProfileOverride !== void 0 ? { allowAuthProfileOverride: llm.allowAuthProfileOverride } : {},
...llm.allowAgentIdOverride !== void 0 ? { allowAgentIdOverride: llm.allowAgentIdOverride } : {}
} } : {},
...subagent ? { subagent: {
...subagent.allowModelOverride !== void 0 ? { allowModelOverride: subagent.allowModelOverride } : {},
...subagent.allowedModels ? { allowedModels: subagent.allowedModels.toSorted() } : {}
} } : {}
}
};
}
function resolvePluginInstallRecordTrust(record) {
if (!record?.clawhubTrustDisposition) return;
return {
disposition: record.clawhubTrustDisposition,
...record.clawhubTrustReasons ? { reasons: [...record.clawhubTrustReasons] } : {},
...record.clawhubTrustCheckedAt ? { checkedAt: record.clawhubTrustCheckedAt } : {},
...record.clawhubTrustAcknowledgedAt ? { acknowledgedAt: record.clawhubTrustAcknowledgedAt } : {},
...record.clawhubTrustPending !== void 0 ? { pending: record.clawhubTrustPending } : {},
...record.clawhubTrustStale !== void 0 ? { stale: record.clawhubTrustStale } : {}
};
}
function buildPluginCapabilityConsentReview(params) {
const { pluginId, manifest, record } = params;
const summary = buildPluginCapabilitySummary({
manifest,
origin: "global",
entryConfig: params.config.plugins?.entries?.[pluginId]
});
const declared = params.declared ?? summary.declared;
const spec = record.resolvedSpec ?? record.spec;
const packageName = record.clawhubPackage ?? record.resolvedName;
const previousDeclared = params.previousDeclared ?? record.acceptedSurface;
const widened = params.widened ?? (previousDeclared ? diffDeclaredSurfaceWidening(previousDeclared, declared).widened : void 0);
const trust = resolvePluginInstallRecordTrust(record);
return {
pluginId,
name: manifest.name ?? pluginId,
...manifest.version ?? record.version ? { version: manifest.version ?? record.version } : {},
...summary,
declared,
reviewToken: computeDeclaredSurfaceHash(declared),
source: {
kind: record.source,
...spec ? { spec: redactSensitiveUrlLikeString(spec) } : {},
...packageName ? { packageName } : {},
...resolvePluginInstallRecordIntegrity(record)
},
...trust ? { trust } : {},
...widened && Object.keys(widened).length > 0 ? { widened } : {},
...record.acceptedSurfaceAt ? { acceptedAt: record.acceptedSurfaceAt } : {}
};
}
//#endregion
export { formatPluginCapabilityConsentRequired as a, resolvePluginInstallRecordIntegrity as c, diffDeclaredSurfaceWidening as i, resolvePluginInstallRecordTrust as l, buildPluginCapabilitySummary as n, mergePluginDeclaredSurfaces as o, computeDeclaredSurfaceHash as r, resolveAcceptedSurfaceCurrent as s, buildPluginCapabilityConsentReview as t, resolvePluginPackageDeclaredSurface as u };