test(FN-4191): complete Step 5 — cover configurable compaction behavior

Fusion-Task-Id: FN-4191
Fusion-Task-Lineage: 00fddcfc-e136-41a5-84b1-b6f53b1692cb
This commit is contained in:
Fusion
2026-05-14 04:53:19 -07:00
committed by gsxdsm
parent 4f2c458447
commit 7b68913bf5
2 changed files with 121 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { buildCompactedRoomTranscript } from "../chat.js";
import { buildCompactedRoomTranscript, ChatManager } from "../chat.js";
function makeMessage(index: number, overrides: Partial<{
id: string;
@@ -106,6 +106,58 @@ describe("buildCompactedRoomTranscript", () => {
expect(transcript).toContain("message-79-");
});
it("supports recentVerbatim override via opts", () => {
const messages = Array.from({ length: 10 }, (_, index) => makeMessage(index));
const transcript = buildCompactedRoomTranscript(messages, "msg-8", { recentVerbatim: 4 });
expect(transcript).toContain("## Earlier room context (compacted)");
expect(transcript).toContain("- Span: 6 messages");
expect(transcript).not.toContain("- [2026-01-01T00:00:00.000Z] (user) User: message-0");
for (let index = 6; index < 10; index += 1) {
expect(transcript).toContain(`- [2026-01-01T00:00:${String(index).padStart(2, "0")}.000Z]`);
}
});
it("supports summaryMaxChars override via opts", () => {
const olderMessages = Array.from({ length: 18 }, (_, index) => makeMessage(index, {
role: "user",
content: `older-${index}-` + "z".repeat(500),
}));
const recentMessages = Array.from({ length: 12 }, (_, index) => makeMessage(index + 18, {
role: index === 11 ? "user" : "assistant",
senderAgentId: index === 11 ? null : `agent-${index}`,
content: `recent-${index}`,
}));
const transcript = buildCompactedRoomTranscript([...olderMessages, ...recentMessages], "msg-29", { summaryMaxChars: 200 });
const [summaryBlock] = transcript.split("\n\n");
expect(summaryBlock.length).toBeLessThanOrEqual(200);
expect(summaryBlock).toContain("## Earlier room context (compacted)");
});
it("falls back to defaults when room compaction settings are invalid", async () => {
const manager = new ChatManager({} as any, "/tmp", undefined, undefined, async () => ({
fallbackProvider: undefined,
fallbackModelId: undefined,
defaultProvider: undefined,
defaultModelId: undefined,
chatRoomRecentVerbatimMessages: 0,
chatRoomCompactionFetchLimit: -1,
chatRoomSummaryMaxChars: Number.NaN,
}));
const settings = await (manager as any).getRoomCompactionSettings();
expect(settings).toEqual({ recentVerbatim: 12, fetchLimit: 80, summaryMaxChars: 1500 });
const managerWithThrow = new ChatManager({} as any, "/tmp", undefined, undefined, async () => {
throw new Error("boom");
});
const fallbackSettings = await (managerWithThrow as any).getRoomCompactionSettings();
expect(fallbackSettings).toEqual({ recentVerbatim: 12, fetchLimit: 80, summaryMaxChars: 1500 });
});
it("computes unique participant labels from older messages", () => {
const older = [
makeMessage(0, { role: "user", senderAgentId: null, content: "user older" }),

View File

@@ -260,6 +260,74 @@ describe("Chat orchestration — rooms (FN-3805..FN-3811 contract)", () => {
expect(prompt.match(/\[LATEST USER MESSAGE — ANSWER THIS\]/g)).toHaveLength(1);
});
it("uses project chat room compaction settings at responder time", async () => {
mockChatStore.listRoomMembers.mockReturnValue([
{ roomId: "room-1", agentId: "agent-a", role: "member", addedAt: "2026-01-01" },
]);
mockAgentStore.listAgents.mockResolvedValue([{ id: "agent-a", name: "Alpha", role: "executor" }]);
mockAgentStore.getAgent.mockResolvedValue({ id: "agent-a", name: "Alpha", role: "executor" });
const promptSpy = vi.fn().mockResolvedValue(undefined);
mockChatStore.addRoomMessage.mockImplementationOnce((_roomId: string, input: any) => ({
id: "history-latest",
roomId: "room-1",
...input,
}));
__setCreateResolvedAgentSession(async () => ({
session: {
prompt: promptSpy,
dispose: vi.fn(),
state: {
messages: [{ role: "assistant", content: "Room reply" }],
},
},
} as any));
const history = Array.from({ length: 15 }, (_, index) => ({
id: `msg-${index + 1}`,
role: index % 2 === 0 ? "user" : "assistant",
senderAgentId: index % 2 === 0 ? null : "agent-a",
content: `history-item-${index}`,
createdAt: `2026-01-01T00:00:${String(index).padStart(2, "0")}.000Z`,
}));
history[history.length - 1] = {
...history[history.length - 1],
id: "history-latest",
role: "user",
senderAgentId: null,
content: "hello @Alpha",
};
mockChatStore.getRoomMessages.mockImplementation((_roomId: string, filter?: { limit?: number }) => {
const limit = filter?.limit ?? history.length;
return history.slice(-limit);
});
const manager = new ChatManager(
mockChatStore as any,
"/tmp",
mockAgentStore as any,
undefined,
async () => ({
fallbackProvider: undefined,
fallbackModelId: undefined,
defaultProvider: undefined,
defaultModelId: undefined,
chatRoomRecentVerbatimMessages: 3,
chatRoomCompactionFetchLimit: 10,
chatRoomSummaryMaxChars: 400,
}),
);
await manager.sendRoomMessage("room-1", "hello @Alpha");
expect(mockChatStore.getRoomMessages).toHaveBeenCalledWith("room-1", { limit: 10 });
const prompt = promptSpy.mock.calls[0]?.[0] as string;
expect(prompt).toContain("## Earlier room context (compacted)");
expect(prompt).toContain("history-item-12");
expect(prompt).toContain("history-item-13");
expect(prompt).toContain("hello @Alpha [LATEST USER MESSAGE — ANSWER THIS]");
expect(prompt).not.toContain("- [2026-01-01T00:00:11.000Z] (assistant) Agent agent-a: history-item-11");
});
it("throws surfaced error when room has members but no resolvable responders", async () => {
mockChatStore.listRoomMembers.mockReturnValue([
{ roomId: "room-1", agentId: "agent-a", role: "member", addedAt: "2026-01-01" },