// Task 468 — conversation-archive path slices :Section.body server-side from
// a non-LLM source of turnText (the bin's per-session tempfile). Mirrors the
// document path's Task 465 contract on the chat side.
//
// These tests cover the cross-process plumbing: the cache-path helper that
// both bin and writer use to construct the deterministic tempfile path, plus
// the slicer's behaviour when keyed by `conversationIdentity`.
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { tmpdir } from "node:os";
import { sep } from "node:path";
import { turnTextCachePath, TURN_TEXT_CACHE_DIR_PREFIX, } from "../../lib/conversation-pipeline/turn-text-cache-path.js";
import { deriveSectionBodies } from "../memory-ingest.js";
describe("turnTextCachePath", () => {
    it("constructs a deterministic path under os.tmpdir() keyed by (cid, sha, sessionIndex)", () => {
        const path = turnTextCachePath({
            conversationIdentity: "cid123",
            archiveSha256: "sha456",
            sessionIndex: 1,
        });
        expect(path).toBe([tmpdir(), TURN_TEXT_CACHE_DIR_PREFIX, "cid123-sha456", "session-1.txt"].join(sep));
    });
    it("produces distinct paths for distinct session indices on the same archive", () => {
        const a = turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha",
            sessionIndex: 1,
        });
        const b = turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha",
            sessionIndex: 2,
        });
        expect(a).not.toBe(b);
    });
    it("produces distinct dirs for distinct archives on the same conversation", () => {
        const a = turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha-old",
            sessionIndex: 1,
        });
        const b = turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha-new",
            sessionIndex: 1,
        });
        // Differ in the per-archive directory segment, not the file basename.
        expect(a).not.toBe(b);
        expect(a.endsWith("session-1.txt")).toBe(true);
        expect(b.endsWith("session-1.txt")).toBe(true);
    });
    it("throws on missing conversationIdentity", () => {
        expect(() => turnTextCachePath({
            conversationIdentity: "",
            archiveSha256: "sha",
            sessionIndex: 1,
        })).toThrow(/conversationIdentity/);
    });
    it("throws on missing archiveSha256", () => {
        expect(() => turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "",
            sessionIndex: 1,
        })).toThrow(/archiveSha256/);
    });
    it("throws on non-integer sessionIndex", () => {
        expect(() => turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha",
            sessionIndex: 1.5,
        })).toThrow(/sessionIndex/);
    });
    it("throws on sessionIndex < 1", () => {
        expect(() => turnTextCachePath({
            conversationIdentity: "cid",
            archiveSha256: "sha",
            sessionIndex: 0,
        })).toThrow(/sessionIndex/);
    });
});
describe("deriveSectionBodies on the conversation-archive path", () => {
    let logSpy;
    beforeEach(() => {
        logSpy = vi.spyOn(console, "error").mockImplementation(() => { });
    });
    afterEach(() => {
        logSpy.mockRestore();
    });
    // Mirror of Task 465 test (e) on the chat side — the agent-supplied `body`
    // is the LLM-paraphrase vector this task exists to close. The slicer is
    // shared between paths but the chat-path identity flows through as
    // `sourceKey` so logs stay grep-able by conversationIdentity.
    it("suppresses an agent-supplied body and returns the verbatim turnText slice", () => {
        const turnText = "[2024-01-15T09:30:00+00:00] Joel: Morning\n[2024-01-15T09:31:00+00:00] Adam: hey";
        const cid = "cid-abc";
        const sections = [
            {
                sourceStart: 0,
                sourceEnd: 42,
                body: "PARAPHRASED SUMMARY — Joel greets Adam in the morning",
            },
        ];
        const result = deriveSectionBodies(sections, turnText, cid);
        expect(result).toEqual([turnText.slice(0, 42)]);
        expect(result[0]).not.toContain("PARAPHRASED");
        expect(logSpy.mock.calls[0][0]).toContain("agent body suppressed");
        expect(logSpy.mock.calls[0][0]).toContain(`sourceKey=${cid}`);
    });
    it("slices multiple sections of a chat turnText into verbatim bodies", () => {
        const turnText = "[2024-01-15T09:30:00+00:00] Joel: Morning\n[2024-01-15T09:31:00+00:00] Adam: hey";
        const sections = [
            { sourceStart: 0, sourceEnd: 41 },
            { sourceStart: 42, sourceEnd: turnText.length },
        ];
        const result = deriveSectionBodies(sections, turnText, "cid-multi");
        expect(result[0]).toBe(turnText.slice(0, 41));
        expect(result[1]).toBe(turnText.slice(42, turnText.length));
    });
    it("throws with conversationIdentity in the error when offsets exceed turnText length", () => {
        const turnText = "short";
        const sections = [{ sourceStart: 0, sourceEnd: 1000 }];
        expect(() => deriveSectionBodies(sections, turnText, "cid-oob")).toThrow(/out-of-bounds sourceEnd.*sourceEnd=1000.*textLength=5.*cid-oob/);
    });
});
//# sourceMappingURL=memory-ingest-chat-body-server-sliced.test.js.map