mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 22:21:35 +00:00
* refactor(config): consolidate media model lists * refactor(config): unify memory configuration * refactor(config): consolidate TTS ownership * refactor(config): move typing policy to agents * refactor(config): retire product-level config surfaces * refactor(config): share scoped tool policy type * chore(config): refresh generated baselines * fix(config): honor agent typing overrides * fix(config): migrate sibling config consumers * refactor(infra): keep base64url decoder private * fix(config): strip invalid legacy TTS values * chore(config): refresh rebased baseline hash * fix(doctor): route legacy messages.tts.realtime voice to talk during tts move * refactor(config): polish final layout names * refactor(config): freeze retired tuning defaults * feat(config): add fast mode default symmetry * refactor(config): key agent entries by id * docs(config): update final layout reference * test(config): cover final layout migrations * chore(config): refresh final layout baselines * fix(config): align final layout runtime readers * fix(config): align remaining readers * fix(config): stabilize final layout migrations * fix(config): finalize config projection proof * fix(config): address final layout review * docs(release): preserve historical config names * fix(config): complete keyed agent migration * fix(config): close final migration gaps * fix(config): finish full-branch review * fix(config): complete runtime secret detection * fix(config): close final review findings * fix(config): finish canonical docs and heartbeat migration * fix(config): integrate latest main after rebase * refactor(env): isolate test-only controls * refactor(env): isolate build and development controls * refactor(env): collapse process identity indirection * refactor(env): remove duplicate config and temp aliases * docs(env): define the operator-facing allowlist * ci(env): ratchet production variable count * fix(env): remove stale provider helper import * fix(env): make ratchet sorting explicit * test(env): keep test seam in dead-code audit * test(env): cover ratchet growth and boundary; document surface budgets * docs(config): document tier-eval consolidations * docs(config): clarify speech preference ownership * test(memory): align retired tuning fixtures * refactor(memory): freeze engine heuristics * refactor(config): apply tier-eval tranche * refactor(tts): move persona shaping to providers * refactor(compaction): move prompt policy to providers * test(config): align hookified prompt fixtures * chore(deadcode): classify test-only exports * chore(github): remove unused spawn helper * chore(deadcode): classify queue diagnostics * chore(deadcode): remove unused lane snapshot export * chore(plugin-sdk): ratchet consolidated surface * fix(config): integrate latest main after rebase
193 lines
6.0 KiB
TypeScript
193 lines
6.0 KiB
TypeScript
/** Resolves effective plugin ids from config, installed records, and activation metadata. */
|
|
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
|
import { sortUniqueStrings } from "@openclaw/normalization-core/string-normalization";
|
|
import {
|
|
listExplicitlyDisabledChannelIdsForConfig,
|
|
listPotentialConfiguredChannelIds,
|
|
} from "../channels/config-presence.js";
|
|
import { applyPluginAutoEnable } from "../config/plugin-auto-enable.js";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { isVitestRuntimeEnv } from "../infra/env.js";
|
|
import {
|
|
listExplicitConfiguredChannelIdsForConfig,
|
|
loadGatewayStartupPluginPlan,
|
|
resolveConfiguredChannelPluginIds,
|
|
} from "./channel-plugin-ids.js";
|
|
import { normalizePluginsConfig } from "./config-state.js";
|
|
import { loadManifestMetadataSnapshot } from "./manifest-contract-eligibility.js";
|
|
import { passesManifestOwnerBasePolicy } from "./manifest-owner-policy.js";
|
|
import { defaultSlotIdForKey } from "./slots.js";
|
|
|
|
function collectConfiguredChannelIds(
|
|
config: OpenClawConfig,
|
|
activationSourceConfig: OpenClawConfig,
|
|
env: NodeJS.ProcessEnv,
|
|
): string[] {
|
|
const disabled = new Set([
|
|
...listExplicitlyDisabledChannelIdsForConfig(config),
|
|
...listExplicitlyDisabledChannelIdsForConfig(activationSourceConfig),
|
|
]);
|
|
const ids = new Set([
|
|
...listPotentialConfiguredChannelIds(config, env, { includePersistedAuthState: false }),
|
|
...listExplicitConfiguredChannelIdsForConfig(activationSourceConfig),
|
|
]);
|
|
return [...ids]
|
|
.map((channelId) => normalizeOptionalLowercaseString(channelId))
|
|
.filter((channelId): channelId is string => {
|
|
if (!channelId) {
|
|
return false;
|
|
}
|
|
return !disabled.has(channelId);
|
|
})
|
|
.toSorted((left, right) => left.localeCompare(right));
|
|
}
|
|
|
|
function collectBundledChannelOwnerPluginIds(params: {
|
|
config: OpenClawConfig;
|
|
channelIds: readonly string[];
|
|
env: NodeJS.ProcessEnv;
|
|
workspaceDir?: string;
|
|
bundledPluginsDir?: string;
|
|
}): string[] {
|
|
const plugins = normalizePluginsConfig(params.config.plugins);
|
|
const channelIds = new Set(
|
|
params.channelIds
|
|
.map((channelId) => normalizeOptionalLowercaseString(channelId))
|
|
.filter((channelId): channelId is string => Boolean(channelId)),
|
|
);
|
|
if (channelIds.size === 0) {
|
|
return [];
|
|
}
|
|
const env = params.bundledPluginsDir
|
|
? {
|
|
...params.env,
|
|
OPENCLAW_BUNDLED_PLUGINS_DIR: params.bundledPluginsDir,
|
|
...(isVitestRuntimeEnv(params.env) || isVitestRuntimeEnv()
|
|
? { OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR: "1" }
|
|
: {}),
|
|
}
|
|
: params.env;
|
|
const snapshot = loadManifestMetadataSnapshot({
|
|
config: params.config,
|
|
env,
|
|
workspaceDir: params.workspaceDir,
|
|
});
|
|
const pluginIds = new Set<string>();
|
|
for (const plugin of snapshot.plugins) {
|
|
if (plugin.origin !== "bundled") {
|
|
continue;
|
|
}
|
|
if (
|
|
plugin.channels.some((channelId) =>
|
|
channelIds.has(normalizeOptionalLowercaseString(channelId) ?? ""),
|
|
)
|
|
) {
|
|
const pluginId = normalizeOptionalLowercaseString(plugin.id);
|
|
if (
|
|
pluginId &&
|
|
passesManifestOwnerBasePolicy({
|
|
plugin: { id: pluginId },
|
|
normalizedConfig: plugins,
|
|
allowRestrictiveAllowlistBypass: true,
|
|
})
|
|
) {
|
|
pluginIds.add(pluginId);
|
|
}
|
|
}
|
|
}
|
|
return sortUniqueStrings(pluginIds);
|
|
}
|
|
|
|
function collectExplicitEffectivePluginIds(config: OpenClawConfig): string[] {
|
|
const plugins = normalizePluginsConfig(config.plugins);
|
|
if (!plugins.enabled) {
|
|
return [];
|
|
}
|
|
|
|
const ids = new Set(plugins.allow);
|
|
for (const [pluginId, entry] of Object.entries(plugins.entries)) {
|
|
if (
|
|
entry?.enabled === true &&
|
|
(plugins.allow.length === 0 || plugins.allow.includes(pluginId))
|
|
) {
|
|
ids.add(pluginId);
|
|
}
|
|
}
|
|
for (const pluginId of plugins.deny) {
|
|
ids.delete(pluginId);
|
|
}
|
|
for (const [pluginId, entry] of Object.entries(plugins.entries)) {
|
|
if (entry?.enabled === false) {
|
|
ids.delete(pluginId);
|
|
}
|
|
}
|
|
return sortUniqueStrings(ids);
|
|
}
|
|
|
|
function collectSelectedContextEnginePluginIds(config: OpenClawConfig): string[] {
|
|
const plugins = normalizePluginsConfig(config.plugins);
|
|
if (!plugins.enabled) {
|
|
return [];
|
|
}
|
|
const pluginId = plugins.slots.contextEngine;
|
|
if (!pluginId || pluginId === defaultSlotIdForKey("contextEngine")) {
|
|
return [];
|
|
}
|
|
if (plugins.deny.includes(pluginId)) {
|
|
return [];
|
|
}
|
|
if (plugins.entries[pluginId]?.enabled === false) {
|
|
return [];
|
|
}
|
|
return [pluginId];
|
|
}
|
|
|
|
/** Lists plugin ids that are effectively enabled for a config/discovery context. */
|
|
export function resolveEffectivePluginIds(params: {
|
|
config: OpenClawConfig;
|
|
env: NodeJS.ProcessEnv;
|
|
workspaceDir?: string;
|
|
bundledPluginsDir?: string;
|
|
}): string[] {
|
|
const autoEnabled = applyPluginAutoEnable({
|
|
config: params.config,
|
|
env: params.env,
|
|
});
|
|
const effectiveConfig = autoEnabled.config;
|
|
const ids = new Set(collectExplicitEffectivePluginIds(effectiveConfig));
|
|
for (const pluginId of collectSelectedContextEnginePluginIds(effectiveConfig)) {
|
|
ids.add(pluginId);
|
|
}
|
|
const configuredChannelIds = collectConfiguredChannelIds(
|
|
effectiveConfig,
|
|
params.config,
|
|
params.env,
|
|
);
|
|
for (const pluginId of resolveConfiguredChannelPluginIds({
|
|
config: effectiveConfig,
|
|
activationSourceConfig: params.config,
|
|
workspaceDir: params.workspaceDir,
|
|
env: params.env,
|
|
})) {
|
|
ids.add(pluginId);
|
|
}
|
|
for (const pluginId of collectBundledChannelOwnerPluginIds({
|
|
config: effectiveConfig,
|
|
channelIds: configuredChannelIds,
|
|
env: params.env,
|
|
workspaceDir: params.workspaceDir,
|
|
...(params.bundledPluginsDir ? { bundledPluginsDir: params.bundledPluginsDir } : {}),
|
|
})) {
|
|
ids.add(pluginId);
|
|
}
|
|
for (const pluginId of loadGatewayStartupPluginPlan({
|
|
config: effectiveConfig,
|
|
activationSourceConfig: params.config,
|
|
workspaceDir: params.workspaceDir,
|
|
env: params.env,
|
|
}).pluginIds) {
|
|
ids.add(pluginId);
|
|
}
|
|
return sortUniqueStrings(ids);
|
|
}
|