From 686294f9f8b2600c6b7a2d023bc9b79f514609bc Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 11 Aug 2026 05:26:07 -0700 Subject: [PATCH] test(sqlite): right-size reliability crash payloads (#122016) * test(sqlite): right-size reliability crash payloads * test(agents): replace hanging provider error integration --------- Co-authored-by: Amp --- .../lib/sqlite-reliability-index-repair.ts | 4 +- scripts/lib/sqlite-reliability-runner.ts | 4 +- ...t-helpers.formatassistanterrortext.test.ts | 17 ++++++ .../provider-error-text.integration.test.ts | 54 ------------------- test/scripts/bench-sqlite-reliability.test.ts | 7 ++- 5 files changed, 26 insertions(+), 60 deletions(-) delete mode 100644 src/plugins/provider-error-text.integration.test.ts diff --git a/scripts/lib/sqlite-reliability-index-repair.ts b/scripts/lib/sqlite-reliability-index-repair.ts index 7b7a819a0e38..005c77919455 100644 --- a/scripts/lib/sqlite-reliability-index-repair.ts +++ b/scripts/lib/sqlite-reliability-index-repair.ts @@ -27,7 +27,9 @@ type WorkerExit = IndexRepairProof["exit"]; const INDEX_REPAIR_WORKER_PATH = fileURLToPath( new URL("./sqlite-reliability-index-repair-worker.ts", import.meta.url), ); -const INDEX_REPAIR_ROWS = 32_768; +// Keep enough index pages to spill both rollback-journal and WAL transactions +// before the worker reports its explicit crash point. +const INDEX_REPAIR_ROWS = 16_384; const INDEX_REPAIR_TIMEOUT_MS = 30_000; function fileSize(filePath: string): number { diff --git a/scripts/lib/sqlite-reliability-runner.ts b/scripts/lib/sqlite-reliability-runner.ts index 7e31c722e0d8..499108446db0 100644 --- a/scripts/lib/sqlite-reliability-runner.ts +++ b/scripts/lib/sqlite-reliability-runner.ts @@ -57,7 +57,9 @@ type IterationMetric = { type CompactionProof = ReliabilityReport["maintenanceProof"]["compaction"]; -const COMPACTION_BLOAT_ROWS = 256; +// Exceed the 1 MiB interruption thresholds without copying an arbitrary 64 MiB +// through every repository and restore crash phase. +const COMPACTION_BLOAT_ROWS = 64; const COMPACTION_BLOAT_PAYLOAD_BYTES = 256 * 1024; function nowMs(): number { diff --git a/src/agents/embedded-agent-helpers.formatassistanterrortext.test.ts b/src/agents/embedded-agent-helpers.formatassistanterrortext.test.ts index bea8a05963a2..5a2330f67e50 100644 --- a/src/agents/embedded-agent-helpers.formatassistanterrortext.test.ts +++ b/src/agents/embedded-agent-helpers.formatassistanterrortext.test.ts @@ -231,6 +231,23 @@ describe("formatAssistantErrorText", () => { const result = formatAssistantErrorText(msg, { provider: "Anthropic" }); expect(result).toBe(formatBillingErrorMessage("Anthropic", "claude-3-5-sonnet")); }); + it("uses prepared provider ownership for billing classification", () => { + const provider = "custom-openrouter"; + const model = "anthropic/claude-sonnet-4"; + const result = formatAssistantErrorText( + makeAssistantError("HTTP 403: API key budget limit exceeded"), + { + provider, + providerOwner: { + id: "openrouter", + classifyFailoverReason: ({ provider: owner, errorMessage }) => + owner === "openrouter" && errorMessage.includes("budget limit") ? "billing" : undefined, + }, + model, + }, + ); + expect(result).toBe(formatBillingErrorMessage(provider, model)); + }); it("returns generic billing message when provider is not given", () => { const msg = makeAssistantError("insufficient credits"); const result = formatAssistantErrorText(msg); diff --git a/src/plugins/provider-error-text.integration.test.ts b/src/plugins/provider-error-text.integration.test.ts deleted file mode 100644 index 036f28695f5e..000000000000 --- a/src/plugins/provider-error-text.integration.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { formatAssistantErrorText } from "../agents/embedded-agent-helpers/error-text.js"; -import { formatBillingErrorMessage } from "../agents/failover/user-copy.js"; -import { makeAssistantMessageFixture } from "../agents/test-helpers/assistant-message-fixtures.js"; -import type { OpenClawConfig } from "../config/types.openclaw.js"; -import { resolveProviderRuntimePlugin } from "./provider-runtime.js"; - -describe("provider-owned terminal error formatting", () => { - it("uses resolved OpenRouter ownership for a custom-provider billing error", () => { - const provider = "custom-openrouter"; - const model = "anthropic/claude-sonnet-4"; - const config = { - models: { - providers: { - [provider]: { - api: "openai-completions", - baseUrl: "https://openrouter.ai/api/v1", - models: [ - { - id: model, - name: model, - reasoning: false, - input: ["text"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 16_000, - maxTokens: 1_024, - }, - ], - }, - }, - }, - } satisfies OpenClawConfig; - const owner = resolveProviderRuntimePlugin({ - provider, - providerOwner: "openrouter", - modelId: model, - config, - }); - expect(owner?.id).toBe("openrouter"); - - const billing = makeAssistantMessageFixture({ - provider, - model, - errorMessage: "HTTP 403: API key budget limit exceeded", - }); - expect( - formatAssistantErrorText(billing, { - provider, - providerOwner: owner, - model, - }), - ).toBe(formatBillingErrorMessage(provider, model)); - }); -}); diff --git a/test/scripts/bench-sqlite-reliability.test.ts b/test/scripts/bench-sqlite-reliability.test.ts index cf0d5d8812ec..49a157401e6d 100644 --- a/test/scripts/bench-sqlite-reliability.test.ts +++ b/test/scripts/bench-sqlite-reliability.test.ts @@ -21,9 +21,10 @@ import { import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js"; const tempDirs = useAutoCleanupTempDirTracker(afterEach); -// Windows repeats ACL checks and >64 MiB crash/restore copies throughout the full proof. +// Windows repeats ACL checks and crash/restore copies throughout the full proof. const RELIABILITY_PROOF_TIMEOUT_MS = process.platform === "win32" ? 480_000 : 240_000; const RELIABILITY_SMOKE_TEST_TIMEOUT_MS = process.platform === "win32" ? 1_200_000 : 300_000; +const MIN_MULTICHUNK_RESTORE_BYTES = 2 * 1024 * 1024; function reliabilitySmokeTest(name: string, test: () => void): void { it(name, test, RELIABILITY_SMOKE_TEST_TIMEOUT_MS); @@ -234,7 +235,6 @@ describe("scripts/bench-sqlite-reliability", () => { expect(firstReport.indexRepairInterruptionProof.rollbackJournal).toMatchObject({ recoveryVerified: true, repairedIndexes: ["idx_openclaw_reliability_records_identity"], - rowsPreserved: 32_768, }); expect( firstReport.indexRepairInterruptionProof.rollbackJournal.journalBytesObserved, @@ -246,7 +246,6 @@ describe("scripts/bench-sqlite-reliability", () => { expect(firstReport.indexRepairInterruptionProof.wal).toMatchObject({ recoveryVerified: true, repairedIndexes: ["idx_openclaw_reliability_records_identity"], - rowsPreserved: 32_768, }); expect(firstReport.indexRepairInterruptionProof.wal.walBytesObserved).toBeGreaterThan(0); expect( @@ -344,7 +343,7 @@ describe("scripts/bench-sqlite-reliability", () => { firstReport.maintenanceProof.repositoryInterruption.afterCommit.payload, ); expect(firstReport.maintenanceProof.restoreInterruption.snapshotBytes).toBeGreaterThan( - 64 * 1024 * 1024, + MIN_MULTICHUNK_RESTORE_BYTES, ); expect(firstReport.maintenanceProof.restoreInterruption.beforePublish).toMatchObject({ existingTargetPreserved: false,