From 70ebf4898b0d7dbcedb640d6fcc13562bf7e9a61 Mon Sep 17 00:00:00 2001 From: EvanYao Date: Fri, 15 May 2026 08:40:36 +0800 Subject: [PATCH] fix(config): treat enabled channels as configured --- CHANGELOG.md | 1 + src/config/channel-configured-shared.ts | 6 ++++- src/config/channel-configured.test.ts | 32 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15524515482..cf8dad53946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Channels/config: treat channel entries with only `enabled: true` as configured state so plugin-backed channels can auto-enable from an explicit on switch. Fixes #81323. (#81331) Thanks @EvanYao826 and @vincentkoc. - CLI/update: add an update finalization path for externally swapped core runtimes, running update-time doctor repair and plugin convergence from post-doctor config and install-record state before reporting completion. Thanks @shakkernerd. - Agents/WebChat: stop a successful assistant turn whose stale `errorMessage` matches a billing, auth, or rate-limit pattern from rotating profiles, falling back, or surfacing a hard `FailoverError` unless the current attempt has a real failover failure. (#70900) Thanks @truffle-dev. - Control UI/logs: make the Gateway Logs stream height responsive to the viewport with a minimum height floor, so larger screens can show substantially more log lines without collapsing on shorter viewports. (#53916) Thanks @extrasmall0. diff --git a/src/config/channel-configured-shared.ts b/src/config/channel-configured-shared.ts index 79e9fc0202c..253cc43c5c0 100644 --- a/src/config/channel-configured-shared.ts +++ b/src/config/channel-configured-shared.ts @@ -15,7 +15,11 @@ export function hasMeaningfulChannelConfigShallow(value: unknown): boolean { if (!isRecord(value)) { return false; } - return Object.keys(value).some((key) => key !== "enabled"); + const keys = Object.keys(value); + if (keys.length === 1 && keys[0] === "enabled") { + return value.enabled === true; + } + return keys.some((key) => key !== "enabled"); } export function isStaticallyChannelConfigured( diff --git a/src/config/channel-configured.test.ts b/src/config/channel-configured.test.ts index 8229a6bb988..c2ba2ce35e0 100644 --- a/src/config/channel-configured.test.ts +++ b/src/config/channel-configured.test.ts @@ -44,6 +44,38 @@ describe("isChannelConfigured", () => { ).toBe(true); }); + it("treats explicit enabled channel config as configured state", () => { + expect( + isChannelConfigured( + { + channels: { + "openclaw-weixin": { + enabled: true, + }, + }, + }, + "openclaw-weixin", + {}, + ), + ).toBe(true); + }); + + it("does not treat disabled channel config as configured state", () => { + expect( + isChannelConfigured( + { + channels: { + "openclaw-weixin": { + enabled: false, + }, + }, + }, + "openclaw-weixin", + {}, + ), + ).toBe(false); + }); + it("does not treat persisted Matrix credentials as configured channel state", () => { expect( isChannelConfigured({}, "matrix", { OPENCLAW_STATE_DIR: "state-with-matrix-creds" }),