// Server-side state shared by the route handlers: what the protocol needs, // plus what main.ts resolved at startup (config.ts). import type { ServerWebSocket } from "flux:http" import type { ServerConfig } from "./config" import type { ClientEntry } from "../types/control" export let state = { config: undefined as unknown as ServerConfig, clients: new Map(), nextClientId: 0, /** * The clients still building the first frame of the last push, with when * the push went out and the queries waiting for the frame (control.ts * awaitFirstFrame). Entered by a push (rebuild.ts pushed), left on the * client's `ready` message or its disconnect (control.ts ready). */ loading: new Map void> }>(), /** * Identity of this server run, included in control responses that carry * cross-call state (client ids, log seq cursors). Both reset on restart, so * a consumer that sees the generation change knows its ids and cursors are * from a dead server and must be re-fetched. */ generation: Date.now(), /** * The latched reload message (JSON text), replayed to late-joining clients. * Set by a successful rebuild (and the build-failure trigger). */ currentReload: null as string | null, /** * The running bundle's sourcemaps (JSON text, bundle -> .tsx sources), * keyed by the module name stack frames cite ("main" for the app, the * isolate id for each isolate), used to remap stack traces in forwarded * client logs (see control.ts). Replaced on every reload; a reload without * maps clears them so frames are never remapped against a stale map. */ currentMaps: null as Record | null, /** * The `runtime:*` modules the running bundle imports * (BundleOutput.projectModules), set by every rebuild: what only the * project's own runtime has, so the local client must be the project's. */ projectModules: [] as string[], /** * The project's path the local client was expected at, when the stock * client runs in its place (the project did not build one for this host, * binaries.ts); null when the client is the project's or there is none. A * reload whose bundle imports a module of the project's runtime then says * so (rebuild.ts), since the stock client cannot run it. */ stockClientFor: null as string | null, /** The address clients reach this server on (host:port), set once bound. */ serverUrl: "", /** The p2p tunnel's ticket, when the tunnel is on (--tunnel); else null. */ tunnelTicket: null as string | null, stats: false, /** * Whether the user's own input is muted on every client, for an agent * measuring or testing (the `mute` message; `welcome` carries it to a client * joining while muted). Set by /mute. */ userInputMuted: false, /** * Whether reload-on-save is paused (the /watch endpoint, sol mcp's * pause_watch), so an agent's half-finished saves are not pushed to the * user's screens while it edits; its explicit reload still is. */ watchPaused: false, // Capture events from all connected clients share one clock (captureStartMs, // integer milliseconds) so they merge into one coherent timeline, tagged by // `device`. Streamed to disk as JSON Lines - see main.ts's "capture" handling. captureStartMs: 0, captureLastAt: 0, // ms, same clock as captureStartMs /** Serializes capture appends so events land on disk in arrival order. */ captureChain: Promise.resolve(), }