@reactor-team/js-sdk 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/core/types.ts","../package.json","../src/core/CoordinatorClient.ts","../src/core/LocalCoordinatorClient.ts","../src/utils/webrtc.ts","../src/core/WebRTCTransportClient.ts","../src/core/Reactor.ts","../src/react/ReactorProvider.tsx","../src/core/store.ts","../src/react/hooks.ts","../src/react/ReactorView.tsx","../src/react/ReactorController.tsx","../src/react/WebcamStream.tsx","../src/utils/tokens.ts"],"sourcesContent":["export * from \"./core/Reactor\";\nexport * from \"./core/TransportClient\";\nexport * from \"./core/WebRTCTransportClient\";\nexport * from \"./react/ReactorProvider\";\nexport * from \"./react/ReactorView\";\nexport * from \"./react/ReactorController\";\nexport * from \"./react/WebcamStream\";\nexport * from \"./react/hooks\";\nexport * from \"./types\";\nexport * from \"./utils/tokens\";\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\nexport type ReactorStatus =\n | \"disconnected\" // Not connected to anything\n | \"connecting\" // Establishing connection to coordinator\n | \"waiting\" // Connected to coordinator, waiting for GPU assignment\n | \"ready\"; // Connected to GPU machine, can send/receive messages\n\n/**\n * The message scope identifies the envelope layer a data channel message belongs to.\n * - \"application\": model-defined commands (client->runtime) and model-emitted payloads (runtime->client).\n * - \"runtime\": platform-level control messages (e.g., capabilities exchange).\n */\nexport type MessageScope = \"application\" | \"runtime\";\n\n// Re-export core types that users may need\nexport type {\n TrackCapability,\n CommandCapability,\n Capabilities,\n TransportDeclaration,\n CreateSessionResponse as SessionInfo,\n} from \"./core/types\";\n\nexport interface ReactorError {\n code: string;\n message: string;\n timestamp: number;\n recoverable: boolean;\n component: \"api\" | \"gpu\";\n retryAfter?: number;\n}\n\nexport class ConflictError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class AbortError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\n/** Matches both our custom AbortError and the native DOMException thrown by fetch(). */\nexport function isAbortError(error: unknown): boolean {\n return (\n error instanceof AbortError ||\n (error instanceof Error && error.name === \"AbortError\")\n );\n}\n\nexport interface ReactorState {\n status: ReactorStatus;\n lastError?: ReactorError;\n}\n\n/**\n * Options for configuring the connect polling behavior.\n */\nexport interface ConnectOptions {\n /** Maximum number of SDP polling attempts before giving up. Default: 6. */\n maxAttempts?: number;\n}\n\n/**\n * Transport-agnostic timing breakdown of the connect() handshake, recorded\n * once per connection and included in every subsequent {@link ConnectionStats}\n * update. All durations are in milliseconds (from `performance.now()`).\n *\n * For transport-specific timings (e.g. ICE negotiation, data channel open),\n * see the relevant transport stats type (e.g. {@link WebRTCTransportTimings}).\n */\nexport interface ConnectionTimings {\n /** POST /sessions round-trip time */\n sessionCreationMs: number;\n /** Total time spent in transport.connect() (signaling, negotiation, etc.) */\n transportConnectingMs: number;\n /** End-to-end: connect() invocation → status \"ready\" */\n totalMs: number;\n}\n\nexport interface ConnectionStats {\n /** ICE candidate-pair round-trip time in milliseconds */\n rtt?: number;\n /** ICE candidate type: \"host\", \"srflx\", \"prflx\", or \"relay\" (TURN) */\n candidateType?: string;\n /** Estimated available outgoing bitrate in bits/second */\n availableOutgoingBitrate?: number;\n /** Received video frames per second */\n framesPerSecond?: number;\n /** Ratio of packets lost (0-1) */\n packetLossRatio?: number;\n /** Network jitter in seconds (from inbound-rtp) */\n jitter?: number;\n /** Timing breakdown of the initial connection handshake (set once, persisted until disconnect) */\n connectionTimings?: ConnectionTimings;\n timestamp: number;\n}\n\nexport type ReactorEvent =\n | \"statusChanged\" //updates on the reactor status\n | \"sessionIdChanged\" //updates on the session ID.\n | \"message\" //application-scoped messages from the model\n | \"runtimeMessage\" //internal platform-level control messages (e.g. capabilities)\n | \"trackReceived\" // (name: string, track: MediaStreamTrack, stream: MediaStream)\n | \"error\" //error events with ReactorError details\n | \"sessionExpirationChanged\" //session expiration has changed\n | \"capabilitiesReceived\" //server capabilities received after session creation\n | \"statsUpdate\"; //WebRTC stats update (RTT, etc.)\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * Internal types for the Reactor SDK.\n *\n * All Zod schemas and derived TypeScript types live here.\n * Version constants are sourced from package.json via resolveJsonModule.\n */\n\nimport { z } from \"zod\";\nimport packageJson from \"../../package.json\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Version Constants (single source of truth: package.json)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const REACTOR_SDK_VERSION: string = packageJson.version;\nexport const REACTOR_API_VERSION: number = (packageJson as any).reactor\n .apiVersion;\nexport const REACTOR_WEBRTC_VERSION: string = (packageJson as any).reactor\n .webrtcVersion;\nexport const REACTOR_SDK_TYPE = \"js\" as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Versioning Headers\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const API_VERSION_HEADER = \"Reactor-API-Version\";\nexport const API_ACCEPT_VERSION_HEADER = \"Reactor-API-Accept-Version\";\nexport const WEBRTC_VERSION_HEADER = \"Reactor-WebRTC-Version\";\n\nexport const VERSION_ERROR_CODES = {\n 426: \"CLIENT_VERSION_TOO_OLD\",\n 501: \"SERVER_VERSION_TOO_OLD\",\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Session States\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum SessionState {\n CREATED = \"CREATED\",\n PENDING = \"PENDING\",\n SUSPENDED = \"SUSPENDED\",\n WAITING = \"WAITING\",\n ACTIVE = \"ACTIVE\",\n INACTIVE = \"INACTIVE\",\n CLOSED = \"CLOSED\",\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Shared Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const ClientInfoSchema = z.object({\n sdk_version: z.string(),\n sdk_type: z.literal(\"js\"),\n});\n\nexport const TransportDeclarationSchema = z.object({\n protocol: z.string(),\n version: z.string(),\n});\n\nexport const TrackCapabilitySchema = z.object({\n name: z.string(),\n kind: z.enum([\"video\", \"audio\"]),\n direction: z.enum([\"recvonly\", \"sendonly\"]),\n});\n\nexport const TrackMappingEntrySchema = TrackCapabilitySchema.extend({\n mid: z.string(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Session API Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\n// POST /sessions — Request\nexport const CreateSessionRequestSchema = z.object({\n model: z.object({ name: z.string() }),\n client_info: ClientInfoSchema,\n supported_transports: z.array(TransportDeclarationSchema),\n extra_args: z.record(z.string(), z.any()).optional(),\n});\n\n// POST /sessions — Response (201): slim initial response before Runtime accepts\nexport const InitialSessionResponseSchema = z.object({\n session_id: z.string(),\n model: z.object({ name: z.string() }),\n server_info: z.object({ server_version: z.string() }).optional(),\n state: z.string(),\n cluster: z.string().optional(),\n});\n\n// Mirrors the proto Command message.\nexport const CommandCapabilitySchema = z.object({\n name: z.string(),\n description: z.string(),\n schema: z.record(z.string(), z.any()).optional(),\n});\n\n// GET /sessions/{id} — Full response with capabilities (populated after Runtime accepts).\n// Mirrors the proto TransportCapabilities message.\nexport const CapabilitiesSchema = z.object({\n protocol_version: z.string(),\n tracks: z.array(TrackCapabilitySchema),\n commands: z.array(CommandCapabilitySchema).optional(),\n emission_fps: z.number().nullable().optional(),\n});\n\nexport const SessionResponseSchema = z.object({\n session_id: z.string(),\n server_info: z.object({ server_version: z.string() }).optional(),\n selected_transport: TransportDeclarationSchema.optional(),\n model: z.object({ name: z.string(), version: z.string().optional() }),\n capabilities: CapabilitiesSchema.optional(),\n state: z.string(),\n cluster: z.string().optional(),\n});\n\n// Full session response: selected_transport and capabilities are guaranteed present\nexport const CreateSessionResponseSchema = SessionResponseSchema.extend({\n selected_transport: TransportDeclarationSchema,\n capabilities: CapabilitiesSchema,\n});\n\n// GET /sessions/{id}/info — Response (200)\nexport const SessionInfoResponseSchema = z.object({\n session_id: z.string(),\n cluster: z.string().optional(),\n state: z.string(),\n});\n\n// DELETE /sessions/{id} — Request\nexport const TerminateSessionRequestSchema = z.object({\n reason: z.string().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// WebRTC Transport Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\n// GET /sessions/{id}/transport/webrtc/ice_servers — Response (200)\nexport const IceServerCredentialsSchema = z.object({\n username: z.string(),\n password: z.string(),\n});\n\nexport const IceServerSchema = z.object({\n uris: z.array(z.string()),\n credentials: IceServerCredentialsSchema.optional(),\n});\n\nexport const IceServersResponseSchema = z.object({\n ice_servers: z.array(IceServerSchema),\n});\n\n// POST/PUT /sessions/{id}/transport/webrtc/sdp_params — Request\nexport const WebRTCSdpOfferRequestSchema = z.object({\n sdp_offer: z.string(),\n client_info: ClientInfoSchema.optional(),\n track_mapping: z.array(TrackMappingEntrySchema),\n});\n\n// GET /sessions/{id}/transport/webrtc/sdp_params — Response (200)\nexport const WebRTCSdpAnswerResponseSchema = z.object({\n sdp_answer: z.string(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inferred TypeScript Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type ClientInfo = z.infer<typeof ClientInfoSchema>;\nexport type TransportDeclaration = z.infer<typeof TransportDeclarationSchema>;\nexport type TrackCapability = z.infer<typeof TrackCapabilitySchema>;\nexport type CommandCapability = z.infer<typeof CommandCapabilitySchema>;\nexport type TrackMappingEntry = z.infer<typeof TrackMappingEntrySchema>;\n\nexport type CreateSessionRequest = z.infer<typeof CreateSessionRequestSchema>;\nexport type InitialSessionResponse = z.infer<\n typeof InitialSessionResponseSchema\n>;\nexport type SessionResponse = z.infer<typeof SessionResponseSchema>;\nexport type CreateSessionResponse = z.infer<typeof CreateSessionResponseSchema>;\nexport type Capabilities = z.infer<typeof CapabilitiesSchema>;\n\nexport type SessionInfoResponse = z.infer<typeof SessionInfoResponseSchema>;\nexport type TerminateSessionRequest = z.infer<\n typeof TerminateSessionRequestSchema\n>;\n\nexport type IceServer = z.infer<typeof IceServerSchema>;\nexport type IceServersResponse = z.infer<typeof IceServersResponseSchema>;\n\nexport type WebRTCSdpOfferRequest = z.infer<typeof WebRTCSdpOfferRequestSchema>;\nexport type WebRTCSdpAnswerResponse = z.infer<\n typeof WebRTCSdpAnswerResponseSchema\n>;\n","{\n \"name\": \"@reactor-team/js-sdk\",\n \"version\": \"2.7.0\",\n \"description\": \"Reactor JavaScript frontend SDK\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:unit\": \"vitest run __tests__/unit\",\n \"test:integration\": \"vitest run __tests__/integration\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\"\n },\n \"keywords\": [\n \"reactor\",\n \"frontend\",\n \"sdk\"\n ],\n \"author\": \"Reactor Technologies, Inc.\",\n \"reactor\": {\n \"apiVersion\": 1,\n \"webrtcVersion\": \"1.0\"\n },\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/reactor-team/js-sdk\"\n },\n \"packageManager\": \"pnpm@10.12.1\",\n \"devDependencies\": {\n \"@roamhq/wrtc\": \"^0.8.0\",\n \"@types/inquirer\": \"^9.0.9\",\n \"@types/node\": \"^20\",\n \"@types/react\": \"^18.2.8\",\n \"@types/ws\": \"^8.18.1\",\n \"prettier\": \"^3.6.2\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^3.0.0\"\n },\n \"dependencies\": {\n \"@bufbuild/protobuf\": \"^2.0.0\",\n \"chalk\": \"^5.3.0\",\n \"inquirer\": \"^9.3.0\",\n \"simple-git\": \"^3.24.0\",\n \"ws\": \"^8.18.3\",\n \"zod\": \"^4.0.5\"\n },\n \"peerDependencies\": {\n \"react\": \"^17.0.0 || ^18.0.0 || ^19.0.0\",\n \"zustand\": \"^5.0.6\"\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * The CoordinatorClient handles session lifecycle via HTTP requests.\n *\n * Transport signaling (ICE servers, SDP exchange) is NOT handled here —\n * that responsibility belongs to the TransportClient implementations.\n */\n\nimport {\n type CreateSessionRequest,\n type CreateSessionResponse,\n type InitialSessionResponse,\n type SessionInfoResponse,\n type TerminateSessionRequest,\n CreateSessionResponseSchema,\n InitialSessionResponseSchema,\n SessionResponseSchema,\n SessionInfoResponseSchema,\n SessionState,\n REACTOR_API_VERSION,\n REACTOR_SDK_VERSION,\n REACTOR_SDK_TYPE,\n REACTOR_WEBRTC_VERSION,\n API_VERSION_HEADER,\n API_ACCEPT_VERSION_HEADER,\n VERSION_ERROR_CODES,\n} from \"./types\";\nimport { AbortError } from \"../types\";\n\nconst SESSION_POLL_INITIAL_BACKOFF_MS = 200;\nconst SESSION_POLL_MAX_BACKOFF_MS = 10_000;\nconst SESSION_POLL_BACKOFF_MULTIPLIER = 2;\nconst SESSION_POLL_DEFAULT_MAX_ATTEMPTS = 20;\n\nexport interface CoordinatorClientOptions {\n baseUrl: string;\n jwtToken: string;\n model: string;\n}\n\nexport class CoordinatorClient {\n protected readonly baseUrl: string;\n private jwtToken: string;\n protected readonly model: string;\n protected currentSessionId?: string;\n private abortController: AbortController;\n\n constructor(options: CoordinatorClientOptions) {\n this.baseUrl = options.baseUrl;\n this.jwtToken = options.jwtToken;\n this.model = options.model;\n this.abortController = new AbortController();\n }\n\n /**\n * Aborts any in-flight HTTP requests.\n * A fresh AbortController is created so the client remains reusable.\n */\n abort(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n /**\n * The current abort signal, passed to every fetch() call.\n * Protected so subclasses can forward it to their own fetch calls.\n */\n protected get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Returns authorization + versioning headers for all coordinator requests.\n */\n protected getHeaders(): HeadersInit {\n return {\n Authorization: `Bearer ${this.jwtToken}`,\n [API_VERSION_HEADER]: String(REACTOR_API_VERSION),\n [API_ACCEPT_VERSION_HEADER]: String(REACTOR_API_VERSION),\n };\n }\n\n /**\n * Checks an HTTP response for version mismatch errors (426, 501).\n * Logs a clear message and throws with a descriptive error code.\n */\n protected async checkVersionMismatch(response: Response): Promise<void> {\n if (response.status === 426) {\n const msg =\n `Client API version (${REACTOR_API_VERSION}) is too old. ` +\n `Server requires a newer version. Please upgrade @reactor-team/js-sdk.`;\n console.error(`[Reactor]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[426]}: ${msg}`);\n }\n\n if (response.status === 501) {\n const msg =\n `Server does not support API version ${REACTOR_API_VERSION}. ` +\n `The server may need to be updated.`;\n console.error(`[Reactor]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[501]}: ${msg}`);\n }\n }\n\n protected sleep(ms: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const { signal } = this;\n if (signal.aborted) {\n reject(new AbortError(\"Sleep aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError(\"Sleep aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n /**\n * Creates a new session with the coordinator.\n * No SDP is sent — transport signaling is decoupled from session creation.\n *\n * The POST response is a slim acknowledgment (session_id, model name, status).\n * Capabilities and transport details are populated later once the Runtime\n * accepts the session — use {@link pollSessionReady} to wait for them.\n */\n async createSession(\n extraArgs?: Record<string, any>\n ): Promise<InitialSessionResponse> {\n console.debug(\"[CoordinatorClient] Creating session...\");\n\n const requestBody: CreateSessionRequest = {\n model: { name: this.model },\n client_info: {\n sdk_version: REACTOR_SDK_VERSION,\n sdk_type: REACTOR_SDK_TYPE,\n },\n supported_transports: [\n { protocol: \"webrtc\", version: REACTOR_WEBRTC_VERSION },\n ],\n ...(extraArgs ? { extra_args: extraArgs } : {}),\n };\n\n const response = await fetch(`${this.baseUrl}/sessions`, {\n method: \"POST\",\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(requestBody),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to create session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n const parsed = InitialSessionResponseSchema.parse(data);\n this.currentSessionId = parsed.session_id;\n\n console.debug(\n \"[CoordinatorClient] Session created:\",\n this.currentSessionId,\n \"state:\",\n parsed.state\n );\n\n return parsed;\n }\n\n /**\n * Polls GET /sessions/{id} until the Runtime has accepted the session\n * and populated capabilities and selected_transport.\n */\n async pollSessionReady(opts?: {\n maxAttempts?: number;\n }): Promise<CreateSessionResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const maxAttempts = opts?.maxAttempts ?? SESSION_POLL_DEFAULT_MAX_ATTEMPTS;\n let backoffMs = SESSION_POLL_INITIAL_BACKOFF_MS;\n let attempt = 0;\n\n console.debug(\n \"[CoordinatorClient] Polling session until capabilities are available...\"\n );\n\n while (true) {\n if (this.signal.aborted) {\n throw new AbortError(\"Session polling aborted\");\n }\n\n if (attempt >= maxAttempts) {\n throw new Error(\n `Session polling exceeded maximum attempts (${maxAttempts}). ` +\n `The model may be unavailable or overloaded.`\n );\n }\n\n attempt++;\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to poll session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n const partial = SessionResponseSchema.parse(data);\n\n const terminalStates: string[] = [\n SessionState.CLOSED,\n SessionState.INACTIVE,\n ];\n if (terminalStates.includes(partial.state)) {\n throw new Error(\n `Session entered terminal state \"${partial.state}\" while waiting for capabilities`\n );\n }\n\n if (partial.capabilities && partial.selected_transport) {\n const full = CreateSessionResponseSchema.parse(data);\n console.debug(\n `[CoordinatorClient] Session ready after ${attempt} poll(s), ` +\n `transport: ${full.selected_transport.protocol}, ` +\n `tracks: ${full.capabilities.tracks.length}`\n );\n return full;\n }\n\n console.debug(\n `[CoordinatorClient] Session poll ${attempt}/${maxAttempts} — ` +\n `state: ${partial.state}, waiting ${backoffMs}ms...`\n );\n\n await this.sleep(backoffMs);\n backoffMs = Math.min(\n backoffMs * SESSION_POLL_BACKOFF_MULTIPLIER,\n SESSION_POLL_MAX_BACKOFF_MS\n );\n }\n }\n\n /**\n * Gets full session details from the coordinator.\n * Returns the same shape as the creation response but with updated state.\n */\n async getSession(): Promise<CreateSessionResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to get session: ${response.status} ${errorText}`);\n }\n\n const data = await response.json();\n return CreateSessionResponseSchema.parse(data);\n }\n\n /**\n * Gets lightweight session status (session_id, cluster, status).\n */\n async getSessionInfo(): Promise<SessionInfoResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}/info`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to get session info: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n return SessionInfoResponseSchema.parse(data);\n }\n\n /**\n * Restarts an inactive session with a different compute unit.\n * The session ID is preserved but a new transport must be established.\n */\n async restartSession(): Promise<void> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n console.debug(\n \"[CoordinatorClient] Restarting session:\",\n this.currentSessionId\n );\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"PUT\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to restart session: ${response.status} ${errorText}`\n );\n }\n }\n\n /**\n * Terminates the current session by sending a DELETE request.\n * No-op if no session has been created yet.\n * @param reason Optional termination reason\n */\n async terminateSession(reason?: string): Promise<void> {\n if (!this.currentSessionId) {\n return;\n }\n\n console.debug(\n \"[CoordinatorClient] Terminating session:\",\n this.currentSessionId\n );\n\n const body: TerminateSessionRequest | undefined = reason\n ? { reason }\n : undefined;\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"DELETE\",\n headers: {\n ...this.getHeaders(),\n ...(body ? { \"Content-Type\": \"application/json\" } : {}),\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n signal: this.signal,\n }\n );\n\n if (response.ok) {\n this.currentSessionId = undefined;\n return;\n }\n\n if (response.status === 404) {\n console.debug(\n \"[CoordinatorClient] Session not found on server, clearing local state:\",\n this.currentSessionId\n );\n this.currentSessionId = undefined;\n return;\n }\n\n const errorText = await response.text();\n throw new Error(\n `Failed to terminate session: ${response.status} ${errorText}`\n );\n }\n\n getSessionId(): string | undefined {\n return this.currentSessionId;\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * LocalCoordinatorClient connects to a local runtime instance.\n *\n * The local runtime uses a simpler protocol than the production coordinator:\n * - POST /start_session → starts session, returns full capabilities immediately\n * - POST /stop_session → stops session\n * - Transport signaling via /sessions/{id}/transport/webrtc/* (unchanged)\n *\n * No session polling is needed because the local runtime IS the model host —\n * capabilities are known the moment the session is created.\n */\n\nimport { CoordinatorClient } from \"./CoordinatorClient\";\nimport {\n type CreateSessionResponse,\n type InitialSessionResponse,\n CreateSessionResponseSchema,\n InitialSessionResponseSchema,\n API_VERSION_HEADER,\n API_ACCEPT_VERSION_HEADER,\n REACTOR_API_VERSION,\n} from \"./types\";\n\nexport class LocalCoordinatorClient extends CoordinatorClient {\n private cachedSessionResponse?: CreateSessionResponse;\n\n constructor(baseUrl: string, model: string) {\n super({\n baseUrl,\n jwtToken: \"local\",\n model,\n });\n }\n\n protected override getHeaders(): HeadersInit {\n return {\n [API_VERSION_HEADER]: String(REACTOR_API_VERSION),\n [API_ACCEPT_VERSION_HEADER]: String(REACTOR_API_VERSION),\n };\n }\n\n /**\n * Starts a session on the local runtime.\n *\n * Unlike the production coordinator, the local runtime returns the full\n * response (capabilities, selected_transport) immediately — no polling needed.\n */\n override async createSession(\n extraArgs?: Record<string, any>\n ): Promise<InitialSessionResponse> {\n console.debug(\"[LocalCoordinatorClient] Starting session...\");\n\n const response = await fetch(`${this.baseUrl}/start_session`, {\n method: \"POST\",\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n ...(extraArgs ? { extra_args: extraArgs } : {}),\n }),\n signal: this.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to start session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n\n this.cachedSessionResponse = CreateSessionResponseSchema.parse(data);\n this.currentSessionId = this.cachedSessionResponse.session_id;\n\n console.debug(\n \"[LocalCoordinatorClient] Session started:\",\n this.currentSessionId,\n \"transport:\",\n this.cachedSessionResponse.selected_transport.protocol,\n \"tracks:\",\n this.cachedSessionResponse.capabilities.tracks.length\n );\n\n return InitialSessionResponseSchema.parse(data);\n }\n\n /**\n * Returns the cached full session response immediately.\n * The local runtime already provided everything in start_session.\n */\n override async pollSessionReady(): Promise<CreateSessionResponse> {\n if (!this.cachedSessionResponse) {\n throw new Error(\n \"No cached session response. Call createSession() first.\"\n );\n }\n return this.cachedSessionResponse;\n }\n\n /**\n * Stops the session on the local runtime.\n */\n override async terminateSession(): Promise<void> {\n if (!this.currentSessionId) {\n return;\n }\n\n console.debug(\n \"[LocalCoordinatorClient] Stopping session:\",\n this.currentSessionId\n );\n\n try {\n await fetch(`${this.baseUrl}/stop_session`, {\n method: \"POST\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n } catch (error) {\n console.error(\"[LocalCoordinatorClient] Error stopping session:\", error);\n }\n\n this.currentSessionId = undefined;\n this.cachedSessionResponse = undefined;\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * Stateless WebRTC utility functions for SDP exchange and peer connection management.\n */\n\nimport type { IceServersResponse } from \"../core/types\";\nimport type { MessageScope, ConnectionStats } from \"../types\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface WebRTCConfig {\n iceServers: RTCIceServer[];\n dataChannelLabel?: string;\n}\n\nconst DEFAULT_DATA_CHANNEL_LABEL = \"data\";\n\nconst FORCE_RELAY_MODE = false;\n\n/**\n * Safe cross-browser default for the maximum data channel message size (bytes).\n * Most browsers negotiate 256 KiB via SCTP; we use a slightly lower value to\n * leave room for framing overhead.\n */\nconst DEFAULT_MAX_MESSAGE_BYTES = 256 * 1024; // 256 KiB\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Peer Connection Creation\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Creates a new RTCPeerConnection with the specified configuration.\n * @param config WebRTC configuration with required iceServers\n */\nexport function createPeerConnection(config: WebRTCConfig): RTCPeerConnection {\n return new RTCPeerConnection({\n iceServers: config.iceServers,\n iceTransportPolicy: FORCE_RELAY_MODE ? \"relay\" : \"all\",\n });\n}\n\n/**\n * Creates a data channel on the peer connection.\n */\nexport function createDataChannel(\n pc: RTCPeerConnection,\n label?: string\n): RTCDataChannel {\n return pc.createDataChannel(label ?? DEFAULT_DATA_CHANNEL_LABEL);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// SDP Offer/Answer\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Creates an SDP offer on the peer connection.\n * No MID munging — track identity is conveyed via track_mapping metadata.\n * @returns The SDP offer string with gathered ICE candidates.\n */\nexport async function createOffer(pc: RTCPeerConnection): Promise<string> {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n await waitForIceGathering(pc);\n\n const localDescription = pc.localDescription;\n if (!localDescription) {\n throw new Error(\"Failed to create local description\");\n }\n\n return localDescription.sdp;\n}\n\n/**\n * Creates an SDP answer in response to a received offer.\n * Waits for ICE gathering to complete before returning.\n */\nexport async function createAnswer(\n pc: RTCPeerConnection,\n offer: string\n): Promise<string> {\n await setRemoteDescription(pc, offer);\n\n const answer = await pc.createAnswer();\n await pc.setLocalDescription(answer);\n\n await waitForIceGathering(pc);\n\n const localDescription = pc.localDescription;\n if (!localDescription) {\n throw new Error(\"Failed to create local description\");\n }\n\n return localDescription.sdp;\n}\n\n/**\n * Sets the remote description on the peer connection.\n */\nexport async function setRemoteDescription(\n pc: RTCPeerConnection,\n sdp: string\n): Promise<void> {\n const sessionDescription = new RTCSessionDescription({\n sdp: sdp,\n type: \"answer\",\n });\n await pc.setRemoteDescription(sessionDescription);\n}\n\n/**\n * Gets the local SDP description from the peer connection.\n */\nexport function getLocalDescription(pc: RTCPeerConnection): string | undefined {\n const desc = pc.localDescription;\n if (!desc) return undefined;\n return desc.sdp;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ICE Handling\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transforms ICE servers from the API response to RTCIceServer format.\n * The API uses `uris` and a nested `credentials` object; the browser\n * RTCIceServer interface expects `urls`, `username`, and `credential`.\n */\nexport function transformIceServers(\n response: IceServersResponse\n): RTCIceServer[] {\n return response.ice_servers.map((server) => {\n const rtcServer: RTCIceServer = {\n urls: server.uris,\n };\n if (server.credentials) {\n rtcServer.username = server.credentials.username;\n rtcServer.credential = server.credentials.password;\n }\n return rtcServer;\n });\n}\n\n/**\n * Adds an ICE candidate to the peer connection.\n */\nexport async function addIceCandidate(\n pc: RTCPeerConnection,\n candidate: RTCIceCandidateInit\n): Promise<void> {\n await pc.addIceCandidate(new RTCIceCandidate(candidate));\n}\n\n/**\n * Waits for ICE gathering to complete with a timeout.\n */\nexport function waitForIceGathering(\n pc: RTCPeerConnection,\n timeoutMs: number = 5000\n): Promise<void> {\n return new Promise((resolve) => {\n if (pc.iceGatheringState === \"complete\") {\n resolve();\n return;\n }\n\n const onGatheringStateChange = () => {\n if (pc.iceGatheringState === \"complete\") {\n pc.removeEventListener(\n \"icegatheringstatechange\",\n onGatheringStateChange\n );\n resolve();\n }\n };\n\n pc.addEventListener(\"icegatheringstatechange\", onGatheringStateChange);\n\n setTimeout(() => {\n pc.removeEventListener(\"icegatheringstatechange\", onGatheringStateChange);\n resolve();\n }, timeoutMs);\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Track Management\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Adds a track to the peer connection.\n */\nexport function addTrack(\n pc: RTCPeerConnection,\n track: MediaStreamTrack,\n stream?: MediaStream\n): RTCRtpSender {\n const mediaStream = stream ?? new MediaStream([track]);\n return pc.addTrack(track, mediaStream);\n}\n\n/**\n * Removes a track from the peer connection by its sender.\n */\nexport function removeTrack(pc: RTCPeerConnection, sender: RTCRtpSender): void {\n pc.removeTrack(sender);\n}\n\n/**\n * Finds the sender for a specific track.\n */\nexport function findSenderForTrack(\n pc: RTCPeerConnection,\n track: MediaStreamTrack\n): RTCRtpSender | undefined {\n return pc.getSenders().find((sender) => sender.track === track);\n}\n\n/**\n * Removes all tracks from the peer connection.\n */\nexport function removeAllTracks(pc: RTCPeerConnection): void {\n for (const sender of pc.getSenders()) {\n pc.removeTrack(sender);\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data Channel Messaging\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Sends a message through a data channel wrapped in the two-level envelope.\n *\n * Wire format:\n * { scope: \"application\"|\"runtime\", data: { type: <command>, data: <payload> } }\n *\n * @param channel The RTCDataChannel to send on.\n * @param command Inner command/message type (e.g. \"set_prompt\", \"requestCapabilities\").\n * @param data Payload for the command.\n * @param scope Outer envelope scope – defaults to \"application\".\n * @param maxBytes Max allowed serialized message size in bytes.\n * Defaults to {@link DEFAULT_MAX_MESSAGE_BYTES} (256 KiB).\n * Pass the negotiated SCTP limit when available.\n */\nexport function sendMessage(\n channel: RTCDataChannel,\n command: string,\n data: any,\n scope: MessageScope = \"application\",\n maxBytes: number = DEFAULT_MAX_MESSAGE_BYTES\n): void {\n if (channel.readyState !== \"open\") {\n throw new Error(`Data channel not open: ${channel.readyState}`);\n }\n const jsonData = typeof data === \"string\" ? JSON.parse(data) : data;\n const inner = { type: command, data: jsonData };\n const payload = { scope, data: inner };\n const serialized = JSON.stringify(payload);\n\n const byteLength = new TextEncoder().encode(serialized).byteLength;\n if (byteLength > maxBytes) {\n throw new Error(\n `Data channel message too large: ${byteLength} bytes exceeds ` +\n `limit of ${maxBytes} bytes (command: \"${command}\")`\n );\n }\n\n channel.send(serialized);\n}\n\n/**\n * Parses a received data channel message, attempting JSON parse.\n */\nexport function parseMessage(data: unknown): unknown {\n if (typeof data === \"string\") {\n try {\n return JSON.parse(data);\n } catch {\n return data;\n }\n }\n return data;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Connection State\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Checks if the peer connection is in a connected state.\n */\nexport function isConnected(pc: RTCPeerConnection): boolean {\n return pc.connectionState === \"connected\";\n}\n\n/**\n * Checks if the peer connection is closed or failed.\n */\nexport function isClosed(pc: RTCPeerConnection): boolean {\n return pc.connectionState === \"closed\" || pc.connectionState === \"failed\";\n}\n\n/**\n * Closes the peer connection and cleans up.\n */\nexport function closePeerConnection(pc: RTCPeerConnection): void {\n pc.close();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stats Extraction\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Extracts ConnectionStats from an RTCStatsReport.\n * Reads candidate-pair, local-candidate, and inbound-rtp (video) reports.\n */\nexport function extractConnectionStats(\n report: RTCStatsReport\n): ConnectionStats {\n let rtt: number | undefined;\n let availableOutgoingBitrate: number | undefined;\n let localCandidateId: string | undefined;\n let framesPerSecond: number | undefined;\n let jitter: number | undefined;\n let packetLossRatio: number | undefined;\n\n report.forEach((stat) => {\n if (stat.type === \"candidate-pair\" && stat.state === \"succeeded\") {\n if (stat.currentRoundTripTime !== undefined) {\n rtt = stat.currentRoundTripTime * 1000;\n }\n if (stat.availableOutgoingBitrate !== undefined) {\n availableOutgoingBitrate = stat.availableOutgoingBitrate;\n }\n localCandidateId = stat.localCandidateId;\n }\n\n if (stat.type === \"inbound-rtp\" && stat.kind === \"video\") {\n if (stat.framesPerSecond !== undefined) {\n framesPerSecond = stat.framesPerSecond;\n }\n if (stat.jitter !== undefined) {\n jitter = stat.jitter;\n }\n if (\n stat.packetsReceived !== undefined &&\n stat.packetsLost !== undefined &&\n stat.packetsReceived + stat.packetsLost > 0\n ) {\n packetLossRatio =\n stat.packetsLost / (stat.packetsReceived + stat.packetsLost);\n }\n }\n });\n\n let candidateType: string | undefined;\n if (localCandidateId) {\n const localCandidate = report.get(localCandidateId);\n if (localCandidate?.candidateType) {\n candidateType = localCandidate.candidateType;\n }\n }\n\n return {\n rtt,\n candidateType,\n availableOutgoingBitrate,\n framesPerSecond,\n packetLossRatio,\n jitter,\n timestamp: Date.now(),\n };\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * WebRTC implementation of the TransportClient interface.\n *\n * Handles the full WebRTC lifecycle: signaling (ICE servers, SDP exchange\n * via the transport REST endpoints), RTCPeerConnection management, data\n * channel messaging, track publishing, and stats collection.\n */\n\nimport * as webrtc from \"../utils/webrtc\";\nimport type {\n TransportClient,\n TransportClientConfig,\n TransportStatus,\n TransportEvent,\n} from \"./TransportClient\";\nimport type { MessageScope, ConnectionStats } from \"../types\";\nimport { AbortError } from \"../types\";\nimport {\n type TrackCapability,\n type TrackMappingEntry,\n type WebRTCSdpOfferRequest,\n type WebRTCSdpAnswerResponse,\n IceServersResponseSchema,\n WebRTCSdpAnswerResponseSchema,\n REACTOR_WEBRTC_VERSION,\n REACTOR_SDK_VERSION,\n REACTOR_SDK_TYPE,\n WEBRTC_VERSION_HEADER,\n VERSION_ERROR_CODES,\n} from \"./types\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype EventHandler = (...args: any[]) => void;\n\nconst PING_INTERVAL_MS = 5_000;\nconst STATS_INTERVAL_MS = 2_000;\n\nconst INITIAL_BACKOFF_MS = 200;\nconst MAX_BACKOFF_MS = 15_000;\nconst BACKOFF_MULTIPLIER = 2;\nconst DEFAULT_MAX_POLL_ATTEMPTS = 6;\n\nexport interface WebRTCTransportConfig extends TransportClientConfig {\n webrtcVersion?: string;\n maxPollAttempts?: number;\n}\n\n/**\n * WebRTC-specific timing breakdown of the transport connection.\n * Recorded once per connection and accessible via {@link WebRTCTransportClient.getTransportTimings}.\n */\nexport interface WebRTCTransportTimings {\n protocol: \"webrtc\";\n /** Time spent polling for the SDP answer (POST offer → GET answer 200) */\n sdpPollingMs: number;\n /** Number of SDP poll requests made (1 = answered on first try) */\n sdpPollingAttempts: number;\n /** setRemoteDescription → RTCPeerConnection connectionState \"connected\" */\n iceNegotiationMs: number;\n /** setRemoteDescription → RTCDataChannel \"open\" */\n dataChannelMs: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Transceiver bookkeeping\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface TransceiverEntry {\n name: string;\n kind: \"audio\" | \"video\";\n direction: RTCRtpTransceiverDirection;\n transceiver?: RTCRtpTransceiver;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Implementation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class WebRTCTransportClient implements TransportClient {\n private eventListeners: Map<TransportEvent, Set<EventHandler>> = new Map();\n private peerConnection: RTCPeerConnection | undefined;\n private dataChannel: RTCDataChannel | undefined;\n private status: TransportStatus = \"disconnected\";\n private pingInterval: ReturnType<typeof setInterval> | undefined;\n private statsInterval: ReturnType<typeof setInterval> | undefined;\n private stats: ConnectionStats | undefined;\n\n private transceiverMap: Map<string, TransceiverEntry> = new Map();\n private publishedTracks: Map<string, MediaStreamTrack> = new Map();\n private peerConnected = false;\n private dataChannelOpen = false;\n\n private iceStartTime?: number;\n private iceNegotiationMs?: number;\n private dataChannelMs?: number;\n private sdpPollingMs?: number;\n private sdpPollingAttempts?: number;\n\n private readonly baseUrl: string;\n private readonly sessionId: string;\n private readonly jwtToken: string;\n private readonly webrtcVersion: string;\n private readonly maxPollAttempts: number;\n private abortController: AbortController;\n\n constructor(config: WebRTCTransportConfig) {\n this.baseUrl = config.baseUrl;\n this.sessionId = config.sessionId;\n this.jwtToken = config.jwtToken;\n this.webrtcVersion = config.webrtcVersion ?? REACTOR_WEBRTC_VERSION;\n this.maxPollAttempts = config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;\n this.abortController = new AbortController();\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Event Emitter\n // ─────────────────────────────────────────────────────────────────────────\n\n on(event: TransportEvent, handler: EventHandler): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(handler);\n }\n\n off(event: TransportEvent, handler: EventHandler): void {\n this.eventListeners.get(event)?.delete(handler);\n }\n\n private emit(event: TransportEvent, ...args: unknown[]): void {\n this.eventListeners.get(event)?.forEach((handler) => handler(...args));\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // HTTP Helpers\n // ─────────────────────────────────────────────────────────────────────────\n\n private get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private get transportBaseUrl(): string {\n return `${this.baseUrl}/sessions/${this.sessionId}/transport/webrtc`;\n }\n\n private getHeaders(): HeadersInit {\n return {\n Authorization: `Bearer ${this.jwtToken}`,\n [WEBRTC_VERSION_HEADER]: this.webrtcVersion,\n };\n }\n\n private async checkVersionMismatch(response: Response): Promise<void> {\n if (response.status === 426) {\n const msg =\n `Client WebRTC version (${this.webrtcVersion}) is too old. ` +\n `Server requires a newer version. Please upgrade @reactor-team/js-sdk.`;\n console.error(`[WebRTCTransport]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[426]}: ${msg}`);\n }\n\n if (response.status === 501) {\n const msg =\n `Server does not support WebRTC version ${this.webrtcVersion}. ` +\n `The server may need to be updated.`;\n console.error(`[WebRTCTransport]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[501]}: ${msg}`);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const { signal } = this;\n if (signal.aborted) {\n reject(new AbortError(\"Sleep aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError(\"Sleep aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Transport Signaling (HTTP)\n // ─────────────────────────────────────────────────────────────────────────\n\n private async fetchIceServers(): Promise<RTCIceServer[]> {\n console.debug(\"[WebRTCTransport] Fetching ICE servers...\");\n\n const response = await fetch(`${this.transportBaseUrl}/ice_servers`, {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ICE servers: ${response.status}`);\n }\n\n const data = await response.json();\n const parsed = IceServersResponseSchema.parse(data);\n const iceServers = webrtc.transformIceServers(parsed);\n\n console.debug(\"[WebRTCTransport] Received ICE servers:\", iceServers.length);\n return iceServers;\n }\n\n private async sendSdpOffer(\n sdpOffer: string,\n trackMapping: TrackMappingEntry[],\n method: \"POST\" | \"PUT\" = \"POST\"\n ): Promise<void> {\n console.debug(\n `[WebRTCTransport] Sending SDP offer (${method}) for session:`,\n this.sessionId\n );\n\n const requestBody: WebRTCSdpOfferRequest = {\n sdp_offer: sdpOffer,\n client_info: {\n sdk_version: REACTOR_SDK_VERSION,\n sdk_type: REACTOR_SDK_TYPE,\n },\n track_mapping: trackMapping,\n };\n\n const response = await fetch(`${this.transportBaseUrl}/sdp_params`, {\n method,\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(requestBody),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (response.status !== 202) {\n const errorText = await response.text();\n throw new Error(\n `Failed to send SDP offer: ${response.status} ${errorText}`\n );\n }\n\n console.debug(\"[WebRTCTransport] SDP offer accepted (202)\");\n }\n\n private async pollSdpAnswer(): Promise<WebRTCSdpAnswerResponse> {\n console.debug(\"[WebRTCTransport] Polling for SDP answer...\");\n\n const pollStart = performance.now();\n let backoffMs = INITIAL_BACKOFF_MS;\n let attempt = 0;\n\n while (true) {\n if (this.signal.aborted) {\n throw new AbortError(\"SDP polling aborted\");\n }\n\n if (attempt >= this.maxPollAttempts) {\n throw new Error(\n `SDP polling exceeded maximum attempts (${this.maxPollAttempts})`\n );\n }\n\n attempt++;\n console.debug(\n `[WebRTCTransport] SDP poll attempt ${attempt}/${this.maxPollAttempts}`\n );\n\n const response = await fetch(`${this.transportBaseUrl}/sdp_params`, {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (response.status === 200) {\n const data = await response.json();\n const parsed = WebRTCSdpAnswerResponseSchema.parse(data);\n this.sdpPollingMs = performance.now() - pollStart;\n this.sdpPollingAttempts = attempt;\n console.debug(\n `[WebRTCTransport] Received SDP answer via polling (${attempt} attempt(s), ${this.sdpPollingMs.toFixed(0)}ms)`\n );\n return parsed;\n }\n\n if (response.status === 202) {\n console.debug(\n `[WebRTCTransport] SDP answer pending, retrying in ${backoffMs}ms...`\n );\n await this.sleep(backoffMs);\n backoffMs = Math.min(backoffMs * BACKOFF_MULTIPLIER, MAX_BACKOFF_MS);\n continue;\n }\n\n const errorText = await response.text();\n throw new Error(\n `Failed to poll SDP answer: ${response.status} ${errorText}`\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Connection Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n async connect(tracks: TrackCapability[]): Promise<void> {\n this.setStatus(\"connecting\");\n this.resetTransportTimings();\n\n const iceServers = await this.fetchIceServers();\n\n this.peerConnection = webrtc.createPeerConnection({ iceServers });\n this.setupPeerConnectionHandlers();\n\n this.dataChannel = webrtc.createDataChannel(this.peerConnection);\n this.setupDataChannelHandlers();\n\n this.transceiverMap.clear();\n for (const track of tracks) {\n const transceiver = this.peerConnection.addTransceiver(track.kind, {\n direction: track.direction,\n });\n this.transceiverMap.set(track.name, {\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n transceiver,\n });\n console.debug(\n `[WebRTCTransport] Transceiver added: \"${track.name}\" (${track.kind}, ${track.direction})`\n );\n }\n\n const sdpOffer = await webrtc.createOffer(this.peerConnection);\n\n const trackMapping = this.buildTrackMapping(tracks);\n\n await this.sendSdpOffer(sdpOffer, trackMapping, \"POST\");\n\n const answerResponse = await this.pollSdpAnswer();\n\n this.iceStartTime = performance.now();\n await webrtc.setRemoteDescription(\n this.peerConnection,\n answerResponse.sdp_answer\n );\n console.debug(\"[WebRTCTransport] Remote description set\");\n }\n\n async reconnect(tracks: TrackCapability[]): Promise<void> {\n this.setStatus(\"connecting\");\n\n this.stopPing();\n this.stopStatsPolling();\n\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = undefined;\n }\n if (this.peerConnection) {\n webrtc.closePeerConnection(this.peerConnection);\n this.peerConnection = undefined;\n }\n this.peerConnected = false;\n this.dataChannelOpen = false;\n this.resetTransportTimings();\n\n const iceServers = await this.fetchIceServers();\n\n this.peerConnection = webrtc.createPeerConnection({ iceServers });\n this.setupPeerConnectionHandlers();\n\n this.dataChannel = webrtc.createDataChannel(this.peerConnection);\n this.setupDataChannelHandlers();\n\n this.transceiverMap.clear();\n for (const track of tracks) {\n const transceiver = this.peerConnection.addTransceiver(track.kind, {\n direction: track.direction,\n });\n this.transceiverMap.set(track.name, {\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n transceiver,\n });\n }\n\n const sdpOffer = await webrtc.createOffer(this.peerConnection);\n const trackMapping = this.buildTrackMapping(tracks);\n\n await this.sendSdpOffer(sdpOffer, trackMapping, \"PUT\");\n\n const answerResponse = await this.pollSdpAnswer();\n\n this.iceStartTime = performance.now();\n await webrtc.setRemoteDescription(\n this.peerConnection,\n answerResponse.sdp_answer\n );\n console.debug(\"[WebRTCTransport] Remote description set (reconnect)\");\n }\n\n async disconnect(): Promise<void> {\n this.stopPing();\n this.stopStatsPolling();\n\n for (const name of Array.from(this.publishedTracks.keys())) {\n await this.unpublishTrack(name);\n }\n\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = undefined;\n }\n\n if (this.peerConnection) {\n webrtc.closePeerConnection(this.peerConnection);\n this.peerConnection = undefined;\n }\n\n this.transceiverMap.clear();\n this.peerConnected = false;\n this.dataChannelOpen = false;\n this.resetTransportTimings();\n this.setStatus(\"disconnected\");\n console.debug(\"[WebRTCTransport] Disconnected\");\n }\n\n abort(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n getStatus(): TransportStatus {\n return this.status;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Track Mapping\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Builds the track_mapping array from capabilities + transceiver MIDs.\n * Must be called after createOffer + setLocalDescription so that\n * transceiver.mid is assigned.\n */\n private buildTrackMapping(tracks: TrackCapability[]): TrackMappingEntry[] {\n return tracks.map((track) => {\n const entry = this.transceiverMap.get(track.name);\n const mid = entry?.transceiver?.mid;\n if (mid == null) {\n throw new Error(\n `Cannot build track mapping: transceiver \"${track.name}\" has no MID. ` +\n `Was createOffer() called?`\n );\n }\n return {\n mid,\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n };\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Messaging\n // ─────────────────────────────────────────────────────────────────────────\n\n private get maxMessageBytes(): number | undefined {\n return this.peerConnection?.sctp?.maxMessageSize ?? undefined;\n }\n\n sendCommand(\n command: string,\n data: any,\n scope: MessageScope = \"application\"\n ): void {\n if (!this.dataChannel) {\n throw new Error(\"[WebRTCTransport] Data channel not available\");\n }\n\n try {\n webrtc.sendMessage(\n this.dataChannel,\n command,\n data,\n scope,\n this.maxMessageBytes\n );\n } catch (error) {\n console.warn(\"[WebRTCTransport] Failed to send message:\", error);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Track Publishing\n // ─────────────────────────────────────────────────────────────────────────\n\n async publishTrack(name: string, track: MediaStreamTrack): Promise<void> {\n if (!this.peerConnection) {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - not initialized`\n );\n }\n\n if (this.status !== \"connected\") {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - not connected`\n );\n }\n\n const entry = this.transceiverMap.get(name);\n if (!entry || !entry.transceiver) {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - no transceiver ` +\n `(was it declared in capabilities?)`\n );\n }\n\n if (entry.direction === \"recvonly\") {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - transceiver is recvonly`\n );\n }\n\n await entry.transceiver.sender.replaceTrack(track);\n this.publishedTracks.set(name, track);\n console.debug(`[WebRTCTransport] Track \"${name}\" published successfully`);\n }\n\n async unpublishTrack(name: string): Promise<void> {\n const entry = this.transceiverMap.get(name);\n if (!entry?.transceiver || !this.publishedTracks.has(name)) return;\n\n try {\n await entry.transceiver.sender.replaceTrack(null);\n console.debug(\n `[WebRTCTransport] Track \"${name}\" unpublished successfully`\n );\n } catch (error) {\n console.error(\n `[WebRTCTransport] Failed to unpublish track \"${name}\":`,\n error\n );\n throw error;\n } finally {\n this.publishedTracks.delete(name);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Stats\n // ─────────────────────────────────────────────────────────────────────────\n\n getStats(): ConnectionStats | undefined {\n return this.stats;\n }\n\n getTransportTimings(): WebRTCTransportTimings | undefined {\n if (this.iceNegotiationMs == null || this.dataChannelMs == null) {\n return undefined;\n }\n return {\n protocol: \"webrtc\",\n sdpPollingMs: this.sdpPollingMs ?? 0,\n sdpPollingAttempts: this.sdpPollingAttempts ?? 0,\n iceNegotiationMs: this.iceNegotiationMs,\n dataChannelMs: this.dataChannelMs,\n };\n }\n\n private resetTransportTimings(): void {\n this.iceStartTime = undefined;\n this.iceNegotiationMs = undefined;\n this.dataChannelMs = undefined;\n this.sdpPollingMs = undefined;\n this.sdpPollingAttempts = undefined;\n }\n\n private startStatsPolling(): void {\n this.stopStatsPolling();\n this.statsInterval = setInterval(async () => {\n if (!this.peerConnection) return;\n try {\n const report = await this.peerConnection.getStats();\n this.stats = webrtc.extractConnectionStats(report);\n this.emit(\"statsUpdate\", this.stats);\n } catch {\n // Connection may be closing\n }\n }, STATS_INTERVAL_MS);\n }\n\n private stopStatsPolling(): void {\n if (this.statsInterval !== undefined) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n this.stats = undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Ping (Client Liveness)\n // ─────────────────────────────────────────────────────────────────────────\n\n private startPing(): void {\n this.stopPing();\n this.pingInterval = setInterval(() => {\n if (this.dataChannel?.readyState === \"open\") {\n try {\n webrtc.sendMessage(this.dataChannel, \"ping\", {}, \"runtime\");\n } catch {\n // Data channel may be closing\n }\n }\n }, PING_INTERVAL_MS);\n }\n\n private stopPing(): void {\n if (this.pingInterval !== undefined) {\n clearInterval(this.pingInterval);\n this.pingInterval = undefined;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Internal Helpers\n // ─────────────────────────────────────────────────────────────────────────\n\n private checkFullyConnected(): void {\n if (this.peerConnected && this.dataChannelOpen) {\n this.setStatus(\"connected\");\n this.startStatsPolling();\n }\n }\n\n private setStatus(newStatus: TransportStatus): void {\n if (this.status !== newStatus) {\n this.status = newStatus;\n this.emit(\"statusChanged\", newStatus);\n }\n }\n\n private setupPeerConnectionHandlers(): void {\n if (!this.peerConnection) return;\n\n this.peerConnection.onconnectionstatechange = () => {\n const state = this.peerConnection?.connectionState;\n console.debug(\"[WebRTCTransport] Connection state:\", state);\n\n if (state) {\n switch (state) {\n case \"connected\":\n if (this.iceStartTime != null && this.iceNegotiationMs == null) {\n this.iceNegotiationMs = performance.now() - this.iceStartTime;\n }\n this.peerConnected = true;\n this.checkFullyConnected();\n break;\n case \"disconnected\":\n case \"closed\":\n this.peerConnected = false;\n this.setStatus(\"disconnected\");\n break;\n case \"failed\":\n this.peerConnected = false;\n this.setStatus(\"error\");\n break;\n }\n }\n };\n\n this.peerConnection.ontrack = (event) => {\n let trackName: string | undefined;\n for (const [name, entry] of this.transceiverMap) {\n if (entry.transceiver === event.transceiver) {\n trackName = name;\n break;\n }\n }\n trackName ??= event.transceiver.mid ?? `unknown-${event.track.id}`;\n\n console.debug(\n `[WebRTCTransport] Track received: \"${trackName}\" (${event.track.kind}, mid=${event.transceiver.mid})`\n );\n const stream = event.streams[0] ?? new MediaStream([event.track]);\n this.emit(\"trackReceived\", trackName, event.track, stream);\n };\n\n this.peerConnection.onicecandidate = (event) => {\n if (event.candidate) {\n console.debug(\"[WebRTCTransport] ICE candidate:\", event.candidate);\n }\n };\n\n this.peerConnection.onicecandidateerror = (event) => {\n console.warn(\"[WebRTCTransport] ICE candidate error:\", event);\n };\n\n this.peerConnection.ondatachannel = (event) => {\n console.debug(\"[WebRTCTransport] Data channel received from remote\");\n this.dataChannel = event.channel;\n this.setupDataChannelHandlers();\n };\n }\n\n private setupDataChannelHandlers(): void {\n if (!this.dataChannel) return;\n\n this.dataChannel.onopen = () => {\n console.debug(\"[WebRTCTransport] Data channel open\");\n if (this.iceStartTime != null && this.dataChannelMs == null) {\n this.dataChannelMs = performance.now() - this.iceStartTime;\n }\n this.dataChannelOpen = true;\n this.startPing();\n this.checkFullyConnected();\n };\n\n this.dataChannel.onclose = () => {\n console.debug(\"[WebRTCTransport] Data channel closed\");\n this.dataChannelOpen = false;\n this.stopPing();\n };\n\n this.dataChannel.onerror = (error) => {\n console.error(\"[WebRTCTransport] Data channel error:\", error);\n };\n\n this.dataChannel.onmessage = (event) => {\n const rawData = webrtc.parseMessage(event.data) as any;\n console.debug(\"[WebRTCTransport] Received message:\", rawData);\n\n try {\n if (rawData?.scope === \"application\" && rawData?.data !== undefined) {\n this.emit(\"message\", rawData.data, \"application\" as MessageScope);\n } else if (\n rawData?.scope === \"runtime\" &&\n rawData?.data !== undefined\n ) {\n this.emit(\"message\", rawData.data, \"runtime\" as MessageScope);\n } else {\n console.warn(\n \"[WebRTCTransport] Received message without envelope, treating as application\"\n );\n this.emit(\"message\", rawData, \"application\" as MessageScope);\n }\n } catch (error) {\n console.error(\n \"[WebRTCTransport] Failed to parse/validate message:\",\n error\n );\n }\n };\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\nimport {\n type ReactorEvent,\n type ReactorStatus,\n type ReactorState,\n type ReactorError,\n type MessageScope,\n type ConnectOptions,\n type ConnectionStats,\n type ConnectionTimings,\n isAbortError,\n} from \"../types\";\nimport { CoordinatorClient } from \"./CoordinatorClient\";\nimport { LocalCoordinatorClient } from \"./LocalCoordinatorClient\";\nimport { type TransportClient, type TransportStatus } from \"./TransportClient\";\nimport { WebRTCTransportClient } from \"./WebRTCTransportClient\";\nimport {\n type Capabilities,\n type CreateSessionResponse,\n type TrackCapability,\n REACTOR_WEBRTC_VERSION,\n} from \"./types\";\nimport { z } from \"zod\";\n\nconst LOCAL_COORDINATOR_URL = \"http://localhost:8080\";\nexport const DEFAULT_BASE_URL = \"https://api.reactor.inc\";\n\nconst OptionsSchema = z.object({\n apiUrl: z.string().default(DEFAULT_BASE_URL),\n modelName: z.string(),\n local: z.boolean().default(false),\n});\nexport type Options = z.input<typeof OptionsSchema>;\n\ntype EventHandler = (...args: any[]) => void;\n\nexport class Reactor {\n private coordinatorClient: CoordinatorClient | undefined;\n private transportClient: TransportClient | undefined;\n private status: ReactorStatus = \"disconnected\";\n private coordinatorUrl: string;\n private lastError?: ReactorError;\n private model: string;\n private sessionExpiration?: number;\n private local: boolean;\n private sessionId?: string;\n private connectStartTime?: number;\n private connectionTimings?: ConnectionTimings;\n\n private capabilities?: Capabilities;\n private tracks: TrackCapability[] = [];\n private sessionResponse?: CreateSessionResponse;\n\n constructor(options: Options) {\n const validatedOptions = OptionsSchema.parse(options);\n this.coordinatorUrl = validatedOptions.apiUrl;\n this.model = validatedOptions.modelName;\n this.local = validatedOptions.local;\n if (this.local && options.apiUrl === undefined) {\n this.coordinatorUrl = LOCAL_COORDINATOR_URL;\n }\n }\n\n private eventListeners: Map<ReactorEvent, Set<EventHandler>> = new Map();\n\n on(event: ReactorEvent, handler: EventHandler) {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(handler);\n }\n\n off(event: ReactorEvent, handler: EventHandler) {\n this.eventListeners.get(event)?.delete(handler);\n }\n\n emit(event: ReactorEvent, ...args: any[]) {\n this.eventListeners.get(event)?.forEach((handler) => handler(...args));\n }\n\n /**\n * Sends a command to the model via the data channel.\n */\n async sendCommand(\n command: string,\n data: any,\n scope: MessageScope = \"application\"\n ): Promise<void> {\n if (process.env.NODE_ENV !== \"development\" && this.status !== \"ready\") {\n const errorMessage = `Cannot send message, status is ${this.status}`;\n console.warn(\"[Reactor]\", errorMessage);\n return;\n }\n\n try {\n this.transportClient?.sendCommand(command, data, scope);\n } catch (error) {\n console.error(\"[Reactor] Failed to send message:\", error);\n this.createError(\n \"MESSAGE_SEND_FAILED\",\n `Failed to send message: ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n /**\n * Publishes a MediaStreamTrack to a named sendonly track.\n * The transceiver is already set up from capabilities — this just\n * calls replaceTrack() on the sender.\n */\n async publishTrack(name: string, track: MediaStreamTrack): Promise<void> {\n if (process.env.NODE_ENV !== \"development\" && this.status !== \"ready\") {\n console.warn(\n `[Reactor] Cannot publish track \"${name}\", status is ${this.status}`\n );\n return;\n }\n\n try {\n await this.transportClient?.publishTrack(name, track);\n } catch (error) {\n console.error(`[Reactor] Failed to publish track \"${name}\":`, error);\n this.createError(\n \"TRACK_PUBLISH_FAILED\",\n `Failed to publish track \"${name}\": ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n async unpublishTrack(name: string): Promise<void> {\n try {\n await this.transportClient?.unpublishTrack(name);\n } catch (error) {\n console.error(`[Reactor] Failed to unpublish track \"${name}\":`, error);\n this.createError(\n \"TRACK_UNPUBLISH_FAILED\",\n `Failed to unpublish track \"${name}\": ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n /**\n * Reconnects to an existing session with a fresh transport.\n */\n async reconnect(options?: ConnectOptions): Promise<void> {\n if (!this.sessionId || !this.coordinatorClient) {\n console.warn(\"[Reactor] No active session to reconnect to.\");\n return;\n }\n\n if (this.status === \"ready\") {\n console.warn(\"[Reactor] Already connected, no need to reconnect.\");\n return;\n }\n\n if (this.tracks.length === 0) {\n console.warn(\"[Reactor] No tracks available for reconnect.\");\n return;\n }\n\n this.setStatus(\"connecting\");\n\n try {\n if (!this.transportClient) {\n this.transportClient = new WebRTCTransportClient({\n baseUrl: this.coordinatorUrl,\n sessionId: this.sessionId,\n jwtToken: this.local ? \"local\" : \"\",\n maxPollAttempts: options?.maxAttempts,\n });\n this.setupTransportHandlers();\n }\n\n await this.transportClient.reconnect(this.tracks);\n } catch (error) {\n if (isAbortError(error)) return;\n\n console.error(\"[Reactor] Failed to reconnect:\", error);\n this.disconnect(true);\n this.createError(\n \"RECONNECTION_FAILED\",\n `Failed to reconnect: ${error}`,\n \"api\",\n true\n );\n }\n }\n\n /**\n * Connects to the coordinator, creates a session, then establishes\n * the transport using server-declared capabilities.\n */\n async connect(jwtToken?: string, options?: ConnectOptions): Promise<void> {\n console.debug(\"[Reactor] Connecting, status:\", this.status);\n\n if (jwtToken == undefined && !this.local) {\n throw new Error(\"No authentication provided and not in local mode\");\n }\n\n if (this.status !== \"disconnected\") {\n throw new Error(\"Already connected or connecting\");\n }\n this.setStatus(\"connecting\");\n\n this.connectStartTime = performance.now();\n\n try {\n this.coordinatorClient = this.local\n ? new LocalCoordinatorClient(this.coordinatorUrl, this.model)\n : new CoordinatorClient({\n baseUrl: this.coordinatorUrl,\n jwtToken: jwtToken!,\n model: this.model,\n });\n\n // 1. Create session — slim response with session_id and status\n const tSession = performance.now();\n const initialResponse = await this.coordinatorClient.createSession();\n const sessionCreationMs = performance.now() - tSession;\n\n this.setSessionId(initialResponse.session_id);\n\n console.debug(\n \"[Reactor] Session created:\",\n initialResponse.session_id,\n \"state:\",\n initialResponse.state\n );\n\n // 2. Poll until the Runtime accepts and capabilities are available\n this.setStatus(\"waiting\");\n\n const tPoll = performance.now();\n const sessionResponse = await this.coordinatorClient.pollSessionReady();\n const sessionPollingMs = performance.now() - tPoll;\n\n this.sessionResponse = sessionResponse;\n\n // 3. Store capabilities and tracks\n this.capabilities = sessionResponse.capabilities;\n this.tracks = sessionResponse.capabilities.tracks;\n this.emit(\"capabilitiesReceived\", this.capabilities);\n\n console.debug(\n \"[Reactor] Session ready, transport:\",\n sessionResponse.selected_transport.protocol,\n \"tracks:\",\n this.tracks.length\n );\n\n // 4. Instantiate transport based on selected_transport\n const protocol = sessionResponse.selected_transport.protocol;\n if (protocol !== \"webrtc\") {\n throw new Error(`Unsupported transport protocol: ${protocol}`);\n }\n\n this.transportClient = new WebRTCTransportClient({\n baseUrl: this.coordinatorUrl,\n sessionId: sessionResponse.session_id,\n jwtToken: this.local ? \"local\" : jwtToken!,\n webrtcVersion:\n sessionResponse.selected_transport.version ?? REACTOR_WEBRTC_VERSION,\n maxPollAttempts: options?.maxAttempts,\n });\n this.setupTransportHandlers();\n\n // 5. Connect transport using capabilities tracks\n const tTransport = performance.now();\n await this.transportClient.connect(this.tracks);\n const transportConnectingMs = performance.now() - tTransport;\n\n this.connectionTimings = {\n sessionCreationMs: sessionCreationMs + sessionPollingMs,\n transportConnectingMs,\n totalMs: 0,\n };\n } catch (error) {\n if (isAbortError(error)) return;\n\n console.error(\"[Reactor] Connection failed:\", error);\n this.createError(\n \"CONNECTION_FAILED\",\n `Connection failed: ${error}`,\n \"api\",\n true\n );\n try {\n await this.disconnect(false);\n } catch (disconnectError) {\n console.error(\n \"[Reactor] Failed to clean up after connection failure:\",\n disconnectError\n );\n }\n throw error;\n }\n }\n\n /**\n * Sets up event handlers for the transport client.\n * Each handler captures the client reference to ignore stale events.\n */\n private setupTransportHandlers(): void {\n if (!this.transportClient) return;\n const client = this.transportClient;\n\n client.on(\"message\", (message: any, scope: MessageScope) => {\n if (this.transportClient !== client) return;\n if (scope === \"application\") {\n this.emit(\"message\", message);\n } else if (scope === \"runtime\") {\n this.emit(\"runtimeMessage\", message);\n }\n });\n\n client.on(\"statusChanged\", (status: TransportStatus) => {\n if (this.transportClient !== client) return;\n switch (status) {\n case \"connected\":\n this.finalizeConnectionTimings();\n this.setStatus(\"ready\");\n break;\n case \"disconnected\":\n this.disconnect(true);\n break;\n case \"error\":\n this.createError(\n \"GPU_CONNECTION_ERROR\",\n \"Transport connection failed\",\n \"gpu\",\n true\n );\n this.disconnect();\n break;\n }\n });\n\n client.on(\n \"trackReceived\",\n (name: string, track: MediaStreamTrack, stream: MediaStream) => {\n if (this.transportClient !== client) return;\n this.emit(\"trackReceived\", name, track, stream);\n }\n );\n\n client.on(\"statsUpdate\", (stats: ConnectionStats) => {\n if (this.transportClient !== client) return;\n this.emit(\"statsUpdate\", {\n ...stats,\n connectionTimings: this.connectionTimings,\n });\n });\n }\n\n /**\n * Disconnects from both the transport and the coordinator.\n */\n async disconnect(recoverable: boolean = false) {\n if (this.status === \"disconnected\" && !this.sessionId) {\n console.warn(\"[Reactor] Already disconnected\");\n return;\n }\n\n this.coordinatorClient?.abort();\n this.transportClient?.abort();\n\n if (this.coordinatorClient && !recoverable) {\n try {\n await this.coordinatorClient.terminateSession();\n } catch (error) {\n console.error(\"[Reactor] Error terminating session:\", error);\n }\n this.coordinatorClient = undefined;\n }\n\n if (this.transportClient) {\n try {\n await this.transportClient.disconnect();\n } catch (error) {\n console.error(\"[Reactor] Error disconnecting transport:\", error);\n }\n if (!recoverable) {\n this.transportClient = undefined;\n }\n }\n\n this.setStatus(\"disconnected\");\n this.resetConnectionTimings();\n if (!recoverable) {\n this.setSessionExpiration(undefined);\n this.setSessionId(undefined);\n this.capabilities = undefined;\n this.tracks = [];\n this.sessionResponse = undefined;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Getters\n // ─────────────────────────────────────────────────────────────────────────\n\n getSessionId(): string | undefined {\n return this.sessionId;\n }\n\n getStatus(): ReactorStatus {\n return this.status;\n }\n\n getState(): ReactorState {\n return {\n status: this.status,\n lastError: this.lastError,\n };\n }\n\n getLastError(): ReactorError | undefined {\n return this.lastError;\n }\n\n getCapabilities(): Capabilities | undefined {\n return this.capabilities;\n }\n\n getSessionInfo(): CreateSessionResponse | undefined {\n return this.sessionResponse;\n }\n\n getStats(): ConnectionStats | undefined {\n const stats = this.transportClient?.getStats();\n if (!stats) return undefined;\n return { ...stats, connectionTimings: this.connectionTimings };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Private State Management\n // ─────────────────────────────────────────────────────────────────────────\n\n private setSessionId(newSessionId: string | undefined) {\n console.debug(\n \"[Reactor] Setting session ID:\",\n newSessionId,\n \"from\",\n this.sessionId\n );\n if (this.sessionId !== newSessionId) {\n this.sessionId = newSessionId;\n this.emit(\"sessionIdChanged\", newSessionId);\n }\n }\n\n private setStatus(newStatus: ReactorStatus) {\n console.debug(\"[Reactor] Setting status:\", newStatus, \"from\", this.status);\n if (this.status !== newStatus) {\n this.status = newStatus;\n this.emit(\"statusChanged\", newStatus);\n }\n }\n\n private setSessionExpiration(newSessionExpiration: number | undefined) {\n console.debug(\n \"[Reactor] Setting session expiration:\",\n newSessionExpiration\n );\n if (this.sessionExpiration !== newSessionExpiration) {\n this.sessionExpiration = newSessionExpiration;\n this.emit(\"sessionExpirationChanged\", newSessionExpiration);\n }\n }\n\n private resetConnectionTimings(): void {\n this.connectStartTime = undefined;\n this.connectionTimings = undefined;\n }\n\n private finalizeConnectionTimings(): void {\n if (!this.connectionTimings || this.connectStartTime == null) return;\n\n this.connectionTimings.totalMs = performance.now() - this.connectStartTime;\n this.connectStartTime = undefined;\n\n console.debug(\"[Reactor] Connection timings:\", this.connectionTimings);\n }\n\n private createError(\n code: string,\n message: string,\n component: \"api\" | \"gpu\",\n recoverable: boolean,\n retryAfter?: number\n ) {\n this.lastError = {\n code,\n message,\n timestamp: Date.now(),\n recoverable,\n component,\n retryAfter,\n };\n this.emit(\"error\", this.lastError);\n }\n}\n","\"use client\";\n\nimport { ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport {\n createReactorStore,\n initReactorStore,\n ReactorContext,\n ReactorStore,\n ReactorStoreApi,\n type ReactorInitializationProps,\n} from \"../core/store\";\nimport { useStore } from \"zustand\";\nimport type { ConnectOptions } from \"../types\";\n\n/**\n * Options for the React provider's connect behavior.\n * Extends the core ConnectOptions with autoConnect for the React lifecycle.\n */\nexport interface ReactorConnectOptions extends ConnectOptions {\n /** Whether to automatically connect when the provider mounts. Default: false. */\n autoConnect?: boolean;\n}\n\n// Provider props\ninterface ReactorProviderProps extends ReactorInitializationProps {\n connectOptions?: ReactorConnectOptions;\n jwtToken?: string;\n children: ReactNode;\n}\n\n// tsx component\nexport function ReactorProvider({\n children,\n connectOptions,\n jwtToken,\n ...props\n}: ReactorProviderProps) {\n // Stable Reactor instance\n const storeRef = useRef<ReactorStoreApi | undefined>(undefined);\n const firstRender = useRef(true);\n // State to trigger re-renders when store changes\n const [_storeVersion, setStoreVersion] = useState(0);\n\n if (storeRef.current === undefined) {\n console.debug(\"[ReactorProvider] Creating new reactor store\");\n // We create the store without autoconnecting, to avoid duplicate connections.\n // We actually connect when the component is mounted, to be on sync with the react component lifecycle.\n storeRef.current = createReactorStore(\n initReactorStore({\n ...props,\n jwtToken,\n })\n );\n console.debug(\"[ReactorProvider] Reactor store created successfully\");\n }\n\n // Destructure connectOptions with defaults\n const { autoConnect = false, ...pollingOptions } = connectOptions ?? {};\n\n const { apiUrl, modelName, local } = props;\n const maxAttempts = pollingOptions.maxAttempts;\n\n // Handle page unload (refresh, close, navigate away) with non-recoverable disconnect\n useEffect(() => {\n const handleBeforeUnload = () => {\n console.debug(\n \"[ReactorProvider] Page unloading, performing non-recoverable disconnect\"\n );\n // Call disconnect synchronously - we can't await here as the page is unloading\n // The disconnect(false) ensures non-recoverable cleanup (stops session, clears state)\n storeRef.current?.getState().internal.reactor.disconnect(false);\n };\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\n\n return () => {\n window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n };\n }, []);\n\n useEffect(() => {\n if (firstRender.current) {\n firstRender.current = false;\n\n // We know as a fact that the store is not undefined at this point\n const current = storeRef.current!;\n if (\n autoConnect &&\n current.getState().status === \"disconnected\" &&\n jwtToken\n ) {\n console.debug(\n \"[ReactorProvider] Starting autoconnect in first render...\"\n );\n current\n .getState()\n .connect(jwtToken, pollingOptions)\n .then(() => {\n console.debug(\n \"[ReactorProvider] Autoconnect successful in first render\"\n );\n })\n .catch((error) => {\n console.error(\n \"[ReactorProvider] Failed to autoconnect in first render:\",\n error\n );\n });\n }\n return () => {\n console.debug(\n \"[ReactorProvider] Disconnecting in cleanup for first render\"\n );\n current\n .getState()\n .disconnect()\n .then(() => {\n console.debug(\n \"[ReactorProvider] Disconnect completed successfully in cleanup for first render\"\n );\n })\n .catch((error) => {\n console.error(\n \"[ReactorProvider] Failed to disconnect in cleanup for first render:\",\n error\n );\n });\n };\n }\n\n console.debug(\"[ReactorProvider] Updating reactor store\");\n storeRef.current = createReactorStore(\n initReactorStore({\n apiUrl,\n modelName,\n local,\n jwtToken,\n } satisfies ReactorInitializationProps)\n );\n\n // Store current reference to the store in the return\n const current = storeRef.current!;\n\n // Increment version to trigger re-render and propagate new store to Provider\n setStoreVersion((v) => v + 1);\n console.debug(\n \"[ReactorProvider] Reactor store updated successfully, and increased version\"\n );\n\n if (\n autoConnect &&\n current.getState().status === \"disconnected\" &&\n jwtToken\n ) {\n console.debug(\"[ReactorProvider] Starting autoconnect...\");\n current\n .getState()\n .connect(jwtToken, pollingOptions)\n .then(() => {\n console.debug(\"[ReactorProvider] Autoconnect successful\");\n })\n .catch((error) => {\n console.error(\"[ReactorProvider] Failed to autoconnect:\", error);\n });\n }\n\n return () => {\n console.debug(\"[ReactorProvider] Disconnecting in cleanup\");\n current\n .getState()\n .disconnect()\n .then(() => {\n console.debug(\n \"[ReactorProvider] Disconnect completed successfully in cleanup\"\n );\n })\n .catch((error) => {\n console.error(\"[ReactorProvider] Failed to disconnect:\", error);\n });\n };\n }, [apiUrl, modelName, autoConnect, local, jwtToken, maxAttempts]);\n\n return (\n <ReactorContext.Provider value={storeRef.current}>\n {children}\n </ReactorContext.Provider>\n );\n}\n\nexport function useReactorStore<T = ReactorStore>(\n selector: (state: ReactorStore) => T\n): T {\n const ctx = useContext(ReactorContext);\n if (!ctx) {\n throw new Error(\"useReactor must be used within a ReactorProvider\");\n }\n\n return useStore(ctx, selector);\n}\n","import { StoreApi } from \"zustand\";\nimport type {\n ReactorStatus,\n ReactorError,\n MessageScope,\n ConnectOptions,\n} from \"../types\";\nimport { Reactor, type Options as ReactorOptions } from \"./Reactor\";\nimport { create } from \"zustand/react\";\nimport { createContext } from \"react\";\n\nexport type ReactorStoreApi = ReturnType<typeof createReactorStore>;\n\nexport interface ReactorState {\n status: ReactorStatus;\n /**\n * Media tracks received from the model, keyed by track name.\n *\n * Each entry maps a recvonly track name (e.g. `\"main_video\"`,\n * `\"main_audio\"`) to the live `MediaStreamTrack` delivered by the model.\n */\n tracks: Record<string, MediaStreamTrack>;\n lastError?: ReactorError;\n sessionId?: string;\n sessionExpiration?: number;\n jwtToken?: string;\n}\n\nexport interface ReactorActions {\n sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;\n connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;\n disconnect(recoverable?: boolean): Promise<void>;\n publish(name: string, track: MediaStreamTrack): Promise<void>;\n unpublish(name: string): Promise<void>;\n reconnect(options?: ConnectOptions): Promise<void>;\n}\n\n// Internal state not exposed to components\ninterface ReactorInternalState {\n reactor: Reactor;\n}\n\nexport const ReactorContext = createContext<ReactorStoreApi | undefined>(\n undefined\n);\n\nexport type ReactorStore = ReactorState &\n ReactorActions & {\n internal: ReactorInternalState;\n };\n\n// We introduce two methods to perform authentication:\n// - putting the auth information inside of the ReactorProvider props, and then calling connect() without arguments.\n// - not putting anything in the props, and then calling connect() passing as arguments the auth information.\n// When in the first case, the auth information is saved in the STATE. Then, when you call connect() without arguments,\n// the actual auth information is fetched from that STATE.\n// In the second case, you pass the auth information directly into the function in the Reactor core.\nexport const defaultInitState: ReactorState = {\n status: \"disconnected\",\n tracks: {},\n lastError: undefined,\n sessionExpiration: undefined,\n jwtToken: undefined,\n sessionId: undefined,\n};\n\nexport interface ReactorInitializationProps extends ReactorOptions {\n jwtToken?: string;\n}\n\nexport const initReactorStore = (\n props: ReactorInitializationProps\n): ReactorState & ReactorInitializationProps => {\n return {\n ...defaultInitState,\n // These are only used for dev initialization, not exposed in the store\n ...props,\n };\n};\n\nexport const createReactorStore = (\n initProps: ReactorInitializationProps,\n publicState: ReactorState = defaultInitState\n): StoreApi<ReactorStore> => {\n console.debug(\"[ReactorStore] Creating store\", {\n apiUrl: initProps.apiUrl,\n jwtToken: initProps.jwtToken,\n initialState: publicState,\n });\n\n return create<ReactorStore>()((set, get) => {\n const reactor = new Reactor(initProps);\n\n console.debug(\"[ReactorStore] Setting up event listeners\");\n\n reactor.on(\"statusChanged\", (newStatus: ReactorStatus) => {\n console.debug(\"[ReactorStore] Status changed\", {\n oldStatus: get().status,\n newStatus,\n });\n if (newStatus === \"disconnected\") {\n set({ status: newStatus, tracks: {} });\n } else {\n set({ status: newStatus });\n }\n });\n\n reactor.on(\n \"sessionExpirationChanged\",\n (newSessionExpiration: number | undefined) => {\n console.debug(\"[ReactorStore] Session expiration changed\", {\n oldSessionExpiration: get().sessionExpiration,\n newSessionExpiration: newSessionExpiration,\n });\n set({ sessionExpiration: newSessionExpiration });\n }\n );\n\n reactor.on(\"trackReceived\", (name: string, track: MediaStreamTrack) => {\n console.debug(\"[ReactorStore] Track received\", {\n name,\n kind: track.kind,\n id: track.id,\n });\n set({ tracks: { ...get().tracks, [name]: track } });\n });\n\n reactor.on(\"error\", (error: ReactorError) => {\n console.debug(\"[ReactorStore] Error occurred\", error);\n set({ lastError: error });\n });\n\n reactor.on(\"sessionIdChanged\", (newSessionId: string | undefined) => {\n console.debug(\"[ReactorStore] Session ID changed\", {\n oldSessionId: get().sessionId,\n newSessionId: newSessionId,\n });\n set({ sessionId: newSessionId });\n });\n\n return {\n ...publicState,\n jwtToken: initProps.jwtToken,\n internal: { reactor },\n\n // actions\n onMessage: (handler: (message: any) => void) => {\n console.debug(\"[ReactorStore] Registering message handler\");\n\n get().internal.reactor.on(\"message\", handler);\n\n return () => {\n console.debug(\"[ReactorStore] Cleaning up message handler\");\n get().internal.reactor.off(\"message\", handler);\n };\n },\n sendCommand: async (command: string, data: any, scope?: MessageScope) => {\n console.debug(\"[ReactorStore] Sending command\", {\n command,\n data,\n scope,\n });\n try {\n await get().internal.reactor.sendCommand(command, data, scope);\n console.debug(\"[ReactorStore] Command sent successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Failed to send command:\", error);\n throw error;\n }\n },\n connect: async (jwtToken?: string, options?: ConnectOptions) => {\n if (jwtToken === undefined) {\n // If no JWT Token, it might have been passed in the constructor props. So read from it.\n jwtToken = get().jwtToken;\n }\n\n console.debug(\"[ReactorStore] Connect called.\");\n\n try {\n await get().internal.reactor.connect(jwtToken, options);\n console.debug(\"[ReactorStore] Connect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Connect failed:\", error);\n throw error;\n }\n },\n disconnect: async (recoverable: boolean = false) => {\n console.debug(\"[ReactorStore] Disconnect called\", {\n currentStatus: get().status,\n });\n\n try {\n await get().internal.reactor.disconnect(recoverable);\n console.debug(\"[ReactorStore] Disconnect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Disconnect failed:\", error);\n throw error;\n }\n },\n publish: async (name: string, track: MediaStreamTrack) => {\n console.debug(`[ReactorStore] Publishing track \"${name}\"`);\n\n try {\n await get().internal.reactor.publishTrack(name, track);\n console.debug(\n `[ReactorStore] Track \"${name}\" published successfully`\n );\n } catch (error) {\n console.error(\n `[ReactorStore] Failed to publish track \"${name}\":`,\n error\n );\n throw error;\n }\n },\n unpublish: async (name: string) => {\n console.debug(`[ReactorStore] Unpublishing track \"${name}\"`);\n\n try {\n await get().internal.reactor.unpublishTrack(name);\n console.debug(\n `[ReactorStore] Track \"${name}\" unpublished successfully`\n );\n } catch (error) {\n console.error(\n `[ReactorStore] Failed to unpublish track \"${name}\":`,\n error\n );\n throw error;\n }\n },\n reconnect: async (options?: ConnectOptions) => {\n console.debug(\"[ReactorStore] Reconnecting\");\n try {\n await get().internal.reactor.reconnect(options);\n console.debug(\"[ReactorStore] Reconnect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Failed to reconnect:\", error);\n throw error;\n }\n },\n };\n });\n};\n","import { useReactorStore } from \"./ReactorProvider\";\nimport type { ReactorStore } from \"../core/store\";\nimport type { ConnectionStats } from \"../types\";\nimport { useShallow } from \"zustand/shallow\";\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Generic hook for accessing selected parts of the Reactor store.\n *\n * @param selector - A function that selects part of the store state.\n * @returns The selected slice from the store.\n */\nexport function useReactor<T>(selector: (state: ReactorStore) => T): T {\n return useReactorStore(useShallow(selector));\n}\n\n/**\n * Hook for receiving model application messages.\n *\n * Only fires for messages sent by the model via `get_ctx().send()`.\n * Internal platform-level messages (e.g. capabilities) are NOT delivered here.\n *\n * @param handler - Callback invoked with each application message payload.\n */\nexport function useReactorMessage(handler: (message: any) => void): void {\n const reactor = useReactor((state) => state.internal.reactor);\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const stableHandler = (message: any) => {\n handlerRef.current(message);\n };\n\n reactor.on(\"message\", stableHandler);\n\n return () => {\n reactor.off(\"message\", stableHandler);\n };\n }, [reactor]);\n}\n\n/**\n * Hook for receiving internal platform-level (runtime) messages.\n *\n * This is intended for advanced use cases that need access to the runtime\n * control layer, such as capabilities negotiation. Model application messages\n * sent via `get_ctx().send()` are NOT delivered through this hook — use\n * {@link useReactorMessage} for those.\n *\n * @param handler - Callback invoked with each runtime message payload.\n */\nexport function useReactorInternalMessage(\n handler: (message: any) => void\n): void {\n const reactor = useReactor((state) => state.internal.reactor);\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const stableHandler = (message: any) => {\n handlerRef.current(message);\n };\n\n reactor.on(\"runtimeMessage\", stableHandler);\n\n return () => {\n reactor.off(\"runtimeMessage\", stableHandler);\n };\n }, [reactor]);\n}\n\n/**\n * Hook that returns the current connection stats (RTT, etc.).\n * Updates every ~2s while connected. Returns undefined when disconnected.\n */\nexport function useStats(): ConnectionStats | undefined {\n const reactor = useReactor((state) => state.internal.reactor);\n const [stats, setStats] = useState<ConnectionStats | undefined>(undefined);\n\n useEffect(() => {\n const handler = (newStats: ConnectionStats) => {\n setStats(newStats);\n };\n\n reactor.on(\"statsUpdate\", handler);\n\n return () => {\n reactor.off(\"statsUpdate\", handler);\n setStats(undefined);\n };\n }, [reactor]);\n\n return stats;\n}\n","\"use client\";\n\nimport { useReactor } from \"./hooks\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport React from \"react\";\n\nexport interface ReactorViewProps {\n /**\n * The name of the recvonly track to render.\n * Must match a track name declared in the server capabilities.\n * Check the model's documentation for available track names.\n * Defaults to `\"main_video\"`.\n */\n track?: string;\n /**\n * Optional name of a recvonly audio track to play alongside the video\n * (e.g. `\"main_audio\"`). The audio is mixed into the same `<video>` element.\n * Check the model's documentation for available track names.\n */\n audioTrack?: string;\n width?: number;\n height?: number;\n className?: string;\n style?: React.CSSProperties;\n videoObjectFit?: NonNullable<\n React.VideoHTMLAttributes<HTMLVideoElement>[\"style\"]\n >[\"objectFit\"];\n /** Controls whether inbound audio plays. Default true (muted) to satisfy browser autoplay policies. */\n muted?: boolean;\n}\n\nexport function ReactorView({\n track = \"main_video\",\n audioTrack,\n width,\n height,\n className,\n style,\n videoObjectFit = \"contain\",\n muted = true,\n}: ReactorViewProps) {\n const { videoMediaTrack, audioMediaTrack, status } = useReactor((state) => ({\n videoMediaTrack: state.tracks[track] ?? null,\n audioMediaTrack: audioTrack ? (state.tracks[audioTrack] ?? null) : null,\n status: state.status,\n }));\n\n const videoRef = useRef<HTMLVideoElement>(null);\n\n const mediaStream = useMemo(() => {\n const tracks: MediaStreamTrack[] = [];\n if (videoMediaTrack) tracks.push(videoMediaTrack);\n if (audioMediaTrack) tracks.push(audioMediaTrack);\n if (tracks.length === 0) return null;\n return new MediaStream(tracks);\n }, [videoMediaTrack, audioMediaTrack]);\n\n useEffect(() => {\n console.debug(\"[ReactorView] Media track effect triggered\", {\n track,\n hasVideoElement: !!videoRef.current,\n hasVideoTrack: !!videoMediaTrack,\n hasAudioTrack: !!audioMediaTrack,\n });\n\n if (videoRef.current && mediaStream) {\n console.debug(\"[ReactorView] Attaching media stream to element\");\n try {\n videoRef.current.srcObject = mediaStream;\n videoRef.current.play().catch((e) => {\n console.warn(\"[ReactorView] Auto-play failed:\", e);\n });\n console.debug(\"[ReactorView] Media stream attached successfully\");\n } catch (error) {\n console.error(\"[ReactorView] Failed to attach media stream:\", error);\n }\n\n return () => {\n console.debug(\"[ReactorView] Detaching media stream from element\");\n if (videoRef.current) {\n videoRef.current.srcObject = null;\n }\n };\n } else {\n console.debug(\"[ReactorView] No tracks or element to attach\");\n }\n }, [mediaStream]);\n\n const showPlaceholder = !videoMediaTrack;\n\n return (\n <div\n style={{\n position: \"relative\",\n background: \"#000\",\n ...(width && { width }),\n ...(height && { height }),\n ...style,\n }}\n className={className}\n >\n <video\n ref={videoRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: videoObjectFit,\n display: showPlaceholder ? \"none\" : \"block\",\n }}\n muted={muted}\n playsInline\n />\n {showPlaceholder && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"16px\",\n fontFamily: \"monospace\",\n textAlign: \"center\",\n padding: \"20px\",\n boxSizing: \"border-box\",\n }}\n >\n {status}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useReactor, useReactorInternalMessage } from \"./hooks\";\nimport React, { useState, useCallback } from \"react\";\n\nexport interface ReactorControllerProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface CommandParamSchema {\n description?: string;\n type: string;\n minimum?: number;\n maximum?: number;\n required?: boolean;\n enum?: string[];\n}\n\ninterface CommandSchema {\n description: string;\n schema: Record<string, CommandParamSchema>;\n}\n\n// The runtime sends commands as a list of {name, description, schema}\n// matching the proto Command message.\ninterface CommandCapabilityMessage {\n name: string;\n description: string;\n schema?: Record<string, CommandParamSchema>;\n}\n\ninterface CommandsMessage {\n commands: CommandCapabilityMessage[];\n}\n\nexport function ReactorController({\n className,\n style,\n}: ReactorControllerProps) {\n const { sendCommand, status } = useReactor((state) => ({\n sendCommand: state.sendCommand,\n status: state.status,\n }));\n const [commands, setCommands] = useState<Record<string, CommandSchema>>({});\n const [formValues, setFormValues] = useState<\n Record<string, Record<string, any>>\n >({});\n const [expandedCommands, setExpandedCommands] = useState<\n Record<string, boolean>\n >({});\n\n // Reset commands when disconnected\n React.useEffect(() => {\n if (status === \"disconnected\") {\n setCommands({});\n setFormValues({});\n setExpandedCommands({});\n }\n }, [status]);\n\n // Function to request capabilities (sent on the \"runtime\" channel)\n const requestCapabilities = useCallback(() => {\n if (status === \"ready\") {\n sendCommand(\"requestCapabilities\", {}, \"runtime\");\n }\n }, [status, sendCommand]);\n\n // Send requestCapabilities when ready\n React.useEffect(() => {\n if (status === \"ready\") {\n requestCapabilities();\n }\n }, [status, requestCapabilities]);\n\n // Retry every 5 seconds if capabilities not set\n React.useEffect(() => {\n // Only set up interval if status is ready and commands are empty\n if (status !== \"ready\" || Object.keys(commands).length > 0) {\n return;\n }\n\n const interval = setInterval(() => {\n requestCapabilities();\n }, 5000);\n\n return () => clearInterval(interval);\n }, [status, commands, requestCapabilities]);\n\n useReactorInternalMessage((message) => {\n if (\n message &&\n typeof message === \"object\" &&\n message.type === \"modelCapabilities\" &&\n message.data &&\n \"commands\" in message.data\n ) {\n const commandsMessage = message.data as CommandsMessage;\n\n // Convert the list of command descriptors (proto Command shape)\n // into a Record keyed by name for the controller's internal state.\n const commandsRecord: Record<string, CommandSchema> = {};\n for (const cmd of commandsMessage.commands) {\n commandsRecord[cmd.name] = {\n description: cmd.description,\n schema: cmd.schema ?? {},\n };\n }\n setCommands(commandsRecord);\n\n // Initialize form values for each command\n const initialValues: Record<string, Record<string, any>> = {};\n const initialExpanded: Record<string, boolean> = {};\n\n Object.entries(commandsRecord).forEach(([commandName, commandSchema]) => {\n initialValues[commandName] = {};\n initialExpanded[commandName] = false;\n\n Object.entries(commandSchema.schema).forEach(\n ([paramName, paramSchema]) => {\n if (paramSchema.type === \"number\") {\n initialValues[commandName][paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"string\") {\n initialValues[commandName][paramName] = \"\";\n } else if (paramSchema.type === \"boolean\") {\n initialValues[commandName][paramName] = false;\n } else if (paramSchema.type === \"integer\") {\n initialValues[commandName][paramName] = paramSchema.minimum ?? 0;\n }\n }\n );\n });\n setFormValues(initialValues);\n setExpandedCommands(initialExpanded);\n }\n });\n\n const handleInputChange = useCallback(\n (commandName: string, paramName: string, value: any) => {\n setFormValues((prev) => ({\n ...prev,\n [commandName]: {\n ...prev[commandName],\n [paramName]: value,\n },\n }));\n },\n []\n );\n\n const toggleCommandExpanded = useCallback((commandName: string) => {\n setExpandedCommands((prev) => ({\n ...prev,\n [commandName]: !prev[commandName],\n }));\n }, []);\n\n const handleCommandSubmit = useCallback(\n async (commandName: string) => {\n const commandSchema = commands[commandName];\n const formData = formValues[commandName] || {};\n\n // Build the data object according to the schema structure\n const data: Record<string, any> = {};\n\n // Only include parameters that are defined in the schema\n Object.keys(commandSchema.schema).forEach((paramName) => {\n const paramSchema = commandSchema.schema[paramName];\n let value = formData[paramName];\n\n // Type conversion based on schema\n if (paramSchema.type === \"number\" && typeof value === \"string\") {\n value = parseFloat(value) || 0;\n } else if (\n paramSchema.type === \"integer\" &&\n typeof value === \"string\"\n ) {\n value = parseInt(value) || 0;\n } else if (\n paramSchema.type === \"boolean\" &&\n typeof value !== \"boolean\"\n ) {\n value = Boolean(value);\n }\n\n // Only include the parameter if it has a value or is required\n if (value !== undefined && value !== \"\" && value !== null) {\n data[paramName] = value;\n } else if (paramSchema.required) {\n // Set default values for required parameters\n if (paramSchema.type === \"number\") {\n data[paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"integer\") {\n data[paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"string\") {\n data[paramName] = \"\";\n } else if (paramSchema.type === \"boolean\") {\n data[paramName] = false;\n }\n }\n });\n\n console.log(`Executing command: ${commandName}`, data);\n\n await sendCommand(commandName, data);\n },\n [formValues, sendCommand, commands]\n );\n\n const renderInput = (\n commandName: string,\n paramName: string,\n paramSchema: any\n ) => {\n const value = formValues[commandName]?.[paramName] ?? \"\";\n\n if (paramSchema.type === \"number\" || paramSchema.type === \"integer\") {\n const isInteger = paramSchema.type === \"integer\";\n const step = isInteger ? 1 : 0.1;\n const parseValue = isInteger ? parseInt : parseFloat;\n\n // Use slider if min/max are defined, otherwise use number input\n if (\n typeof paramSchema.minimum === \"number\" &&\n typeof paramSchema.maximum === \"number\"\n ) {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName} ({paramSchema.minimum} - {paramSchema.maximum})\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"range\"\n min={paramSchema.minimum}\n max={paramSchema.maximum}\n step={step}\n value={value}\n onChange={(e) => {\n const newValue = parseValue(e.target.value) || 0;\n handleInputChange(commandName, paramName, newValue);\n // Execute command immediately for sliders\n handleCommandSubmit(commandName);\n }}\n style={{ width: \"100%\", marginBottom: \"4px\" }}\n />\n <div style={{ fontSize: \"11px\", color: \"#888\" }}>\n Value: {value}\n </div>\n </div>\n );\n } else {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"number\"\n value={value}\n min={paramSchema.minimum}\n max={paramSchema.maximum}\n step={step}\n inputMode=\"numeric\"\n onChange={(e) => {\n const val = e.target.value;\n if (val === \"\" || val === \"-\") {\n // Allow empty or just minus sign while typing\n handleInputChange(commandName, paramName, val);\n } else {\n const parsed = parseValue(val);\n if (!isNaN(parsed)) {\n handleInputChange(commandName, paramName, parsed);\n }\n }\n }}\n onBlur={(e) => {\n // On blur, ensure we have a valid number\n const val = e.target.value;\n if (val === \"\" || val === \"-\") {\n handleInputChange(commandName, paramName, 0);\n }\n }}\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n />\n </div>\n );\n }\n } else if (paramSchema.type === \"string\") {\n if (paramSchema.enum) {\n // Dropdown for enum values\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <select\n value={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.value)\n }\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n >\n <option value=\"\">Select...</option>\n {paramSchema.enum.map((option: string) => (\n <option key={option} value={option}>\n {option}\n </option>\n ))}\n </select>\n </div>\n );\n } else {\n // Text input\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"text\"\n value={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.value)\n }\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n />\n </div>\n );\n }\n } else if (paramSchema.type === \"boolean\") {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{\n fontSize: \"12px\",\n color: \"#666\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.checked)\n }\n style={{ marginRight: \"6px\" }}\n />\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n </div>\n );\n }\n\n return null;\n };\n\n const renderCommand = (commandName: string, commandSchema: CommandSchema) => {\n const hasParams = Object.keys(commandSchema.schema).length > 0;\n const isExpanded = expandedCommands[commandName];\n\n // Check if this command has any slider inputs (number/integer with min/max)\n const hasSliderInputs = Object.values(commandSchema.schema).some(\n (paramSchema) =>\n (paramSchema.type === \"number\" || paramSchema.type === \"integer\") &&\n typeof paramSchema.minimum === \"number\" &&\n typeof paramSchema.maximum === \"number\"\n );\n\n // Don't show execute button if command has slider inputs (they execute automatically)\n const showExecuteButton = !hasSliderInputs;\n\n return (\n <div\n key={commandName}\n style={{\n border: \"1px solid #ddd\",\n borderRadius: \"4px\",\n marginBottom: \"8px\",\n backgroundColor: \"#fafafa\",\n }}\n >\n {/* Command Header - Always Visible */}\n <div\n onClick={() => toggleCommandExpanded(commandName)}\n style={{\n padding: \"8px 12px\",\n cursor: \"pointer\",\n borderBottom: isExpanded ? \"1px solid #ddd\" : \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div>\n <h4\n style={{\n margin: \"0\",\n fontSize: \"13px\",\n fontWeight: \"bold\",\n }}\n >\n {commandName}\n </h4>\n {isExpanded && commandSchema.description && (\n <p\n style={{ margin: \"4px 0 0 0\", fontSize: \"11px\", color: \"#666\" }}\n >\n {commandSchema.description}\n </p>\n )}\n </div>\n <div\n style={{\n fontSize: \"10px\",\n color: \"#999\",\n transform: isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\",\n transition: \"transform 0.2s\",\n }}\n >\n ▼\n </div>\n </div>\n\n {/* Command Content - Collapsible */}\n {isExpanded && (\n <div style={{ padding: \"12px\", paddingTop: \"0\" }}>\n {hasParams && (\n <div style={{ marginBottom: showExecuteButton ? \"12px\" : \"0\" }}>\n <div\n style={{\n marginBottom: \"8px\",\n fontSize: \"12px\",\n fontWeight: \"bold\",\n color: \"#555\",\n }}\n >\n Parameters:\n </div>\n {Object.entries(commandSchema.schema).map(\n ([paramName, paramSchema]) => (\n <div\n key={`${commandName}-${paramName}`}\n style={{ marginLeft: \"8px\" }}\n >\n {renderInput(commandName, paramName, paramSchema)}\n </div>\n )\n )}\n </div>\n )}\n\n {!hasParams && (\n <div\n style={{\n marginBottom: showExecuteButton ? \"12px\" : \"0\",\n marginTop: \"2px\",\n fontSize: \"11px\",\n color: \"#666\",\n fontStyle: \"italic\",\n }}\n >\n No parameters required\n </div>\n )}\n\n {showExecuteButton && (\n <button\n onClick={() => handleCommandSubmit(commandName)}\n style={{\n padding: \"8px 16px\",\n fontSize: \"12px\",\n backgroundColor: \"#007bff\",\n color: \"white\",\n border: \"none\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n fontWeight: \"bold\",\n }}\n >\n Execute {commandName}\n </button>\n )}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={className} style={style}>\n <div style={{ fontFamily: \"monospace\", fontSize: \"12px\" }}>\n {Object.keys(commands).length === 0 ? (\n <div style={{ padding: \"12px\", color: \"#666\", fontStyle: \"italic\" }}>\n Waiting for commands schema...\n </div>\n ) : (\n <div>\n <h3\n style={{\n margin: \"0 0 16px 0\",\n fontSize: \"16px\",\n fontWeight: \"bold\",\n }}\n >\n Reactor Commands\n </h3>\n {Object.entries(commands).map(([commandName, commandSchema]) => (\n <div key={commandName}>\n {renderCommand(commandName, commandSchema)}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useReactor } from \"./hooks\";\nimport { useEffect, useRef, useState } from \"react\";\nimport React from \"react\";\n\nexport interface WebcamStreamProps {\n /**\n * The name of the sendonly track to publish the webcam to.\n * Must match a track name declared in the server capabilities.\n * Check the model's documentation for available track names.\n */\n track: string;\n className?: string;\n style?: React.CSSProperties;\n videoConstraints?: MediaTrackConstraints;\n showWebcam?: boolean;\n videoObjectFit?: NonNullable<\n React.VideoHTMLAttributes<HTMLVideoElement>[\"style\"]\n >[\"objectFit\"];\n}\n\nexport function WebcamStream({\n track,\n className,\n style,\n videoConstraints = {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n },\n showWebcam = true,\n videoObjectFit = \"contain\",\n}: WebcamStreamProps) {\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [isPublishing, setIsPublishing] = useState(false);\n const [permissionDenied, setPermissionDenied] = useState(false);\n\n const { status, publish, unpublish, reactor } = useReactor((state) => ({\n status: state.status,\n publish: state.publish,\n unpublish: state.unpublish,\n reactor: state.internal.reactor,\n }));\n\n const videoRef = useRef<HTMLVideoElement>(null);\n\n // Start webcam\n const startWebcam = async () => {\n console.debug(\"[WebcamPublisher] Starting webcam\");\n\n try {\n const mediaStream = await navigator.mediaDevices.getUserMedia({\n video: videoConstraints,\n audio: false,\n });\n\n console.debug(\"[WebcamPublisher] Webcam started successfully\");\n setStream(mediaStream);\n setPermissionDenied(false);\n } catch (err) {\n console.error(\"[WebcamPublisher] Failed to start webcam:\", err);\n\n // Check if the error is a permission denial\n if (\n err instanceof DOMException &&\n (err.name === \"NotAllowedError\" || err.name === \"PermissionDeniedError\")\n ) {\n console.debug(\"[WebcamPublisher] Camera permission denied\");\n setPermissionDenied(true);\n }\n }\n };\n\n // Stop webcam\n const stopWebcam = async () => {\n console.debug(\"[WebcamPublisher] Stopping webcam\");\n\n // Unpublish if currently publishing\n try {\n await unpublish(track);\n console.debug(\"[WebcamPublisher] Unpublished before stopping\");\n } catch (err) {\n console.error(\"[WebcamPublisher] Error unpublishing before stop:\", err);\n }\n\n setIsPublishing(false);\n\n // Stop all tracks\n stream?.getTracks().forEach((t) => {\n t.stop();\n console.debug(\"[WebcamPublisher] Stopped track:\", t.kind);\n });\n setStream(null);\n\n console.debug(\"[WebcamPublisher] Webcam stopped\");\n };\n\n // Attach stream to video element\n useEffect(() => {\n console.debug(\"[WebcamPublisher] Stream effect triggered\", {\n hasVideoElement: !!videoRef.current,\n hasStream: !!stream,\n });\n\n if (!videoRef.current) {\n return;\n }\n\n if (stream) {\n console.debug(\"[WebcamPublisher] Attaching stream to video element\");\n videoRef.current.srcObject = stream;\n console.debug(\"[WebcamPublisher] Stream attached successfully\");\n } else {\n console.debug(\"[WebcamPublisher] Clearing video element\");\n videoRef.current.srcObject = null;\n }\n }, [stream]);\n\n // Auto-publish when reactor is ready and webcam is active\n useEffect(() => {\n if (!stream) {\n return;\n }\n\n if (status === \"ready\" && !isPublishing) {\n console.debug(\n \"[WebcamPublisher] Reactor ready, auto-publishing webcam stream\"\n );\n const videoTrack = stream.getVideoTracks()[0];\n if (videoTrack) {\n publish(track, videoTrack)\n .then(() => {\n console.debug(\"[WebcamPublisher] Auto-publish successful\");\n setIsPublishing(true);\n })\n .catch((err) => {\n console.error(\"[WebcamPublisher] Auto-publish failed:\", err);\n });\n }\n } else if (status !== \"ready\" && isPublishing) {\n console.debug(\"[WebcamPublisher] Reactor not ready, auto-unpublishing\");\n unpublish(track)\n .then(() => {\n console.debug(\"[WebcamPublisher] Auto-unpublish successful\");\n setIsPublishing(false);\n })\n .catch((err) => {\n console.error(\"[WebcamPublisher] Auto-unpublish failed:\", err);\n });\n }\n }, [status, stream, isPublishing, publish, unpublish, track]);\n\n // Listen for error events from Reactor\n useEffect(() => {\n const handleError = (error: any) => {\n console.debug(\"[WebcamPublisher] Received error event:\", error);\n\n // Handle track publish failures by resetting state\n if (error.code === \"TRACK_PUBLISH_FAILED\") {\n console.debug(\n \"[WebcamPublisher] Track publish failed, resetting isPublishing state\"\n );\n setIsPublishing(false);\n }\n };\n\n reactor.on(\"error\", handleError);\n\n return () => {\n reactor.off(\"error\", handleError);\n };\n }, [reactor]);\n\n // Reset publishing state when status changes away from ready\n useEffect(() => {\n if (status !== \"ready\") {\n console.debug(\n \"[WebcamPublisher] Status changed to\",\n status,\n \"- resetting isPublishing state\"\n );\n setIsPublishing(false);\n }\n }, [status, isPublishing]);\n\n // Auto-start webcam on mount and cleanup on unmount\n useEffect(() => {\n console.debug(\"[WebcamPublisher] Auto-starting webcam\");\n startWebcam();\n\n return () => {\n console.debug(\"[WebcamPublisher] Cleanup on unmount\");\n stopWebcam();\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const showPlaceholder = !stream;\n\n return (\n <div\n style={{\n display: showWebcam ? \"block\" : \"none\",\n position: \"relative\",\n background: \"#000\",\n ...style,\n }}\n className={className}\n >\n <video\n ref={videoRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: videoObjectFit,\n display: showPlaceholder ? \"none\" : \"block\",\n }}\n muted\n playsInline\n autoPlay\n />\n {showPlaceholder && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"16px\",\n fontFamily: \"monospace\",\n textAlign: \"center\",\n padding: \"20px\",\n boxSizing: \"border-box\",\n flexDirection: \"column\",\n gap: \"12px\",\n }}\n >\n {permissionDenied ? (\n <div style={{ fontSize: \"12px\", fontFamily: \"monospace\" }}>\n Camera access denied.\n <br />\n Please allow access in your browser settings.\n </div>\n ) : (\n <div style={{ fontSize: \"12px\", fontFamily: \"monospace\" }}>\n Starting camera...\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { DEFAULT_BASE_URL } from \"../core/Reactor\";\n\n/**\n * ⚠️ INSECURE: Fetches a JWT token directly from the client.\n *\n * WARNING: This function exposes your API key in client-side code.\n * Only use this for local development or testing purposes.\n * In production, call /tokens from your server and pass the JWT to your frontend.\n *\n * @param apiKey - Your Reactor API key (will be exposed in client code!)\n * @param apiUrl - Optional API URL, defaults to production\n * @returns string containing the JWT token\n */\nexport async function fetchInsecureToken(\n apiKey: string,\n apiUrl: string = DEFAULT_BASE_URL\n): Promise<string> {\n console.warn(\n \"[Reactor] ⚠️ SECURITY WARNING: fetchInsecureToken() exposes your API key in client-side code. \" +\n \"This should ONLY be used for local development or testing. \" +\n \"In production, fetch tokens from your server instead.\"\n );\n\n const response = await fetch(`${apiUrl}/tokens`, {\n method: \"GET\",\n headers: {\n \"Reactor-API-Key\": apiKey,\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to create token: ${response.status} ${error}`);\n }\n\n const { jwt } = await response.json();\n\n return jwt;\n}\n"],"mappings":"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","names":["import_zod","import_react","import_react","_a","current","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","React","_a","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/core/types.ts","../package.json","../src/core/CoordinatorClient.ts","../src/core/LocalCoordinatorClient.ts","../src/utils/webrtc.ts","../src/core/WebRTCTransportClient.ts","../src/core/Reactor.ts","../src/react/ReactorProvider.tsx","../src/core/store.ts","../src/react/hooks.ts","../src/react/ReactorView.tsx","../src/react/ReactorController.tsx","../src/react/WebcamStream.tsx"],"sourcesContent":["export * from \"./core/Reactor\";\nexport * from \"./react/ReactorProvider\";\nexport * from \"./react/ReactorView\";\nexport * from \"./react/ReactorController\";\nexport * from \"./react/WebcamStream\";\nexport * from \"./react/hooks\";\nexport * from \"./types\";\nexport type { ReactorStore } from \"./core/store\";\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\nexport type ReactorStatus =\n | \"disconnected\" // Not connected to anything\n | \"connecting\" // Establishing connection to coordinator\n | \"waiting\" // Connected to coordinator, waiting for GPU assignment\n | \"ready\"; // Connected to GPU machine, can send/receive messages\n\n/**\n * The message scope identifies the envelope layer a data channel message belongs to.\n * - \"application\": model-defined commands (client->runtime) and model-emitted payloads (runtime->client).\n * - \"runtime\": platform-level control messages (e.g., capabilities exchange).\n */\nexport type MessageScope = \"application\" | \"runtime\";\n\n// Re-export core types that users may need\nexport type {\n TrackCapability,\n CommandCapability,\n Capabilities,\n SessionResponse,\n} from \"./core/types\";\n\nexport interface ReactorError {\n code: string;\n message: string;\n timestamp: number;\n recoverable: boolean;\n component: \"api\" | \"gpu\";\n retryAfter?: number;\n}\n\nexport class ConflictError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class AbortError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\n/** Matches both our custom AbortError and the native DOMException thrown by fetch(). */\nexport function isAbortError(error: unknown): boolean {\n return (\n error instanceof AbortError ||\n (error instanceof Error && error.name === \"AbortError\")\n );\n}\n\nexport interface ReactorState {\n status: ReactorStatus;\n lastError?: ReactorError;\n}\n\n/**\n * Options for configuring the connect polling behavior.\n */\nexport interface ConnectOptions {\n /** Maximum number of SDP polling attempts before giving up. Default: 6. */\n maxAttempts?: number;\n}\n\n/**\n * Transport-agnostic timing breakdown of the connect() handshake, recorded\n * once per connection and included in every subsequent {@link ConnectionStats}\n * update. All durations are in milliseconds (from `performance.now()`).\n *\n * For transport-specific timings (e.g. ICE negotiation, data channel open),\n * see the relevant transport stats type (e.g. {@link WebRTCTransportTimings}).\n */\nexport interface ConnectionTimings {\n /** POST /sessions round-trip time */\n sessionCreationMs: number;\n /** Total time spent in transport.connect() (signaling, negotiation, etc.) */\n transportConnectingMs: number;\n /** End-to-end: connect() invocation → status \"ready\" */\n totalMs: number;\n}\n\nexport interface ConnectionStats {\n /** ICE candidate-pair round-trip time in milliseconds */\n rtt?: number;\n /** ICE candidate type: \"host\", \"srflx\", \"prflx\", or \"relay\" (TURN) */\n candidateType?: string;\n /** Estimated available outgoing bitrate in bits/second */\n availableOutgoingBitrate?: number;\n /** Received video frames per second */\n framesPerSecond?: number;\n /** Ratio of packets lost (0-1) */\n packetLossRatio?: number;\n /** Network jitter in seconds (from inbound-rtp) */\n jitter?: number;\n /** Timing breakdown of the initial connection handshake (set once, persisted until disconnect) */\n connectionTimings?: ConnectionTimings;\n timestamp: number;\n}\n\nexport type ReactorEvent =\n | \"statusChanged\" //updates on the reactor status\n | \"sessionIdChanged\" //updates on the session ID.\n | \"message\" //application-scoped messages from the model\n | \"runtimeMessage\" //internal platform-level control messages (e.g. capabilities)\n | \"trackReceived\" // (name: string, track: MediaStreamTrack, stream: MediaStream)\n | \"error\" //error events with ReactorError details\n | \"sessionExpirationChanged\" //session expiration has changed\n | \"capabilitiesReceived\" //server capabilities received after session creation\n | \"statsUpdate\"; //WebRTC stats update (RTT, etc.)\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * Internal types for the Reactor SDK.\n *\n * All Zod schemas and derived TypeScript types live here.\n * Version constants are sourced from package.json via resolveJsonModule.\n */\n\nimport { z } from \"zod\";\nimport packageJson from \"../../package.json\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Version Constants (single source of truth: package.json)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const REACTOR_SDK_VERSION: string = packageJson.version;\nexport const REACTOR_API_VERSION: number = (packageJson as any).reactor\n .apiVersion;\nexport const REACTOR_WEBRTC_VERSION: string = (packageJson as any).reactor\n .webrtcVersion;\nexport const REACTOR_SDK_TYPE = \"js\" as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Versioning Headers\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const API_VERSION_HEADER = \"Reactor-API-Version\";\nexport const API_ACCEPT_VERSION_HEADER = \"Reactor-API-Accept-Version\";\nexport const WEBRTC_VERSION_HEADER = \"Reactor-WebRTC-Version\";\n\nexport const VERSION_ERROR_CODES = {\n 426: \"CLIENT_VERSION_TOO_OLD\",\n 501: \"SERVER_VERSION_TOO_OLD\",\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Session States\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum SessionState {\n CREATED = \"CREATED\",\n PENDING = \"PENDING\",\n SUSPENDED = \"SUSPENDED\",\n WAITING = \"WAITING\",\n ACTIVE = \"ACTIVE\",\n INACTIVE = \"INACTIVE\",\n CLOSED = \"CLOSED\",\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Shared Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const ClientInfoSchema = z.object({\n sdk_version: z.string(),\n sdk_type: z.literal(\"js\"),\n});\n\nexport const TransportDeclarationSchema = z.object({\n protocol: z.string(),\n version: z.string(),\n});\n\nexport const TrackCapabilitySchema = z.object({\n name: z.string(),\n kind: z.enum([\"video\", \"audio\"]),\n direction: z.enum([\"recvonly\", \"sendonly\"]),\n});\n\nexport const TrackMappingEntrySchema = TrackCapabilitySchema.extend({\n mid: z.string(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Session API Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\n// POST /sessions — Request\nexport const CreateSessionRequestSchema = z.object({\n model: z.object({ name: z.string() }),\n client_info: ClientInfoSchema,\n supported_transports: z.array(TransportDeclarationSchema),\n extra_args: z.record(z.string(), z.any()).optional(),\n});\n\n// Mirrors the proto Command message.\nexport const CommandCapabilitySchema = z.object({\n name: z.string(),\n description: z.string(),\n schema: z.record(z.string(), z.any()).optional(),\n});\n\n// Mirrors the proto TransportCapabilities message.\nexport const CapabilitiesSchema = z.object({\n protocol_version: z.string(),\n tracks: z.array(TrackCapabilitySchema),\n commands: z.array(CommandCapabilitySchema).optional(),\n emission_fps: z.number().nullable().optional(),\n});\n\n// GET /sessions/{id}/info — Response (200)\nexport const SessionInfoResponseSchema = z.object({\n session_id: z.string(),\n state: z.string(),\n cluster: z.string(),\n});\n\n// POST /sessions — Response (201)\nexport const CreateSessionResponseSchema = SessionInfoResponseSchema.extend({\n model: z.object({ name: z.string(), version: z.string().optional() }),\n server_info: z.object({ server_version: z.string() }),\n});\n\n// GET /sessions/{id} — Response (200)\nexport const SessionResponseSchema = CreateSessionResponseSchema.extend({\n selected_transport: TransportDeclarationSchema.optional(),\n capabilities: CapabilitiesSchema.optional(),\n});\n\n// DELETE /sessions/{id} — Request\nexport const TerminateSessionRequestSchema = z.object({\n reason: z.string().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// WebRTC Transport Schemas\n// ─────────────────────────────────────────────────────────────────────────────\n\n// GET /sessions/{id}/transport/webrtc/ice_servers — Response (200)\nexport const IceServerCredentialsSchema = z.object({\n username: z.string(),\n password: z.string(),\n});\n\nexport const IceServerSchema = z.object({\n uris: z.array(z.string()),\n credentials: IceServerCredentialsSchema.optional(),\n});\n\nexport const IceServersResponseSchema = z.object({\n ice_servers: z.array(IceServerSchema),\n});\n\n// POST/PUT /sessions/{id}/transport/webrtc/sdp_params — Request\nexport const WebRTCSdpOfferRequestSchema = z.object({\n sdp_offer: z.string(),\n client_info: ClientInfoSchema.optional(),\n track_mapping: z.array(TrackMappingEntrySchema),\n});\n\n// GET /sessions/{id}/transport/webrtc/sdp_params — Response (200)\nexport const WebRTCSdpAnswerResponseSchema = z.object({\n sdp_answer: z.string(),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inferred TypeScript Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type ClientInfo = z.infer<typeof ClientInfoSchema>;\nexport type TransportDeclaration = z.infer<typeof TransportDeclarationSchema>;\nexport type TrackCapability = z.infer<typeof TrackCapabilitySchema>;\nexport type CommandCapability = z.infer<typeof CommandCapabilitySchema>;\nexport type TrackMappingEntry = z.infer<typeof TrackMappingEntrySchema>;\n\nexport type CreateSessionRequest = z.infer<typeof CreateSessionRequestSchema>;\nexport type CreateSessionResponse = z.infer<typeof CreateSessionResponseSchema>;\nexport type SessionResponse = z.infer<typeof SessionResponseSchema>;\nexport type Capabilities = z.infer<typeof CapabilitiesSchema>;\n\nexport type SessionInfoResponse = z.infer<typeof SessionInfoResponseSchema>;\nexport type TerminateSessionRequest = z.infer<\n typeof TerminateSessionRequestSchema\n>;\n\nexport type IceServer = z.infer<typeof IceServerSchema>;\nexport type IceServersResponse = z.infer<typeof IceServersResponseSchema>;\n\nexport type WebRTCSdpOfferRequest = z.infer<typeof WebRTCSdpOfferRequestSchema>;\nexport type WebRTCSdpAnswerResponse = z.infer<\n typeof WebRTCSdpAnswerResponseSchema\n>;\n","{\n \"name\": \"@reactor-team/js-sdk\",\n \"version\": \"2.8.0\",\n \"description\": \"Reactor JavaScript frontend SDK\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:unit\": \"vitest run __tests__/unit\",\n \"test:integration\": \"vitest run __tests__/integration\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\"\n },\n \"keywords\": [\n \"reactor\",\n \"frontend\",\n \"sdk\"\n ],\n \"author\": \"Reactor Technologies, Inc.\",\n \"reactor\": {\n \"apiVersion\": 1,\n \"webrtcVersion\": \"1.0\"\n },\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/reactor-team/js-sdk\"\n },\n \"packageManager\": \"pnpm@10.12.1\",\n \"devDependencies\": {\n \"@roamhq/wrtc\": \"^0.8.0\",\n \"@types/inquirer\": \"^9.0.9\",\n \"@types/node\": \"^20\",\n \"@types/react\": \"^18.2.8\",\n \"@types/ws\": \"^8.18.1\",\n \"prettier\": \"^3.6.2\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^3.0.0\"\n },\n \"dependencies\": {\n \"@bufbuild/protobuf\": \"^2.0.0\",\n \"chalk\": \"^5.3.0\",\n \"inquirer\": \"^9.3.0\",\n \"simple-git\": \"^3.24.0\",\n \"ws\": \"^8.18.3\",\n \"zod\": \"^4.0.5\"\n },\n \"peerDependencies\": {\n \"react\": \"^17.0.0 || ^18.0.0 || ^19.0.0\",\n \"zustand\": \"^5.0.6\"\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * The CoordinatorClient handles session lifecycle via HTTP requests.\n *\n * Transport signaling (ICE servers, SDP exchange) is NOT handled here —\n * that responsibility belongs to the TransportClient implementations.\n */\n\nimport {\n type CreateSessionRequest,\n type CreateSessionResponse,\n type SessionResponse,\n type SessionInfoResponse,\n type TerminateSessionRequest,\n CreateSessionResponseSchema,\n SessionResponseSchema,\n SessionInfoResponseSchema,\n SessionState,\n REACTOR_API_VERSION,\n REACTOR_SDK_VERSION,\n REACTOR_SDK_TYPE,\n REACTOR_WEBRTC_VERSION,\n API_VERSION_HEADER,\n API_ACCEPT_VERSION_HEADER,\n VERSION_ERROR_CODES,\n} from \"./types\";\nimport { AbortError } from \"../types\";\n\nconst SESSION_POLL_INITIAL_BACKOFF_MS = 200;\nconst SESSION_POLL_MAX_BACKOFF_MS = 10_000;\nconst SESSION_POLL_BACKOFF_MULTIPLIER = 2;\nconst SESSION_POLL_DEFAULT_MAX_ATTEMPTS = 20;\n\nexport interface CoordinatorClientOptions {\n baseUrl: string;\n jwtToken: string;\n model: string;\n}\n\nexport class CoordinatorClient {\n protected readonly baseUrl: string;\n private jwtToken: string;\n protected readonly model: string;\n protected currentSessionId?: string;\n private abortController: AbortController;\n\n constructor(options: CoordinatorClientOptions) {\n this.baseUrl = options.baseUrl;\n this.jwtToken = options.jwtToken;\n this.model = options.model;\n this.abortController = new AbortController();\n }\n\n /**\n * Aborts any in-flight HTTP requests.\n * A fresh AbortController is created so the client remains reusable.\n */\n abort(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n /**\n * The current abort signal, passed to every fetch() call.\n * Protected so subclasses can forward it to their own fetch calls.\n */\n protected get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Returns authorization + versioning headers for all coordinator requests.\n */\n protected getHeaders(): HeadersInit {\n return {\n Authorization: `Bearer ${this.jwtToken}`,\n [API_VERSION_HEADER]: String(REACTOR_API_VERSION),\n [API_ACCEPT_VERSION_HEADER]: String(REACTOR_API_VERSION),\n };\n }\n\n /**\n * Checks an HTTP response for version mismatch errors (426, 501).\n * Logs a clear message and throws with a descriptive error code.\n */\n protected async checkVersionMismatch(response: Response): Promise<void> {\n if (response.status === 426) {\n const msg =\n `Client API version (${REACTOR_API_VERSION}) is too old. ` +\n `Server requires a newer version. Please upgrade @reactor-team/js-sdk.`;\n console.error(`[Reactor]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[426]}: ${msg}`);\n }\n\n if (response.status === 501) {\n const msg =\n `Server does not support API version ${REACTOR_API_VERSION}. ` +\n `The server may need to be updated.`;\n console.error(`[Reactor]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[501]}: ${msg}`);\n }\n }\n\n protected sleep(ms: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const { signal } = this;\n if (signal.aborted) {\n reject(new AbortError(\"Sleep aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError(\"Sleep aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n /**\n * Creates a new session with the coordinator.\n * No SDP is sent — transport signaling is decoupled from session creation.\n *\n * The POST response is a slim acknowledgment (session_id, model name, status).\n * Capabilities and transport details are populated later once the Runtime\n * accepts the session — use {@link pollSessionReady} to wait for them.\n */\n async createSession(\n extraArgs?: Record<string, any>\n ): Promise<CreateSessionResponse> {\n console.debug(\"[CoordinatorClient] Creating session...\");\n\n const requestBody: CreateSessionRequest = {\n model: { name: this.model },\n client_info: {\n sdk_version: REACTOR_SDK_VERSION,\n sdk_type: REACTOR_SDK_TYPE,\n },\n supported_transports: [\n { protocol: \"webrtc\", version: REACTOR_WEBRTC_VERSION },\n ],\n ...(extraArgs ? { extra_args: extraArgs } : {}),\n };\n\n const response = await fetch(`${this.baseUrl}/sessions`, {\n method: \"POST\",\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(requestBody),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to create session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n const parsed = CreateSessionResponseSchema.parse(data);\n this.currentSessionId = parsed.session_id;\n\n console.debug(\n \"[CoordinatorClient] Session created:\",\n this.currentSessionId,\n \"state:\",\n parsed.state\n );\n\n return parsed;\n }\n\n /**\n * Polls GET /sessions/{id} until the Runtime has accepted the session\n * and populated capabilities and selected_transport.\n */\n async pollSessionReady(opts?: {\n maxAttempts?: number;\n }): Promise<SessionResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const maxAttempts = opts?.maxAttempts ?? SESSION_POLL_DEFAULT_MAX_ATTEMPTS;\n let backoffMs = SESSION_POLL_INITIAL_BACKOFF_MS;\n let attempt = 0;\n\n console.debug(\n \"[CoordinatorClient] Polling session until capabilities are available...\"\n );\n\n while (true) {\n if (this.signal.aborted) {\n throw new AbortError(\"Session polling aborted\");\n }\n\n if (attempt >= maxAttempts) {\n throw new Error(\n `Session polling exceeded maximum attempts (${maxAttempts}). ` +\n `The model may be unavailable or overloaded.`\n );\n }\n\n attempt++;\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to poll session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n const partial = SessionResponseSchema.parse(data);\n\n const terminalStates: string[] = [\n SessionState.CLOSED,\n SessionState.INACTIVE,\n ];\n if (terminalStates.includes(partial.state)) {\n throw new Error(\n `Session entered terminal state \"${partial.state}\" while waiting for capabilities`\n );\n }\n\n if (partial.capabilities && partial.selected_transport) {\n console.debug(\n `[CoordinatorClient] Session ready after ${attempt} poll(s), ` +\n `transport: ${partial.selected_transport.protocol}, ` +\n `tracks: ${partial.capabilities.tracks.length}`\n );\n return partial;\n }\n\n console.debug(\n `[CoordinatorClient] Session poll ${attempt}/${maxAttempts} — ` +\n `state: ${partial.state}, waiting ${backoffMs}ms...`\n );\n\n await this.sleep(backoffMs);\n backoffMs = Math.min(\n backoffMs * SESSION_POLL_BACKOFF_MULTIPLIER,\n SESSION_POLL_MAX_BACKOFF_MS\n );\n }\n }\n\n /**\n * Gets session details from the coordinator.\n * Fields like selected_transport and capabilities are only present\n * after the Runtime accepts the session.\n */\n async getSession(): Promise<SessionResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to get session: ${response.status} ${errorText}`);\n }\n\n const data = await response.json();\n return SessionResponseSchema.parse(data);\n }\n\n /**\n * Gets lightweight session status (session_id, cluster, status).\n */\n async getSessionInfo(): Promise<SessionInfoResponse> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}/info`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to get session info: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n return SessionInfoResponseSchema.parse(data);\n }\n\n /**\n * Restarts an inactive session with a different compute unit.\n * The session ID is preserved but a new transport must be established.\n */\n async restartSession(): Promise<void> {\n if (!this.currentSessionId) {\n throw new Error(\"No active session. Call createSession() first.\");\n }\n\n console.debug(\n \"[CoordinatorClient] Restarting session:\",\n this.currentSessionId\n );\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"PUT\",\n headers: this.getHeaders(),\n signal: this.signal,\n }\n );\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to restart session: ${response.status} ${errorText}`\n );\n }\n }\n\n /**\n * Terminates the current session by sending a DELETE request.\n * No-op if no session has been created yet.\n * @param reason Optional termination reason\n */\n async terminateSession(reason?: string): Promise<void> {\n if (!this.currentSessionId) {\n return;\n }\n\n console.debug(\n \"[CoordinatorClient] Terminating session:\",\n this.currentSessionId\n );\n\n const body: TerminateSessionRequest | undefined = reason\n ? { reason }\n : undefined;\n\n const response = await fetch(\n `${this.baseUrl}/sessions/${this.currentSessionId}`,\n {\n method: \"DELETE\",\n headers: {\n ...this.getHeaders(),\n ...(body ? { \"Content-Type\": \"application/json\" } : {}),\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n signal: this.signal,\n }\n );\n\n if (response.ok) {\n this.currentSessionId = undefined;\n return;\n }\n\n if (response.status === 404) {\n console.debug(\n \"[CoordinatorClient] Session not found on server, clearing local state:\",\n this.currentSessionId\n );\n this.currentSessionId = undefined;\n return;\n }\n\n const errorText = await response.text();\n throw new Error(\n `Failed to terminate session: ${response.status} ${errorText}`\n );\n }\n\n getSessionId(): string | undefined {\n return this.currentSessionId;\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * LocalCoordinatorClient connects to a local runtime instance.\n *\n * The local runtime uses a simpler protocol than the production coordinator:\n * - POST /start_session → starts session, returns full capabilities immediately\n * - POST /stop_session → stops session\n * - Transport signaling via /sessions/{id}/transport/webrtc/* (unchanged)\n *\n * No session polling is needed because the local runtime IS the model host —\n * capabilities are known the moment the session is created.\n */\n\nimport { CoordinatorClient } from \"./CoordinatorClient\";\nimport {\n type CreateSessionResponse,\n type SessionResponse,\n CreateSessionResponseSchema,\n SessionResponseSchema,\n API_VERSION_HEADER,\n API_ACCEPT_VERSION_HEADER,\n REACTOR_API_VERSION,\n} from \"./types\";\n\nexport class LocalCoordinatorClient extends CoordinatorClient {\n private cachedSessionResponse?: SessionResponse;\n\n constructor(baseUrl: string, model: string) {\n super({\n baseUrl,\n jwtToken: \"local\",\n model,\n });\n }\n\n protected override getHeaders(): HeadersInit {\n return {\n [API_VERSION_HEADER]: String(REACTOR_API_VERSION),\n [API_ACCEPT_VERSION_HEADER]: String(REACTOR_API_VERSION),\n };\n }\n\n /**\n * Starts a session on the local runtime.\n *\n * Unlike the production coordinator, the local runtime returns the full\n * response (capabilities, selected_transport) immediately — no polling needed.\n */\n override async createSession(\n extraArgs?: Record<string, any>\n ): Promise<CreateSessionResponse> {\n console.debug(\"[LocalCoordinatorClient] Starting session...\");\n\n const response = await fetch(`${this.baseUrl}/start_session`, {\n method: \"POST\",\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n ...(extraArgs ? { extra_args: extraArgs } : {}),\n }),\n signal: this.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to start session: ${response.status} ${errorText}`\n );\n }\n\n const data = await response.json();\n\n const session = SessionResponseSchema.parse(data);\n this.cachedSessionResponse = session;\n this.currentSessionId = session.session_id;\n\n console.debug(\n \"[LocalCoordinatorClient] Session started:\",\n this.currentSessionId,\n \"transport:\",\n session.selected_transport?.protocol,\n \"tracks:\",\n session.capabilities?.tracks.length\n );\n\n return CreateSessionResponseSchema.parse(data);\n }\n\n /**\n * Returns the cached full session response immediately.\n * The local runtime already provided everything in start_session.\n */\n override async pollSessionReady(): Promise<SessionResponse> {\n if (!this.cachedSessionResponse) {\n throw new Error(\n \"No cached session response. Call createSession() first.\"\n );\n }\n return this.cachedSessionResponse;\n }\n\n /**\n * Stops the session on the local runtime.\n */\n override async terminateSession(): Promise<void> {\n if (!this.currentSessionId) {\n return;\n }\n\n console.debug(\n \"[LocalCoordinatorClient] Stopping session:\",\n this.currentSessionId\n );\n\n try {\n await fetch(`${this.baseUrl}/stop_session`, {\n method: \"POST\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n } catch (error) {\n console.error(\"[LocalCoordinatorClient] Error stopping session:\", error);\n }\n\n this.currentSessionId = undefined;\n this.cachedSessionResponse = undefined;\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * Stateless WebRTC utility functions for SDP exchange and peer connection management.\n */\n\nimport type { IceServersResponse } from \"../core/types\";\nimport type { MessageScope, ConnectionStats } from \"../types\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface WebRTCConfig {\n iceServers: RTCIceServer[];\n dataChannelLabel?: string;\n}\n\nconst DEFAULT_DATA_CHANNEL_LABEL = \"data\";\n\nconst FORCE_RELAY_MODE = false;\n\n/**\n * Safe cross-browser default for the maximum data channel message size (bytes).\n * Most browsers negotiate 256 KiB via SCTP; we use a slightly lower value to\n * leave room for framing overhead.\n */\nconst DEFAULT_MAX_MESSAGE_BYTES = 256 * 1024; // 256 KiB\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Peer Connection Creation\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Creates a new RTCPeerConnection with the specified configuration.\n * @param config WebRTC configuration with required iceServers\n */\nexport function createPeerConnection(config: WebRTCConfig): RTCPeerConnection {\n return new RTCPeerConnection({\n iceServers: config.iceServers,\n iceTransportPolicy: FORCE_RELAY_MODE ? \"relay\" : \"all\",\n });\n}\n\n/**\n * Creates a data channel on the peer connection.\n */\nexport function createDataChannel(\n pc: RTCPeerConnection,\n label?: string\n): RTCDataChannel {\n return pc.createDataChannel(label ?? DEFAULT_DATA_CHANNEL_LABEL);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// SDP Offer/Answer\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Creates an SDP offer on the peer connection.\n * No MID munging — track identity is conveyed via track_mapping metadata.\n * @returns The SDP offer string with gathered ICE candidates.\n */\nexport async function createOffer(pc: RTCPeerConnection): Promise<string> {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n await waitForIceGathering(pc);\n\n const localDescription = pc.localDescription;\n if (!localDescription) {\n throw new Error(\"Failed to create local description\");\n }\n\n return localDescription.sdp;\n}\n\n/**\n * Creates an SDP answer in response to a received offer.\n * Waits for ICE gathering to complete before returning.\n */\nexport async function createAnswer(\n pc: RTCPeerConnection,\n offer: string\n): Promise<string> {\n await setRemoteDescription(pc, offer);\n\n const answer = await pc.createAnswer();\n await pc.setLocalDescription(answer);\n\n await waitForIceGathering(pc);\n\n const localDescription = pc.localDescription;\n if (!localDescription) {\n throw new Error(\"Failed to create local description\");\n }\n\n return localDescription.sdp;\n}\n\n/**\n * Sets the remote description on the peer connection.\n */\nexport async function setRemoteDescription(\n pc: RTCPeerConnection,\n sdp: string\n): Promise<void> {\n const sessionDescription = new RTCSessionDescription({\n sdp: sdp,\n type: \"answer\",\n });\n await pc.setRemoteDescription(sessionDescription);\n}\n\n/**\n * Gets the local SDP description from the peer connection.\n */\nexport function getLocalDescription(pc: RTCPeerConnection): string | undefined {\n const desc = pc.localDescription;\n if (!desc) return undefined;\n return desc.sdp;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ICE Handling\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transforms ICE servers from the API response to RTCIceServer format.\n * The API uses `uris` and a nested `credentials` object; the browser\n * RTCIceServer interface expects `urls`, `username`, and `credential`.\n */\nexport function transformIceServers(\n response: IceServersResponse\n): RTCIceServer[] {\n return response.ice_servers.map((server) => {\n const rtcServer: RTCIceServer = {\n urls: server.uris,\n };\n if (server.credentials) {\n rtcServer.username = server.credentials.username;\n rtcServer.credential = server.credentials.password;\n }\n return rtcServer;\n });\n}\n\n/**\n * Adds an ICE candidate to the peer connection.\n */\nexport async function addIceCandidate(\n pc: RTCPeerConnection,\n candidate: RTCIceCandidateInit\n): Promise<void> {\n await pc.addIceCandidate(new RTCIceCandidate(candidate));\n}\n\n/**\n * Waits for ICE gathering to complete with a timeout.\n */\nexport function waitForIceGathering(\n pc: RTCPeerConnection,\n timeoutMs: number = 5000\n): Promise<void> {\n return new Promise((resolve) => {\n if (pc.iceGatheringState === \"complete\") {\n resolve();\n return;\n }\n\n const onGatheringStateChange = () => {\n if (pc.iceGatheringState === \"complete\") {\n pc.removeEventListener(\n \"icegatheringstatechange\",\n onGatheringStateChange\n );\n resolve();\n }\n };\n\n pc.addEventListener(\"icegatheringstatechange\", onGatheringStateChange);\n\n setTimeout(() => {\n pc.removeEventListener(\"icegatheringstatechange\", onGatheringStateChange);\n resolve();\n }, timeoutMs);\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Track Management\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Adds a track to the peer connection.\n */\nexport function addTrack(\n pc: RTCPeerConnection,\n track: MediaStreamTrack,\n stream?: MediaStream\n): RTCRtpSender {\n const mediaStream = stream ?? new MediaStream([track]);\n return pc.addTrack(track, mediaStream);\n}\n\n/**\n * Removes a track from the peer connection by its sender.\n */\nexport function removeTrack(pc: RTCPeerConnection, sender: RTCRtpSender): void {\n pc.removeTrack(sender);\n}\n\n/**\n * Finds the sender for a specific track.\n */\nexport function findSenderForTrack(\n pc: RTCPeerConnection,\n track: MediaStreamTrack\n): RTCRtpSender | undefined {\n return pc.getSenders().find((sender) => sender.track === track);\n}\n\n/**\n * Removes all tracks from the peer connection.\n */\nexport function removeAllTracks(pc: RTCPeerConnection): void {\n for (const sender of pc.getSenders()) {\n pc.removeTrack(sender);\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data Channel Messaging\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Sends a message through a data channel wrapped in the two-level envelope.\n *\n * Wire format:\n * { scope: \"application\"|\"runtime\", data: { type: <command>, data: <payload> } }\n *\n * @param channel The RTCDataChannel to send on.\n * @param command Inner command/message type (e.g. \"set_prompt\", \"requestCapabilities\").\n * @param data Payload for the command.\n * @param scope Outer envelope scope – defaults to \"application\".\n * @param maxBytes Max allowed serialized message size in bytes.\n * Defaults to {@link DEFAULT_MAX_MESSAGE_BYTES} (256 KiB).\n * Pass the negotiated SCTP limit when available.\n */\nexport function sendMessage(\n channel: RTCDataChannel,\n command: string,\n data: any,\n scope: MessageScope = \"application\",\n maxBytes: number = DEFAULT_MAX_MESSAGE_BYTES\n): void {\n if (channel.readyState !== \"open\") {\n throw new Error(`Data channel not open: ${channel.readyState}`);\n }\n const jsonData = typeof data === \"string\" ? JSON.parse(data) : data;\n const inner = { type: command, data: jsonData };\n const payload = { scope, data: inner };\n const serialized = JSON.stringify(payload);\n\n const byteLength = new TextEncoder().encode(serialized).byteLength;\n if (byteLength > maxBytes) {\n throw new Error(\n `Data channel message too large: ${byteLength} bytes exceeds ` +\n `limit of ${maxBytes} bytes (command: \"${command}\")`\n );\n }\n\n channel.send(serialized);\n}\n\n/**\n * Parses a received data channel message, attempting JSON parse.\n */\nexport function parseMessage(data: unknown): unknown {\n if (typeof data === \"string\") {\n try {\n return JSON.parse(data);\n } catch {\n return data;\n }\n }\n return data;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Connection State\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Checks if the peer connection is in a connected state.\n */\nexport function isConnected(pc: RTCPeerConnection): boolean {\n return pc.connectionState === \"connected\";\n}\n\n/**\n * Checks if the peer connection is closed or failed.\n */\nexport function isClosed(pc: RTCPeerConnection): boolean {\n return pc.connectionState === \"closed\" || pc.connectionState === \"failed\";\n}\n\n/**\n * Closes the peer connection and cleans up.\n */\nexport function closePeerConnection(pc: RTCPeerConnection): void {\n pc.close();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stats Extraction\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Extracts ConnectionStats from an RTCStatsReport.\n * Reads candidate-pair, local-candidate, and inbound-rtp (video) reports.\n */\nexport function extractConnectionStats(\n report: RTCStatsReport\n): ConnectionStats {\n let rtt: number | undefined;\n let availableOutgoingBitrate: number | undefined;\n let localCandidateId: string | undefined;\n let framesPerSecond: number | undefined;\n let jitter: number | undefined;\n let packetLossRatio: number | undefined;\n\n report.forEach((stat) => {\n if (stat.type === \"candidate-pair\" && stat.state === \"succeeded\") {\n if (stat.currentRoundTripTime !== undefined) {\n rtt = stat.currentRoundTripTime * 1000;\n }\n if (stat.availableOutgoingBitrate !== undefined) {\n availableOutgoingBitrate = stat.availableOutgoingBitrate;\n }\n localCandidateId = stat.localCandidateId;\n }\n\n if (stat.type === \"inbound-rtp\" && stat.kind === \"video\") {\n if (stat.framesPerSecond !== undefined) {\n framesPerSecond = stat.framesPerSecond;\n }\n if (stat.jitter !== undefined) {\n jitter = stat.jitter;\n }\n if (\n stat.packetsReceived !== undefined &&\n stat.packetsLost !== undefined &&\n stat.packetsReceived + stat.packetsLost > 0\n ) {\n packetLossRatio =\n stat.packetsLost / (stat.packetsReceived + stat.packetsLost);\n }\n }\n });\n\n let candidateType: string | undefined;\n if (localCandidateId) {\n const localCandidate = report.get(localCandidateId);\n if (localCandidate?.candidateType) {\n candidateType = localCandidate.candidateType;\n }\n }\n\n return {\n rtt,\n candidateType,\n availableOutgoingBitrate,\n framesPerSecond,\n packetLossRatio,\n jitter,\n timestamp: Date.now(),\n };\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\n/**\n * WebRTC implementation of the TransportClient interface.\n *\n * Handles the full WebRTC lifecycle: signaling (ICE servers, SDP exchange\n * via the transport REST endpoints), RTCPeerConnection management, data\n * channel messaging, track publishing, and stats collection.\n */\n\nimport * as webrtc from \"../utils/webrtc\";\nimport type {\n TransportClient,\n TransportClientConfig,\n TransportStatus,\n TransportEvent,\n} from \"./TransportClient\";\nimport type { MessageScope, ConnectionStats } from \"../types\";\nimport { AbortError } from \"../types\";\nimport {\n type TrackCapability,\n type TrackMappingEntry,\n type WebRTCSdpOfferRequest,\n type WebRTCSdpAnswerResponse,\n IceServersResponseSchema,\n WebRTCSdpAnswerResponseSchema,\n REACTOR_WEBRTC_VERSION,\n REACTOR_SDK_VERSION,\n REACTOR_SDK_TYPE,\n WEBRTC_VERSION_HEADER,\n VERSION_ERROR_CODES,\n} from \"./types\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype EventHandler = (...args: any[]) => void;\n\nconst PING_INTERVAL_MS = 5_000;\nconst STATS_INTERVAL_MS = 2_000;\n\nconst INITIAL_BACKOFF_MS = 200;\nconst MAX_BACKOFF_MS = 15_000;\nconst BACKOFF_MULTIPLIER = 2;\nconst DEFAULT_MAX_POLL_ATTEMPTS = 6;\n\nexport interface WebRTCTransportConfig extends TransportClientConfig {\n webrtcVersion?: string;\n maxPollAttempts?: number;\n}\n\n/**\n * WebRTC-specific timing breakdown of the transport connection.\n * Recorded once per connection and accessible via {@link WebRTCTransportClient.getTransportTimings}.\n */\nexport interface WebRTCTransportTimings {\n protocol: \"webrtc\";\n /** Time spent polling for the SDP answer (POST offer → GET answer 200) */\n sdpPollingMs: number;\n /** Number of SDP poll requests made (1 = answered on first try) */\n sdpPollingAttempts: number;\n /** setRemoteDescription → RTCPeerConnection connectionState \"connected\" */\n iceNegotiationMs: number;\n /** setRemoteDescription → RTCDataChannel \"open\" */\n dataChannelMs: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Transceiver bookkeeping\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface TransceiverEntry {\n name: string;\n kind: \"audio\" | \"video\";\n direction: RTCRtpTransceiverDirection;\n transceiver?: RTCRtpTransceiver;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Implementation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class WebRTCTransportClient implements TransportClient {\n private eventListeners: Map<TransportEvent, Set<EventHandler>> = new Map();\n private peerConnection: RTCPeerConnection | undefined;\n private dataChannel: RTCDataChannel | undefined;\n private status: TransportStatus = \"disconnected\";\n private pingInterval: ReturnType<typeof setInterval> | undefined;\n private statsInterval: ReturnType<typeof setInterval> | undefined;\n private stats: ConnectionStats | undefined;\n\n private transceiverMap: Map<string, TransceiverEntry> = new Map();\n private publishedTracks: Map<string, MediaStreamTrack> = new Map();\n private peerConnected = false;\n private dataChannelOpen = false;\n\n private iceStartTime?: number;\n private iceNegotiationMs?: number;\n private dataChannelMs?: number;\n private sdpPollingMs?: number;\n private sdpPollingAttempts?: number;\n\n private readonly baseUrl: string;\n private readonly sessionId: string;\n private readonly jwtToken: string;\n private readonly webrtcVersion: string;\n private readonly maxPollAttempts: number;\n private abortController: AbortController;\n\n constructor(config: WebRTCTransportConfig) {\n this.baseUrl = config.baseUrl;\n this.sessionId = config.sessionId;\n this.jwtToken = config.jwtToken;\n this.webrtcVersion = config.webrtcVersion ?? REACTOR_WEBRTC_VERSION;\n this.maxPollAttempts = config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;\n this.abortController = new AbortController();\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Event Emitter\n // ─────────────────────────────────────────────────────────────────────────\n\n on(event: TransportEvent, handler: EventHandler): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(handler);\n }\n\n off(event: TransportEvent, handler: EventHandler): void {\n this.eventListeners.get(event)?.delete(handler);\n }\n\n private emit(event: TransportEvent, ...args: unknown[]): void {\n this.eventListeners.get(event)?.forEach((handler) => handler(...args));\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // HTTP Helpers\n // ─────────────────────────────────────────────────────────────────────────\n\n private get signal(): AbortSignal {\n return this.abortController.signal;\n }\n\n private get transportBaseUrl(): string {\n return `${this.baseUrl}/sessions/${this.sessionId}/transport/webrtc`;\n }\n\n private getHeaders(): HeadersInit {\n return {\n Authorization: `Bearer ${this.jwtToken}`,\n [WEBRTC_VERSION_HEADER]: this.webrtcVersion,\n };\n }\n\n private async checkVersionMismatch(response: Response): Promise<void> {\n if (response.status === 426) {\n const msg =\n `Client WebRTC version (${this.webrtcVersion}) is too old. ` +\n `Server requires a newer version. Please upgrade @reactor-team/js-sdk.`;\n console.error(`[WebRTCTransport]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[426]}: ${msg}`);\n }\n\n if (response.status === 501) {\n const msg =\n `Server does not support WebRTC version ${this.webrtcVersion}. ` +\n `The server may need to be updated.`;\n console.error(`[WebRTCTransport]`, msg);\n throw new Error(`${VERSION_ERROR_CODES[501]}: ${msg}`);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const { signal } = this;\n if (signal.aborted) {\n reject(new AbortError(\"Sleep aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError(\"Sleep aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Transport Signaling (HTTP)\n // ─────────────────────────────────────────────────────────────────────────\n\n private async fetchIceServers(): Promise<RTCIceServer[]> {\n console.debug(\"[WebRTCTransport] Fetching ICE servers...\");\n\n const response = await fetch(`${this.transportBaseUrl}/ice_servers`, {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ICE servers: ${response.status}`);\n }\n\n const data = await response.json();\n const parsed = IceServersResponseSchema.parse(data);\n const iceServers = webrtc.transformIceServers(parsed);\n\n console.debug(\"[WebRTCTransport] Received ICE servers:\", iceServers.length);\n return iceServers;\n }\n\n private async sendSdpOffer(\n sdpOffer: string,\n trackMapping: TrackMappingEntry[],\n method: \"POST\" | \"PUT\" = \"POST\"\n ): Promise<void> {\n console.debug(\n `[WebRTCTransport] Sending SDP offer (${method}) for session:`,\n this.sessionId\n );\n\n const requestBody: WebRTCSdpOfferRequest = {\n sdp_offer: sdpOffer,\n client_info: {\n sdk_version: REACTOR_SDK_VERSION,\n sdk_type: REACTOR_SDK_TYPE,\n },\n track_mapping: trackMapping,\n };\n\n const response = await fetch(`${this.transportBaseUrl}/sdp_params`, {\n method,\n headers: {\n ...this.getHeaders(),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(requestBody),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (response.status !== 202) {\n const errorText = await response.text();\n throw new Error(\n `Failed to send SDP offer: ${response.status} ${errorText}`\n );\n }\n\n console.debug(\"[WebRTCTransport] SDP offer accepted (202)\");\n }\n\n private async pollSdpAnswer(): Promise<WebRTCSdpAnswerResponse> {\n console.debug(\"[WebRTCTransport] Polling for SDP answer...\");\n\n const pollStart = performance.now();\n let backoffMs = INITIAL_BACKOFF_MS;\n let attempt = 0;\n\n while (true) {\n if (this.signal.aborted) {\n throw new AbortError(\"SDP polling aborted\");\n }\n\n if (attempt >= this.maxPollAttempts) {\n throw new Error(\n `SDP polling exceeded maximum attempts (${this.maxPollAttempts})`\n );\n }\n\n attempt++;\n console.debug(\n `[WebRTCTransport] SDP poll attempt ${attempt}/${this.maxPollAttempts}`\n );\n\n const response = await fetch(`${this.transportBaseUrl}/sdp_params`, {\n method: \"GET\",\n headers: this.getHeaders(),\n signal: this.signal,\n });\n\n await this.checkVersionMismatch(response);\n\n if (response.status === 200) {\n const data = await response.json();\n const parsed = WebRTCSdpAnswerResponseSchema.parse(data);\n this.sdpPollingMs = performance.now() - pollStart;\n this.sdpPollingAttempts = attempt;\n console.debug(\n `[WebRTCTransport] Received SDP answer via polling (${attempt} attempt(s), ${this.sdpPollingMs.toFixed(0)}ms)`\n );\n return parsed;\n }\n\n if (response.status === 202) {\n console.debug(\n `[WebRTCTransport] SDP answer pending, retrying in ${backoffMs}ms...`\n );\n await this.sleep(backoffMs);\n backoffMs = Math.min(backoffMs * BACKOFF_MULTIPLIER, MAX_BACKOFF_MS);\n continue;\n }\n\n const errorText = await response.text();\n throw new Error(\n `Failed to poll SDP answer: ${response.status} ${errorText}`\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Connection Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n async connect(tracks: TrackCapability[]): Promise<void> {\n this.setStatus(\"connecting\");\n this.resetTransportTimings();\n\n const iceServers = await this.fetchIceServers();\n\n this.peerConnection = webrtc.createPeerConnection({ iceServers });\n this.setupPeerConnectionHandlers();\n\n this.dataChannel = webrtc.createDataChannel(this.peerConnection);\n this.setupDataChannelHandlers();\n\n this.transceiverMap.clear();\n for (const track of tracks) {\n const transceiver = this.peerConnection.addTransceiver(track.kind, {\n direction: track.direction,\n });\n this.transceiverMap.set(track.name, {\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n transceiver,\n });\n console.debug(\n `[WebRTCTransport] Transceiver added: \"${track.name}\" (${track.kind}, ${track.direction})`\n );\n }\n\n const sdpOffer = await webrtc.createOffer(this.peerConnection);\n\n const trackMapping = this.buildTrackMapping(tracks);\n\n await this.sendSdpOffer(sdpOffer, trackMapping, \"POST\");\n\n const answerResponse = await this.pollSdpAnswer();\n\n this.iceStartTime = performance.now();\n await webrtc.setRemoteDescription(\n this.peerConnection,\n answerResponse.sdp_answer\n );\n console.debug(\"[WebRTCTransport] Remote description set\");\n }\n\n async reconnect(tracks: TrackCapability[]): Promise<void> {\n this.setStatus(\"connecting\");\n\n this.stopPing();\n this.stopStatsPolling();\n\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = undefined;\n }\n if (this.peerConnection) {\n webrtc.closePeerConnection(this.peerConnection);\n this.peerConnection = undefined;\n }\n this.peerConnected = false;\n this.dataChannelOpen = false;\n this.resetTransportTimings();\n\n const iceServers = await this.fetchIceServers();\n\n this.peerConnection = webrtc.createPeerConnection({ iceServers });\n this.setupPeerConnectionHandlers();\n\n this.dataChannel = webrtc.createDataChannel(this.peerConnection);\n this.setupDataChannelHandlers();\n\n this.transceiverMap.clear();\n for (const track of tracks) {\n const transceiver = this.peerConnection.addTransceiver(track.kind, {\n direction: track.direction,\n });\n this.transceiverMap.set(track.name, {\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n transceiver,\n });\n }\n\n const sdpOffer = await webrtc.createOffer(this.peerConnection);\n const trackMapping = this.buildTrackMapping(tracks);\n\n await this.sendSdpOffer(sdpOffer, trackMapping, \"PUT\");\n\n const answerResponse = await this.pollSdpAnswer();\n\n this.iceStartTime = performance.now();\n await webrtc.setRemoteDescription(\n this.peerConnection,\n answerResponse.sdp_answer\n );\n console.debug(\"[WebRTCTransport] Remote description set (reconnect)\");\n }\n\n async disconnect(): Promise<void> {\n this.stopPing();\n this.stopStatsPolling();\n\n for (const name of Array.from(this.publishedTracks.keys())) {\n await this.unpublishTrack(name);\n }\n\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = undefined;\n }\n\n if (this.peerConnection) {\n webrtc.closePeerConnection(this.peerConnection);\n this.peerConnection = undefined;\n }\n\n this.transceiverMap.clear();\n this.peerConnected = false;\n this.dataChannelOpen = false;\n this.resetTransportTimings();\n this.setStatus(\"disconnected\");\n console.debug(\"[WebRTCTransport] Disconnected\");\n }\n\n abort(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n getStatus(): TransportStatus {\n return this.status;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Track Mapping\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Builds the track_mapping array from capabilities + transceiver MIDs.\n * Must be called after createOffer + setLocalDescription so that\n * transceiver.mid is assigned.\n */\n private buildTrackMapping(tracks: TrackCapability[]): TrackMappingEntry[] {\n return tracks.map((track) => {\n const entry = this.transceiverMap.get(track.name);\n const mid = entry?.transceiver?.mid;\n if (mid == null) {\n throw new Error(\n `Cannot build track mapping: transceiver \"${track.name}\" has no MID. ` +\n `Was createOffer() called?`\n );\n }\n return {\n mid,\n name: track.name,\n kind: track.kind,\n direction: track.direction,\n };\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Messaging\n // ─────────────────────────────────────────────────────────────────────────\n\n private get maxMessageBytes(): number | undefined {\n return this.peerConnection?.sctp?.maxMessageSize ?? undefined;\n }\n\n sendCommand(\n command: string,\n data: any,\n scope: MessageScope = \"application\"\n ): void {\n if (!this.dataChannel) {\n throw new Error(\"[WebRTCTransport] Data channel not available\");\n }\n\n try {\n webrtc.sendMessage(\n this.dataChannel,\n command,\n data,\n scope,\n this.maxMessageBytes\n );\n } catch (error) {\n console.warn(\"[WebRTCTransport] Failed to send message:\", error);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Track Publishing\n // ─────────────────────────────────────────────────────────────────────────\n\n async publishTrack(name: string, track: MediaStreamTrack): Promise<void> {\n if (!this.peerConnection) {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - not initialized`\n );\n }\n\n if (this.status !== \"connected\") {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - not connected`\n );\n }\n\n const entry = this.transceiverMap.get(name);\n if (!entry || !entry.transceiver) {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - no transceiver ` +\n `(was it declared in capabilities?)`\n );\n }\n\n if (entry.direction === \"recvonly\") {\n throw new Error(\n `[WebRTCTransport] Cannot publish track \"${name}\" - transceiver is recvonly`\n );\n }\n\n await entry.transceiver.sender.replaceTrack(track);\n this.publishedTracks.set(name, track);\n console.debug(`[WebRTCTransport] Track \"${name}\" published successfully`);\n }\n\n async unpublishTrack(name: string): Promise<void> {\n const entry = this.transceiverMap.get(name);\n if (!entry?.transceiver || !this.publishedTracks.has(name)) return;\n\n try {\n await entry.transceiver.sender.replaceTrack(null);\n console.debug(\n `[WebRTCTransport] Track \"${name}\" unpublished successfully`\n );\n } catch (error) {\n console.error(\n `[WebRTCTransport] Failed to unpublish track \"${name}\":`,\n error\n );\n throw error;\n } finally {\n this.publishedTracks.delete(name);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Stats\n // ─────────────────────────────────────────────────────────────────────────\n\n getStats(): ConnectionStats | undefined {\n return this.stats;\n }\n\n getTransportTimings(): WebRTCTransportTimings | undefined {\n if (this.iceNegotiationMs == null || this.dataChannelMs == null) {\n return undefined;\n }\n return {\n protocol: \"webrtc\",\n sdpPollingMs: this.sdpPollingMs ?? 0,\n sdpPollingAttempts: this.sdpPollingAttempts ?? 0,\n iceNegotiationMs: this.iceNegotiationMs,\n dataChannelMs: this.dataChannelMs,\n };\n }\n\n private resetTransportTimings(): void {\n this.iceStartTime = undefined;\n this.iceNegotiationMs = undefined;\n this.dataChannelMs = undefined;\n this.sdpPollingMs = undefined;\n this.sdpPollingAttempts = undefined;\n }\n\n private startStatsPolling(): void {\n this.stopStatsPolling();\n this.statsInterval = setInterval(async () => {\n if (!this.peerConnection) return;\n try {\n const report = await this.peerConnection.getStats();\n this.stats = webrtc.extractConnectionStats(report);\n this.emit(\"statsUpdate\", this.stats);\n } catch {\n // Connection may be closing\n }\n }, STATS_INTERVAL_MS);\n }\n\n private stopStatsPolling(): void {\n if (this.statsInterval !== undefined) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n this.stats = undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Ping (Client Liveness)\n // ─────────────────────────────────────────────────────────────────────────\n\n private startPing(): void {\n this.stopPing();\n this.pingInterval = setInterval(() => {\n if (this.dataChannel?.readyState === \"open\") {\n try {\n webrtc.sendMessage(this.dataChannel, \"ping\", {}, \"runtime\");\n } catch {\n // Data channel may be closing\n }\n }\n }, PING_INTERVAL_MS);\n }\n\n private stopPing(): void {\n if (this.pingInterval !== undefined) {\n clearInterval(this.pingInterval);\n this.pingInterval = undefined;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Internal Helpers\n // ─────────────────────────────────────────────────────────────────────────\n\n private checkFullyConnected(): void {\n if (this.peerConnected && this.dataChannelOpen) {\n this.setStatus(\"connected\");\n this.startStatsPolling();\n }\n }\n\n private setStatus(newStatus: TransportStatus): void {\n if (this.status !== newStatus) {\n this.status = newStatus;\n this.emit(\"statusChanged\", newStatus);\n }\n }\n\n private setupPeerConnectionHandlers(): void {\n if (!this.peerConnection) return;\n\n this.peerConnection.onconnectionstatechange = () => {\n const state = this.peerConnection?.connectionState;\n console.debug(\"[WebRTCTransport] Connection state:\", state);\n\n if (state) {\n switch (state) {\n case \"connected\":\n if (this.iceStartTime != null && this.iceNegotiationMs == null) {\n this.iceNegotiationMs = performance.now() - this.iceStartTime;\n }\n this.peerConnected = true;\n this.checkFullyConnected();\n break;\n case \"disconnected\":\n case \"closed\":\n this.peerConnected = false;\n this.setStatus(\"disconnected\");\n break;\n case \"failed\":\n this.peerConnected = false;\n this.setStatus(\"error\");\n break;\n }\n }\n };\n\n this.peerConnection.ontrack = (event) => {\n let trackName: string | undefined;\n for (const [name, entry] of this.transceiverMap) {\n if (entry.transceiver === event.transceiver) {\n trackName = name;\n break;\n }\n }\n trackName ??= event.transceiver.mid ?? `unknown-${event.track.id}`;\n\n console.debug(\n `[WebRTCTransport] Track received: \"${trackName}\" (${event.track.kind}, mid=${event.transceiver.mid})`\n );\n const stream = event.streams[0] ?? new MediaStream([event.track]);\n this.emit(\"trackReceived\", trackName, event.track, stream);\n };\n\n this.peerConnection.onicecandidate = (event) => {\n if (event.candidate) {\n console.debug(\"[WebRTCTransport] ICE candidate:\", event.candidate);\n }\n };\n\n this.peerConnection.onicecandidateerror = (event) => {\n console.warn(\"[WebRTCTransport] ICE candidate error:\", event);\n };\n\n this.peerConnection.ondatachannel = (event) => {\n console.debug(\"[WebRTCTransport] Data channel received from remote\");\n this.dataChannel = event.channel;\n this.setupDataChannelHandlers();\n };\n }\n\n private setupDataChannelHandlers(): void {\n if (!this.dataChannel) return;\n\n this.dataChannel.onopen = () => {\n console.debug(\"[WebRTCTransport] Data channel open\");\n if (this.iceStartTime != null && this.dataChannelMs == null) {\n this.dataChannelMs = performance.now() - this.iceStartTime;\n }\n this.dataChannelOpen = true;\n this.startPing();\n this.checkFullyConnected();\n };\n\n this.dataChannel.onclose = () => {\n console.debug(\"[WebRTCTransport] Data channel closed\");\n this.dataChannelOpen = false;\n this.stopPing();\n };\n\n this.dataChannel.onerror = (error) => {\n console.error(\"[WebRTCTransport] Data channel error:\", error);\n };\n\n this.dataChannel.onmessage = (event) => {\n const rawData = webrtc.parseMessage(event.data) as any;\n console.debug(\"[WebRTCTransport] Received message:\", rawData);\n\n try {\n if (rawData?.scope === \"application\" && rawData?.data !== undefined) {\n this.emit(\"message\", rawData.data, \"application\" as MessageScope);\n } else if (\n rawData?.scope === \"runtime\" &&\n rawData?.data !== undefined\n ) {\n this.emit(\"message\", rawData.data, \"runtime\" as MessageScope);\n } else {\n console.warn(\n \"[WebRTCTransport] Received message without envelope, treating as application\"\n );\n this.emit(\"message\", rawData, \"application\" as MessageScope);\n }\n } catch (error) {\n console.error(\n \"[WebRTCTransport] Failed to parse/validate message:\",\n error\n );\n }\n };\n }\n}\n","// Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.\n\nimport {\n type ReactorEvent,\n type ReactorStatus,\n type ReactorState,\n type ReactorError,\n type MessageScope,\n type ConnectOptions,\n type ConnectionStats,\n type ConnectionTimings,\n isAbortError,\n} from \"../types\";\nimport { CoordinatorClient } from \"./CoordinatorClient\";\nimport { LocalCoordinatorClient } from \"./LocalCoordinatorClient\";\nimport { type TransportClient, type TransportStatus } from \"./TransportClient\";\nimport { WebRTCTransportClient } from \"./WebRTCTransportClient\";\nimport {\n type Capabilities,\n type SessionResponse,\n type TrackCapability,\n REACTOR_WEBRTC_VERSION,\n} from \"./types\";\nimport { z } from \"zod\";\n\nconst LOCAL_COORDINATOR_URL = \"http://localhost:8080\";\nexport const DEFAULT_BASE_URL = \"https://api.reactor.inc\";\n\nconst OptionsSchema = z.object({\n apiUrl: z.string().default(DEFAULT_BASE_URL),\n modelName: z.string(),\n local: z.boolean().default(false),\n});\nexport type Options = z.input<typeof OptionsSchema>;\n\ntype EventHandler = (...args: any[]) => void;\n\nexport class Reactor {\n private coordinatorClient: CoordinatorClient | undefined;\n private transportClient: TransportClient | undefined;\n private status: ReactorStatus = \"disconnected\";\n private coordinatorUrl: string;\n private lastError?: ReactorError;\n private model: string;\n private sessionExpiration?: number;\n private local: boolean;\n private sessionId?: string;\n private connectStartTime?: number;\n private connectionTimings?: ConnectionTimings;\n\n private capabilities?: Capabilities;\n private tracks: TrackCapability[] = [];\n private sessionResponse?: SessionResponse;\n\n constructor(options: Options) {\n const validatedOptions = OptionsSchema.parse(options);\n this.coordinatorUrl = validatedOptions.apiUrl;\n this.model = validatedOptions.modelName;\n this.local = validatedOptions.local;\n if (this.local && options.apiUrl === undefined) {\n this.coordinatorUrl = LOCAL_COORDINATOR_URL;\n }\n }\n\n private eventListeners: Map<ReactorEvent, Set<EventHandler>> = new Map();\n\n on(event: ReactorEvent, handler: EventHandler) {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(handler);\n }\n\n off(event: ReactorEvent, handler: EventHandler) {\n this.eventListeners.get(event)?.delete(handler);\n }\n\n emit(event: ReactorEvent, ...args: any[]) {\n this.eventListeners.get(event)?.forEach((handler) => handler(...args));\n }\n\n /**\n * Sends a command to the model via the data channel.\n */\n async sendCommand(\n command: string,\n data: any,\n scope: MessageScope = \"application\"\n ): Promise<void> {\n if (process.env.NODE_ENV !== \"development\" && this.status !== \"ready\") {\n const errorMessage = `Cannot send message, status is ${this.status}`;\n console.warn(\"[Reactor]\", errorMessage);\n return;\n }\n\n try {\n this.transportClient?.sendCommand(command, data, scope);\n } catch (error) {\n console.error(\"[Reactor] Failed to send message:\", error);\n this.createError(\n \"MESSAGE_SEND_FAILED\",\n `Failed to send message: ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n /**\n * Publishes a MediaStreamTrack to a named sendonly track.\n * The transceiver is already set up from capabilities — this just\n * calls replaceTrack() on the sender.\n */\n async publishTrack(name: string, track: MediaStreamTrack): Promise<void> {\n if (process.env.NODE_ENV !== \"development\" && this.status !== \"ready\") {\n console.warn(\n `[Reactor] Cannot publish track \"${name}\", status is ${this.status}`\n );\n return;\n }\n\n try {\n await this.transportClient?.publishTrack(name, track);\n } catch (error) {\n console.error(`[Reactor] Failed to publish track \"${name}\":`, error);\n this.createError(\n \"TRACK_PUBLISH_FAILED\",\n `Failed to publish track \"${name}\": ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n async unpublishTrack(name: string): Promise<void> {\n try {\n await this.transportClient?.unpublishTrack(name);\n } catch (error) {\n console.error(`[Reactor] Failed to unpublish track \"${name}\":`, error);\n this.createError(\n \"TRACK_UNPUBLISH_FAILED\",\n `Failed to unpublish track \"${name}\": ${error}`,\n \"gpu\",\n true\n );\n }\n }\n\n /**\n * Reconnects to an existing session with a fresh transport.\n */\n async reconnect(options?: ConnectOptions): Promise<void> {\n if (!this.sessionId || !this.coordinatorClient) {\n console.warn(\"[Reactor] No active session to reconnect to.\");\n return;\n }\n\n if (this.status === \"ready\") {\n console.warn(\"[Reactor] Already connected, no need to reconnect.\");\n return;\n }\n\n if (this.tracks.length === 0) {\n console.warn(\"[Reactor] No tracks available for reconnect.\");\n return;\n }\n\n this.setStatus(\"connecting\");\n\n try {\n if (!this.transportClient) {\n this.transportClient = new WebRTCTransportClient({\n baseUrl: this.coordinatorUrl,\n sessionId: this.sessionId,\n jwtToken: this.local ? \"local\" : \"\",\n maxPollAttempts: options?.maxAttempts,\n });\n this.setupTransportHandlers();\n }\n\n await this.transportClient.reconnect(this.tracks);\n } catch (error) {\n if (isAbortError(error)) return;\n\n console.error(\"[Reactor] Failed to reconnect:\", error);\n this.disconnect(true);\n this.createError(\n \"RECONNECTION_FAILED\",\n `Failed to reconnect: ${error}`,\n \"api\",\n true\n );\n }\n }\n\n /**\n * Connects to the coordinator, creates a session, then establishes\n * the transport using server-declared capabilities.\n */\n async connect(jwtToken?: string, options?: ConnectOptions): Promise<void> {\n console.debug(\"[Reactor] Connecting, status:\", this.status);\n\n if (jwtToken == undefined && !this.local) {\n throw new Error(\"No authentication provided and not in local mode\");\n }\n\n if (this.status !== \"disconnected\") {\n throw new Error(\"Already connected or connecting\");\n }\n this.setStatus(\"connecting\");\n\n this.connectStartTime = performance.now();\n\n try {\n this.coordinatorClient = this.local\n ? new LocalCoordinatorClient(this.coordinatorUrl, this.model)\n : new CoordinatorClient({\n baseUrl: this.coordinatorUrl,\n jwtToken: jwtToken!,\n model: this.model,\n });\n\n // 1. Create session — slim response with session_id and status\n const tSession = performance.now();\n const initialResponse = await this.coordinatorClient.createSession();\n const sessionCreationMs = performance.now() - tSession;\n\n this.setSessionId(initialResponse.session_id);\n\n console.debug(\n \"[Reactor] Session created:\",\n initialResponse.session_id,\n \"state:\",\n initialResponse.state\n );\n\n // 2. Poll until the Runtime accepts and capabilities are available\n this.setStatus(\"waiting\");\n\n const tPoll = performance.now();\n const sessionResponse = await this.coordinatorClient.pollSessionReady();\n const sessionPollingMs = performance.now() - tPoll;\n\n this.sessionResponse = sessionResponse;\n\n // 3. Store capabilities and tracks\n this.capabilities = sessionResponse.capabilities!;\n this.tracks = sessionResponse.capabilities!.tracks;\n this.emit(\"capabilitiesReceived\", this.capabilities);\n\n console.debug(\n \"[Reactor] Session ready, transport:\",\n sessionResponse.selected_transport!.protocol,\n \"tracks:\",\n this.tracks.length\n );\n\n // 4. Instantiate transport based on selected_transport\n const protocol = sessionResponse.selected_transport!.protocol;\n if (protocol !== \"webrtc\") {\n throw new Error(`Unsupported transport protocol: ${protocol}`);\n }\n\n this.transportClient = new WebRTCTransportClient({\n baseUrl: this.coordinatorUrl,\n sessionId: sessionResponse.session_id,\n jwtToken: this.local ? \"local\" : jwtToken!,\n webrtcVersion:\n sessionResponse.selected_transport?.version ?? REACTOR_WEBRTC_VERSION,\n maxPollAttempts: options?.maxAttempts,\n });\n this.setupTransportHandlers();\n\n // 5. Connect transport using capabilities tracks\n const tTransport = performance.now();\n await this.transportClient.connect(this.tracks);\n const transportConnectingMs = performance.now() - tTransport;\n\n this.connectionTimings = {\n sessionCreationMs: sessionCreationMs + sessionPollingMs,\n transportConnectingMs,\n totalMs: 0,\n };\n } catch (error) {\n if (isAbortError(error)) return;\n\n console.error(\"[Reactor] Connection failed:\", error);\n this.createError(\n \"CONNECTION_FAILED\",\n `Connection failed: ${error}`,\n \"api\",\n true\n );\n try {\n await this.disconnect(false);\n } catch (disconnectError) {\n console.error(\n \"[Reactor] Failed to clean up after connection failure:\",\n disconnectError\n );\n }\n throw error;\n }\n }\n\n /**\n * Sets up event handlers for the transport client.\n * Each handler captures the client reference to ignore stale events.\n */\n private setupTransportHandlers(): void {\n if (!this.transportClient) return;\n const client = this.transportClient;\n\n client.on(\"message\", (message: any, scope: MessageScope) => {\n if (this.transportClient !== client) return;\n if (scope === \"application\") {\n this.emit(\"message\", message);\n } else if (scope === \"runtime\") {\n this.emit(\"runtimeMessage\", message);\n }\n });\n\n client.on(\"statusChanged\", (status: TransportStatus) => {\n if (this.transportClient !== client) return;\n switch (status) {\n case \"connected\":\n this.finalizeConnectionTimings();\n this.setStatus(\"ready\");\n break;\n case \"disconnected\":\n this.disconnect(true);\n break;\n case \"error\":\n this.createError(\n \"GPU_CONNECTION_ERROR\",\n \"Transport connection failed\",\n \"gpu\",\n true\n );\n this.disconnect();\n break;\n }\n });\n\n client.on(\n \"trackReceived\",\n (name: string, track: MediaStreamTrack, stream: MediaStream) => {\n if (this.transportClient !== client) return;\n this.emit(\"trackReceived\", name, track, stream);\n }\n );\n\n client.on(\"statsUpdate\", (stats: ConnectionStats) => {\n if (this.transportClient !== client) return;\n this.emit(\"statsUpdate\", {\n ...stats,\n connectionTimings: this.connectionTimings,\n });\n });\n }\n\n /**\n * Disconnects from both the transport and the coordinator.\n */\n async disconnect(recoverable: boolean = false) {\n if (this.status === \"disconnected\" && !this.sessionId) {\n console.warn(\"[Reactor] Already disconnected\");\n return;\n }\n\n this.coordinatorClient?.abort();\n this.transportClient?.abort();\n\n if (this.coordinatorClient && !recoverable) {\n try {\n await this.coordinatorClient.terminateSession();\n } catch (error) {\n console.error(\"[Reactor] Error terminating session:\", error);\n }\n this.coordinatorClient = undefined;\n }\n\n if (this.transportClient) {\n try {\n await this.transportClient.disconnect();\n } catch (error) {\n console.error(\"[Reactor] Error disconnecting transport:\", error);\n }\n if (!recoverable) {\n this.transportClient = undefined;\n }\n }\n\n this.setStatus(\"disconnected\");\n this.resetConnectionTimings();\n if (!recoverable) {\n this.setSessionExpiration(undefined);\n this.setSessionId(undefined);\n this.capabilities = undefined;\n this.tracks = [];\n this.sessionResponse = undefined;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Getters\n // ─────────────────────────────────────────────────────────────────────────\n\n getSessionId(): string | undefined {\n return this.sessionId;\n }\n\n getStatus(): ReactorStatus {\n return this.status;\n }\n\n getState(): ReactorState {\n return {\n status: this.status,\n lastError: this.lastError,\n };\n }\n\n getLastError(): ReactorError | undefined {\n return this.lastError;\n }\n\n getCapabilities(): Capabilities | undefined {\n return this.capabilities;\n }\n\n getSessionInfo(): SessionResponse | undefined {\n return this.sessionResponse;\n }\n\n getStats(): ConnectionStats | undefined {\n const stats = this.transportClient?.getStats();\n if (!stats) return undefined;\n return { ...stats, connectionTimings: this.connectionTimings };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Private State Management\n // ─────────────────────────────────────────────────────────────────────────\n\n private setSessionId(newSessionId: string | undefined) {\n console.debug(\n \"[Reactor] Setting session ID:\",\n newSessionId,\n \"from\",\n this.sessionId\n );\n if (this.sessionId !== newSessionId) {\n this.sessionId = newSessionId;\n this.emit(\"sessionIdChanged\", newSessionId);\n }\n }\n\n private setStatus(newStatus: ReactorStatus) {\n console.debug(\"[Reactor] Setting status:\", newStatus, \"from\", this.status);\n if (this.status !== newStatus) {\n this.status = newStatus;\n this.emit(\"statusChanged\", newStatus);\n }\n }\n\n private setSessionExpiration(newSessionExpiration: number | undefined) {\n console.debug(\n \"[Reactor] Setting session expiration:\",\n newSessionExpiration\n );\n if (this.sessionExpiration !== newSessionExpiration) {\n this.sessionExpiration = newSessionExpiration;\n this.emit(\"sessionExpirationChanged\", newSessionExpiration);\n }\n }\n\n private resetConnectionTimings(): void {\n this.connectStartTime = undefined;\n this.connectionTimings = undefined;\n }\n\n private finalizeConnectionTimings(): void {\n if (!this.connectionTimings || this.connectStartTime == null) return;\n\n this.connectionTimings.totalMs = performance.now() - this.connectStartTime;\n this.connectStartTime = undefined;\n\n console.debug(\"[Reactor] Connection timings:\", this.connectionTimings);\n }\n\n private createError(\n code: string,\n message: string,\n component: \"api\" | \"gpu\",\n recoverable: boolean,\n retryAfter?: number\n ) {\n this.lastError = {\n code,\n message,\n timestamp: Date.now(),\n recoverable,\n component,\n retryAfter,\n };\n this.emit(\"error\", this.lastError);\n }\n}\n","\"use client\";\n\nimport { ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport {\n createReactorStore,\n initReactorStore,\n ReactorContext,\n ReactorStore,\n ReactorStoreApi,\n type ReactorInitializationProps,\n} from \"../core/store\";\nimport { useStore } from \"zustand\";\nimport type { ConnectOptions } from \"../types\";\n\n/**\n * Options for the React provider's connect behavior.\n * Extends the core ConnectOptions with autoConnect for the React lifecycle.\n */\nexport interface ReactorConnectOptions extends ConnectOptions {\n /** Whether to automatically connect when the provider mounts. Default: false. */\n autoConnect?: boolean;\n}\n\n// Provider props\ninterface ReactorProviderProps extends ReactorInitializationProps {\n connectOptions?: ReactorConnectOptions;\n jwtToken?: string;\n children: ReactNode;\n}\n\n// tsx component\nexport function ReactorProvider({\n children,\n connectOptions,\n jwtToken,\n ...props\n}: ReactorProviderProps) {\n // Stable Reactor instance\n const storeRef = useRef<ReactorStoreApi | undefined>(undefined);\n const firstRender = useRef(true);\n // State to trigger re-renders when store changes\n const [_storeVersion, setStoreVersion] = useState(0);\n\n if (storeRef.current === undefined) {\n console.debug(\"[ReactorProvider] Creating new reactor store\");\n // We create the store without autoconnecting, to avoid duplicate connections.\n // We actually connect when the component is mounted, to be on sync with the react component lifecycle.\n storeRef.current = createReactorStore(\n initReactorStore({\n ...props,\n jwtToken,\n })\n );\n console.debug(\"[ReactorProvider] Reactor store created successfully\");\n }\n\n // Destructure connectOptions with defaults\n const { autoConnect = false, ...pollingOptions } = connectOptions ?? {};\n\n const { apiUrl, modelName, local } = props;\n const maxAttempts = pollingOptions.maxAttempts;\n\n // Handle page unload (refresh, close, navigate away) with non-recoverable disconnect\n useEffect(() => {\n const handleBeforeUnload = () => {\n console.debug(\n \"[ReactorProvider] Page unloading, performing non-recoverable disconnect\"\n );\n // Call disconnect synchronously - we can't await here as the page is unloading\n // The disconnect(false) ensures non-recoverable cleanup (stops session, clears state)\n storeRef.current?.getState().internal.reactor.disconnect(false);\n };\n\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\n\n return () => {\n window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n };\n }, []);\n\n useEffect(() => {\n if (firstRender.current) {\n firstRender.current = false;\n\n // We know as a fact that the store is not undefined at this point\n const current = storeRef.current!;\n if (\n autoConnect &&\n current.getState().status === \"disconnected\" &&\n jwtToken\n ) {\n console.debug(\n \"[ReactorProvider] Starting autoconnect in first render...\"\n );\n current\n .getState()\n .connect(jwtToken, pollingOptions)\n .then(() => {\n console.debug(\n \"[ReactorProvider] Autoconnect successful in first render\"\n );\n })\n .catch((error) => {\n console.error(\n \"[ReactorProvider] Failed to autoconnect in first render:\",\n error\n );\n });\n }\n return () => {\n console.debug(\n \"[ReactorProvider] Disconnecting in cleanup for first render\"\n );\n current\n .getState()\n .disconnect()\n .then(() => {\n console.debug(\n \"[ReactorProvider] Disconnect completed successfully in cleanup for first render\"\n );\n })\n .catch((error) => {\n console.error(\n \"[ReactorProvider] Failed to disconnect in cleanup for first render:\",\n error\n );\n });\n };\n }\n\n console.debug(\"[ReactorProvider] Updating reactor store\");\n storeRef.current = createReactorStore(\n initReactorStore({\n apiUrl,\n modelName,\n local,\n jwtToken,\n } satisfies ReactorInitializationProps)\n );\n\n // Store current reference to the store in the return\n const current = storeRef.current!;\n\n // Increment version to trigger re-render and propagate new store to Provider\n setStoreVersion((v) => v + 1);\n console.debug(\n \"[ReactorProvider] Reactor store updated successfully, and increased version\"\n );\n\n if (\n autoConnect &&\n current.getState().status === \"disconnected\" &&\n jwtToken\n ) {\n console.debug(\"[ReactorProvider] Starting autoconnect...\");\n current\n .getState()\n .connect(jwtToken, pollingOptions)\n .then(() => {\n console.debug(\"[ReactorProvider] Autoconnect successful\");\n })\n .catch((error) => {\n console.error(\"[ReactorProvider] Failed to autoconnect:\", error);\n });\n }\n\n return () => {\n console.debug(\"[ReactorProvider] Disconnecting in cleanup\");\n current\n .getState()\n .disconnect()\n .then(() => {\n console.debug(\n \"[ReactorProvider] Disconnect completed successfully in cleanup\"\n );\n })\n .catch((error) => {\n console.error(\"[ReactorProvider] Failed to disconnect:\", error);\n });\n };\n }, [apiUrl, modelName, autoConnect, local, jwtToken, maxAttempts]);\n\n return (\n <ReactorContext.Provider value={storeRef.current}>\n {children}\n </ReactorContext.Provider>\n );\n}\n\nexport function useReactorStore<T = ReactorStore>(\n selector: (state: ReactorStore) => T\n): T {\n const ctx = useContext(ReactorContext);\n if (!ctx) {\n throw new Error(\"useReactor must be used within a ReactorProvider\");\n }\n\n return useStore(ctx, selector);\n}\n","import { StoreApi } from \"zustand\";\nimport type {\n ReactorStatus,\n ReactorError,\n MessageScope,\n ConnectOptions,\n} from \"../types\";\nimport { Reactor, type Options as ReactorOptions } from \"./Reactor\";\nimport { create } from \"zustand/react\";\nimport { createContext } from \"react\";\n\nexport type ReactorStoreApi = ReturnType<typeof createReactorStore>;\n\nexport interface ReactorState {\n status: ReactorStatus;\n /**\n * Media tracks received from the model, keyed by track name.\n *\n * Each entry maps a recvonly track name (e.g. `\"main_video\"`,\n * `\"main_audio\"`) to the live `MediaStreamTrack` delivered by the model.\n */\n tracks: Record<string, MediaStreamTrack>;\n lastError?: ReactorError;\n sessionId?: string;\n sessionExpiration?: number;\n jwtToken?: string;\n}\n\nexport interface ReactorActions {\n sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;\n connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;\n disconnect(recoverable?: boolean): Promise<void>;\n publish(name: string, track: MediaStreamTrack): Promise<void>;\n unpublish(name: string): Promise<void>;\n reconnect(options?: ConnectOptions): Promise<void>;\n}\n\n// Internal state not exposed to components\ninterface ReactorInternalState {\n reactor: Reactor;\n}\n\nexport const ReactorContext = createContext<ReactorStoreApi | undefined>(\n undefined\n);\n\nexport type ReactorStore = ReactorState &\n ReactorActions & {\n internal: ReactorInternalState;\n };\n\n// We introduce two methods to perform authentication:\n// - putting the auth information inside of the ReactorProvider props, and then calling connect() without arguments.\n// - not putting anything in the props, and then calling connect() passing as arguments the auth information.\n// When in the first case, the auth information is saved in the STATE. Then, when you call connect() without arguments,\n// the actual auth information is fetched from that STATE.\n// In the second case, you pass the auth information directly into the function in the Reactor core.\nexport const defaultInitState: ReactorState = {\n status: \"disconnected\",\n tracks: {},\n lastError: undefined,\n sessionExpiration: undefined,\n jwtToken: undefined,\n sessionId: undefined,\n};\n\nexport interface ReactorInitializationProps extends ReactorOptions {\n jwtToken?: string;\n}\n\nexport const initReactorStore = (\n props: ReactorInitializationProps\n): ReactorState & ReactorInitializationProps => {\n return {\n ...defaultInitState,\n // These are only used for dev initialization, not exposed in the store\n ...props,\n };\n};\n\nexport const createReactorStore = (\n initProps: ReactorInitializationProps,\n publicState: ReactorState = defaultInitState\n): StoreApi<ReactorStore> => {\n console.debug(\"[ReactorStore] Creating store\", {\n apiUrl: initProps.apiUrl,\n jwtToken: initProps.jwtToken,\n initialState: publicState,\n });\n\n return create<ReactorStore>()((set, get) => {\n const reactor = new Reactor(initProps);\n\n console.debug(\"[ReactorStore] Setting up event listeners\");\n\n reactor.on(\"statusChanged\", (newStatus: ReactorStatus) => {\n console.debug(\"[ReactorStore] Status changed\", {\n oldStatus: get().status,\n newStatus,\n });\n if (newStatus === \"disconnected\") {\n set({ status: newStatus, tracks: {} });\n } else {\n set({ status: newStatus });\n }\n });\n\n reactor.on(\n \"sessionExpirationChanged\",\n (newSessionExpiration: number | undefined) => {\n console.debug(\"[ReactorStore] Session expiration changed\", {\n oldSessionExpiration: get().sessionExpiration,\n newSessionExpiration: newSessionExpiration,\n });\n set({ sessionExpiration: newSessionExpiration });\n }\n );\n\n reactor.on(\"trackReceived\", (name: string, track: MediaStreamTrack) => {\n console.debug(\"[ReactorStore] Track received\", {\n name,\n kind: track.kind,\n id: track.id,\n });\n set({ tracks: { ...get().tracks, [name]: track } });\n });\n\n reactor.on(\"error\", (error: ReactorError) => {\n console.debug(\"[ReactorStore] Error occurred\", error);\n set({ lastError: error });\n });\n\n reactor.on(\"sessionIdChanged\", (newSessionId: string | undefined) => {\n console.debug(\"[ReactorStore] Session ID changed\", {\n oldSessionId: get().sessionId,\n newSessionId: newSessionId,\n });\n set({ sessionId: newSessionId });\n });\n\n return {\n ...publicState,\n jwtToken: initProps.jwtToken,\n internal: { reactor },\n\n // actions\n onMessage: (handler: (message: any) => void) => {\n console.debug(\"[ReactorStore] Registering message handler\");\n\n get().internal.reactor.on(\"message\", handler);\n\n return () => {\n console.debug(\"[ReactorStore] Cleaning up message handler\");\n get().internal.reactor.off(\"message\", handler);\n };\n },\n sendCommand: async (command: string, data: any, scope?: MessageScope) => {\n console.debug(\"[ReactorStore] Sending command\", {\n command,\n data,\n scope,\n });\n try {\n await get().internal.reactor.sendCommand(command, data, scope);\n console.debug(\"[ReactorStore] Command sent successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Failed to send command:\", error);\n throw error;\n }\n },\n connect: async (jwtToken?: string, options?: ConnectOptions) => {\n if (jwtToken === undefined) {\n // If no JWT Token, it might have been passed in the constructor props. So read from it.\n jwtToken = get().jwtToken;\n }\n\n console.debug(\"[ReactorStore] Connect called.\");\n\n try {\n await get().internal.reactor.connect(jwtToken, options);\n console.debug(\"[ReactorStore] Connect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Connect failed:\", error);\n throw error;\n }\n },\n disconnect: async (recoverable: boolean = false) => {\n console.debug(\"[ReactorStore] Disconnect called\", {\n currentStatus: get().status,\n });\n\n try {\n await get().internal.reactor.disconnect(recoverable);\n console.debug(\"[ReactorStore] Disconnect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Disconnect failed:\", error);\n throw error;\n }\n },\n publish: async (name: string, track: MediaStreamTrack) => {\n console.debug(`[ReactorStore] Publishing track \"${name}\"`);\n\n try {\n await get().internal.reactor.publishTrack(name, track);\n console.debug(\n `[ReactorStore] Track \"${name}\" published successfully`\n );\n } catch (error) {\n console.error(\n `[ReactorStore] Failed to publish track \"${name}\":`,\n error\n );\n throw error;\n }\n },\n unpublish: async (name: string) => {\n console.debug(`[ReactorStore] Unpublishing track \"${name}\"`);\n\n try {\n await get().internal.reactor.unpublishTrack(name);\n console.debug(\n `[ReactorStore] Track \"${name}\" unpublished successfully`\n );\n } catch (error) {\n console.error(\n `[ReactorStore] Failed to unpublish track \"${name}\":`,\n error\n );\n throw error;\n }\n },\n reconnect: async (options?: ConnectOptions) => {\n console.debug(\"[ReactorStore] Reconnecting\");\n try {\n await get().internal.reactor.reconnect(options);\n console.debug(\"[ReactorStore] Reconnect completed successfully\");\n } catch (error) {\n console.error(\"[ReactorStore] Failed to reconnect:\", error);\n throw error;\n }\n },\n };\n });\n};\n","import { useReactorStore } from \"./ReactorProvider\";\nimport type { ReactorStore } from \"../core/store\";\nimport type { ConnectionStats } from \"../types\";\nimport { useShallow } from \"zustand/shallow\";\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Generic hook for accessing selected parts of the Reactor store.\n *\n * @param selector - A function that selects part of the store state.\n * @returns The selected slice from the store.\n */\nexport function useReactor<T>(selector: (state: ReactorStore) => T): T {\n return useReactorStore(useShallow(selector));\n}\n\n/**\n * Hook for receiving model application messages.\n *\n * Only fires for messages sent by the model via `get_ctx().send()`.\n * Internal platform-level messages (e.g. capabilities) are NOT delivered here.\n *\n * @param handler - Callback invoked with each application message payload.\n */\nexport function useReactorMessage(handler: (message: any) => void): void {\n const reactor = useReactor((state) => state.internal.reactor);\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const stableHandler = (message: any) => {\n handlerRef.current(message);\n };\n\n reactor.on(\"message\", stableHandler);\n\n return () => {\n reactor.off(\"message\", stableHandler);\n };\n }, [reactor]);\n}\n\n/**\n * Hook for receiving internal platform-level (runtime) messages.\n *\n * This is intended for advanced use cases that need access to the runtime\n * control layer, such as capabilities negotiation. Model application messages\n * sent via `get_ctx().send()` are NOT delivered through this hook — use\n * {@link useReactorMessage} for those.\n *\n * @param handler - Callback invoked with each runtime message payload.\n */\nexport function useReactorInternalMessage(\n handler: (message: any) => void\n): void {\n const reactor = useReactor((state) => state.internal.reactor);\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const stableHandler = (message: any) => {\n handlerRef.current(message);\n };\n\n reactor.on(\"runtimeMessage\", stableHandler);\n\n return () => {\n reactor.off(\"runtimeMessage\", stableHandler);\n };\n }, [reactor]);\n}\n\n/**\n * Hook that returns the current connection stats (RTT, etc.).\n * Updates every ~2s while connected. Returns undefined when disconnected.\n */\nexport function useStats(): ConnectionStats | undefined {\n const reactor = useReactor((state) => state.internal.reactor);\n const [stats, setStats] = useState<ConnectionStats | undefined>(undefined);\n\n useEffect(() => {\n const handler = (newStats: ConnectionStats) => {\n setStats(newStats);\n };\n\n reactor.on(\"statsUpdate\", handler);\n\n return () => {\n reactor.off(\"statsUpdate\", handler);\n setStats(undefined);\n };\n }, [reactor]);\n\n return stats;\n}\n","\"use client\";\n\nimport { useReactor } from \"./hooks\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport React from \"react\";\n\nexport interface ReactorViewProps {\n /**\n * The name of the recvonly track to render.\n * Must match a track name declared in the server capabilities.\n * Check the model's documentation for available track names.\n * Defaults to `\"main_video\"`.\n */\n track?: string;\n /**\n * Optional name of a recvonly audio track to play alongside the video\n * (e.g. `\"main_audio\"`). The audio is mixed into the same `<video>` element.\n * Check the model's documentation for available track names.\n */\n audioTrack?: string;\n width?: number;\n height?: number;\n className?: string;\n style?: React.CSSProperties;\n videoObjectFit?: NonNullable<\n React.VideoHTMLAttributes<HTMLVideoElement>[\"style\"]\n >[\"objectFit\"];\n /** Controls whether inbound audio plays. Default true (muted) to satisfy browser autoplay policies. */\n muted?: boolean;\n}\n\nexport function ReactorView({\n track = \"main_video\",\n audioTrack,\n width,\n height,\n className,\n style,\n videoObjectFit = \"contain\",\n muted = true,\n}: ReactorViewProps) {\n const { videoMediaTrack, audioMediaTrack, status } = useReactor((state) => ({\n videoMediaTrack: state.tracks[track] ?? null,\n audioMediaTrack: audioTrack ? (state.tracks[audioTrack] ?? null) : null,\n status: state.status,\n }));\n\n const videoRef = useRef<HTMLVideoElement>(null);\n\n const mediaStream = useMemo(() => {\n const tracks: MediaStreamTrack[] = [];\n if (videoMediaTrack) tracks.push(videoMediaTrack);\n if (audioMediaTrack) tracks.push(audioMediaTrack);\n if (tracks.length === 0) return null;\n return new MediaStream(tracks);\n }, [videoMediaTrack, audioMediaTrack]);\n\n useEffect(() => {\n console.debug(\"[ReactorView] Media track effect triggered\", {\n track,\n hasVideoElement: !!videoRef.current,\n hasVideoTrack: !!videoMediaTrack,\n hasAudioTrack: !!audioMediaTrack,\n });\n\n if (videoRef.current && mediaStream) {\n console.debug(\"[ReactorView] Attaching media stream to element\");\n try {\n videoRef.current.srcObject = mediaStream;\n videoRef.current.play().catch((e) => {\n console.warn(\"[ReactorView] Auto-play failed:\", e);\n });\n console.debug(\"[ReactorView] Media stream attached successfully\");\n } catch (error) {\n console.error(\"[ReactorView] Failed to attach media stream:\", error);\n }\n\n return () => {\n console.debug(\"[ReactorView] Detaching media stream from element\");\n if (videoRef.current) {\n videoRef.current.srcObject = null;\n }\n };\n } else {\n console.debug(\"[ReactorView] No tracks or element to attach\");\n }\n }, [mediaStream]);\n\n const showPlaceholder = !videoMediaTrack;\n\n return (\n <div\n style={{\n position: \"relative\",\n background: \"#000\",\n ...(width && { width }),\n ...(height && { height }),\n ...style,\n }}\n className={className}\n >\n <video\n ref={videoRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: videoObjectFit,\n display: showPlaceholder ? \"none\" : \"block\",\n }}\n muted={muted}\n playsInline\n />\n {showPlaceholder && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"16px\",\n fontFamily: \"monospace\",\n textAlign: \"center\",\n padding: \"20px\",\n boxSizing: \"border-box\",\n }}\n >\n {status}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useReactor, useReactorInternalMessage } from \"./hooks\";\nimport React, { useState, useCallback } from \"react\";\n\nexport interface ReactorControllerProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface CommandParamSchema {\n description?: string;\n type: string;\n minimum?: number;\n maximum?: number;\n required?: boolean;\n enum?: string[];\n}\n\ninterface CommandSchema {\n description: string;\n schema: Record<string, CommandParamSchema>;\n}\n\n// The runtime sends commands as a list of {name, description, schema}\n// matching the proto Command message.\ninterface CommandCapabilityMessage {\n name: string;\n description: string;\n schema?: Record<string, CommandParamSchema>;\n}\n\ninterface CommandsMessage {\n commands: CommandCapabilityMessage[];\n}\n\nexport function ReactorController({\n className,\n style,\n}: ReactorControllerProps) {\n const { sendCommand, status } = useReactor((state) => ({\n sendCommand: state.sendCommand,\n status: state.status,\n }));\n const [commands, setCommands] = useState<Record<string, CommandSchema>>({});\n const [formValues, setFormValues] = useState<\n Record<string, Record<string, any>>\n >({});\n const [expandedCommands, setExpandedCommands] = useState<\n Record<string, boolean>\n >({});\n\n // Reset commands when disconnected\n React.useEffect(() => {\n if (status === \"disconnected\") {\n setCommands({});\n setFormValues({});\n setExpandedCommands({});\n }\n }, [status]);\n\n // Function to request capabilities (sent on the \"runtime\" channel)\n const requestCapabilities = useCallback(() => {\n if (status === \"ready\") {\n sendCommand(\"requestCapabilities\", {}, \"runtime\");\n }\n }, [status, sendCommand]);\n\n // Send requestCapabilities when ready\n React.useEffect(() => {\n if (status === \"ready\") {\n requestCapabilities();\n }\n }, [status, requestCapabilities]);\n\n // Retry every 5 seconds if capabilities not set\n React.useEffect(() => {\n // Only set up interval if status is ready and commands are empty\n if (status !== \"ready\" || Object.keys(commands).length > 0) {\n return;\n }\n\n const interval = setInterval(() => {\n requestCapabilities();\n }, 5000);\n\n return () => clearInterval(interval);\n }, [status, commands, requestCapabilities]);\n\n useReactorInternalMessage((message) => {\n if (\n message &&\n typeof message === \"object\" &&\n message.type === \"modelCapabilities\" &&\n message.data &&\n \"commands\" in message.data\n ) {\n const commandsMessage = message.data as CommandsMessage;\n\n // Convert the list of command descriptors (proto Command shape)\n // into a Record keyed by name for the controller's internal state.\n const commandsRecord: Record<string, CommandSchema> = {};\n for (const cmd of commandsMessage.commands) {\n commandsRecord[cmd.name] = {\n description: cmd.description,\n schema: cmd.schema ?? {},\n };\n }\n setCommands(commandsRecord);\n\n // Initialize form values for each command\n const initialValues: Record<string, Record<string, any>> = {};\n const initialExpanded: Record<string, boolean> = {};\n\n Object.entries(commandsRecord).forEach(([commandName, commandSchema]) => {\n initialValues[commandName] = {};\n initialExpanded[commandName] = false;\n\n Object.entries(commandSchema.schema).forEach(\n ([paramName, paramSchema]) => {\n if (paramSchema.type === \"number\") {\n initialValues[commandName][paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"string\") {\n initialValues[commandName][paramName] = \"\";\n } else if (paramSchema.type === \"boolean\") {\n initialValues[commandName][paramName] = false;\n } else if (paramSchema.type === \"integer\") {\n initialValues[commandName][paramName] = paramSchema.minimum ?? 0;\n }\n }\n );\n });\n setFormValues(initialValues);\n setExpandedCommands(initialExpanded);\n }\n });\n\n const handleInputChange = useCallback(\n (commandName: string, paramName: string, value: any) => {\n setFormValues((prev) => ({\n ...prev,\n [commandName]: {\n ...prev[commandName],\n [paramName]: value,\n },\n }));\n },\n []\n );\n\n const toggleCommandExpanded = useCallback((commandName: string) => {\n setExpandedCommands((prev) => ({\n ...prev,\n [commandName]: !prev[commandName],\n }));\n }, []);\n\n const handleCommandSubmit = useCallback(\n async (commandName: string) => {\n const commandSchema = commands[commandName];\n const formData = formValues[commandName] || {};\n\n // Build the data object according to the schema structure\n const data: Record<string, any> = {};\n\n // Only include parameters that are defined in the schema\n Object.keys(commandSchema.schema).forEach((paramName) => {\n const paramSchema = commandSchema.schema[paramName];\n let value = formData[paramName];\n\n // Type conversion based on schema\n if (paramSchema.type === \"number\" && typeof value === \"string\") {\n value = parseFloat(value) || 0;\n } else if (\n paramSchema.type === \"integer\" &&\n typeof value === \"string\"\n ) {\n value = parseInt(value) || 0;\n } else if (\n paramSchema.type === \"boolean\" &&\n typeof value !== \"boolean\"\n ) {\n value = Boolean(value);\n }\n\n // Only include the parameter if it has a value or is required\n if (value !== undefined && value !== \"\" && value !== null) {\n data[paramName] = value;\n } else if (paramSchema.required) {\n // Set default values for required parameters\n if (paramSchema.type === \"number\") {\n data[paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"integer\") {\n data[paramName] = paramSchema.minimum ?? 0;\n } else if (paramSchema.type === \"string\") {\n data[paramName] = \"\";\n } else if (paramSchema.type === \"boolean\") {\n data[paramName] = false;\n }\n }\n });\n\n console.log(`Executing command: ${commandName}`, data);\n\n await sendCommand(commandName, data);\n },\n [formValues, sendCommand, commands]\n );\n\n const renderInput = (\n commandName: string,\n paramName: string,\n paramSchema: any\n ) => {\n const value = formValues[commandName]?.[paramName] ?? \"\";\n\n if (paramSchema.type === \"number\" || paramSchema.type === \"integer\") {\n const isInteger = paramSchema.type === \"integer\";\n const step = isInteger ? 1 : 0.1;\n const parseValue = isInteger ? parseInt : parseFloat;\n\n // Use slider if min/max are defined, otherwise use number input\n if (\n typeof paramSchema.minimum === \"number\" &&\n typeof paramSchema.maximum === \"number\"\n ) {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName} ({paramSchema.minimum} - {paramSchema.maximum})\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"range\"\n min={paramSchema.minimum}\n max={paramSchema.maximum}\n step={step}\n value={value}\n onChange={(e) => {\n const newValue = parseValue(e.target.value) || 0;\n handleInputChange(commandName, paramName, newValue);\n // Execute command immediately for sliders\n handleCommandSubmit(commandName);\n }}\n style={{ width: \"100%\", marginBottom: \"4px\" }}\n />\n <div style={{ fontSize: \"11px\", color: \"#888\" }}>\n Value: {value}\n </div>\n </div>\n );\n } else {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"number\"\n value={value}\n min={paramSchema.minimum}\n max={paramSchema.maximum}\n step={step}\n inputMode=\"numeric\"\n onChange={(e) => {\n const val = e.target.value;\n if (val === \"\" || val === \"-\") {\n // Allow empty or just minus sign while typing\n handleInputChange(commandName, paramName, val);\n } else {\n const parsed = parseValue(val);\n if (!isNaN(parsed)) {\n handleInputChange(commandName, paramName, parsed);\n }\n }\n }}\n onBlur={(e) => {\n // On blur, ensure we have a valid number\n const val = e.target.value;\n if (val === \"\" || val === \"-\") {\n handleInputChange(commandName, paramName, 0);\n }\n }}\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n />\n </div>\n );\n }\n } else if (paramSchema.type === \"string\") {\n if (paramSchema.enum) {\n // Dropdown for enum values\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <select\n value={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.value)\n }\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n >\n <option value=\"\">Select...</option>\n {paramSchema.enum.map((option: string) => (\n <option key={option} value={option}>\n {option}\n </option>\n ))}\n </select>\n </div>\n );\n } else {\n // Text input\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{ fontSize: \"12px\", color: \"#666\", display: \"block\" }}\n >\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n <input\n type=\"text\"\n value={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.value)\n }\n style={{\n width: \"100%\",\n padding: \"4px\",\n fontSize: \"12px\",\n border: \"1px solid #ccc\",\n borderRadius: \"2px\",\n }}\n />\n </div>\n );\n }\n } else if (paramSchema.type === \"boolean\") {\n return (\n <div style={{ marginBottom: \"8px\" }}>\n <label\n style={{\n fontSize: \"12px\",\n color: \"#666\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={value}\n onChange={(e) =>\n handleInputChange(commandName, paramName, e.target.checked)\n }\n style={{ marginRight: \"6px\" }}\n />\n {paramName}\n {paramSchema.description && ` - ${paramSchema.description}`}\n {paramSchema.required && <span style={{ color: \"red\" }}> *</span>}\n </label>\n </div>\n );\n }\n\n return null;\n };\n\n const renderCommand = (commandName: string, commandSchema: CommandSchema) => {\n const hasParams = Object.keys(commandSchema.schema).length > 0;\n const isExpanded = expandedCommands[commandName];\n\n // Check if this command has any slider inputs (number/integer with min/max)\n const hasSliderInputs = Object.values(commandSchema.schema).some(\n (paramSchema) =>\n (paramSchema.type === \"number\" || paramSchema.type === \"integer\") &&\n typeof paramSchema.minimum === \"number\" &&\n typeof paramSchema.maximum === \"number\"\n );\n\n // Don't show execute button if command has slider inputs (they execute automatically)\n const showExecuteButton = !hasSliderInputs;\n\n return (\n <div\n key={commandName}\n style={{\n border: \"1px solid #ddd\",\n borderRadius: \"4px\",\n marginBottom: \"8px\",\n backgroundColor: \"#fafafa\",\n }}\n >\n {/* Command Header - Always Visible */}\n <div\n onClick={() => toggleCommandExpanded(commandName)}\n style={{\n padding: \"8px 12px\",\n cursor: \"pointer\",\n borderBottom: isExpanded ? \"1px solid #ddd\" : \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div>\n <h4\n style={{\n margin: \"0\",\n fontSize: \"13px\",\n fontWeight: \"bold\",\n }}\n >\n {commandName}\n </h4>\n {isExpanded && commandSchema.description && (\n <p\n style={{ margin: \"4px 0 0 0\", fontSize: \"11px\", color: \"#666\" }}\n >\n {commandSchema.description}\n </p>\n )}\n </div>\n <div\n style={{\n fontSize: \"10px\",\n color: \"#999\",\n transform: isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\",\n transition: \"transform 0.2s\",\n }}\n >\n ▼\n </div>\n </div>\n\n {/* Command Content - Collapsible */}\n {isExpanded && (\n <div style={{ padding: \"12px\", paddingTop: \"0\" }}>\n {hasParams && (\n <div style={{ marginBottom: showExecuteButton ? \"12px\" : \"0\" }}>\n <div\n style={{\n marginBottom: \"8px\",\n fontSize: \"12px\",\n fontWeight: \"bold\",\n color: \"#555\",\n }}\n >\n Parameters:\n </div>\n {Object.entries(commandSchema.schema).map(\n ([paramName, paramSchema]) => (\n <div\n key={`${commandName}-${paramName}`}\n style={{ marginLeft: \"8px\" }}\n >\n {renderInput(commandName, paramName, paramSchema)}\n </div>\n )\n )}\n </div>\n )}\n\n {!hasParams && (\n <div\n style={{\n marginBottom: showExecuteButton ? \"12px\" : \"0\",\n marginTop: \"2px\",\n fontSize: \"11px\",\n color: \"#666\",\n fontStyle: \"italic\",\n }}\n >\n No parameters required\n </div>\n )}\n\n {showExecuteButton && (\n <button\n onClick={() => handleCommandSubmit(commandName)}\n style={{\n padding: \"8px 16px\",\n fontSize: \"12px\",\n backgroundColor: \"#007bff\",\n color: \"white\",\n border: \"none\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n fontWeight: \"bold\",\n }}\n >\n Execute {commandName}\n </button>\n )}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={className} style={style}>\n <div style={{ fontFamily: \"monospace\", fontSize: \"12px\" }}>\n {Object.keys(commands).length === 0 ? (\n <div style={{ padding: \"12px\", color: \"#666\", fontStyle: \"italic\" }}>\n Waiting for commands schema...\n </div>\n ) : (\n <div>\n <h3\n style={{\n margin: \"0 0 16px 0\",\n fontSize: \"16px\",\n fontWeight: \"bold\",\n }}\n >\n Reactor Commands\n </h3>\n {Object.entries(commands).map(([commandName, commandSchema]) => (\n <div key={commandName}>\n {renderCommand(commandName, commandSchema)}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useReactor } from \"./hooks\";\nimport { useEffect, useRef, useState } from \"react\";\nimport React from \"react\";\n\nexport interface WebcamStreamProps {\n /**\n * The name of the sendonly track to publish the webcam to.\n * Must match a track name declared in the server capabilities.\n * Check the model's documentation for available track names.\n */\n track: string;\n className?: string;\n style?: React.CSSProperties;\n videoConstraints?: MediaTrackConstraints;\n showWebcam?: boolean;\n videoObjectFit?: NonNullable<\n React.VideoHTMLAttributes<HTMLVideoElement>[\"style\"]\n >[\"objectFit\"];\n}\n\nexport function WebcamStream({\n track,\n className,\n style,\n videoConstraints = {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n },\n showWebcam = true,\n videoObjectFit = \"contain\",\n}: WebcamStreamProps) {\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [isPublishing, setIsPublishing] = useState(false);\n const [permissionDenied, setPermissionDenied] = useState(false);\n\n const { status, publish, unpublish, reactor } = useReactor((state) => ({\n status: state.status,\n publish: state.publish,\n unpublish: state.unpublish,\n reactor: state.internal.reactor,\n }));\n\n const videoRef = useRef<HTMLVideoElement>(null);\n\n // Start webcam\n const startWebcam = async () => {\n console.debug(\"[WebcamPublisher] Starting webcam\");\n\n try {\n const mediaStream = await navigator.mediaDevices.getUserMedia({\n video: videoConstraints,\n audio: false,\n });\n\n console.debug(\"[WebcamPublisher] Webcam started successfully\");\n setStream(mediaStream);\n setPermissionDenied(false);\n } catch (err) {\n console.error(\"[WebcamPublisher] Failed to start webcam:\", err);\n\n // Check if the error is a permission denial\n if (\n err instanceof DOMException &&\n (err.name === \"NotAllowedError\" || err.name === \"PermissionDeniedError\")\n ) {\n console.debug(\"[WebcamPublisher] Camera permission denied\");\n setPermissionDenied(true);\n }\n }\n };\n\n // Stop webcam\n const stopWebcam = async () => {\n console.debug(\"[WebcamPublisher] Stopping webcam\");\n\n // Unpublish if currently publishing\n try {\n await unpublish(track);\n console.debug(\"[WebcamPublisher] Unpublished before stopping\");\n } catch (err) {\n console.error(\"[WebcamPublisher] Error unpublishing before stop:\", err);\n }\n\n setIsPublishing(false);\n\n // Stop all tracks\n stream?.getTracks().forEach((t) => {\n t.stop();\n console.debug(\"[WebcamPublisher] Stopped track:\", t.kind);\n });\n setStream(null);\n\n console.debug(\"[WebcamPublisher] Webcam stopped\");\n };\n\n // Attach stream to video element\n useEffect(() => {\n console.debug(\"[WebcamPublisher] Stream effect triggered\", {\n hasVideoElement: !!videoRef.current,\n hasStream: !!stream,\n });\n\n if (!videoRef.current) {\n return;\n }\n\n if (stream) {\n console.debug(\"[WebcamPublisher] Attaching stream to video element\");\n videoRef.current.srcObject = stream;\n console.debug(\"[WebcamPublisher] Stream attached successfully\");\n } else {\n console.debug(\"[WebcamPublisher] Clearing video element\");\n videoRef.current.srcObject = null;\n }\n }, [stream]);\n\n // Auto-publish when reactor is ready and webcam is active\n useEffect(() => {\n if (!stream) {\n return;\n }\n\n if (status === \"ready\" && !isPublishing) {\n console.debug(\n \"[WebcamPublisher] Reactor ready, auto-publishing webcam stream\"\n );\n const videoTrack = stream.getVideoTracks()[0];\n if (videoTrack) {\n publish(track, videoTrack)\n .then(() => {\n console.debug(\"[WebcamPublisher] Auto-publish successful\");\n setIsPublishing(true);\n })\n .catch((err) => {\n console.error(\"[WebcamPublisher] Auto-publish failed:\", err);\n });\n }\n } else if (status !== \"ready\" && isPublishing) {\n console.debug(\"[WebcamPublisher] Reactor not ready, auto-unpublishing\");\n unpublish(track)\n .then(() => {\n console.debug(\"[WebcamPublisher] Auto-unpublish successful\");\n setIsPublishing(false);\n })\n .catch((err) => {\n console.error(\"[WebcamPublisher] Auto-unpublish failed:\", err);\n });\n }\n }, [status, stream, isPublishing, publish, unpublish, track]);\n\n // Listen for error events from Reactor\n useEffect(() => {\n const handleError = (error: any) => {\n console.debug(\"[WebcamPublisher] Received error event:\", error);\n\n // Handle track publish failures by resetting state\n if (error.code === \"TRACK_PUBLISH_FAILED\") {\n console.debug(\n \"[WebcamPublisher] Track publish failed, resetting isPublishing state\"\n );\n setIsPublishing(false);\n }\n };\n\n reactor.on(\"error\", handleError);\n\n return () => {\n reactor.off(\"error\", handleError);\n };\n }, [reactor]);\n\n // Reset publishing state when status changes away from ready\n useEffect(() => {\n if (status !== \"ready\") {\n console.debug(\n \"[WebcamPublisher] Status changed to\",\n status,\n \"- resetting isPublishing state\"\n );\n setIsPublishing(false);\n }\n }, [status, isPublishing]);\n\n // Auto-start webcam on mount and cleanup on unmount\n useEffect(() => {\n console.debug(\"[WebcamPublisher] Auto-starting webcam\");\n startWebcam();\n\n return () => {\n console.debug(\"[WebcamPublisher] Cleanup on unmount\");\n stopWebcam();\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const showPlaceholder = !stream;\n\n return (\n <div\n style={{\n display: showWebcam ? \"block\" : \"none\",\n position: \"relative\",\n background: \"#000\",\n ...style,\n }}\n className={className}\n >\n <video\n ref={videoRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: videoObjectFit,\n display: showPlaceholder ? \"none\" : \"block\",\n }}\n muted\n playsInline\n autoPlay\n />\n {showPlaceholder && (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"16px\",\n fontFamily: \"monospace\",\n textAlign: \"center\",\n padding: \"20px\",\n boxSizing: \"border-box\",\n flexDirection: \"column\",\n gap: \"12px\",\n }}\n >\n {permissionDenied ? (\n <div style={{ fontSize: \"12px\", fontFamily: \"monospace\" }}>\n Camera access denied.\n <br />\n Please allow access in your browser settings.\n </div>\n ) : (\n <div style={{ fontSize: \"12px\", fontFamily: \"monospace\" }}>\n Starting camera...\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_zod","import_react","import_react","_a","current","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","React","_a","import_react","import_jsx_runtime"]}