import { sortToolPrefixSpecs, } from "./tool-registry-contract.js";
import { sha256Hex, stableJsonStringify } from "./stable-json.js";
export function buildImmutablePrefix(input) {
    const systemPrompt = normalizeStableText(input.systemPrompt);
    const toolSpecs = sortToolPrefixSpecs(input.toolSpecs ?? []);
    const fewShots = normalizeStableTextList(input.fewShots ?? []);
    const pinnedMemory = normalizeStableTextList(input.pinnedMemory ?? []);
    const systemPromptHash = sha256Hex(systemPrompt);
    const toolSpecsHash = sha256Hex(stableJsonStringify(toolSpecs));
    const fewShotsHash = sha256Hex(stableJsonStringify(fewShots));
    const pinnedMemoryHash = sha256Hex(stableJsonStringify(pinnedMemory));
    const prefixHash = sha256Hex(stableJsonStringify({
        schemaVersion: 1,
        systemPrompt,
        toolSpecs,
        fewShots,
        pinnedMemory,
    }));
    return {
        schemaVersion: 1,
        systemPrompt,
        toolSpecs,
        fewShots,
        pinnedMemory,
        hashes: {
            systemPromptHash,
            toolSpecsHash,
            fewShotsHash,
            pinnedMemoryHash,
            prefixHash,
        },
    };
}
export function createOmkSessionState(input) {
    const prefix = buildImmutablePrefix(input);
    const diagnostic = {
        level: "info",
        code: "prefix_initialized",
        message: "Cache-stable immutable prefix initialized.",
        currentHash: prefix.hashes.prefixHash,
    };
    return {
        schemaVersion: 1,
        prefix,
        log: [],
        scratch: {},
        diagnostics: [diagnostic],
    };
}
export function appendLogEntry(state, entry) {
    return {
        ...state,
        log: [...state.log, normalizeLogEntry(entry)],
    };
}
export function resetScratch(state, scratch = {}) {
    const diagnostic = {
        level: "info",
        code: "scratch_reset",
        message: "Volatile scratch reset without mutating immutable prefix.",
        currentHash: state.prefix.hashes.prefixHash,
    };
    return {
        ...state,
        scratch,
        diagnostics: [...state.diagnostics, diagnostic],
    };
}
export function diffImmutablePrefix(previous, next) {
    const diagnostics = [];
    if (previous.hashes.prefixHash !== next.hashes.prefixHash) {
        diagnostics.push({
            level: "warning",
            code: "prefix_changed",
            message: "Immutable prefix hash changed; provider prefix cache should be invalidated.",
            previousHash: previous.hashes.prefixHash,
            currentHash: next.hashes.prefixHash,
        });
    }
    pushHashDiff(diagnostics, "system_prompt_changed", "System prompt changed.", previous.hashes.systemPromptHash, next.hashes.systemPromptHash);
    pushHashDiff(diagnostics, "tool_specs_changed", "Tool specs changed.", previous.hashes.toolSpecsHash, next.hashes.toolSpecsHash);
    pushHashDiff(diagnostics, "few_shots_changed", "Few-shot prefix changed.", previous.hashes.fewShotsHash, next.hashes.fewShotsHash);
    pushHashDiff(diagnostics, "pinned_memory_changed", "Pinned memory prefix changed.", previous.hashes.pinnedMemoryHash, next.hashes.pinnedMemoryHash);
    return diagnostics;
}
function normalizeStableText(value) {
    return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
}
function normalizeStableTextList(values) {
    return values.map((value) => normalizeStableText(value));
}
function normalizeLogEntry(entry) {
    return {
        ...entry,
        content: normalizeStableText(entry.content),
    };
}
function pushHashDiff(diagnostics, code, message, previousHash, currentHash) {
    if (previousHash === currentHash)
        return;
    diagnostics.push({
        level: "warning",
        code,
        message,
        previousHash,
        currentHash,
    });
}
