Archived
fix: handle session start persistence
This commit is contained in:
@@ -215,6 +215,35 @@ describe("PiSessionService", () => {
|
||||
expect(fake.calls.dispose).toBe(1);
|
||||
});
|
||||
|
||||
it("reports persistence from actual session-file existence for fresh active sessions", async () => {
|
||||
const dir = await mkdtemp(join(tmpdir(), "pi-web-persisted-"));
|
||||
const sessionFile = join(dir, "new-session.jsonl");
|
||||
const hub = new CapturingSessionEventHub();
|
||||
const fake = fakeRuntime("new-session", { sessionFile });
|
||||
let service: PiSessionService | undefined;
|
||||
try {
|
||||
service = new PiSessionService(hub, {
|
||||
createAgentRuntime: runtimeCreator(fake.runtime),
|
||||
sessionManager: sessionGateway([]),
|
||||
heartbeatIntervalMs: 60_000,
|
||||
});
|
||||
|
||||
const session = await service.start("/workspace");
|
||||
const createdEvent = hub.globalEvents.find((event) => event.type === "session.created");
|
||||
|
||||
expect(session).toMatchObject({ id: "new-session", path: sessionFile, persisted: false });
|
||||
expect(createdEvent).toMatchObject({ type: "session.created", session: { id: "new-session", persisted: false } });
|
||||
await expect(service.status(sessionRef("new-session"))).resolves.toMatchObject({ sessionId: "new-session", persisted: false });
|
||||
|
||||
await writeFile(sessionFile, '{"type":"session","id":"new-session"}\n', "utf8");
|
||||
|
||||
await expect(service.status(sessionRef("new-session"))).resolves.toMatchObject({ sessionId: "new-session", persisted: true });
|
||||
} finally {
|
||||
await service?.dispose();
|
||||
await rm(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("opens legacy id-only lookups from the default session store gateway", async () => {
|
||||
const hub = new CapturingSessionEventHub();
|
||||
const fake = fakeRuntime("legacy-session");
|
||||
@@ -376,7 +405,7 @@ describe("PiSessionService", () => {
|
||||
|
||||
const sessions = await service.list("/workspace");
|
||||
expect(sessions).toHaveLength(2);
|
||||
expect(sessions[0]).toMatchObject({ id: "active" });
|
||||
expect(sessions[0]).toMatchObject({ id: "active", persisted: true });
|
||||
expect(sessions[0]?.archived).toBeUndefined();
|
||||
expect(sessions[1]).toMatchObject({ id: "archived", archived: true, archivedAt: "2026-01-01T00:00:00.000Z" });
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { statSync } from "node:fs";
|
||||
import { open, readFile, writeFile } from "node:fs/promises";
|
||||
import type { ImageContent } from "@earendil-works/pi-ai";
|
||||
import type { StreamFn } from "@earendil-works/pi-agent-core";
|
||||
@@ -540,6 +541,7 @@ export class PiSessionService {
|
||||
id: session.sessionId,
|
||||
path: session.sessionFile ?? "",
|
||||
cwd,
|
||||
persisted: sessionFileExists(session.sessionFile),
|
||||
created: new Date().toISOString(),
|
||||
modified: new Date().toISOString(),
|
||||
messageCount: session.messages.length,
|
||||
@@ -1857,6 +1859,7 @@ export class PiSessionService {
|
||||
const contextUsage = session.getContextUsage();
|
||||
return {
|
||||
sessionId: session.sessionId,
|
||||
persisted: sessionFileExists(session.sessionFile),
|
||||
...(model === undefined ? {} : { model }),
|
||||
thinkingLevel: session.thinkingLevel,
|
||||
isStreaming: session.isStreaming,
|
||||
@@ -1949,6 +1952,7 @@ function clientSessionFromListEntry(session: PiSessionListEntry): ClientSession
|
||||
id: session.id,
|
||||
path: session.path,
|
||||
cwd: session.cwd,
|
||||
persisted: true,
|
||||
...(session.name === undefined ? {} : { name: session.name }),
|
||||
created: session.created.toISOString(),
|
||||
modified: session.modified.toISOString(),
|
||||
@@ -2151,6 +2155,15 @@ function sessionPathsEqual(a: string, b: string): boolean {
|
||||
return cwdPathsEqual(a, b);
|
||||
}
|
||||
|
||||
function sessionFileExists(sessionFile: string | undefined): sessionFile is string {
|
||||
if (sessionFile === undefined || sessionFile === "") return false;
|
||||
try {
|
||||
return statSync(sessionFile).isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function sessionFileMatches(session: PiAgentSession, expectedSessionFile: string | undefined): boolean {
|
||||
const sessionFile = nonEmptyString(session.sessionFile);
|
||||
return sessionFile !== undefined && expectedSessionFile !== undefined && sessionPathsEqual(sessionFile, expectedSessionFile);
|
||||
|
||||
Reference in New Issue
Block a user