/**
 * Post-turn queue — executes registered PostTurnHandlers after each turn_end.
 *
 * Handles:
 * - Priority ordering (lower priority number = runs first)
 * - Sequential execution
 * - Cancellation via AbortSignal (fires on user input)
 * - Error isolation (one handler failing doesn't block others)
 *
 * Lives in the extensions layer (app/extensions/), not core/.
 */
/**
 * Run all post-turn handlers that pass shouldRun(), respecting priority order.
 *
 * Execution model:
 * 1. Filter handlers via shouldRun() (sync, fast)
 * 2. Sort by priority (ascending)
 * 3. Execute handlers sequentially. Before each handler, check for user input
 *    and abort if pending.
 *
 * @returns The number of handlers that executed (including errored ones).
 */
export async function runPostTurnHandlers(handlers, ctx, controller, options) {
    const extensionPathFor = (handler) => options.resolveExtensionPath?.(handler) ?? '<post-turn>';
    // 1. Filter
    const eligible = handlers.filter((h) => {
        try {
            return h.shouldRun(ctx);
        }
        catch {
            // shouldRun is supposed to be fast and safe — if it throws, skip the handler
            options.onError({
                extensionPath: extensionPathFor(h),
                event: 'post_turn',
                error: `PostTurnHandler '${h.name}' threw in shouldRun()`
            });
            return false;
        }
    });
    if (eligible.length === 0)
        return 0;
    // 2. Sort by priority (stable sort — preserves registration order for equal priorities)
    eligible.sort((a, b) => a.priority - b.priority);
    // 3. Execute sequentially
    let executedCount = 0;
    for (const handler of eligible) {
        // Check for cancellation before each handler
        if (controller.signal.aborted || options.hasPendingMessages()) {
            controller.abort();
            break;
        }
        await executeHandler(handler, ctx, controller.signal, options, extensionPathFor(handler));
        executedCount++;
    }
    return executedCount;
}
async function executeHandler(handler, ctx, signal, options, extensionPath) {
    try {
        await handler.execute(ctx, signal);
    }
    catch (err) {
        // Error isolation — log and continue
        const message = err instanceof Error ? err.message : String(err);
        const stack = err instanceof Error ? err.stack : undefined;
        options.onError({
            extensionPath,
            event: 'post_turn',
            error: `PostTurnHandler '${handler.name}' failed: ${message}`,
            stack
        });
    }
}
//# sourceMappingURL=post-turn-queue.js.map