/** * The CLI lane's `ForgeTransport` — the same seam game-play-agent fills with a WebSocket * (`utils/voxel-ws.ts`'s `sendAndWaitForResult`), filled here by posting straight into a page the * CLI owns. Semantics are deliberately re-implemented, not redesigned: null on timeout or * transport failure, 3 attempts by default, an idle timeout when `progressType` is given, and * matching on type AND requestId. Read `voxel-ws.ts` alongside this file — every rule below has a * counterpart there, and the two must not drift. * * Two things differ from the web lane, both because there is no relay in between: * * - The command envelope. The engine's message handler reads `{ type, data }`, so the flat * command the pipeline builds (`{ type, requestId, ...payload }`) is repacked here. * - The reply rename. The engine posts `*_SAVED` / `*_PLACED`; the pipeline awaits `*_RESULT`. * In the web lane the creator does that rename in the browser. Doing it HERE, in Node, is what * keeps the extracted pipeline byte-identical for both lanes. * * NOTE on the import below: `@bitmagic/world-forger` is a real **dependency** of this package, * like `@bitmagic/asset-core`. It is the PUBLISHABLE half of the forger — the artifact schema, the * host seams and the three browser-driven pipeline steps — and `publish-npm.yml` publishes it * ahead of the CLI so npm can resolve it at install time. The private design/geometry half lives * in `@bitmagic/world-forger-internal`, which is never published and must never be imported from * here, nor bundled into `dist/`: bundled JS is readable, and minification is not protection. */ import type { ForgeTransport } from '@bitmagic/world-forger/pipeline/transport-types.js'; /** The `{ type, data }` envelope `CreatorMessageHandler` dispatches on. */ export interface PageCommand { type: string; data: Record; } /** * The narrow slice of "a loaded game page" the transport needs. `browser-host.ts` implements it * over Playwright; tests implement it with an object, which is why every rule in this file is * unit-testable without a browser. */ export interface ForgePageBridge { /** Post a command into the page. Rejecting means the page is gone — a transport failure. */ postCommand(command: PageCommand): Promise; /** Subscribe to every message the page posted. Returns an unsubscribe. */ onMessage(listener: (message: Record) => void): () => void; } export interface ForgePageTransportOptions { log?: (message: string) => void; /** Gap between attempts. Overridden in tests; 1s in production, matching the web lane. */ retryDelayMs?: number; } /** * Reply-name → awaited-name. Authoritative list carried over from the creator's own relay * (`game-play-agent/src/lab/browser.ts:112-123`). The last two entries are identity: the level * bake already posts its result and its progress under the names the pipeline awaits, and they are * listed rather than omitted so this map reads as the complete forge vocabulary. */ export declare const RESULT_TYPE_MAP: Record; /** * Build the transport over a page bridge. The returned object is the shared package's * `ForgeTransport` and nothing more — `commands/forge.ts` hands it straight to * `ForgeDeps.transport` via `buildCliForgeDeps`. */ export declare function createForgePageTransport(bridge: ForgePageBridge, options?: ForgePageTransportOptions): ForgeTransport;