diff --git a/src/auto-reply/reply/commands.test-harness.ts b/src/auto-reply/reply/commands.test-harness.ts index 4cda5199f2..84ef0c0f84 100644 --- a/src/auto-reply/reply/commands.test-harness.ts +++ b/src/auto-reply/reply/commands.test-harness.ts @@ -1,5 +1,6 @@ import type { OpenClawConfig } from "../../config/config.js"; import type { MsgContext } from "../templating.js"; +import type { HandleCommandsParams } from "./commands-types.js"; import { buildCommandContext } from "./commands.js"; import { parseInlineDirectives } from "./directive-handling.js"; @@ -10,7 +11,7 @@ export function buildCommandTestParams( options?: { workspaceDir?: string; }, -) { +): HandleCommandsParams { const ctx = { Body: commandBody, CommandBody: commandBody, @@ -29,7 +30,7 @@ export function buildCommandTestParams( commandAuthorized: true, }); - return { + const params: HandleCommandsParams = { ctx, cfg, command, @@ -38,12 +39,13 @@ export function buildCommandTestParams( sessionKey: "agent:main:main", workspaceDir: options?.workspaceDir ?? "/tmp", defaultGroupActivation: () => "mention", - resolvedVerboseLevel: "off" as const, - resolvedReasoningLevel: "off" as const, + resolvedVerboseLevel: "off", + resolvedReasoningLevel: "off", resolveDefaultThinkingLevel: async () => undefined, provider: "whatsapp", model: "test-model", contextTokens: 0, isGroup: false, }; + return params; } diff --git a/src/auto-reply/reply/commands.test.ts b/src/auto-reply/reply/commands.test.ts index f0b825a9b3..7d89239ae8 100644 --- a/src/auto-reply/reply/commands.test.ts +++ b/src/auto-reply/reply/commands.test.ts @@ -102,6 +102,7 @@ vi.mock("../../gateway/call.js", () => ({ callGateway: (opts: unknown) => callGatewayMock(opts), })); +import type { HandleCommandsParams } from "./commands-types.js"; import { buildCommandContext, handleCommands } from "./commands.js"; // Avoid expensive workspace scans during /context tests. @@ -504,6 +505,7 @@ describe("/compact command", () => { ...params, sessionEntry: { sessionId: "session-1", + updatedAt: Date.now(), groupId: "group-1", groupChannel: "#general", space: "workspace-1", @@ -651,7 +653,7 @@ function buildPolicyParams( commandBody: string, cfg: OpenClawConfig, ctxOverrides?: Partial, -) { +): HandleCommandsParams { const ctx = { Body: commandBody, CommandBody: commandBody, @@ -670,7 +672,7 @@ function buildPolicyParams( commandAuthorized: true, }); - return { + const params: HandleCommandsParams = { ctx, cfg, command, @@ -679,14 +681,15 @@ function buildPolicyParams( sessionKey: "agent:main:main", workspaceDir: "/tmp", defaultGroupActivation: () => "mention", - resolvedVerboseLevel: "off" as const, - resolvedReasoningLevel: "off" as const, + resolvedVerboseLevel: "off", + resolvedReasoningLevel: "off", resolveDefaultThinkingLevel: async () => undefined, provider: "telegram", model: "test-model", contextTokens: 0, isGroup: false, }; + return params; } describe("handleCommands /allowlist", () => { diff --git a/src/channels/plugins/actions/actions.test.ts b/src/channels/plugins/actions/actions.test.ts index 8e1d4ffba2..2593f15a09 100644 --- a/src/channels/plugins/actions/actions.test.ts +++ b/src/channels/plugins/actions/actions.test.ts @@ -1,27 +1,27 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../../config/config.js"; -const handleDiscordAction = vi.fn(async () => ({ details: { ok: true } })); -const handleTelegramAction = vi.fn(async () => ({ ok: true })); -const sendReactionSignal = vi.fn(async () => ({ ok: true })); -const removeReactionSignal = vi.fn(async () => ({ ok: true })); -const handleSlackAction = vi.fn(async () => ({ details: { ok: true } })); +const handleDiscordAction = vi.fn(async (..._args: unknown[]) => ({ details: { ok: true } })); +const handleTelegramAction = vi.fn(async (..._args: unknown[]) => ({ ok: true })); +const sendReactionSignal = vi.fn(async (..._args: unknown[]) => ({ ok: true })); +const removeReactionSignal = vi.fn(async (..._args: unknown[]) => ({ ok: true })); +const handleSlackAction = vi.fn(async (..._args: unknown[]) => ({ details: { ok: true } })); vi.mock("../../../agents/tools/discord-actions.js", () => ({ - handleDiscordAction: (...args: unknown[]) => handleDiscordAction(...args), + handleDiscordAction, })); vi.mock("../../../agents/tools/telegram-actions.js", () => ({ - handleTelegramAction: (...args: unknown[]) => handleTelegramAction(...args), + handleTelegramAction, })); vi.mock("../../../signal/send-reactions.js", () => ({ - sendReactionSignal: (...args: unknown[]) => sendReactionSignal(...args), - removeReactionSignal: (...args: unknown[]) => removeReactionSignal(...args), + sendReactionSignal, + removeReactionSignal, })); vi.mock("../../../agents/tools/slack-actions.js", () => ({ - handleSlackAction: (...args: unknown[]) => handleSlackAction(...args), + handleSlackAction, })); const { discordMessageActions } = await import("./discord.js"); @@ -136,7 +136,8 @@ describe("telegram message actions", () => { }); it("routes poll with normalized params", async () => { - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "poll", params: { to: "123", @@ -332,7 +333,7 @@ describe("handleDiscordMessageAction", () => { describe("telegramMessageActions", () => { it("excludes sticker actions when not enabled", () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - const actions = telegramMessageActions.listActions({ cfg }); + const actions = telegramMessageActions.listActions?.({ cfg }) ?? []; expect(actions).not.toContain("sticker"); expect(actions).not.toContain("sticker-search"); }); @@ -340,7 +341,8 @@ describe("telegramMessageActions", () => { it("allows media-only sends and passes asVoice", async () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "send", params: { to: "123", @@ -366,7 +368,8 @@ describe("telegramMessageActions", () => { it("passes silent flag for silent sends", async () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "send", params: { to: "456", @@ -391,7 +394,8 @@ describe("telegramMessageActions", () => { it("maps edit action params into editMessage", async () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "edit", params: { chatId: "123", @@ -421,6 +425,7 @@ describe("telegramMessageActions", () => { await expect( telegramMessageActions.handleAction({ + channel: "telegram", action: "edit", params: { chatId: "123", @@ -445,7 +450,7 @@ describe("telegramMessageActions", () => { }, }, } as OpenClawConfig; - const actions = telegramMessageActions.listActions({ cfg }); + const actions = telegramMessageActions.listActions?.({ cfg }) ?? []; expect(actions).toContain("sticker"); expect(actions).toContain("sticker-search"); @@ -462,7 +467,7 @@ describe("telegramMessageActions", () => { }, }, } as OpenClawConfig; - const actions = telegramMessageActions.listActions({ cfg }); + const actions = telegramMessageActions.listActions?.({ cfg }) ?? []; expect(actions).not.toContain("sticker"); expect(actions).not.toContain("sticker-search"); @@ -471,7 +476,8 @@ describe("telegramMessageActions", () => { it("accepts numeric messageId and channelId for reactions", async () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "react", params: { channelId: 123, @@ -483,17 +489,22 @@ describe("telegramMessageActions", () => { }); expect(handleTelegramAction).toHaveBeenCalledTimes(1); - const call = handleTelegramAction.mock.calls[0]?.[0] as Record; - expect(call.action).toBe("react"); - expect(String(call.chatId)).toBe("123"); - expect(String(call.messageId)).toBe("456"); - expect(call.emoji).toBe("ok"); + const call = handleTelegramAction.mock.calls[0]?.[0]; + if (!call) { + throw new Error("missing telegram action call"); + } + const callPayload = call as Record; + expect(callPayload.action).toBe("react"); + expect(String(callPayload.chatId)).toBe("123"); + expect(String(callPayload.messageId)).toBe("456"); + expect(callPayload.emoji).toBe("ok"); }); it("routes poll action to sendPoll with question and options", async () => { const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; - await telegramMessageActions.handleAction({ + await telegramMessageActions.handleAction?.({ + channel: "telegram", action: "poll", params: { to: "-100123", @@ -519,14 +530,14 @@ describe("telegramMessageActions", () => { describe("signalMessageActions", () => { it("returns no actions when no configured accounts exist", () => { const cfg = {} as OpenClawConfig; - expect(signalMessageActions.listActions({ cfg })).toEqual([]); + expect(signalMessageActions.listActions?.({ cfg }) ?? []).toEqual([]); }); it("hides react when reactions are disabled", () => { const cfg = { channels: { signal: { account: "+15550001111", actions: { reactions: false } } }, } as OpenClawConfig; - expect(signalMessageActions.listActions({ cfg })).toEqual(["send"]); + expect(signalMessageActions.listActions?.({ cfg }) ?? []).toEqual(["send"]); }); it("enables react when at least one account allows reactions", () => { @@ -540,7 +551,7 @@ describe("signalMessageActions", () => { }, }, } as OpenClawConfig; - expect(signalMessageActions.listActions({ cfg })).toEqual(["send", "react"]); + expect(signalMessageActions.listActions?.({ cfg }) ?? []).toEqual(["send", "react"]); }); it("skips send for plugin dispatch", () => { @@ -555,6 +566,7 @@ describe("signalMessageActions", () => { await expect( signalMessageActions.handleAction({ + channel: "signal", action: "react", params: { to: "+15550001111", messageId: "123", emoji: "✅" }, cfg, @@ -575,7 +587,8 @@ describe("signalMessageActions", () => { }, } as OpenClawConfig; - await signalMessageActions.handleAction({ + await signalMessageActions.handleAction?.({ + channel: "signal", action: "react", params: { to: "+15550001111", messageId: "123", emoji: "👍" }, cfg, @@ -592,7 +605,8 @@ describe("signalMessageActions", () => { channels: { signal: { account: "+15550001111" } }, } as OpenClawConfig; - await signalMessageActions.handleAction({ + await signalMessageActions.handleAction?.({ + channel: "signal", action: "react", params: { recipient: "uuid:123e4567-e89b-12d3-a456-426614174000", @@ -618,6 +632,7 @@ describe("signalMessageActions", () => { await expect( signalMessageActions.handleAction({ + channel: "signal", action: "react", params: { to: "signal:group:group-id", messageId: "123", emoji: "✅" }, cfg, @@ -631,7 +646,8 @@ describe("signalMessageActions", () => { channels: { signal: { account: "+15550001111" } }, } as OpenClawConfig; - await signalMessageActions.handleAction({ + await signalMessageActions.handleAction?.({ + channel: "signal", action: "react", params: { to: "signal:group:group-id", diff --git a/src/cli/config-cli.test.ts b/src/cli/config-cli.test.ts index c67bd0667b..82494353dd 100644 --- a/src/cli/config-cli.test.ts +++ b/src/cli/config-cli.test.ts @@ -8,8 +8,8 @@ import type { ConfigFileSnapshot, OpenClawConfig } from "../config/types.js"; * but before runtime defaults), so runtime defaults don't leak into the written config. */ -const mockReadConfigFileSnapshot = vi.fn<[], Promise>(); -const mockWriteConfigFile = vi.fn<[OpenClawConfig], Promise>(async () => {}); +const mockReadConfigFileSnapshot = vi.fn<() => Promise>(); +const mockWriteConfigFile = vi.fn<(cfg: OpenClawConfig) => Promise>(async () => {}); vi.mock("../config/config.js", () => ({ readConfigFileSnapshot: () => mockReadConfigFileSnapshot(), @@ -107,7 +107,7 @@ describe("config cli", () => { const resolved: OpenClawConfig = { gateway: { port: 18789 }, }; - const runtimeMerged: OpenClawConfig = { + const runtimeMerged = { ...resolved, agents: { defaults: { @@ -118,7 +118,7 @@ describe("config cli", () => { } as never, messages: { ackReaction: "✅" } as never, sessions: { persistence: { enabled: true } } as never, - }; + } as unknown as OpenClawConfig; setSnapshot(resolved, runtimeMerged); await runConfigCommand(["config", "set", "gateway.auth.mode", "token"]); diff --git a/src/config/redact-snapshot.test.ts b/src/config/redact-snapshot.test.ts index b2662e54ac..8f262d545f 100644 --- a/src/config/redact-snapshot.test.ts +++ b/src/config/redact-snapshot.test.ts @@ -11,7 +11,16 @@ import { OpenClawSchema } from "./zod-schema.js"; const { mapSensitivePaths } = __test__; -function makeSnapshot(config: Record, raw?: string): ConfigFileSnapshot { +type TestSnapshot> = ConfigFileSnapshot & { + parsed: TConfig; + resolved: TConfig; + config: TConfig; +}; + +function makeSnapshot>( + config: TConfig, + raw?: string, +): TestSnapshot { return { path: "/home/user/.openclaw/config.json5", exists: true, @@ -24,17 +33,17 @@ function makeSnapshot(config: Record, raw?: string): ConfigFile issues: [], warnings: [], legacyIssues: [], - }; + } as TestSnapshot; } -function restoreRedactedValues( +function restoreRedactedValues( incoming: unknown, - original: unknown, + original: TOriginal, hints?: ConfigUiHints, -): unknown { +): TOriginal { var result = restoreRedactedValues_orig(incoming, original, hints); expect(result.ok).toBe(true); - return result.result; + return result.result as TOriginal; } describe("redactConfigSnapshot", () => { @@ -335,7 +344,8 @@ describe("redactConfigSnapshot", () => { compaction: { softThresholdTokens: 50000 }, }); const result = redactConfigSnapshot(snapshot); - const compaction = result.config.compaction as Record; + const config = result.config as typeof snapshot.config; + const compaction = config.compaction as Record; expect(compaction.softThresholdTokens).toBe(50000); }); @@ -365,7 +375,8 @@ describe("redactConfigSnapshot", () => { custom: { mySecret: "this-is-a-custom-secret-value" }, }); const result = redactConfigSnapshot(snapshot, hints); - const custom = result.config.custom as Record; + const config = result.config as typeof snapshot.config; + const custom = config.custom as Record; const resolved = result.resolved as Record>; expect(custom.mySecret).toBe(REDACTED_SENTINEL); expect(resolved.custom.mySecret).toBe(REDACTED_SENTINEL); @@ -396,12 +407,11 @@ describe("redactConfigSnapshot", () => { }); const redacted = redactConfigSnapshot(snapshot, hints); - expect(redacted.config.plugins.entries["voice-call"].config.apiToken).toBe(REDACTED_SENTINEL); - expect(redacted.config.plugins.entries["voice-call"].config.displayName).toBe( - "Voice call extension", - ); - expect(redacted.config.channels["my-channel"].accessToken).toBe(REDACTED_SENTINEL); - expect(redacted.config.channels["my-channel"].room).toBe("general"); + const config = redacted.config as typeof snapshot.config; + expect(config.plugins.entries["voice-call"].config.apiToken).toBe(REDACTED_SENTINEL); + expect(config.plugins.entries["voice-call"].config.displayName).toBe("Voice call extension"); + expect(config.channels["my-channel"].accessToken).toBe(REDACTED_SENTINEL); + expect(config.channels["my-channel"].room).toBe("general"); const restored = restoreRedactedValues(redacted.config, snapshot.config, hints); expect(restored).toEqual(snapshot.config); @@ -425,9 +435,8 @@ describe("redactConfigSnapshot", () => { }); const redacted = redactConfigSnapshot(snapshot, hints); - expect(redacted.config.plugins.entries["voice-call"].config.apiToken).toBe( - "not-secret-on-purpose", - ); + const config = redacted.config as typeof snapshot.config; + expect(config.plugins.entries["voice-call"].config.apiToken).toBe("not-secret-on-purpose"); }); it("handles nested values properly (roundtrip)", () => { @@ -436,8 +445,9 @@ describe("redactConfigSnapshot", () => { custom2: [{ mySecret: "this-is-a-custom-secret-value" }], }); const result = redactConfigSnapshot(snapshot); - expect(result.config.custom1.anykey.mySecret).toBe(REDACTED_SENTINEL); - expect(result.config.custom2[0].mySecret).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.custom1.anykey.mySecret).toBe(REDACTED_SENTINEL); + expect(config.custom2[0].mySecret).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.custom1.anykey.mySecret).toBe("this-is-a-custom-secret-value"); expect(restored.custom2[0].mySecret).toBe("this-is-a-custom-secret-value"); @@ -453,8 +463,9 @@ describe("redactConfigSnapshot", () => { custom2: [{ mySecret: "this-is-a-custom-secret-value" }], }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.custom1.anykey.mySecret).toBe(REDACTED_SENTINEL); - expect(result.config.custom2[0].mySecret).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.custom1.anykey.mySecret).toBe(REDACTED_SENTINEL); + expect(config.custom2[0].mySecret).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.custom1.anykey.mySecret).toBe("this-is-a-custom-secret-value"); expect(restored.custom2[0].mySecret).toBe("this-is-a-custom-secret-value"); @@ -465,8 +476,9 @@ describe("redactConfigSnapshot", () => { custom: { token: "this-is-a-custom-secret-value", mySecret: "this-is-a-custom-secret-value" }, }); const result = redactConfigSnapshot(snapshot); - expect(result.config.custom.token).toBe(REDACTED_SENTINEL); - expect(result.config.custom.mySecret).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.custom.token).toBe(REDACTED_SENTINEL); + expect(config.custom.mySecret).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.custom.token).toBe("this-is-a-custom-secret-value"); expect(restored.custom.mySecret).toBe("this-is-a-custom-secret-value"); @@ -483,8 +495,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.custom.anykey).toBe(REDACTED_SENTINEL); - expect(result.config.custom.mySecret).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.custom.anykey).toBe(REDACTED_SENTINEL); + expect(config.custom.mySecret).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.custom.anykey).toBe("this-is-a-custom-secret-value"); expect(restored.custom.mySecret).toBe("this-is-a-custom-secret-value"); @@ -495,8 +508,9 @@ describe("redactConfigSnapshot", () => { token: ["this-is-a-custom-secret-value", "this-is-a-custom-secret-value"], }); const result = redactConfigSnapshot(snapshot); - expect(result.config.token[0]).toBe(REDACTED_SENTINEL); - expect(result.config.token[1]).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.token[0]).toBe(REDACTED_SENTINEL); + expect(config.token[1]).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.token[0]).toBe("this-is-a-custom-secret-value"); expect(restored.token[1]).toBe("this-is-a-custom-secret-value"); @@ -510,8 +524,9 @@ describe("redactConfigSnapshot", () => { custom: ["this-is-a-custom-secret-value", "this-is-a-custom-secret-value"], }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.custom[0]).toBe(REDACTED_SENTINEL); - expect(result.config.custom[1]).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.custom[0]).toBe(REDACTED_SENTINEL); + expect(config.custom[1]).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.custom[0]).toBe("this-is-a-custom-secret-value"); expect(restored.custom[1]).toBe("this-is-a-custom-secret-value"); @@ -522,8 +537,9 @@ describe("redactConfigSnapshot", () => { harmless: ["this-is-a-custom-harmless-value", "this-is-a-custom-secret-looking-value"], }); const result = redactConfigSnapshot(snapshot); - expect(result.config.harmless[0]).toBe("this-is-a-custom-harmless-value"); - expect(result.config.harmless[1]).toBe("this-is-a-custom-secret-looking-value"); + const config = result.config as typeof snapshot.config; + expect(config.harmless[0]).toBe("this-is-a-custom-harmless-value"); + expect(config.harmless[1]).toBe("this-is-a-custom-secret-looking-value"); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.harmless[0]).toBe("this-is-a-custom-harmless-value"); expect(restored.harmless[1]).toBe("this-is-a-custom-secret-looking-value"); @@ -537,8 +553,9 @@ describe("redactConfigSnapshot", () => { custom: ["this-is-a-custom-harmless-value", "this-is-a-custom-secret-value"], }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.custom[0]).toBe("this-is-a-custom-harmless-value"); - expect(result.config.custom[1]).toBe("this-is-a-custom-secret-value"); + const config = result.config as typeof snapshot.config; + expect(config.custom[0]).toBe("this-is-a-custom-harmless-value"); + expect(config.custom[1]).toBe("this-is-a-custom-secret-value"); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.custom[0]).toBe("this-is-a-custom-harmless-value"); expect(restored.custom[1]).toBe("this-is-a-custom-secret-value"); @@ -553,8 +570,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot); - expect(result.config.nested.level.token[0]).toBe(REDACTED_SENTINEL); - expect(result.config.nested.level.token[1]).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.nested.level.token[0]).toBe(REDACTED_SENTINEL); + expect(config.nested.level.token[1]).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.nested.level.token[0]).toBe("this-is-a-custom-secret-value"); expect(restored.nested.level.token[1]).toBe("this-is-a-custom-secret-value"); @@ -572,8 +590,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.nested.level.custom[0]).toBe(REDACTED_SENTINEL); - expect(result.config.nested.level.custom[1]).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.nested.level.custom[0]).toBe(REDACTED_SENTINEL); + expect(config.nested.level.custom[1]).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.nested.level.custom[0]).toBe("this-is-a-custom-secret-value"); expect(restored.nested.level.custom[1]).toBe("this-is-a-custom-secret-value"); @@ -588,8 +607,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot); - expect(result.config.nested.level.token[0]).toBe(42); - expect(result.config.nested.level.token[1]).toBe(815); + const config = result.config as typeof snapshot.config; + expect(config.nested.level.token[0]).toBe(42); + expect(config.nested.level.token[1]).toBe(815); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.nested.level.token[0]).toBe(42); expect(restored.nested.level.token[1]).toBe(815); @@ -607,8 +627,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.nested.level.custom[0]).toBe(42); - expect(result.config.nested.level.custom[1]).toBe(815); + const config = result.config as typeof snapshot.config; + expect(config.nested.level.custom[0]).toBe(42); + expect(config.nested.level.custom[1]).toBe(815); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.nested.level.custom[0]).toBe(42); expect(restored.nested.level.custom[1]).toBe(815); @@ -623,8 +644,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot); - expect(result.config.nested.password.harmless[0]).toBe(REDACTED_SENTINEL); - expect(result.config.nested.password.harmless[1]).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.nested.password.harmless[0]).toBe(REDACTED_SENTINEL); + expect(config.nested.password.harmless[1]).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.nested.password.harmless[0]).toBe("value"); expect(restored.nested.password.harmless[1]).toBe("value"); @@ -639,8 +661,9 @@ describe("redactConfigSnapshot", () => { }, }); const result = redactConfigSnapshot(snapshot); - expect(result.config.nested.level.harmless[0]).toBe("value"); - expect(result.config.nested.level.harmless[1]).toBe("value"); + const config = result.config as typeof snapshot.config; + expect(config.nested.level.harmless[0]).toBe("value"); + expect(config.nested.level.harmless[1]).toBe("value"); const restored = restoreRedactedValues(result.config, snapshot.config); expect(restored.nested.level.harmless[0]).toBe("value"); expect(restored.nested.level.harmless[1]).toBe("value"); @@ -816,7 +839,7 @@ describe("restoreRedactedValues", () => { }; const snapshot = makeSnapshot(originalConfig); const redacted = redactConfigSnapshot(snapshot, hints); - const custom = redacted.config.custom as Record; + const custom = (redacted.config as typeof originalConfig).custom as Record; expect(custom.myApiKey).toBe(REDACTED_SENTINEL); expect(custom.displayName).toBe("My Bot"); @@ -905,8 +928,9 @@ describe("realredactConfigSnapshot_real", () => { }); const result = redactConfigSnapshot(snapshot, hints); - expect(result.config.agents.defaults.memorySearch.remote.apiKey).toBe(REDACTED_SENTINEL); - expect(result.config.agents.list[0].memorySearch.remote.apiKey).toBe(REDACTED_SENTINEL); + const config = result.config as typeof snapshot.config; + expect(config.agents.defaults.memorySearch.remote.apiKey).toBe(REDACTED_SENTINEL); + expect(config.agents.list[0].memorySearch.remote.apiKey).toBe(REDACTED_SENTINEL); const restored = restoreRedactedValues(result.config, snapshot.config, hints); expect(restored.agents.defaults.memorySearch.remote.apiKey).toBe("1234"); expect(restored.agents.list[0].memorySearch.remote.apiKey).toBe("6789");