import assert from "node:assert/strict"; import { mkdtempSync, readFileSync, rmSync, existsSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { SessionStore } from "../src/session-store.js"; test("SessionStore persists index + transcript header and can reload", () => { const root = mkdtempSync(join(tmpdir(), "pi-bot-session-store-")); try { const store1 = new SessionStore(root); store1.load(); const key = "dashboard:dm:dashboard-user"; const record1 = store1.ensureSession(key); assert.equal(record1.sessionKey, key); assert.ok(record1.sessionId); assert.ok(record1.sessionFile.endsWith(".jsonl")); assert.ok(existsSync(record1.sessionFile)); const firstLine = readFileSync(record1.sessionFile, "utf-8").split(/\r?\n/)[0] ?? ""; const header = JSON.parse(firstLine) as { type?: string; id?: string }; assert.equal(header.type, "session"); assert.equal(header.id, record1.sessionId); const store2 = new SessionStore(root); store2.load(); assert.deepEqual(store2.listSessionKeys(), [key]); const record2 = store2.ensureSession(key); assert.equal(record2.sessionId, record1.sessionId); assert.equal(record2.sessionFile, record1.sessionFile); } finally { rmSync(root, { recursive: true, force: true }); } }); test("SessionStore reset archives prior transcript and rotates sessionId", () => { const root = mkdtempSync(join(tmpdir(), "pi-bot-session-store-reset-")); try { const store = new SessionStore(root); store.load(); const key = "feishu:dm:user-1"; const first = store.ensureSession(key); assert.ok(existsSync(first.sessionFile)); const second = store.resetSession(key); assert.notEqual(second.sessionId, first.sessionId); assert.notEqual(second.sessionFile, first.sessionFile); assert.ok(existsSync(second.sessionFile)); const sessionsDir = join(root, ".pi-bot", "sessions"); const archiveDir = join(sessionsDir, "archive"); // Old file should have been moved into archive (best-effort rename). assert.ok(existsSync(archiveDir)); } finally { rmSync(root, { recursive: true, force: true }); } });