/** * InstanceManager — multi-instance discovery and registry management (Phase 2b) * * Discovers running Godot instances via: * 1. Machine-level registry: ~/.godot-mcp/instances/ * 2. Project-level registry: {project}/.godot/mcp-instances/ * * Each instance writes its own JSON file (no concurrent write contention). * Stale detection: lastSeen > staleTimeout → stale status. * * 2026-08-10 (行225): 补全写入能力——registerSelf/unregisterSelf/updateLastSeen/allocatePort, * 让 TS server 也能把自己注册到 registry(此前仅 GD 端 editor/headless 写入,TS 端只读)。 * 配合 instance-http-server.ts 实现 MULTI_INSTANCE 接收端闭环。 */ export interface InstanceInfo { id: string; projectPath: string; projectName: string; port: number; pid: number; lastSeen: string; godotVersion: string; capabilities: string[]; status?: 'ready' | 'compiling' | 'unresponsive'; registeredAt?: number; } export type InstanceStatus = 'alive' | 'stale' | 'unreachable'; export interface InstanceManagerOptions { /** Machine-level registry directory. Defaults to ~/.godot-mcp/instances/ */ registryDir?: string; /** Project-level registry directory. Optional. */ projectRegistryDir?: string; /** Stale timeout in ms. Defaults to 70000 (70s). */ staleTimeoutMs?: number; /** CMP-7: pid liveness probe override (测试注入用)。默认用 process.kill(pid, 0)。 */ isPidAlive?: (pid: number) => boolean; } export declare const DEFAULT_PORT_START = 9081; export declare const DEFAULT_PORT_END = 9090; export declare function getDefaultRegistryDir(): string; export declare class InstanceManager { private readonly registryDir; private readonly projectRegistryDir?; private readonly staleTimeoutMs; private readonly _portRange; private readonly _isPidAlive; private instances; constructor(opts?: InstanceManagerOptions); /** Get configured port range. */ get portRange(): [number, number]; /** Load instances from both registry levels. Machine-level first, then project-level overrides. */ loadFromRegistry(): Promise; /** Get instance by id. */ getInstance(id: string): InstanceInfo | undefined; /** Get all loaded instances. */ getAllInstances(): InstanceInfo[]; /** Determine status of an instance based on lastSeen timestamp + pid liveness. */ getStatus(instance: InstanceInfo): InstanceStatus; /** * 注册(或更新)一个实例到 registry。原子写 .tmp → rename。 * 机器级 registry 优先(TS server 跨项目,projectRegistryDir 可选时写 machine-level)。 */ registerSelf(info: InstanceInfo): Promise; /** 删除一个实例的 registry JSON(退出清理用)。best-effort,不存在不报错。 */ unregisterSelf(id: string): Promise; /** 心跳更新:只改 lastSeen 字段,原子重写。读失败/解析失败则 no-op(不阻断心跳定时器)。 */ updateLastSeen(id: string): Promise; /** * 在 portRange 内找第一个未被占用的端口。 * @param existingPorts 已占用端口集合(从 loadFromRegistry 结果提取) * @returns 第一个空闲端口 * @throws 全部占用时 throw(不静默 fallback,让调用方决策) */ allocatePort(existingPorts: number[]): number; /** Read instance JSON files from a directory. Corrupt/invalid files are skipped. */ private readRegistryDir; } /** Convenience: get machine-level registry directory path. */ export declare function getMachineRegistryDir(): string; /** Convenience: discover all instances. Creates a temporary manager and runs discovery. */ export declare function discoverInstances(opts?: InstanceManagerOptions): Promise; /** * 构造本 TS server 实例的 InstanceInfo(2026-08-10 行225:接收端注册自己用)。 * id 格式 `ts--`(对齐 GD 端 editor- / _ 命名惯例, * ts- 前缀区分来源)。projectPath/projectName 来自调用方(resolveProjectPath 结果)。 */ export declare function buildInstanceInfo(opts: { port: number; projectPath: string; projectName: string; godotVersion?: string; }): InstanceInfo;