@lumencast/runtime 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +39 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/{broadcast-L5wm2I6J.js → broadcast-ydSpPUje.js} +3 -3
  4. package/dist/{broadcast-L5wm2I6J.js.map → broadcast-ydSpPUje.js.map} +1 -1
  5. package/dist/{control-eEUG7unp.js → control-zTsF-bHP.js} +4 -4
  6. package/dist/{control-eEUG7unp.js.map → control-zTsF-bHP.js.map} +1 -1
  7. package/dist/{index-Clrya_9l.js → index-ClWi5UzJ.js} +422 -341
  8. package/dist/index-ClWi5UzJ.js.map +1 -0
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.html +1 -1
  12. package/dist/index.js +5 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/lumencast.js +22 -18
  15. package/dist/mount.d.ts.map +1 -1
  16. package/dist/mount.js +63 -0
  17. package/dist/mount.js.map +1 -1
  18. package/dist/render/primitives/index.d.ts.map +1 -1
  19. package/dist/render/primitives/index.js +6 -0
  20. package/dist/render/primitives/index.js.map +1 -1
  21. package/dist/render/primitives/meet-peer-slot.d.ts +29 -0
  22. package/dist/render/primitives/meet-peer-slot.d.ts.map +1 -0
  23. package/dist/render/primitives/meet-peer-slot.js +46 -0
  24. package/dist/render/primitives/meet-peer-slot.js.map +1 -0
  25. package/dist/state/reserved-leaves.d.ts +37 -0
  26. package/dist/state/reserved-leaves.d.ts.map +1 -0
  27. package/dist/state/reserved-leaves.js +96 -0
  28. package/dist/state/reserved-leaves.js.map +1 -0
  29. package/dist/{status-pill-elORkMrh.js → status-pill-DkHIOL5V.js} +2 -2
  30. package/dist/{status-pill-elORkMrh.js.map → status-pill-DkHIOL5V.js.map} +1 -1
  31. package/dist/{test-7q_KJkdX.js → test-COpMkyms.js} +4 -4
  32. package/dist/{test-7q_KJkdX.js.map → test-COpMkyms.js.map} +1 -1
  33. package/dist/transport/ws.d.ts +4 -1
  34. package/dist/transport/ws.d.ts.map +1 -1
  35. package/dist/transport/ws.js +7 -0
  36. package/dist/transport/ws.js.map +1 -1
  37. package/dist/{tree-BMxx5170.js → tree-Cubmxeqo.js} +213 -197
  38. package/dist/tree-Cubmxeqo.js.map +1 -0
  39. package/dist/types.d.ts +30 -2
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/webrtc/index.d.ts +1 -1
  42. package/dist/webrtc/index.d.ts.map +1 -1
  43. package/dist/webrtc/index.js.map +1 -1
  44. package/dist/webrtc/peer-stream-registry.d.ts +17 -0
  45. package/dist/webrtc/peer-stream-registry.d.ts.map +1 -1
  46. package/dist/webrtc/peer-stream-registry.js +22 -0
  47. package/dist/webrtc/peer-stream-registry.js.map +1 -1
  48. package/package.json +4 -4
  49. package/src/index.ts +13 -0
  50. package/src/mount.ts +66 -0
  51. package/src/render/primitives/index.ts +6 -0
  52. package/src/render/primitives/meet-peer-slot.tsx +55 -0
  53. package/src/state/reserved-leaves.ts +121 -0
  54. package/src/transport/ws.ts +11 -0
  55. package/src/types.ts +30 -2
  56. package/src/webrtc/index.ts +1 -0
  57. package/src/webrtc/peer-stream-registry.ts +38 -0
  58. package/dist/index-Clrya_9l.js.map +0 -1
  59. package/dist/tree-BMxx5170.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { ErrorCode } from "@lumencast/protocol";
1
+ import type { ErrorCode, SceneRosterEntry } from "@lumencast/protocol";
2
2
  import type { ResolveCaptureDevice } from "./render/primitives/capture";
3
3
  import type { ResolvePeerStream, SubscribePeerStream } from "./render/primitives/media";
4
+ import type { ReservedCamLeaves } from "./state/reserved-leaves";
4
5
  export type LumencastMode = "broadcast" | "control" | "test";
5
6
  export type LumencastStatus = "disconnected" | "connecting" | "live";
