mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-01 06:50:23 +00:00
fix(config): strip legacy googlechat streamMode on load
This commit is contained in:
@@ -664,6 +664,9 @@ describe("doctor config flow", () => {
|
||||
discord: {
|
||||
streaming: false,
|
||||
},
|
||||
googlechat: {
|
||||
streamMode: "append",
|
||||
},
|
||||
slack: {
|
||||
streaming: true,
|
||||
},
|
||||
@@ -688,6 +691,14 @@ describe("doctor config flow", () => {
|
||||
String(message).includes("boolean channels.discord.streaming are legacy"),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
noteSpy.mock.calls.some(
|
||||
([message, title]) =>
|
||||
title === "Legacy config keys detected" &&
|
||||
String(message).includes("channels.googlechat:") &&
|
||||
String(message).includes("channels.googlechat.streamMode is legacy and no longer used"),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
noteSpy.mock.calls.some(
|
||||
([message, title]) =>
|
||||
@@ -708,6 +719,36 @@ describe("doctor config flow", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("repairs legacy googlechat streamMode by removing it", async () => {
|
||||
const result = await runDoctorConfigWithInput({
|
||||
config: {
|
||||
channels: {
|
||||
googlechat: {
|
||||
streamMode: "append",
|
||||
accounts: {
|
||||
work: {
|
||||
streamMode: "replace",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
run: loadAndMaybeMigrateDoctorConfig,
|
||||
});
|
||||
|
||||
const cfg = result.cfg as {
|
||||
channels: {
|
||||
googlechat: {
|
||||
accounts?: {
|
||||
work?: Record<string, unknown>;
|
||||
};
|
||||
} & Record<string, unknown>;
|
||||
};
|
||||
};
|
||||
expect(cfg.channels.googlechat.streamMode).toBeUndefined();
|
||||
expect(cfg.channels.googlechat.accounts?.work?.streamMode).toBeUndefined();
|
||||
});
|
||||
|
||||
it("warns clearly about legacy nested channel allow aliases and points to doctor --fix", async () => {
|
||||
const noteSpy = vi.spyOn(noteModule, "note").mockImplementation(() => {});
|
||||
try {
|
||||
|
||||
@@ -757,6 +757,14 @@ describe("config strict validation", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
googlechat: {
|
||||
streamMode: "append",
|
||||
accounts: {
|
||||
work: {
|
||||
streamMode: "replace",
|
||||
},
|
||||
},
|
||||
},
|
||||
slack: {
|
||||
streaming: true,
|
||||
},
|
||||
@@ -771,6 +779,10 @@ describe("config strict validation", () => {
|
||||
expect(snap.legacyIssues.some((issue) => issue.path === "channels.discord.accounts")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(snap.legacyIssues.some((issue) => issue.path === "channels.googlechat")).toBe(true);
|
||||
expect(snap.legacyIssues.some((issue) => issue.path === "channels.googlechat.accounts")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(snap.legacyIssues.some((issue) => issue.path === "channels.slack")).toBe(true);
|
||||
expect(snap.sourceConfig.channels?.telegram).toMatchObject({
|
||||
streaming: "block",
|
||||
@@ -784,6 +796,16 @@ describe("config strict validation", () => {
|
||||
expect(snap.sourceConfig.channels?.discord?.accounts?.work).toMatchObject({
|
||||
streaming: "block",
|
||||
});
|
||||
expect(
|
||||
(snap.sourceConfig.channels?.googlechat as Record<string, unknown> | undefined)?.streamMode,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
(
|
||||
snap.sourceConfig.channels?.googlechat?.accounts?.work as
|
||||
| Record<string, unknown>
|
||||
| undefined
|
||||
)?.streamMode,
|
||||
).toBeUndefined();
|
||||
expect(snap.sourceConfig.channels?.slack).toMatchObject({
|
||||
streaming: "partial",
|
||||
nativeStreaming: true,
|
||||
|
||||
@@ -499,6 +499,48 @@ describe("legacy migrate channel streaming aliases", () => {
|
||||
streaming: "off",
|
||||
});
|
||||
});
|
||||
|
||||
it("removes legacy googlechat streamMode aliases", () => {
|
||||
const raw = {
|
||||
channels: {
|
||||
googlechat: {
|
||||
streamMode: "append",
|
||||
accounts: {
|
||||
work: {
|
||||
streamMode: "replace",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const validated = validateConfigObjectWithPlugins(raw);
|
||||
expect(validated.ok).toBe(true);
|
||||
if (!validated.ok) {
|
||||
return;
|
||||
}
|
||||
expect(
|
||||
(validated.config.channels?.googlechat as Record<string, unknown> | undefined)?.streamMode,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
(
|
||||
validated.config.channels?.googlechat?.accounts?.work as Record<string, unknown> | undefined
|
||||
)?.streamMode,
|
||||
).toBeUndefined();
|
||||
|
||||
const res = migrateLegacyConfig(raw);
|
||||
expect(res.changes).toContain("Removed channels.googlechat.streamMode (legacy key no longer used).");
|
||||
expect(res.changes).toContain(
|
||||
"Removed channels.googlechat.accounts.work.streamMode (legacy key no longer used).",
|
||||
);
|
||||
expect(
|
||||
(res.config?.channels?.googlechat as Record<string, unknown> | undefined)?.streamMode,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
(res.config?.channels?.googlechat?.accounts?.work as Record<string, unknown> | undefined)
|
||||
?.streamMode,
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("legacy migrate nested channel enabled aliases", () => {
|
||||
|
||||
@@ -242,6 +242,14 @@ function hasLegacySlackStreamingKeys(value: unknown): boolean {
|
||||
return entry.streamMode !== undefined || typeof entry.streaming === "boolean";
|
||||
}
|
||||
|
||||
function hasLegacyGoogleChatStreamMode(value: unknown): boolean {
|
||||
const entry = getRecord(value);
|
||||
if (!entry) {
|
||||
return false;
|
||||
}
|
||||
return entry.streamMode !== undefined;
|
||||
}
|
||||
|
||||
function hasLegacyKeysInAccounts(
|
||||
value: unknown,
|
||||
matchEntry: (entry: Record<string, unknown>) => boolean,
|
||||
@@ -409,6 +417,21 @@ const CHANNEL_ENABLED_ALIAS_RULES: LegacyConfigRule[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const GOOGLECHAT_STREAMMODE_RULES: LegacyConfigRule[] = [
|
||||
{
|
||||
path: ["channels", "googlechat"],
|
||||
message:
|
||||
"channels.googlechat.streamMode is legacy and no longer used; it is removed on load.",
|
||||
match: (value) => hasLegacyGoogleChatStreamMode(value),
|
||||
},
|
||||
{
|
||||
path: ["channels", "googlechat", "accounts"],
|
||||
message:
|
||||
"channels.googlechat.accounts.<id>.streamMode is legacy and no longer used; it is removed on load.",
|
||||
match: (value) => hasLegacyKeysInAccounts(value, hasLegacyGoogleChatStreamMode),
|
||||
},
|
||||
];
|
||||
|
||||
export const LEGACY_CONFIG_MIGRATIONS_CHANNELS: LegacyConfigMigrationSpec[] = [
|
||||
defineLegacyConfigMigration({
|
||||
id: "thread-bindings.ttlHours->idleHours",
|
||||
@@ -683,4 +706,46 @@ export const LEGACY_CONFIG_MIGRATIONS_CHANNELS: LegacyConfigMigrationSpec[] = [
|
||||
raw.channels = channels;
|
||||
},
|
||||
}),
|
||||
defineLegacyConfigMigration({
|
||||
id: "channels.googlechat.streamMode->remove",
|
||||
describe: "Remove legacy Google Chat streamMode keys that are no longer used",
|
||||
legacyRules: GOOGLECHAT_STREAMMODE_RULES,
|
||||
apply: (raw, changes) => {
|
||||
const channels = getRecord(raw.channels);
|
||||
if (!channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
const migrateEntry = (entry: Record<string, unknown>, pathPrefix: string) => {
|
||||
if (entry.streamMode === undefined) {
|
||||
return;
|
||||
}
|
||||
delete entry.streamMode;
|
||||
changes.push(`Removed ${pathPrefix}.streamMode (legacy key no longer used).`);
|
||||
};
|
||||
|
||||
const googlechat = getRecord(channels.googlechat);
|
||||
if (!googlechat) {
|
||||
return;
|
||||
}
|
||||
|
||||
migrateEntry(googlechat, "channels.googlechat");
|
||||
|
||||
const accounts = getRecord(googlechat.accounts);
|
||||
if (accounts) {
|
||||
for (const [accountId, accountValue] of Object.entries(accounts)) {
|
||||
const account = getRecord(accountValue);
|
||||
if (!account) {
|
||||
continue;
|
||||
}
|
||||
migrateEntry(account, `channels.googlechat.accounts.${accountId}`);
|
||||
accounts[accountId] = account;
|
||||
}
|
||||
googlechat.accounts = accounts;
|
||||
}
|
||||
|
||||
channels.googlechat = googlechat;
|
||||
raw.channels = channels;
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user