import { t as openNodeSqliteDatabase } from "./node-sqlite-GN5_mcoB.js";
import { l as createPrivateSqliteTempDirectorySync } from "./sqlite-readonly-location-BhNwU7vJ.js";
import { Kt as executeSqliteQuerySync, Yt as iterateSqliteQuerySync, qt as executeSqliteQueryTakeFirstSync } from "./openclaw-state-db-Cb4e1jdd.js";
import { r as resolveOpenClawAgentSqlitePath } from "./openclaw-agent-db.paths-BAQb87PB.js";
import { y as runOpenClawAgentWriteTransaction } from "./openclaw-agent-db-DwEkomYQ.js";
import { b as writeSessionEntry } from "./session-accessor.sqlite-entry-store-B5zyYu48.js";
import { c as resolveSqliteScope, i as getSessionKysely, m as toDatabaseOptions, p as runExclusiveSqliteSessionWrite, r as formatSqliteSessionReferenceForScope } from "./session-accessor.sqlite-scope-I8SegJ8n.js";
import { C as publishSessionEntryCacheInvalidation, i as ensureTranscriptSessionRoot, l as touchTranscriptMutationInTransaction, r as ensureTranscriptGenerationInTransaction, t as advanceTranscriptMutationAtInTransaction } from "./session-accessor.sqlite-transcript-state-CTvnr6Is.js";
import { c as reconcileSessionTranscriptIndexInTransaction } from "./session-transcript-index-DNNZzEu4.js";
import { n as appendTranscriptEventsInTransaction } from "./session-accessor.sqlite-transcript-store-BAnJbMnW.js";
import { i as readExactSessionEntryRowForCanonicalRepair } from "./session-accessor.sqlite-canonical-repair-CDXJuUY4.js";
import { n as replaceSessionOwnerInTransaction } from "./session-accessor.sqlite-owner-DnpCjRb7.js";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { createHash } from "node:crypto";
//#region src/config/sessions/session-accessor.sqlite-import-stage.ts
function withSqliteSessionImportStage(run) {
	const directory = createPrivateSqliteTempDirectorySync(os.tmpdir(), "openclaw-session-import-");
	let database;
	try {
		const filename = path.join(directory, "transcripts.sqlite");
		fs.closeSync(fs.openSync(filename, "wx", 384));
		database = openNodeSqliteDatabase(filename);
		database.exec(`
      PRAGMA cache_size = -2048;
      PRAGMA temp_store = FILE;
      CREATE TABLE rows (
        source INTEGER NOT NULL, seq INTEGER NOT NULL, event_json TEXT NOT NULL,
        created_at INTEGER, PRIMARY KEY (source, seq)
      ) WITHOUT ROWID;
      CREATE TABLE seen (hash BLOB NOT NULL, event_json TEXT NOT NULL);
      CREATE INDEX seen_hash ON seen(hash);
      BEGIN;
    `);
		return run(new SqliteSessionImportStage(database));
	} finally {
		try {
			database?.close();
		} finally {
			fs.rmSync(directory, {
				recursive: true,
				force: true
			});
		}
	}
}
var SqliteSessionImportStage = class {
	constructor(database) {
		this.database = database;
		this.insert = database.prepare("INSERT INTO rows VALUES (?, ?, ?, ?)");
		this.read = database.prepare("SELECT seq, event_json AS eventJson, created_at AS createdAt FROM rows WHERE source = ? ORDER BY seq");
		this.findSeen = database.prepare("SELECT 1 FROM seen WHERE hash = ? AND event_json = ? LIMIT 1");
		this.insertSeen = database.prepare("INSERT INTO seen VALUES (?, ?)");
	}
	append(source, seq, eventJson, createdAt) {
		this.insert.run(source, seq, eventJson, createdAt);
	}
	rows(source) {
		return this.read.iterate(source);
	}
	resetSeen() {
		this.database.exec("DELETE FROM seen");
	}
	hasSeen(eventJson) {
		return this.findSeen.get(createHash("sha256").update(eventJson).digest(), eventJson) !== void 0;
	}
	addSeen(eventJson) {
		this.insertSeen.run(createHash("sha256").update(eventJson).digest(), eventJson);
	}
};
//#endregion
//#region src/config/sessions/session-accessor.sqlite-import.ts
function resolveSqliteSessionImport(params) {
	if (params.readExactTranscriptRows && params.readTranscriptEvents) throw new Error("SQLite session import accepts only one transcript row source");
	const resolvedScope = resolveSqliteScope(params);
	return {
		params,
		resolved: params.preserveExactStoredKey ? {
			...resolvedScope,
			sessionKey: params.sessionKey
		} : resolvedScope
	};
}
function importSqliteSessionRowsInTransaction(database, prepared, stage, source) {
	const { params, resolved } = prepared;
	let transcriptEvents = 0;
	const currentEntry = readExactSessionEntryRowForCanonicalRepair(database, resolved.sessionKey, { allowMalformedRowRepair: params.allowMalformedRowRepair === true })?.entry;
	if (params.skipIfExists === true && currentEntry) return {
		sessionId: params.entry.sessionId,
		sessionKey: resolved.sessionKey,
		skippedExisting: true,
		transcriptEvents
	};
	const preservedHarnessId = params.entry.agentHarnessId === void 0 && currentEntry?.sessionId === params.entry.sessionId && currentEntry.lifecycleRevision === params.entry.lifecycleRevision ? currentEntry.agentHarnessId?.trim() : void 0;
	const importedEntry = {
		...params.entry,
		...preservedHarnessId ? { agentHarnessId: preservedHarnessId } : {},
		sessionFile: formatSqliteSessionReferenceForScope({
			...resolved,
			sessionId: params.entry.sessionId
		})
	};
	writeSessionEntry(database, resolved.sessionKey, importedEntry, {
		allowStoredAliases: true,
		previousEntry: currentEntry ?? null
	});
	if (params.readExactTranscriptRows) {
		replaceSessionOwnerInTransaction(database, resolved.sessionKey, params.entry.owner);
		const transcriptScope = {
			...resolved,
			sessionId: params.entry.sessionId
		};
		const db = getSessionKysely(database.db);
		if (!executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("transcript_events").select("seq").where("session_id", "=", params.entry.sessionId).limit(1))) {
			for (const row of stage.rows(source)) {
				if (row.seq === 0) {
					ensureTranscriptSessionRoot(database, transcriptScope, row.createdAt, { allowStoredAlias: true });
					ensureTranscriptGenerationInTransaction(database, params.entry.sessionId);
				}
				executeSqliteQuerySync(database.db, db.insertInto("transcript_events").values({
					session_id: params.entry.sessionId,
					seq: row.seq,
					event_json: row.eventJson,
					created_at: row.createdAt
				}));
				transcriptEvents += 1;
			}
			reconcileSessionTranscriptIndexInTransaction(database.db, params.entry.sessionId);
			publishSessionEntryCacheInvalidation(database);
		}
	} else if (params.readTranscriptEvents) {
		const transcriptScope = {
			...resolved,
			sessionId: params.entry.sessionId
		};
		stage.resetSeen();
		for (const row of iterateSqliteQuerySync(database.db, getSessionKysely(database.db).selectFrom("transcript_events").select("event_json").where("session_id", "=", params.entry.sessionId))) stage.addSeen(row.event_json);
		transcriptEvents = appendTranscriptEventsInTransaction(database, transcriptScope, (function* () {
			for (const row of stage.rows(source)) {
				if (stage.hasSeen(row.eventJson)) continue;
				if (yield JSON.parse(row.eventJson)) stage.addSeen(row.eventJson);
			}
		})(), {
			allowStoredAlias: true,
			scheduleProjectionReconcile: false,
			touchMutation: false
		});
		reconcileSessionTranscriptIndexInTransaction(database.db, params.entry.sessionId);
		publishSessionEntryCacheInvalidation(database);
	}
	if (params.transcriptMtimeMs !== void 0) advanceTranscriptMutationAtInTransaction(database, params.entry.sessionId, params.transcriptMtimeMs);
	else if (transcriptEvents > 0) touchTranscriptMutationInTransaction(database, params.entry.sessionId);
	return {
		sessionId: params.entry.sessionId,
		sessionKey: resolved.sessionKey,
		transcriptEvents
	};
}
/** Imports legacy session rows that share one SQLite store in one durable transaction. */
async function importSqliteSessionRowsBatch(params) {
	if (params.length === 0) return [];
	const prepared = params.map(resolveSqliteSessionImport);
	const resolved = prepared[0].resolved;
	const databasePath = resolveOpenClawAgentSqlitePath(toDatabaseOptions(resolved));
	if (prepared.some((row) => resolveOpenClawAgentSqlitePath(toDatabaseOptions(row.resolved)) !== databasePath)) throw new Error("SQLite session import batch spans multiple stores");
	return await runExclusiveSqliteSessionWrite(resolved, async () => withSqliteSessionImportStage((stage) => {
		const validators = [];
		for (const [source, { params: importParams }] of prepared.entries()) {
			let seq = 0;
			importParams.readExactTranscriptRows?.((row) => stage.append(source, seq++, row.eventJson, row.createdAt));
			const validate = importParams.readTranscriptEvents?.((event) => stage.append(source, seq++, JSON.stringify(event), null));
			if (validate) validators.push(validate);
		}
		for (const validate of validators) validate();
		return runOpenClawAgentWriteTransaction((database) => prepared.map((row, source) => importSqliteSessionRowsInTransaction(database, row, stage, source)), toDatabaseOptions(resolved));
	}));
}
/** Imports one legacy session entry and its transcript rows for doctor migration. */
async function importSqliteSessionRows(params) {
	return (await importSqliteSessionRowsBatch([params]))[0];
}
//#endregion
export { importSqliteSessionRowsBatch as n, importSqliteSessionRows as t };
