mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 15:38:25 +00:00
136 lines
5.0 KiB
TypeScript
136 lines
5.0 KiB
TypeScript
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 { mockedGlobalHookRunner } from "./run.overflow-compaction.mocks.shared.js";
|
|
import {
|
|
mockedCompactDirect,
|
|
mockedRunEmbeddedAttempt,
|
|
mockedSessionLikelyHasOversizedToolResults,
|
|
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", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockedGlobalHookRunner.hasHooks.mockImplementation(() => false);
|
|
});
|
|
|
|
it("passes precomputed legacy before_agent_start result into the attempt", async () => {
|
|
const legacyResult = {
|
|
modelOverride: "legacy-model",
|
|
prependContext: "legacy context",
|
|
};
|
|
mockedGlobalHookRunner.hasHooks.mockImplementation(
|
|
(hookName) => hookName === "before_agent_start",
|
|
);
|
|
mockedGlobalHookRunner.runBeforeAgentStart.mockResolvedValueOnce(legacyResult);
|
|
mockedRunEmbeddedAttempt.mockResolvedValueOnce(makeAttemptResult({ promptError: null }));
|
|
|
|
await runEmbeddedPiAgent({
|
|
sessionId: "test-session",
|
|
sessionKey: "test-key",
|
|
sessionFile: "/tmp/session.json",
|
|
workspaceDir: "/tmp/workspace",
|
|
prompt: "hello",
|
|
timeoutMs: 30000,
|
|
runId: "run-legacy-pass-through",
|
|
});
|
|
|
|
expect(mockedGlobalHookRunner.runBeforeAgentStart).toHaveBeenCalledTimes(1);
|
|
expect(mockedRunEmbeddedAttempt).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
legacyBeforeAgentStartResult: legacyResult,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("passes trigger=overflow when retrying compaction after context overflow", async () => {
|
|
mockOverflowRetrySuccess({
|
|
runEmbeddedAttempt: mockedRunEmbeddedAttempt,
|
|
compactDirect: mockedCompactDirect,
|
|
});
|
|
|
|
await runEmbeddedPiAgent(overflowBaseRunParams);
|
|
|
|
expect(mockedCompactDirect).toHaveBeenCalledTimes(1);
|
|
expect(mockedCompactDirect).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
trigger: "overflow",
|
|
authProfileId: "test-profile",
|
|
}),
|
|
);
|
|
});
|
|
|
|
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");
|
|
|
|
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 }));
|
|
|
|
mockedCompactDirect
|
|
.mockResolvedValueOnce({
|
|
ok: false,
|
|
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 },
|
|
});
|
|
|
|
mockedSessionLikelyHasOversizedToolResults.mockReturnValue(true);
|
|
mockedTruncateOversizedToolResultsInSession.mockResolvedValueOnce({
|
|
truncated: true,
|
|
truncatedCount: 1,
|
|
});
|
|
|
|
const result = await runEmbeddedPiAgent(overflowBaseRunParams);
|
|
|
|
expect(mockedCompactDirect).toHaveBeenCalledTimes(3);
|
|
expect(mockedTruncateOversizedToolResultsInSession).toHaveBeenCalledTimes(1);
|
|
expect(mockedRunEmbeddedAttempt).toHaveBeenCalledTimes(4);
|
|
expect(result.meta.error?.kind).toBe("context_overflow");
|
|
});
|
|
|
|
it("returns retry_limit when repeated retries never converge", async () => {
|
|
mockedRunEmbeddedAttempt.mockClear();
|
|
mockedCompactDirect.mockClear();
|
|
mockedPickFallbackThinkingLevel.mockClear();
|
|
mockedRunEmbeddedAttempt.mockResolvedValue(
|
|
makeAttemptResult({ promptError: new Error("unsupported reasoning mode") }),
|
|
);
|
|
mockedPickFallbackThinkingLevel.mockReturnValue("low");
|
|
|
|
const result = await runEmbeddedPiAgent(overflowBaseRunParams);
|
|
|
|
expect(mockedRunEmbeddedAttempt).toHaveBeenCalledTimes(32);
|
|
expect(mockedCompactDirect).not.toHaveBeenCalled();
|
|
expect(result.meta.error?.kind).toBe("retry_limit");
|
|
expect(result.payloads?.[0]?.isError).toBe(true);
|
|
});
|
|
});
|