import { describe, expect, test } from "bun:test"; import { type BuildChatUploadPayloadOptions, buildChatUploadPayload, } from "./chat-evidence"; import type { ChatSession } from "./chat-types"; function buildOptions( sessions: ChatSession[], includeRoles?: BuildChatUploadPayloadOptions["includeRoles"], ) { return { sessions, deviceId: "device-1", includeRoles, } satisfies BuildChatUploadPayloadOptions; } describe("buildChatUploadPayload", () => { test("emits evidence thread/message payload for included roles", () => { const session: ChatSession = { providerId: "cline", externalThreadId: "thread-a", conversationFile: "/tmp/thread-a.jsonl", projectPath: "/Users/test/workspace/project-a", title: "Fix lint errors", startedAt: new Date("2026-03-01T10:00:00.000Z"), endedAt: new Date("2026-03-01T10:30:00.000Z"), messages: [ { externalMessageId: "msg-1", role: "user", timestamp: new Date("2026-03-01T10:01:00.000Z"), text: "Please fix this", }, { externalMessageId: "msg-2", role: "assistant", timestamp: new Date("2026-03-01T10:02:00.000Z"), text: "Sure", }, ], }; const { payload } = buildChatUploadPayload(buildOptions([session])); expect(payload.events).toHaveLength(1); expect(payload.evidenceThreads).toHaveLength(1); expect(payload.evidenceMessages).toHaveLength(1); expect(payload.evidenceMessages[0]?.threadId).toBe( payload.evidenceThreads[0]?.id, ); expect(payload.evidenceMessages[0]?.role).toBe("user"); }); test("deduplicates evidence threads and keeps all included messages", () => { const sharedThread = "thread-shared"; const firstSession: ChatSession = { providerId: "copilot", externalThreadId: sharedThread, conversationFile: "/tmp/copilot-thread-1.json", messages: [ { externalMessageId: "m-1", role: "user", timestamp: new Date("2026-03-02T09:00:00.000Z"), text: "question 1", }, ], }; const secondSession: ChatSession = { providerId: "copilot", externalThreadId: sharedThread, conversationFile: "/tmp/copilot-thread-2.json", messages: [ { externalMessageId: "m-2", role: "assistant", timestamp: new Date("2026-03-02T09:01:00.000Z"), text: "answer 1", }, ], }; const { payload } = buildChatUploadPayload( buildOptions([firstSession, secondSession], ["user", "assistant"]), ); expect(payload.evidenceThreads).toHaveLength(1); expect(payload.evidenceMessages).toHaveLength(2); expect(new Set(payload.evidenceMessages.map((m) => m.threadId)).size).toBe( 1, ); expect(payload.events).toHaveLength(2); }); });