From 70b1c17ae01ea34cbb928d41fe1248893b019905 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 4 May 2026 18:15:18 -0400 Subject: [PATCH] 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. --- CHANGELOG.md | 1 + .../plugin-auto-enable.channels.test.ts | 50 +++++++++++++++++++ src/config/plugin-auto-enable.shared.ts | 2 +- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0688104e1b..30cd4d07e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 `/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 ] [--json]` so users can inspect saved per-agent auth profiles without dumping secrets or hitting the old “too many arguments” path. Thanks @vincentkoc. diff --git a/src/config/plugin-auto-enable.channels.test.ts b/src/config/plugin-auto-enable.channels.test.ts index 52e38e10645..66060bd2ecf 100644 --- a/src/config/plugin-auto-enable.channels.test.ts +++ b/src/config/plugin-auto-enable.channels.test.ts @@ -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: { diff --git a/src/config/plugin-auto-enable.shared.ts b/src/config/plugin-auto-enable.shared.ts index bb6c125e9bf..745dff0b4c6 100644 --- a/src/config/plugin-auto-enable.shared.ts +++ b/src/config/plugin-auto-enable.shared.ts @@ -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[] {