"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.rebuildSessionSearchIndex = rebuildSessionSearchIndex;
exports.rebuildSessionSearchIndexWithMetadata = rebuildSessionSearchIndexWithMetadata;
exports.searchSessions = searchSessions;
exports.getSessionSearchIndexStatus = getSessionSearchIndexStatus;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const sessionStorage_1 = require("./sessionStorage");
async function rebuildSessionSearchIndex(projectDir) {
    const rebuilt = await rebuildSessionSearchIndexWithMetadata(projectDir);
    return rebuilt.entries;
}
async function rebuildSessionSearchIndexWithMetadata(projectDir, now = new Date()) {
    const sessions = await sessionStorage_1.SessionStorage.listSessions(projectDir);
    const entries = [];
    for (const session of sessions) {
        const storage = new sessionStorage_1.SessionStorage(projectDir, session.model, session.sessionId);
        const events = await storage.readAll();
        entries.push(...eventsToSearchEntries(session, events));
    }
    const metadata = {
        rebuiltAt: now.toISOString(),
        sessionCount: sessions.length,
        entryCount: entries.length,
        sourceUpdatedAt: sourceUpdatedAt(sessions),
    };
    const index = { metadata, entries };
    await writeIndex(projectDir, index);
    return index;
}
async function searchSessions(projectDir, query, limit = 10) {
    const { entries } = await readOrBuildIndex(projectDir);
    const queryTokens = tokenize(query);
    if (queryTokens.length === 0)
        return [];
    return entries
        .map((entry) => ({ entry, score: scoreEntry(queryTokens, entry.tokens) }))
        .filter((result) => result.score > 0)
        .sort((a, b) => b.score - a.score || b.entry.timestamp.localeCompare(a.entry.timestamp))
        .slice(0, limit);
}
async function getSessionSearchIndexStatus(projectDir) {
    const filePath = indexPath(projectDir);
    const sessions = await sessionStorage_1.SessionStorage.listSessions(projectDir);
    const sourceUpdated = sourceUpdatedAt(sessions);
    try {
        const index = await readIndex(projectDir);
        return {
            ...index.metadata,
            exists: true,
            fresh: index.metadata.sourceUpdatedAt >= sourceUpdated,
            indexPath: filePath,
        };
    }
    catch {
        return {
            exists: false,
            fresh: false,
            indexPath: filePath,
            rebuiltAt: '',
            sessionCount: sessions.length,
            entryCount: 0,
            sourceUpdatedAt: sourceUpdated,
        };
    }
}
function eventsToSearchEntries(session, events) {
    return events.flatMap((event) => {
        const text = eventToText(event);
        if (!text)
            return [];
        return [{
                id: event.id,
                sessionId: session.sessionId,
                timestamp: event.timestamp,
                role: eventRole(event),
                text,
                tokens: tokenize(text),
            }];
    });
}
function eventToText(event) {
    switch (event.data.kind) {
        case 'message': return event.data.message.content ?? '';
        case 'tool_result': return event.data.result.output;
        case 'compact_boundary': return event.data.summary;
        case 'continuity_checkpoint': return [event.data.checkpoint.currentGoal, event.data.checkpoint.summary, event.data.checkpoint.nextAction].join('\n');
        case 'system': return event.data.content;
        default: return '';
    }
}
function eventRole(event) {
    if (event.data.kind === 'message')
        return event.data.message.role;
    return event.type;
}
function tokenize(text) {
    return Array.from(new Set(text.toLowerCase().match(/[a-z0-9_./-]{2,}/g) ?? []));
}
function scoreEntry(queryTokens, entryTokens) {
    const entrySet = new Set(entryTokens);
    const matches = queryTokens.filter((token) => entrySet.has(token)).length;
    return matches / Math.sqrt(Math.max(1, entryTokens.length));
}
async function readOrBuildIndex(projectDir) {
    try {
        return await readIndex(projectDir);
    }
    catch {
        return rebuildSessionSearchIndexWithMetadata(projectDir);
    }
}
async function readIndex(projectDir) {
    const parsed = JSON.parse(await fs.readFile(indexPath(projectDir), 'utf-8'));
    if (Array.isArray(parsed)) {
        return { metadata: { rebuiltAt: '', sessionCount: 0, entryCount: parsed.length, sourceUpdatedAt: '' }, entries: parsed };
    }
    return parsed;
}
async function writeIndex(projectDir, index) {
    const filePath = indexPath(projectDir);
    await fs.mkdir(path.dirname(filePath), { recursive: true });
    await fs.writeFile(filePath, JSON.stringify(index, null, 2), 'utf-8');
}
function sourceUpdatedAt(sessions) {
    return sessions.reduce((latest, session) => {
        const timestamp = session.updatedAt ?? session.createdAt;
        return timestamp > latest ? timestamp : latest;
    }, '');
}
function indexPath(projectDir) {
    return path.join(projectDir, '.harness', 'memory', 'session-search-index.json');
}
//# sourceMappingURL=sessionSearchIndex.js.map