/**
 * Checkpoint Runtime
 *
 * Provides the runtime functions that are injected into the sandbox
 * as `__checkpoint` namespace. These are called by the transformed code.
 */
import { OperationCheckpointManager, getOperationCheckpointManager, hasOperationCheckpointManager, setOperationCheckpointManager, clearOperationCheckpointManager, setCheckpointExecutionId, clearCheckpointExecutionId, } from './operation-checkpoint-manager';
import { CHECKPOINT_RESTORE_API_NAME } from './constants';
/**
 * Initialize the checkpoint runtime for an execution context
 */
export function initializeCheckpointRuntime(config) {
    // Set the current execution ID first
    setCheckpointExecutionId(config.executionId);
    // Create and register the manager
    const manager = new OperationCheckpointManager(config.executionId, config.cache, config.config);
    setOperationCheckpointManager(manager);
}
/**
 * Initialize the checkpoint runtime with provenance integration
 *
 * When provenance is enabled:
 * - Restricted data is automatically forced to use reference checkpoints
 * - Provenance is re-attached when restoring checkpoints
 * - Security policies continue to work after checkpoint restoration
 */
export function initializeCheckpointRuntimeWithProvenance(config) {
    // Set the current execution ID first
    setCheckpointExecutionId(config.executionId);
    // Create and register the manager
    const manager = new OperationCheckpointManager(config.executionId, config.cache, config.config);
    // Configure provenance integration
    if (config.provenanceExtractor) {
        manager.setProvenanceExtractor(config.provenanceExtractor);
    }
    if (config.provenanceAttacher) {
        manager.setProvenanceAttacher(config.provenanceAttacher);
    }
    if (config.provenanceMetaAttacher) {
        manager.setProvenanceMetaAttacher(config.provenanceMetaAttacher);
    }
    setOperationCheckpointManager(manager);
}
/**
 * Configure provenance functions on an existing checkpoint manager
 * Call this if the manager was already initialized without provenance
 */
export function configureCheckpointProvenance(provenanceExtractor, provenanceAttacher) {
    if (!hasOperationCheckpointManager()) {
        return;
    }
    const manager = getOperationCheckpointManager();
    manager.setProvenanceExtractor(provenanceExtractor);
    manager.setProvenanceAttacher(provenanceAttacher);
}
/**
 * Cleanup the checkpoint runtime for an execution
 * @param executionId - Optional execution ID to clean up (uses current if not provided)
 */
export function cleanupCheckpointRuntime(executionId) {
    clearOperationCheckpointManager(executionId);
    clearCheckpointExecutionId();
}
/**
 * Get the checkpoint runtime functions to inject into sandbox
 * These are the functions available as `__checkpoint` in transformed code
 */
export function getCheckpointRuntime() {
    return {
        buffer: checkpointBuffer,
        [CHECKPOINT_RESTORE_API_NAME]: checkpointRestore,
    };
}
/**
 * Buffer a result in memory (does NOT persist to cache)
 * Use checkpointFlush() to persist on error
 * Note: This is synchronous - no await needed
 */
function checkpointBuffer(checkpointId, result, metadata) {
    if (!hasOperationCheckpointManager()) {
        return;
    }
    const manager = getOperationCheckpointManager();
    manager.bufferResult(checkpointId, result, metadata);
}
/**
 * Restore a value from a checkpoint
 * @param fullCheckpointId - The full checkpoint ID (format: {executionId}:{shortId})
 *                           The execution ID is parsed from the ID itself, no need to pass separately
 */
async function checkpointRestore(fullCheckpointId) {
    if (!hasOperationCheckpointManager()) {
        throw new Error('Checkpoint system not initialized');
    }
    const manager = getOperationCheckpointManager();
    // Parse the full checkpoint ID to extract execution ID and short ID
    const parsed = OperationCheckpointManager.parseCheckpointId(fullCheckpointId);
    if (!parsed) {
        throw new Error(`Checkpoint not found: ${fullCheckpointId}`);
    }
    // Load from the parsed execution ID
    const checkpoint = await manager.loadFromExecution(parsed.shortId, parsed.executionId);
    if (!checkpoint) {
        throw new Error(`Checkpoint not found: ${fullCheckpointId} (execution: ${parsed.executionId})`);
    }
    return manager.restore(checkpoint);
}
/**
 * Get all checkpoint infos for error reporting
 */
function getCheckpointInfos() {
    if (!hasOperationCheckpointManager()) {
        return [];
    }
    const manager = getOperationCheckpointManager();
    return manager.getAllCheckpoints();
}
/**
 * Get restore instructions for the LLM
 */
function getRestoreInstructions() {
    if (!hasOperationCheckpointManager()) {
        return 'No checkpoints available.';
    }
    const manager = getOperationCheckpointManager();
    return manager.generateRestoreInstructions();
}
/**
 * Get the current execution's checkpoint manager
 */
export function getCurrentCheckpointManager() {
    if (!hasOperationCheckpointManager()) {
        return null;
    }
    return getOperationCheckpointManager();
}
/**
 * Get checkpoint data for error responses
 * NOTE: This also flushes buffered checkpoints to cache before returning data
 */
export async function getCheckpointDataForError() {
    if (!hasOperationCheckpointManager()) {
        return null;
    }
    const manager = getOperationCheckpointManager();
    // First, persist all buffered checkpoints so they're available for recovery
    await manager.persistAll();
    const checkpoints = manager.getAllCheckpoints();
    if (checkpoints.length === 0) {
        return null;
    }
    // Count restricted checkpoints
    const restrictedCount = checkpoints.filter(cp => cp.hasRestrictedProvenance).length;
    return {
        checkpoints,
        restoreInstructions: manager.generateRestoreInstructions(),
        stats: manager.getStats(),
        restrictedCount: restrictedCount > 0 ? restrictedCount : undefined,
    };
}
//# sourceMappingURL=checkpoint-runtime.js.map