/**
 * Creates a managed stream that wraps the source stream with lifecycle management.
 *
 * The managed stream:
 * - Emits "chunk" events for each chunk
 * - Throws errors from error chunks
 * - Finalizes the session on complete or cancel (but NOT on error - see below)
 *
 * IMPORTANT: This stream intentionally does NOT finalize the session on errors.
 * If you call session.finalize("error") here, the session becomes non-pending,
 * which means new managed streams created during retry will immediately close
 * (see the `!session.isPending()` check in pull).
 *
 * The retry logic in wrapWithRetry is responsible for finalizing the session
 * when all retries are exhausted. Don't be a hero and add finalization here.
 *
 * @param source - The source async iterable stream
 * @param session - The session to update with events
 * @returns A managed stream with lifecycle hooks
 */
export function createManagedStream(source, session) {
    const iterator = source[Symbol.asyncIterator]();
    let closed = false;
    const readable = new ReadableStream({
        async pull(controller) {
            if (closed || !session.isPending()) {
                controller.close();
                return;
            }
            try {
                const result = await iterator.next();
                if (result.done) {
                    closed = true;
                    session.finalize("complete");
                    controller.close();
                    return;
                }
                session.recordChunk();
                void session.events.emit("chunk", result.value, session);
                if (result.value.type === "error") {
                    const chunkError = result.value
                        .error;
                    closed = true;
                    // don't finalize here, wrapWithRetry catches this and decides whether to retry
                    controller.error(chunkError);
                    return;
                }
                controller.enqueue(result.value);
            }
            catch (error) {
                closed = true;
                // no finalization, let wrapWithRetry handle it
                controller.error(error);
            }
        },
        cancel() {
            if (!closed) {
                closed = true;
                if (session.isPending()) {
                    session.finalize("aborted");
                }
            }
            void iterator.return?.();
        },
    });
    return readable;
}
//# sourceMappingURL=managed-stream.js.map