/** Bridge factories wiring `SessionCompaction` + recovery to a host's session/agent. */
import { checkCompactionNeeded } from './session-compaction.js';
// ============================================================================
// Factory: CompactionActions
// ============================================================================
/** Build CompactionActions that bridge SessionCompaction to AgentSession internals. */
export function createCompactionActions(deps) {
    return {
        tryExtensionCompaction: async (preparation, branchEntries, customInstructions, signal) => {
            const runner = deps.extensionRunner();
            if (!runner?.hasHandlers('session_before_compact'))
                return {};
            const result = (await runner.emit({
                type: 'session_before_compact',
                preparation,
                branchEntries,
                customInstructions,
                signal
            }));
            if (result?.cancel)
                return { cancelled: true };
            if (result?.compaction)
                return { result: result.compaction };
            return {};
        },
        persistCompaction: async (result, fromExtension) => {
            deps.sessionManager.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, result.details, fromExtension);
            const newEntries = deps.sessionManager.getEntries();
            const sessionContext = deps.sessionManager.buildSessionContext();
            deps.agent.replaceMessages(sessionContext.messages);
            deps.onMessagesReplaced?.(sessionContext);
            const savedEntry = newEntries.find((e) => e.type === 'compaction' && e.summary === result.summary);
            const runner = deps.extensionRunner();
            if (runner && savedEntry) {
                await runner.emit({
                    type: 'session_compact',
                    compactionEntry: savedEntry,
                    fromExtension
                });
            }
        },
        removeLastAssistantMessage: () => deps.removeLastErrorGroup(),
        continueAgent: () => {
            setTimeout(() => {
                deps.agent.continue().catch(() => { });
            }, 100);
        },
        hasQueuedMessages: () => deps.agent.hasQueuedMessages()
    };
}
// ============================================================================
// Factory: ErrorRecoveryActions
// ============================================================================
/** Build ErrorRecoveryActions that bridge SessionErrorRecovery to AgentSession internals. */
export function createErrorRecoveryActions(deps) {
    return {
        removeLastAssistantMessage: () => deps.removeLastErrorGroup(),
        continue: () => deps.agent.continue(),
        runCompaction: async (keepRecentTokens) => {
            const branchEntries = deps.sessionManager.getBranch();
            const model = deps.model();
            const apiKey = model ? await deps.modelRegistry.getApiKey(model) : undefined;
            if (!model || !apiKey)
                return false;
            // Remove the error assistant message before compaction
            const messages = deps.agent.state.messages;
            if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
                const nextMessages = messages.slice(0, -1);
                deps.agent.replaceMessages(nextMessages);
                deps.onAgentMessagesReplaced?.(nextMessages);
            }
            try {
                await deps.compaction.runAuto('overflow', true, model, apiKey, branchEntries, deps.compactionActions(), keepRecentTokens);
                return true;
            }
            catch {
                return false;
            }
        },
        switchToFallbackModel: async (fallbackModel, _stripThinking) => {
            // Model fallback: find and switch to the fallback model
            const parts = fallbackModel.split('/');
            const provider = parts.length > 1 ? parts[0] : 'anthropic';
            const modelId = parts.length > 1 ? parts[1] : fallbackModel;
            const model = deps.modelRegistry.find(provider, modelId);
            if (!model)
                return false;
            await deps.setModel(model);
            return true;
        }
    };
}
// ============================================================================
// Standalone: triggerCompactionIfNeeded
// ============================================================================
/** Check compaction decision and trigger if needed.
 *
 * `opts.heartbeatWrap` is the per-turn heartbeat wrap captured *synchronously*
 * by the caller before the agent loop's finally clears it. Forwarded into
 * runAuto so the LLM compaction + persist work emits compaction_* telemetry. */
export async function triggerCompactionIfNeeded(deps, msg, skipAbortedCheck, opts) {
    const branchEntries = deps.sessionManager.getBranch();
    const decision = checkCompactionNeeded(msg, {
        currentModel: deps.model(),
        branchEntries,
        contextWindowOverride: deps.getContextWindowOverride?.()
    }, skipAbortedCheck);
    if (decision.action === 'overflow') {
        const messages = deps.agent.state.messages;
        if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
            const nextMessages = messages.slice(0, -1);
            deps.agent.replaceMessages(nextMessages);
            deps.onAgentMessagesReplaced?.(nextMessages);
        }
        await deps.compaction.runAuto('overflow', true, deps.model(), await deps.modelRegistry.getApiKey(deps.model()), branchEntries, deps.compactionActions, undefined, opts?.heartbeatWrap);
    }
    else if (decision.action === 'threshold') {
        await deps.compaction.runAuto('threshold', false, deps.model(), deps.model() ? await deps.modelRegistry.getApiKey(deps.model()) : undefined, branchEntries, deps.compactionActions, undefined, opts?.heartbeatWrap);
    }
}
//# sourceMappingURL=compaction-bridge.js.map