openclaw / src /agents /sessions /agent-session-compaction-correlation.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
e249c6d verified
Raw History Blame Contribute Delete
3.66 kB
import type { Model } from "openclaw/plugin-sdk/llm";
import { describe, expect, it, vi } from "vitest";
import { subscribeEmbeddedAgentSession } from "../embedded-agent-subscribe.js";
import { guardSessionManager } from "../session-tool-result-guard-wrapper.js";
import {
createAssistant,
createAssistantResultStream,
createAutoCompactionSettings,
createOverflowAssistant,
createTestSession,
registerAgentSessionLoopTestLifecycle,
streamMocks,
testModel,
} from "./agent-session-loop-correctness.test-support.js";
import {
createCompactionHandlers,
createResourceLoader,
} from "./agent-session-loop-resource-loader.test-support.js";
import { SessionManager } from "./session-manager.js";
registerAgentSessionLoopTestLifecycle();
describe("AgentSession compaction correlation", () => {
it.each(["manual", "automatic"])(
"correlates repeated %s compactions and tokens through the subscriber",
async (mode) => {
const runId = "run-tokens-after";
const sessionManager = guardSessionManager(SessionManager.inMemory(), { runId });
sessionManager.appendMessage({ role: "user", content: "old prompt", timestamp: 1 });
sessionManager.appendMessage({
...createAssistant(testModel, [{ type: "text", text: "retained answer" }]),
timestamp: 2,
});
let requests = 0;
streamMocks.streamSimple.mockImplementation((activeModel: Model) =>
createAssistantResultStream(
++requests % 2 === 1
? createOverflowAssistant(activeModel)
: createAssistant(activeModel, [{ type: "text", text: "complete retry" }]),
),
);
const { session } = await createTestSession({
sessionManager,
settingsManager: createAutoCompactionSettings(),
resourceLoader: createResourceLoader(createCompactionHandlers()),
});
const onAgentEvent = vi.fn();
const subscription = subscribeEmbeddedAgentSession({ session, runId, onAgentEvent });
try {
for (const prompt of ["first long request", "second long request"]) {
if (mode === "manual") {
sessionManager.appendMessage({ role: "user", content: prompt, timestamp: 3 });
sessionManager.appendMessage(
createAssistant(testModel, [{ type: "text", text: "answer" }]),
);
await session.compact();
} else {
await session.prompt(prompt);
}
}
const compactions = sessionManager
.getBranch()
.filter((entry) => entry.type === "compaction");
expect(compactions).toHaveLength(2);
const itemIds = compactions.map(({ __openclaw: metadata }) => metadata?.itemId);
expect(itemIds).toEqual([expect.any(String), expect.any(String)]);
expect(new Set(itemIds).size).toBe(2);
expect(compactions.map(({ __openclaw: metadata }) => metadata?.runId)).toEqual([
runId,
runId,
]);
const events = onAgentEvent.mock.calls
.map(([event]) => event)
.filter((event) => event.stream === "compaction");
expect(events.map(({ data }) => ({ phase: data.phase, itemId: data.itemId }))).toEqual(
itemIds.flatMap((itemId) => [
{ phase: "start", itemId },
{ phase: "end", itemId },
]),
);
expect(subscription.getCompactionCount()).toBe(2);
expect(subscription.getLastCompactionTokensAfter()).toEqual(expect.any(Number));
expect(subscription.getLastCompactionTokensAfter()).toBeGreaterThan(0);
} finally {
subscription.unsubscribe();
}
},
);
});