"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.ArtifactStore = void 0;
class ArtifactStore {
    constructor(maxArtifacts = 50) {
        this.artifacts = new Map();
        this.counter = 0;
        this.maxArtifacts = maxArtifacts;
    }
    /**
     * Store a skill result artifact and return its reference ID.
     * Evicts least-recently-accessed artifacts when exceeding capacity.
     */
    store(entry) {
        const id = `art-${++this.counter}`;
        const now = Date.now();
        this.artifacts.set(id, {
            id,
            ...entry,
            storedAt: now,
            lastAccessedAt: now,
        });
        // LRU eviction: remove least-recently-accessed artifacts
        while (this.artifacts.size > this.maxArtifacts) {
            let oldestId;
            let oldestTime = Infinity;
            for (const [aid, art] of this.artifacts) {
                if (art.lastAccessedAt < oldestTime) {
                    oldestTime = art.lastAccessedAt;
                    oldestId = aid;
                }
            }
            if (oldestId)
                this.artifacts.delete(oldestId);
            else
                break;
        }
        return id;
    }
    /**
     * Get a stored artifact by ID. Updates access time for LRU tracking.
     */
    get(id) {
        const artifact = this.artifacts.get(id);
        if (artifact)
            artifact.lastAccessedAt = Date.now();
        return artifact;
    }
    /**
     * Generate a compact summary for an artifact (for Claude's context).
     */
    generateSummary(id) {
        const artifact = this.artifacts.get(id);
        if (!artifact)
            return undefined;
        const data = artifact.data;
        const columns = data?.columns || [];
        const rows = data?.rows || [];
        return {
            id: artifact.id,
            skillId: artifact.skillId,
            stepId: artifact.stepId,
            layer: artifact.layer,
            title: artifact.title,
            rowCount: rows.length,
            columns,
            sampleRow: rows.length > 0 ? rows[0] : undefined,
            diagnosticCount: Array.isArray(artifact.diagnostics) ? artifact.diagnostics.length : 0,
            planPhaseId: artifact.planPhaseId,
            planPhaseTitle: artifact.planPhaseTitle,
            planPhaseGoal: artifact.planPhaseGoal,
            sourceToolCallId: artifact.sourceToolCallId,
            identityResolution: artifact.identityResolution,
        };
    }
    /**
     * Generate a compact summary optimized for Claude's context window.
     * Delegates to generateSummary(), then reshapes:
     * - skillId/layer: omitted (already in parent invoke_skill result)
     * - diagnosticCount: only included when > 0
     * - columns + sampleRow → preview: { column: value } (self-describing)
     */
    generateCompactSummary(id) {
        const full = this.generateSummary(id);
        if (!full)
            return undefined;
        let preview;
        if (full.sampleRow && full.columns.length > 0) {
            preview = {};
            for (let i = 0; i < full.columns.length; i++) {
                preview[full.columns[i]] = i < full.sampleRow.length ? full.sampleRow[i] : null;
            }
        }
        return {
            id: full.id,
            stepId: full.stepId,
            title: full.title,
            rowCount: full.rowCount,
            ...(preview ? { preview } : {}),
            ...(full.diagnosticCount > 0 ? { diagnosticCount: full.diagnosticCount } : {}),
            ...(full.planPhaseId ? { planPhaseId: full.planPhaseId } : {}),
            ...(full.planPhaseTitle ? { planPhaseTitle: full.planPhaseTitle } : {}),
        };
    }
    /**
     * Fetch artifact data at the requested detail level.
     * For 'rows' detail, supports pagination via offset/limit to prevent token overflow.
     * Returns totalRows and hasMore so the caller knows whether to fetch more.
     */
    fetch(id, detail, offset, limit) {
        const artifact = this.artifacts.get(id);
        if (!artifact)
            return undefined;
        artifact.lastAccessedAt = Date.now();
        switch (detail) {
            case 'summary':
                return this.generateSummary(id);
            case 'rows': {
                const allRows = artifact.data?.rows || [];
                const totalRows = allRows.length;
                const effectiveOffset = offset ?? 0;
                const effectiveLimit = limit ?? ArtifactStore.DEFAULT_PAGE_SIZE;
                const pagedRows = allRows.slice(effectiveOffset, effectiveOffset + effectiveLimit);
                const hasMore = effectiveOffset + effectiveLimit < totalRows;
                return {
                    id: artifact.id,
                    columns: artifact.data?.columns || [],
                    rows: pagedRows,
                    totalRows,
                    offset: effectiveOffset,
                    limit: effectiveLimit,
                    hasMore,
                    diagnostics: artifact.diagnostics,
                    planPhaseId: artifact.planPhaseId,
                    planPhaseTitle: artifact.planPhaseTitle,
                    planPhaseGoal: artifact.planPhaseGoal,
                    sourceToolCallId: artifact.sourceToolCallId,
                    paramsHash: artifact.paramsHash,
                    identityResolution: artifact.identityResolution,
                };
            }
            case 'full': {
                // Cap rows at MAX_FULL_ROWS to prevent context window overflow.
                // Larger datasets should use detail="rows" with pagination.
                const fullRows = artifact.data?.rows || [];
                const truncatedFull = fullRows.length > ArtifactStore.MAX_FULL_ROWS;
                const cappedData = truncatedFull
                    ? { ...artifact.data, rows: fullRows.slice(0, ArtifactStore.MAX_FULL_ROWS) }
                    : artifact.data;
                return {
                    id: artifact.id,
                    skillId: artifact.skillId,
                    stepId: artifact.stepId,
                    layer: artifact.layer,
                    title: artifact.title,
                    data: cappedData,
                    diagnostics: artifact.diagnostics,
                    planPhaseId: artifact.planPhaseId,
                    planPhaseTitle: artifact.planPhaseTitle,
                    planPhaseGoal: artifact.planPhaseGoal,
                    sourceToolCallId: artifact.sourceToolCallId,
                    paramsHash: artifact.paramsHash,
                    identityResolution: artifact.identityResolution,
                    ...(truncatedFull ? { truncated: true, totalRows: fullRows.length, hint: 'Use detail="rows" with offset/limit for complete data' } : {}),
                };
            }
            default:
                return this.generateSummary(id);
        }
    }
    /** Get total artifact count. */
    get size() {
        return this.artifacts.size;
    }
    /**
     * Serialize all artifacts for snapshot persistence.
     * Returns a shallow copy of all stored artifacts.
     */
    serialize() {
        return Array.from(this.artifacts.values());
    }
    /**
     * Restore an ArtifactStore from a persisted snapshot.
     * Reconstructs the internal counter from the highest artifact ID
     * so new artifacts get IDs that don't collide with restored ones.
     */
    static fromSnapshot(artifacts) {
        const store = new ArtifactStore();
        for (const art of artifacts) {
            store.artifacts.set(art.id, art);
            const num = parseInt(art.id.replace('art-', ''), 10) || 0;
            if (num > store.counter)
                store.counter = num;
        }
        return store;
    }
    /** Clear all artifacts (e.g., on session reset). */
    clear() {
        this.artifacts.clear();
        this.counter = 0;
    }
}
exports.ArtifactStore = ArtifactStore;
/** Default page size for 'rows' fetch — balances completeness vs token budget. */
ArtifactStore.DEFAULT_PAGE_SIZE = 50;
/** Hard cap for 'full' fetch — prevents context overflow on large artifacts. */
ArtifactStore.MAX_FULL_ROWS = 500;
//# sourceMappingURL=artifactStore.js.map