pi session context persistence, fix new session button, add clear all sessions

- handle pi process death by nulling piProcess ref so next message respawns
- replay conversation history on respawn via --session flag
- fix user message JSONL format to array for pi compatibility
- fix container sessions mount to match storage path
- fix ChatPanelWrapper: key on inner component so usePiChat resets on new session
- add bulk delete sessions endpoint and clear all button in chat header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 00:04:14 +00:00
co-authored by Claude Opus 4.6
parent a8d3d1a423
commit c443fe0fe2
9 changed files with 192 additions and 31 deletions
+16 -2
View File
@@ -129,7 +129,7 @@ export function messagesToJnlEntries(messages: Message[], meta: SessionMeta): Jn
id,
parentId: prevId,
timestamp: new Date(msg.timestamp).toISOString(),
message: { role: 'user', content: msg.text ?? '' },
message: { role: 'user', content: [{ type: 'text' as const, text: msg.text ?? '' }] },
};
entries.push(entry);
prevId = id;
@@ -281,11 +281,16 @@ export function jnlEntriesToMessages(entries: JnlEntry[]): ParsedSession {
const ts = new Date(entry.timestamp).getTime();
if (msgEntry.message.role === 'user') {
const rawContent = msgEntry.message.content;
const text =
typeof rawContent === 'string'
? rawContent
: (rawContent as Array<JnlTextContent>).map((c) => c.text).join('\n');
messages.push({
id: entry.id,
timestamp: ts,
role: 'user',
text: msgEntry.message.content as string,
text,
});
} else if (msgEntry.message.role === 'assistant') {
const contentBlocks = msgEntry.message.content as Array<JnlTextContent | JnlToolCall>;
@@ -380,6 +385,15 @@ function metaToIndexEntry(meta: SessionMeta, relFile: string): SessionIndexEntry
};
}
// ── Path resolution ─────────────────────────────────────────────────────
export async function getSessionFilePath(baseCwd: string, sessionId: string): Promise<string | null> {
const index = await loadIndex(baseCwd);
const entry = index[sessionId];
if (!entry) return null;
return path.join(getSessionsDir(baseCwd), entry.file);
}
// ── Session CRUD ───────────────────────────────────────────────────────
export async function saveSession(