122 lines
3.9 KiB
TypeScript
122 lines
3.9 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { groupMessagesByApiRound } from "../grouping";
|
|
|
|
function makeMsg(type: "user" | "assistant" | "system", id: string): any {
|
|
return {
|
|
type,
|
|
message: { id, content: `${type}-${id}` },
|
|
};
|
|
}
|
|
|
|
describe("groupMessagesByApiRound", () => {
|
|
// Boundary fires when: assistant msg with NEW id AND current group has items
|
|
test("splits before first assistant if user messages precede it", () => {
|
|
const messages = [makeMsg("user", "u1"), makeMsg("assistant", "a1")];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
// user msgs form group 1, assistant starts group 2
|
|
expect(groups).toHaveLength(2);
|
|
expect(groups[0]).toHaveLength(1);
|
|
expect(groups[1]).toHaveLength(1);
|
|
});
|
|
|
|
test("single assistant message forms one group", () => {
|
|
const messages = [makeMsg("assistant", "a1")];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(1);
|
|
});
|
|
|
|
test("splits at new assistant message ID", () => {
|
|
const messages = [
|
|
makeMsg("user", "u1"),
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("assistant", "a2"),
|
|
];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(3);
|
|
});
|
|
|
|
test("keeps same-ID assistant messages in same group (streaming chunks)", () => {
|
|
const messages = [
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("assistant", "a1"),
|
|
];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(1);
|
|
expect(groups[0]).toHaveLength(3);
|
|
});
|
|
|
|
test("returns empty array for empty input", () => {
|
|
expect(groupMessagesByApiRound([])).toEqual([]);
|
|
});
|
|
|
|
test("handles all user messages (no assistant)", () => {
|
|
const messages = [makeMsg("user", "u1"), makeMsg("user", "u2")];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(1);
|
|
});
|
|
|
|
test("three API rounds produce correct groups", () => {
|
|
const messages = [
|
|
makeMsg("user", "u1"),
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("user", "u2"),
|
|
makeMsg("assistant", "a2"),
|
|
makeMsg("user", "u3"),
|
|
makeMsg("assistant", "a3"),
|
|
];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
// [u1], [a1, u2], [a2, u3], [a3] = 4 groups
|
|
expect(groups).toHaveLength(4);
|
|
});
|
|
|
|
test("consecutive user messages stay in same group", () => {
|
|
const messages = [makeMsg("user", "u1"), makeMsg("user", "u2")];
|
|
expect(groupMessagesByApiRound(messages)).toHaveLength(1);
|
|
});
|
|
|
|
test("does not produce empty groups", () => {
|
|
const messages = [
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("assistant", "a2"),
|
|
];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
for (const group of groups) {
|
|
expect(group.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
test("handles single message", () => {
|
|
expect(groupMessagesByApiRound([makeMsg("user", "u1")])).toHaveLength(1);
|
|
});
|
|
|
|
test("preserves message order within groups", () => {
|
|
const messages = [makeMsg("assistant", "a1"), makeMsg("user", "u2")];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups[0][0].message.id).toBe("a1");
|
|
expect(groups[0][1].message.id).toBe("u2");
|
|
});
|
|
|
|
test("handles system messages", () => {
|
|
const messages = [
|
|
makeMsg("system", "s1"),
|
|
makeMsg("assistant", "a1"),
|
|
];
|
|
// system msg is non-assistant, goes to current. Then assistant a1 is new ID
|
|
// and current has items, so split.
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(2);
|
|
});
|
|
|
|
test("tool_result after assistant stays in same round", () => {
|
|
const messages = [
|
|
makeMsg("assistant", "a1"),
|
|
makeMsg("user", "tool_result_1"),
|
|
makeMsg("assistant", "a1"), // same ID = no new boundary
|
|
];
|
|
const groups = groupMessagesByApiRound(messages);
|
|
expect(groups).toHaveLength(1);
|
|
expect(groups[0]).toHaveLength(3);
|
|
});
|
|
});
|