fix(channels): resolve cold channel presence from registry

This commit is contained in:
Vincent Koc
2026-04-25 18:52:56 -07:00
parent 94316334fe
commit e4199379ff
4 changed files with 61 additions and 21 deletions

View File

@@ -538,6 +538,7 @@ describe("listReadOnlyChannelPluginsForConfig", () => {
{
env: { ...process.env },
includePersistedAuthState: false,
includeSetupRuntimeFallback: true,
},
);
@@ -715,6 +716,7 @@ describe("listReadOnlyChannelPluginsForConfig", () => {
{
env: { ...process.env },
includePersistedAuthState: false,
includeSetupRuntimeFallback: true,
},
);

View File

@@ -7,10 +7,9 @@ import {
resolveDiscoverableScopedChannelPluginIds,
} from "../../plugins/channel-plugin-ids.js";
import { loadOpenClawPlugins } from "../../plugins/loader.js";
import {
loadPluginManifestRegistry,
type PluginManifestRecord,
} from "../../plugins/manifest-registry.js";
import { loadPluginManifestRegistryForInstalledIndex } from "../../plugins/manifest-registry-installed.js";
import type { PluginManifestRecord } from "../../plugins/manifest-registry.js";
import { loadPluginRegistrySnapshot } from "../../plugins/plugin-registry.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
import { sanitizeForLog } from "../../terminal/ansi.js";
import { getBundledChannelSetupPlugin } from "./bundled.js";
@@ -491,6 +490,7 @@ function resolveExternalReadOnlyChannelPluginIds(params: {
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
manifestRecords: params.records,
});
if (candidatePluginIds.length === 0) {
return [];
@@ -521,11 +521,18 @@ export function resolveReadOnlyChannelPluginsForConfig(
): ReadOnlyChannelPluginResolution {
const env = options.env ?? process.env;
const workspaceDir = resolveReadOnlyWorkspaceDir(cfg, options);
const manifestRecords = loadPluginManifestRegistry({
const pluginIndex = loadPluginRegistrySnapshot({
config: cfg,
workspaceDir,
env,
cache: options.cache,
});
const manifestRecords = loadPluginManifestRegistryForInstalledIndex({
index: pluginIndex,
config: cfg,
workspaceDir,
env,
includeDisabled: true,
}).plugins;
const externalManifestRecords = listExternalChannelManifestRecords(manifestRecords);
const configuredChannelIds = [

View File

@@ -56,18 +56,21 @@ type ResolveManifestActivationPlanParams = {
cache?: boolean;
origin?: PluginOrigin;
onlyPluginIds?: readonly string[];
manifestRecords?: readonly PluginManifestRecord[];
};
export function resolveManifestActivationPlan(
params: ResolveManifestActivationPlanParams,
): PluginActivationPlan {
const onlyPluginIdSet = createPluginIdScopeSet(normalizePluginIdScope(params.onlyPluginIds));
const registry = loadPluginManifestRegistry({
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
});
const registry = params.manifestRecords
? { plugins: params.manifestRecords, diagnostics: [] }
: loadPluginManifestRegistry({
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
});
const entries = registry.plugins
.flatMap((plugin) => {
if (params.origin && plugin.origin !== params.origin) {

View File

@@ -19,7 +19,9 @@ import {
isBundledManifestOwner,
passesManifestOwnerBasePolicy,
} from "./manifest-owner-policy.js";
import { loadPluginManifestRegistry, type PluginManifestRecord } from "./manifest-registry.js";
import { loadPluginManifestRegistryForInstalledIndex } from "./manifest-registry-installed.js";
import type { PluginManifestRecord } from "./manifest-registry.js";
import { loadPluginRegistrySnapshot } from "./plugin-registry.js";
const IGNORED_CHANNEL_CONFIG_KEYS = new Set(["defaults", "modelByChannel"]);
@@ -340,6 +342,27 @@ function listDisabledChannelIdsForConfig(config: OpenClawConfig): string[] {
.filter((channelId): channelId is string => Boolean(channelId));
}
function loadInstalledChannelManifestRecords(params: {
config: OpenClawConfig;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
cache?: boolean;
}): readonly PluginManifestRecord[] {
const index = loadPluginRegistrySnapshot({
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
});
return loadPluginManifestRegistryForInstalledIndex({
index,
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
includeDisabled: true,
}).plugins;
}
export function resolveConfiguredChannelPresencePolicy(params: {
config: OpenClawConfig;
activationSourceConfig?: OpenClawConfig;
@@ -355,12 +378,12 @@ export function resolveConfiguredChannelPresencePolicy(params: {
resolveAgentWorkspaceDir(params.config, resolveDefaultAgentId(params.config));
const records =
params.manifestRecords ??
loadPluginManifestRegistry({
loadInstalledChannelManifestRecords({
config: params.config,
workspaceDir,
env,
cache: params.cache,
}).plugins;
});
const disabledChannelIds = new Set(listDisabledChannelIdsForConfig(params.config));
const entrySources = new Map<string, Set<ConfiguredChannelPresenceSource>>();
@@ -471,17 +494,20 @@ function resolveScopedChannelOwnerPluginIds(params: {
workspaceDir?: string;
env: NodeJS.ProcessEnv;
cache?: boolean;
manifestRecords?: readonly PluginManifestRecord[];
}): string[] {
const channelIds = normalizeChannelIds(params.channelIds);
if (channelIds.length === 0) {
return [];
}
const registry = loadPluginManifestRegistry({
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
});
const records =
params.manifestRecords ??
loadInstalledChannelManifestRecords({
config: params.config,
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
});
const trustConfig = params.activationSourceConfig ?? params.config;
const normalizedConfig = normalizePluginsConfig(trustConfig.plugins);
const candidateIds = dedupeSortedPluginIds(
@@ -495,6 +521,7 @@ function resolveScopedChannelOwnerPluginIds(params: {
workspaceDir: params.workspaceDir,
env: params.env,
cache: params.cache,
manifestRecords: records,
});
}),
);
@@ -502,7 +529,7 @@ function resolveScopedChannelOwnerPluginIds(params: {
return [];
}
const candidateIdSet = new Set(candidateIds);
return registry.plugins
return records
.filter((plugin) => {
if (!candidateIdSet.has(plugin.id)) {
return false;
@@ -525,6 +552,7 @@ export function resolveDiscoverableScopedChannelPluginIds(params: {
workspaceDir?: string;
env: NodeJS.ProcessEnv;
cache?: boolean;
manifestRecords?: readonly PluginManifestRecord[];
}): string[] {
return resolveScopedChannelOwnerPluginIds(params);
}