diff --git a/src/auto-reply/reply/session-updates.ts b/src/auto-reply/reply/session-updates.ts index 34e4c35c5..4835437ef 100644 --- a/src/auto-reply/reply/session-updates.ts +++ b/src/auto-reply/reply/session-updates.ts @@ -3,8 +3,8 @@ import crypto from "node:crypto"; import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js"; import type { ClawdbotConfig } from "../../config/config.js"; import { type SessionEntry, saveSessionStore } from "../../config/sessions.js"; -import { drainSystemEventEntries } from "../../infra/system-events.js"; import { buildChannelSummary } from "../../infra/channel-summary.js"; +import { drainSystemEventEntries } from "../../infra/system-events.js"; export async function prependSystemEvents(params: { cfg: ClawdbotConfig; diff --git a/src/config/config.test.ts b/src/config/config.test.ts index c25143f2d..8d442e4dc 100644 --- a/src/config/config.test.ts +++ b/src/config/config.test.ts @@ -2003,11 +2003,14 @@ describe("config preservation on validation failure", () => { const { readConfigFileSnapshot } = await import("./config.js"); const snap = await readConfigFileSnapshot(); - expect(snap.valid).toBe(false); - expect(snap.legacyIssues.length).toBeGreaterThan(0); + expect(snap.valid).toBe(true); + expect(snap.legacyIssues).toHaveLength(0); expect((snap.config as Record).customData).toEqual({ preserved: true, }); + expect(snap.config.channels?.whatsapp?.allowFrom).toEqual([ + "+15555550123", + ]); }); }); }); diff --git a/src/config/io.ts b/src/config/io.ts index 77fc7ac94..1b3741b1a 100644 --- a/src/config/io.ts +++ b/src/config/io.ts @@ -352,11 +352,15 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) { } const migrated = applyLegacyMigrations(resolved); - const resolvedConfig = migrated.next ?? resolved; - const legacyIssues = findLegacyConfigIssues(resolvedConfig); + const resolvedConfigRaw = migrated.next ?? resolved; + const legacyIssues = findLegacyConfigIssues(resolvedConfigRaw); - const validated = validateConfigObject(resolvedConfig); + const validated = validateConfigObject(resolvedConfigRaw); if (!validated.ok) { + const resolvedConfig = + typeof resolvedConfigRaw === "object" && resolvedConfigRaw !== null + ? (resolvedConfigRaw as ClawdbotConfig) + : {}; return { path: configPath, exists: true, diff --git a/src/infra/outbound/message-action-runner.test.ts b/src/infra/outbound/message-action-runner.test.ts index 1f982f35d..7dc76ef71 100644 --- a/src/infra/outbound/message-action-runner.test.ts +++ b/src/infra/outbound/message-action-runner.test.ts @@ -4,9 +4,11 @@ import type { ClawdbotConfig } from "../../config/config.js"; import { runMessageAction } from "./message-action-runner.js"; const slackConfig = { - slack: { - botToken: "xoxb-test", - appToken: "xapp-test", + channels: { + slack: { + botToken: "xoxb-test", + appToken: "xapp-test", + }, }, } as ClawdbotConfig; @@ -16,7 +18,7 @@ describe("runMessageAction context isolation", () => { cfg: slackConfig, action: "send", params: { - provider: "slack", + channel: "slack", to: "#C123", message: "hi", }, @@ -33,7 +35,7 @@ describe("runMessageAction context isolation", () => { cfg: slackConfig, action: "send", params: { - provider: "slack", + channel: "slack", to: "channel:C999", message: "hi", }, @@ -49,7 +51,7 @@ describe("runMessageAction context isolation", () => { cfg: slackConfig, action: "thread-reply", params: { - provider: "slack", + channel: "slack", channelId: "C999", message: "hi", }, diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index 59f972af7..cd668bf7c 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -924,18 +924,20 @@ describe("createTelegramBot", () => { replySpy.mockReset(); loadConfig.mockReturnValue({ - telegram: { - accounts: { - opie: { - botToken: "tok-opie", - dmPolicy: "open", + channels: { + telegram: { + accounts: { + opie: { + botToken: "tok-opie", + dmPolicy: "open", + }, }, }, }, bindings: [ { agentId: "opie", - match: { provider: "telegram", accountId: "opie" }, + match: { channel: "telegram", accountId: "opie" }, }, ], }); @@ -1851,9 +1853,11 @@ describe("createTelegramBot", () => { replySpy.mockResolvedValue({ text: "response" }); loadConfig.mockReturnValue({ - telegram: { - groupPolicy: "open", - groups: { "*": { requireMention: false } }, + channels: { + telegram: { + groupPolicy: "open", + groups: { "*": { requireMention: false } }, + }, }, }); diff --git a/src/web/auto-reply.test.ts b/src/web/auto-reply.test.ts index b6be5e890..974123fa5 100644 --- a/src/web/auto-reply.test.ts +++ b/src/web/auto-reply.test.ts @@ -159,14 +159,16 @@ describe("partial reply gating", () => { const replyResolver = vi.fn().mockResolvedValue({ text: "final reply" }); const mockConfig: ClawdbotConfig = { - whatsapp: { - allowFrom: ["*"], + channels: { + whatsapp: { + allowFrom: ["*"], + }, }, }; setLoadConfigMock(mockConfig); - await monitorWebProvider( + await monitorWebChannel( false, async ({ onMessage }) => { await onMessage({