Something went wrong. Try again.
fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
Something went wrong. Try again.
5.4 kB · 128 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";import { tmpdir } from "node:os";import { join } from "node:path";import { describe, expect, it, vi } from "vitest";import { CURRENT_SESSION_VERSION, SessionManager } from "../../src/core/session-manager.js";import { resolveSessionPath, SessionSelectorAmbiguousError, SessionSelectorNotFoundError,} from "../../src/core/session-resolver.js";import { assistantMsg, userMsg } from "../utilities.js";
function createSession(cwd: string, sessionDir: string, prompt: string): SessionManager { const session = SessionManager.create(cwd, sessionDir); session.appendMessage(userMsg(prompt)); session.appendMessage(assistantMsg(`${prompt} answer`)); return session;}
/** Header-only transcript, so decoy ids stay independent of session-id generation. */function writeHeaderOnlySession(sessionDir: string, id: string, cwd: string): string { mkdirSync(sessionDir, { recursive: true }); const path = join(sessionDir, `${id}.jsonl`); const header = { type: "session", version: CURRENT_SESSION_VERSION, id, timestamp: new Date().toISOString(), cwd }; writeFileSync(path, `${JSON.stringify(header)}\n`); return path;}
describe("resolveSessionPath", () => { it("resolves a session id from the directory listing without scanning the catalog", async () => { const tempDir = mkdtempSync(join(tmpdir(), "session-selector-")); try { const sessionDir = join(tempDir, "sessions"); const cwd = join(tempDir, "project"); const target = createSession(cwd, sessionDir, "target"); writeHeaderOnlySession(sessionDir, "decoy-0000", join(tempDir, "other")); const listSpy = vi.spyOn(SessionManager, "list"); const listAllSpy = vi.spyOn(SessionManager, "listAll");
const resolved = await resolveSessionPath(target.getSessionId(), cwd, sessionDir);
expect(resolved).toEqual({ type: "local", path: target.getSessionFile() }); expect(listSpy).not.toHaveBeenCalled(); expect(listAllSpy).not.toHaveBeenCalled(); listSpy.mockRestore(); listAllSpy.mockRestore(); } finally { rmSync(tempDir, { recursive: true, force: true }); } });
it("resolves an id prefix and a display-id suffix without scanning the catalog", async () => { const tempDir = mkdtempSync(join(tmpdir(), "session-selector-")); try { const sessionDir = join(tempDir, "sessions"); const cwd = join(tempDir, "project"); const target = createSession(cwd, sessionDir, "target"); writeHeaderOnlySession(sessionDir, "decoy-0000", join(tempDir, "other")); const listSpy = vi.spyOn(SessionManager, "list"); const listAllSpy = vi.spyOn(SessionManager, "listAll");
const byPrefix = await resolveSessionPath(target.getSessionId().slice(0, 8), cwd, sessionDir); const bySuffix = await resolveSessionPath(target.getSessionId().slice(-12), cwd, sessionDir);
expect(byPrefix).toEqual({ type: "local", path: target.getSessionFile() }); expect(bySuffix).toEqual({ type: "local", path: target.getSessionFile() }); expect(listSpy).not.toHaveBeenCalled(); expect(listAllSpy).not.toHaveBeenCalled(); listSpy.mockRestore(); listAllSpy.mockRestore(); } finally { rmSync(tempDir, { recursive: true, force: true }); } });
it("reports a session from another project as global with its saved cwd", async () => { const tempDir = mkdtempSync(join(tmpdir(), "session-selector-")); try { const sessionDir = join(tempDir, "sessions"); const otherCwd = join(tempDir, "other"); const target = createSession(otherCwd, sessionDir, "target");
const resolved = await resolveSessionPath(target.getSessionId(), join(tempDir, "project"), sessionDir);
expect(resolved).toEqual({ type: "global", path: target.getSessionFile(), cwd: otherCwd }); } finally { rmSync(tempDir, { recursive: true, force: true }); } });
it("falls back to the scanning resolver for ambiguous and unknown selectors", async () => { const tempDir = mkdtempSync(join(tmpdir(), "session-selector-")); try { const sessionDir = join(tempDir, "sessions"); const cwd = join(tempDir, "project"); writeHeaderOnlySession(sessionDir, "kolbr-aaa", cwd); writeHeaderOnlySession(sessionDir, "kolbr-bbb", cwd);
await expect(resolveSessionPath("kolbr", cwd, sessionDir)).rejects.toBeInstanceOf( SessionSelectorAmbiguousError, ); await expect(resolveSessionPath("zzzznope", cwd, sessionDir)).rejects.toBeInstanceOf( SessionSelectorNotFoundError, ); } finally { rmSync(tempDir, { recursive: true, force: true }); } });
it("does not resolve a transcript whose header id disagrees with its file name", async () => { const tempDir = mkdtempSync(join(tmpdir(), "session-selector-")); try { const sessionDir = join(tempDir, "sessions"); const cwd = join(tempDir, "project"); const target = createSession(cwd, sessionDir, "target"); writeFileSync(join(sessionDir, "renamed.jsonl"), readFileSync(target.getSessionFile()!));
await expect(resolveSessionPath("renamed", cwd, sessionDir)).rejects.toBeInstanceOf( SessionSelectorNotFoundError, ); // The header id still resolves through the scanning fallback. const byHeaderId = await resolveSessionPath(target.getSessionId(), cwd, sessionDir); expect(byHeaderId.path).toBe(target.getSessionFile()); } finally { rmSync(tempDir, { recursive: true, force: true }); } });});