(
projectRoot: string,
sessionId: string,
buildEvents: (context: {
readonly events: ReadonlyArray<TranscriptEvent>;
readonly nextSeq: number;
}) => ReadonlyArray<TranscriptEvent> | Promise<ReadonlyArray<TranscriptEvent>>,
)
| 58 | } |
| 59 | |
| 60 | export async function appendTranscriptEvents( |
| 61 | projectRoot: string, |
| 62 | sessionId: string, |
| 63 | buildEvents: (context: { |
| 64 | readonly events: ReadonlyArray<TranscriptEvent>; |
| 65 | readonly nextSeq: number; |
| 66 | }) => ReadonlyArray<TranscriptEvent> | Promise<ReadonlyArray<TranscriptEvent>>, |
| 67 | ): Promise<TranscriptEvent[]> { |
| 68 | const key = `${projectRoot}:${sessionId}`; |
| 69 | const previous = appendQueues.get(key) ?? Promise.resolve(); |
| 70 | let result: TranscriptEvent[] = []; |
| 71 | |
| 72 | const next = previous.then(async () => { |
| 73 | const events = await readTranscriptEvents(projectRoot, sessionId); |
| 74 | const nextSeq = events.reduce((max, event) => Math.max(max, event.seq), 0) + 1; |
| 75 | const built = await buildEvents({ events, nextSeq }); |
| 76 | result = built.map((event) => TranscriptEventSchema.parse(event)); |
| 77 | if (result.length === 0) return; |
| 78 | |
| 79 | await mkdir(sessionsDir(projectRoot), { recursive: true }); |
| 80 | await appendFile( |
| 81 | transcriptPath(projectRoot, sessionId), |
| 82 | `${result.map((event) => JSON.stringify(event)).join("\n")}\n`, |
| 83 | "utf-8", |
| 84 | ); |
| 85 | }); |
| 86 | |
| 87 | appendQueues.set(key, next.catch(() => undefined)); |
| 88 | await next; |
| 89 | return result; |
| 90 | } |
| 91 | |
| 92 | function transcriptRoleForMessage(message: AgentMessage): TranscriptRole | null { |
| 93 | if (!message || typeof message !== "object" || !("role" in message)) return null; |
no test coverage detected