6
7
  export interface LumencastTokenProvider {
@@ -13,7 +14,12 @@ export interface LumencastError {
13
14
  recoverable: boolean;
14
15
  }
15
16
  export interface LumencastMetric {
16
- name: "delta_received" | "delta_applied" | "frame_dropped" | "reconnect" | "snapshot_received" | "scene_changed";
17
+ name: "delta_received" | "delta_applied" | "frame_dropped" | "reconnect" | "snapshot_received" | "scene_changed"
18
+ /** A render bundle was warmed ahead of time from a roster entry (either a
19
+ * `scene_roster` frame or the `preloadRoster` mount option). Emitted once
20
+ * the warm fetch resolves (or from cache). Carries `scene_id` +
21
+ * `scene_version` + `source` ("frame" | "option"). */
22
+ | "roster_preloaded";
17
23
  [key: string]: unknown;
18
24
  }
19
25
  /** Anti-silent-drop render diagnostic (ADR 001 §3.4, issue #34).
@@ -76,6 +82,28 @@ export interface MountOptions {
76
82
  * re-renders when its peer joins mid-show. `createPeerViewer()` returns one.
77
83
  * Preferred over `resolvePeerStream` when both are supplied. */
78
84
  subscribePeerStream?: SubscribePeerStream;
85
+ /** ADR Blue 009 §3.2–3.3 — host sink for the reserved `__cam.*` LSDP leaves
86
+ * (never rendered, never bound to a node). Called with the full current
87
+ * projection whenever it changes : `viewer` carries the receive-only viewer
88
+ * creds (`__cam.viewer`, Orion #268) and `slots` the `slotRef → peer_label`
89
+ * snapshot (`__cam.slots.*`, Orion #267). The host (Solar) feeds `viewer` into
90
+ * its peer-viewer injection and drives its slot-binding registry's
91
+ * `assign(slotRef, peer_label | null)` so `x-zab.meet-peer` nodes re-key by
92
+ * `slotRef`. Receive-only : the runtime forwards the token verbatim, never
93
+ * reads it. Omit it and the reserved leaves are simply not surfaced (the
94
+ * preview/headless paths are unaffected). */
95
+ onReservedLeaves?: (leaves: ReservedCamLeaves) => void;
96
+ /** Preload the render bundles of a known scene roster so the FIRST switch to
97
+ * each scene is instant (a warm cache hit instead of a blocking fetch).
98
+ * Each entry is `{ scene_id, scene_version }`. Warmed in the background right
99
+ * after mount — best-effort: a failed warm is swallowed (the scene still
100
+ * fetches on demand at switch time) and never blocks or errors the mount.
101
+ *
102
+ * This is the PUBLIC preload surface (lumencast-js #87b) for hosts that
103
+ * already know the roster at mount time. When the server also emits
104
+ * `scene_roster` frames the runtime warms from those too — both paths feed
105
+ * the same cache and are idempotent (a version is warmed at most once). */
106
+ preloadRoster?: readonly SceneRosterEntry[];
79
107
  }
