/** * A minimal push/pull async queue used to turn callback/stream-driven agent * output into an `AsyncIterable`. Shared by the provider harness adapters * (Codex app-server, Cursor CLI). */ export class AsyncQueue implements AsyncIterable { private values: T[] = [] private resolvers: Array<(value: IteratorResult) => void> = [] private done = false push(value: T) { if (this.done) return const resolver = this.resolvers.shift() if (resolver) { resolver({ value, done: false }) return } this.values.push(value) } finish() { if (this.done) return this.done = true while (this.resolvers.length > 0) { const resolver = this.resolvers.shift() resolver?.({ value: undefined as T, done: true }) } } [Symbol.asyncIterator](): AsyncIterator { return { next: () => { if (this.values.length > 0) { return Promise.resolve({ value: this.values.shift() as T, done: false }) } if (this.done) { return Promise.resolve({ value: undefined as T, done: true }) } return new Promise>((resolve) => { this.resolvers.push(resolve) }) }, } } }