refactor(test): dedupe agent and discord test fixtures

This commit is contained in:
Peter Steinberger
2026-02-22 20:01:43 +00:00
parent 5547a2275c
commit 3c75bc0e41
26 changed files with 632 additions and 737 deletions

View File

@@ -7,9 +7,9 @@ vi.mock("../pi-model-discovery.js", () => ({
import { buildInlineProviderModels, resolveModel } from "./model.js";
import {
buildOpenAICodexForwardCompatExpectation,
makeModel,
mockDiscoveredModel,
OPENAI_CODEX_TEMPLATE_MODEL,
mockOpenAICodexTemplateModel,
resetMockDiscoverModels,
} from "./model.test-harness.js";
@@ -38,21 +38,11 @@ describe("pi embedded model e2e smoke", () => {
});
it("builds an openai-codex forward-compat fallback for gpt-5.3-codex", () => {
mockDiscoveredModel({
provider: "openai-codex",
modelId: "gpt-5.2-codex",
templateModel: OPENAI_CODEX_TEMPLATE_MODEL,
});
mockOpenAICodexTemplateModel();
const result = resolveModel("openai-codex", "gpt-5.3-codex", "/tmp/agent");
expect(result.error).toBeUndefined();
expect(result.model).toMatchObject({
provider: "openai-codex",
id: "gpt-5.3-codex",
api: "openai-codex-responses",
baseUrl: "https://chatgpt.com/backend-api",
reasoning: true,
});
expect(result.model).toMatchObject(buildOpenAICodexForwardCompatExpectation("gpt-5.3-codex"));
});
it("keeps unknown-model errors for non-forward-compat IDs", () => {

View File

@@ -25,6 +25,28 @@ export const OPENAI_CODEX_TEMPLATE_MODEL = {
maxTokens: 128000,
};
export function mockOpenAICodexTemplateModel(): void {
mockDiscoveredModel({
provider: "openai-codex",
modelId: "gpt-5.2-codex",
templateModel: OPENAI_CODEX_TEMPLATE_MODEL,
});
}
export function buildOpenAICodexForwardCompatExpectation(
id: string = "gpt-5.3-codex",
): Partial<typeof OPENAI_CODEX_TEMPLATE_MODEL> & { provider: string; id: string } {
return {
provider: "openai-codex",
id,
api: "openai-codex-responses",
baseUrl: "https://chatgpt.com/backend-api",
reasoning: true,
contextWindow: 272000,
maxTokens: 128000,
};
}
export function resetMockDiscoverModels(): void {
vi.mocked(discoverModels).mockReturnValue({
find: vi.fn(() => null),

View File

@@ -8,9 +8,10 @@ vi.mock("../pi-model-discovery.js", () => ({
import type { OpenClawConfig } from "../../config/config.js";
import { buildInlineProviderModels, resolveModel } from "./model.js";
import {
buildOpenAICodexForwardCompatExpectation,
makeModel,
mockDiscoveredModel,
OPENAI_CODEX_TEMPLATE_MODEL,
mockOpenAICodexTemplateModel,
resetMockDiscoverModels,
} from "./model.test-harness.js";
@@ -171,24 +172,12 @@ describe("resolveModel", () => {
});
it("builds an openai-codex fallback for gpt-5.3-codex", () => {
mockDiscoveredModel({
provider: "openai-codex",
modelId: "gpt-5.2-codex",
templateModel: OPENAI_CODEX_TEMPLATE_MODEL,
});
mockOpenAICodexTemplateModel();
const result = resolveModel("openai-codex", "gpt-5.3-codex", "/tmp/agent");
expect(result.error).toBeUndefined();
expect(result.model).toMatchObject({
provider: "openai-codex",
id: "gpt-5.3-codex",
api: "openai-codex-responses",
baseUrl: "https://chatgpt.com/backend-api",
reasoning: true,
contextWindow: 272000,
maxTokens: 128000,
});
expect(result.model).toMatchObject(buildOpenAICodexForwardCompatExpectation("gpt-5.3-codex"));
});
it("builds an anthropic forward-compat fallback for claude-opus-4-6", () => {

View File

@@ -1,5 +1,28 @@
import type { EmbeddedRunAttemptResult } from "./run/types.js";
export const DEFAULT_OVERFLOW_ERROR_MESSAGE =
"request_too_large: Request size exceeds model context window";
export function makeOverflowError(message: string = DEFAULT_OVERFLOW_ERROR_MESSAGE): Error {
return new Error(message);
}
export function makeCompactionSuccess(params: {
summary: string;
firstKeptEntryId: string;
tokensBefore: number;
}) {
return {
ok: true as const,
compacted: true as const,
result: {
summary: params.summary,
firstKeptEntryId: params.firstKeptEntryId,
tokensBefore: params.tokensBefore,
},
};
}
export function makeAttemptResult(
overrides: Partial<EmbeddedRunAttemptResult> = {},
): EmbeddedRunAttemptResult {
@@ -43,24 +66,38 @@ export function mockOverflowRetrySuccess(params: {
compactDirect: MockCompactDirect;
overflowMessage?: string;
}) {
const overflowError = new Error(
params.overflowMessage ?? "request_too_large: Request size exceeds model context window",
);
const overflowError = makeOverflowError(params.overflowMessage);
params.runEmbeddedAttempt.mockResolvedValueOnce(
makeAttemptResult({ promptError: overflowError }),
);
params.runEmbeddedAttempt.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
params.compactDirect.mockResolvedValueOnce({
ok: true,
compacted: true,
result: {
params.compactDirect.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted session",
firstKeptEntryId: "entry-5",
tokensBefore: 150000,
},
});
}),
);
return overflowError;
}
export function queueOverflowAttemptWithOversizedToolOutput(
runEmbeddedAttempt: MockRunEmbeddedAttempt,
overflowError: Error = makeOverflowError(),
): Error {
runEmbeddedAttempt.mockResolvedValueOnce(
makeAttemptResult({
promptError: overflowError,
messagesSnapshot: [
{
role: "assistant",
content: "big tool output",
} as unknown as EmbeddedRunAttemptResult["messagesSnapshot"][number],
],
}),
);
return overflowError;
}

View File

@@ -8,7 +8,13 @@ vi.mock("../../utils.js", () => ({
import { log } from "./logger.js";
import { runEmbeddedPiAgent } from "./run.js";
import { makeAttemptResult, mockOverflowRetrySuccess } from "./run.overflow-compaction.fixture.js";
import {
makeAttemptResult,
makeCompactionSuccess,
makeOverflowError,
mockOverflowRetrySuccess,
queueOverflowAttemptWithOversizedToolOutput,
} from "./run.overflow-compaction.fixture.js";
import {
mockedCompactDirect,
mockedRunEmbeddedAttempt,
@@ -86,15 +92,13 @@ describe("overflow compaction in run loop", () => {
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowHintError }))
.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
mockedCompactDirect.mockResolvedValueOnce({
ok: true,
compacted: true,
result: {
mockedCompactDirect.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted session",
firstKeptEntryId: "entry-6",
tokensBefore: 140000,
},
});
}),
);
const result = await runEmbeddedPiAgent(baseParams);
@@ -105,7 +109,7 @@ describe("overflow compaction in run loop", () => {
});
it("returns error if compaction fails", async () => {
const overflowError = new Error("request_too_large: Request size exceeds model context window");
const overflowError = makeOverflowError();
mockedRunEmbeddedAttempt.mockResolvedValue(makeAttemptResult({ promptError: overflowError }));
@@ -125,21 +129,8 @@ describe("overflow compaction in run loop", () => {
});
it("falls back to tool-result truncation and retries when oversized results are detected", async () => {
const overflowError = new Error("request_too_large: Request size exceeds model context window");
mockedRunEmbeddedAttempt
.mockResolvedValueOnce(
makeAttemptResult({
promptError: overflowError,
messagesSnapshot: [
{
role: "assistant",
content: "big tool output",
} as unknown as EmbeddedRunAttemptResult["messagesSnapshot"][number],
],
}),
)
.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
queueOverflowAttemptWithOversizedToolOutput(mockedRunEmbeddedAttempt, makeOverflowError());
mockedRunEmbeddedAttempt.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
mockedCompactDirect.mockResolvedValueOnce({
ok: false,
@@ -167,7 +158,7 @@ describe("overflow compaction in run loop", () => {
});
it("retries compaction up to 3 times before giving up", async () => {
const overflowError = new Error("request_too_large: Request size exceeds model context window");
const overflowError = makeOverflowError();
// 4 overflow errors: 3 compaction retries + final failure
mockedRunEmbeddedAttempt
@@ -177,21 +168,27 @@ describe("overflow compaction in run loop", () => {
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowError }));
mockedCompactDirect
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 1", firstKeptEntryId: "entry-3", tokensBefore: 180000 },
})
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 2", firstKeptEntryId: "entry-5", tokensBefore: 160000 },
})
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 3", firstKeptEntryId: "entry-7", tokensBefore: 140000 },
});
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 1",
firstKeptEntryId: "entry-3",
tokensBefore: 180000,
}),
)
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 2",
firstKeptEntryId: "entry-5",
tokensBefore: 160000,
}),
)
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 3",
firstKeptEntryId: "entry-7",
tokensBefore: 140000,
}),
);
const result = await runEmbeddedPiAgent(baseParams);
@@ -204,7 +201,7 @@ describe("overflow compaction in run loop", () => {
});
it("succeeds after second compaction attempt", async () => {
const overflowError = new Error("request_too_large: Request size exceeds model context window");
const overflowError = makeOverflowError();
mockedRunEmbeddedAttempt
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowError }))
@@ -212,16 +209,20 @@ describe("overflow compaction in run loop", () => {
.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
mockedCompactDirect
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 1", firstKeptEntryId: "entry-3", tokensBefore: 180000 },
})
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 2", firstKeptEntryId: "entry-5", tokensBefore: 160000 },
});
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 1",
firstKeptEntryId: "entry-3",
tokensBefore: 180000,
}),
)
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 2",
firstKeptEntryId: "entry-5",
tokensBefore: 160000,
}),
);
const result = await runEmbeddedPiAgent(baseParams);
@@ -259,15 +260,13 @@ describe("overflow compaction in run loop", () => {
)
.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
mockedCompactDirect.mockResolvedValueOnce({
ok: true,
compacted: true,
result: {
mockedCompactDirect.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted session",
firstKeptEntryId: "entry-5",
tokensBefore: 150000,
},
});
}),
);
const result = await runEmbeddedPiAgent(baseParams);

