Show session lineage and support detaching forks

This commit is contained in:
Federico Jaramillo Martinez
2026-05-10 00:28:08 +02:00
parent d539aa2f96
commit 39ea4bfc15
11 changed files with 128 additions and 11 deletions
+21
View File
@@ -1,3 +1,4 @@
import { readFile, writeFile } from "node:fs/promises";
import {
AuthStorage,
createAgentSessionFromServices,
@@ -115,6 +116,7 @@ export class PiSessionService {
modified: s.modified.toISOString(),
messageCount: s.messageCount,
firstMessage: s.firstMessage,
...(s.parentSessionPath === undefined ? {} : { parentSessionPath: s.parentSessionPath }),
...(archived === undefined ? {} : { archived: true, archivedAt: archived.archivedAt }),
};
});
@@ -234,6 +236,13 @@ export class PiSessionService {
await this.archiveStore.restore(sessionId);
}
async detachParent(sessionId: string): Promise<void> {
const session = await this.getOrOpen(sessionId);
const sessionFile = session.sessionFile;
if (sessionFile === undefined || sessionFile === "") throw new Error("Session is not persisted");
await clearParentSession(sessionFile);
}
async abort(sessionId: string): Promise<void> {
const active = this.active.get(sessionId);
if (!active) return;
@@ -414,6 +423,18 @@ export class PiSessionService {
}
}
async function clearParentSession(sessionFile: string): Promise<void> {
const content = await readFile(sessionFile, "utf8");
const newlineIndex = content.indexOf("\n");
const firstLine = newlineIndex === -1 ? content : content.slice(0, newlineIndex);
const rest = newlineIndex === -1 ? "" : content.slice(newlineIndex);
const header: unknown = JSON.parse(firstLine);
if (!isRecord(header) || header["type"] !== "session") throw new Error("Invalid session file header");
if (header["parentSession"] === undefined) return;
delete header["parentSession"];
await writeFile(sessionFile, `${JSON.stringify(header)}${rest}`, "utf8");
}
function userTextMessage(text: string): { role: "user"; content: string } {
return { role: "user", content: text };
}