80
108
  export interface LumencastHandle {
81
109
  /** Tear down the WS, unmount the React tree, release timers. Idempotent. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAExF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EACA,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,eAAe,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;+BAE+B;AAC/B,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;;yDAGqD;IACrD,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;;;;;yEAOqE;IACrE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;gFAK4E;IAC5E,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EACA,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,eAAe;IACjB;;;2DAGuD;OACrD,kBAAkB,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;+BAE+B;AAC/B,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;;yDAGqD;IACrD,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;;;;;yEAOqE;IACrE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;gFAK4E;IAC5E,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C;;;;;;;;;kDAS8C;IAC9C,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD;;;;;;;;;gFAS4E;IAC5E,aAAa,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { MeetViewer, type MeetViewerOptions } from "./meet-viewer.js";
2
2
  import { type PeerStreamListener, type PeerStreamRegistry } from "./peer-stream-registry.js";
3
3
  export { MeetViewer, type MeetViewerOptions, type MeetViewerDeps, type PeerInfo, type RemoteTrackEvent, } from "./meet-viewer.js";
4
- export { createPeerStreamRegistry, type PeerStreamRegistry, type PeerStreamListener, } from "./peer-stream-registry.js";
4
+ export { createPeerStreamRegistry, type PeerStreamRegistry, type PeerStreamListener, type RosterListener, } from "./peer-stream-registry.js";
5
5
  export interface PeerViewer {
6
6
  /** Join the room(s) (viewer role, no capture). */
7
7
  join: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IAC7D,8EAA8E;IAC9E,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;IACrF,mDAAmD;IACnD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;gDAC4C;IAC5C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;mFAImF;AACnF;;;;;;;8BAO8B;AAC9B,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1C;AA+BD;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAevE;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAC1D,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB;oFACgF;IAChF,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD;;oEAEgE;IAChE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;;;;;;2EAU2E;AAC3E,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA8ErB;AAED;;oEAEoE;AACpE,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D;;oCAEoC;AACpC,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAYjG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IAC7D,8EAA8E;IAC9E,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;IACrF,mDAAmD;IACnD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;gDAC4C;IAC5C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;mFAImF;AACnF;;;;;;;8BAO8B;AAC9B,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1C;AA+BD;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAevE;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAC1D,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB;oFACgF;IAChF,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD;;oEAEgE;IAChE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;;;;;;2EAU2E;AAC3E,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA8ErB;AAED;;oEAEoE;AACpE,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D;;oCAEoC;AACpC,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAYjG"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,29 @@
1
1
  export type PeerStreamListener = (stream: MediaStream | null) => void;
2
+ /** Notified whenever the live roster changes ORDER (a peer connects for the first
3
+ * time, or a connected peer drops). A pure re-`set` of an already-present label's
4
+ * stream is NOT a roster change (same arrival order) — it reaches per-label
5
+ * `subscribe` listeners only. Carries no payload : the listener re-reads
6
+ * `orderedLabels()`. */
7
+ export type RosterListener = () => void;
2
8
  export interface PeerStreamRegistry {
3
9
  /** #4 contract — the current stream for a label, or `null` if the peer is not
4
10
  * connected (yet / any more). Synchronous, side-effect free. */
5
11
  resolve(peerLabel: string): MediaStream | null;
12
+ /** The live `peer_label`s in ARRIVAL ORDER (insertion order of the backing Map,
13
+ * restricted to labels that currently hold a stream). Drives positional slot
14
+ * resolution (`@<n>` → `orderedLabels()[n]`, ADR Blue 009 axe 1 positional
15
+ * variant). Returns a fresh array — safe for the caller to keep / index. */
16
+ orderedLabels(): string[];
6
17
  /** Push channel for the LIVE `media` primitive : invoked immediately with the
7
18
  * current value, then on every change for `peerLabel`. Returns an
8
19
  * unsubscribe. */
9
20
  subscribe(peerLabel: string, listener: PeerStreamListener): () => void;
21
+ /** Roster-change channel : invoked whenever a peer connects (new label) or
22
+ * leaves (label dropped) — i.e. whenever `orderedLabels()` could shift. Lets a
23
+ * positional consumer re-resolve `@<n>` when arrivals/departures shuffle the
24
+ * order. NOT invoked on a pure stream replacement of an existing label. Returns
25
+ * an unsubscribe. */
26
+ subscribeRoster(listener: RosterListener): () => void;
10
27
  /** Viewer-side : publish / replace a peer's stream (peer connected). */
11
28
  set(peerLabel: string, stream: MediaStream): void;
12
29
  /** Viewer-side : drop a peer's stream (peer left / connection failed). The
@@ -1 +1 @@
1
- {"version":3,"file":"peer-stream-registry.d.ts","sourceRoot":"","sources":["../../src/webrtc/peer-stream-registry.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC;qEACiE;IACjE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAC/C;;uBAEmB;IACnB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAC;IACvE,wEAAwE;IACxE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAClD;;gDAE4C;IAC5C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;iBACa;IACb,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CAgD7D"}
1
+ {"version":3,"file":"peer-stream-registry.d.ts","sourceRoot":"","sources":["../../src/webrtc/peer-stream-registry.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;AAEtE;;;;yBAIyB;AACzB,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC;qEACiE;IACjE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAC/C;;;iFAG6E;IAC7E,aAAa,IAAI,MAAM,EAAE,CAAC;IAC1B;;uBAEmB;IACnB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAC;IACvE;;;;0BAIsB;IACtB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;IACtD,wEAAwE;IACxE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAClD;;gDAE4C;IAC5C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;iBACa;IACb,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CAoE7D"}
@@ -23,6 +23,7 @@
23
23
  export function createPeerStreamRegistry() {
24
24
  const streams = new Map();
25
25
  const listeners = new Map();
26
+ const rosterListeners = new Set();
26
27
  function notify(peerLabel) {
27
28
  const set = listeners.get(peerLabel);
28
29
  if (set === undefined)
@@ -31,10 +32,25 @@ export function createPeerStreamRegistry() {
31
32
  for (const listener of set)
32
33
  listener(value);
33
34
  }
35
+ function notifyRoster() {
36
+ for (const listener of [...rosterListeners])
37
+ listener();
38
+ }
34
39
  return {
35
40
  resolve(peerLabel) {
36
41
  return streams.get(peerLabel) ?? null;
37
42
  },
43
+ orderedLabels() {
44
+ // Map preserves insertion order = arrival order ; every key holds a stream
45
+ // (a dropped peer is `delete`d in remove()).
46
+ return [...streams.keys()];
47
+ },
48
+ subscribeRoster(listener) {
49
+ rosterListeners.add(listener);
50
+ return () => {
51
+ rosterListeners.delete(listener);
52
+ };
53
+ },
38
54
  subscribe(peerLabel, listener) {
39
55
  let set = listeners.get(peerLabel);
40
56
  if (set === undefined) {
@@ -57,20 +73,26 @@ export function createPeerStreamRegistry() {
57
73
  set(peerLabel, stream) {
58
74
  if (streams.get(peerLabel) === stream)
59
75
  return; // idempotent re-emit guard
76
+ const isNew = !streams.has(peerLabel); // a brand-new arrival shifts the roster
60
77
  streams.set(peerLabel, stream);
61
78
  notify(peerLabel);
79
+ if (isNew)
80
+ notifyRoster();
62
81
  },
63
82
  remove(peerLabel) {
64
83
  if (!streams.has(peerLabel))
65
84
  return;
66
85
  streams.delete(peerLabel);
67
86
  notify(peerLabel);
87
+ notifyRoster(); // a departure shifts every later position
68
88
  },
69
89
  clear() {
70
90
  const labels = [...streams.keys()];
71
91
  streams.clear();
72
92
  for (const label of labels)
73
93
  notify(label);
94
+ if (labels.length > 0)
95
+ notifyRoster();
74
96
  },
75
97
  };
76
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"peer-stream-registry.js","sourceRoot":"","sources":["../../src/webrtc/peer-stream-registry.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,sCAAsC;AACtC,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAC9E,uEAAuE;AACvE,EAAE;AACF,gFAAgF;AAChF,4EAA4E;AAC5E,wEAAwE;AACxE,oEAAoE;AACpE,2EAA2E;AAC3E,2EAA2E;AAC3E,+EAA+E;AAC/E,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,4DAA4D;AAuB5D,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAmC,CAAC;IAE7D,SAAS,MAAM,CAAC,SAAiB;QAC/B,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;QAC7C,KAAK,MAAM,QAAQ,IAAI,GAAG;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,OAAO,CAAC,SAAS;YACf,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;QACxC,CAAC;QACD,SAAS,CAAC,SAAS,EAAE,QAAQ;YAC3B,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;gBAChB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAChC,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClB,oEAAoE;YACpE,8DAA8D;YAC9D,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC;YACzC,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACnC,IAAI,CAAC,KAAK,SAAS;oBAAE,OAAO;gBAC5B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACnB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;oBAAE,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChD,CAAC,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,SAAS,EAAE,MAAM;YACnB,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,MAAM;gBAAE,OAAO,CAAC,2BAA2B;YAC1E,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC/B,MAAM,CAAC,SAAS,CAAC,CAAC;QACpB,CAAC;QACD,MAAM,CAAC,SAAS;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,OAAO;YACpC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC1B,MAAM,CAAC,SAAS,CAAC,CAAC;QACpB,CAAC;QACD,KAAK;YACH,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,KAAK,MAAM,KAAK,IAAI,MAAM;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"peer-stream-registry.js","sourceRoot":"","sources":["../../src/webrtc/peer-stream-registry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumencast/runtime",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Browser runtime for Lumencast — mount(), LSDP/1 transport, leaf-grain store, LSML render, animations, overlays.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  "framer-motion": "^12.0.0",
37
37
  "react": "^19.0.0",
38
38
  "react-dom": "^19.0.0",
39
- "@lumencast/protocol": "0.10.0"
39
+ "@lumencast/protocol": "0.12.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@playwright/test": "^1.49.1",
@@ -50,8 +50,8 @@
50
50
  "vite-plugin-dts": "^4.5.0",
51
51
  "vitest": "^4.1.5",
52
52
  "ws": "^8.18.0",
53
- "@lumencast/dev-server": "0.10.0",
54
- "@lumencast/server": "0.10.0"
53
+ "@lumencast/dev-server": "0.12.0",
54
+ "@lumencast/server": "0.12.0"
55
55
  },
56
56
  "scripts": {
57
57
  "dev": "vite",
package/src/index.ts CHANGED
@@ -37,6 +37,18 @@ export type { ResolveCaptureDevice } from "./render/primitives/capture.js";
37
37
  // runtime's contract.
38
38
  export type { ResolvePeerStream, SubscribePeerStream } from "./render/primitives/media.js";
39
39
 
40
+ // ADR Blue 009 §3.2–3.3 — reserved `__cam.*` LSDP leaves (slot→peer assignments
41
+ // + receive-only viewer creds) surfaced to the host via `MountOptions
42
+ // .onReservedLeaves`. Exported so the consuming host (Solar) types its sink and
43
+ // reuses the reserved-path predicate / wire-name constants without re-deriving.
44
+ export {
45
+ CAM_RESERVED_PREFIX,
46
+ CAM_SLOTS_PREFIX,
47
+ CAM_VIEWER_LEAF,
48
+ isReservedCamPath,
49
+ type ReservedCamLeaves,
50
+ } from "./state/reserved-leaves.js";
51
+
40
52
  // ADR 006 #3 — WebRTC viewer (mesh, viewer role) + peer-stream registry. The
41
53
  // #3↔#4 bridge : a viewer joins Meet room(s), receives N peers and returns the
42
54
  // `resolvePeerStream` / `subscribePeerStream` the `media`/`meet.peer` LIVE render
@@ -64,6 +76,7 @@ export {
64
76
  type RemoteTrackEvent,
65
77
  type PeerStreamRegistry,
66
78
  type PeerStreamListener,
79
+ type RosterListener,
67
80
  } from "./webrtc/index.js";
68
81
 
69
82
  // Bundle types are useful for hosts that want to typecheck pre-compiled scenes.
package/src/mount.ts CHANGED
@@ -7,6 +7,7 @@ import { createElement } from "react";
7
7
  import { LumencastApp } from "./app.js";
8
8
  import { applyDelta } from "./state/apply-delta.js";
9
9
  import { applySnapshot } from "./state/apply-snapshot.js";
10
+ import { createReservedLeafObserver } from "./state/reserved-leaves.js";
10
11
  import { createStore } from "./state/store.js";
11
12
  import { createBundleFetcher, type BundleFetcher, type RenderBundle } from "./render/bundle.js";
12
13
  import { WsClient, type ConnectionStatus, type TransportError } from "./transport/ws.js";
@@ -45,6 +46,20 @@ export function mount(options: MountOptions): LumencastHandle {
45
46
 
46
47
  let active = true;
47
48
 
49
+ // Render-bundle versions already warmed (or warming) by the preload path.
50
+ // Keeps both roster sources (the `scene_roster` frame and the `preloadRoster`
51
+ // mount option) idempotent — a version is fetched by the warmer at most once.
52
+ const warmedVersions = new Set<string>();
53
+
54
+ // ADR Blue 009 §3.2–3.3 — surface the reserved `__cam.*` LSDP leaves (the
55
+ // slot→peer assignments + the receive-only viewer creds) to the host so its
56
+ // WebRTC viewer (Solar) can drive room joins + `x-zab.meet-peer` slot re-keying.
57
+ // The runtime never joins, holds creds, or re-keys ; it only forwards. Created
58
+ // only when the host opts in — zero cost on the preview/headless paths.
59
+ const reservedLeaves = options.onReservedLeaves
60
+ ? createReservedLeafObserver(options.onReservedLeaves)
61
+ : undefined;
62
+
48
63
  // ADR 001 §3.4 (issue #34) — anti-silent-drop diagnostics are events
49
64
  // surfaced to the host, never console logs in `broadcast` mode.
50
65
  const removeDiagnosticsHandler = options.onDiagnostic
@@ -59,6 +74,7 @@ export function mount(options: MountOptions): LumencastHandle {
59
74
  onStatus: setStatus,
60
75
  onSnapshot: (frame) => {
61
76
  if (!active) return;
77
+ reservedLeaves?.onSnapshot(frame.state);
62
78
  void onSnapshot(
63
79
  bundleFetcher,
64
80
  bundleSignal,
@@ -78,6 +94,7 @@ export function mount(options: MountOptions): LumencastHandle {
78
94
  if (!active) return;
79
95
  const start = performance.now();
80
96
  applyDelta(store, frame);
97
+ reservedLeaves?.onDelta(frame.patches);
81
98
  options.onMetric?.({
82
99
  name: "delta_applied",
83
100
  duration_ms: performance.now() - start,
@@ -95,6 +112,13 @@ export function mount(options: MountOptions): LumencastHandle {
95
112
  to: frame.scene_version,
96
113
  });
97
114
  },
115
+ onSceneRoster: (frame) => {
116
+ if (!active) return;
117
+ // The server advertised the show roster (LSDP/1.1 `scene_roster`).
118
+ // Warm every scene's render bundle in the background so the first switch
119
+ // to each is a cache hit, not a blocking fetch.
120
+ warmRoster(frame.entries, "frame");
121
+ },
98
122
  onServerError: (frame) => {
99
123
  reportError({
100
124
  code: frame.code,
@@ -109,6 +133,12 @@ export function mount(options: MountOptions): LumencastHandle {
109
133
 
110
134
  ws.start();
111
135
 
136
+ // Public preload surface (#87b) — warm a host-supplied roster right after
137
+ // mount, before any switch. Same warmer + cache as the `scene_roster` frame.
138
+ if (options.preloadRoster !== undefined && options.preloadRoster.length > 0) {
139
+ warmRoster(options.preloadRoster, "option");
140
+ }
141
+
112
142
  const root: Root = createRoot(options.target);
113
143
  root.render(
114
144
  createElement(LumencastApp, {
@@ -153,6 +183,42 @@ export function mount(options: MountOptions): LumencastHandle {
153
183
 
154
184
  // --- helpers ----------------------------------------------------------
155
185
 
186
+ /**
187
+ * Warm the render bundles for a set of roster entries in the background.
188
+ * Best-effort and non-blocking: each `get()` populates the fetcher's cache
189
+ * keyed by `scene_version`, so the eventual `onSnapshot` fetch for that scene
190
+ * is an instant cache hit. Idempotent via `warmedVersions`; the already-active
191
+ * scene is skipped (its bundle is already loaded or in flight). A failed warm
192
+ * is swallowed and its version released so a later roster can retry — the
193
+ * scene still fetches on demand at switch time.
194
+ */
195
+ function warmRoster(
196
+ entries: readonly { scene_id: string; scene_version: string }[],
197
+ source: "frame" | "option",
198
+ ): void {
199
+ const activeVersion = bundleSignal.value?.scene_version;
200
+ for (const { scene_id, scene_version } of entries) {
201
+ if (scene_version === activeVersion) continue;
202
+ if (warmedVersions.has(scene_version)) continue;
203
+ warmedVersions.add(scene_version);
204
+ void bundleFetcher
205
+ .get(scene_id, scene_version)
206
+ .then(() => {
207
+ if (!active) return;
208
+ options.onMetric?.({
209
+ name: "roster_preloaded",
210
+ scene_id,
211
+ scene_version,
212
+ source,
213
+ });
214
+ })
215
+ .catch(() => {
216
+ // Release so a subsequent roster advertisement can retry the warm.
217
+ warmedVersions.delete(scene_version);
218
+ });
219
+ }
220
+ }
221
+
156
222
  async function onSnapshot(
157
223
  fetcher: BundleFetcher,
158
224
  bSignal: typeof bundleSignal,
@@ -13,6 +13,7 @@ import { Image } from "./image";
13
13
  import { Shape } from "./shape";
14
14
  import { Media } from "./media";
15
15
  import { MeetPeer } from "./meet-peer";
16
+ import { MeetPeerSlot } from "./meet-peer-slot";
16
17
  import { Instance } from "./instance";
17
18
  import { Capture } from "./capture";
18
19
  // `repeat` is dispatched specially in the tree (it iterates a bound
@@ -55,4 +56,9 @@ export const PRIMITIVES: Partial<Record<RenderKind, ComponentType<PrimitiveProps
55
56
  instance: Instance,
56
57
  // RFC-0001 / ADR 004 — Zab vendor capture placeholder (transparent, inert).
57
58
  "x-zab.capture": Capture,
59
+ // ADR Blue 009 §3.1 (Amendment 2) — Zab vendor meet-peer SLOT placeholder.
60
+ // Carries only a logical `x-zab.slotRef` ; the host's slot-aware peer-stream
61
+ // registry resolves `slotRef → peer_label → MediaStream` (transparent when
62
+ // unbound). Closes the kind→primitive gap that left it an unknown-kind drop.
63
+ "x-zab.meet-peer": MeetPeerSlot,
58
64
  };
@@ -0,0 +1,55 @@
1
+ import type { PrimitiveProps } from "./index";
2
+ import { LivePeerVideo } from "./live-peer-video";
3
+
4
+ /** `x-zab.meet-peer` — the transparent meet-peer SLOT placeholder (Zab vendor
5
+ * primitive, ADR Blue 009 §3.1 Amendment 2 ; type shipped in v0.10.0 / #81).
6
+ *
7
+ * Distinct from `meet.peer` (the cam-identity source) : this node carries NO
8
+ * peer identity, only a hash-stable LOGICAL `x-zab.slotRef` (e.g. `cam-caster-1`)
9
+ * + geometry. WHICH `peer_label` fills a slot is RUNTIME, stream-level ZabCam
10
+ * state — never baked in the scene. The slot→peer binding is ported by Orion on
11
+ * the LSDP as `__cam.slots.<slotRef>` = "<peer_label>" (§3.3) and re-keyed into
12
+ * the host's peer-stream registry (Solar `slot-binding.ts`) so the registry
13
+ * resolves `slotRef → peer_label → MediaStream`.
14
+ *
15
+ * Contract (rendered verbatim) :
16
+ * - `x-zab.slotRef` (string) — the SLOT REFERENCE, used as the resolver KEY.
17
+ * The host's peer-stream resolver (`resolvePeerStream`/`subscribePeerStream`)
18
+ * is keyed by `slotRef` on the antenne (Solar's slot-aware registry maps it
19
+ * to a `peer_label`, then to a stream). Empty / missing → a transparent inert
20
+ * box (the slot is not addressable).
21
+ * - geometry (`width`/`height` + position) — applied by the Tree's
22
+ * UniversalWrapper, exactly like `meet.peer` ; the `<video>` fills the box
23
+ * 100%/100% and is never forced full-screen (RC-Geo).
24
+ *
25
+ * Receive-only : the slot reads its stream through the host viewer (Solar joins
26
+ * the room and owns the peer connections / track lifecycle) ; the primitive
27
+ * carries no creds and never mutates the scene (RC-ReadOnly). An UNBOUND slot
28
+ * (no `__cam.slots.*` assignment) or a not-yet-connected peer → a transparent
29
+ * placeholder, no throw, no diagnostic (R3). */
30
+ export function MeetPeerSlot({ resolved }: PrimitiveProps) {
31
+ const slotRef =
32
+ typeof resolved["x-zab.slotRef"] === "string" &&
33
+ (resolved["x-zab.slotRef"] as string).length > 0
34
+ ? (resolved["x-zab.slotRef"] as string)
35
+ : "";
36
+
37
+ // No slotRef → not addressable : a transparent inert box of the wrapper
38
+ // geometry (no throw, no diagnostic), exactly like an unbound slot.
39
+ if (slotRef === "") {
40
+ return (
41
+ <div
42
+ aria-hidden
43
+ data-lumencast-meet-peer-slot
44
+ style={{ width: "100%", height: "100%", opacity: 0, pointerEvents: "none" }}
45
+ />
46
+ );
47
+ }
48
+
49
+ // Key the peer-viewer resolver by `slotRef` (NOT a peer_label). The shared
50
+ // `LivePeerVideo` is resolver-key agnostic : it passes its `peerLabel` prop
51
+ // straight to `resolvePeerStream`/`subscribePeerStream`, and the host's
52
+ // slot-aware registry translates the slotRef to the bound peer's stream. An
53
+ // unbound slot resolves to `null` → the transparent placeholder.
54
+ return <LivePeerVideo peerLabel={slotRef} objectFit="cover" muted />;
55
+ }
@@ -0,0 +1,121 @@
1
+ // Reserved `__cam.*` LSDP leaves — surfaced to the host, never rendered.
2
+ //
3
+ // ADR Blue 009 §3.2–3.3 (axe 1, antenne). The meet-cam antenne path needs two
4
+ // pieces of RUNTIME, stream-level ZabCam state that travel on the LSDP wire as
5
+ // RESERVED leaves (they bind to no node and are never painted) :
6
+ //
7
+ // - `__cam.slots.<slotRef>` = "<peer_label>" (Orion #267 deltas, §3.3)
8
+ // which peer currently fills an authored `x-zab.meet-peer` slot.
9
+ // - `__cam.viewer` = { rooms: [{ signalingUrl, roomId, token }] } (Orion #268)
10
+ // the receive-only viewer credentials for the active stream.
11
+ //
12
+ // The runtime does NOT join rooms, hold creds, or re-key slots itself — that is
13
+ // the host's WebRTC viewer (Solar `peer-viewer/*`). The runtime's only job is to
14
+ // SURFACE these reserved leaves to the host through `MountOptions.onReservedLeaves`
15
+ // so Solar can feed `__cam.viewer` into its viewer injection and drive its
16
+ // slot-binding registry's `assign(slotRef, peer_label | null)` from `__cam.slots.*`.
17
+ // Receive-only : the token flows host→viewer→join ; the runtime never reads it.
18
+
19
+ /** Every reserved cam leaf lives under this prefix. */
20
+ export const CAM_RESERVED_PREFIX = "__cam.";
21
+
22
+ /** One scalar leaf per bound slot : `__cam.slots.<slotRef>` = "<peer_label>"
23
+ * (ADR Blue 009 §3.3). Mirrors Solar's `CAM_SLOTS_PREFIX` — keep them in sync. */
24
+ export const CAM_SLOTS_PREFIX = "__cam.slots.";
25
+
26
+ /** The single viewer-credentials leaf (ADR Blue 009 §3.2, Orion #268). */
27
+ export const CAM_VIEWER_LEAF = "__cam.viewer";
28
+
29
+ /** The reserved cam state surfaced to the host in one shot on every change. */
30
+ export interface ReservedCamLeaves {
31
+ /** `__cam.viewer` — receive-only viewer creds for the active stream. Opaque to
32
+ * the runtime (shape `{ rooms: [{ signalingUrl, roomId, token }] }` validated
33
+ * host-side) ; `undefined` when the leaf is absent. */
34
+ viewer?: unknown;
35
+ /** `slotRef → peer_label` snapshot from the `__cam.slots.*` subtree. A slot
36
+ * ABSENT from this map is UNBOUND — the host releases it (`assign(slotRef,
37
+ * null)`) so the `x-zab.meet-peer` node falls back to its placeholder. Only
38
+ * non-empty string values are kept. */
39
+ slots: Record<string, string>;
40
+ }
41
+
42
+ /** A reserved cam leaf the runtime forwards rather than renders. */
43
+ export function isReservedCamPath(path: string): boolean {
44
+ return path === CAM_VIEWER_LEAF || path.startsWith(CAM_SLOTS_PREFIX);
45
+ }
46
+
47
+ /** Project a raw reserved-leaf state into the host-facing shape. Defensive : a
48
+ * malformed slot value (non-string / empty) or empty slotRef is dropped. */
49
+ function project(raw: Map<string, unknown>): ReservedCamLeaves {
50
+ const slots: Record<string, string> = {};
51
+ let viewer: unknown;
52
+ for (const [path, value] of raw) {
53
+ if (path === CAM_VIEWER_LEAF) {
54
+ if (value !== undefined && value !== null) viewer = value;
55
+ } else if (path.startsWith(CAM_SLOTS_PREFIX)) {
56
+ const slotRef = path.slice(CAM_SLOTS_PREFIX.length);
57
+ if (slotRef !== "" && typeof value === "string" && value !== "") slots[slotRef] = value;
58
+ }
59
+ }
60
+ return viewer !== undefined ? { viewer, slots } : { slots };
61
+ }
62
+
63
+ /** A stable identity key for change detection — two `ReservedCamLeaves` with the
64
+ * same content always produce the same key regardless of insertion order. */
65
+ function identity(leaves: ReservedCamLeaves): string {
66
+ const slots = Object.keys(leaves.slots)
67
+ .sort()
68
+ .map((k) => `${k}=${leaves.slots[k]}`)
69
+ .join("&");
70
+ const viewer = leaves.viewer === undefined ? "" : JSON.stringify(leaves.viewer);
71
+ return `${slots}|${viewer}`;
72
+ }
73
+
74
+ export interface ReservedLeafObserver {
75
+ /** Reseed from a full snapshot's state (reserved leaves not present are
76
+ * dropped). Emits when the projected state changed. */
77
+ onSnapshot(state: Record<string, unknown>): void;
78
+ /** Apply a delta's patches ; emits only when a reserved leaf actually moved. */
79
+ onDelta(patches: ReadonlyArray<{ path: string; value: unknown }>): void;
80
+ }
81
+
82
+ /** Track the reserved `__cam.*` leaves across snapshots + deltas and `emit` the
83
+ * host-facing projection whenever it changes (de-duplicated by content, so an
84
+ * unrelated scene's deltas never call back). Created only when the host supplies
85
+ * `onReservedLeaves` — zero cost otherwise. */
86
+ export function createReservedLeafObserver(
87
+ emit: (leaves: ReservedCamLeaves) => void,
88
+ ): ReservedLeafObserver {
89
+ const raw = new Map<string, unknown>();
90
+ // Seed with the empty projection's identity so a plain scene (no cam leaves)
91
+ // never fires a spurious empty emit ; a later transition to/from cam state does.
92
+ let last = identity({ slots: {} });
93
+
94
+ const flush = (): void => {
95
+ const leaves = project(raw);
96
+ const key = identity(leaves);
97
+ if (key === last) return;
98
+ last = key;
99
+ emit(leaves);
100
+ };
101
+
102
+ return {
103
+ onSnapshot(state) {
104
+ raw.clear();
105
+ for (const [path, value] of Object.entries(state)) {
106
+ if (isReservedCamPath(path)) raw.set(path, value);
107
+ }
108
+ flush();
109
+ },
110
+ onDelta(patches) {
111
+ let touched = false;
112
+ for (const patch of patches) {
113
+ if (isReservedCamPath(patch.path)) {
114
+ raw.set(patch.path, patch.value);
115
+ touched = true;
116
+ }
117
+ }
118
+ if (touched) flush();
119
+ },
120
+ };
121
+ }
@@ -25,6 +25,7 @@ import {
25
25
  type ErrorFrame,
26
26
  type Patch,
27
27
  type SceneChangedFrame,
28
+ type SceneRosterFrame,
28
29
  type SnapshotFrame,
29
30
  } from "@lumencast/protocol";
30
31
  import type { LumencastToken } from "../types.js";
@@ -57,6 +58,9 @@ export interface WsClientOptions {
57
58
  onSnapshot?: (frame: SnapshotFrame) => void;
58
59
  onDelta?: (frame: DeltaFrame) => void;
59
60
  onSceneChanged?: (frame: SceneChangedFrame) => void;
61
+ /** Out-of-band roster advertisement (LSDP/1.1 `scene_roster`, additive).
62
+ * Carries no sequence — dispatched without touching the sequence tracker. */
63
+ onSceneRoster?: (frame: SceneRosterFrame) => void;
60
64
  onServerError?: (frame: ErrorFrame) => void;
61
65
  /** Wire-level / codec / unrecoverable errors. */
62
66
  onTransportError?: (err: TransportError) => void;
@@ -298,6 +302,13 @@ export class WsClient {
298
302
  if (!frame.recoverable) this.close();
299
303
  return;
300
304
  }
305
+ case "scene_roster": {
306
+ // Out-of-band roster metadata: NOT part of the snapshot/delta stream.
307
+ // It carries no seq and MUST NOT touch the sequence tracker — forward
308
+ // it verbatim so the host can warm its render-bundle cache.
309
+ this.opts.onSceneRoster?.(frame);
310
+ return;
311
+ }
301
312
  case "pong":
302
313
  return;
303
314
  }