View File

@@ -2,7 +2,13 @@ import "./run.overflow-compaction.mocks.shared.js";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { pickFallbackThinkingLevel } from "../pi-embedded-helpers.js";
import { runEmbeddedPiAgent } from "./run.js";
import { makeAttemptResult, mockOverflowRetrySuccess } from "./run.overflow-compaction.fixture.js";
import {
makeAttemptResult,
makeCompactionSuccess,
makeOverflowError,
mockOverflowRetrySuccess,
queueOverflowAttemptWithOversizedToolOutput,
} from "./run.overflow-compaction.fixture.js";
import { mockedGlobalHookRunner } from "./run.overflow-compaction.mocks.shared.js";
import {
mockedCompactDirect,
@@ -11,7 +17,6 @@ import {
mockedTruncateOversizedToolResultsInSession,
overflowBaseRunParams,
} from "./run.overflow-compaction.shared-test.js";
import type { EmbeddedRunAttemptResult } from "./run/types.js";
const mockedPickFallbackThinkingLevel = vi.mocked(pickFallbackThinkingLevel);
describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
@@ -67,20 +72,11 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
});
it("does not reset compaction attempt budget after successful tool-result truncation", async () => {
const overflowError = new Error("request_too_large: Request size exceeds model context window");
const overflowError = queueOverflowAttemptWithOversizedToolOutput(
mockedRunEmbeddedAttempt,
makeOverflowError(),
);
mockedRunEmbeddedAttempt
.mockResolvedValueOnce(
makeAttemptResult({
promptError: overflowError,
messagesSnapshot: [
{
role: "assistant",
content: "big tool output",
} as unknown as EmbeddedRunAttemptResult["messagesSnapshot"][number],
],
}),
)
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowError }))
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowError }))
.mockResolvedValueOnce(makeAttemptResult({ promptError: overflowError }));
@@ -91,16 +87,20 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
compacted: false,
reason: "nothing to compact",
})
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 2", firstKeptEntryId: "entry-5", tokensBefore: 160000 },
})
.mockResolvedValueOnce({
ok: true,
compacted: true,
result: { summary: "Compacted 3", firstKeptEntryId: "entry-7", tokensBefore: 140000 },
});
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 2",
firstKeptEntryId: "entry-5",
tokensBefore: 160000,
}),
)
.mockResolvedValueOnce(
makeCompactionSuccess({
summary: "Compacted 3",
firstKeptEntryId: "entry-7",
tokensBefore: 140000,
}),
);
mockedSessionLikelyHasOversizedToolResults.mockReturnValue(true);
mockedTruncateOversizedToolResultsInSession.mockResolvedValueOnce({