fix(config): prefer plugin ids for built-in channel claims

Prefer the manifest plugin id when auto-allowlisting configured built-in channel aliases, with regression coverage for alias/id split plugins and same-name official channel plugins.
This commit is contained in:
Brandon
2026-05-04 18:15:18 -04:00
committed by GitHub
parent 683d892eed
commit 70b1c17ae0
3 changed files with 52 additions and 1 deletions

View File

@@ -12,6 +12,7 @@ Docs: https://docs.openclaw.ai
- Dependencies: refresh runtime and provider packages including Pi 0.73.0, ACPX adapters, OpenAI, Anthropic, Slack, and TypeScript native preview, while keeping the Bedrock runtime installer override pinned below the Windows ARM Node 24 npm resolver failure.
- Agents/performance: pass the resolved workspace through BTW, compaction, embedded-run model generation, and PDF model setup so explicit agent-dir model refreshes can reuse the current workspace-scoped plugin metadata snapshot instead of falling back to cold plugin metadata scans. (#77519, #77532)
- Config/plugin auto-enable: prefer the claiming plugin manifest id over a built-in channel alias when auto-allowlisting a configured channel, so WeCom/Yuanbao-style aliases resolve to the installed plugin id. Thanks @Beandon13.
- Plugins/active-memory: skip session-store channel entries that contain `:` when resolving the recall subagent's channel, so QQ c2c agent IDs (e.g. `c2c:10D4F7C2…`) and other scoped conversation IDs do not reach bundled-plugin `dirName` validation and crash the recall run. The same guard already applied to explicit `channelId` params (#76704); this extends it to store-derived channels. (#77396) Thanks @hclsys.
- Secrets/external channel contracts: also look in `<rootDir>/dist/` when resolving the `secret-contract-api` sidecar, so npm-published externalized channel plugins (e.g. `@openclaw/discord` since 2026.5.2) whose compiled artifacts live under `dist/` actually contribute their channel SecretRef contracts to the runtime snapshot. Without this, env-backed `channels.discord.token` SecretRefs silently failed to resolve at gateway start on 2026.5.3, leaving the channel `not configured` even though #76449 had landed the generic external-contract loader. Thanks @mogglemoss.
- Models/auth: add `openclaw models auth list [--provider <id>] [--json]` so users can inspect saved per-agent auth profiles without dumping secrets or hitting the old “too many arguments” path. Thanks @vincentkoc.

View File

@@ -335,6 +335,56 @@ describe("applyPluginAutoEnable channels", () => {
});
describe("preferOver channel prioritization", () => {
it("uses the plugin manifest id for built-in channel claims", () => {
const result = applyPluginAutoEnable({
config: {
channels: {
wecom: { token: "enabled" },
},
plugins: {
allow: ["existing-plugin"],
},
},
env: makeIsolatedEnv(),
manifestRegistry: makeRegistry([
{
id: "wecom-openclaw-plugin",
channels: ["wecom"],
},
]),
});
expect(result.config.plugins?.entries?.["wecom-openclaw-plugin"]?.enabled).toBe(true);
expect(result.config.plugins?.entries?.wecom).toBeUndefined();
expect(result.config.plugins?.allow).toEqual(["existing-plugin", "wecom-openclaw-plugin"]);
expect(result.changes.join("\n")).toContain("enabled automatically.");
});
it("preserves same-name official channel plugin ids", () => {
const result = applyPluginAutoEnable({
config: {
channels: {
discord: { token: "enabled" },
},
plugins: {
allow: ["existing-plugin"],
},
},
env: makeIsolatedEnv(),
manifestRegistry: makeRegistry([
{
id: "discord",
channels: ["discord"],
},
]),
});
expect(result.config.channels?.discord?.enabled).toBe(true);
expect(result.config.plugins?.entries?.discord).toBeUndefined();
expect(result.config.plugins?.allow).toEqual(["existing-plugin", "discord"]);
expect(result.changes.join("\n")).toContain("Discord configured, enabled automatically.");
});
it("uses manifest channel config preferOver metadata for plugin channels", () => {
const result = applyPluginAutoEnable({
config: {

View File

@@ -303,7 +303,7 @@ function collectPluginIdsForConfiguredChannel(
if (preferredIds.size > 0) {
return [...preferredIds].toSorted((left, right) => left.localeCompare(right));
}
return [builtInId ?? claims[0]?.plugin.id ?? normalizedChannelId];
return [claims[0]?.plugin.id ?? builtInId ?? normalizedChannelId];
}
function collectConfiguredChannelIds(cfg: OpenClawConfig, env: NodeJS.ProcessEnv): string[] {