feat: persist session transcripts
This commit is contained in:
51
packages/session/src/transcript.ts
Normal file
51
packages/session/src/transcript.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { DevflowError } from "@devflow/core";
|
||||
|
||||
import type { SessionAdapter, SessionHandle, TranscriptChunk } from "./adapter.js";
|
||||
|
||||
export interface TranscriptChunkSink {
|
||||
append(sessionId: string, chunks: readonly TranscriptChunk[]): Promise<unknown>;
|
||||
}
|
||||
|
||||
export interface CaptureAndPersistTranscriptInput {
|
||||
adapter: Pick<SessionAdapter, "capture">;
|
||||
handle: SessionHandle;
|
||||
fromSeq: bigint;
|
||||
sink: TranscriptChunkSink;
|
||||
}
|
||||
|
||||
export interface CaptureAndPersistTranscriptResult {
|
||||
captured: number;
|
||||
lastSeq: bigint;
|
||||
}
|
||||
|
||||
export async function captureAndPersistTranscript(
|
||||
input: CaptureAndPersistTranscriptInput,
|
||||
): Promise<CaptureAndPersistTranscriptResult> {
|
||||
const chunks: TranscriptChunk[] = [];
|
||||
let lastSeq = input.fromSeq;
|
||||
|
||||
for await (const chunk of input.adapter.capture(input.handle, input.fromSeq)) {
|
||||
if (chunk.seq <= lastSeq) {
|
||||
throw new DevflowError("Transcript chunks must be strictly increasing", {
|
||||
class: "fatal",
|
||||
code: "transcript_sequence_invalid",
|
||||
});
|
||||
}
|
||||
if (chunk.seq !== lastSeq + 1n) {
|
||||
throw new DevflowError("Transcript chunks must be contiguous", {
|
||||
class: "fatal",
|
||||
code: "transcript_sequence_gap",
|
||||
});
|
||||
}
|
||||
chunks.push(chunk);
|
||||
lastSeq = chunk.seq;
|
||||
}
|
||||
|
||||
if (chunks.length === 0) {
|
||||
return { captured: 0, lastSeq: input.fromSeq };
|
||||
}
|
||||
|
||||
await input.sink.append(input.handle.sessionId, chunks);
|
||||
|
||||
return { captured: chunks.length, lastSeq };
|
||||
}
|
||||
Reference in New Issue
Block a user