/** * Process state management for Godot MCP Enhanced. * * C-04: Async state-mutating operations are serialized through `enqueueAsync`. * Reads are still direct (no queueing) since they're atomic in the Node.js * single-threaded model. This prevents race conditions when MCP clients * introduce parallel tool calls. */ import type { ChildProcess } from 'child_process'; /** Kill process tree without blocking the event loop. Uses async spawn on Windows. */ export declare function forceKillTree(proc: ChildProcess): void; /** * 按 PID 杀进程树(与 forceKillTree 共享双平台语义,IMPORTANT-1)。 * Windows taskkill /F /T 清整树;POSIX pkill -P 杀子进程 + SIGTERM 主进程 * (Godot 可能 spawn 导入/资源子进程,对等 forceKillTree POSIX 分支)。 * 导出仅为测试可测性(@internal)。 */ export declare function killPidTree(pid: number): void; /** Async kill: waits for 'close' event, with 5 s fallback. */ export declare function killProcess(proc: ChildProcess): Promise; /** 记录本会话 spawn 的需要 orphan 兜底的 Godot 进程 PID(仅 run_project)。 */ export declare function registerSpawnedGodotPid(pid: number): void; /** 进程正常退出时移除(主动清理,避免集合累积死 PID)。 */ export declare function unregisterSpawnedGodotPid(pid: number): void; /** 测试用:读取当前集合。 */ export declare function getSpawnedGodotPids(): number[]; /** Serialize an async state-mutating operation. Ensures only one async mutation * is in-flight at a time. Supports returning a value from the serialized function. */ declare function enqueueAsync(fn: () => (Promise | T)): Promise; export declare function isProcessBusy(): boolean; /** * Acquire the long-running process slot through the async serialization queue. * Serialized via enqueueAsync to prevent race conditions when MCP clients * issue parallel tool calls (e.g. run_project + execute_gdscript simultaneously). * Returns true if acquired, false if slot is busy. */ export declare function acquireProcessSlot(owner?: string): Promise; export declare function setProcessBusy(busy: boolean): void; /** Get info about what is currently holding the long-running lock. */ export declare function getBusyInfo(): { owner: string; startTime: number; projectDir: string; }; /** Build a user-friendly error message when the long-running slot is occupied. */ export declare function buildBusyErrorMessage(): string; export declare function acquireShortRunningSlot(): boolean; export declare function releaseShortRunningSlot(): void; export declare function getShortRunningCount(): number; export declare function getRunningProcess(): ChildProcess | null; export declare function setRunningProcess(proc: ChildProcess | null, skipBusyCheck?: boolean): void; export declare function getOutputBuffer(): string[]; export declare function appendOutput(lines: string[]): void; export declare function clearOutputBuffer(): void; export declare function setOutputBuffer(buf: string[]): void; export declare function getProcessStartTime(): number; export declare function setProcessStartTime(t: number): void; export declare function getProjectDir(): string; export declare function setProjectDir(d: string): void; /** Reset all module-level state — for test isolation. */ export declare function resetState(): void; export { enqueueAsync }; export declare function killOrphanGodotProcesses(projectDir?: string, options?: { fullSystemScan?: boolean; }): Promise;