ros-mobile-bridge 0.1.2 → 0.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/CircuitBreaker.ts","../src/EventLoopMonitor.ts","../src/SubscriptionBandwidth.ts","../src/schemaToTemplate.ts","../src/jsonSchemaToTemplate.ts","../src/builtinSchemas.ts","../src/FoxgloveClient.ts","../src/RosbridgeClient.ts","../src/constants.ts","../src/ProtocolManager.ts"],"names":["parseRos2idl","parseRosMsgDef","MessageReader","MessageWriter","NOOP_LOGGER","TEXT_DECODER","MAX_RECONNECT_ATTEMPTS","BASE_RECONNECT_DELAY_MS","CONNECTION_TIMEOUT_MS","ZERO_TWIST","CMD_VEL_SCHEMA"],"mappings":"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","file":"index.cjs","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * CircuitBreaker — per-subscription state machine that gracefully suspends\n * a topic when the adaptive throttle has done all it can but the JS thread\n * is still saturated.\n *\n * Design rationale: at the deepest throttle bucket (e.g. 0.5 Hz cap), each\n * 1080p q95 frame parse still takes ~200 ms on a modern phone — even one\n * frame every two seconds produces a perceptible 200 ms gesture freeze. No\n * amount of further throttle tuning fixes this; the workload is\n * fundamentally too heavy for the transport on this device. The breaker\n * detects sustained overload at the deepest bucket and unsubscribes from\n * the bridge, freeing the JS thread, network, and memory entirely for that\n * topic until the user (or auto-retry) decides to try again.\n *\n * The state machine has four states:\n * - `closed`: normal, throttle handles the rest\n * - `tripped_auto`: paused, auto-retry timer running (exponential backoff)\n * - `tripped_manual`: paused, NO auto-retry — user opted out\n * - `half_open`: re-subscribed, watching lag for `recoveryDwellMs`; if lag\n * stays low, close; if it spikes, re-trip with longer cooldown.\n *\n * The breaker is a pure state machine — it doesn't send WebSocket ops\n * itself. The protocol client's `onStateChange` callback is responsible for\n * the side effects (send unsubscribe on enter `tripped_auto`, send\n * subscribe on enter `half_open`, etc).\n */\n\nimport type { CircuitBreakerState } from './types';\n\nexport interface CircuitBreakerConfig {\n /**\n * Lag threshold (ms) above which the breaker considers the subscription\n * \"still saturated\" while at the deepest throttle bucket. Suggest 150 ms —\n * comfortably above normal scheduler jitter (~5–30 ms on healthy hardware)\n * and below the threshold where a user perceives the UI as stalled.\n */\n lagThresholdMs: number;\n\n /**\n * Sustained ms of over-threshold lag before tripping. Suggest 2000 ms —\n * long enough that single-frame spikes (one heavy decode, a GC pause)\n * don't trigger, short enough that a genuinely saturating workload trips\n * before the user perceives the app as frozen. Together with the 500 ms\n * `WARMUP_MS` this puts the absolute minimum subscribe-to-unsubscribe\n * floor at ~2.5 s.\n */\n tripDwellMs: number;\n\n /**\n * ms of healthy operation in `half_open` before closing the breaker.\n * Suggest 10000 ms.\n */\n recoveryDwellMs: number;\n\n /**\n * Cooldown durations per consecutive trip within this connection. Index\n * `tripCount - 1` is read; the last value is reused for further trips.\n * Suggest `[30000, 60000, 120000, 300000]`.\n */\n cooldownsMs: number[];\n\n /**\n * Side-effect handler. Called on every state transition. The protocol\n * client uses it to send the actual `subscribe` / `unsubscribe` ops to\n * the bridge.\n */\n onStateChange: (newState: CircuitBreakerState, oldState: CircuitBreakerState) => void;\n}\n\n/**\n * ms of sustained healthy observations before we reset the saturation\n * timer. Without this debounce, lag oscillating around the trip threshold\n * resets the timer every other sample and the breaker never accumulates\n * enough dwell to trip even when the workload is plainly saturating things.\n */\nconst HEALTHY_DEBOUNCE_MS = 4000;\n\n/**\n * Grace period after a (re)subscription before the breaker can register\n * any observations. The first few hundred ms after subscribe have transient\n * spikes (TCP-window fill, bridge backlog drain, first JIT pass through\n * the message-handler hot path) that don't reflect sustained workload.\n * Without warmup these can trip the breaker on lightweight topics before\n * the JIT settles in.\n *\n * Originally 2000 ms — tuned alongside the looser defaults below for\n * JSON-sim spike patterns. Tightened to 500 ms for the CDR-realistic\n * regime: schema parsing happens once in `subscribe()` rather than per\n * message, the per-frame hot path JITs in a handful of frames not seconds,\n * and on real workloads (1080p+ raw camera streams) the cold-start \"flood\"\n * window is what the user perceives as a freeze. A shorter warmup lets the\n * breaker step in before the user feels stuck. The remaining 500 ms is\n * still longer than any genuine cold-path JIT settle on the four target\n * runtimes; topics that legitimately fluctuate during the first half-second\n * also don't see their first sustained spike until the trip dwell anyway.\n */\nconst WARMUP_MS = 500;\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed';\n private tripCount = 0;\n private saturationObservedAt = 0;\n private healthyObservedAt = 0;\n private cooldownTimer: ReturnType<typeof setTimeout> | null = null;\n private subscriptionStartedAt: number = Date.now();\n private nextRetryAt: number | null = null;\n\n constructor(private readonly config: CircuitBreakerConfig) {}\n\n getState(): CircuitBreakerState {\n return this.state;\n }\n\n /**\n * `Date.now()` when auto-retry is scheduled to fire, or `null` if no\n * cooldown is running (closed / half_open / tripped_manual).\n */\n getNextRetryAt(): number | null {\n return this.nextRetryAt;\n }\n\n /**\n * Single entry point for \"I saw a message; here's the current bandwidth\n * and JS-thread lag.\" Internally gates by `HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC`\n * and the breaker's `lagThresholdMs` so the trip policy lives in one place\n * instead of being replicated at every call site.\n */\n recordObservation(now: number, bytesPerSec: number, lagMs: number): void {\n if (bytesPerSec > HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC && lagMs > this.config.lagThresholdMs) {\n this.recordOverloaded(now);\n } else {\n this.recordHealthy(now);\n }\n }\n\n /**\n * Called from the protocol client's `recordBytes` when the tracker is in\n * the heavily-throttled range (top buckets) and lag exceeds the threshold.\n */\n recordOverloaded(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state === 'closed' || this.state === 'half_open') {\n if (this.saturationObservedAt === 0) {\n this.saturationObservedAt = now;\n } else if (now - this.saturationObservedAt >= this.config.tripDwellMs) {\n this.trip();\n }\n this.healthyObservedAt = 0;\n }\n }\n\n /**\n * Called from `recordBytes` when lag is below threshold or the tracker is\n * below the heavily-throttled range.\n */\n recordHealthy(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state !== 'closed' && this.state !== 'half_open') return;\n\n if (this.healthyObservedAt === 0) {\n this.healthyObservedAt = now;\n }\n const healthyDwell = now - this.healthyObservedAt;\n\n if (this.saturationObservedAt > 0 && healthyDwell >= HEALTHY_DEBOUNCE_MS) {\n this.saturationObservedAt = 0;\n }\n\n if (this.state === 'half_open' && healthyDwell >= this.config.recoveryDwellMs) {\n this.close();\n }\n }\n\n /**\n * User pressed \"try again now\" — bypasses the cooldown timer and jumps\n * straight to `half_open`. Works from any tripped state.\n */\n retry(): void {\n if (this.state === 'tripped_auto' || this.state === 'tripped_manual') {\n this.clearCooldown();\n this.openHalf();\n }\n }\n\n /**\n * User pressed \"stop trying\" — switches `tripped_auto` to `tripped_manual`\n * and cancels the auto-retry timer. The subscription remains paused until\n * the user manually retries.\n */\n disable(): void {\n if (this.state === 'tripped_auto') {\n this.clearCooldown();\n this.transition('tripped_manual');\n }\n }\n\n /**\n * Called by the protocol client on disconnect or unsubscribe so the\n * cooldown timer doesn't outlive the connection.\n */\n destroy(): void {\n this.clearCooldown();\n }\n\n // ── Internal transitions ─────────────────────────────────────────────\n\n private trip(): void {\n this.tripCount++;\n this.saturationObservedAt = 0;\n const cooldownIdx = Math.min(this.tripCount - 1, this.config.cooldownsMs.length - 1);\n const cooldownMs = this.config.cooldownsMs[cooldownIdx] ?? 30_000;\n this.nextRetryAt = Date.now() + cooldownMs;\n this.transition('tripped_auto');\n this.cooldownTimer = setTimeout(() => {\n this.cooldownTimer = null;\n this.nextRetryAt = null;\n if (this.state === 'tripped_auto') {\n this.openHalf();\n }\n }, cooldownMs);\n }\n\n private openHalf(): void {\n const now = Date.now();\n this.saturationObservedAt = 0;\n this.healthyObservedAt = 0;\n this.subscriptionStartedAt = now;\n this.transition('half_open');\n }\n\n private close(): void {\n this.saturationObservedAt = 0;\n this.transition('closed');\n }\n\n private transition(next: CircuitBreakerState): void {\n const prev = this.state;\n if (prev === next) return;\n this.state = next;\n try {\n this.config.onStateChange(next, prev);\n } catch {\n // The side-effect callback shouldn't throw; if it does we don't want\n // to leave the breaker in a half-applied state — `this.state` is\n // already updated above.\n }\n }\n\n private clearCooldown(): void {\n if (this.cooldownTimer !== null) {\n clearTimeout(this.cooldownTimer);\n this.cooldownTimer = null;\n }\n this.nextRetryAt = null;\n }\n}\n\n/**\n * Default config tuned for the camera-on-modern-phone workload that\n * motivated the breaker. Protocol clients can override per subscription.\n *\n * v0.1.x history: the original `lagThresholdMs: 250 / tripDwellMs: 5000`\n * pair was calibrated against JSON-sim tests where the failure shape was\n * 100–333 ms transient spikes interleaved with healthy stretches. CDR\n * sensor streams on real hardware fail in a different regime — sustained\n * multi-second freezes during the cold-start window. The current values\n * (`150 / 2000`) trade some false-positive risk on transient spikes for\n * faster detection of the genuine-freeze pattern, since that's the case\n * where the user perceives the app as stuck and needs the breaker to\n * step in before the symptom passes the perception threshold.\n */\nexport const DEFAULT_BREAKER_CONFIG: Omit<CircuitBreakerConfig, 'onStateChange'> = {\n lagThresholdMs: 150,\n tripDwellMs: 2_000,\n recoveryDwellMs: 10_000,\n cooldownsMs: [30_000, 60_000, 120_000, 300_000],\n};\n\n/**\n * Bytes/sec floor a subscription must exceed before the breaker considers\n * tripping it. Without this gate, when one heavy publisher saturates the\n * thread, every subscription sees the same high lag and trips in lockstep\n * — killing innocent low-rate topics. With the gate, only the actual heavy\n * contributor qualifies.\n */\nexport const HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC = 500_000;\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * EventLoopMonitor — direct measurement of JS-thread saturation.\n *\n * Hardcoded byte/sec bucket thresholds were a proxy for \"is the JS thread\n * saturated?\" calibrated to one device class and one message size; on\n * different devices or with bigger frames they under- or over-throttled.\n * This monitor measures the actual symptom.\n *\n * Mechanism: a `setInterval` fires every PROBE_INTERVAL_MS. Each tick\n * records how late it ran vs. when it was scheduled. Under saturation the\n * JS thread is busy with parse / reconcile work and the timer fires late —\n * that delta IS the lag. Under idle, lag is ~0-5 ms (normal scheduler\n * jitter).\n *\n * Smoothing: a 1 s rolling window keeps (timestamp, lag) pairs. The\n * reported value is the MAX over that window, not an EMA — bursty\n * saturation should be detected on the spike, not blurred away.\n *\n * The monitor starts on first `getMaxLagMs()` call (lazy) and runs forever.\n * Cost: one `setInterval` at 5 Hz reading `Date.now()`.\n *\n * Public surface: `getMaxLagMs`, `getLagStats`, `getLagHistoryCsv`, and\n * `clearLagHistory` are exported from the package and let consumers build\n * \"currently throttled\" diagnostics. `setModeGetter` is module-internal —\n * protocol clients call it from their constructors so the lag history is\n * tagged with the active throttle mode for bug-report exports, and\n * consumers never need to wire it themselves.\n */\n\nconst PROBE_INTERVAL_MS = 200;\nconst WINDOW_MS = 1000;\nconst HISTORY_MAX = 600;\n\ninterface LagSample {\n t: number;\n lag: number;\n}\n\ninterface HistorySample {\n t: number;\n lag: number;\n mode: string;\n}\n\nlet started = false;\nlet lastTickAt = 0;\nconst samples: LagSample[] = [];\nconst history: HistorySample[] = [];\n\nlet modeGetter: () => string = () => 'auto';\n\n/**\n * Internal. Protocol clients invoke this from their constructors with the\n * value they received from `ProtocolClientOptions.getThrottleMode`. The\n * monitor uses the result to tag history samples with the active throttle\n * mode for the diagnostics CSV. Not re-exported from the package entry\n * point — consumers configure throttle mode through `getThrottleMode`.\n */\nexport function setModeGetter(fn: () => string): void {\n modeGetter = fn;\n}\n\nfunction startMonitor(): void {\n if (started) return;\n started = true;\n lastTickAt = Date.now();\n const handle: unknown = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickAt;\n const lag = Math.max(0, elapsed - PROBE_INTERVAL_MS);\n lastTickAt = now;\n\n samples.push({ t: now, lag });\n const cutoff = now - WINDOW_MS;\n while (samples.length > 0) {\n const head = samples[0];\n if (!head || head.t >= cutoff) break;\n samples.shift();\n }\n\n let mode = 'auto';\n try {\n mode = modeGetter();\n } catch {\n // mode tagging is best-effort; never break the monitor on a bad getter.\n }\n history.push({ t: now, lag, mode });\n if (history.length > HISTORY_MAX) {\n history.shift();\n }\n }, PROBE_INTERVAL_MS);\n\n // The monitor is a passive diagnostic; it must not keep a Node process\n // alive on its own. Once a consumer's real work (an active WebSocket,\n // an HTTP server) finishes, the process should exit even if the monitor\n // is still ticking. `unref` exists on Node's Timeout object; browsers,\n // React Native, and Electron's renderer don't have or need it.\n const unref = (handle as { unref?: () => void } | null)?.unref;\n if (typeof unref === 'function') {\n unref.call(handle);\n }\n}\n\n/**\n * Max observed JS-thread lag (ms) over the last `WINDOW_MS`. Auto-starts\n * the monitor on first call. Returns `0` if no samples have been collected\n * yet.\n */\nexport function getMaxLagMs(): number {\n if (!started) startMonitor();\n let max = 0;\n for (const s of samples) {\n if (s.lag > max) max = s.lag;\n }\n return max;\n}\n\n/**\n * Percentile statistics over the long-term history buffer (roughly the last\n * 2 minutes). Returns `null` when no samples have been collected yet.\n */\nexport function getLagStats(): {\n count: number;\n durationSec: number;\n p50: number;\n p90: number;\n p99: number;\n max: number;\n} | null {\n if (history.length === 0) return null;\n const sorted = history.map((s) => s.lag).sort((a, b) => a - b);\n const pick = (q: number): number => {\n const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * q));\n return sorted[idx] ?? 0;\n };\n const first = history[0];\n const last = history[history.length - 1];\n const span = first && last ? (last.t - first.t) / 1000 : 0;\n return {\n count: history.length,\n durationSec: Math.round(span),\n p50: pick(0.5),\n p90: pick(0.9),\n p99: pick(0.99),\n max: sorted[sorted.length - 1] ?? 0,\n };\n}\n\n/**\n * CSV dump of the history buffer. One row per sample, mode-tagged so a\n * recording that spans a throttle-mode change still tells you which lag\n * values belong to which mode. Useful for attaching to bug reports.\n */\nexport function getLagHistoryCsv(): string {\n const header = 'timestamp_ms,lag_ms,mode';\n const rows = history.map((s) => `${s.t},${s.lag},${s.mode}`);\n return [header, ...rows].join('\\n');\n}\n\n/**\n * Clear the long-term history buffer. The rolling 1 s window used by the\n * throttle keeps running, so live throttle decisions stay correct. Useful\n * when starting a new test session.\n */\nexport function clearLagHistory(): void {\n history.length = 0;\n}\n\n/**\n * Test helper. Resets the monitor's internal state so unit tests get a\n * clean slate. Not exported from the package entry point.\n *\n * @internal\n */\nexport function __resetEventLoopMonitor(): void {\n samples.length = 0;\n history.length = 0;\n lastTickAt = Date.now();\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * SubscriptionBandwidth — adaptive throttle driven by JS-thread saturation.\n *\n * Bucket selection reads `EventLoopMonitor.getMaxLagMs()` rather than a\n * per-subscription bytes/sec rate. The symptom the throttle is protecting\n * against (gesture and control starvation) is a property of the JS thread,\n * not of any single message stream, so the right signal is thread saturation\n * directly. A bytes/sec ladder would have to be calibrated per device class\n * and per message size — fragile in a library targeting four runtimes — and\n * would miss the case where several medium-rate subscriptions (lidar + odom\n * + imu) sum to thread saturation while none individually crosses a byte\n * threshold.\n *\n * Bytes/sec is still tracked per subscription for metrics and UI (\"currently\n * throttled because /camera is at 5 MB/s\") via `getSubscriptionStats`; it is\n * not the throttle decision input.\n *\n * Hysteresis: tighten immediately on the spike (saturation costs gesture\n * authority — pay the cost up front), relax slowly (3 s below threshold) so\n * the throttle doesn't oscillate around a boundary.\n *\n * The curves themselves (`DEFAULT_PRESETS` below) were tuned on one device\n * class. Consumers can override per mode via `ProtocolClientOptions.presetOverrides`;\n * each tracker carries its own effective preset map so two clients with\n * different overrides don't share state.\n */\n\nimport { getMaxLagMs } from './EventLoopMonitor';\nimport type { BucketDef, ProtocolLogger, ThrottleMode } from './types';\n\nconst BANDWIDTH_WINDOW_MS = 1000;\nconst TIGHTEN_DWELL_MS = 0;\nconst RELAX_DWELL_MS = 3000;\n\n/**\n * Library-tuned throttle curves. Override via\n * `ProtocolClientOptions.presetOverrides` to ship a per-device-class curve.\n * Exported for use by consumers building their own preset variants on top\n * of the defaults (e.g. `{ ...DEFAULT_PRESETS, auto: [...customAuto] }`).\n *\n * @experimental The override *shape* (`BucketDef`, `ThrottleMode`,\n * `presetOverrides`) is semver-stable, but the default *values* in this map\n * may be rebalanced in any patch release as device-tuning data accrues. Do\n * not snapshot these numbers and assume they're frozen; reference the export\n * if you want to track the current defaults.\n */\nexport const DEFAULT_PRESETS: Record<ThrottleMode, BucketDef[]> = {\n performance: [{ threshold: 0, minIntervalMs: 0, label: 'none' }],\n\n auto: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 100, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 150, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n\n efficient: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 80, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 130, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n};\n\nconst THROTTLE_MODES: readonly ThrottleMode[] = ['performance', 'auto', 'efficient'];\n\n/**\n * Pessimistic-start initial bucket per mode. Without this, every new\n * subscription floods → spike → tighten, costing the first ~1 s of\n * usability while the throttle catches up. Each tracker boots at a\n * moderate cap and only relaxes if observed lag stays below the\n * next-lower bucket's threshold long enough.\n */\nconst INITIAL_BUCKET_PER_MODE: Record<ThrottleMode, number> = {\n performance: 0,\n auto: 2,\n efficient: 3,\n};\n\n/**\n * Validate a single mode's bucket array. Returns `true` if usable as an\n * override; logs a warning and returns `false` otherwise so the caller can\n * fall back to the default for that mode.\n *\n * Only enforces correctness-essential rules:\n * - The array is non-empty.\n * - The first bucket has `threshold === 0`.\n *\n * Consumer-hygiene rules (thresholds sorted ascending, unique labels) are\n * intentionally not enforced — `recordBytes` and `bucketLabelForLag`\n * terminate with sensible-enough results in their absence, and listing every\n * possible quality rule is not the library's job.\n */\nfunction validatePreset(\n buckets: BucketDef[] | undefined,\n mode: ThrottleMode,\n logger: ProtocolLogger,\n): boolean {\n if (!buckets || buckets.length === 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: empty bucket array; using default preset for this mode`,\n );\n return false;\n }\n const first = buckets[0];\n if (!first || first.threshold !== 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: first bucket must have threshold === 0 (the \"no throttle\" base case); using default preset for this mode`,\n );\n return false;\n }\n return true;\n}\n\n/**\n * Merge consumer-supplied overrides on top of `DEFAULT_PRESETS`. Invalid\n * per-mode overrides are skipped (with a `logger.warn`); valid ones replace\n * the default for their mode. Returns a fresh object so two clients with\n * different overrides never share mutable state through this map.\n */\nexport function buildEffectivePresets(\n overrides: Partial<Record<ThrottleMode, BucketDef[]>> | undefined,\n logger: ProtocolLogger,\n): Record<ThrottleMode, BucketDef[]> {\n const merged: Record<ThrottleMode, BucketDef[]> = {\n performance: DEFAULT_PRESETS.performance,\n auto: DEFAULT_PRESETS.auto,\n efficient: DEFAULT_PRESETS.efficient,\n };\n if (!overrides) return merged;\n\n for (const mode of THROTTLE_MODES) {\n const override = overrides[mode];\n if (override === undefined) continue;\n if (validatePreset(override, mode, logger)) {\n merged[mode] = override;\n }\n }\n return merged;\n}\n\nexport interface BandwidthTracker {\n /** Ring buffer of (timestamp, byteSize) over the rolling window. */\n window: Array<{ t: number; b: number }>;\n /** Cached bytes/sec, updated on each `recordBytes`. */\n bytesPerSec: number;\n /** Bucket index currently applied (drives `adaptiveMinIntervalMs`). */\n currentBucket: number;\n /**\n * Most recently observed target bucket (may differ from `currentBucket`\n * while we're inside the hysteresis dwell window).\n */\n targetBucket: number;\n /** ms timestamp when `targetBucket` was first observed. */\n targetObservedAt: number;\n /** Effective adaptive throttle interval. `0` means no throttle. */\n adaptiveMinIntervalMs: number;\n /**\n * Effective preset map for this tracker. Shared by reference across every\n * tracker created by the same client; never mutated after construction.\n */\n presets: Record<ThrottleMode, BucketDef[]>;\n}\n\nexport function createBandwidthTracker(\n mode: ThrottleMode = 'auto',\n presets: Record<ThrottleMode, BucketDef[]> = DEFAULT_PRESETS,\n): BandwidthTracker {\n const initialBucket = INITIAL_BUCKET_PER_MODE[mode] ?? 0;\n const preset = presets[mode];\n const safeInitial = Math.min(initialBucket, Math.max(0, preset.length - 1));\n const initialIntervalMs = preset[safeInitial]?.minIntervalMs ?? 0;\n return {\n window: [],\n bytesPerSec: 0,\n currentBucket: safeInitial,\n targetBucket: safeInitial,\n targetObservedAt: 0,\n adaptiveMinIntervalMs: initialIntervalMs,\n presets,\n };\n}\n\n/**\n * Record an incoming message of `byteSize` bytes at time `now`. Updates the\n * rolling byte window and applies the bucket policy for the active mode\n * based on JS-thread lag. Mutates `tracker` in place.\n *\n * Bucket selection reads from `EventLoopMonitor.getMaxLagMs()` — a global\n * signal, not per-subscription. If every subscription is a small\n * contributor but they sum to JS-thread saturation, the throttle still\n * fires. That's correct: the symptom we're protecting against (gesture and\n * control starvation) is a property of the thread, not a single stream.\n */\nexport function recordBytes(\n tracker: BandwidthTracker,\n now: number,\n byteSize: number,\n mode: ThrottleMode = 'auto',\n): void {\n tracker.window.push({ t: now, b: byteSize });\n const cutoff = now - BANDWIDTH_WINDOW_MS;\n while (tracker.window.length > 0) {\n const head = tracker.window[0];\n if (!head || head.t >= cutoff) break;\n tracker.window.shift();\n }\n let total = 0;\n for (const e of tracker.window) total += e.b;\n tracker.bytesPerSec = total / (BANDWIDTH_WINDOW_MS / 1000);\n\n const buckets = tracker.presets[mode];\n const lagMs = getMaxLagMs();\n\n let targetBucket = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n targetBucket = i;\n break;\n }\n }\n\n if (targetBucket !== tracker.targetBucket) {\n tracker.targetBucket = targetBucket;\n tracker.targetObservedAt = now;\n return;\n }\n if (targetBucket === tracker.currentBucket) {\n return;\n }\n\n const dwell = now - tracker.targetObservedAt;\n const tighten = targetBucket > tracker.currentBucket;\n const requiredDwell = tighten ? TIGHTEN_DWELL_MS : RELAX_DWELL_MS;\n if (dwell < requiredDwell) return;\n\n if (tighten) {\n tracker.currentBucket = targetBucket;\n } else {\n tracker.currentBucket = Math.max(targetBucket, tracker.currentBucket - 1);\n tracker.targetObservedAt = now;\n }\n tracker.adaptiveMinIntervalMs = buckets[tracker.currentBucket]?.minIntervalMs ?? 0;\n}\n\n/**\n * Effective min-interval (ms) for a callback, combining the user's request\n * with the adaptive throttle. The user's `userMinIntervalMs` is a floor —\n * adaptive can only make the interval longer, never shorter.\n */\nexport function effectiveMinInterval(\n userMinIntervalMs: number | undefined,\n disableAdaptive: boolean,\n tracker: BandwidthTracker,\n): number {\n const user = userMinIntervalMs ?? 0;\n if (disableAdaptive) return user;\n return Math.max(user, tracker.adaptiveMinIntervalMs);\n}\n\n/**\n * Reset the tracker to the deepest bucket so half-open recovery starts\n * conservative. The throttle's existing step-relax logic walks the bucket\n * back up if observed lag stays below the next-lower bucket's threshold.\n * Avoids a flood-then-tighten cycle on every breaker recovery.\n */\nexport function setTrackerToDeepest(tracker: BandwidthTracker, mode: ThrottleMode): void {\n const buckets = tracker.presets[mode];\n const lastIdx = Math.max(0, buckets.length - 1);\n tracker.currentBucket = lastIdx;\n tracker.targetBucket = lastIdx;\n tracker.targetObservedAt = 0;\n tracker.adaptiveMinIntervalMs = buckets[lastIdx]?.minIntervalMs ?? 0;\n}\n\n/**\n * Label of the bucket the tracker is currently sitting at. Used by UI to\n * tell the user what cap their subscription is throttled to right now.\n * Returns `\"none\"` for the no-cap bucket (or when the tracker's bucket\n * index is somehow out of range, which shouldn't happen in practice).\n */\nexport function getTrackerBucketLabel(tracker: BandwidthTracker, mode: ThrottleMode): string {\n const buckets = tracker.presets[mode];\n return buckets[tracker.currentBucket]?.label ?? 'none';\n}\n\n/**\n * Resolve which bucket a given lag value would land in for the active mode\n * under the library's **default** presets. Independent of any tracker —\n * pass a raw lag measurement (typically from `getMaxLagMs()`) and the\n * active throttle mode, and get back the bucket label the default-tuned\n * throttle would apply at that lag.\n *\n * Useful for diagnostics overlays that want to show \"JS lag is N ms →\n * bucket X\" so observers can correlate measured lag with the throttle\n * policy.\n *\n * **Note on `presetOverrides`:** this function is a stateless module-level\n * helper and has no awareness of per-client overrides. If a consumer\n * supplies `presetOverrides.auto`, calling `bucketLabelForLag('auto', lag)`\n * still returns the **default** bucket label for that lag value, not the\n * override's. For override-aware bucket labels, read\n * `getSubscriptionStats(topic).bucketLabel` off a live subscription.\n */\nexport function bucketLabelForLag(mode: ThrottleMode, lagMs: number): string {\n const buckets = DEFAULT_PRESETS[mode];\n let idx = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n idx = i;\n break;\n }\n }\n return buckets[idx]?.label ?? 'none';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * schemaToTemplate — derive a default JSON payload from a parsed ROS message\n * definition.\n *\n * Takes the array returned by `@foxglove/rosmsg` (for `.msg` and ros2msg) or\n * `@foxglove/ros2idl-parser` (for ros2idl). The first element is the root\n * message; subsequent elements are referenced types. Returns a plain object\n * with every field set to its zero / empty default, ready to use as a\n * starting point for a publish payload editor.\n */\n\nimport type { MessageDefinition } from '@foxglove/message-definition';\n\nconst PRIMITIVE_DEFAULTS: Record<string, unknown> = {\n bool: false,\n int8: 0,\n uint8: 0,\n int16: 0,\n uint16: 0,\n int32: 0,\n uint32: 0,\n int64: 0,\n uint64: 0,\n float32: 0.0,\n float64: 0.0,\n string: '',\n wstring: '',\n time: { sec: 0, nsec: 0 },\n duration: { sec: 0, nsec: 0 },\n 'builtin_interfaces/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/Duration': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Duration': { sec: 0, nanosec: 0 },\n};\n\n/**\n * Build a default JSON template from a parsed message definition. Used by\n * `IProtocolClient.getSchemaTemplate` to surface ready-to-edit payloads for\n * publish UIs.\n */\nexport function schemaToTemplate(\n definitions: MessageDefinition[],\n): Record<string, unknown> {\n if (!definitions.length) return {};\n\n const typeMap = new Map<string, MessageDefinition>();\n for (const def of definitions) {\n if (def.name) {\n typeMap.set(def.name, def);\n }\n }\n\n const root = definitions[0];\n if (!root) return {};\n return buildObject(root, typeMap, 0);\n}\n\nfunction buildObject(\n def: MessageDefinition,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): Record<string, unknown> {\n // Guard against self-referencing types.\n if (depth > 10) return {};\n\n const result: Record<string, unknown> = {};\n\n for (const field of def.definitions) {\n if (field.isConstant) continue;\n\n const defaultVal = getFieldDefault(field.type, field.isComplex, typeMap, depth);\n\n if (field.isArray) {\n result[field.name] = [];\n } else {\n result[field.name] = defaultVal;\n }\n }\n\n return result;\n}\n\nfunction getFieldDefault(\n typeName: string,\n isComplex: boolean | undefined,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): unknown {\n if (PRIMITIVE_DEFAULTS[typeName] !== undefined) {\n const val = PRIMITIVE_DEFAULTS[typeName];\n return typeof val === 'object' ? JSON.parse(JSON.stringify(val)) : val;\n }\n\n if (isComplex) {\n const subDef = typeMap.get(typeName);\n if (subDef) {\n return buildObject(subDef, typeMap, depth + 1);\n }\n for (const [key, def] of typeMap) {\n if (key.endsWith(`/${typeName}`) || typeName.endsWith(`/${key}`)) {\n return buildObject(def, typeMap, depth + 1);\n }\n }\n }\n\n return '';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * jsonSchemaToTemplate — derive a zero-valued JSON payload from a JSON Schema.\n *\n * Used by the Foxglove WebSocket path to turn bridges that ship JSON Schema\n * into Topic-Publisher / field-path templates. The reference foxglove_bridge\n * ships ros2idl instead, which `schemaToTemplate` handles; this parser\n * covers the remaining gap so consumers don't need a hard-coded table of\n * well-known ROS 2 types.\n *\n * Scope: draft-07-compatible JSON Schema, restricted to the subset a bridge\n * typically emits for ROS message shapes (object / array / primitive).\n * Does not resolve `$ref`, `allOf` / `oneOf` / `anyOf`, or enum defaults.\n */\n\nexport function jsonSchemaToTemplate(schema: unknown): unknown {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return null;\n const s = schema as Record<string, unknown>;\n\n // Explicit `default` wins over type-derived zero value.\n if ('default' in s) return s.default;\n\n const type = s.type;\n if (type === 'object') {\n const props = s.properties;\n if (!props || typeof props !== 'object' || Array.isArray(props)) return {};\n const result: Record<string, unknown> = {};\n for (const [key, sub] of Object.entries(props as Record<string, unknown>)) {\n result[key] = jsonSchemaToTemplate(sub);\n }\n return result;\n }\n\n if (type === 'array') {\n // Zero-length array matches the ROS shape for variable-length fields\n // (JointState.name, LaserScan.ranges, etc.).\n return [];\n }\n\n if (type === 'string') return '';\n if (type === 'number' || type === 'integer') return 0;\n if (type === 'boolean') return false;\n if (type === 'null') return null;\n\n // Union type (e.g. ['number', 'null']) — pick the first non-null entry.\n if (Array.isArray(type)) {\n const first = type.find((t) => t !== 'null') ?? type[0];\n return jsonSchemaToTemplate({ ...s, type: first });\n }\n\n return null;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * Bundled IDL definitions for the ROS 2 system services that\n * `foxglove_bridge` (and other CDR transports) commonly discover via graph\n * introspection without shipping inline schemas. Without these fallbacks,\n * callers cannot invoke parameter operations or cancel action goals over\n * Foxglove WS when the bridge omits the IDL — which is the default\n * behavior in `foxglove_bridge` 3.2.6+ for services it discovered through\n * ROS 2 introspection rather than from explicit `.srv` files.\n *\n * Definitions are taken from `rcl_interfaces` and `action_msgs`, both\n * stable across ROS 2 distributions. Bounded sequences (`T[<=N]`) in the\n * canonical `.msg` files are encoded here as unbounded sequences (`T[]`):\n * the two forms produce identical CDR wire output for any value with N or\n * fewer elements, and the parser pin we depend on (`@foxglove/rosmsg`)\n * accepts the unbounded form directly without negotiation.\n *\n * The lookup surface is intentionally narrow:\n * `getBundledServiceSchema(serviceType)` returns request- and\n * response-side schema strings or `null`. This module is **not** exported\n * from `src/index.ts`; it is an internal fallback that the Foxglove\n * protocol client consults only when the bridge-advertised schema is\n * missing. Bridge-shipped schemas remain authoritative when present.\n */\n\nconst SEP = '\\n================================================================================\\n';\n\n// ─── nested message definitions ──────────────────────────────────────────\n// Each constant is a single `MSG: package/Type` block. Service schemas\n// further down compose them with `SEP` to produce the standard\n// concatenated form `@foxglove/rosmsg` parses with `{ ros2: true }`.\n\nconst MSG_PARAMETER_VALUE = `MSG: rcl_interfaces/ParameterValue\nuint8 type\nbool bool_value\nint64 integer_value\nfloat64 double_value\nstring string_value\nbyte[] byte_array_value\nbool[] bool_array_value\nint64[] integer_array_value\nfloat64[] double_array_value\nstring[] string_array_value`;\n\nconst MSG_PARAMETER = `MSG: rcl_interfaces/Parameter\nstring name\nParameterValue value`;\n\nconst MSG_SET_PARAMETERS_RESULT = `MSG: rcl_interfaces/SetParametersResult\nbool successful\nstring reason`;\n\nconst MSG_LIST_PARAMETERS_RESULT = `MSG: rcl_interfaces/ListParametersResult\nstring[] names\nstring[] prefixes`;\n\nconst MSG_FLOATING_POINT_RANGE = `MSG: rcl_interfaces/FloatingPointRange\nfloat64 from_value\nfloat64 to_value\nfloat64 step`;\n\nconst MSG_INTEGER_RANGE = `MSG: rcl_interfaces/IntegerRange\nint64 from_value\nint64 to_value\nuint64 step`;\n\nconst MSG_PARAMETER_DESCRIPTOR = `MSG: rcl_interfaces/ParameterDescriptor\nstring name\nuint8 type\nstring description\nstring additional_constraints\nbool read_only\nbool dynamic_typing\nFloatingPointRange[] floating_point_range\nIntegerRange[] integer_range`;\n\nconst MSG_TIME = `MSG: builtin_interfaces/Time\nint32 sec\nuint32 nanosec`;\n\nconst MSG_UUID = `MSG: unique_identifier_msgs/UUID\nuint8[16] uuid`;\n\nconst MSG_GOAL_INFO = `MSG: action_msgs/GoalInfo\nunique_identifier_msgs/UUID goal_id\nbuiltin_interfaces/Time stamp`;\n\n// ─── service request / response schemas ──────────────────────────────────\n\n// rcl_interfaces/srv/ListParameters\nconst LIST_PARAMETERS_REQUEST = `uint64 DEPTH_RECURSIVE=0\nstring[] prefixes\nuint64 depth`;\nconst LIST_PARAMETERS_RESPONSE = ['ListParametersResult result', MSG_LIST_PARAMETERS_RESULT].join(SEP);\n\n// rcl_interfaces/srv/GetParameters\nconst GET_PARAMETERS_REQUEST = 'string[] names';\nconst GET_PARAMETERS_RESPONSE = ['ParameterValue[] values', MSG_PARAMETER_VALUE].join(SEP);\n\n// rcl_interfaces/srv/SetParameters\nconst SET_PARAMETERS_REQUEST = ['Parameter[] parameters', MSG_PARAMETER, MSG_PARAMETER_VALUE].join(SEP);\nconst SET_PARAMETERS_RESPONSE = ['SetParametersResult[] results', MSG_SET_PARAMETERS_RESULT].join(SEP);\n\n// rcl_interfaces/srv/DescribeParameters\nconst DESCRIBE_PARAMETERS_REQUEST = 'string[] names';\nconst DESCRIBE_PARAMETERS_RESPONSE = [\n 'ParameterDescriptor[] descriptors',\n MSG_PARAMETER_DESCRIPTOR,\n MSG_FLOATING_POINT_RANGE,\n MSG_INTEGER_RANGE,\n].join(SEP);\n\n// rcl_interfaces/srv/GetParameterTypes\nconst GET_PARAMETER_TYPES_REQUEST = 'string[] names';\nconst GET_PARAMETER_TYPES_RESPONSE = 'uint8[] types';\n\n// action_msgs/srv/CancelGoal\nconst CANCEL_GOAL_REQUEST = ['GoalInfo goal_info', MSG_GOAL_INFO, MSG_UUID, MSG_TIME].join(SEP);\nconst CANCEL_GOAL_RESPONSE = [\n `int8 ERROR_NONE = 0\nint8 ERROR_REJECTED = 1\nint8 ERROR_UNKNOWN_GOAL_ID = 2\nint8 ERROR_GOAL_TERMINATED = 3\nint8 return_code\nGoalInfo[] goals_canceling`,\n MSG_GOAL_INFO,\n MSG_UUID,\n MSG_TIME,\n].join(SEP);\n\n// ─── lookup table ────────────────────────────────────────────────────────\n\n/**\n * Result of {@link getBundledServiceSchema}: the request- and response-side\n * schema strings, ready to feed into `@foxglove/rosmsg`'s `parse` (with\n * `{ ros2: true }`). Both sides are present because every bundled service\n * needs encoding the request and decoding the response — splitting the\n * surface would only invite half-configured callers.\n */\nexport interface BundledServiceSchemas {\n request: string;\n response: string;\n}\n\nconst BUNDLED: Record<string, BundledServiceSchemas> = {\n 'rcl_interfaces/srv/ListParameters': {\n request: LIST_PARAMETERS_REQUEST,\n response: LIST_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/GetParameters': {\n request: GET_PARAMETERS_REQUEST,\n response: GET_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/SetParameters': {\n request: SET_PARAMETERS_REQUEST,\n response: SET_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/DescribeParameters': {\n request: DESCRIBE_PARAMETERS_REQUEST,\n response: DESCRIBE_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/GetParameterTypes': {\n request: GET_PARAMETER_TYPES_REQUEST,\n response: GET_PARAMETER_TYPES_RESPONSE,\n },\n 'action_msgs/srv/CancelGoal': {\n request: CANCEL_GOAL_REQUEST,\n response: CANCEL_GOAL_RESPONSE,\n },\n};\n\n/**\n * Look up bundled request/response schemas for a ROS 2 service type\n * (e.g. `\"rcl_interfaces/srv/ListParameters\"`). Returns `null` if the type\n * is not in the bundle. Consult this only when the bridge did not ship a\n * schema inline; bridge-advertised schemas remain authoritative.\n */\nexport function getBundledServiceSchema(serviceType: string): BundledServiceSchemas | null {\n return BUNDLED[serviceType] ?? null;\n}\n\n/**\n * Predicate: does the bundle carry a fallback for this service type? Mostly\n * useful for diagnostics — callers needing the schema content itself should\n * call {@link getBundledServiceSchema} directly.\n */\nexport function hasBundledServiceSchema(serviceType: string): boolean {\n return serviceType in BUNDLED;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * FoxgloveClient — Foxglove WebSocket Protocol v1 implementation.\n *\n * Implements `IProtocolClient` against raw `WebSocket` using the Foxglove WS\n * v1 spec: https://github.com/foxglove/ws-protocol/blob/main/docs/spec.md\n *\n * Key design decisions:\n *\n * - Uses the runtime's global `WebSocket` (no `@foxglove/ws-protocol` SDK),\n * so the same compiled output runs in React Native, browsers, Node 22+\n * natively, and Node 18-21 with a `ws` polyfill.\n * - Supports JSON and CDR (binary) encoding via `@foxglove/rosmsg2-serialization`,\n * with ros2idl and ros2msg schemas.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - Keep-alive ping every 5 s, reconnect if no pong in 10 s.\n * - Dead-man's switch: publishes zero Twist on unexpected disconnect when\n * the client has been publishing on `/cmd_vel`.\n * - Control-priority outbox: gesture, E-Stop, and action-cancel publishes\n * drain at the top of every incoming WS message handler so they ride out\n * before the JS thread is consumed by the next parse macrotask.\n */\n\nimport { parse as parseRosMsgDef } from '@foxglove/rosmsg';\nimport { parseRos2idl } from '@foxglove/ros2idl-parser';\nimport { MessageReader, MessageWriter } from '@foxglove/rosmsg2-serialization';\nimport type { MessageDefinition } from '@foxglove/message-definition';\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\nimport { schemaToTemplate } from './schemaToTemplate';\nimport { jsonSchemaToTemplate } from './jsonSchemaToTemplate';\nimport { getBundledServiceSchema } from './builtinSchemas';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level singletons. `new TextEncoder()` / `new TextDecoder()` are\n// cheap but not free, and the per-message hot path constructs one per call\n// in the original code. Reusing matches what Node and browsers do\n// internally for encoders without options.\nconst TEXT_ENCODER = new TextEncoder();\nconst TEXT_DECODER = new TextDecoder();\n\n/**\n * Decode a base64 string to a byte array using only globally-available\n * primitives. Only the JSON-op `serviceCallResponse` back-compat path\n * still needs this — outbound and inbound binary frames are byte-native.\n * Avoids `Buffer` (Node-only) and the `FileReader`/`Blob` round-trip\n * (RN-finicky).\n */\nfunction base64ToUint8(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n out[i] = binary.charCodeAt(i);\n }\n return out;\n}\n\n/**\n * CDR_LE encapsulation header (4 bytes: `00 01 00 00`). Sent as the entire\n * payload when a schemaless service is called with an empty request — the\n * bridge default-constructs the request server-side from the known service\n * type. Common case for services discovered via ROS 2 graph introspection\n * (foxglove_bridge 3.2.6+'s default), where the bridge advertises the type\n * name but omits the inline IDL.\n */\nconst CDR_LE_HEADER = new Uint8Array([0x00, 0x01, 0x00, 0x00]);\n\n/**\n * True if `request` is empty enough that the bridge can default-construct\n * the Request struct server-side: `null`, `undefined`, or an object literal\n * with no own keys. Non-empty requests genuinely cannot be CDR-encoded\n * without field-layout information and surface a clear error.\n */\nfunction isEmptyRequest(request: unknown): boolean {\n if (request === null || request === undefined) return true;\n if (typeof request !== 'object' || Array.isArray(request)) return false;\n return Object.keys(request as Record<string, unknown>).length === 0;\n}\n\n/**\n * Parse a Foxglove-WS-advertised service or channel schema string into the\n * `MessageDefinition[]` shape both `MessageReader` and `MessageWriter`\n * accept. Uses the declared `schemaEncoding` first; falls back to the same\n * heuristic order `getSchemaTemplate` uses when the bridge doesn't set it.\n * Throws if no parser handles the string.\n */\nfunction parseFoxgloveSchema(\n schemaStr: string,\n encodingHint: string | undefined,\n): MessageDefinition[] {\n const declared = (encodingHint ?? '').toLowerCase();\n const tryRos2idl = (): MessageDefinition[] | null => {\n try {\n return parseRos2idl(schemaStr);\n } catch {\n return null;\n }\n };\n const tryRos2msg = (): MessageDefinition[] | null => {\n try {\n return parseRosMsgDef(schemaStr, { ros2: true });\n } catch {\n return null;\n }\n };\n\n const order = declared === 'ros2idl' ? [tryRos2idl, tryRos2msg] : [tryRos2msg, tryRos2idl];\n for (const attempt of order) {\n const defs = attempt();\n if (defs && defs.length > 0) return defs;\n }\n throw new Error(\n `Could not parse schema (encodingHint=${encodingHint ?? 'none'}, preview=\"${schemaStr.substring(0, 80)}\")`,\n );\n}\n\n// ─── Foxglove WS v1 Protocol Types ──────────────────────────────────────────\n\ninterface FoxgloveChannel {\n id: number;\n topic: string;\n encoding: string;\n schemaName: string;\n schema: string;\n schemaEncoding?: string;\n}\n\ninterface FoxgloveServerInfo {\n op: 'serverInfo';\n name: string;\n capabilities: string[];\n supportedEncodings?: string[];\n metadata?: Record<string, string>;\n sessionId?: string;\n}\n\ninterface FoxgloveAdvertise {\n op: 'advertise';\n channels: FoxgloveChannel[];\n}\n\ninterface FoxgloveUnadvertise {\n op: 'unadvertise';\n channelIds: number[];\n}\n\ninterface FoxgloveServiceResponse {\n op: 'serviceCallResponse';\n serviceId: number;\n callId: number;\n encoding: string;\n data: string;\n}\n\ninterface FoxgloveServiceFailure {\n op: 'serviceCallFailure';\n callId: number;\n message?: string;\n}\n\ninterface FoxgloveService {\n id: number;\n name: string;\n type: string;\n requestSchema?: string;\n responseSchema?: string;\n /** Schema-format hint (`\"ros2idl\"`, `\"ros2msg\"`, ...) for the *request*. */\n requestSchemaEncoding?: string;\n /** Schema-format hint for the *response*. */\n responseSchemaEncoding?: string;\n}\n\ninterface FoxgloveAdvertiseServices {\n op: 'advertiseServices';\n services: FoxgloveService[];\n}\n\ntype FoxgloveServerMessage =\n | FoxgloveServerInfo\n | FoxgloveAdvertise\n | FoxgloveUnadvertise\n | FoxgloveAdvertiseServices\n | FoxgloveServiceResponse\n | FoxgloveServiceFailure\n | { op: string; [key: string]: unknown };\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n// Subprotocol negotiation: send both, server picks the one it supports.\n// - foxglove.sdk.v1: Foxglove Bridge 3.x+ (ROS 2 Jazzy+), adds CDR services + schemas op\n// - foxglove.websocket.v1: Foxglove Bridge 1.x-2.x (Humble/Iron), standard ws-protocol\n// Wire format (opcodes, binary layout, JSON ops) is identical across both.\nconst SUBPROTOCOLS = ['foxglove.sdk.v1', 'foxglove.websocket.v1'];\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\n// Binary op-codes (Foxglove WS v1). Per spec the numbering is *per\n// direction* — 0x02 means TIME inbound but SERVICE_CALL_REQUEST outbound\n// — so we keep two enums to make directionality explicit at call sites.\n//\n// Server → client opcodes we consume. 0x02 TIME and 0x04\n// FETCH_ASSET_RESPONSE are spec-listed but not used here yet.\n// SERVICE_CALL_FAILURE is deliberately absent: per spec it travels as the\n// JSON op `serviceCallFailure`, not as a binary frame.\nenum BinaryOpcode {\n MESSAGE_DATA = 0x01,\n SERVICE_CALL_RESPONSE = 0x03,\n}\n\n// Client → server opcodes we emit. Subset of the spec; the rest of the\n// client→server surface (subscribe, advertise, getParameters, ...) is\n// JSON ops sent via `sendJson`.\nenum ClientBinaryOpcode {\n MESSAGE_DATA = 0x01,\n SERVICE_CALL_REQUEST = 0x02,\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\nexport class FoxgloveClient implements IProtocolClient {\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n\n constructor(options?: ProtocolClientOptions) {\n // `options.onLatency` is intentionally not consumed here. The earlier\n // JSON-op `ping`/`pong` keep-alive that drove RTT measurement is not\n // in the Foxglove WS v1 spec; current bridges reject it with a\n // status-level-2 error. WebSocket-level RFC 6455 ping/pong handles\n // connection liveness automatically but is not portably accessible\n // from JS (browsers don't expose `ws.ping()`). Until the spec or a\n // host-injected probe gives us a portable signal, FoxgloveClient\n // leaves `onLatency` quiescent. RosbridgeClient still drives it.\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n // Channel state\n private channels = new Map<number, FoxgloveChannel>();\n private topicToChannelId = new Map<string, number>();\n\n // Per-subscription state. Each callback keeps its own throttle clock so\n // multi-subscriber topics with different `maxFrequency` settings stay\n // isolated. Bandwidth tracking is per-subscription and feeds the adaptive\n // throttle layered on top of per-callback `maxFrequency`.\n private nextSubscriptionId = 1;\n private subscriptions = new Map<\n number,\n {\n topic: string;\n channelId: number;\n callbacks: Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private topicToSubscriptionId = new Map<string, number>();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n // CDR message readers — keyed by subscriptionId, created from channel schema.\n private messageReaders = new Map<number, MessageReader>();\n\n // Publish state — maps topic → client-advertised channelId.\n private nextClientChannelId = 1;\n private advertisedTopics = new Map<string, number>();\n private hasPublishedTwist = false;\n\n // Control-priority outbox. Twist / E-Stop publishes route through here\n // and get flushed at the top of every incoming WS message handler.\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<{ channelId: number; data: Record<string, unknown> }> = [];\n private controlFlushScheduled = false;\n\n // Service calls\n private nextServiceCallId = 1;\n private pendingServiceCalls = new Map<\n number,\n {\n resolve: (v: Record<string, unknown>) => void;\n reject: (e: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private availableServices = new Map<string, FoxgloveService>();\n /**\n * Per-service CDR codecs. Compiled lazily on first call from the schema\n * the bridge shipped in `advertiseServices`. Foxglove WS service requests\n * and responses are CDR-encoded for ROS 2; the codec parses the bare\n * Request/Response struct (the bridge handles `rmw_request_id_t` wrapping).\n */\n // The defs caches hold the parsed MessageDefinition[] keyed by service id.\n // Keeping them alongside the writer/reader caches buys two things: cheap\n // lookup of zero-value defaults (via schemaToTemplate) when the caller\n // passes an empty request, and a single source of truth for \"where did\n // this schema come from\" (bridge-advertised, bundled fallback, or neither).\n private serviceRequestDefs = new Map<number, MessageDefinition[]>();\n private serviceResponseDefs = new Map<number, MessageDefinition[]>();\n private serviceRequestWriters = new Map<number, MessageWriter>();\n private serviceResponseReaders = new Map<number, MessageReader>();\n\n // Reconnection\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n // Connection handshake\n private connectResolve: (() => void) | null = null;\n private connectReject: ((e: Error) => void) | null = null;\n private serverInfoReceived = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Opening WebSocket to ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n\n // Drain pending control-priority publishes BEFORE closing the socket.\n // Without this, an Action Client cancel-goal queued via the outbox +\n // setTimeout(0) gets dropped when cleanup() closes the websocket — the\n // macrotask scheduler hadn't fired yet, so the E-Stop's cancel never\n // reaches the robot.\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n const appTopics = new Set(this.advertisedTopics.keys());\n\n return Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n }\n\n getSchemaTemplate(schemaName: string): Record<string, unknown> | null {\n // Find a channel advertising this schema, then pick the parser that\n // matches the schema format. Foxglove WS lets a server advertise\n // channels with ros2idl (reference foxglove_bridge), ros2msg (legacy),\n // or JSON Schema (some bridges). Try the declared `schemaEncoding`\n // first, then heuristic-detect; the older foxglove-websocket Python\n // library doesn't set the field.\n for (const ch of this.channels.values()) {\n if (ch.schemaName !== schemaName || !ch.schema) continue;\n const encoding = (ch.schemaEncoding ?? '').toLowerCase();\n const schemaStr = ch.schema;\n const looksLikeJsonSchema = schemaStr.trimStart().startsWith('{');\n\n const tryRos2idl = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRos2idl(schemaStr));\n } catch {\n return null;\n }\n };\n const tryRos2msg = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRosMsgDef(schemaStr, { ros2: true }));\n } catch {\n return null;\n }\n };\n const tryJsonSchema = (): Record<string, unknown> | null => {\n try {\n const parsed = JSON.parse(schemaStr);\n const t = jsonSchemaToTemplate(parsed);\n return t && typeof t === 'object' && !Array.isArray(t)\n ? (t as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n };\n\n let order: Array<() => Record<string, unknown> | null>;\n if (encoding === 'ros2idl') {\n order = [tryRos2idl, tryJsonSchema, tryRos2msg];\n } else if (encoding === 'jsonschema' || looksLikeJsonSchema) {\n order = [tryJsonSchema, tryRos2idl, tryRos2msg];\n } else {\n order = [tryRos2msg, tryRos2idl, tryJsonSchema];\n }\n\n for (const attempt of order) {\n const t = attempt();\n if (t) return t;\n }\n this.log(\n `Schema template parse failed for \"${schemaName}\" — all parsers rejected the schema.`,\n );\n break;\n }\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n\n const existingSubId = this.topicToSubscriptionId.get(topic);\n if (existingSubId !== undefined) {\n const sub = this.subscriptions.get(existingSubId);\n if (sub) {\n sub.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n return () => {\n sub.callbacks.delete(onMessage);\n if (sub.callbacks.size === 0) {\n this.unsubscribeTopic(topic, existingSubId);\n }\n };\n }\n }\n\n const channelId = this.topicToChannelId.get(topic);\n if (channelId === undefined) {\n this.logger.warn(\n `[FoxgloveClient] Topic \"${topic}\" not available. Available: ${Array.from(this.topicToChannelId.keys()).join(', ')}`,\n );\n return () => {};\n }\n\n const subscriptionId = this.nextSubscriptionId++;\n const callbacks = new Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.sendJson({ op: 'unsubscribe', subscriptionIds: [subscriptionId] });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId: sub.channelId }],\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.subscriptions.set(subscriptionId, {\n topic,\n channelId,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n this.topicToSubscriptionId.set(topic, subscriptionId);\n\n const channel = this.channels.get(channelId);\n if (channel && channel.schema && channel.encoding !== 'json') {\n const schemaEncoding = channel.schemaEncoding ?? '';\n this.log(\n `Creating CDR reader for \"${topic}\" (encoding=${channel.encoding}, schemaEncoding=${schemaEncoding})`,\n );\n try {\n let msgDefs;\n if (schemaEncoding === 'ros2idl') {\n msgDefs = parseRos2idl(channel.schema);\n } else {\n msgDefs = parseRosMsgDef(channel.schema, { ros2: true });\n }\n this.messageReaders.set(subscriptionId, new MessageReader(msgDefs));\n this.log(` CDR reader created successfully for \"${topic}\"`);\n } catch (err) {\n this.log(` CDR reader FAILED for \"${topic}\": ${String(err)}`);\n this.log(` Schema preview: ${channel.schema.substring(0, 200)}`);\n }\n }\n\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId }],\n });\n\n return () => {\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic, subscriptionId);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n let clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) {\n clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n\n // Delay first message so the bridge has time to create the ROS\n // publisher. Without this, the message arrives before the publisher\n // is ready and gets dropped.\n const chId = clientChannelId;\n setTimeout(() => {\n this.sendBinaryMessage(chId, data);\n }, 150);\n return;\n }\n\n if (options?.priority === 'control') {\n // Conflate-on-replace by destination. If an entry for this channel is\n // already pending, replace it with the new one rather than appending.\n // Under sustained JS-thread saturation the outbox can accumulate dozens\n // of stale control-priority publishes (e.g. a 30 Hz joystick streaming\n // /cmd_vel while the thread is blocked by a camera decode); without\n // conflation a release-the-joystick zero-Twist queued behind them\n // drains LAST, so the robot keeps moving until every stale frame has\n // been sent. With conflation the zero replaces the stale entry at the\n // same slot and the robot stops in one WS send. The latest publish IS\n // the latest intent — including a stop command. Insertion order across\n // distinct topics is preserved (replace happens in place); only\n // intra-topic duplicates collapse.\n const existing = this.controlOutbox.findIndex((e) => e.channelId === clientChannelId);\n if (existing >= 0) {\n this.controlOutbox[existing] = { channelId: clientChannelId, data };\n } else {\n this.controlOutbox.push({ channelId: clientChannelId, data });\n }\n this.scheduleControlFlush();\n return;\n }\n\n this.sendBinaryMessage(clientChannelId, data);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < FoxgloveClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.sendBinaryMessage(entry.channelId, entry.data);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n const clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n }\n\n unadvertise(topic: string): void {\n const clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'unadvertise',\n channelIds: [clientChannelId],\n });\n }\n }\n\n private sendBinaryMessage(channelId: number, data: Record<string, unknown>): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n const jsonPayload = JSON.stringify(data);\n const payloadBytes = TEXT_ENCODER.encode(jsonPayload);\n\n const buffer = new ArrayBuffer(1 + 4 + payloadBytes.byteLength);\n const view = new DataView(buffer);\n view.setUint8(0, ClientBinaryOpcode.MESSAGE_DATA);\n view.setUint32(1, channelId, true);\n new Uint8Array(buffer, 5).set(payloadBytes);\n\n // Send as a typed array, not the raw ArrayBuffer. React Native's\n // WebSocket native bridge silently drops `send(ArrayBuffer)` payloads\n // above roughly 400 bytes (verified via tcpdump on Chesster: 16-name\n // get_parameters request never left the phone). The Uint8Array path\n // goes through a different RN native serializer that handles every\n // size we send. Same bytes on the wire on browsers/Node; this is\n // load-bearing for RN. Do not revert.\n this.ws.send(new Uint8Array(buffer));\n }\n\n /**\n * Send a service-call request as a binary opcode-0x02 frame. Per\n * Foxglove WS v1 spec, SERVICE_CALL_REQUEST is binary only; the JSON op\n * `serviceCallRequest` that earlier revisions used is not in the spec\n * and is rejected by current bridges with a `status` level-2 message,\n * which leaves the in-flight callId hanging until the 30 s timeout.\n *\n * Frame layout mirrors the inbound 0x03 SERVICE_CALL_RESPONSE parser:\n * [uint8 op=0x02][uint32 serviceId LE][uint32 callId LE]\n * [uint32 encLen LE][utf8 encoding][bytes payload]\n */\n private sendBinaryServiceCallRequest(\n serviceId: number,\n callId: number,\n encoding: string,\n payload: Uint8Array,\n ): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n const encodingBytes = TEXT_ENCODER.encode(encoding);\n const buffer = new ArrayBuffer(\n 1 + 4 + 4 + 4 + encodingBytes.byteLength + payload.byteLength,\n );\n const view = new DataView(buffer);\n view.setUint8(0, ClientBinaryOpcode.SERVICE_CALL_REQUEST);\n view.setUint32(1, serviceId, true);\n view.setUint32(5, callId, true);\n view.setUint32(9, encodingBytes.byteLength, true);\n new Uint8Array(buffer, 13, encodingBytes.byteLength).set(encodingBytes);\n new Uint8Array(buffer, 13 + encodingBytes.byteLength).set(payload);\n // Typed-array send, not raw ArrayBuffer — see comment in\n // sendBinaryMessage. RN drops ArrayBuffer payloads above ~400 bytes,\n // which manifested as 16-name get_parameters requests silently\n // never leaving the phone in Tinca vcode 1071.\n this.ws.send(new Uint8Array(buffer));\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const serviceInfo = this.availableServices.get(service);\n if (!serviceInfo) {\n throw new Error(`Service \"${service}\" not available`);\n }\n\n const callId = this.nextServiceCallId++;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(callId);\n reject(new Error(`Service call \"${service}\" timed out after 30s`));\n }, 30_000);\n\n this.pendingServiceCalls.set(callId, { resolve, reject, timer });\n\n // Encode the request as CDR. JSON-encoded service requests are\n // rejected by foxglove-sdk-cpp v0.18.0+ (\"Unsupported encoding\") even\n // though the server advertises `supportedEncodings: [\"cdr\", \"json\"]`\n // — that capability applies to topic messages, not service calls.\n // CDR is the canonical encoding for ROS 2 services and is accepted\n // by every SDK version.\n //\n // Schema sourcing is layered, in this order:\n // 1. Bridge-advertised `requestSchema` (authoritative when present).\n // 2. Bundled IDL fallback (rcl_interfaces parameter ops,\n // action_msgs/CancelGoal) — used when the bridge omits the\n // schema, the normal case for foxglove_bridge 3.2.6+ services\n // discovered via ROS 2 graph introspection rather than from\n // explicit `.srv` files.\n // 3. No defs at all — empty requests fall back to the CDR\n // encapsulation header only (4 bytes) and the bridge\n // default-constructs from the known service type; non-empty\n // requests cannot be encoded without field layout and surface\n // an explicit error.\n //\n // When defs *are* available (cases 1 and 2), an empty caller request\n // is filled with zero values via `schemaToTemplate` rather than\n // rejected on missing fields. That makes `{}` a stable \"default\n // request\" sentinel across both sim and real-bridge configurations.\n let payloadBytes: Uint8Array;\n try {\n const reqDefs = this.getRequestDefs(serviceInfo);\n if (reqDefs) {\n const writer = this.getOrCompileRequestWriter(serviceInfo.id, reqDefs);\n const payload = isEmptyRequest(request) ? schemaToTemplate(reqDefs) : request;\n payloadBytes = writer.writeMessage(payload);\n } else if (isEmptyRequest(request)) {\n payloadBytes = CDR_LE_HEADER;\n } else {\n throw new Error(\n `Service \"${service}\" (type \"${serviceInfo.type}\") has no request schema advertised and is not in the built-in fallback bundle; cannot encode a non-empty CDR request. ` +\n `The bridge omits inline schemas for services discovered via introspection; empty requests still work via the encapsulation-header fallback.`,\n );\n }\n } catch (err) {\n clearTimeout(timer);\n this.pendingServiceCalls.delete(callId);\n reject(\n new Error(\n `Failed to encode request for \"${service}\": ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n return;\n }\n\n this.sendBinaryServiceCallRequest(serviceInfo.id, callId, 'cdr', payloadBytes);\n });\n }\n\n /**\n * Resolve the parsed request-side {@link MessageDefinition}[] for a\n * service, preferring the bridge-advertised schema and falling back to\n * the built-in bundle (`src/builtinSchemas.ts`) when the bridge omitted\n * one. Returns `null` if neither source has anything for this service —\n * callers then choose between the encapsulation-header fallback (for\n * empty requests) and an explicit error (for non-empty ones). Cached\n * per service id; parse + bundle lookup runs at most once per service\n * advertisement.\n */\n private getRequestDefs(svc: FoxgloveService): MessageDefinition[] | null {\n const cached = this.serviceRequestDefs.get(svc.id);\n if (cached) return cached;\n if (svc.requestSchema) {\n const defs = parseFoxgloveSchema(svc.requestSchema, svc.requestSchemaEncoding);\n this.serviceRequestDefs.set(svc.id, defs);\n return defs;\n }\n const bundled = getBundledServiceSchema(svc.type);\n if (bundled) {\n const defs = parseRosMsgDef(bundled.request, { ros2: true });\n this.serviceRequestDefs.set(svc.id, defs);\n return defs;\n }\n return null;\n }\n\n /** Response-side counterpart to {@link getRequestDefs}; same precedence. */\n private getResponseDefs(svc: FoxgloveService): MessageDefinition[] | null {\n const cached = this.serviceResponseDefs.get(svc.id);\n if (cached) return cached;\n if (svc.responseSchema) {\n const defs = parseFoxgloveSchema(svc.responseSchema, svc.responseSchemaEncoding);\n this.serviceResponseDefs.set(svc.id, defs);\n return defs;\n }\n const bundled = getBundledServiceSchema(svc.type);\n if (bundled) {\n const defs = parseRosMsgDef(bundled.response, { ros2: true });\n this.serviceResponseDefs.set(svc.id, defs);\n return defs;\n }\n return null;\n }\n\n /** Lazily compile and cache the CDR writer for a service's request type. */\n private getOrCompileRequestWriter(\n serviceId: number,\n defs: MessageDefinition[],\n ): MessageWriter {\n const cached = this.serviceRequestWriters.get(serviceId);\n if (cached) return cached;\n const writer = new MessageWriter(defs);\n this.serviceRequestWriters.set(serviceId, writer);\n return writer;\n }\n\n /** Lazily compile and cache the CDR reader for a service's response type. */\n private getOrCompileResponseReader(\n serviceId: number,\n defs: MessageDefinition[],\n ): MessageReader {\n const cached = this.serviceResponseReaders.get(serviceId);\n if (cached) return cached;\n const reader = new MessageReader(defs);\n this.serviceResponseReaders.set(serviceId, reader);\n return reader;\n }\n\n private findServiceById(serviceId: number): FoxgloveService | undefined {\n for (const svc of this.availableServices.values()) {\n if (svc.id === serviceId) return svc;\n }\n return undefined;\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return Array.from(this.availableServices.values()).map((s) => ({\n name: s.name,\n type: s.type,\n }));\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ────────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanup();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n this.connectResolve = resolve;\n this.connectReject = reject;\n\n try {\n this.ws = new WebSocket(this.url, SUBPROTOCOLS);\n this.ws.binaryType = 'arraybuffer';\n\n this.ws.onopen = () => {\n const negotiated = this.ws?.protocol ?? 'unknown';\n this.log(\n `WebSocket handshake successful (protocol: ${negotiated}), waiting for serverInfo...`,\n );\n this.clearConnectionTimeout();\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleWsMessage(event);\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ??\n 'Handshake failed or connection rejected by server';\n this.log(`WebSocket error: ${detail}`);\n this.logger.error('[FoxgloveClient] WebSocket error:', event);\n this.handleConnectionError(new Error(`WebSocket error: ${detail}`));\n };\n\n this.ws.onclose = (event: CloseEvent) => {\n this.log(`WebSocket closed: code=${event.code}, reason=${event.reason || 'none'}`);\n this.handleClose(event.code ?? 1000, event.reason ?? '');\n };\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.handleConnectionError(\n new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`),\n );\n }, CONNECTION_TIMEOUT_MS);\n } catch (err) {\n this.handleConnectionError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n }\n\n // ── Private: WebSocket message handling ──────────────────────────────────\n\n private handleWsMessage(event: MessageEvent): void {\n // Drain the control outbox BEFORE we spend the JS thread parsing this\n // incoming message. Under heavy load, control publishes that landed in\n // the outbox while the previous parse held the thread now ride out\n // before this one starts. Cheap when outbox is empty.\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n if (typeof event.data === 'string') {\n this.handleJsonMessage(event.data);\n } else if (event.data instanceof ArrayBuffer) {\n this.handleBinaryMessage(event.data);\n }\n }\n\n private handleJsonMessage(raw: string): void {\n let msg: FoxgloveServerMessage;\n try {\n msg = JSON.parse(raw) as FoxgloveServerMessage;\n } catch {\n this.logger.warn('[FoxgloveClient] Failed to parse JSON message');\n return;\n }\n\n switch (msg.op) {\n case 'serverInfo':\n this.handleServerInfo(msg as FoxgloveServerInfo);\n break;\n case 'advertise':\n this.handleAdvertise(msg as FoxgloveAdvertise);\n break;\n case 'unadvertise':\n this.handleUnadvertise(msg as FoxgloveUnadvertise);\n break;\n case 'advertiseServices':\n this.handleAdvertiseServices(msg as FoxgloveAdvertiseServices);\n break;\n case 'serviceCallResponse':\n this.handleServiceCallResponse(msg as FoxgloveServiceResponse);\n break;\n case 'serviceCallFailure':\n this.handleServiceCallFailure(msg as FoxgloveServiceFailure);\n break;\n case 'schemas':\n // sdk.v1 sends schemas metadata; not currently needed.\n break;\n case 'status': {\n const status = msg as { level?: number; message?: string };\n if (status.level === 2) {\n const text = status.message ?? '';\n this.logger.error('[FoxgloveClient] Server error:', text);\n // Status messages are undirected — they don't carry a callId.\n // When the bridge rejects a service-call request (e.g. an\n // unsupported encoding or a stale schema), this is the only\n // signal that reaches us; without fast-fail the in-flight\n // callIds hang until their 30 s timeout. Substring-match keeps\n // the rejection scoped to service-call errors.\n if (/serviceCallRequest/i.test(text) && this.pendingServiceCalls.size > 0) {\n this.rejectAllPendingServiceCalls(`Bridge rejected service call: ${text}`);\n }\n }\n break;\n }\n }\n }\n\n private handleBinaryMessage(buffer: ArrayBuffer): void {\n if (buffer.byteLength < 1) return;\n\n const view = new DataView(buffer);\n const opcode = view.getUint8(0);\n\n switch (opcode) {\n case BinaryOpcode.MESSAGE_DATA:\n this.handleBinaryMessageData(buffer, view);\n return;\n case BinaryOpcode.SERVICE_CALL_RESPONSE:\n this.handleBinaryServiceCallResponse(buffer, view);\n return;\n default:\n // Spec-listed but currently unused (0x02 TIME, 0x04\n // FETCH_ASSET_RESPONSE) and any future opcode — drop silently\n // rather than logging on the hot path.\n return;\n }\n }\n\n private handleBinaryMessageData(buffer: ArrayBuffer, view: DataView): void {\n // messageData binary format (server → client):\n // [uint8 op=0x01] [uint32LE subscriptionId] [uint64LE timestamp] [payload]\n if (buffer.byteLength < 13) return;\n const subscriptionId = view.getUint32(1, true);\n\n const timestampLow = view.getUint32(5, true);\n const timestampHigh = view.getUint32(9, true);\n const timestampNs = timestampHigh * 0x100000000 + timestampLow;\n const sec = Math.floor(timestampNs / 1_000_000_000);\n const nsec = timestampNs % 1_000_000_000;\n\n const payloadOffset = 13;\n // Zero-copy view, NOT `buffer.slice(payloadOffset)`. `ArrayBuffer.slice`\n // allocates a fresh ArrayBuffer and copies the payload bytes on every\n // inbound frame, including frames dropped a few lines below by the\n // throttle short-circuit. On raw image topics (10 MB/frame at 30 Hz)\n // that's ~300 MB/s of allocation + GC churn even when 100 % of frames\n // are dropped. `TextDecoder.decode`, `MessageReader.readMessage`, and\n // the four `data = ...` assignments below all accept `Uint8Array`\n // transparently; the regression test in FoxgloveClient.test.ts asserts\n // `data.buffer === frameBuffer` to pin the zero-copy invariant.\n const payload = new Uint8Array(buffer, payloadOffset);\n\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n const mode = this.getThrottleMode();\n recordBytes(sub.bandwidth, now, buffer.byteLength, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second pass.\n const deliverTo: Array<[(msg: RosMessage) => void, { lastDeliveredAt: number }]> = [];\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n const channelInfo = this.channels.get(sub.channelId);\n const schemaName = channelInfo?.schemaName ?? '';\n const encoding = channelInfo?.encoding ?? 'json';\n\n let data: Record<string, unknown> | Uint8Array;\n\n if (encoding === 'json') {\n try {\n const text = TEXT_DECODER.decode(payload);\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n data = payload;\n }\n } else {\n const reader = this.messageReaders.get(subscriptionId);\n if (reader) {\n try {\n data = reader.readMessage(payload) as Record<string, unknown>;\n } catch {\n data = payload;\n }\n } else {\n data = payload;\n }\n }\n\n const rosMsg: RosMessage = {\n topic: sub.topic,\n schemaName,\n encoding: encoding === 'json' ? 'json' : 'cdr',\n data,\n receiveTime: { sec, nsec },\n byteSize: payload.byteLength,\n };\n\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Subscriber callback error:', err);\n }\n }\n }\n\n private handleServerInfo(info: FoxgloveServerInfo): void {\n this.log(`Received serverInfo: ${info.name} (sessionId: ${info.sessionId ?? 'none'})`);\n this.serverInfoReceived = true;\n }\n\n private handleAdvertise(msg: FoxgloveAdvertise): void {\n for (const ch of msg.channels) {\n this.channels.set(ch.id, ch);\n this.topicToChannelId.set(ch.topic, ch.id);\n this.log(\n ` Channel: ${ch.topic} [${ch.schemaName}] encoding=${ch.encoding} schemaEncoding=${ch.schemaEncoding ?? 'none'}`,\n );\n }\n\n if (this.connectResolve && this.serverInfoReceived) {\n this.log(`Connection established with ${msg.channels.length} initial topics.`);\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.setStatus('connected');\n\n this.connectResolve();\n this.connectResolve = null;\n this.connectReject = null;\n } else {\n this.notifyTopicsChanged();\n }\n }\n\n private handleUnadvertise(msg: FoxgloveUnadvertise): void {\n for (const id of msg.channelIds) {\n const ch = this.channels.get(id);\n if (ch) {\n this.topicToChannelId.delete(ch.topic);\n }\n this.channels.delete(id);\n }\n this.notifyTopicsChanged();\n }\n\n private handleAdvertiseServices(msg: FoxgloveAdvertiseServices): void {\n for (const svc of msg.services) {\n this.availableServices.set(svc.name, svc);\n }\n this.notifyServicesChanged();\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Services listener error:', err);\n }\n }\n }\n\n /**\n * Service-call responses arrive on two distinct wire paths and both\n * funnel into {@link dispatchServiceCallResponse}:\n *\n * 1. JSON op `serviceCallResponse` (handled here) — older bridges\n * and any deployment with binary responses disabled. `data` is\n * base64, decoded once into a Uint8Array before dispatch.\n * 2. Binary opcode 0x03 (handled in\n * {@link handleBinaryServiceCallResponse}) — the default for\n * foxglove-sdk-cpp ≥ 0.18.0 / foxglove_bridge 3.2.6+. Payload\n * bytes are passed through directly with no base64 round-trip.\n *\n * Before this split, only the JSON path existed and the binary\n * frames were dropped by {@link handleBinaryMessage} — pending callIds\n * never resolved and surfaced as 30 s timeouts on every callService.\n */\n private handleServiceCallResponse(msg: FoxgloveServiceResponse): void {\n const payload = msg.data ? base64ToUint8(msg.data) : new Uint8Array();\n this.dispatchServiceCallResponse(msg.callId, msg.serviceId, msg.encoding ?? '', payload);\n }\n\n /**\n * Inner decode + dispatch shared by the JSON-op and binary-frame\n * paths. Owns the lookup of the pending call, the timer cleanup, and\n * the CDR / JSON branch — splitting it out keeps the two surface\n * paths thin and prevents drift between them.\n */\n private dispatchServiceCallResponse(\n callId: number,\n serviceId: number,\n encoding: string,\n payload: Uint8Array,\n ): void {\n const pending = this.pendingServiceCalls.get(callId);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(callId);\n\n try {\n if (encoding === 'cdr' && payload.byteLength > 0) {\n const svc = this.findServiceById(serviceId);\n const respDefs = svc ? this.getResponseDefs(svc) : null;\n if (!svc || !respDefs) {\n // Neither the bridge nor the bundle has a response schema for\n // this service. Surface the raw bytes so the consumer can still\n // inspect them rather than swallowing the payload entirely.\n pending.resolve({ rawBytes: payload } as Record<string, unknown>);\n return;\n }\n const reader = this.getOrCompileResponseReader(svc.id, respDefs);\n const decoded = reader.readMessage(payload);\n pending.resolve(decoded as Record<string, unknown>);\n } else if (encoding === 'json' && payload.byteLength > 0) {\n // Back-compat path for older bridges that responded in JSON.\n // TextDecoder is the correct decoder here — `atob` would only\n // round-trip ASCII payloads, but Foxglove can send UTF-8.\n const text = TEXT_DECODER.decode(payload);\n const parsed = JSON.parse(text) as Record<string, unknown>;\n pending.resolve(parsed);\n } else {\n pending.resolve({ success: true });\n }\n } catch (err) {\n pending.reject(\n new Error(\n `Failed to parse service response: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n }\n\n /**\n * Parse a binary opcode-0x03 SERVICE_CALL_RESPONSE frame and dispatch\n * to {@link dispatchServiceCallResponse}. Frame layout (LE throughout):\n *\n * [uint8 op=0x03][uint32 serviceId][uint32 callId]\n * [uint32 encodingLength][utf8 encoding][bytes payload]\n *\n * Malformed frames (too short for the header, or an `encodingLength`\n * that runs past the buffer) are dropped silently — the bridge will\n * either resend or fail the call via the JSON `serviceCallFailure`\n * op, and either way logging on the hot binary path would be noisy.\n */\n private handleBinaryServiceCallResponse(buffer: ArrayBuffer, view: DataView): void {\n if (buffer.byteLength < 13) return; // 1 + 4 + 4 + 4\n const serviceId = view.getUint32(1, true);\n const callId = view.getUint32(5, true);\n const encodingLength = view.getUint32(9, true);\n const payloadOffset = 13 + encodingLength;\n if (buffer.byteLength < payloadOffset) return;\n const encoding = TEXT_DECODER.decode(new Uint8Array(buffer, 13, encodingLength));\n const payload = new Uint8Array(buffer, payloadOffset);\n this.dispatchServiceCallResponse(callId, serviceId, encoding, payload);\n }\n\n /**\n * Handle a `serviceCallFailure` op (callId-targeted rejection from the\n * bridge). Without this, failures sat unhandled and the in-flight promise\n * timed out at 30 s — turning every misencoded request, unknown service,\n * or schema mismatch into a long, opaque hang.\n */\n private handleServiceCallFailure(msg: FoxgloveServiceFailure): void {\n const pending = this.pendingServiceCalls.get(msg.callId);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(msg.callId);\n pending.reject(new Error(msg.message ?? 'Service call failed (no message from bridge)'));\n }\n\n /**\n * Reject every in-flight service call with `reason`, clear their timers,\n * and empty the pending map. Used by {@link cleanup} on disconnect and\n * by the status-level-2 fast-fail path where the bridge has signalled a\n * service-call rejection without naming a callId.\n */\n private rejectAllPendingServiceCalls(reason: string): void {\n for (const pending of this.pendingServiceCalls.values()) {\n clearTimeout(pending.timer);\n pending.reject(new Error(reason));\n }\n this.pendingServiceCalls.clear();\n }\n\n // ── Private: reconnection ────────────────────────────────────────────────\n\n private handleConnectionError(error: Error): void {\n this.clearConnectionTimeout();\n\n if (this.connectReject) {\n this.connectReject(error);\n this.connectResolve = null;\n this.connectReject = null;\n }\n\n this.setStatus('error');\n this.cleanup();\n this.scheduleReconnect();\n }\n\n private handleClose(_code: number, _reason: string): void {\n const wasConnected = this.status === 'connected';\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanup();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.logger.warn(\n `[FoxgloveClient] Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached`,\n );\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[FoxgloveClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: unsubscribe ─────────────────────────────────────────────────\n\n private unsubscribeTopic(topic: string, subscriptionId: number): void {\n const sub = this.subscriptions.get(subscriptionId);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns. Tearing them down here\n // would nuke listeners belonging to other consumers watching the same\n // topic.\n\n this.subscriptions.delete(subscriptionId);\n this.topicToSubscriptionId.delete(topic);\n this.messageReaders.delete(subscriptionId);\n\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.sendJson({\n op: 'unsubscribe',\n subscriptionIds: [subscriptionId],\n });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return 'closed';\n const sub = this.subscriptions.get(subId);\n return sub?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n return this.subscriptions.get(subId)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n const sub = this.subscriptions.get(subId);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ───────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: cleanup ─────────────────────────────────────────────────────\n\n private cleanup(): void {\n this.clearConnectionTimeout();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.rejectAllPendingServiceCalls('Connection closed');\n\n if (this.ws) {\n if (this.ws.readyState === WebSocket.OPEN && this.advertisedTopics.size > 0) {\n const channelIds = Array.from(this.advertisedTopics.values());\n try {\n this.sendJson({ op: 'unadvertise', channelIds });\n } catch {\n // best effort\n }\n }\n\n this.ws.onopen = null;\n this.ws.onmessage = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n if (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n ) {\n this.ws.close();\n }\n this.ws = null;\n }\n\n this.channels.clear();\n this.topicToChannelId.clear();\n this.subscriptions.clear();\n this.topicToSubscriptionId.clear();\n this.messageReaders.clear();\n this.advertisedTopics.clear();\n this.availableServices.clear();\n this.serviceRequestDefs.clear();\n this.serviceResponseDefs.clear();\n this.serviceRequestWriters.clear();\n this.serviceResponseReaders.clear();\n this.notifyServicesChanged();\n this.serverInfoReceived = false;\n this.nextSubscriptionId = 1;\n this.nextClientChannelId = 1;\n this.nextServiceCallId = 1;\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ─────────────────────────────────────────────────────\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Status listener error:', err);\n }\n }\n }\n\n private sendJson(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private notifyTopicsChanged(): void {\n const appTopics = new Set(this.advertisedTopics.keys());\n const topics: TopicInfo[] = Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n for (const cb of this.topicsListeners) {\n try {\n cb(topics);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[FoxgloveClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * RosbridgeClient — rosbridge v2 protocol implementation.\n *\n * Implements the rosbridge v2 JSON protocol directly over the runtime's\n * `WebSocket`. No `roslib` dependency: that library pulls in Node-only\n * modules (`bson`, `ws`) that break in React Native and that we don't need\n * because the protocol is a small JSON envelope.\n *\n * Protocol spec: https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/ROSBRIDGE_PROTOCOL.md\n * Default port: 9090.\n *\n * Features:\n *\n * - Topic discovery via the `/rosapi/topics` service.\n * - Subscribe with `throttle_rate` and `queue_length=1` (drop old, keep\n * latest) for sane defaults on high-rate topics.\n * - Publish with auto-advertise on first send.\n * - Service calls with a 30 s timeout.\n * - Dead-man's switch: zero Twist on unexpected disconnect.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - `tryDropPublishBeforeParse` fast-path: bounded substring scan extracts\n * `op` and `topic` from a `publish` envelope so we can drop messages no\n * callback wants without paying `JSON.parse` cost on the full payload.\n * Matters for high-bandwidth topics where parse dominates per-message\n * work.\n */\n\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level decoder singleton — see the FoxgloveClient comment for the\n// rationale; same reasoning for the rosbridge binary-frame path.\nconst TEXT_DECODER = new TextDecoder();\n\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\nconst DEFAULT_THROTTLE_RATE_MS = 100;\nconst SERVICE_CALL_TIMEOUT_MS = 30_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\nexport class RosbridgeClient implements IProtocolClient {\n private readonly onLatency: ((rttMs: number) => void) | undefined;\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n private availableServices: ServiceInfo[] = [];\n private servicesPollTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(options?: ProtocolClientOptions) {\n this.onLatency = options?.onLatency;\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n private activeSubscriptions = new Map<\n string,\n {\n schemaName: string;\n callbacks: Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n private advertisedTopics = new Set<string>();\n private hasPublishedTwist = false;\n\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<{ op: 'publish'; topic: string; msg: Record<string, unknown> }> = [];\n private controlFlushScheduled = false;\n\n private discoveredTopics: TopicInfo[] = [];\n\n private pendingServiceCalls = new Map<\n string,\n {\n resolve: (result: Record<string, unknown>) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private serviceCallCounter = 0;\n\n private latencyProbeTimer: ReturnType<typeof setInterval> | null = null;\n\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Connecting to rosbridge at ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n if (!this.ws || !this.isConnected) {\n return this.discoveredTopics;\n }\n\n try {\n const result = await this.callService('/rosapi/topics', {});\n const names: string[] = (result.topics as string[]) ?? [];\n const types: string[] = (result.types as string[]) ?? [];\n\n const topics: TopicInfo[] = [];\n for (let i = 0; i < names.length; i++) {\n const name = names[i];\n if (!name) continue;\n topics.push({\n topic: name,\n schemaName: types[i] ?? '',\n encoding: 'json',\n source: this.advertisedTopics.has(name) ? 'app' : 'robot',\n });\n }\n\n this.discoveredTopics = topics;\n this.log(`Discovered ${topics.length} topics.`);\n this.notifyTopicsChanged();\n return topics;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Failed to get topics via rosapi: ${msg}`);\n return this.discoveredTopics;\n }\n }\n\n getSchemaTemplate(_schemaName: string): Record<string, unknown> | null {\n // rosbridge's /rosapi/message_details is async and not surfaced through\n // the current IProtocolClient contract. Consumers that need a template\n // for a rosbridge connection should compose one client-side. Foxglove WS\n // does the heavy lifting via inline schemas.\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n if (!this.ws || this.status !== 'connected') {\n return () => {};\n }\n\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n\n const existing = this.activeSubscriptions.get(topic);\n if (existing) {\n existing.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n return () => {\n existing.callbacks.delete(onMessage);\n if (existing.callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n const topicInfo = this.discoveredTopics.find((t) => t.topic === topic);\n const messageType = topicInfo?.schemaName ?? '';\n\n if (!messageType) {\n this.log(`Warning: subscribing to \"${topic}\" without known message type`);\n }\n\n const callbacks = new Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.send({ op: 'unsubscribe', topic });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'subscribe',\n topic,\n type: sub.schemaName,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.activeSubscriptions.set(topic, {\n schemaName: messageType,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n\n this.send({\n op: 'subscribe',\n topic,\n type: messageType,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n\n return () => {\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n if (!this.advertisedTopics.has(topic)) {\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n const payload = { op: 'publish' as const, topic, msg: data };\n\n if (options?.priority === 'control') {\n // Conflate-on-replace by topic. Mirrors the FoxgloveClient outbox: if a\n // control-priority publish for this topic is already pending, replace\n // rather than append. Under JS-thread saturation a stop publish (zero\n // Twist released by a joystick gesture-end, action cancel, etc.) drains\n // in one WS send instead of behind every stale tick that piled up\n // during the block. The latest publish IS the latest intent. Insertion\n // order across distinct topics is preserved (replace in place); only\n // intra-topic duplicates collapse.\n const existing = this.controlOutbox.findIndex((e) => e.topic === topic);\n if (existing >= 0) {\n this.controlOutbox[existing] = payload;\n } else {\n this.controlOutbox.push(payload);\n }\n this.scheduleControlFlush();\n return;\n }\n\n this.send(payload);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < RosbridgeClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.send(entry);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n unadvertise(topic: string): void {\n if (!this.advertisedTopics.has(topic)) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'unadvertise',\n topic,\n });\n }\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const id = `service_call:${service}:${++this.serviceCallCounter}`;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n reject(\n new Error(`Service call \"${service}\" timed out after ${SERVICE_CALL_TIMEOUT_MS}ms`),\n );\n }, SERVICE_CALL_TIMEOUT_MS);\n\n this.pendingServiceCalls.set(id, { resolve, reject, timer });\n\n this.send({\n op: 'call_service',\n id,\n service,\n args: request,\n });\n });\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return [...this.availableServices];\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n private async discoverServices(): Promise<void> {\n if (!this.isConnected) return;\n try {\n const result = await this.callService('/rosapi/services', {});\n const names: string[] = (result.services as string[]) ?? [];\n const next: ServiceInfo[] = names.map((n) => ({ name: n, type: '' }));\n const prevKey = this.availableServices\n .map((s) => s.name)\n .sort()\n .join('|');\n const nextKey = next.map((s) => s.name).sort().join('|');\n if (prevKey === nextKey) return;\n this.availableServices = next;\n this.notifyServicesChanged();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Service discovery via /rosapi/services failed: ${msg}`);\n this.stopServicesPoll();\n }\n }\n\n private startServicesPoll(): void {\n if (this.servicesPollTimer) return;\n void this.discoverServices();\n this.servicesPollTimer = setInterval(() => {\n void this.discoverServices();\n }, 30_000);\n }\n\n private stopServicesPoll(): void {\n if (this.servicesPollTimer) {\n clearInterval(this.servicesPollTimer);\n this.servicesPollTimer = null;\n }\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Services listener error:', err);\n }\n }\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ──────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanupConnection();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.log(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`);\n reject(new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }, CONNECTION_TIMEOUT_MS);\n\n this.ws.onopen = () => {\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.log('Connected to rosbridge server.');\n this.setStatus('connected');\n this.startLatencyProbe();\n this.startServicesPoll();\n resolve();\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ?? 'Connection error';\n this.log(`Rosbridge error: ${detail}`);\n this.logger.error('[RosbridgeClient] Error:', event);\n\n if (this.status === 'connecting') {\n this.clearConnectionTimeout();\n reject(new Error(`Rosbridge error: ${detail}`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }\n };\n\n this.ws.onclose = () => {\n const wasConnected = this.status === 'connected';\n this.log('Rosbridge connection closed.');\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanupConnection();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleMessage(event.data as string | ArrayBuffer);\n };\n } catch (err) {\n this.clearConnectionTimeout();\n const error = err instanceof Error ? err : new Error(String(err));\n reject(error);\n this.cleanup();\n this.setStatus('error');\n }\n });\n }\n\n // ── Private: message handling ──────────────────────────────────────────\n\n private handleMessage(raw: string | ArrayBuffer): void {\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n try {\n const data = typeof raw === 'string' ? raw : TEXT_DECODER.decode(raw);\n const byteSize = typeof raw === 'string' ? data.length : raw.byteLength;\n // Compute mode once per incoming message and forward to the inner\n // handlers so we don't call the host's `getThrottleMode` twice on the\n // fast-path → dispatch flow.\n const mode = this.getThrottleMode();\n\n if (this.tryDropPublishBeforeParse(data, byteSize, mode)) {\n return;\n }\n\n const msg = JSON.parse(data) as Record<string, unknown>;\n const op = msg.op as string;\n\n switch (op) {\n case 'publish':\n this.handlePublish(msg, byteSize, mode);\n break;\n case 'service_response':\n this.handleServiceResponse(msg);\n break;\n case 'status': {\n const level = msg.level as string | undefined;\n const statusMsg = msg.msg as string | undefined;\n if (level === 'error' || level === 'warning') {\n this.log(`rosbridge ${level}: ${statusMsg ?? 'unknown'}`);\n }\n break;\n }\n }\n } catch (err) {\n this.logger.error('[RosbridgeClient] Failed to parse message:', err);\n }\n }\n\n /**\n * Drop a publish message before paying full `JSON.parse` cost.\n *\n * Rosbridge frames look like `{\"op\":\"publish\",\"topic\":\"…\",\"msg\":{…}}`.\n * For fat payloads (base64-encoded camera frames, large arrays)\n * `JSON.parse` on the whole envelope dominates per-message cost. We do a\n * cheap substring search to extract `op` and `topic`, run the same\n * throttle/breaker accounting `handlePublish` would do, and return `true`\n * to skip the parse when no callback wants the message right now.\n *\n * Handles both compact (`{\"op\":\"publish\"`) and pretty (`{\"op\": \"publish\"`)\n * JSON forms.\n */\n private tryDropPublishBeforeParse(data: string, byteSize: number, mode: ThrottleMode): boolean {\n if (\n !data.startsWith('{\"op\":\"publish\"') &&\n !data.startsWith('{\"op\": \"publish\"')\n ) {\n return false;\n }\n\n const topicKeyIdx = data.indexOf('\"topic\"');\n if (topicKeyIdx < 0 || topicKeyIdx > 200) return false;\n\n let i = topicKeyIdx + 7;\n if (data[i] !== ':') return false;\n i++;\n if (data[i] === ' ') i++;\n if (data[i] !== '\"') return false;\n i++;\n const topicEnd = data.indexOf('\"', i);\n if (topicEnd < 0) return false;\n const topic = data.slice(i, topicEnd);\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return true; // not subscribed → drop\n\n const now = Date.now();\n\n if (sub.isPaused) {\n recordBytes(sub.bandwidth, now, byteSize, mode);\n return true;\n }\n\n let anyCallbackWantsThis = false;\n for (const entry of sub.callbacks.values()) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n anyCallbackWantsThis = true;\n break;\n }\n }\n\n if (anyCallbackWantsThis) return false;\n\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n return true;\n }\n\n private handlePublish(msg: Record<string, unknown>, byteSize: number, mode: ThrottleMode): void {\n const topic = msg.topic as string;\n const msgData = (msg.msg ?? {}) as Record<string, unknown>;\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second loop.\n const deliverTo: Array<[(msg: RosMessage) => void, { lastDeliveredAt: number }]> = [];\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n const rosMsg: RosMessage = {\n topic,\n schemaName: sub.schemaName,\n encoding: 'json',\n data: msgData,\n receiveTime: {\n sec: Math.floor(now / 1000),\n nsec: (now % 1000) * 1_000_000,\n },\n byteSize,\n };\n\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Subscriber callback error:', err);\n }\n }\n }\n\n private handleServiceResponse(msg: Record<string, unknown>): void {\n const id = msg.id as string;\n const pending = this.pendingServiceCalls.get(id);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(id);\n\n const success = msg.result === true || msg.result === 'true';\n if (success) {\n const values = (msg.values ?? {}) as Record<string, unknown>;\n pending.resolve(values);\n } else {\n const errorMsg =\n typeof msg.values === 'string' ? msg.values : 'Service call failed';\n pending.reject(new Error(errorMsg));\n }\n }\n\n // ── Private: topic management ──────────────────────────────────────────\n\n private unsubscribeTopic(topic: string): void {\n const sub = this.activeSubscriptions.get(topic);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns.\n\n this.activeSubscriptions.delete(topic);\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.send({ op: 'unsubscribe', topic });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n return this.activeSubscriptions.get(topic)?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n return this.activeSubscriptions.get(topic)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ─────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: latency probe ──────────────────────────────────────────────\n\n private startLatencyProbe(): void {\n this.stopLatencyProbe();\n this.latencyProbeTimer = setInterval(() => {\n if (!this.ws || this.status !== 'connected') return;\n const start = Date.now();\n const id = `latency_probe:${++this.serviceCallCounter}`;\n\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n }, 5_000);\n\n this.pendingServiceCalls.set(id, {\n resolve: () => {\n clearTimeout(timer);\n if (this.onLatency) {\n try {\n this.onLatency(Date.now() - start);\n } catch {\n // metrics must never affect protocol operation\n }\n }\n },\n reject: () => {\n clearTimeout(timer);\n },\n timer,\n });\n\n this.send({\n op: 'call_service',\n id,\n service: '/rosapi/topics',\n args: {},\n });\n }, 5_000);\n }\n\n private stopLatencyProbe(): void {\n if (this.latencyProbeTimer) {\n clearInterval(this.latencyProbeTimer);\n this.latencyProbeTimer = null;\n }\n }\n\n // ── Private: reconnection ──────────────────────────────────────────────\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.log(`Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached.`);\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[RosbridgeClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: cleanup ───────────────────────────────────────────────────\n\n private cleanupConnection(): void {\n this.clearConnectionTimeout();\n this.stopServicesPoll();\n this.activeSubscriptions.clear();\n\n for (const [, pending] of this.pendingServiceCalls) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Connection closed'));\n }\n this.pendingServiceCalls.clear();\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n for (const topic of this.advertisedTopics) {\n try {\n this.send({ op: 'unadvertise', topic });\n } catch {\n // best effort\n }\n }\n }\n\n this.advertisedTopics.clear();\n }\n\n private cleanup(): void {\n this.cleanupConnection();\n this.stopLatencyProbe();\n this.stopServicesPoll();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n // ignore\n }\n this.ws = null;\n }\n\n this.discoveredTopics = [];\n if (this.availableServices.length > 0) {\n this.availableServices = [];\n this.notifyServicesChanged();\n }\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ───────────────────────────────────────────────────\n\n private send(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Status listener error:', err);\n }\n }\n }\n\n private notifyTopicsChanged(): void {\n for (const cb of this.topicsListeners) {\n try {\n cb(this.discoveredTopics);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[RosbridgeClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\nimport type { ProtocolType } from './types';\n\n/**\n * Default TCP port for each supported protocol. Useful for consumers\n * building connection-configuration UIs that want a sensible starting\n * value when the user changes protocol.\n */\nexport const DEFAULT_PORTS: Record<ProtocolType, number> = {\n 'foxglove-ws': 8765,\n rosbridge: 9090,\n zenoh: 7447,\n};\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * ProtocolManager — factory plus active-connection lifecycle manager.\n *\n * Builds the appropriate `IProtocolClient` for `options.protocol`, sanitizes\n * the user-entered host, validates the URL with `new URL()`, and forwards\n * the connection. Holds the active client so callers don't have to.\n *\n * `setClientOptions` is the injection point for the host's `onLatency`\n * callback, `logger`, and `getThrottleMode` selector. Options are stored\n * and forwarded into every client the manager constructs.\n */\n\nimport { FoxgloveClient } from './FoxgloveClient';\nimport { RosbridgeClient } from './RosbridgeClient';\nimport type {\n ConnectionOptions,\n IProtocolClient,\n ProtocolClientOptions,\n} from './types';\nimport { DEFAULT_PORTS } from './constants';\n\n/**\n * Normalize a user-entered host string into something safe to drop into\n * `${scheme}://${host}:${port}`. Strips `ws://`, `wss://`, `http://`,\n * `https://` prefixes (paste from a browser address bar or a Foxglove URL),\n * drops a trailing `:port` (so a `host:8766` paste doesn't poison the URL\n * with two ports — the dedicated `port` field always wins), and trims\n * trailing path / query / fragment plus whitespace.\n */\nfunction sanitizeHost(raw: string): string {\n let host = (raw ?? '').trim();\n host = host.replace(/^(wss?|https?):\\/\\//i, '');\n // Drop trailing path/query/fragment.\n host = host.split('/')[0] ?? host;\n host = host.split('?')[0] ?? host;\n host = host.split('#')[0] ?? host;\n // Strip trailing :port. IPv6 literals are bracketed (`[::1]:8765`), so\n // only strip when the colon isn't inside brackets.\n if (!host.startsWith('[')) {\n const colonIx = host.indexOf(':');\n if (colonIx !== -1) host = host.slice(0, colonIx);\n }\n return host;\n}\n\nexport class ProtocolManager {\n private activeClient: IProtocolClient | null = null;\n private activeOptions: ConnectionOptions | null = null;\n private clientOptions: ProtocolClientOptions | undefined;\n\n /**\n * Set options forwarded to every client constructed by this manager.\n * Host applications typically call this once at startup.\n */\n setClientOptions(options: ProtocolClientOptions): void {\n this.clientOptions = options;\n }\n\n /**\n * Create and connect a protocol client for the given options.\n *\n * For `protocol: 'zenoh'`, throws a clear \"planned for v0.2.0\" error —\n * the v0.1.0 release does not ship a Zenoh implementation.\n */\n async connect(options: ConnectionOptions): Promise<IProtocolClient> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n }\n\n const client = this.createClient(options);\n const scheme = options.secure ? 'wss' : 'ws';\n const port = options.port || DEFAULT_PORTS[options.protocol];\n const host = sanitizeHost(options.host);\n const url = `${scheme}://${host}:${port}`;\n\n // Validate before handing to the runtime's WebSocket implementation.\n // Some platforms (React Native on Android via okhttp3) throw on the\n // native message-queue thread for malformed ports/hosts — there's no\n // JS-side handler for that, so the process dies. Catching here keeps\n // the failure inside the connection flow where the host can surface\n // it as a regular connection error.\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n } catch {\n throw new Error(\n `Invalid connection URL \"${url}\" — check host and port. Hosts should not include \"ws://\" or \":port\"; use the port field instead.`,\n );\n }\n\n await client.connect(url);\n\n this.activeClient = client;\n this.activeOptions = options;\n\n return client;\n }\n\n /**\n * Disconnect the active client and forget it.\n */\n async disconnect(): Promise<void> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n this.activeClient = null;\n this.activeOptions = null;\n }\n }\n\n /**\n * Currently active client, or `null` if not connected.\n */\n getClient(): IProtocolClient | null {\n return this.activeClient;\n }\n\n /**\n * Currently active connection options, or `null` if not connected.\n */\n getOptions(): ConnectionOptions | null {\n return this.activeOptions;\n }\n\n private createClient(options: ConnectionOptions): IProtocolClient {\n switch (options.protocol) {\n case 'foxglove-ws':\n return new FoxgloveClient(this.clientOptions);\n case 'rosbridge':\n return new RosbridgeClient(this.clientOptions);\n case 'zenoh':\n throw new Error('Zenoh support is planned for v0.2.0');\n default: {\n const exhaustive: never = options.protocol;\n throw new Error(`Unknown protocol: ${String(exhaustive)}`);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/CircuitBreaker.ts","../src/EventLoopMonitor.ts","../src/SubscriptionBandwidth.ts","../src/schemaToTemplate.ts","../src/jsonSchemaToTemplate.ts","../src/schemaName.ts","../src/builtinSchemas.ts","../src/FoxgloveClient.ts","../src/RosbridgeClient.ts","../src/constants.ts","../src/ProtocolManager.ts","../src/materializeBytes.ts"],"names":["parseRos2idl","parseRosMsgDef","MessageReader","MessageWriter","NOOP_LOGGER","TEXT_DECODER","MAX_RECONNECT_ATTEMPTS","BASE_RECONNECT_DELAY_MS","CONNECTION_TIMEOUT_MS","ZERO_TWIST","CMD_VEL_SCHEMA"],"mappings":"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","file":"index.cjs","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * CircuitBreaker — per-subscription state machine that gracefully suspends\n * a topic when the adaptive throttle has done all it can but the JS thread\n * is still saturated.\n *\n * Design rationale: at the deepest throttle bucket (e.g. 0.5 Hz cap), each\n * 1080p q95 frame parse still takes ~200 ms on a modern phone — even one\n * frame every two seconds produces a perceptible 200 ms gesture freeze. No\n * amount of further throttle tuning fixes this; the workload is\n * fundamentally too heavy for the transport on this device. The breaker\n * detects sustained overload at the deepest bucket and unsubscribes from\n * the bridge, freeing the JS thread, network, and memory entirely for that\n * topic until the user (or auto-retry) decides to try again.\n *\n * The state machine has four states:\n * - `closed`: normal, throttle handles the rest\n * - `tripped_auto`: paused, auto-retry timer running (exponential backoff)\n * - `tripped_manual`: paused, NO auto-retry — user opted out\n * - `half_open`: re-subscribed, watching lag for `recoveryDwellMs`; if lag\n * stays low, close; if it spikes, re-trip with longer cooldown.\n *\n * The breaker is a pure state machine — it doesn't send WebSocket ops\n * itself. The protocol client's `onStateChange` callback is responsible for\n * the side effects (send unsubscribe on enter `tripped_auto`, send\n * subscribe on enter `half_open`, etc).\n */\n\nimport type { CircuitBreakerState } from './types';\n\nexport interface CircuitBreakerConfig {\n /**\n * Lag threshold (ms) above which the breaker considers the subscription\n * \"still saturated\" while at the deepest throttle bucket. Suggest 150 ms —\n * comfortably above normal scheduler jitter (~5–30 ms on healthy hardware)\n * and below the threshold where a user perceives the UI as stalled.\n */\n lagThresholdMs: number;\n\n /**\n * Sustained ms of over-threshold lag before tripping. Suggest 2000 ms —\n * long enough that single-frame spikes (one heavy decode, a GC pause)\n * don't trigger, short enough that a genuinely saturating workload trips\n * before the user perceives the app as frozen. Together with the 500 ms\n * `WARMUP_MS` this puts the absolute minimum subscribe-to-unsubscribe\n * floor at ~2.5 s.\n */\n tripDwellMs: number;\n\n /**\n * ms of healthy operation in `half_open` before closing the breaker.\n * Suggest 10000 ms.\n */\n recoveryDwellMs: number;\n\n /**\n * Cooldown durations per consecutive trip within this connection. Index\n * `tripCount - 1` is read; the last value is reused for further trips.\n * Suggest `[30000, 60000, 120000, 300000]`.\n */\n cooldownsMs: number[];\n\n /**\n * Side-effect handler. Called on every state transition. The protocol\n * client uses it to send the actual `subscribe` / `unsubscribe` ops to\n * the bridge.\n */\n onStateChange: (newState: CircuitBreakerState, oldState: CircuitBreakerState) => void;\n}\n\n/**\n * ms of sustained healthy observations before we reset the saturation\n * timer. Without this debounce, lag oscillating around the trip threshold\n * resets the timer every other sample and the breaker never accumulates\n * enough dwell to trip even when the workload is plainly saturating things.\n */\nconst HEALTHY_DEBOUNCE_MS = 4000;\n\n/**\n * Grace period after a (re)subscription before the breaker can register\n * any observations. The first few hundred ms after subscribe have transient\n * spikes (TCP-window fill, bridge backlog drain, first JIT pass through\n * the message-handler hot path) that don't reflect sustained workload.\n * Without warmup these can trip the breaker on lightweight topics before\n * the JIT settles in.\n *\n * Originally 2000 ms — tuned alongside the looser defaults below for\n * JSON-sim spike patterns. Tightened to 500 ms for the CDR-realistic\n * regime: schema parsing happens once in `subscribe()` rather than per\n * message, the per-frame hot path JITs in a handful of frames not seconds,\n * and on real workloads (1080p+ raw camera streams) the cold-start \"flood\"\n * window is what the user perceives as a freeze. A shorter warmup lets the\n * breaker step in before the user feels stuck. The remaining 500 ms is\n * still longer than any genuine cold-path JIT settle on the four target\n * runtimes; topics that legitimately fluctuate during the first half-second\n * also don't see their first sustained spike until the trip dwell anyway.\n */\nconst WARMUP_MS = 500;\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed';\n private tripCount = 0;\n private saturationObservedAt = 0;\n private healthyObservedAt = 0;\n private cooldownTimer: ReturnType<typeof setTimeout> | null = null;\n private subscriptionStartedAt: number = Date.now();\n private nextRetryAt: number | null = null;\n\n constructor(private readonly config: CircuitBreakerConfig) {}\n\n getState(): CircuitBreakerState {\n return this.state;\n }\n\n /**\n * `Date.now()` when auto-retry is scheduled to fire, or `null` if no\n * cooldown is running (closed / half_open / tripped_manual).\n */\n getNextRetryAt(): number | null {\n return this.nextRetryAt;\n }\n\n /**\n * Single entry point for \"I saw a message; here's the current bandwidth\n * and JS-thread lag.\" Internally gates by `HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC`\n * and the breaker's `lagThresholdMs` so the trip policy lives in one place\n * instead of being replicated at every call site.\n */\n recordObservation(now: number, bytesPerSec: number, lagMs: number): void {\n if (bytesPerSec > HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC && lagMs > this.config.lagThresholdMs) {\n this.recordOverloaded(now);\n } else {\n this.recordHealthy(now);\n }\n }\n\n /**\n * Called from the protocol client's `recordBytes` when the tracker is in\n * the heavily-throttled range (top buckets) and lag exceeds the threshold.\n */\n recordOverloaded(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state === 'closed' || this.state === 'half_open') {\n if (this.saturationObservedAt === 0) {\n this.saturationObservedAt = now;\n } else if (now - this.saturationObservedAt >= this.config.tripDwellMs) {\n this.trip();\n }\n this.healthyObservedAt = 0;\n }\n }\n\n /**\n * Called from `recordBytes` when lag is below threshold or the tracker is\n * below the heavily-throttled range.\n */\n recordHealthy(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state !== 'closed' && this.state !== 'half_open') return;\n\n if (this.healthyObservedAt === 0) {\n this.healthyObservedAt = now;\n }\n const healthyDwell = now - this.healthyObservedAt;\n\n if (this.saturationObservedAt > 0 && healthyDwell >= HEALTHY_DEBOUNCE_MS) {\n this.saturationObservedAt = 0;\n }\n\n if (this.state === 'half_open' && healthyDwell >= this.config.recoveryDwellMs) {\n this.close();\n }\n }\n\n /**\n * User pressed \"try again now\" — bypasses the cooldown timer and jumps\n * straight to `half_open`. Works from any tripped state.\n */\n retry(): void {\n if (this.state === 'tripped_auto' || this.state === 'tripped_manual') {\n this.clearCooldown();\n this.openHalf();\n }\n }\n\n /**\n * User pressed \"stop trying\" — switches `tripped_auto` to `tripped_manual`\n * and cancels the auto-retry timer. The subscription remains paused until\n * the user manually retries.\n */\n disable(): void {\n if (this.state === 'tripped_auto') {\n this.clearCooldown();\n this.transition('tripped_manual');\n }\n }\n\n /**\n * Called by the protocol client on disconnect or unsubscribe so the\n * cooldown timer doesn't outlive the connection.\n */\n destroy(): void {\n this.clearCooldown();\n }\n\n // ── Internal transitions ─────────────────────────────────────────────\n\n private trip(): void {\n this.tripCount++;\n this.saturationObservedAt = 0;\n const cooldownIdx = Math.min(this.tripCount - 1, this.config.cooldownsMs.length - 1);\n const cooldownMs = this.config.cooldownsMs[cooldownIdx] ?? 30_000;\n this.nextRetryAt = Date.now() + cooldownMs;\n this.transition('tripped_auto');\n this.cooldownTimer = setTimeout(() => {\n this.cooldownTimer = null;\n this.nextRetryAt = null;\n if (this.state === 'tripped_auto') {\n this.openHalf();\n }\n }, cooldownMs);\n }\n\n private openHalf(): void {\n const now = Date.now();\n this.saturationObservedAt = 0;\n this.healthyObservedAt = 0;\n this.subscriptionStartedAt = now;\n this.transition('half_open');\n }\n\n private close(): void {\n this.saturationObservedAt = 0;\n this.transition('closed');\n }\n\n private transition(next: CircuitBreakerState): void {\n const prev = this.state;\n if (prev === next) return;\n this.state = next;\n try {\n this.config.onStateChange(next, prev);\n } catch {\n // The side-effect callback shouldn't throw; if it does we don't want\n // to leave the breaker in a half-applied state — `this.state` is\n // already updated above.\n }\n }\n\n private clearCooldown(): void {\n if (this.cooldownTimer !== null) {\n clearTimeout(this.cooldownTimer);\n this.cooldownTimer = null;\n }\n this.nextRetryAt = null;\n }\n}\n\n/**\n * Default config tuned for the camera-on-modern-phone workload that\n * motivated the breaker. Protocol clients can override per subscription.\n *\n * v0.1.x history: the original `lagThresholdMs: 250 / tripDwellMs: 5000`\n * pair was calibrated against JSON-sim tests where the failure shape was\n * 100–333 ms transient spikes interleaved with healthy stretches. CDR\n * sensor streams on real hardware fail in a different regime — sustained\n * multi-second freezes during the cold-start window. The current values\n * (`150 / 2000`) trade some false-positive risk on transient spikes for\n * faster detection of the genuine-freeze pattern, since that's the case\n * where the user perceives the app as stuck and needs the breaker to\n * step in before the symptom passes the perception threshold.\n */\nexport const DEFAULT_BREAKER_CONFIG: Omit<CircuitBreakerConfig, 'onStateChange'> = {\n lagThresholdMs: 150,\n tripDwellMs: 2_000,\n recoveryDwellMs: 10_000,\n cooldownsMs: [30_000, 60_000, 120_000, 300_000],\n};\n\n/**\n * Bytes/sec floor a subscription must exceed before the breaker considers\n * tripping it. Without this gate, when one heavy publisher saturates the\n * thread, every subscription sees the same high lag and trips in lockstep\n * — killing innocent low-rate topics. With the gate, only the actual heavy\n * contributor qualifies.\n */\nexport const HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC = 500_000;\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * EventLoopMonitor — direct measurement of JS-thread saturation.\n *\n * Hardcoded byte/sec bucket thresholds were a proxy for \"is the JS thread\n * saturated?\" calibrated to one device class and one message size; on\n * different devices or with bigger frames they under- or over-throttled.\n * This monitor measures the actual symptom.\n *\n * Mechanism: a `setInterval` fires every PROBE_INTERVAL_MS. Each tick\n * records how late it ran vs. when it was scheduled. Under saturation the\n * JS thread is busy with parse / reconcile work and the timer fires late —\n * that delta IS the lag. Under idle, lag is ~0-5 ms (normal scheduler\n * jitter).\n *\n * Smoothing: a 1 s rolling window keeps (timestamp, lag) pairs. The\n * reported value is the MAX over that window, not an EMA — bursty\n * saturation should be detected on the spike, not blurred away.\n *\n * The monitor starts on first `getMaxLagMs()` call (lazy) and runs forever.\n * Cost: one `setInterval` at 5 Hz reading `Date.now()`.\n *\n * Public surface: `getMaxLagMs`, `getLagStats`, `getLagHistoryCsv`, and\n * `clearLagHistory` are exported from the package and let consumers build\n * \"currently throttled\" diagnostics. `setModeGetter` is module-internal —\n * protocol clients call it from their constructors so the lag history is\n * tagged with the active throttle mode for bug-report exports, and\n * consumers never need to wire it themselves.\n */\n\nconst PROBE_INTERVAL_MS = 200;\nconst WINDOW_MS = 1000;\nconst HISTORY_MAX = 600;\n\ninterface LagSample {\n t: number;\n lag: number;\n}\n\ninterface HistorySample {\n t: number;\n lag: number;\n mode: string;\n}\n\nlet started = false;\nlet lastTickAt = 0;\nconst samples: LagSample[] = [];\nconst history: HistorySample[] = [];\n\nlet modeGetter: () => string = () => 'auto';\n\n/**\n * Internal. Protocol clients invoke this from their constructors with the\n * value they received from `ProtocolClientOptions.getThrottleMode`. The\n * monitor uses the result to tag history samples with the active throttle\n * mode for the diagnostics CSV. Not re-exported from the package entry\n * point — consumers configure throttle mode through `getThrottleMode`.\n */\nexport function setModeGetter(fn: () => string): void {\n modeGetter = fn;\n}\n\nfunction startMonitor(): void {\n if (started) return;\n started = true;\n lastTickAt = Date.now();\n const handle: unknown = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickAt;\n const lag = Math.max(0, elapsed - PROBE_INTERVAL_MS);\n lastTickAt = now;\n\n samples.push({ t: now, lag });\n const cutoff = now - WINDOW_MS;\n while (samples.length > 0) {\n const head = samples[0];\n if (!head || head.t >= cutoff) break;\n samples.shift();\n }\n\n let mode = 'auto';\n try {\n mode = modeGetter();\n } catch {\n // mode tagging is best-effort; never break the monitor on a bad getter.\n }\n history.push({ t: now, lag, mode });\n if (history.length > HISTORY_MAX) {\n history.shift();\n }\n }, PROBE_INTERVAL_MS);\n\n // The monitor is a passive diagnostic; it must not keep a Node process\n // alive on its own. Once a consumer's real work (an active WebSocket,\n // an HTTP server) finishes, the process should exit even if the monitor\n // is still ticking. `unref` exists on Node's Timeout object; browsers,\n // React Native, and Electron's renderer don't have or need it.\n const unref = (handle as { unref?: () => void } | null)?.unref;\n if (typeof unref === 'function') {\n unref.call(handle);\n }\n}\n\n/**\n * Max observed JS-thread lag (ms) over the last `WINDOW_MS`. Auto-starts\n * the monitor on first call. Returns `0` if no samples have been collected\n * yet.\n */\nexport function getMaxLagMs(): number {\n if (!started) startMonitor();\n let max = 0;\n for (const s of samples) {\n if (s.lag > max) max = s.lag;\n }\n return max;\n}\n\n/**\n * Percentile statistics over the long-term history buffer (roughly the last\n * 2 minutes). Returns `null` when no samples have been collected yet.\n */\nexport function getLagStats(): {\n count: number;\n durationSec: number;\n p50: number;\n p90: number;\n p99: number;\n max: number;\n} | null {\n if (history.length === 0) return null;\n const sorted = history.map((s) => s.lag).sort((a, b) => a - b);\n const pick = (q: number): number => {\n const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * q));\n return sorted[idx] ?? 0;\n };\n const first = history[0];\n const last = history[history.length - 1];\n const span = first && last ? (last.t - first.t) / 1000 : 0;\n return {\n count: history.length,\n durationSec: Math.round(span),\n p50: pick(0.5),\n p90: pick(0.9),\n p99: pick(0.99),\n max: sorted[sorted.length - 1] ?? 0,\n };\n}\n\n/**\n * CSV dump of the history buffer. One row per sample, mode-tagged so a\n * recording that spans a throttle-mode change still tells you which lag\n * values belong to which mode. Useful for attaching to bug reports.\n */\nexport function getLagHistoryCsv(): string {\n const header = 'timestamp_ms,lag_ms,mode';\n const rows = history.map((s) => `${s.t},${s.lag},${s.mode}`);\n return [header, ...rows].join('\\n');\n}\n\n/**\n * Clear the long-term history buffer. The rolling 1 s window used by the\n * throttle keeps running, so live throttle decisions stay correct. Useful\n * when starting a new test session.\n */\nexport function clearLagHistory(): void {\n history.length = 0;\n}\n\n/**\n * Test helper. Resets the monitor's internal state so unit tests get a\n * clean slate. Not exported from the package entry point.\n *\n * @internal\n */\nexport function __resetEventLoopMonitor(): void {\n samples.length = 0;\n history.length = 0;\n lastTickAt = Date.now();\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * SubscriptionBandwidth — adaptive throttle driven by JS-thread saturation.\n *\n * Bucket selection reads `EventLoopMonitor.getMaxLagMs()` rather than a\n * per-subscription bytes/sec rate. The symptom the throttle is protecting\n * against (gesture and control starvation) is a property of the JS thread,\n * not of any single message stream, so the right signal is thread saturation\n * directly. A bytes/sec ladder would have to be calibrated per device class\n * and per message size — fragile in a library targeting four runtimes — and\n * would miss the case where several medium-rate subscriptions (lidar + odom\n * + imu) sum to thread saturation while none individually crosses a byte\n * threshold.\n *\n * Bytes/sec is still tracked per subscription for metrics and UI (\"currently\n * throttled because /camera is at 5 MB/s\") via `getSubscriptionStats`; it is\n * not the throttle decision input.\n *\n * Hysteresis: tighten immediately on the spike (saturation costs gesture\n * authority — pay the cost up front), relax slowly (3 s below threshold) so\n * the throttle doesn't oscillate around a boundary.\n *\n * The curves themselves (`DEFAULT_PRESETS` below) were tuned on one device\n * class. Consumers can override per mode via `ProtocolClientOptions.presetOverrides`;\n * each tracker carries its own effective preset map so two clients with\n * different overrides don't share state.\n */\n\nimport { getMaxLagMs } from './EventLoopMonitor';\nimport type { BucketDef, ProtocolLogger, ThrottleMode } from './types';\n\nconst BANDWIDTH_WINDOW_MS = 1000;\nconst TIGHTEN_DWELL_MS = 0;\nconst RELAX_DWELL_MS = 3000;\n\n/**\n * Library-tuned throttle curves. Override via\n * `ProtocolClientOptions.presetOverrides` to ship a per-device-class curve.\n * Exported for use by consumers building their own preset variants on top\n * of the defaults (e.g. `{ ...DEFAULT_PRESETS, auto: [...customAuto] }`).\n *\n * @experimental The override *shape* (`BucketDef`, `ThrottleMode`,\n * `presetOverrides`) is semver-stable, but the default *values* in this map\n * may be rebalanced in any patch release as device-tuning data accrues. Do\n * not snapshot these numbers and assume they're frozen; reference the export\n * if you want to track the current defaults.\n */\nexport const DEFAULT_PRESETS: Record<ThrottleMode, BucketDef[]> = {\n performance: [{ threshold: 0, minIntervalMs: 0, label: 'none' }],\n\n auto: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 100, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 150, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n\n efficient: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 80, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 130, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n};\n\nconst THROTTLE_MODES: readonly ThrottleMode[] = ['performance', 'auto', 'efficient'];\n\n/**\n * Pessimistic-start initial bucket per mode. Without this, every new\n * subscription floods → spike → tighten, costing the first ~1 s of\n * usability while the throttle catches up. Each tracker boots at a\n * moderate cap and only relaxes if observed lag stays below the\n * next-lower bucket's threshold long enough.\n */\nconst INITIAL_BUCKET_PER_MODE: Record<ThrottleMode, number> = {\n performance: 0,\n auto: 2,\n efficient: 3,\n};\n\n/**\n * Validate a single mode's bucket array. Returns `true` if usable as an\n * override; logs a warning and returns `false` otherwise so the caller can\n * fall back to the default for that mode.\n *\n * Only enforces correctness-essential rules:\n * - The array is non-empty.\n * - The first bucket has `threshold === 0`.\n *\n * Consumer-hygiene rules (thresholds sorted ascending, unique labels) are\n * intentionally not enforced — `recordBytes` and `bucketLabelForLag`\n * terminate with sensible-enough results in their absence, and listing every\n * possible quality rule is not the library's job.\n */\nfunction validatePreset(\n buckets: BucketDef[] | undefined,\n mode: ThrottleMode,\n logger: ProtocolLogger,\n): boolean {\n if (!buckets || buckets.length === 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: empty bucket array; using default preset for this mode`,\n );\n return false;\n }\n const first = buckets[0];\n if (!first || first.threshold !== 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: first bucket must have threshold === 0 (the \"no throttle\" base case); using default preset for this mode`,\n );\n return false;\n }\n return true;\n}\n\n/**\n * Merge consumer-supplied overrides on top of `DEFAULT_PRESETS`. Invalid\n * per-mode overrides are skipped (with a `logger.warn`); valid ones replace\n * the default for their mode. Returns a fresh object so two clients with\n * different overrides never share mutable state through this map.\n */\nexport function buildEffectivePresets(\n overrides: Partial<Record<ThrottleMode, BucketDef[]>> | undefined,\n logger: ProtocolLogger,\n): Record<ThrottleMode, BucketDef[]> {\n const merged: Record<ThrottleMode, BucketDef[]> = {\n performance: DEFAULT_PRESETS.performance,\n auto: DEFAULT_PRESETS.auto,\n efficient: DEFAULT_PRESETS.efficient,\n };\n if (!overrides) return merged;\n\n for (const mode of THROTTLE_MODES) {\n const override = overrides[mode];\n if (override === undefined) continue;\n if (validatePreset(override, mode, logger)) {\n merged[mode] = override;\n }\n }\n return merged;\n}\n\nexport interface BandwidthTracker {\n /** Ring buffer of (timestamp, byteSize) over the rolling window. */\n window: Array<{ t: number; b: number }>;\n /** Cached bytes/sec, updated on each `recordBytes`. */\n bytesPerSec: number;\n /** Bucket index currently applied (drives `adaptiveMinIntervalMs`). */\n currentBucket: number;\n /**\n * Most recently observed target bucket (may differ from `currentBucket`\n * while we're inside the hysteresis dwell window).\n */\n targetBucket: number;\n /** ms timestamp when `targetBucket` was first observed. */\n targetObservedAt: number;\n /** Effective adaptive throttle interval. `0` means no throttle. */\n adaptiveMinIntervalMs: number;\n /**\n * Effective preset map for this tracker. Shared by reference across every\n * tracker created by the same client; never mutated after construction.\n */\n presets: Record<ThrottleMode, BucketDef[]>;\n}\n\nexport function createBandwidthTracker(\n mode: ThrottleMode = 'auto',\n presets: Record<ThrottleMode, BucketDef[]> = DEFAULT_PRESETS,\n): BandwidthTracker {\n const initialBucket = INITIAL_BUCKET_PER_MODE[mode] ?? 0;\n const preset = presets[mode];\n const safeInitial = Math.min(initialBucket, Math.max(0, preset.length - 1));\n const initialIntervalMs = preset[safeInitial]?.minIntervalMs ?? 0;\n return {\n window: [],\n bytesPerSec: 0,\n currentBucket: safeInitial,\n targetBucket: safeInitial,\n targetObservedAt: 0,\n adaptiveMinIntervalMs: initialIntervalMs,\n presets,\n };\n}\n\n/**\n * Record an incoming message of `byteSize` bytes at time `now`. Updates the\n * rolling byte window and applies the bucket policy for the active mode\n * based on JS-thread lag. Mutates `tracker` in place.\n *\n * Bucket selection reads from `EventLoopMonitor.getMaxLagMs()` — a global\n * signal, not per-subscription. If every subscription is a small\n * contributor but they sum to JS-thread saturation, the throttle still\n * fires. That's correct: the symptom we're protecting against (gesture and\n * control starvation) is a property of the thread, not a single stream.\n */\nexport function recordBytes(\n tracker: BandwidthTracker,\n now: number,\n byteSize: number,\n mode: ThrottleMode = 'auto',\n): void {\n tracker.window.push({ t: now, b: byteSize });\n const cutoff = now - BANDWIDTH_WINDOW_MS;\n while (tracker.window.length > 0) {\n const head = tracker.window[0];\n if (!head || head.t >= cutoff) break;\n tracker.window.shift();\n }\n let total = 0;\n for (const e of tracker.window) total += e.b;\n tracker.bytesPerSec = total / (BANDWIDTH_WINDOW_MS / 1000);\n\n const buckets = tracker.presets[mode];\n const lagMs = getMaxLagMs();\n\n let targetBucket = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n targetBucket = i;\n break;\n }\n }\n\n if (targetBucket !== tracker.targetBucket) {\n tracker.targetBucket = targetBucket;\n tracker.targetObservedAt = now;\n return;\n }\n if (targetBucket === tracker.currentBucket) {\n return;\n }\n\n const dwell = now - tracker.targetObservedAt;\n const tighten = targetBucket > tracker.currentBucket;\n const requiredDwell = tighten ? TIGHTEN_DWELL_MS : RELAX_DWELL_MS;\n if (dwell < requiredDwell) return;\n\n if (tighten) {\n tracker.currentBucket = targetBucket;\n } else {\n tracker.currentBucket = Math.max(targetBucket, tracker.currentBucket - 1);\n tracker.targetObservedAt = now;\n }\n tracker.adaptiveMinIntervalMs = buckets[tracker.currentBucket]?.minIntervalMs ?? 0;\n}\n\n/**\n * Effective min-interval (ms) for a callback, combining the user's request\n * with the adaptive throttle. The user's `userMinIntervalMs` is a floor —\n * adaptive can only make the interval longer, never shorter.\n */\nexport function effectiveMinInterval(\n userMinIntervalMs: number | undefined,\n disableAdaptive: boolean,\n tracker: BandwidthTracker,\n): number {\n const user = userMinIntervalMs ?? 0;\n if (disableAdaptive) return user;\n return Math.max(user, tracker.adaptiveMinIntervalMs);\n}\n\n/**\n * Reset the tracker to the deepest bucket so half-open recovery starts\n * conservative. The throttle's existing step-relax logic walks the bucket\n * back up if observed lag stays below the next-lower bucket's threshold.\n * Avoids a flood-then-tighten cycle on every breaker recovery.\n */\nexport function setTrackerToDeepest(tracker: BandwidthTracker, mode: ThrottleMode): void {\n const buckets = tracker.presets[mode];\n const lastIdx = Math.max(0, buckets.length - 1);\n tracker.currentBucket = lastIdx;\n tracker.targetBucket = lastIdx;\n tracker.targetObservedAt = 0;\n tracker.adaptiveMinIntervalMs = buckets[lastIdx]?.minIntervalMs ?? 0;\n}\n\n/**\n * Label of the bucket the tracker is currently sitting at. Used by UI to\n * tell the user what cap their subscription is throttled to right now.\n * Returns `\"none\"` for the no-cap bucket (or when the tracker's bucket\n * index is somehow out of range, which shouldn't happen in practice).\n */\nexport function getTrackerBucketLabel(tracker: BandwidthTracker, mode: ThrottleMode): string {\n const buckets = tracker.presets[mode];\n return buckets[tracker.currentBucket]?.label ?? 'none';\n}\n\n/**\n * Resolve which bucket a given lag value would land in for the active mode\n * under the library's **default** presets. Independent of any tracker —\n * pass a raw lag measurement (typically from `getMaxLagMs()`) and the\n * active throttle mode, and get back the bucket label the default-tuned\n * throttle would apply at that lag.\n *\n * Useful for diagnostics overlays that want to show \"JS lag is N ms →\n * bucket X\" so observers can correlate measured lag with the throttle\n * policy.\n *\n * **Note on `presetOverrides`:** this function is a stateless module-level\n * helper and has no awareness of per-client overrides. If a consumer\n * supplies `presetOverrides.auto`, calling `bucketLabelForLag('auto', lag)`\n * still returns the **default** bucket label for that lag value, not the\n * override's. For override-aware bucket labels, read\n * `getSubscriptionStats(topic).bucketLabel` off a live subscription.\n */\nexport function bucketLabelForLag(mode: ThrottleMode, lagMs: number): string {\n const buckets = DEFAULT_PRESETS[mode];\n let idx = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n idx = i;\n break;\n }\n }\n return buckets[idx]?.label ?? 'none';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * schemaToTemplate — derive a default JSON payload from a parsed ROS message\n * definition.\n *\n * Takes the array returned by `@foxglove/rosmsg` (for `.msg` and ros2msg) or\n * `@foxglove/ros2idl-parser` (for ros2idl). The first element is the root\n * message; subsequent elements are referenced types. Returns a plain object\n * with every field set to its zero / empty default, ready to use as a\n * starting point for a publish payload editor.\n */\n\nimport type { MessageDefinition } from '@foxglove/message-definition';\n\nconst PRIMITIVE_DEFAULTS: Record<string, unknown> = {\n bool: false,\n int8: 0,\n uint8: 0,\n int16: 0,\n uint16: 0,\n int32: 0,\n uint32: 0,\n int64: 0,\n uint64: 0,\n float32: 0.0,\n float64: 0.0,\n string: '',\n wstring: '',\n time: { sec: 0, nsec: 0 },\n duration: { sec: 0, nsec: 0 },\n 'builtin_interfaces/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/Duration': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Duration': { sec: 0, nanosec: 0 },\n};\n\n/**\n * Build a default JSON template from a parsed message definition. Used by\n * `IProtocolClient.getSchemaTemplate` to surface ready-to-edit payloads for\n * publish UIs.\n */\nexport function schemaToTemplate(\n definitions: MessageDefinition[],\n): Record<string, unknown> {\n if (!definitions.length) return {};\n\n const typeMap = new Map<string, MessageDefinition>();\n for (const def of definitions) {\n if (def.name) {\n typeMap.set(def.name, def);\n }\n }\n\n const root = definitions[0];\n if (!root) return {};\n return buildObject(root, typeMap, 0);\n}\n\nfunction buildObject(\n def: MessageDefinition,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): Record<string, unknown> {\n // Guard against self-referencing types.\n if (depth > 10) return {};\n\n const result: Record<string, unknown> = {};\n\n for (const field of def.definitions) {\n if (field.isConstant) continue;\n\n const defaultVal = getFieldDefault(field.type, field.isComplex, typeMap, depth);\n\n if (field.isArray) {\n result[field.name] = [];\n } else {\n result[field.name] = defaultVal;\n }\n }\n\n return result;\n}\n\nfunction getFieldDefault(\n typeName: string,\n isComplex: boolean | undefined,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): unknown {\n if (PRIMITIVE_DEFAULTS[typeName] !== undefined) {\n const val = PRIMITIVE_DEFAULTS[typeName];\n return typeof val === 'object' ? JSON.parse(JSON.stringify(val)) : val;\n }\n\n if (isComplex) {\n const subDef = typeMap.get(typeName);\n if (subDef) {\n return buildObject(subDef, typeMap, depth + 1);\n }\n for (const [key, def] of typeMap) {\n if (key.endsWith(`/${typeName}`) || typeName.endsWith(`/${key}`)) {\n return buildObject(def, typeMap, depth + 1);\n }\n }\n }\n\n return '';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * jsonSchemaToTemplate — derive a zero-valued JSON payload from a JSON Schema.\n *\n * Used by the Foxglove WebSocket path to turn bridges that ship JSON Schema\n * into Topic-Publisher / field-path templates. The reference foxglove_bridge\n * ships ros2idl instead, which `schemaToTemplate` handles; this parser\n * covers the remaining gap so consumers don't need a hard-coded table of\n * well-known ROS 2 types.\n *\n * Scope: draft-07-compatible JSON Schema, restricted to the subset a bridge\n * typically emits for ROS message shapes (object / array / primitive).\n * Does not resolve `$ref`, `allOf` / `oneOf` / `anyOf`, or enum defaults.\n */\n\nexport function jsonSchemaToTemplate(schema: unknown): unknown {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return null;\n const s = schema as Record<string, unknown>;\n\n // Explicit `default` wins over type-derived zero value.\n if ('default' in s) return s.default;\n\n const type = s.type;\n if (type === 'object') {\n const props = s.properties;\n if (!props || typeof props !== 'object' || Array.isArray(props)) return {};\n const result: Record<string, unknown> = {};\n for (const [key, sub] of Object.entries(props as Record<string, unknown>)) {\n result[key] = jsonSchemaToTemplate(sub);\n }\n return result;\n }\n\n if (type === 'array') {\n // Zero-length array matches the ROS shape for variable-length fields\n // (JointState.name, LaserScan.ranges, etc.).\n return [];\n }\n\n if (type === 'string') return '';\n if (type === 'number' || type === 'integer') return 0;\n if (type === 'boolean') return false;\n if (type === 'null') return null;\n\n // Union type (e.g. ['number', 'null']) — pick the first non-null entry.\n if (Array.isArray(type)) {\n const first = type.find((t) => t !== 'null') ?? type[0];\n return jsonSchemaToTemplate({ ...s, type: first });\n }\n\n return null;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * ROS schema-name helpers.\n *\n * Bridges report the same logical type in two forms depending on ROS version\n * and bridge: the 3-part ROS 2 canonical `pkg/kind/Type`\n * (`geometry_msgs/msg/Twist`) and the 2-part ROS 1 / legacy `pkg/Type`\n * (`geometry_msgs/Twist`). Comparing names by exact string therefore gives\n * false mismatches. The kind segment cannot be inferred from a 2-part name, so\n * the only safe canonicalization is to *strip* the kind, never to insert one.\n */\n\n// Matches a 3-part name whose middle segment is a recognized ROS 2 interface\n// kind. Package and type names are single path segments (no embedded slash).\nconst INTERFACE_KIND = /^([^/]+)\\/(?:msg|srv|action)\\/([^/]+)$/;\n\n/**\n * Reduce `pkg/kind/Type` to `pkg/Type` by dropping a recognized interface-kind\n * segment (`msg` / `srv` / `action`). Names already in 2-part form, or whose\n * middle segment is not a recognized kind, pass through unchanged. Internal —\n * the basis for the exported {@link matchesSchema} and for tolerant builtin\n * lookups; not re-exported from `index.ts`.\n */\nexport function stripInterfaceKind(name: string): string {\n const m = INTERFACE_KIND.exec(name);\n return m ? `${m[1]}/${m[2]}` : name;\n}\n\n/**\n * Compare two ROS schema names for equality, tolerant of the ROS 1 / ROS 2\n * `msg/` (and `srv/`, `action/`) asymmetry. An exact string compare reports a\n * false mismatch when one side carries the interface-kind segment and the\n * other does not.\n *\n * `matchesSchema` strips the interface-kind segment from both sides and\n * compares `pkg` + `Type`, so it is **kind-agnostic** and handles `msg`,\n * `srv`, and `action` types uniformly. Because the kind is dropped,\n * `pkg/msg/Foo` and `pkg/srv/Foo` compare equal — a theoretical collision that\n * does not arise in practice, since a topic's message type is never compared\n * against a service type. Comparison is exact on the surviving `pkg` and\n * `Type` segments; there is no case or whitespace folding.\n *\n * @example\n * ```ts\n * matchesSchema('sensor_msgs/msg/Image', 'sensor_msgs/Image'); // true\n * matchesSchema('std_srvs/srv/Trigger', 'std_srvs/Trigger'); // true\n * matchesSchema('std_msgs/msg/String', 'std_msgs/msg/Header'); // false\n * ```\n */\nexport function matchesSchema(a: string, b: string): boolean {\n return stripInterfaceKind(a) === stripInterfaceKind(b);\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\nimport { stripInterfaceKind } from './schemaName';\n\n/**\n * Bundled IDL definitions for the ROS 2 system services that\n * `foxglove_bridge` (and other CDR transports) commonly discover via graph\n * introspection without shipping inline schemas. Without these fallbacks,\n * callers cannot invoke parameter operations or cancel action goals over\n * Foxglove WS when the bridge omits the IDL — which is the default\n * behavior in `foxglove_bridge` 3.2.6+ for services it discovered through\n * ROS 2 introspection rather than from explicit `.srv` files.\n *\n * Definitions are taken from `rcl_interfaces` and `action_msgs`, both\n * stable across ROS 2 distributions. Bounded sequences (`T[<=N]`) in the\n * canonical `.msg` files are encoded here as unbounded sequences (`T[]`):\n * the two forms produce identical CDR wire output for any value with N or\n * fewer elements, and the parser pin we depend on (`@foxglove/rosmsg`)\n * accepts the unbounded form directly without negotiation.\n *\n * The lookup surface is intentionally narrow:\n * `getBundledServiceSchema(serviceType)` returns request- and\n * response-side schema strings or `null`. This module is **not** exported\n * from `src/index.ts`; it is an internal fallback that the Foxglove\n * protocol client consults only when the bridge-advertised schema is\n * missing. Bridge-shipped schemas remain authoritative when present.\n */\n\nconst SEP = '\\n================================================================================\\n';\n\n// ─── nested message definitions ──────────────────────────────────────────\n// Each constant is a single `MSG: package/Type` block. Service schemas\n// further down compose them with `SEP` to produce the standard\n// concatenated form `@foxglove/rosmsg` parses with `{ ros2: true }`.\n\nconst MSG_PARAMETER_VALUE = `MSG: rcl_interfaces/ParameterValue\nuint8 type\nbool bool_value\nint64 integer_value\nfloat64 double_value\nstring string_value\nbyte[] byte_array_value\nbool[] bool_array_value\nint64[] integer_array_value\nfloat64[] double_array_value\nstring[] string_array_value`;\n\nconst MSG_PARAMETER = `MSG: rcl_interfaces/Parameter\nstring name\nParameterValue value`;\n\nconst MSG_SET_PARAMETERS_RESULT = `MSG: rcl_interfaces/SetParametersResult\nbool successful\nstring reason`;\n\nconst MSG_LIST_PARAMETERS_RESULT = `MSG: rcl_interfaces/ListParametersResult\nstring[] names\nstring[] prefixes`;\n\nconst MSG_FLOATING_POINT_RANGE = `MSG: rcl_interfaces/FloatingPointRange\nfloat64 from_value\nfloat64 to_value\nfloat64 step`;\n\nconst MSG_INTEGER_RANGE = `MSG: rcl_interfaces/IntegerRange\nint64 from_value\nint64 to_value\nuint64 step`;\n\nconst MSG_PARAMETER_DESCRIPTOR = `MSG: rcl_interfaces/ParameterDescriptor\nstring name\nuint8 type\nstring description\nstring additional_constraints\nbool read_only\nbool dynamic_typing\nFloatingPointRange[] floating_point_range\nIntegerRange[] integer_range`;\n\nconst MSG_TIME = `MSG: builtin_interfaces/Time\nint32 sec\nuint32 nanosec`;\n\nconst MSG_UUID = `MSG: unique_identifier_msgs/UUID\nuint8[16] uuid`;\n\nconst MSG_GOAL_INFO = `MSG: action_msgs/GoalInfo\nunique_identifier_msgs/UUID goal_id\nbuiltin_interfaces/Time stamp`;\n\n// ─── service request / response schemas ──────────────────────────────────\n\n// rcl_interfaces/srv/ListParameters\nconst LIST_PARAMETERS_REQUEST = `uint64 DEPTH_RECURSIVE=0\nstring[] prefixes\nuint64 depth`;\nconst LIST_PARAMETERS_RESPONSE = ['ListParametersResult result', MSG_LIST_PARAMETERS_RESULT].join(SEP);\n\n// rcl_interfaces/srv/GetParameters\nconst GET_PARAMETERS_REQUEST = 'string[] names';\nconst GET_PARAMETERS_RESPONSE = ['ParameterValue[] values', MSG_PARAMETER_VALUE].join(SEP);\n\n// rcl_interfaces/srv/SetParameters\nconst SET_PARAMETERS_REQUEST = ['Parameter[] parameters', MSG_PARAMETER, MSG_PARAMETER_VALUE].join(SEP);\nconst SET_PARAMETERS_RESPONSE = ['SetParametersResult[] results', MSG_SET_PARAMETERS_RESULT].join(SEP);\n\n// rcl_interfaces/srv/DescribeParameters\nconst DESCRIBE_PARAMETERS_REQUEST = 'string[] names';\nconst DESCRIBE_PARAMETERS_RESPONSE = [\n 'ParameterDescriptor[] descriptors',\n MSG_PARAMETER_DESCRIPTOR,\n MSG_FLOATING_POINT_RANGE,\n MSG_INTEGER_RANGE,\n].join(SEP);\n\n// rcl_interfaces/srv/GetParameterTypes\nconst GET_PARAMETER_TYPES_REQUEST = 'string[] names';\nconst GET_PARAMETER_TYPES_RESPONSE = 'uint8[] types';\n\n// action_msgs/srv/CancelGoal\nconst CANCEL_GOAL_REQUEST = ['GoalInfo goal_info', MSG_GOAL_INFO, MSG_UUID, MSG_TIME].join(SEP);\nconst CANCEL_GOAL_RESPONSE = [\n `int8 ERROR_NONE = 0\nint8 ERROR_REJECTED = 1\nint8 ERROR_UNKNOWN_GOAL_ID = 2\nint8 ERROR_GOAL_TERMINATED = 3\nint8 return_code\nGoalInfo[] goals_canceling`,\n MSG_GOAL_INFO,\n MSG_UUID,\n MSG_TIME,\n].join(SEP);\n\n// ─── lookup table ────────────────────────────────────────────────────────\n\n/**\n * Result of {@link getBundledServiceSchema}: the request- and response-side\n * schema strings, ready to feed into `@foxglove/rosmsg`'s `parse` (with\n * `{ ros2: true }`). Both sides are present because every bundled service\n * needs encoding the request and decoding the response — splitting the\n * surface would only invite half-configured callers.\n */\nexport interface BundledServiceSchemas {\n request: string;\n response: string;\n}\n\nconst BUNDLED: Record<string, BundledServiceSchemas> = {\n 'rcl_interfaces/srv/ListParameters': {\n request: LIST_PARAMETERS_REQUEST,\n response: LIST_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/GetParameters': {\n request: GET_PARAMETERS_REQUEST,\n response: GET_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/SetParameters': {\n request: SET_PARAMETERS_REQUEST,\n response: SET_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/DescribeParameters': {\n request: DESCRIBE_PARAMETERS_REQUEST,\n response: DESCRIBE_PARAMETERS_RESPONSE,\n },\n 'rcl_interfaces/srv/GetParameterTypes': {\n request: GET_PARAMETER_TYPES_REQUEST,\n response: GET_PARAMETER_TYPES_RESPONSE,\n },\n 'action_msgs/srv/CancelGoal': {\n request: CANCEL_GOAL_REQUEST,\n response: CANCEL_GOAL_RESPONSE,\n },\n};\n\n/**\n * Look up bundled request/response schemas for a ROS 2 service type\n * (e.g. `\"rcl_interfaces/srv/ListParameters\"`). Returns `null` if the type\n * is not in the bundle. Consult this only when the bridge did not ship a\n * schema inline; bridge-advertised schemas remain authoritative.\n *\n * The lookup is tolerant of the 2-part / 3-part schema-name asymmetry: a\n * bridge reporting `rcl_interfaces/ListParameters` resolves to the bundled\n * `rcl_interfaces/srv/ListParameters`. Every bundled key is a `srv/` type, so\n * matching kind-agnostically can never resolve to the wrong interface kind.\n */\nexport function getBundledServiceSchema(serviceType: string): BundledServiceSchemas | null {\n const exact = BUNDLED[serviceType];\n if (exact) return exact;\n\n const target = stripInterfaceKind(serviceType);\n for (const key of Object.keys(BUNDLED)) {\n if (stripInterfaceKind(key) === target) return BUNDLED[key] ?? null;\n }\n return null;\n}\n\n/**\n * Predicate: does the bundle carry a fallback for this service type? Mostly\n * useful for diagnostics — callers needing the schema content itself should\n * call {@link getBundledServiceSchema} directly. Tolerant of the 2-part /\n * 3-part asymmetry, matching {@link getBundledServiceSchema}.\n */\nexport function hasBundledServiceSchema(serviceType: string): boolean {\n return getBundledServiceSchema(serviceType) !== null;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * FoxgloveClient — Foxglove WebSocket Protocol v1 implementation.\n *\n * Implements `IProtocolClient` against raw `WebSocket` using the Foxglove WS\n * v1 spec: https://github.com/foxglove/ws-protocol/blob/main/docs/spec.md\n *\n * Key design decisions:\n *\n * - Uses the runtime's global `WebSocket` (no `@foxglove/ws-protocol` SDK),\n * so the same compiled output runs in React Native, browsers, Node 22+\n * natively, and Node 18-21 with a `ws` polyfill.\n * - Supports JSON and CDR (binary) encoding via `@foxglove/rosmsg2-serialization`,\n * with ros2idl and ros2msg schemas.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - Keep-alive ping every 5 s, reconnect if no pong in 10 s.\n * - Dead-man's switch: publishes zero Twist on unexpected disconnect when\n * the client has been publishing on `/cmd_vel`.\n * - Control-priority outbox: gesture, E-Stop, and action-cancel publishes\n * drain at the top of every incoming WS message handler so they ride out\n * before the JS thread is consumed by the next parse macrotask.\n */\n\nimport { parse as parseRosMsgDef } from '@foxglove/rosmsg';\nimport { parseRos2idl } from '@foxglove/ros2idl-parser';\nimport { MessageReader, MessageWriter } from '@foxglove/rosmsg2-serialization';\nimport type { MessageDefinition } from '@foxglove/message-definition';\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\nimport { schemaToTemplate } from './schemaToTemplate';\nimport { jsonSchemaToTemplate } from './jsonSchemaToTemplate';\nimport { getBundledServiceSchema } from './builtinSchemas';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level singletons. `new TextEncoder()` / `new TextDecoder()` are\n// cheap but not free, and the per-message hot path constructs one per call\n// in the original code. Reusing matches what Node and browsers do\n// internally for encoders without options.\nconst TEXT_ENCODER = new TextEncoder();\nconst TEXT_DECODER = new TextDecoder();\n\n/**\n * Decode a base64 string to a byte array using only globally-available\n * primitives. Only the JSON-op `serviceCallResponse` back-compat path\n * still needs this — outbound and inbound binary frames are byte-native.\n * Avoids `Buffer` (Node-only) and the `FileReader`/`Blob` round-trip\n * (RN-finicky).\n */\nfunction base64ToUint8(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n out[i] = binary.charCodeAt(i);\n }\n return out;\n}\n\n/**\n * CDR_LE encapsulation header (4 bytes: `00 01 00 00`). Sent as the entire\n * payload when a schemaless service is called with an empty request — the\n * bridge default-constructs the request server-side from the known service\n * type. Common case for services discovered via ROS 2 graph introspection\n * (foxglove_bridge 3.2.6+'s default), where the bridge advertises the type\n * name but omits the inline IDL.\n */\nconst CDR_LE_HEADER = new Uint8Array([0x00, 0x01, 0x00, 0x00]);\n\n/**\n * True if `request` is empty enough that the bridge can default-construct\n * the Request struct server-side: `null`, `undefined`, or an object literal\n * with no own keys. Non-empty requests genuinely cannot be CDR-encoded\n * without field-layout information and surface a clear error.\n */\nfunction isEmptyRequest(request: unknown): boolean {\n if (request === null || request === undefined) return true;\n if (typeof request !== 'object' || Array.isArray(request)) return false;\n return Object.keys(request as Record<string, unknown>).length === 0;\n}\n\n/**\n * Parse a Foxglove-WS-advertised service or channel schema string into the\n * `MessageDefinition[]` shape both `MessageReader` and `MessageWriter`\n * accept. Uses the declared `schemaEncoding` first; falls back to the same\n * heuristic order `getSchemaTemplate` uses when the bridge doesn't set it.\n * Throws if no parser handles the string.\n */\nfunction parseFoxgloveSchema(\n schemaStr: string,\n encodingHint: string | undefined,\n): MessageDefinition[] {\n const declared = (encodingHint ?? '').toLowerCase();\n const tryRos2idl = (): MessageDefinition[] | null => {\n try {\n return parseRos2idl(schemaStr);\n } catch {\n return null;\n }\n };\n const tryRos2msg = (): MessageDefinition[] | null => {\n try {\n return parseRosMsgDef(schemaStr, { ros2: true });\n } catch {\n return null;\n }\n };\n\n const order = declared === 'ros2idl' ? [tryRos2idl, tryRos2msg] : [tryRos2msg, tryRos2idl];\n for (const attempt of order) {\n const defs = attempt();\n if (defs && defs.length > 0) return defs;\n }\n throw new Error(\n `Could not parse schema (encodingHint=${encodingHint ?? 'none'}, preview=\"${schemaStr.substring(0, 80)}\")`,\n );\n}\n\n// ─── Foxglove WS v1 Protocol Types ──────────────────────────────────────────\n\ninterface FoxgloveChannel {\n id: number;\n topic: string;\n encoding: string;\n schemaName: string;\n schema: string;\n schemaEncoding?: string;\n}\n\ninterface FoxgloveServerInfo {\n op: 'serverInfo';\n name: string;\n capabilities: string[];\n supportedEncodings?: string[];\n metadata?: Record<string, string>;\n sessionId?: string;\n}\n\ninterface FoxgloveAdvertise {\n op: 'advertise';\n channels: FoxgloveChannel[];\n}\n\ninterface FoxgloveUnadvertise {\n op: 'unadvertise';\n channelIds: number[];\n}\n\ninterface FoxgloveServiceResponse {\n op: 'serviceCallResponse';\n serviceId: number;\n callId: number;\n encoding: string;\n data: string;\n}\n\ninterface FoxgloveServiceFailure {\n op: 'serviceCallFailure';\n callId: number;\n message?: string;\n}\n\ninterface FoxgloveService {\n id: number;\n name: string;\n type: string;\n requestSchema?: string;\n responseSchema?: string;\n /** Schema-format hint (`\"ros2idl\"`, `\"ros2msg\"`, ...) for the *request*. */\n requestSchemaEncoding?: string;\n /** Schema-format hint for the *response*. */\n responseSchemaEncoding?: string;\n}\n\ninterface FoxgloveAdvertiseServices {\n op: 'advertiseServices';\n services: FoxgloveService[];\n}\n\ntype FoxgloveServerMessage =\n | FoxgloveServerInfo\n | FoxgloveAdvertise\n | FoxgloveUnadvertise\n | FoxgloveAdvertiseServices\n | FoxgloveServiceResponse\n | FoxgloveServiceFailure\n | { op: string; [key: string]: unknown };\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n// Subprotocol negotiation: send both, server picks the one it supports.\n// - foxglove.sdk.v1: Foxglove Bridge 3.x+ (ROS 2 Jazzy+), adds CDR services + schemas op\n// - foxglove.websocket.v1: Foxglove Bridge 1.x-2.x (Humble/Iron), standard ws-protocol\n// Wire format (opcodes, binary layout, JSON ops) is identical across both.\nconst SUBPROTOCOLS = ['foxglove.sdk.v1', 'foxglove.websocket.v1'];\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\n// Binary op-codes (Foxglove WS v1). Per spec the numbering is *per\n// direction* — 0x02 means TIME inbound but SERVICE_CALL_REQUEST outbound\n// — so we keep two enums to make directionality explicit at call sites.\n//\n// Server → client opcodes we consume. 0x02 TIME and 0x04\n// FETCH_ASSET_RESPONSE are spec-listed but not used here yet.\n// SERVICE_CALL_FAILURE is deliberately absent: per spec it travels as the\n// JSON op `serviceCallFailure`, not as a binary frame.\nenum BinaryOpcode {\n MESSAGE_DATA = 0x01,\n SERVICE_CALL_RESPONSE = 0x03,\n}\n\n// Client → server opcodes we emit. Subset of the spec; the rest of the\n// client→server surface (subscribe, advertise, getParameters, ...) is\n// JSON ops sent via `sendJson`.\nenum ClientBinaryOpcode {\n MESSAGE_DATA = 0x01,\n SERVICE_CALL_REQUEST = 0x02,\n}\n\n// Per-callback subscription state. One entry per `onMessage` registered\n// against a topic; `dispatchMode` and the deferred-drain fields below it are\n// only exercised by `latest-only` subscribers.\ninterface CallbackEntry {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n dispatchMode: 'immediate' | 'latest-only';\n // `latest-only` deferred-drain state. `pending` holds a materialized\n // (owned) copy of the newest un-delivered payload; `drainTimer` is the armed\n // `setTimeout(0)` that will parse and deliver it. Both null in `immediate`.\n pending: { payload: Uint8Array; sec: number; nsec: number } | null;\n drainTimer: ReturnType<typeof setTimeout> | null;\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\nexport class FoxgloveClient implements IProtocolClient {\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n\n constructor(options?: ProtocolClientOptions) {\n // `options.onLatency` is intentionally not consumed here. The earlier\n // JSON-op `ping`/`pong` keep-alive that drove RTT measurement is not\n // in the Foxglove WS v1 spec; current bridges reject it with a\n // status-level-2 error. WebSocket-level RFC 6455 ping/pong handles\n // connection liveness automatically but is not portably accessible\n // from JS (browsers don't expose `ws.ping()`). Until the spec or a\n // host-injected probe gives us a portable signal, FoxgloveClient\n // leaves `onLatency` quiescent. RosbridgeClient still drives it.\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n // Channel state\n private channels = new Map<number, FoxgloveChannel>();\n private topicToChannelId = new Map<string, number>();\n\n // Per-subscription state. Each callback keeps its own throttle clock so\n // multi-subscriber topics with different `maxFrequency` settings stay\n // isolated. Bandwidth tracking is per-subscription and feeds the adaptive\n // throttle layered on top of per-callback `maxFrequency`.\n private nextSubscriptionId = 1;\n private subscriptions = new Map<\n number,\n {\n topic: string;\n channelId: number;\n callbacks: Map<\n (msg: RosMessage) => void,\n CallbackEntry\n >;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private topicToSubscriptionId = new Map<string, number>();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n // CDR message readers — keyed by subscriptionId, created from channel schema.\n private messageReaders = new Map<number, MessageReader>();\n\n // Publish state — maps topic → client-advertised channelId.\n private nextClientChannelId = 1;\n private advertisedTopics = new Map<string, number>();\n private hasPublishedTwist = false;\n\n // Control-priority outbox. Twist / E-Stop publishes route through here\n // and get flushed at the top of every incoming WS message handler.\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<{ channelId: number; data: Record<string, unknown> }> = [];\n private controlFlushScheduled = false;\n\n // Service calls\n private nextServiceCallId = 1;\n private pendingServiceCalls = new Map<\n number,\n {\n resolve: (v: Record<string, unknown>) => void;\n reject: (e: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private availableServices = new Map<string, FoxgloveService>();\n /**\n * Per-service CDR codecs. Compiled lazily on first call from the schema\n * the bridge shipped in `advertiseServices`. Foxglove WS service requests\n * and responses are CDR-encoded for ROS 2; the codec parses the bare\n * Request/Response struct (the bridge handles `rmw_request_id_t` wrapping).\n */\n // The defs caches hold the parsed MessageDefinition[] keyed by service id.\n // Keeping them alongside the writer/reader caches buys two things: cheap\n // lookup of zero-value defaults (via schemaToTemplate) when the caller\n // passes an empty request, and a single source of truth for \"where did\n // this schema come from\" (bridge-advertised, bundled fallback, or neither).\n private serviceRequestDefs = new Map<number, MessageDefinition[]>();\n private serviceResponseDefs = new Map<number, MessageDefinition[]>();\n private serviceRequestWriters = new Map<number, MessageWriter>();\n private serviceResponseReaders = new Map<number, MessageReader>();\n\n // Reconnection\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n // Connection handshake\n private connectResolve: (() => void) | null = null;\n private connectReject: ((e: Error) => void) | null = null;\n private serverInfoReceived = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Opening WebSocket to ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n\n // Drain pending control-priority publishes BEFORE closing the socket.\n // Without this, an Action Client cancel-goal queued via the outbox +\n // setTimeout(0) gets dropped when cleanup() closes the websocket — the\n // macrotask scheduler hadn't fired yet, so the E-Stop's cancel never\n // reaches the robot.\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n const appTopics = new Set(this.advertisedTopics.keys());\n\n return Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n }\n\n getSchemaTemplate(schemaName: string): Record<string, unknown> | null {\n // Find a channel advertising this schema, then pick the parser that\n // matches the schema format. Foxglove WS lets a server advertise\n // channels with ros2idl (reference foxglove_bridge), ros2msg (legacy),\n // or JSON Schema (some bridges). Try the declared `schemaEncoding`\n // first, then heuristic-detect; the older foxglove-websocket Python\n // library doesn't set the field.\n for (const ch of this.channels.values()) {\n if (ch.schemaName !== schemaName || !ch.schema) continue;\n const encoding = (ch.schemaEncoding ?? '').toLowerCase();\n const schemaStr = ch.schema;\n const looksLikeJsonSchema = schemaStr.trimStart().startsWith('{');\n\n const tryRos2idl = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRos2idl(schemaStr));\n } catch {\n return null;\n }\n };\n const tryRos2msg = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRosMsgDef(schemaStr, { ros2: true }));\n } catch {\n return null;\n }\n };\n const tryJsonSchema = (): Record<string, unknown> | null => {\n try {\n const parsed = JSON.parse(schemaStr);\n const t = jsonSchemaToTemplate(parsed);\n return t && typeof t === 'object' && !Array.isArray(t)\n ? (t as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n };\n\n let order: Array<() => Record<string, unknown> | null>;\n if (encoding === 'ros2idl') {\n order = [tryRos2idl, tryJsonSchema, tryRos2msg];\n } else if (encoding === 'jsonschema' || looksLikeJsonSchema) {\n order = [tryJsonSchema, tryRos2idl, tryRos2msg];\n } else {\n order = [tryRos2msg, tryRos2idl, tryJsonSchema];\n }\n\n for (const attempt of order) {\n const t = attempt();\n if (t) return t;\n }\n this.log(\n `Schema template parse failed for \"${schemaName}\" — all parsers rejected the schema.`,\n );\n break;\n }\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n const dispatchMode = options?.dispatchMode ?? 'immediate';\n\n const existingSubId = this.topicToSubscriptionId.get(topic);\n if (existingSubId !== undefined) {\n const sub = this.subscriptions.get(existingSubId);\n if (sub) {\n sub.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n dispatchMode,\n pending: null,\n drainTimer: null,\n });\n return () => {\n const entry = sub.callbacks.get(onMessage);\n if (entry) this.cancelDrain(entry);\n sub.callbacks.delete(onMessage);\n if (sub.callbacks.size === 0) {\n this.unsubscribeTopic(topic, existingSubId);\n }\n };\n }\n }\n\n const channelId = this.topicToChannelId.get(topic);\n if (channelId === undefined) {\n this.logger.warn(\n `[FoxgloveClient] Topic \"${topic}\" not available. Available: ${Array.from(this.topicToChannelId.keys()).join(', ')}`,\n );\n return () => {};\n }\n\n const subscriptionId = this.nextSubscriptionId++;\n const callbacks = new Map<(msg: RosMessage) => void, CallbackEntry>();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n dispatchMode,\n pending: null,\n drainTimer: null,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n // A breaker trip discards any pending latest-only payload: the bytes\n // are stale (the topic tripped *because* it was saturating) and we\n // must not deliver after pausing the subscription.\n if (sub.isPaused) this.cancelAllDrains(sub);\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.sendJson({ op: 'unsubscribe', subscriptionIds: [subscriptionId] });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId: sub.channelId }],\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.subscriptions.set(subscriptionId, {\n topic,\n channelId,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n this.topicToSubscriptionId.set(topic, subscriptionId);\n\n const channel = this.channels.get(channelId);\n if (channel && channel.schema && channel.encoding !== 'json') {\n const schemaEncoding = channel.schemaEncoding ?? '';\n this.log(\n `Creating CDR reader for \"${topic}\" (encoding=${channel.encoding}, schemaEncoding=${schemaEncoding})`,\n );\n try {\n let msgDefs;\n if (schemaEncoding === 'ros2idl') {\n msgDefs = parseRos2idl(channel.schema);\n } else {\n msgDefs = parseRosMsgDef(channel.schema, { ros2: true });\n }\n this.messageReaders.set(subscriptionId, new MessageReader(msgDefs));\n this.log(` CDR reader created successfully for \"${topic}\"`);\n } catch (err) {\n this.log(` CDR reader FAILED for \"${topic}\": ${String(err)}`);\n this.log(` Schema preview: ${channel.schema.substring(0, 200)}`);\n }\n }\n\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId }],\n });\n\n return () => {\n const entry = callbacks.get(onMessage);\n if (entry) this.cancelDrain(entry);\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic, subscriptionId);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n let clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) {\n clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n\n // Delay first message so the bridge has time to create the ROS\n // publisher. Without this, the message arrives before the publisher\n // is ready and gets dropped.\n const chId = clientChannelId;\n setTimeout(() => {\n this.sendBinaryMessage(chId, data);\n }, 150);\n return;\n }\n\n if (options?.priority === 'control') {\n // Conflate-on-replace by destination. If an entry for this channel is\n // already pending, replace it with the new one rather than appending.\n // Under sustained JS-thread saturation the outbox can accumulate dozens\n // of stale control-priority publishes (e.g. a 30 Hz joystick streaming\n // /cmd_vel while the thread is blocked by a camera decode); without\n // conflation a release-the-joystick zero-Twist queued behind them\n // drains LAST, so the robot keeps moving until every stale frame has\n // been sent. With conflation the zero replaces the stale entry at the\n // same slot and the robot stops in one WS send. The latest publish IS\n // the latest intent — including a stop command. Insertion order across\n // distinct topics is preserved (replace happens in place); only\n // intra-topic duplicates collapse.\n const existing = this.controlOutbox.findIndex((e) => e.channelId === clientChannelId);\n if (existing >= 0) {\n this.controlOutbox[existing] = { channelId: clientChannelId, data };\n } else {\n this.controlOutbox.push({ channelId: clientChannelId, data });\n }\n this.scheduleControlFlush();\n return;\n }\n\n this.sendBinaryMessage(clientChannelId, data);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < FoxgloveClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.sendBinaryMessage(entry.channelId, entry.data);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n const clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n }\n\n unadvertise(topic: string): void {\n const clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'unadvertise',\n channelIds: [clientChannelId],\n });\n }\n }\n\n private sendBinaryMessage(channelId: number, data: Record<string, unknown>): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n const jsonPayload = JSON.stringify(data);\n const payloadBytes = TEXT_ENCODER.encode(jsonPayload);\n\n const buffer = new ArrayBuffer(1 + 4 + payloadBytes.byteLength);\n const view = new DataView(buffer);\n view.setUint8(0, ClientBinaryOpcode.MESSAGE_DATA);\n view.setUint32(1, channelId, true);\n new Uint8Array(buffer, 5).set(payloadBytes);\n\n // Send as a typed array, not the raw ArrayBuffer. React Native's\n // WebSocket native bridge silently drops `send(ArrayBuffer)` payloads\n // above roughly 400 bytes (verified via tcpdump on Chesster: 16-name\n // get_parameters request never left the phone). The Uint8Array path\n // goes through a different RN native serializer that handles every\n // size we send. Same bytes on the wire on browsers/Node; this is\n // load-bearing for RN. Do not revert.\n this.ws.send(new Uint8Array(buffer));\n }\n\n /**\n * Send a service-call request as a binary opcode-0x02 frame. Per\n * Foxglove WS v1 spec, SERVICE_CALL_REQUEST is binary only; the JSON op\n * `serviceCallRequest` that earlier revisions used is not in the spec\n * and is rejected by current bridges with a `status` level-2 message,\n * which leaves the in-flight callId hanging until the 30 s timeout.\n *\n * Frame layout mirrors the inbound 0x03 SERVICE_CALL_RESPONSE parser:\n * [uint8 op=0x02][uint32 serviceId LE][uint32 callId LE]\n * [uint32 encLen LE][utf8 encoding][bytes payload]\n */\n private sendBinaryServiceCallRequest(\n serviceId: number,\n callId: number,\n encoding: string,\n payload: Uint8Array,\n ): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n const encodingBytes = TEXT_ENCODER.encode(encoding);\n const buffer = new ArrayBuffer(\n 1 + 4 + 4 + 4 + encodingBytes.byteLength + payload.byteLength,\n );\n const view = new DataView(buffer);\n view.setUint8(0, ClientBinaryOpcode.SERVICE_CALL_REQUEST);\n view.setUint32(1, serviceId, true);\n view.setUint32(5, callId, true);\n view.setUint32(9, encodingBytes.byteLength, true);\n new Uint8Array(buffer, 13, encodingBytes.byteLength).set(encodingBytes);\n new Uint8Array(buffer, 13 + encodingBytes.byteLength).set(payload);\n // Typed-array send, not raw ArrayBuffer — see comment in\n // sendBinaryMessage. RN drops ArrayBuffer payloads above ~400 bytes,\n // which manifested as 16-name get_parameters requests silently\n // never leaving the phone in Tinca vcode 1071.\n this.ws.send(new Uint8Array(buffer));\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const serviceInfo = this.availableServices.get(service);\n if (!serviceInfo) {\n throw new Error(`Service \"${service}\" not available`);\n }\n\n const callId = this.nextServiceCallId++;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(callId);\n reject(new Error(`Service call \"${service}\" timed out after 30s`));\n }, 30_000);\n\n this.pendingServiceCalls.set(callId, { resolve, reject, timer });\n\n // Encode the request as CDR. JSON-encoded service requests are\n // rejected by foxglove-sdk-cpp v0.18.0+ (\"Unsupported encoding\") even\n // though the server advertises `supportedEncodings: [\"cdr\", \"json\"]`\n // — that capability applies to topic messages, not service calls.\n // CDR is the canonical encoding for ROS 2 services and is accepted\n // by every SDK version.\n //\n // Schema sourcing is layered, in this order:\n // 1. Bridge-advertised `requestSchema` (authoritative when present).\n // 2. Bundled IDL fallback (rcl_interfaces parameter ops,\n // action_msgs/CancelGoal) — used when the bridge omits the\n // schema, the normal case for foxglove_bridge 3.2.6+ services\n // discovered via ROS 2 graph introspection rather than from\n // explicit `.srv` files.\n // 3. No defs at all — empty requests fall back to the CDR\n // encapsulation header only (4 bytes) and the bridge\n // default-constructs from the known service type; non-empty\n // requests cannot be encoded without field layout and surface\n // an explicit error.\n //\n // When defs *are* available (cases 1 and 2), an empty caller request\n // is filled with zero values via `schemaToTemplate` rather than\n // rejected on missing fields. That makes `{}` a stable \"default\n // request\" sentinel across both sim and real-bridge configurations.\n let payloadBytes: Uint8Array;\n try {\n const reqDefs = this.getRequestDefs(serviceInfo);\n if (reqDefs) {\n const writer = this.getOrCompileRequestWriter(serviceInfo.id, reqDefs);\n const payload = isEmptyRequest(request) ? schemaToTemplate(reqDefs) : request;\n payloadBytes = writer.writeMessage(payload);\n } else if (isEmptyRequest(request)) {\n payloadBytes = CDR_LE_HEADER;\n } else {\n throw new Error(\n `Service \"${service}\" (type \"${serviceInfo.type}\") has no request schema advertised and is not in the built-in fallback bundle; cannot encode a non-empty CDR request. ` +\n `The bridge omits inline schemas for services discovered via introspection; empty requests still work via the encapsulation-header fallback.`,\n );\n }\n } catch (err) {\n clearTimeout(timer);\n this.pendingServiceCalls.delete(callId);\n reject(\n new Error(\n `Failed to encode request for \"${service}\": ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n return;\n }\n\n this.sendBinaryServiceCallRequest(serviceInfo.id, callId, 'cdr', payloadBytes);\n });\n }\n\n /**\n * Resolve the parsed request-side {@link MessageDefinition}[] for a\n * service, preferring the bridge-advertised schema and falling back to\n * the built-in bundle (`src/builtinSchemas.ts`) when the bridge omitted\n * one. Returns `null` if neither source has anything for this service —\n * callers then choose between the encapsulation-header fallback (for\n * empty requests) and an explicit error (for non-empty ones). Cached\n * per service id; parse + bundle lookup runs at most once per service\n * advertisement.\n */\n private getRequestDefs(svc: FoxgloveService): MessageDefinition[] | null {\n const cached = this.serviceRequestDefs.get(svc.id);\n if (cached) return cached;\n if (svc.requestSchema) {\n const defs = parseFoxgloveSchema(svc.requestSchema, svc.requestSchemaEncoding);\n this.serviceRequestDefs.set(svc.id, defs);\n return defs;\n }\n const bundled = getBundledServiceSchema(svc.type);\n if (bundled) {\n const defs = parseRosMsgDef(bundled.request, { ros2: true });\n this.serviceRequestDefs.set(svc.id, defs);\n return defs;\n }\n return null;\n }\n\n /** Response-side counterpart to {@link getRequestDefs}; same precedence. */\n private getResponseDefs(svc: FoxgloveService): MessageDefinition[] | null {\n const cached = this.serviceResponseDefs.get(svc.id);\n if (cached) return cached;\n if (svc.responseSchema) {\n const defs = parseFoxgloveSchema(svc.responseSchema, svc.responseSchemaEncoding);\n this.serviceResponseDefs.set(svc.id, defs);\n return defs;\n }\n const bundled = getBundledServiceSchema(svc.type);\n if (bundled) {\n const defs = parseRosMsgDef(bundled.response, { ros2: true });\n this.serviceResponseDefs.set(svc.id, defs);\n return defs;\n }\n return null;\n }\n\n /** Lazily compile and cache the CDR writer for a service's request type. */\n private getOrCompileRequestWriter(\n serviceId: number,\n defs: MessageDefinition[],\n ): MessageWriter {\n const cached = this.serviceRequestWriters.get(serviceId);\n if (cached) return cached;\n const writer = new MessageWriter(defs);\n this.serviceRequestWriters.set(serviceId, writer);\n return writer;\n }\n\n /** Lazily compile and cache the CDR reader for a service's response type. */\n private getOrCompileResponseReader(\n serviceId: number,\n defs: MessageDefinition[],\n ): MessageReader {\n const cached = this.serviceResponseReaders.get(serviceId);\n if (cached) return cached;\n const reader = new MessageReader(defs);\n this.serviceResponseReaders.set(serviceId, reader);\n return reader;\n }\n\n private findServiceById(serviceId: number): FoxgloveService | undefined {\n for (const svc of this.availableServices.values()) {\n if (svc.id === serviceId) return svc;\n }\n return undefined;\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return Array.from(this.availableServices.values()).map((s) => ({\n name: s.name,\n type: s.type,\n }));\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ────────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanup();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n this.connectResolve = resolve;\n this.connectReject = reject;\n\n try {\n this.ws = new WebSocket(this.url, SUBPROTOCOLS);\n this.ws.binaryType = 'arraybuffer';\n\n this.ws.onopen = () => {\n const negotiated = this.ws?.protocol ?? 'unknown';\n this.log(\n `WebSocket handshake successful (protocol: ${negotiated}), waiting for serverInfo...`,\n );\n this.clearConnectionTimeout();\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleWsMessage(event);\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ??\n 'Handshake failed or connection rejected by server';\n this.log(`WebSocket error: ${detail}`);\n this.logger.error('[FoxgloveClient] WebSocket error:', event);\n this.handleConnectionError(new Error(`WebSocket error: ${detail}`));\n };\n\n this.ws.onclose = (event: CloseEvent) => {\n this.log(`WebSocket closed: code=${event.code}, reason=${event.reason || 'none'}`);\n this.handleClose(event.code ?? 1000, event.reason ?? '');\n };\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.handleConnectionError(\n new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`),\n );\n }, CONNECTION_TIMEOUT_MS);\n } catch (err) {\n this.handleConnectionError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n }\n\n // ── Private: WebSocket message handling ──────────────────────────────────\n\n private handleWsMessage(event: MessageEvent): void {\n // Drain the control outbox BEFORE we spend the JS thread parsing this\n // incoming message. Under heavy load, control publishes that landed in\n // the outbox while the previous parse held the thread now ride out\n // before this one starts. Cheap when outbox is empty.\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n if (typeof event.data === 'string') {\n this.handleJsonMessage(event.data);\n } else if (event.data instanceof ArrayBuffer) {\n this.handleBinaryMessage(event.data);\n }\n }\n\n private handleJsonMessage(raw: string): void {\n let msg: FoxgloveServerMessage;\n try {\n msg = JSON.parse(raw) as FoxgloveServerMessage;\n } catch {\n this.logger.warn('[FoxgloveClient] Failed to parse JSON message');\n return;\n }\n\n switch (msg.op) {\n case 'serverInfo':\n this.handleServerInfo(msg as FoxgloveServerInfo);\n break;\n case 'advertise':\n this.handleAdvertise(msg as FoxgloveAdvertise);\n break;\n case 'unadvertise':\n this.handleUnadvertise(msg as FoxgloveUnadvertise);\n break;\n case 'advertiseServices':\n this.handleAdvertiseServices(msg as FoxgloveAdvertiseServices);\n break;\n case 'serviceCallResponse':\n this.handleServiceCallResponse(msg as FoxgloveServiceResponse);\n break;\n case 'serviceCallFailure':\n this.handleServiceCallFailure(msg as FoxgloveServiceFailure);\n break;\n case 'schemas':\n // sdk.v1 sends schemas metadata; not currently needed.\n break;\n case 'status': {\n const status = msg as { level?: number; message?: string };\n if (status.level === 2) {\n const text = status.message ?? '';\n this.logger.error('[FoxgloveClient] Server error:', text);\n // Status messages are undirected — they don't carry a callId.\n // When the bridge rejects a service-call request (e.g. an\n // unsupported encoding or a stale schema), this is the only\n // signal that reaches us; without fast-fail the in-flight\n // callIds hang until their 30 s timeout. Substring-match keeps\n // the rejection scoped to service-call errors.\n if (/serviceCallRequest/i.test(text) && this.pendingServiceCalls.size > 0) {\n this.rejectAllPendingServiceCalls(`Bridge rejected service call: ${text}`);\n }\n }\n break;\n }\n }\n }\n\n private handleBinaryMessage(buffer: ArrayBuffer): void {\n if (buffer.byteLength < 1) return;\n\n const view = new DataView(buffer);\n const opcode = view.getUint8(0);\n\n switch (opcode) {\n case BinaryOpcode.MESSAGE_DATA:\n this.handleBinaryMessageData(buffer, view);\n return;\n case BinaryOpcode.SERVICE_CALL_RESPONSE:\n this.handleBinaryServiceCallResponse(buffer, view);\n return;\n default:\n // Spec-listed but currently unused (0x02 TIME, 0x04\n // FETCH_ASSET_RESPONSE) and any future opcode — drop silently\n // rather than logging on the hot path.\n return;\n }\n }\n\n private handleBinaryMessageData(buffer: ArrayBuffer, view: DataView): void {\n // messageData binary format (server → client):\n // [uint8 op=0x01] [uint32LE subscriptionId] [uint64LE timestamp] [payload]\n if (buffer.byteLength < 13) return;\n const subscriptionId = view.getUint32(1, true);\n\n const timestampLow = view.getUint32(5, true);\n const timestampHigh = view.getUint32(9, true);\n const timestampNs = timestampHigh * 0x100000000 + timestampLow;\n const sec = Math.floor(timestampNs / 1_000_000_000);\n const nsec = timestampNs % 1_000_000_000;\n\n const payloadOffset = 13;\n // Zero-copy view, NOT `buffer.slice(payloadOffset)`. `ArrayBuffer.slice`\n // allocates a fresh ArrayBuffer and copies the payload bytes on every\n // inbound frame, including frames dropped a few lines below by the\n // throttle short-circuit. On raw image topics (10 MB/frame at 30 Hz)\n // that's ~300 MB/s of allocation + GC churn even when 100 % of frames\n // are dropped. `TextDecoder.decode`, `MessageReader.readMessage`, and\n // the four `data = ...` assignments below all accept `Uint8Array`\n // transparently; the regression test in FoxgloveClient.test.ts asserts\n // `data.buffer === frameBuffer` to pin the zero-copy invariant.\n const payload = new Uint8Array(buffer, payloadOffset);\n\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n const mode = this.getThrottleMode();\n recordBytes(sub.bandwidth, now, buffer.byteLength, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second pass.\n const deliverTo: Array<[(msg: RosMessage) => void, CallbackEntry]> = [];\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n // `latest-only` callbacks conflate before parse: stash a materialized copy\n // of the newest eligible payload and defer the decode to a `setTimeout(0)`\n // drain. The `payload` view aliases the WS frame buffer (v0.1.2 zero-copy\n // ingest), so it must be copied to survive the tick boundary. `immediate`\n // callbacks keep the synchronous parse-and-deliver path, and the parse runs\n // at most once — shared across every immediate subscriber, skipped entirely\n // when all eligible callbacks are `latest-only`.\n let parsed: RosMessage | null = null;\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n\n if (entry.dispatchMode === 'latest-only') {\n entry.pending = { payload: new Uint8Array(payload), sec, nsec };\n if (entry.drainTimer === null) {\n entry.drainTimer = setTimeout(\n () => this.drainLatestOnly(subscriptionId, cb, entry),\n 0,\n );\n }\n continue;\n }\n\n if (parsed === null) {\n const channelInfo = this.channels.get(sub.channelId);\n const encoding = channelInfo?.encoding ?? 'json';\n parsed = {\n topic: sub.topic,\n schemaName: channelInfo?.schemaName ?? '',\n encoding: encoding === 'json' ? 'json' : 'cdr',\n data: this.decodePayload(payload, subscriptionId, encoding),\n receiveTime: { sec, nsec },\n byteSize: payload.byteLength,\n };\n }\n try {\n cb(parsed);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Subscriber callback error:', err);\n }\n }\n }\n\n /**\n * Decode a `messageData` payload to its delivered shape: a parsed object when\n * a CDR reader or JSON decode succeeds, the raw bytes otherwise. Shared by\n * the synchronous `immediate` path and the deferred `latest-only` drain.\n */\n private decodePayload(\n payload: Uint8Array,\n subscriptionId: number,\n encoding: string,\n ): Record<string, unknown> | Uint8Array {\n if (encoding === 'json') {\n try {\n return JSON.parse(TEXT_DECODER.decode(payload)) as Record<string, unknown>;\n } catch {\n return payload;\n }\n }\n const reader = this.messageReaders.get(subscriptionId);\n if (reader) {\n try {\n return reader.readMessage(payload) as Record<string, unknown>;\n } catch {\n return payload;\n }\n }\n return payload;\n }\n\n /**\n * Drain one `latest-only` callback's pending payload: parse the survivor and\n * deliver it. Cleared state (`pending`, `drainTimer`) is reset *before* the\n * callback runs, so a throwing callback never wedges future delivery — the\n * next arrival re-arms normally. Bails if the subscription was torn down or\n * paused while the drain was armed (no post-teardown delivery).\n */\n private drainLatestOnly(\n subscriptionId: number,\n cb: (msg: RosMessage) => void,\n entry: CallbackEntry,\n ): void {\n entry.drainTimer = null;\n const pending = entry.pending;\n entry.pending = null;\n if (!pending) return;\n\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub || sub.isPaused) return;\n\n const channelInfo = this.channels.get(sub.channelId);\n const encoding = channelInfo?.encoding ?? 'json';\n const rosMsg: RosMessage = {\n topic: sub.topic,\n schemaName: channelInfo?.schemaName ?? '',\n encoding: encoding === 'json' ? 'json' : 'cdr',\n data: this.decodePayload(pending.payload, subscriptionId, encoding),\n receiveTime: { sec: pending.sec, nsec: pending.nsec },\n byteSize: pending.payload.byteLength,\n };\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Subscriber callback error:', err);\n }\n }\n\n /** Cancel one callback's armed drain and drop its pending payload. */\n private cancelDrain(entry: CallbackEntry): void {\n if (entry.drainTimer !== null) {\n clearTimeout(entry.drainTimer);\n entry.drainTimer = null;\n }\n entry.pending = null;\n }\n\n /** Cancel every armed drain on a subscription (teardown / pause). */\n private cancelAllDrains(sub: { callbacks: Map<(msg: RosMessage) => void, CallbackEntry> }): void {\n for (const entry of sub.callbacks.values()) this.cancelDrain(entry);\n }\n\n private handleServerInfo(info: FoxgloveServerInfo): void {\n this.log(`Received serverInfo: ${info.name} (sessionId: ${info.sessionId ?? 'none'})`);\n this.serverInfoReceived = true;\n }\n\n private handleAdvertise(msg: FoxgloveAdvertise): void {\n for (const ch of msg.channels) {\n this.channels.set(ch.id, ch);\n this.topicToChannelId.set(ch.topic, ch.id);\n this.log(\n ` Channel: ${ch.topic} [${ch.schemaName}] encoding=${ch.encoding} schemaEncoding=${ch.schemaEncoding ?? 'none'}`,\n );\n }\n\n if (this.connectResolve && this.serverInfoReceived) {\n this.log(`Connection established with ${msg.channels.length} initial topics.`);\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.setStatus('connected');\n\n this.connectResolve();\n this.connectResolve = null;\n this.connectReject = null;\n } else {\n this.notifyTopicsChanged();\n }\n }\n\n private handleUnadvertise(msg: FoxgloveUnadvertise): void {\n for (const id of msg.channelIds) {\n const ch = this.channels.get(id);\n if (ch) {\n this.topicToChannelId.delete(ch.topic);\n }\n this.channels.delete(id);\n }\n this.notifyTopicsChanged();\n }\n\n private handleAdvertiseServices(msg: FoxgloveAdvertiseServices): void {\n for (const svc of msg.services) {\n this.availableServices.set(svc.name, svc);\n }\n this.notifyServicesChanged();\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Services listener error:', err);\n }\n }\n }\n\n /**\n * Service-call responses arrive on two distinct wire paths and both\n * funnel into {@link dispatchServiceCallResponse}:\n *\n * 1. JSON op `serviceCallResponse` (handled here) — older bridges\n * and any deployment with binary responses disabled. `data` is\n * base64, decoded once into a Uint8Array before dispatch.\n * 2. Binary opcode 0x03 (handled in\n * {@link handleBinaryServiceCallResponse}) — the default for\n * foxglove-sdk-cpp ≥ 0.18.0 / foxglove_bridge 3.2.6+. Payload\n * bytes are passed through directly with no base64 round-trip.\n *\n * Before this split, only the JSON path existed and the binary\n * frames were dropped by {@link handleBinaryMessage} — pending callIds\n * never resolved and surfaced as 30 s timeouts on every callService.\n */\n private handleServiceCallResponse(msg: FoxgloveServiceResponse): void {\n const payload = msg.data ? base64ToUint8(msg.data) : new Uint8Array();\n this.dispatchServiceCallResponse(msg.callId, msg.serviceId, msg.encoding ?? '', payload);\n }\n\n /**\n * Inner decode + dispatch shared by the JSON-op and binary-frame\n * paths. Owns the lookup of the pending call, the timer cleanup, and\n * the CDR / JSON branch — splitting it out keeps the two surface\n * paths thin and prevents drift between them.\n */\n private dispatchServiceCallResponse(\n callId: number,\n serviceId: number,\n encoding: string,\n payload: Uint8Array,\n ): void {\n const pending = this.pendingServiceCalls.get(callId);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(callId);\n\n try {\n if (encoding === 'cdr' && payload.byteLength > 0) {\n const svc = this.findServiceById(serviceId);\n const respDefs = svc ? this.getResponseDefs(svc) : null;\n if (!svc || !respDefs) {\n // Neither the bridge nor the bundle has a response schema for\n // this service. Surface the raw bytes so the consumer can still\n // inspect them rather than swallowing the payload entirely.\n pending.resolve({ rawBytes: payload } as Record<string, unknown>);\n return;\n }\n const reader = this.getOrCompileResponseReader(svc.id, respDefs);\n const decoded = reader.readMessage(payload);\n pending.resolve(decoded as Record<string, unknown>);\n } else if (encoding === 'json' && payload.byteLength > 0) {\n // Back-compat path for older bridges that responded in JSON.\n // TextDecoder is the correct decoder here — `atob` would only\n // round-trip ASCII payloads, but Foxglove can send UTF-8.\n const text = TEXT_DECODER.decode(payload);\n const parsed = JSON.parse(text) as Record<string, unknown>;\n pending.resolve(parsed);\n } else {\n pending.resolve({ success: true });\n }\n } catch (err) {\n pending.reject(\n new Error(\n `Failed to parse service response: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n }\n\n /**\n * Parse a binary opcode-0x03 SERVICE_CALL_RESPONSE frame and dispatch\n * to {@link dispatchServiceCallResponse}. Frame layout (LE throughout):\n *\n * [uint8 op=0x03][uint32 serviceId][uint32 callId]\n * [uint32 encodingLength][utf8 encoding][bytes payload]\n *\n * Malformed frames (too short for the header, or an `encodingLength`\n * that runs past the buffer) are dropped silently — the bridge will\n * either resend or fail the call via the JSON `serviceCallFailure`\n * op, and either way logging on the hot binary path would be noisy.\n */\n private handleBinaryServiceCallResponse(buffer: ArrayBuffer, view: DataView): void {\n if (buffer.byteLength < 13) return; // 1 + 4 + 4 + 4\n const serviceId = view.getUint32(1, true);\n const callId = view.getUint32(5, true);\n const encodingLength = view.getUint32(9, true);\n const payloadOffset = 13 + encodingLength;\n if (buffer.byteLength < payloadOffset) return;\n const encoding = TEXT_DECODER.decode(new Uint8Array(buffer, 13, encodingLength));\n const payload = new Uint8Array(buffer, payloadOffset);\n this.dispatchServiceCallResponse(callId, serviceId, encoding, payload);\n }\n\n /**\n * Handle a `serviceCallFailure` op (callId-targeted rejection from the\n * bridge). Without this, failures sat unhandled and the in-flight promise\n * timed out at 30 s — turning every misencoded request, unknown service,\n * or schema mismatch into a long, opaque hang.\n */\n private handleServiceCallFailure(msg: FoxgloveServiceFailure): void {\n const pending = this.pendingServiceCalls.get(msg.callId);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(msg.callId);\n pending.reject(new Error(msg.message ?? 'Service call failed (no message from bridge)'));\n }\n\n /**\n * Reject every in-flight service call with `reason`, clear their timers,\n * and empty the pending map. Used by {@link cleanup} on disconnect and\n * by the status-level-2 fast-fail path where the bridge has signalled a\n * service-call rejection without naming a callId.\n */\n private rejectAllPendingServiceCalls(reason: string): void {\n for (const pending of this.pendingServiceCalls.values()) {\n clearTimeout(pending.timer);\n pending.reject(new Error(reason));\n }\n this.pendingServiceCalls.clear();\n }\n\n // ── Private: reconnection ────────────────────────────────────────────────\n\n private handleConnectionError(error: Error): void {\n this.clearConnectionTimeout();\n\n if (this.connectReject) {\n this.connectReject(error);\n this.connectResolve = null;\n this.connectReject = null;\n }\n\n this.setStatus('error');\n this.cleanup();\n this.scheduleReconnect();\n }\n\n private handleClose(_code: number, _reason: string): void {\n const wasConnected = this.status === 'connected';\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanup();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.logger.warn(\n `[FoxgloveClient] Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached`,\n );\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[FoxgloveClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: unsubscribe ─────────────────────────────────────────────────\n\n private unsubscribeTopic(topic: string, subscriptionId: number): void {\n const sub = this.subscriptions.get(subscriptionId);\n if (sub) this.cancelAllDrains(sub);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns. Tearing them down here\n // would nuke listeners belonging to other consumers watching the same\n // topic.\n\n this.subscriptions.delete(subscriptionId);\n this.topicToSubscriptionId.delete(topic);\n this.messageReaders.delete(subscriptionId);\n\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.sendJson({\n op: 'unsubscribe',\n subscriptionIds: [subscriptionId],\n });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return 'closed';\n const sub = this.subscriptions.get(subId);\n return sub?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n return this.subscriptions.get(subId)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n const sub = this.subscriptions.get(subId);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ───────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: cleanup ─────────────────────────────────────────────────────\n\n private cleanup(): void {\n this.clearConnectionTimeout();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.rejectAllPendingServiceCalls('Connection closed');\n\n if (this.ws) {\n if (this.ws.readyState === WebSocket.OPEN && this.advertisedTopics.size > 0) {\n const channelIds = Array.from(this.advertisedTopics.values());\n try {\n this.sendJson({ op: 'unadvertise', channelIds });\n } catch {\n // best effort\n }\n }\n\n this.ws.onopen = null;\n this.ws.onmessage = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n if (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n ) {\n this.ws.close();\n }\n this.ws = null;\n }\n\n for (const sub of this.subscriptions.values()) this.cancelAllDrains(sub);\n\n this.channels.clear();\n this.topicToChannelId.clear();\n this.subscriptions.clear();\n this.topicToSubscriptionId.clear();\n this.messageReaders.clear();\n this.advertisedTopics.clear();\n this.availableServices.clear();\n this.serviceRequestDefs.clear();\n this.serviceResponseDefs.clear();\n this.serviceRequestWriters.clear();\n this.serviceResponseReaders.clear();\n this.notifyServicesChanged();\n this.serverInfoReceived = false;\n this.nextSubscriptionId = 1;\n this.nextClientChannelId = 1;\n this.nextServiceCallId = 1;\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ─────────────────────────────────────────────────────\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Status listener error:', err);\n }\n }\n }\n\n private sendJson(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private notifyTopicsChanged(): void {\n const appTopics = new Set(this.advertisedTopics.keys());\n const topics: TopicInfo[] = Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n for (const cb of this.topicsListeners) {\n try {\n cb(topics);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[FoxgloveClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * RosbridgeClient — rosbridge v2 protocol implementation.\n *\n * Implements the rosbridge v2 JSON protocol directly over the runtime's\n * `WebSocket`. No `roslib` dependency: that library pulls in Node-only\n * modules (`bson`, `ws`) that break in React Native and that we don't need\n * because the protocol is a small JSON envelope.\n *\n * Protocol spec: https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/ROSBRIDGE_PROTOCOL.md\n * Default port: 9090.\n *\n * Features:\n *\n * - Topic discovery via the `/rosapi/topics` service.\n * - Subscribe with `throttle_rate` and `queue_length=1` (drop old, keep\n * latest) for sane defaults on high-rate topics.\n * - Publish with auto-advertise on first send.\n * - Service calls with a 30 s timeout.\n * - Dead-man's switch: zero Twist on unexpected disconnect.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - `tryDropPublishBeforeParse` fast-path: bounded substring scan extracts\n * `op` and `topic` from a `publish` envelope so we can drop messages no\n * callback wants without paying `JSON.parse` cost on the full payload.\n * Matters for high-bandwidth topics where parse dominates per-message\n * work.\n */\n\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level decoder singleton — see the FoxgloveClient comment for the\n// rationale; same reasoning for the rosbridge binary-frame path.\nconst TEXT_DECODER = new TextDecoder();\n\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\nconst DEFAULT_THROTTLE_RATE_MS = 100;\nconst SERVICE_CALL_TIMEOUT_MS = 30_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\n// Per-callback subscription state. `dispatchMode` and the deferred-drain\n// fields below it are only exercised by `latest-only` subscribers. rosbridge\n// frames are JSON text, so a `latest-only` callback stashes the raw,\n// unparsed string (immutable, so the stash is copy-free) and parses only the\n// survivor on drain.\ninterface RosbridgeCallbackEntry {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n dispatchMode: 'immediate' | 'latest-only';\n pending: { raw: string; receivedAt: number } | null;\n drainTimer: ReturnType<typeof setTimeout> | null;\n}\n\nexport class RosbridgeClient implements IProtocolClient {\n private readonly onLatency: ((rttMs: number) => void) | undefined;\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n private availableServices: ServiceInfo[] = [];\n private servicesPollTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(options?: ProtocolClientOptions) {\n this.onLatency = options?.onLatency;\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n private activeSubscriptions = new Map<\n string,\n {\n schemaName: string;\n callbacks: Map<(msg: RosMessage) => void, RosbridgeCallbackEntry>;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n private advertisedTopics = new Set<string>();\n private hasPublishedTwist = false;\n\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<{ op: 'publish'; topic: string; msg: Record<string, unknown> }> = [];\n private controlFlushScheduled = false;\n\n private discoveredTopics: TopicInfo[] = [];\n\n private pendingServiceCalls = new Map<\n string,\n {\n resolve: (result: Record<string, unknown>) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private serviceCallCounter = 0;\n\n private latencyProbeTimer: ReturnType<typeof setInterval> | null = null;\n\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Connecting to rosbridge at ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n if (!this.ws || !this.isConnected) {\n return this.discoveredTopics;\n }\n\n try {\n const result = await this.callService('/rosapi/topics', {});\n const names: string[] = (result.topics as string[]) ?? [];\n const types: string[] = (result.types as string[]) ?? [];\n\n const topics: TopicInfo[] = [];\n for (let i = 0; i < names.length; i++) {\n const name = names[i];\n if (!name) continue;\n topics.push({\n topic: name,\n schemaName: types[i] ?? '',\n encoding: 'json',\n source: this.advertisedTopics.has(name) ? 'app' : 'robot',\n });\n }\n\n this.discoveredTopics = topics;\n this.log(`Discovered ${topics.length} topics.`);\n this.notifyTopicsChanged();\n return topics;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Failed to get topics via rosapi: ${msg}`);\n return this.discoveredTopics;\n }\n }\n\n getSchemaTemplate(_schemaName: string): Record<string, unknown> | null {\n // rosbridge's /rosapi/message_details is async and not surfaced through\n // the current IProtocolClient contract. Consumers that need a template\n // for a rosbridge connection should compose one client-side. Foxglove WS\n // does the heavy lifting via inline schemas.\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n if (!this.ws || this.status !== 'connected') {\n return () => {};\n }\n\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n const dispatchMode = options?.dispatchMode ?? 'immediate';\n\n const existing = this.activeSubscriptions.get(topic);\n if (existing) {\n existing.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n dispatchMode,\n pending: null,\n drainTimer: null,\n });\n return () => {\n const entry = existing.callbacks.get(onMessage);\n if (entry) this.cancelDrain(entry);\n existing.callbacks.delete(onMessage);\n if (existing.callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n const topicInfo = this.discoveredTopics.find((t) => t.topic === topic);\n const messageType = topicInfo?.schemaName ?? '';\n\n if (!messageType) {\n this.log(`Warning: subscribing to \"${topic}\" without known message type`);\n }\n\n const callbacks = new Map<(msg: RosMessage) => void, RosbridgeCallbackEntry>();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n dispatchMode,\n pending: null,\n drainTimer: null,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n // A breaker trip discards any pending latest-only payload: stale bytes,\n // and we must not deliver after pausing the subscription.\n if (sub.isPaused) this.cancelAllDrains(sub);\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.send({ op: 'unsubscribe', topic });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'subscribe',\n topic,\n type: sub.schemaName,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.activeSubscriptions.set(topic, {\n schemaName: messageType,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n\n this.send({\n op: 'subscribe',\n topic,\n type: messageType,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n\n return () => {\n const entry = callbacks.get(onMessage);\n if (entry) this.cancelDrain(entry);\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n if (!this.advertisedTopics.has(topic)) {\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n const payload = { op: 'publish' as const, topic, msg: data };\n\n if (options?.priority === 'control') {\n // Conflate-on-replace by topic. Mirrors the FoxgloveClient outbox: if a\n // control-priority publish for this topic is already pending, replace\n // rather than append. Under JS-thread saturation a stop publish (zero\n // Twist released by a joystick gesture-end, action cancel, etc.) drains\n // in one WS send instead of behind every stale tick that piled up\n // during the block. The latest publish IS the latest intent. Insertion\n // order across distinct topics is preserved (replace in place); only\n // intra-topic duplicates collapse.\n const existing = this.controlOutbox.findIndex((e) => e.topic === topic);\n if (existing >= 0) {\n this.controlOutbox[existing] = payload;\n } else {\n this.controlOutbox.push(payload);\n }\n this.scheduleControlFlush();\n return;\n }\n\n this.send(payload);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < RosbridgeClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.send(entry);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n unadvertise(topic: string): void {\n if (!this.advertisedTopics.has(topic)) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'unadvertise',\n topic,\n });\n }\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const id = `service_call:${service}:${++this.serviceCallCounter}`;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n reject(\n new Error(`Service call \"${service}\" timed out after ${SERVICE_CALL_TIMEOUT_MS}ms`),\n );\n }, SERVICE_CALL_TIMEOUT_MS);\n\n this.pendingServiceCalls.set(id, { resolve, reject, timer });\n\n this.send({\n op: 'call_service',\n id,\n service,\n args: request,\n });\n });\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return [...this.availableServices];\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n private async discoverServices(): Promise<void> {\n if (!this.isConnected) return;\n try {\n const result = await this.callService('/rosapi/services', {});\n const names: string[] = (result.services as string[]) ?? [];\n const next: ServiceInfo[] = names.map((n) => ({ name: n, type: '' }));\n const prevKey = this.availableServices\n .map((s) => s.name)\n .sort()\n .join('|');\n const nextKey = next.map((s) => s.name).sort().join('|');\n if (prevKey === nextKey) return;\n this.availableServices = next;\n this.notifyServicesChanged();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Service discovery via /rosapi/services failed: ${msg}`);\n this.stopServicesPoll();\n }\n }\n\n private startServicesPoll(): void {\n if (this.servicesPollTimer) return;\n void this.discoverServices();\n this.servicesPollTimer = setInterval(() => {\n void this.discoverServices();\n }, 30_000);\n }\n\n private stopServicesPoll(): void {\n if (this.servicesPollTimer) {\n clearInterval(this.servicesPollTimer);\n this.servicesPollTimer = null;\n }\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Services listener error:', err);\n }\n }\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ──────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanupConnection();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.log(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`);\n reject(new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }, CONNECTION_TIMEOUT_MS);\n\n this.ws.onopen = () => {\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.log('Connected to rosbridge server.');\n this.setStatus('connected');\n this.startLatencyProbe();\n this.startServicesPoll();\n resolve();\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ?? 'Connection error';\n this.log(`Rosbridge error: ${detail}`);\n this.logger.error('[RosbridgeClient] Error:', event);\n\n if (this.status === 'connecting') {\n this.clearConnectionTimeout();\n reject(new Error(`Rosbridge error: ${detail}`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }\n };\n\n this.ws.onclose = () => {\n const wasConnected = this.status === 'connected';\n this.log('Rosbridge connection closed.');\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanupConnection();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleMessage(event.data as string | ArrayBuffer);\n };\n } catch (err) {\n this.clearConnectionTimeout();\n const error = err instanceof Error ? err : new Error(String(err));\n reject(error);\n this.cleanup();\n this.setStatus('error');\n }\n });\n }\n\n // ── Private: message handling ──────────────────────────────────────────\n\n private handleMessage(raw: string | ArrayBuffer): void {\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n try {\n const data = typeof raw === 'string' ? raw : TEXT_DECODER.decode(raw);\n const byteSize = typeof raw === 'string' ? data.length : raw.byteLength;\n // Compute mode once per incoming message and forward to the inner\n // handlers so we don't call the host's `getThrottleMode` twice on the\n // fast-path → dispatch flow.\n const mode = this.getThrottleMode();\n\n if (this.tryDropPublishBeforeParse(data, byteSize, mode)) {\n return;\n }\n\n const msg = JSON.parse(data) as Record<string, unknown>;\n const op = msg.op as string;\n\n switch (op) {\n case 'publish':\n this.handlePublish(msg, byteSize, mode);\n break;\n case 'service_response':\n this.handleServiceResponse(msg);\n break;\n case 'status': {\n const level = msg.level as string | undefined;\n const statusMsg = msg.msg as string | undefined;\n if (level === 'error' || level === 'warning') {\n this.log(`rosbridge ${level}: ${statusMsg ?? 'unknown'}`);\n }\n break;\n }\n }\n } catch (err) {\n this.logger.error('[RosbridgeClient] Failed to parse message:', err);\n }\n }\n\n /**\n * Drop a publish message before paying full `JSON.parse` cost.\n *\n * Rosbridge frames look like `{\"op\":\"publish\",\"topic\":\"…\",\"msg\":{…}}`.\n * For fat payloads (base64-encoded camera frames, large arrays)\n * `JSON.parse` on the whole envelope dominates per-message cost. We do a\n * cheap substring search to extract `op` and `topic`, run the same\n * throttle/breaker accounting `handlePublish` would do, and return `true`\n * to skip the parse when no callback wants the message right now.\n *\n * Handles both compact (`{\"op\":\"publish\"`) and pretty (`{\"op\": \"publish\"`)\n * JSON forms.\n */\n private tryDropPublishBeforeParse(data: string, byteSize: number, mode: ThrottleMode): boolean {\n if (\n !data.startsWith('{\"op\":\"publish\"') &&\n !data.startsWith('{\"op\": \"publish\"')\n ) {\n return false;\n }\n\n const topicKeyIdx = data.indexOf('\"topic\"');\n if (topicKeyIdx < 0 || topicKeyIdx > 200) return false;\n\n let i = topicKeyIdx + 7;\n if (data[i] !== ':') return false;\n i++;\n if (data[i] === ' ') i++;\n if (data[i] !== '\"') return false;\n i++;\n const topicEnd = data.indexOf('\"', i);\n if (topicEnd < 0) return false;\n const topic = data.slice(i, topicEnd);\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return true; // not subscribed → drop\n\n const now = Date.now();\n\n if (sub.isPaused) {\n recordBytes(sub.bandwidth, now, byteSize, mode);\n return true;\n }\n\n // Walk eligible callbacks. A `latest-only` subscriber conflates before\n // parse: stash the raw (unparsed) frame string — immutable, so copy-free —\n // and defer the JSON.parse to a `setTimeout(0)` drain that parses only the\n // survivor. `immediate` subscribers fall through to the normal parse +\n // `handlePublish` path.\n let anyImmediateWantsThis = false;\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n const eligible = interval <= 0 || now - entry.lastDeliveredAt >= interval;\n if (!eligible) continue;\n\n if (entry.dispatchMode === 'latest-only') {\n entry.lastDeliveredAt = now;\n entry.pending = { raw: data, receivedAt: now };\n if (entry.drainTimer === null) {\n entry.drainTimer = setTimeout(() => this.drainLatestOnly(topic, cb, entry), 0);\n }\n } else {\n anyImmediateWantsThis = true;\n }\n }\n\n // An immediate subscriber needs the parsed message: let the frame through\n // to JSON.parse + handlePublish, which does the bytes/breaker accounting.\n if (anyImmediateWantsThis) return false;\n\n // Nothing immediate wanted it (all eligible callbacks were latest-only, or\n // none were eligible). Account here and skip the parse.\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n return true;\n }\n\n private handlePublish(msg: Record<string, unknown>, byteSize: number, mode: ThrottleMode): void {\n const topic = msg.topic as string;\n const msgData = (msg.msg ?? {}) as Record<string, unknown>;\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second loop.\n // `latest-only` callbacks are skipped here — they were stashed and armed\n // for deferred delivery in `tryDropPublishBeforeParse`, upstream of parse.\n const deliverTo: Array<[(msg: RosMessage) => void, RosbridgeCallbackEntry]> = [];\n for (const [cb, entry] of sub.callbacks) {\n if (entry.dispatchMode === 'latest-only') continue;\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n const rosMsg: RosMessage = {\n topic,\n schemaName: sub.schemaName,\n encoding: 'json',\n data: msgData,\n receiveTime: {\n sec: Math.floor(now / 1000),\n nsec: (now % 1000) * 1_000_000,\n },\n byteSize,\n };\n\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Subscriber callback error:', err);\n }\n }\n }\n\n /**\n * Drain one `latest-only` callback's pending frame: parse the survivor and\n * deliver it. State (`pending`, `drainTimer`) is cleared *before* the\n * callback runs, so a throwing callback never wedges future delivery. Bails\n * if the subscription was torn down or paused while the drain was armed (no\n * post-teardown delivery).\n */\n private drainLatestOnly(\n topic: string,\n cb: (msg: RosMessage) => void,\n entry: RosbridgeCallbackEntry,\n ): void {\n entry.drainTimer = null;\n const pending = entry.pending;\n entry.pending = null;\n if (!pending) return;\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub || sub.isPaused) return;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(pending.raw) as Record<string, unknown>;\n } catch {\n return; // malformed frame; nothing to deliver\n }\n\n const rosMsg: RosMessage = {\n topic,\n schemaName: sub.schemaName,\n encoding: 'json',\n data: (parsed.msg ?? {}) as Record<string, unknown>,\n receiveTime: {\n sec: Math.floor(pending.receivedAt / 1000),\n nsec: (pending.receivedAt % 1000) * 1_000_000,\n },\n byteSize: pending.raw.length,\n };\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Subscriber callback error:', err);\n }\n }\n\n /** Cancel one callback's armed drain and drop its pending frame. */\n private cancelDrain(entry: RosbridgeCallbackEntry): void {\n if (entry.drainTimer !== null) {\n clearTimeout(entry.drainTimer);\n entry.drainTimer = null;\n }\n entry.pending = null;\n }\n\n /** Cancel every armed drain on a subscription (teardown / pause). */\n private cancelAllDrains(sub: {\n callbacks: Map<(msg: RosMessage) => void, RosbridgeCallbackEntry>;\n }): void {\n for (const entry of sub.callbacks.values()) this.cancelDrain(entry);\n }\n\n private handleServiceResponse(msg: Record<string, unknown>): void {\n const id = msg.id as string;\n const pending = this.pendingServiceCalls.get(id);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(id);\n\n const success = msg.result === true || msg.result === 'true';\n if (success) {\n const values = (msg.values ?? {}) as Record<string, unknown>;\n pending.resolve(values);\n } else {\n const errorMsg =\n typeof msg.values === 'string' ? msg.values : 'Service call failed';\n pending.reject(new Error(errorMsg));\n }\n }\n\n // ── Private: topic management ──────────────────────────────────────────\n\n private unsubscribeTopic(topic: string): void {\n const sub = this.activeSubscriptions.get(topic);\n if (sub) this.cancelAllDrains(sub);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns.\n\n this.activeSubscriptions.delete(topic);\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.send({ op: 'unsubscribe', topic });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n return this.activeSubscriptions.get(topic)?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n return this.activeSubscriptions.get(topic)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ─────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: latency probe ──────────────────────────────────────────────\n\n private startLatencyProbe(): void {\n this.stopLatencyProbe();\n this.latencyProbeTimer = setInterval(() => {\n if (!this.ws || this.status !== 'connected') return;\n const start = Date.now();\n const id = `latency_probe:${++this.serviceCallCounter}`;\n\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n }, 5_000);\n\n this.pendingServiceCalls.set(id, {\n resolve: () => {\n clearTimeout(timer);\n if (this.onLatency) {\n try {\n this.onLatency(Date.now() - start);\n } catch {\n // metrics must never affect protocol operation\n }\n }\n },\n reject: () => {\n clearTimeout(timer);\n },\n timer,\n });\n\n this.send({\n op: 'call_service',\n id,\n service: '/rosapi/topics',\n args: {},\n });\n }, 5_000);\n }\n\n private stopLatencyProbe(): void {\n if (this.latencyProbeTimer) {\n clearInterval(this.latencyProbeTimer);\n this.latencyProbeTimer = null;\n }\n }\n\n // ── Private: reconnection ──────────────────────────────────────────────\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.log(`Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached.`);\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[RosbridgeClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: cleanup ───────────────────────────────────────────────────\n\n private cleanupConnection(): void {\n this.clearConnectionTimeout();\n this.stopServicesPoll();\n for (const sub of this.activeSubscriptions.values()) this.cancelAllDrains(sub);\n this.activeSubscriptions.clear();\n\n for (const [, pending] of this.pendingServiceCalls) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Connection closed'));\n }\n this.pendingServiceCalls.clear();\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n for (const topic of this.advertisedTopics) {\n try {\n this.send({ op: 'unadvertise', topic });\n } catch {\n // best effort\n }\n }\n }\n\n this.advertisedTopics.clear();\n }\n\n private cleanup(): void {\n this.cleanupConnection();\n this.stopLatencyProbe();\n this.stopServicesPoll();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n // ignore\n }\n this.ws = null;\n }\n\n this.discoveredTopics = [];\n if (this.availableServices.length > 0) {\n this.availableServices = [];\n this.notifyServicesChanged();\n }\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ───────────────────────────────────────────────────\n\n private send(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Status listener error:', err);\n }\n }\n }\n\n private notifyTopicsChanged(): void {\n for (const cb of this.topicsListeners) {\n try {\n cb(this.discoveredTopics);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[RosbridgeClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\nimport type { ProtocolType } from './types';\n\n/**\n * Default TCP port for each supported protocol. Useful for consumers\n * building connection-configuration UIs that want a sensible starting\n * value when the user changes protocol.\n */\nexport const DEFAULT_PORTS: Record<ProtocolType, number> = {\n 'foxglove-ws': 8765,\n rosbridge: 9090,\n zenoh: 7447,\n};\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * ProtocolManager — factory plus active-connection lifecycle manager.\n *\n * Builds the appropriate `IProtocolClient` for `options.protocol`, sanitizes\n * the user-entered host, validates the URL with `new URL()`, and forwards\n * the connection. Holds the active client so callers don't have to.\n *\n * `setClientOptions` is the injection point for the host's `onLatency`\n * callback, `logger`, and `getThrottleMode` selector. Options are stored\n * and forwarded into every client the manager constructs.\n */\n\nimport { FoxgloveClient } from './FoxgloveClient';\nimport { RosbridgeClient } from './RosbridgeClient';\nimport type {\n ConnectionOptions,\n IProtocolClient,\n ProtocolClientOptions,\n} from './types';\nimport { DEFAULT_PORTS } from './constants';\n\n/**\n * Normalize a user-entered host string into something safe to drop into\n * `${scheme}://${host}:${port}`. Strips `ws://`, `wss://`, `http://`,\n * `https://` prefixes (paste from a browser address bar or a Foxglove URL),\n * drops a trailing `:port` (so a `host:8766` paste doesn't poison the URL\n * with two ports — the dedicated `port` field always wins), and trims\n * trailing path / query / fragment plus whitespace.\n */\nfunction sanitizeHost(raw: string): string {\n let host = (raw ?? '').trim();\n host = host.replace(/^(wss?|https?):\\/\\//i, '');\n // Drop trailing path/query/fragment.\n host = host.split('/')[0] ?? host;\n host = host.split('?')[0] ?? host;\n host = host.split('#')[0] ?? host;\n // Strip trailing :port. IPv6 literals are bracketed (`[::1]:8765`), so\n // only strip when the colon isn't inside brackets.\n if (!host.startsWith('[')) {\n const colonIx = host.indexOf(':');\n if (colonIx !== -1) host = host.slice(0, colonIx);\n }\n return host;\n}\n\nexport class ProtocolManager {\n private activeClient: IProtocolClient | null = null;\n private activeOptions: ConnectionOptions | null = null;\n private clientOptions: ProtocolClientOptions | undefined;\n\n /**\n * Set options forwarded to every client constructed by this manager.\n * Host applications typically call this once at startup.\n */\n setClientOptions(options: ProtocolClientOptions): void {\n this.clientOptions = options;\n }\n\n /**\n * Create and connect a protocol client for the given options.\n *\n * For `protocol: 'zenoh'`, throws a clear \"planned for v0.2.0\" error —\n * the v0.1.0 release does not ship a Zenoh implementation.\n */\n async connect(options: ConnectionOptions): Promise<IProtocolClient> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n }\n\n const client = this.createClient(options);\n const scheme = options.secure ? 'wss' : 'ws';\n const port = options.port || DEFAULT_PORTS[options.protocol];\n const host = sanitizeHost(options.host);\n const url = `${scheme}://${host}:${port}`;\n\n // Validate before handing to the runtime's WebSocket implementation.\n // Some platforms (React Native on Android via okhttp3) throw on the\n // native message-queue thread for malformed ports/hosts — there's no\n // JS-side handler for that, so the process dies. Catching here keeps\n // the failure inside the connection flow where the host can surface\n // it as a regular connection error.\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n } catch {\n throw new Error(\n `Invalid connection URL \"${url}\" — check host and port. Hosts should not include \"ws://\" or \":port\"; use the port field instead.`,\n );\n }\n\n await client.connect(url);\n\n this.activeClient = client;\n this.activeOptions = options;\n\n return client;\n }\n\n /**\n * Disconnect the active client and forget it.\n */\n async disconnect(): Promise<void> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n this.activeClient = null;\n this.activeOptions = null;\n }\n }\n\n /**\n * Currently active client, or `null` if not connected.\n */\n getClient(): IProtocolClient | null {\n return this.activeClient;\n }\n\n /**\n * Currently active connection options, or `null` if not connected.\n */\n getOptions(): ConnectionOptions | null {\n return this.activeOptions;\n }\n\n private createClient(options: ConnectionOptions): IProtocolClient {\n switch (options.protocol) {\n case 'foxglove-ws':\n return new FoxgloveClient(this.clientOptions);\n case 'rosbridge':\n return new RosbridgeClient(this.clientOptions);\n case 'zenoh':\n throw new Error('Zenoh support is planned for v0.2.0');\n default: {\n const exhaustive: never = options.protocol;\n throw new Error(`Unknown protocol: ${String(exhaustive)}`);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * Return an owned copy of `view`'s bytes.\n *\n * `RosMessage.data`, when it is a `Uint8Array`, is a zero-copy view into the\n * inbound WebSocket frame's `ArrayBuffer` (see the `RosMessage` TSDoc). That\n * view is only valid synchronously, inside the subscriber callback, and its\n * `byteOffset` is significant. Handing it to anything that retains the bytes\n * past the callback, or to a native binding that ignores `byteOffset` (some\n * Skia paths, `node-canvas`, `sharp`, FFI, ffmpeg bindings), risks corrupt or\n * aliased data.\n *\n * `materializeBytes` returns a fresh `Uint8Array` backed by its own\n * `ArrayBuffer` with `byteOffset === 0`, safe to retain and to hand to any\n * such consumer. It **always copies**: the result never aliases the input,\n * even when the input already spans its whole buffer. That keeps the contract\n * a single sentence — \"the result is always an owned, offset-0 copy\" — at the\n * cost of one allocation, so do not call it on a hot path where you already\n * hold an owned buffer.\n *\n * @example\n * ```ts\n * client.subscribe('/camera/raw', (msg) => {\n * if (msg.data instanceof Uint8Array) {\n * const owned = materializeBytes(msg.data);\n * skia.MakeImageFromEncoded(owned); // safe: offset-0, owned\n * }\n * });\n * ```\n */\nexport function materializeBytes(view: Uint8Array): Uint8Array {\n return new Uint8Array(view);\n}\n"]}