fix: avoid whatsapp config resurrection
This commit is contained in:
@@ -19,6 +19,7 @@ Docs: https://docs.clawd.bot
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Config: avoid stack traces for invalid configs and log the config path.
|
- Config: avoid stack traces for invalid configs and log the config path.
|
||||||
|
- Doctor: avoid recreating WhatsApp config when only legacy routing keys remain. (#900)
|
||||||
- Doctor: warn when gateway.mode is unset with configure/config guidance.
|
- Doctor: warn when gateway.mode is unset with configure/config guidance.
|
||||||
- OpenCode Zen: route models to the Zen API shape per family so proxy endpoints are used. (#1416)
|
- OpenCode Zen: route models to the Zen API shape per family so proxy endpoints are used. (#1416)
|
||||||
- macOS: include Textual syntax highlighting resources in packaged app to prevent chat crashes. (#1362)
|
- macOS: include Textual syntax highlighting resources in packaged app to prevent chat crashes. (#1362)
|
||||||
|
|||||||
@@ -23,21 +23,33 @@ describe("legacy config detection", () => {
|
|||||||
expect(res.issues[0]?.path).toBe("routing.groupChat.requireMention");
|
expect(res.issues[0]?.path).toBe("routing.groupChat.requireMention");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it("migrates routing.allowFrom to channels.whatsapp.allowFrom", async () => {
|
it("migrates routing.allowFrom to channels.whatsapp.allowFrom when whatsapp configured", async () => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
const { migrateLegacyConfig } = await import("./config.js");
|
const { migrateLegacyConfig } = await import("./config.js");
|
||||||
const res = migrateLegacyConfig({
|
const res = migrateLegacyConfig({
|
||||||
routing: { allowFrom: ["+15555550123"] },
|
routing: { allowFrom: ["+15555550123"] },
|
||||||
|
channels: { whatsapp: {} },
|
||||||
});
|
});
|
||||||
expect(res.changes).toContain("Moved routing.allowFrom → channels.whatsapp.allowFrom.");
|
expect(res.changes).toContain("Moved routing.allowFrom → channels.whatsapp.allowFrom.");
|
||||||
expect(res.config?.channels?.whatsapp?.allowFrom).toEqual(["+15555550123"]);
|
expect(res.config?.channels?.whatsapp?.allowFrom).toEqual(["+15555550123"]);
|
||||||
expect(res.config?.routing?.allowFrom).toBeUndefined();
|
expect(res.config?.routing?.allowFrom).toBeUndefined();
|
||||||
});
|
});
|
||||||
it("migrates routing.groupChat.requireMention to channels whatsapp/telegram/imessage groups", async () => {
|
it("drops routing.allowFrom when whatsapp missing", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { migrateLegacyConfig } = await import("./config.js");
|
||||||
|
const res = migrateLegacyConfig({
|
||||||
|
routing: { allowFrom: ["+15555550123"] },
|
||||||
|
});
|
||||||
|
expect(res.changes).toContain("Removed routing.allowFrom (channels.whatsapp not configured).");
|
||||||
|
expect(res.config?.channels?.whatsapp).toBeUndefined();
|
||||||
|
expect(res.config?.routing?.allowFrom).toBeUndefined();
|
||||||
|
});
|
||||||
|
it("migrates routing.groupChat.requireMention to channels whatsapp/telegram/imessage groups when whatsapp configured", async () => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
const { migrateLegacyConfig } = await import("./config.js");
|
const { migrateLegacyConfig } = await import("./config.js");
|
||||||
const res = migrateLegacyConfig({
|
const res = migrateLegacyConfig({
|
||||||
routing: { groupChat: { requireMention: false } },
|
routing: { groupChat: { requireMention: false } },
|
||||||
|
channels: { whatsapp: {} },
|
||||||
});
|
});
|
||||||
expect(res.changes).toContain(
|
expect(res.changes).toContain(
|
||||||
'Moved routing.groupChat.requireMention → channels.whatsapp.groups."*".requireMention.',
|
'Moved routing.groupChat.requireMention → channels.whatsapp.groups."*".requireMention.',
|
||||||
@@ -53,6 +65,26 @@ describe("legacy config detection", () => {
|
|||||||
expect(res.config?.channels?.imessage?.groups?.["*"]?.requireMention).toBe(false);
|
expect(res.config?.channels?.imessage?.groups?.["*"]?.requireMention).toBe(false);
|
||||||
expect(res.config?.routing?.groupChat?.requireMention).toBeUndefined();
|
expect(res.config?.routing?.groupChat?.requireMention).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
it("migrates routing.groupChat.requireMention to telegram/imessage when whatsapp missing", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { migrateLegacyConfig } = await import("./config.js");
|
||||||
|
const res = migrateLegacyConfig({
|
||||||
|
routing: { groupChat: { requireMention: false } },
|
||||||
|
});
|
||||||
|
expect(res.changes).toContain(
|
||||||
|
'Moved routing.groupChat.requireMention → channels.telegram.groups."*".requireMention.',
|
||||||
|
);
|
||||||
|
expect(res.changes).toContain(
|
||||||
|
'Moved routing.groupChat.requireMention → channels.imessage.groups."*".requireMention.',
|
||||||
|
);
|
||||||
|
expect(res.changes).not.toContain(
|
||||||
|
'Moved routing.groupChat.requireMention → channels.whatsapp.groups."*".requireMention.',
|
||||||
|
);
|
||||||
|
expect(res.config?.channels?.whatsapp).toBeUndefined();
|
||||||
|
expect(res.config?.channels?.telegram?.groups?.["*"]?.requireMention).toBe(false);
|
||||||
|
expect(res.config?.channels?.imessage?.groups?.["*"]?.requireMention).toBe(false);
|
||||||
|
expect(res.config?.routing?.groupChat?.requireMention).toBeUndefined();
|
||||||
|
});
|
||||||
it("migrates routing.groupChat.mentionPatterns to messages.groupChat.mentionPatterns", async () => {
|
it("migrates routing.groupChat.mentionPatterns to messages.groupChat.mentionPatterns", async () => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
const { migrateLegacyConfig } = await import("./config.js");
|
const { migrateLegacyConfig } = await import("./config.js");
|
||||||
|
|||||||
@@ -156,11 +156,16 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_1: LegacyConfigMigration[] = [
|
|||||||
const allowFrom = (routing as Record<string, unknown>).allowFrom;
|
const allowFrom = (routing as Record<string, unknown>).allowFrom;
|
||||||
if (allowFrom === undefined) return;
|
if (allowFrom === undefined) return;
|
||||||
|
|
||||||
const channels = ensureRecord(raw, "channels");
|
const channels = getRecord(raw.channels);
|
||||||
const whatsapp =
|
const whatsapp = channels ? getRecord(channels.whatsapp) : null;
|
||||||
channels.whatsapp && typeof channels.whatsapp === "object"
|
if (!whatsapp) {
|
||||||
? (channels.whatsapp as Record<string, unknown>)
|
delete (routing as Record<string, unknown>).allowFrom;
|
||||||
: {};
|
if (Object.keys(routing as Record<string, unknown>).length === 0) {
|
||||||
|
delete raw.routing;
|
||||||
|
}
|
||||||
|
changes.push("Removed routing.allowFrom (channels.whatsapp not configured).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (whatsapp.allowFrom === undefined) {
|
if (whatsapp.allowFrom === undefined) {
|
||||||
whatsapp.allowFrom = allowFrom;
|
whatsapp.allowFrom = allowFrom;
|
||||||
@@ -173,8 +178,8 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_1: LegacyConfigMigration[] = [
|
|||||||
if (Object.keys(routing as Record<string, unknown>).length === 0) {
|
if (Object.keys(routing as Record<string, unknown>).length === 0) {
|
||||||
delete raw.routing;
|
delete raw.routing;
|
||||||
}
|
}
|
||||||
channels.whatsapp = whatsapp;
|
channels!.whatsapp = whatsapp;
|
||||||
raw.channels = channels;
|
raw.channels = channels!;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -193,7 +198,11 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_1: LegacyConfigMigration[] = [
|
|||||||
if (requireMention === undefined) return;
|
if (requireMention === undefined) return;
|
||||||
|
|
||||||
const channels = ensureRecord(raw, "channels");
|
const channels = ensureRecord(raw, "channels");
|
||||||
const applyTo = (key: "whatsapp" | "telegram" | "imessage") => {
|
const applyTo = (
|
||||||
|
key: "whatsapp" | "telegram" | "imessage",
|
||||||
|
options?: { requireExisting?: boolean },
|
||||||
|
) => {
|
||||||
|
if (options?.requireExisting && !isRecord(channels[key])) return;
|
||||||
const section =
|
const section =
|
||||||
channels[key] && typeof channels[key] === "object"
|
channels[key] && typeof channels[key] === "object"
|
||||||
? (channels[key] as Record<string, unknown>)
|
? (channels[key] as Record<string, unknown>)
|
||||||
@@ -222,7 +231,7 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_1: LegacyConfigMigration[] = [
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
applyTo("whatsapp");
|
applyTo("whatsapp", { requireExisting: true });
|
||||||
applyTo("telegram");
|
applyTo("telegram");
|
||||||
applyTo("imessage");
|
applyTo("imessage");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user