From 7c6c0a8d5447d3e25802ee6967b8099e1c5ceae4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 26 Apr 2026 07:09:14 +0100 Subject: [PATCH] fix: avoid persisted-auth channel startup probes --- CHANGELOG.md | 1 + docs/install/updating.md | 2 + docs/tools/plugin.md | 2 + src/plugins/channel-plugin-ids.test.ts | 45 +++++++++++++++++++++++ src/plugins/gateway-startup-plugin-ids.ts | 2 +- 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bfa846c10..ea92a96d9ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Gateway/plugins: stop persisted WhatsApp auth state from activating bundled channel runtime-dependency repair during startup when `channels.whatsapp` is absent, avoiding npm/git stalls on packaged Linux installs. Fixes #71994. Thanks @xiao398008. - CLI/model runs: keep `openclaw infer model run` on explicit OpenRouter models from loading the full provider catalog or inheriting chat-agent silent-reply policy, restoring non-empty one-shot probe output. Fixes #68791. Thanks @limpredator. - Installer/macOS: rerun Homebrew install steps without the gum spinner when raw-mode ioctl failures occur, and avoid claiming `node@24` was installed when the Homebrew keg binary is missing. Fixes #70411. Thanks @1fanwang and @dad-io. - Installer: load nvm before Node.js detection so `curl | bash` installs respect nvm-managed Node instead of stale system Node. Fixes #49556. Thanks @heavenlxj. diff --git a/docs/install/updating.md b/docs/install/updating.md index 03b06228eb1..9f2583bd48f 100644 --- a/docs/install/updating.md +++ b/docs/install/updating.md @@ -85,6 +85,8 @@ Packaged installs keep bundled plugin runtime dependencies out of the read-only package tree. On startup and during `openclaw doctor --fix`, OpenClaw repairs runtime dependencies only for bundled plugins that are active in config, active through legacy channel config, or enabled by their bundled manifest default. +Persisted channel auth state alone does not trigger Gateway startup +runtime-dependency repair. Explicit disablement wins. A disabled plugin or channel does not get its runtime dependencies repaired just because it exists in the package. External diff --git a/docs/tools/plugin.md b/docs/tools/plugin.md index 02ebb59b505..469189ac7de 100644 --- a/docs/tools/plugin.md +++ b/docs/tools/plugin.md @@ -65,6 +65,8 @@ Packaged OpenClaw installs do not eagerly install every bundled plugin's runtime dependency tree. When a bundled OpenClaw-owned plugin is active from plugin config, legacy channel config, or a default-enabled manifest, startup repairs only that plugin's declared runtime dependencies before importing it. +Persisted channel auth state alone does not activate a bundled channel for +Gateway startup runtime-dependency repair. Explicit disablement still wins: `plugins.entries..enabled: false`, `plugins.deny`, `plugins.enabled: false`, and `channels..enabled: false` prevent automatic bundled runtime-dependency repair for that plugin/channel. diff --git a/src/plugins/channel-plugin-ids.test.ts b/src/plugins/channel-plugin-ids.test.ts index ff6aef449ba..03018ab71c6 100644 --- a/src/plugins/channel-plugin-ids.test.ts +++ b/src/plugins/channel-plugin-ids.test.ts @@ -544,6 +544,51 @@ describe("resolveGatewayStartupPluginIds", () => { }); }); + it("does not treat persisted auth alone as gateway startup intent", () => { + listPotentialConfiguredChannelIds.mockImplementation( + ( + _config: OpenClawConfig, + _env: NodeJS.ProcessEnv, + options?: { includePersistedAuthState?: boolean }, + ) => (options?.includePersistedAuthState === false ? [] : ["demo-channel"]), + ); + + expectStartupPluginIdsCase({ + config: {} as OpenClawConfig, + env: { + OPENCLAW_STATE_DIR: "/tmp/openclaw-with-persisted-demo-channel", + } as NodeJS.ProcessEnv, + expected: ["browser"], + }); + }); + + it("does not treat persisted auth alone as deferred channel startup intent", () => { + loadPluginManifestRegistry + .mockReset() + .mockReturnValue(createManifestRegistryFixtureWithWorkspaceDemoChannel()); + listPotentialConfiguredChannelIds.mockImplementation( + ( + _config: OpenClawConfig, + _env: NodeJS.ProcessEnv, + options?: { includePersistedAuthState?: boolean }, + ) => (options?.includePersistedAuthState === false ? [] : ["demo-channel"]), + ); + + expect( + resolveConfiguredDeferredChannelPluginIds({ + config: { + plugins: { + allow: ["workspace-demo-channel-plugin"], + }, + } as OpenClawConfig, + workspaceDir: "/tmp", + env: { + OPENCLAW_STATE_DIR: "/tmp/openclaw-with-persisted-demo-channel", + } as NodeJS.ProcessEnv, + }), + ).toEqual([]); + }); + it("does not treat explicitly disabled stale channel config as deferred startup intent", () => { loadPluginManifestRegistry .mockReset() diff --git a/src/plugins/gateway-startup-plugin-ids.ts b/src/plugins/gateway-startup-plugin-ids.ts index dc0081cb9b0..86bed0d9b8f 100644 --- a/src/plugins/gateway-startup-plugin-ids.ts +++ b/src/plugins/gateway-startup-plugin-ids.ts @@ -41,7 +41,7 @@ function listDisabledChannelIds(config: OpenClawConfig): Set { function listPotentialEnabledChannelIds(config: OpenClawConfig, env: NodeJS.ProcessEnv): string[] { const disabled = listDisabledChannelIds(config); - return listPotentialConfiguredChannelIds(config, env) + return listPotentialConfiguredChannelIds(config, env, { includePersistedAuthState: false }) .map((id) => normalizeOptionalLowercaseString(id) ?? "") .filter((id) => id && !disabled.has(id)); }