export class EventStream implements AsyncIterable { private readonly queue: T[] = []; private readonly waiting: Array<(result: IteratorResult) => void> = []; private done = false; private readonly finalResultPromise: Promise; private resolveFinalResult!: (result: R) => void; constructor( private readonly isComplete: (event: T) => boolean, private readonly extractResult: (event: T) => R ) { this.finalResultPromise = new Promise((resolve) => { this.resolveFinalResult = resolve; }); } push(event: T): void { if (this.done) { return; } if (this.isComplete(event)) { this.done = true; this.resolveFinalResult(this.extractResult(event)); } const waiter = this.waiting.shift(); if (waiter) { waiter({ value: event, done: false }); return; } this.queue.push(event); } async *[Symbol.asyncIterator](): AsyncIterator { while (true) { if (this.queue.length > 0) { yield this.queue.shift()!; } else if (this.done) { return; } else { const result = await new Promise>((resolve) => this.waiting.push(resolve)); if (result.done) { return; } yield result.value; } } } result(): Promise { return this.finalResultPromise; } } export class AssistantMessageEventStream extends EventStream { constructor() { super( (event) => event.type === "done" || event.type === "error", (event) => { if (event.type === "done") { return event.message; } if (event.type === "error") { return event.error; } throw new Error("Unexpected final event"); } ); } } export function createAssistantMessageEventStream(): AssistantMessageEventStream { return new AssistantMessageEventStream(); }