diff --git a/CHANGELOG.md b/CHANGELOG.md index 5afb5f4b621..870b919331f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -113,6 +113,7 @@ Docs: https://docs.openclaw.ai - Android/Onboarding + voice reliability: request per-toggle onboarding permissions, update pairing guidance to `openclaw devices list/approve`, restore assistant speech playback in mic capture flow, cancel superseded in-flight speech (mute + per-reply token rotation), and keep `talk.config` loads retryable after transient failures. (#29796) Thanks @obviyus. - FS/Sandbox workspace boundaries: add a dedicated `outside-workspace` safe-open error code for root-escape checks, and propagate specific outside-workspace messages across edit/browser/media consumers instead of generic not-found/invalid-path fallbacks. (#29715) Thanks @YuzuruS. - Config/Doctor group allowlist diagnostics: align `groupPolicy: "allowlist"` warnings with per-channel runtime semantics by excluding Google Chat sender-list checks and by warning when no-fallback channels (for example iMessage) omit `groupAllowFrom`, with regression coverage. (#28477) Thanks @tonydehnke. +- Slack/Disabled channel startup: skip Slack monitor socket startup entirely when `channels.slack.enabled=false` (including configs that still contain valid tokens), preventing disabled accounts from opening websocket connections. (#30586) - Onboarding/Custom providers: use Azure OpenAI-specific verification auth/payload shape (`api-key`, deployment-path chat completions payload) when probing Azure endpoints so valid Azure custom-provider setup no longer fails preflight. (#29421) Thanks @kunalk16. - Feishu/Docx editing tools: add `feishu_doc` positional insert, table row/column operations, table-cell merge, and color-text updates; switch markdown write/append/insert to Descendant API insertion with large-document batching; and harden image uploads for data URI/base64/local-path inputs with strict validation and routing-safe upload metadata. (#29411) Thanks @Elarwei001. diff --git a/src/slack/monitor.tool-result.test.ts b/src/slack/monitor.tool-result.test.ts index 457f13586bc..cf81828ceac 100644 --- a/src/slack/monitor.tool-result.test.ts +++ b/src/slack/monitor.tool-result.test.ts @@ -6,7 +6,9 @@ import { defaultSlackTestConfig, getSlackTestState, getSlackClient, + getSlackHandlers, getSlackHandlerOrThrow, + flush, resetSlackTestState, runSlackMessageOnce, startSlackMonitor, @@ -119,6 +121,32 @@ describe("monitorSlackProvider tool results", () => { }; } + it("skips socket startup when Slack channel is disabled", async () => { + slackTestState.config = { + channels: { + slack: { + enabled: false, + mode: "socket", + botToken: "xoxb-config", + appToken: "xapp-config", + }, + }, + }; + const client = getSlackClient(); + if (!client) { + throw new Error("Slack client not registered"); + } + client.auth.test.mockClear(); + + const { controller, run } = startSlackMonitor(monitorSlackProvider); + await flush(); + controller.abort(); + await run; + + expect(client.auth.test).not.toHaveBeenCalled(); + expect(getSlackHandlers()?.size ?? 0).toBe(0); + }); + it("skips tool summaries with responsePrefix", async () => { replyMock.mockResolvedValue({ text: "final reply" }); diff --git a/src/slack/monitor/provider.ts b/src/slack/monitor/provider.ts index 827784723a4..168c5873b0a 100644 --- a/src/slack/monitor/provider.ts +++ b/src/slack/monitor/provider.ts @@ -58,12 +58,26 @@ function parseApiAppIdFromAppToken(raw?: string) { export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) { const cfg = opts.config ?? loadConfig(); + const runtime: RuntimeEnv = opts.runtime ?? createNonExitingRuntime(); let account = resolveSlackAccount({ cfg, accountId: opts.accountId, }); + if (!account.enabled) { + runtime.log?.(`[${account.accountId}] slack account disabled; monitor startup skipped`); + if (opts.abortSignal?.aborted) { + return; + } + await new Promise((resolve) => { + opts.abortSignal?.addEventListener("abort", () => resolve(), { + once: true, + }); + }); + return; + } + const historyLimit = Math.max( 0, account.config.historyLimit ?? @@ -93,8 +107,6 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) { ); } - const runtime: RuntimeEnv = opts.runtime ?? createNonExitingRuntime(); - const slackCfg = account.config; const dmConfig = slackCfg.dm;