/**
 * MCP Server State Management — Bridge Layer
 *
 * Delegates ALL per-session state to SessionManager. This file preserves
 * the same exported function names and signatures that 30+ tool files depend on.
 * Internally, each function uses getActiveSessionId() to determine the current
 * session and delegates to the SessionManager singleton.
 *
 * GLOBAL STATE: Only `config` and `mcpServer` remain global.
 * PER-SESSION STATE: currentDatabase, currentDatabaseName, operations,
 *   generation, vectorService cache, requestScopedNotify — all via SessionManager.
 *
 * CRITICAL: NEVER use console.log() — stdout is JSON-RPC (IMM-02).
 *
 * @module server/state
 */
import { DatabaseService } from '../services/storage/database/index.js';
import type { ServerState, ServerConfig } from './types.js';
import type { DatabaseServices } from './session-state.js';
export type { DatabaseServices };
/**
 * Global server state.
 *
 * `config` and `mcpServer` are truly global (shared across all sessions).
 * `currentDatabase` and `currentDatabaseName` are per-session — the getters
 * delegate to SessionManager using the active session from AsyncLocalStorage.
 *
 * Tool files that read `state.currentDatabaseName` or `state.config` continue
 * to work without changes.
 */
export declare const state: ServerState;
/**
 * Set the request-scoped notification sender for the current session.
 *
 * When set, keepalives are sent via the SDK's extra.sendNotification
 * (which includes relatedRequestId), routing them to the POST response
 * SSE stream that the client IS reading.
 *
 * Set by tool handlers that do long-running work (e.g., ocr_process_pending).
 * Cleared when the handler completes.
 */
export declare function setRequestScopedNotify(fn: ((notification: {
    method: string;
    params: Record<string, unknown>;
}) => Promise<void>) | null): void;
/**
 * Send a keepalive logging notification to prevent MCP client timeout.
 *
 * Uses request-scoped sendNotification (with relatedRequestId) when available,
 * so keepalives go on the same POST SSE stream the client is reading.
 * Falls back to sendLoggingMessage for the standalone stream.
 *
 * Safe to call even if mcpServer is not set — silently no-ops.
 * Fully defensive: catches both sync throws and async rejections.
 */
export declare function sendKeepalive(message: string): void;
/**
 * Require database to be selected - FAIL FAST if not
 *
 * @returns Database service, vector service, and generation counter
 * @throws MCPError with DATABASE_NOT_SELECTED if no database is selected
 */
export declare function requireDatabase(): DatabaseServices;
/**
 * Validate that the database generation matches the expected value.
 *
 * The generation counter increments on every database switch/clear. A mismatch
 * means the database was switched between the time a caller obtained the
 * generation and the time it validates -- indicating a race condition where
 * the caller's database reference is stale.
 *
 * @param expectedGeneration - The generation value obtained from requireDatabase()
 * @throws Error if the current generation does not match
 */
export declare function validateGeneration(expectedGeneration: number): void;
/**
 * Begin tracking an in-flight database operation.
 *
 * Increments the active operation counter and returns the current generation.
 * While any operations are active, selectDatabase() and clearDatabase() will
 * throw to prevent database switches during async work.
 *
 * @returns Current database generation for later validation
 * @throws MCPError if no database is selected
 */
export declare function beginDatabaseOperation(): number;
/**
 * End tracking an in-flight database operation.
 *
 * Decrements the active operation counter. Counter never goes below 0.
 */
export declare function endDatabaseOperation(): void;
/**
 * Refresh the operation timestamp to prevent stale-operation expiration.
 *
 * Long-running operations (e.g., CPU OCR processing 30+ minutes) must call
 * this periodically to signal they are still alive. Without this, the
 * expireStaleOperations() check would consider the operation abandoned after
 * OPERATION_TIMEOUT_MS and reset the guard -- allowing a concurrent
 * selectDatabase() call to close the connection mid-operation.
 *
 * Typically called from keepalive timers that already run every 15 seconds.
 * Safe to call when no operations are active (no-ops silently).
 */
