import { isContextOverflow } from '../core/session/context-overflow.js';
import { classifyError, SessionErrorRecovery } from '../core/session/session-error-recovery.js';
function findLastAssistant(messages) {
    for (let i = messages.length - 1; i >= 0; i -= 1) {
        const message = messages[i];
        if (message?.role === 'assistant')
            return message;
    }
    return undefined;
}
function removeLastErrorGroup(agent, sessionStore, funnel) {
    const messages = agent.state.messages;
    let failedAssistantIndex = messages.length - 1;
    while (failedAssistantIndex >= 0 && messages[failedAssistantIndex]?.role === 'toolResult') {
        failedAssistantIndex -= 1;
    }
    const failedAssistant = messages[failedAssistantIndex];
    if (failedAssistantIndex < 0 ||
        failedAssistant?.role !== 'assistant' ||
        failedAssistant.stopReason !== 'error') {
        console.debug('[embedded-runtime] recovery cleanup skipped: no trailing error assistant');
        return;
    }
    const entryId = funnel.getMessageEntryIds()[failedAssistantIndex];
    agent.replaceMessages(messages.slice(0, failedAssistantIndex));
    funnel.truncateMessageEntryIds(failedAssistantIndex);
    if (entryId) {
        sessionStore.truncateFrom(entryId);
    }
}
/** Build the embedded equivalent of CLI `SessionErrorRecovery`. */
export function createEmbeddedRecoveryWiring(options) {
    const recovery = new SessionErrorRecovery({ sleep: options.recoverySleep });
    if (options.onRecoveryEvent) {
        recovery.onEvent(options.onRecoveryEvent);
    }
    const isOverflow = (message) => isContextOverflow(message, options.agent.state.model?.contextWindow ?? 0);
    return {
        abort() {
            recovery.abort();
        },
        prepareForAgentEnd(event) {
            if (event.type !== 'agent_end')
                return;
            const lastAssistant = findLastAssistant(event.messages);
            // Embedded context-overflow recovery is already owned by compactionWiring,
            // which can compact persisted entries and continue the agent. Do not arm
            // SessionErrorRecovery for the same event or the two systems race.
            if (lastAssistant && classifyError(lastAssistant, isOverflow) === 'context_overflow')
                return;
            recovery.prepareForAgentEnd(lastAssistant, isOverflow, options.getSettings());
        },
        async handleAgentEnd(event) {
            if (event.type !== 'agent_end')
                return false;
            const lastAssistant = findLastAssistant(event.messages);
            if (!lastAssistant) {
                if (recovery.attempt > 0)
                    recovery.onSuccess();
                return false;
            }
            const category = classifyError(lastAssistant, isOverflow);
            if (category === 'context_overflow')
                return false;
            if (!category) {
                if (recovery.attempt > 0)
                    recovery.onSuccess();
                return false;
            }
            return recovery.handleError(lastAssistant, category, options.getSettings(), {
                removeLastAssistantMessage: () => removeLastErrorGroup(options.agent, options.sessionStore, options.funnel),
                continue: options.continueAgent,
                runCompaction: async () => false,
                switchToFallbackModel: async () => false
            });
        },
        wait() {
            return recovery.wait();
        }
    };
}
//# sourceMappingURL=recovery-wiring.js.map