fix: stabilize channel migration

This commit is contained in:
Peter Steinberger
2026-01-13 06:27:55 +00:00
parent 90342a4f3a
commit 993c1de361
6 changed files with 39 additions and 24 deletions

View File

@@ -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;

View File

@@ -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<string, unknown>).customData).toEqual({
preserved: true,
});
expect(snap.config.channels?.whatsapp?.allowFrom).toEqual([
"+15555550123",
]);
});
});
});

View File

@@ -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,

View File

@@ -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",
},

View File

@@ -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 } },
},
},
});

View File

@@ -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({