export declare function touchDatabaseOperation(): void;
/**
 * Get the number of active database operations (for diagnostics/testing).
 */
export declare function getActiveOperationCount(): number;
/**
 * Execute an async function within a tracked database operation scope.
 *
 * Calls beginDatabaseOperation() before the function and endDatabaseOperation()
 * in a finally block, guaranteeing the counter is decremented even on error.
 * Also validates the generation after the function completes to detect any
 * mid-operation database switch.
 *
 * Automatically refreshes the operation timestamp every 60 seconds to prevent
 * expireStaleOperations() from declaring long-running operations (e.g., 30+
 * minute CPU OCR) as stale. Without this heartbeat, a concurrent
 * selectDatabase() call could close the connection mid-operation.
 *
 * @param fn - Async function receiving DatabaseServices
 * @returns The result of fn
 * @throws MCPError if no database is selected
 * @throws Error if the database was switched during the operation
 */
export declare function withDatabaseOperation<T>(fn: (services: DatabaseServices) => Promise<T>): Promise<T>;
/**
 * Check if a database is currently selected
 */
export declare function hasDatabase(): boolean;
/**
 * Get current database name or null
 */
export declare function getCurrentDatabaseName(): string | null;
/**
 * Select a database by name - opens connection and sets as current
 *
 * FAIL FAST: Throws immediately if database doesn't exist or if operations
 * are in-flight (H-2 guard). Uses atomic swap (M-9 fix): opens new DB first,
 * then swaps state, then closes old DB -- no null window.
 *
 * @param name - Database name to select
 * @param storagePath - Optional storage path override
 * @param force - Force-clear stuck in-flight operations before switching.
 *   Use when a previous operation crashed and left the counter stuck.
 * @throws MCPError with DATABASE_NOT_FOUND if database doesn't exist
 * @throws Error if database operations are in-flight and force is false
 */
export declare function selectDatabase(name: string, storagePath?: string, force?: boolean): void;
/**
 * Create a new database and optionally select it
 *
 * FAIL FAST: Throws immediately if database already exists
 *
 * @param name - Database name to create
 * @param description - Optional description
 * @param storagePath - Optional storage path override
 * @param autoSelect - Whether to select the database after creation (default: true)
 * @returns The created database service
 * @throws MCPError with DATABASE_ALREADY_EXISTS if database exists
 */
export declare function createDatabase(name: string, description?: string, storagePath?: string, autoSelect?: boolean): DatabaseService;
/**
 * Delete a database
 *
 * FAIL FAST: Throws if database doesn't exist
 *
 * @param name - Database name to delete
 * @param storagePath - Optional storage path override
 * @throws MCPError with DATABASE_NOT_FOUND if database doesn't exist
 */
export declare function deleteDatabase(name: string, storagePath?: string): void;
/**
 * Clear current database selection - closes connection.
 *
 * FAIL FAST: Throws if async operations are in-flight (H-2 guard).
 * The forceClose parameter bypasses the guard for internal use only
 * (resetState in tests, process exit cleanup).
 *
 * @param forceClose - Skip operation guard (internal use only)
 * @throws Error if database operations are in-flight and forceClose is false
 */
export declare function clearDatabase(forceClose?: boolean): void;
/**
 * Get current server configuration
 */
export declare function getConfig(): ServerConfig;
/**
 * Update server configuration (deep merges nested objects like imageOptimization)
 */
export declare function updateConfig(updates: Partial<ServerConfig>): void;
/**
 * Reset configuration to defaults
 */
export declare function resetConfig(): void;
/**
 * Get default storage path
 */
export declare function getDefaultStoragePath(): string;
/**
 * Reset all server state - ONLY USE IN TESTS
 *
 * Kills all daemon processes to prevent GPU memory accumulation.
 * Shuts down the SessionManager (closes all connections, destroys all sessions).
 * Resets config to defaults.
 */
export declare function resetState(): void;
//# sourceMappingURL=state.d.ts.map