import { EditorConnection } from './EditorConnection.js'; import { EditorToolExecutor } from './EditorToolExecutor.js'; import type { HealthMonitor } from './health-monitor.js'; /** SDK logging level union(对齐 @modelcontextprotocol/server sendLoggingMessage 的 level)。 */ type EditorLogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency'; /** manager 需要的 dispatcher 操作窄接口(避免耦合 ToolDispatcher 全貌)。ToolDispatcher 结构兼容。 */ export interface EditorDispatcher { getHealthMonitor(): HealthMonitor; setEditorExecutor(executor: EditorToolExecutor | null): void; markEditorFallback(): void; degradeToHeadless(): void; setConnectionMode(mode: 'headless' | 'editor'): void; } /** manager 与 GodotServer 的交互边界。 */ export interface EditorConnectionHost { dispatcher: EditorDispatcher; /** 走 SDK 正规 logging 路径(notifications/message),用于重连后通知客户端。 */ sendLoggingMessage(opts: { level: EditorLogLevel; logger: string; data: string; }): unknown; /** 连接成功建立/重建 → GodotServer 同步 connectionMode='editor' + setConnectionMode('editor')。 */ onConnected(): void; /** 连接降级(重连耗尽/心跳卡死/初始化失败)→ GodotServer 同步 connectionMode='headless'。 */ onDegrade(): void; } export interface EditorConnectionOptions { port: number; projectPath: string | null; noFallback: boolean; } export declare class EditorConnectionManager { private conn; private executor; private _editorVerifying; /** B-T5: pingFn catch 保留 err.code,供 onStateChange 分流。 */ private _lastPingErrCode; private readonly port; private readonly projectPath; private readonly noFallback; private readonly host; /** A-2: 并发 rebuild in-flight 去重锁(对齐 game-bridge _connectionLock)。 */ private _rebuildPromise; constructor(host: EditorConnectionHost, opts: EditorConnectionOptions); /** 当前 editor 连接(供 GodotServer 的 provider 读状态/发 RPC)。 */ getConn(): EditorConnection | null; isConnected(): boolean; /** editor 连接对应的项目路径(供 GodotServer.close 的 overrides 卸载用)。 */ getProjectPath(): string | null; /** * 初始化 editor 连接(run() editor 分支调用)。返回 {connected, detail}; * 进程级 exit(noFallback)归 GodotServer。降级副作用(markEditorFallback + * setConnectionMode headless)在此处理,exit 前的 log 归 GodotServer。 */ init(): Promise<{ connected: boolean; detail: string; }>; /** run() 初始化期的降级(markEditorFallback + setConnectionMode headless;非 degradeToHeadless)。 */ private initDegrade; /** * 方案B: editor 降级后(conn=null),manage_tools reconnect 触发重建连接。 * 重新读 secret(editor 可能重启换密钥)+ establish。失败保持 headless(不 exit)。 * * A-2 (2026-08-14 findings :936): 并发 rebuild in-flight 去重(对齐 game-bridge 的 * _connectionLock 模式)。并发两次调用时败者 establish 的清理会误伤胜者: * 败者 catch `this.conn=null` 误清纯者刚建的新 conn → 胜者 verifyProject 假 mismatch * "(no connection)" → mismatch 分支 `this.conn.disconnect()` 在 null 上 TypeError 被吞 * → 胜者 ws 保持 OPEN 无人断(占 MAX_PEERS 槽 + 僵尸重连)。 * 非有意 async: 返回共享 Promise 保持引用相等(败者拿到胜者同一 Promise),async 包装会新建。 */ rebuild(): Promise<{ connected: boolean; detail: string; }>; private _doRebuild; /** close() 时清理:断连 + 清 dispatcher executor 引用(原 GodotServer.close 的 editor 段)。 */ close(): void; /** * 建立 editor 连接:new EditorConnection + connect + executor 接线 + 挂降级 handler。 * 成功 → host.onConnected();失败 → 清理 conn,返回 {connected:false}。 * 不含 exit / init 降级语义;rebuild 复用此方法(失败不 exit,保持 headless)。 * I-04: 降级用专用 reconnectExhausted handler(非 disconnect handler——后者每次 ws.close 触发会过早降级)。 */ private establish; /** 编辑器不可用时的统一降级动作(WS 重连耗尽 / 心跳卡死 / 项目不匹配 共用)。 */ private handleStall; /** * CMP-1 (2026-08-08): 校验 editor 连接对应的项目根与配置一致。 * 发 editor_get_project_path RPC 读 editor 的 res:// 绝对路径,与 this.projectPath * 归一化比对。mismatch → ok:false(调用方 disconnect + 降级)。 * projectPath=null(无 project.godot 上下文)→ 跳过校验(ok:true,不阻断)。 */ private verifyProject; } export {};