feat(session): Explicit session id naming (#5076)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { mkdtempSync, writeFileSync } from "node:fs";
|
||||
import { existsSync, mkdtempSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { basename, join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { SessionManager } from "../../src/core/session-manager.ts";
|
||||
|
||||
@@ -13,6 +13,23 @@ describe("SessionManager.newSession with custom id", () => {
|
||||
expect(session.getSessionId()).toBe("my-custom-id");
|
||||
});
|
||||
|
||||
it("allows alphanumeric session ids with interior punctuation", () => {
|
||||
const session = SessionManager.inMemory();
|
||||
session.newSession({ id: "abc-123_def.456" });
|
||||
expect(session.getSessionId()).toBe("abc-123_def.456");
|
||||
});
|
||||
|
||||
it("rejects invalid custom session ids", () => {
|
||||
const invalidIds = ["", "-abc", "abc-", "_abc", "abc_", ".abc", "abc.", "abc/def", "abc\\def", "abc def"];
|
||||
|
||||
for (const id of invalidIds) {
|
||||
const session = SessionManager.inMemory();
|
||||
expect(() => session.newSession({ id })).toThrow(
|
||||
"Session id must be non-empty, contain only alphanumeric characters",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("generates a UUIDv7 id when no id is provided", () => {
|
||||
const session = SessionManager.inMemory();
|
||||
session.newSession();
|
||||
@@ -46,6 +63,18 @@ describe("SessionManager.newSession with custom id", () => {
|
||||
expect(session.getHeader()!.id).toBe(session.getSessionId());
|
||||
});
|
||||
|
||||
it("uses the provided id when creating a persisted session", () => {
|
||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-session-manager-"));
|
||||
const session = SessionManager.create(tempDir, tempDir, { id: "created-session-id" });
|
||||
|
||||
expect(session.getSessionId()).toBe("created-session-id");
|
||||
expect(session.getHeader()!.id).toBe("created-session-id");
|
||||
const sessionFile = session.getSessionFile()!;
|
||||
expect(sessionFile).toContain("created-session-id");
|
||||
expect(basename(sessionFile)).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_created-session-id\.jsonl$/);
|
||||
expect(existsSync(sessionFile)).toBe(false);
|
||||
});
|
||||
|
||||
it("generates a UUIDv7 id when creating a branched session", () => {
|
||||
const session = SessionManager.inMemory();
|
||||
const firstId = session.appendMessage({
|
||||
@@ -106,4 +135,28 @@ describe("SessionManager.newSession with custom id", () => {
|
||||
expect(header!.id).toMatch(UUID_V7_RE);
|
||||
expect(header!.parentSession).toBe(sourcePath);
|
||||
});
|
||||
|
||||
it("uses the provided id when forking from another session file", () => {
|
||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-session-manager-"));
|
||||
const sourcePath = join(tempDir, "source.jsonl");
|
||||
writeFileSync(
|
||||
sourcePath,
|
||||
`${JSON.stringify({
|
||||
type: "session",
|
||||
version: 3,
|
||||
id: "source-session-id",
|
||||
timestamp: new Date().toISOString(),
|
||||
cwd: tempDir,
|
||||
})}\n`,
|
||||
);
|
||||
|
||||
const forked = SessionManager.forkFrom(sourcePath, tempDir, tempDir, { id: "forked-session-id" });
|
||||
const header = forked.getHeader();
|
||||
expect(header).not.toBeNull();
|
||||
expect(header!.id).toBe("forked-session-id");
|
||||
expect(header!.parentSession).toBe(sourcePath);
|
||||
const sessionFile = forked.getSessionFile()!;
|
||||
expect(sessionFile).toContain("forked-session-id");
|
||||
expect(basename(sessionFile)).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_forked-session-id\.jsonl$/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user