"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.persistAgentTurn = persistAgentTurn;
const sessionPersistenceService_1 = require("./sessionPersistenceService");
const enhancedSessionContext_1 = require("../agent/context/enhancedSessionContext");
const defaultCodebaseServices_1 = require("./codebase/defaultCodebaseServices");
const codeLookupLedger_1 = require("./codebase/codeLookupLedger");
function buildCodebaseSnapshot(codebaseIds) {
    if (!codebaseIds || codebaseIds.length === 0)
        return undefined;
    const registry = (0, defaultCodebaseServices_1.getDefaultCodebaseRegistry)();
    return codebaseIds
        .map(id => registry.get(id))
        .filter(Boolean)
        .map(ref => ({
        codebaseId: ref.codebaseId,
        indexGeneration: ref.indexGeneration,
        consentHash: ref.consent.consentHash,
    }));
}
function buildPersistedAssistantMessage(result) {
    const conclusion = result.conclusion || '';
    if (result.partial !== true)
        return conclusion.substring(0, 10000);
    const warning = [
        '> **结果完整性提示**',
        `> ${result.terminationMessage || '本次分析结果已标记为 partial，结论可能不完整。'}`,
        '',
    ].join('\n');
    return `${warning}${conclusion}`.substring(0, 10000);
}
function persistAgentTurn(input) {
    const { session, sessionId, traceId, query, result, logger } = input;
    const logComponent = input.logComponent ?? 'AgentPersistence';
    const persistenceService = sessionPersistenceService_1.SessionPersistenceService.getInstance();
    try {
        const sessionContext = enhancedSessionContext_1.sessionContextManager.get(sessionId, traceId);
        const snapshot = typeof session.orchestrator.takeSnapshot === 'function'
            ? session.orchestrator.takeSnapshot(sessionId, traceId, {
                referenceTraceId: session.referenceTraceId,
                comparisonSource: session.comparisonSource,
                comparisonReportSection: session.comparisonReportSection,
                conversationSteps: session.conversationSteps || [],
                queryHistory: session.queryHistory || [],
                conclusionHistory: session.conclusionHistory || [],
                agentDialogue: session.agentDialogue || [],
                agentResponses: session.agentResponses || [],
                dataEnvelopes: session.dataEnvelopes || [],
                claimSupport: session.result?.claimSupport || session.claimSupport,
                claimVerificationResult: session.result?.claimVerificationResult || session.claimVerificationResult,
                identityResolutions: session.result?.identityResolutions || session.identityResolutions,
                hypotheses: session.hypotheses || [],
                agentRuntimeProviderId: session.providerId,
                agentRuntimeProviderSnapshotHash: session.providerSnapshotHash,
                codeAwareMode: session.codeAwareMode,
                codebaseIds: session.codebaseIds,
                codebaseSnapshot: buildCodebaseSnapshot(session.codebaseIds),
                codeLookupSummary: codeLookupLedger_1.CodeLookupLedger.restore(sessionId, 12000, 2).toSnapshotSummary(),
                runSequence: session.runSequence || 0,
                activeRun: session.activeRun,
                lastRun: session.lastRun,
                conversationOrdinal: session.conversationOrdinal || 0,
            })
            : null;
        // Stash snapshot EARLY — report builder reads `_lastSnapshot` for
        // analysisNotes / analysisPlan / uncertaintyFlags. Must happen before
        // any persistence I/O that could throw.
        if (snapshot) {
            session._lastSnapshot = snapshot;
        }
        if (snapshot && sessionContext) {
            const focusStoreSnapshot = typeof session.orchestrator.getFocusStore === 'function'
                ? session.orchestrator.getFocusStore().serialize()
                : undefined;
            const traceAgentState = sessionContext.getTraceAgentState() || undefined;
            const saved = persistenceService.saveSessionStateSnapshot(sessionId, snapshot, {
                sessionContext,
                focusStoreSnapshot,
                traceAgentState,
                owner: {
                    tenantId: session.tenantId,
                    workspaceId: session.workspaceId,
                    userId: session.userId,
                },
            });
            if (saved && logger) {
                logger.info(logComponent, 'Session state snapshot persisted atomically', {
                    sessionId,
                    steps: snapshot.conversationSteps.length,
                    envelopes: snapshot.dataEnvelopes.length,
                    notes: snapshot.analysisNotes.length,
                    entityStoreStats: sessionContext.getEntityStore().getStats(),
                });
            }
        }
        else if (sessionContext) {
            // Individual-field fallback for runtimes or older sessions that do not
            // expose a unified snapshot. Current SDK runtimes should normally take
            // the atomic snapshot path above.
            if (!persistenceService.getSession(sessionId)) {
                persistenceService.saveSession({
                    id: sessionId,
                    traceId,
                    traceName: traceId,
                    question: query,
                    messages: [],
                    createdAt: session.createdAt,
                    updatedAt: Date.now(),
                    metadata: {
                        tenantId: session.tenantId,
                        workspaceId: session.workspaceId,
                        userId: session.userId,
                        referenceTraceId: session.referenceTraceId,
                        comparisonSource: session.comparisonSource,
                    },
                });
            }
            persistenceService.saveSessionContext(sessionId, sessionContext);
            if (typeof session.orchestrator.getCachedArchitecture === 'function') {
                const cachedArch = session.orchestrator.getCachedArchitecture(traceId);
                if (cachedArch)
                    persistenceService.saveArchitectureSnapshot(sessionId, cachedArch);
            }
            if (typeof session.orchestrator.getFocusStore === 'function') {
                persistenceService.saveFocusStore(sessionId, session.orchestrator.getFocusStore());
            }
            const traceAgentState = sessionContext.getTraceAgentState();
            if (traceAgentState)
                persistenceService.saveTraceAgentState(sessionId, traceAgentState);
            persistenceService.saveRuntimeArrays(sessionId, {
                conversationSteps: session.conversationSteps || [],
                dataEnvelopes: session.dataEnvelopes || [],
                hypotheses: session.hypotheses || [],
                queryHistory: session.queryHistory || [],
                conclusionHistory: session.conclusionHistory || [],
            });
        }
        // Messages table is a separate SQLite table, always needed for the
        // web UI's history view — persist regardless of which branch above ran.
        if (sessionContext) {
            try {
                const turnIndex = session.runSequence || 1;
                persistenceService.appendMessages(sessionId, [
                    {
                        id: `msg-${sessionId}-turn${turnIndex}-user`,
                        role: 'user',
                        content: query,
                        timestamp: Date.now() - (result.totalDurationMs || 0),
                    },
                    {
                        id: `msg-${sessionId}-turn${turnIndex}-assistant`,
                        role: 'assistant',
                        content: buildPersistedAssistantMessage(result),
                        timestamp: Date.now(),
                    },
                ]);
            }
            catch (msgErr) {
                logger?.warn(logComponent, 'Failed to persist turn messages', {
                    error: msgErr.message,
                });
            }
        }
    }
    catch (err) {
        // Don't fail the analysis if persistence fails — just log. Preserving
        // the snapshot on the session (done above the try boundary) is more
        // important than the SQLite write succeeding.
        const message = err.message;
        if (logger) {
            logger.warn(logComponent, 'Failed to persist session state', { error: message });
        }
        else {
            console.warn(`[AgentPersistence] Failed to persist session ${sessionId} to SQLite: ${message}`);
        }
    }
}
//# sourceMappingURL=persistAgentSession.js.map