53 lines
2.0 KiB
TypeScript
53 lines
2.0 KiB
TypeScript
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import type { CodingConversationV2 } from './conversation-store';
|
|
import { validateSessionKey } from './conversation-store';
|
|
import type { ConversationSnapshot } from '../../shared/coding-conversation-contracts';
|
|
import { getPiManagedPaths } from '../coding-runtime/pi/resource-loader';
|
|
import { projectPiSessionSnapshot } from '../coding-runtime/pi/session-projector';
|
|
|
|
/** Read durable active-branch history without starting or reconfiguring Pi. */
|
|
export async function readCodingConversationHistory(
|
|
userDataDir: string,
|
|
projectId: string,
|
|
conversation: CodingConversationV2
|
|
): Promise<ConversationSnapshot> {
|
|
const base: ConversationSnapshot = {
|
|
schemaVersion: 1,
|
|
conversation: {
|
|
id: conversation.id,
|
|
projectId,
|
|
agentId: conversation.agentId,
|
|
title: conversation.title,
|
|
model: { model: conversation.model, modelResolution: conversation.modelResolution },
|
|
},
|
|
nodes: [],
|
|
run: { status: 'idle' },
|
|
queue: { items: [] },
|
|
context: { usedTokens: 0, contextWindow: 0, compaction: 'idle' },
|
|
pendingInteractions: [],
|
|
worker: { status: 'stopped', generation: 0 },
|
|
cursor: { workerGeneration: 0, seq: 0 },
|
|
};
|
|
if (!conversation.sessionKey) return base;
|
|
const filename = path.join(
|
|
getPiManagedPaths(userDataDir).sessionsDir,
|
|
projectId,
|
|
validateSessionKey(conversation.sessionKey) + '.jsonl'
|
|
);
|
|
const text = await readFile(filename, 'utf8');
|
|
// Pi 0.84.2 rebuilds its current leaf from the last non-header entry.
|
|
const entries = text
|
|
.split('\n')
|
|
.filter((line) => line.trim())
|
|
.map((line) => JSON.parse(line) as { id: string; type: string })
|
|
.filter((entry) => entry.type !== 'session');
|
|
const snapshot = await projectPiSessionSnapshot({
|
|
snapshot: base,
|
|
workerGeneration: 1,
|
|
state: { isStreaming: false },
|
|
entries: { entries, leafId: entries.at(-1)?.id ?? null },
|
|
});
|
|
return { ...snapshot, worker: { status: 'stopped', generation: 1 } };
|
|
}
|