/** * Wire format shared between the Node-side `GodotRunner.sendCommand` and the * GDScript-side `McpBridge` autoload. * * KEEP IN SYNC: src/scripts/mcp_bridge.gd implements the same framing on the * Godot side. Any change here MUST be mirrored there (and vice versa). * * Frame: 4-byte big-endian length prefix + UTF-8 JSON payload. * Max frame size is 16 MiB; oversize frames are rejected on receive. * * Request frame contract (additive): every request JSON payload is * `{ command: string, token?: string, ...params }`. `sendCommand` in * `godot-runner.ts` attaches the per-session auth token; the bridge rejects * any frame whose `token` doesn't match its configured session token (see * `_dispatch_command` in `mcp_bridge.gd`). This is a best-effort accident * guard against unauthenticated local processes finding the bridge port, not * a hard security boundary — see `docs/security.md`. */ export declare const DEFAULT_BRIDGE_PORT = 9900; export declare const MAX_FRAME_BYTES: number; export declare const FRAME_HEADER_BYTES = 4; /** * Ceiling on how long a spawned Godot process is given to bring the bridge * up before `run_project` reports a timeout. `pollBridge` returns on the * first accepted pong, so raising this costs nothing in the healthy case - * it only bounds how long a genuinely broken launch takes to be reported. * Safe to raise furthest of the readiness budgets because `shouldAbort` in * `waitForBridge` aborts the moment the child process exits, so a crashed * launch is still reported early regardless of this ceiling. * `tests/helpers/run-project-or-skip.ts` already overrides this at 20000 for * every integration test, which is the evidence the previous 8000 was too * tight for the fixture project on CI hardware. */ export declare const BRIDGE_WAIT_SPAWNED_TIMEOUT_MS = 30000; /** * Marker the bridge prints on stderr after each simulated input action settles, * as ` `. stderr is a single ordered fd, so every * runtime-error line an input handler wrote during an action lands before that * action's marker and can be attributed to it. * * KEEP IN SYNC: `ACTION_BOUNDARY_SENTINEL` in src/scripts/mcp_bridge.gd is the * twin of this constant. Any change here MUST be mirrored there (and vice * versa) or error attribution silently degrades to unattributed lines. */ export declare const ACTION_BOUNDARY_SENTINEL = "MCP_ACTION_BOUNDARY"; /** * One recorded sentinel. `seq` is the number of retained stderr lines that * preceded it, which is why a mark stays meaningful after the stderr ring * buffer drops older lines. */ export interface ActionBoundaryMark { index: number; seq: number; } /** * Recognize an action-boundary line and return its action index, or null for * any other stderr line. */ export declare function parseActionBoundary(line: string): number | null; export interface BucketBySentinelInput { /** Contiguous stderr lines, oldest first. */ lines: string[]; /** Sequence number of `lines[0]`. */ startSeq: number; /** Marks recorded during the same window, in arrival order. */ boundaries: ActionBoundaryMark[]; /** Number of actions that actually ran, which is the bucket count. */ executedCount: number; } export interface BucketBySentinelResult { buckets: string[][]; trailing: string[]; } /** * Split a stderr window into one bucket per executed action. * * A mark closes its action, so the bucket for `index` gets the lines between * the previous mark and this one. A mark whose index falls outside * `[0, executedCount)` is ignored. Lines at or after the last mark, and every * line when no mark arrived, become `trailing` for the caller to attach to the * last executed action. No filtering happens here: the caller applies * `extractRuntimeErrors` to each bucket. * * When an action's mark is missing (a partial stderr drain), its bucket stays * empty and its lines fall into the next mark's bucket - the two are genuinely * indistinguishable without the marker. */ export declare function bucketBySentinel({ lines, startSeq, boundaries, executedCount, }: BucketBySentinelInput): BucketBySentinelResult; /** * Find an available TCP port by binding to port 0 (OS-assigned ephemeral port), * reading the assigned port, and closing the listener. The brief TOCTOU window * between close and the consumer's listen is acceptable — if a collision occurs, * the bridge readiness check will surface the failure. */ export declare function findFreePort(): Promise; /** * Encode a JSON string as a length-prefixed frame. */ export declare function encodeFrame(payload: string): Buffer; export interface ParseFramesResult { frames: Buffer[]; remainder: Buffer; } /** * Pull as many complete frames as possible from a streaming buffer. Any * partial frame at the tail is returned as `remainder` for the next call. * * Throws if a header advertises a payload larger than {@link MAX_FRAME_BYTES} — * the caller should treat this as a fatal protocol error and close the socket. */ export declare function parseFrames(buffer: Buffer): ParseFramesResult; //# sourceMappingURL=bridge-protocol.d.ts.map