import { randomUUID } from "node:crypto";
import { getAgentStreamEventTurnId } from "./agent-sdk-types.js";
export class ForegroundRunState {
    constructor() {
        this.pendingRuns = new Map();
    }
    createPendingRun(agentId) {
        const pendingRun = createPendingForegroundRun();
        this.pendingRuns.set(agentId, pendingRun);
        return pendingRun;
    }
    getPendingRun(agentId) {
        return this.pendingRuns.get(agentId) ?? null;
    }
    hasPendingRun(agentId) {
        return this.pendingRuns.has(agentId);
    }
    settlePendingRun(agentId, token) {
        const pendingRun = this.pendingRuns.get(agentId);
        if (!pendingRun) {
            return;
        }
        if (token && pendingRun.token !== token) {
            return;
        }
        this.pendingRuns.delete(agentId);
        settlePendingForegroundRun(pendingRun);
    }
    createTurnStream(turnId) {
        return new ForegroundTurnStream(turnId);
    }
    addWaiter(agent, waiter) {
        agent.foregroundTurnWaiters.add(waiter);
    }
    deleteWaiter(agent, waiter) {
        agent.foregroundTurnWaiters.delete(waiter);
        this.settleWaiter(waiter);
    }
    settleWaiter(waiter) {
        if (waiter.settled) {
            return;
        }
        waiter.settled = true;
        waiter.resolveSettled();
    }
    getMatchingWaiters(agent, turnId) {
        if (turnId == null) {
            return [];
        }
        return Array.from(agent.foregroundTurnWaiters).filter((waiter) => waiter.turnId === turnId && !waiter.settled);
    }
    notifyWaiters(waiters, event, options) {
        for (const waiter of waiters) {
            waiter.callback(event);
            if (options.terminal) {
                this.settleWaiter(waiter);
            }
        }
    }
    notifyAgentWaiters(agent, event, options) {
        const waiters = this.getMatchingWaiters(agent, getAgentStreamEventTurnId(event));
        this.notifyWaiters(waiters, event, { terminal: options?.terminal ?? false });
    }
    cancelWaiters(agent, createEvent) {
        for (const waiter of agent.foregroundTurnWaiters) {
            waiter.callback(createEvent(waiter.turnId));
            this.settleWaiter(waiter);
        }
        agent.foregroundTurnWaiters.clear();
    }
    clearAgent(agentId, agent) {
        for (const waiter of agent.foregroundTurnWaiters) {
            this.settleWaiter(waiter);
        }
        agent.foregroundTurnWaiters.clear();
        this.settlePendingRun(agentId);
    }
    rememberFinalizedTurn(agent, turnId) {
        agent.finalizedForegroundTurnIds.add(turnId);
        if (agent.finalizedForegroundTurnIds.size <= 50) {
            return;
        }
        const oldest = agent.finalizedForegroundTurnIds.values().next().value;
        if (oldest) {
            agent.finalizedForegroundTurnIds.delete(oldest);
        }
    }
    hasFinalizedTurn(agent, turnId) {
        return agent.finalizedForegroundTurnIds.has(turnId);
    }
}
export class ForegroundTurnStream {
    constructor(turnId) {
        this.queue = [];
        this.queueResolve = null;
        let resolveSettled;
        const settledPromise = new Promise((resolvePromise) => {
            resolveSettled = resolvePromise;
        });
        this.waiter = {
            turnId,
            settled: false,
            settledPromise,
            resolveSettled,
            callback: (event) => {
                this.queue.push(event);
                this.wake();
            },
        };
    }
    async *events(isTerminalEvent) {
        let done = false;
        while (!done) {
            while (this.queue.length > 0) {
                const event = this.queue.shift();
                yield event;
                if (isTerminalEvent(event)) {
                    done = true;
                    break;
                }
            }
            if (!done && this.queue.length === 0) {
                if (this.waiter.settled) {
                    break;
                }
                await new Promise((resolvePromise) => {
                    this.queueResolve = resolvePromise;
                });
            }
        }
    }
    wake() {
        if (!this.queueResolve) {
            return;
        }
        this.queueResolve();
        this.queueResolve = null;
    }
}
function createPendingForegroundRun() {
    let resolveSettled;
    const settledPromise = new Promise((resolvePromise) => {
        resolveSettled = resolvePromise;
    });
    return {
        token: randomUUID(),
        started: false,
        settled: false,
        settledPromise,
        resolveSettled,
    };
}
function settlePendingForegroundRun(pendingRun) {
    if (pendingRun.settled) {
        return;
    }
    pendingRun.settled = true;
    pendingRun.resolveSettled();
}
//# sourceMappingURL=foreground-run-state.js.map