@pollen-robotics/reachy-mini-sdk 1.10.0-dev.0.main.05ce680 → 1.10.0-dev.0.main.66c3492

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.
@@ -23,6 +23,9 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
23
23
  private _state;
24
24
  private _robots;
25
25
  private _robotState;
26
+ private _lastPoseSeq;
27
+ private _lastPoseFrameAt;
28
+ private _poseSubRefs;
26
29
  private readonly _preselectedRobotId;
27
30
  private _token;
28
31
  private _username;
@@ -44,6 +47,8 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
44
47
  private _volumeResolve;
45
48
  private _micVolumeResolve;
46
49
  private _trackedFaceResolve;
50
+ private _robotNameResolve;
51
+ private _deleteHfTokenResolve;
47
52
  private _applyAudioConfigResolve;
48
53
  private _readAudioParameterResolve;
49
54
  private readonly _logSubscribers;
@@ -238,6 +243,37 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
238
243
  setVolume(volume: number): Promise<number | null>;
239
244
  getMicrophoneVolume(): Promise<number | null>;
240
245
  setMicrophoneVolume(volume: number): Promise<number | null>;
246
+ /**
247
+ * Query the persisted robot display name. Resolves the stored name,
248
+ * `null` when none is set / the channel isn't open / the daemon predates
249
+ * the `get_robot_name` command.
250
+ */
251
+ getRobotName(): Promise<string | null>;
252
+ /**
253
+ * Set and persist the robot display name on the robot. Resolves with the
254
+ * stored (trimmed) name, or `null` on error / channel-closed. Applied live
255
+ * by the daemon (status + central relay + mDNS), so it takes effect right
256
+ * away without a restart; the persisted name also overrides --robot-name
257
+ * on the next start.
258
+ */
259
+ setRobotName(name: string): Promise<string | null>;
260
+ /**
261
+ * Sign this robot out of Hugging Face: asks the daemon to delete its
262
+ * stored HF token, which de-registers the robot from the central
263
+ * signaling relay (it disappears from its owner's robot list until it
264
+ * is set up again). Works over the WebRTC data channel, so it reaches
265
+ * the robot remotely (no LAN HTTP path required).
266
+ *
267
+ * Resolves `true` when the daemon acked success, `false` on a daemon
268
+ * error, or `null` when no ack arrives before the timeout (e.g. a
269
+ * daemon that predates the `delete_hf_token` command silently drops
270
+ * it). Rejects if the data channel isn't open. Note the sign-out
271
+ * drops the central relay, so the session may tear down right after
272
+ * the ack - callers should treat a post-call session drop as expected,
273
+ * and a successful sign-out may surface as `null` if teardown races
274
+ * ahead of the ack.
275
+ */
276
+ signOut(): Promise<boolean | null>;
241
277
  applyAudioConfig(config: AudioConfigEntry[], { verify }?: ApplyAudioConfigOptions): Promise<boolean>;
242
278
  readAudioParameter(name: string): Promise<number[] | null>;
243
279
  /**
@@ -258,6 +294,21 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
258
294
  sendRaw(data: unknown): boolean;
259
295
  subscribeLogs({ onLine, onError }: SubscribeLogsOptions): () => void;
260
296
  requestState(): boolean;
297
+ /**
298
+ * Ask the daemon to *push* the robot state (~30 Hz) over the dedicated
299
+ * unreliable/unordered `pose` data channel instead of polling get_state.
300
+ * Fires `state` events as frames arrive. No-op against an older daemon (no
301
+ * pose channel) - fall back to `requestState()` polling there.
302
+ *
303
+ * Refcounted: pair every `subscribePose()` with exactly one
304
+ * `unsubscribePose()`. Multiple consumers share a single daemon-side
305
+ * subscription; the daemon only stops pushing once the last one releases.
306
+ * If the channel isn't open yet (or the session later reconnects), the
307
+ * subscription is (re-)asserted from `_checkSessionReady`.
308
+ */
309
+ subscribePose(): boolean;
310
+ /** Release one pose-stream consumer; sends `unsubscribe_pose` on the last. */
311
+ unsubscribePose(): boolean;
261
312
  setAudioMuted(muted: boolean): void;
262
313
  setMicMuted(muted: boolean): void;
263
314
  attachVideo(videoElement: HTMLVideoElement): () => void;
@@ -294,6 +345,11 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
294
345
  private _handleSignalingMessage;
295
346
  private _handleEndSession;
296
347
  private _handlePeerMessage;
348
+ /**
349
+ * @param fromPoseStream Frame came from the pushed `pose` channel rather
350
+ * than the reliable control channel. Only those may refresh the state
351
+ * mirror while the stream is live (see the `data.state` branch).
352
+ */
297
353
  private _handleRobotMessage;
298
354
  /** Snap video playback to live edge if buffered lag exceeds 0.5 s. */
299
355
  private _startLatencyMonitor;
@@ -1 +1 @@
1
- {"version":3,"file":"reachy-mini.d.ts","sourceRoot":"","sources":["../../lib/reachy-mini.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reachy-mini.d.ts","sourceRoot":"","sources":["../../lib/reachy-mini.ts"],"names":[],"mappings":"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"}
@@ -40,6 +40,21 @@ const ICE_FAILED_GRACE_MS = 1000;
40
40
  * to be honest with the user.
41
41
  */
42
42
  const MAX_VISIBILITY_DEFER_MS = 60_000;
43
+ /**
44
+ * How long a pushed pose frame keeps the periodic `get_state` poll on hold -
45
+ * both on the way out (no request is sent) and on the way back (a reply that
46
+ * arrives anyway doesn't touch the state mirror).
47
+ *
48
+ * Poll replies carry no `seq`, so they slip past the stale-frame guard: a
49
+ * reply that crosses a fresher pushed frame would rewind the very mirror the
50
+ * stream exists to smooth. While frames flow at ~30 Hz there is nothing left
51
+ * for the poll to add, so it stands down. Keying that on frame arrival rather
52
+ * than on `_poseSubRefs` keeps the poll running against a daemon that doesn't
53
+ * know `subscribe_pose`, and brings it back on its own if the stream stalls.
54
+ * A little over one 500 ms poll period, so a couple of dropped frames don't
55
+ * flip it back and forth.
56
+ */
57
+ const POSE_STREAM_FRESH_MS = 750;
43
58
  /**
44
59
  * Fail-open ceiling for a single `_slotRoundtrip` request/response.
45
60
  * Every slot command has a strict "one reply per request" contract, so
@@ -66,6 +81,19 @@ export class ReachyMini extends EventTarget {
66
81
  _state = 'disconnected';
67
82
  _robots = [];
68
83
  _robotState = {};
84
+ // Highest `seq` seen on the unordered `pose` channel. Frames that arrive
85
+ // out of order (older seq) are dropped so a late packet can't rewind the
86
+ // live mirror. `null` until the first pose frame.
87
+ _lastPoseSeq = null;
88
+ // When the last pushed pose frame was applied, used to park the periodic
89
+ // `get_state` poll while the stream is live (see POSE_STREAM_FRESH_MS).
90
+ _lastPoseFrameAt = 0;
91
+ // Local refcount of pose-stream consumers (the 3D mirror, the wizard's
92
+ // move-end watcher, ...). The daemon's subscription is a per-peer boolean
93
+ // (not refcounted), so we only send `unsubscribe_pose` once the LAST local
94
+ // consumer releases - otherwise one consumer's cleanup would kill the
95
+ // stream for the others.
96
+ _poseSubRefs = 0;
69
97
  _preselectedRobotId;
70
98
  // ─── Auth ────────────────────────────────────────────────────────────
71
99
  _token = null;
@@ -93,6 +121,8 @@ export class ReachyMini extends EventTarget {
93
121
  _volumeResolve = null;
94
122
  _micVolumeResolve = null;
95
123
  _trackedFaceResolve = null;
124
+ _robotNameResolve = null;
125
+ _deleteHfTokenResolve = null;
96
126
  // applyAudioConfig() / readAudioParameter() share the same single-slot
97
127
  // pattern as the volume helpers. Separate slots so the two can be
98
128
  // in-flight concurrently without collision.
@@ -561,7 +591,35 @@ export class ReachyMini extends EventTarget {
561
591
  }
562
592
  };
563
593
  this._pc.ondatachannel = (e) => {
564
- this._dc = e.channel;
594
+ const ch = e.channel;
595
+ // On `subscribe_pose` the daemon opens a second,
596
+ // unreliable/unordered channel labelled "pose" that *pushes*
597
+ // the robot state at ~30 Hz (see media_server
598
+ // `_setup_pose_channel`), so this can fire mid-session. It
599
+ // carries the same `{state:{...}}` envelope as a get_state
600
+ // reply, so we route it through the same handler - but it
601
+ // must NOT gate session readiness (that's the reliable
602
+ // control channel's job) nor become `_dc` (commands must
603
+ // never ride the lossy channel).
604
+ if (ch.label === 'pose') {
605
+ // Fresh channel (new session or daemon restart): the
606
+ // daemon's seq counter may have reset, so forget the old
607
+ // high-water mark or we'd drop every new frame.
608
+ this._lastPoseSeq = null;
609
+ ch.onmessage = (ev) => {
610
+ const msg = JSON.parse(ev.data);
611
+ // Drop stale/reordered frames (unordered channel).
612
+ if (typeof msg.seq === 'number') {
613
+ if (this._lastPoseSeq !== null && msg.seq <= this._lastPoseSeq)
614
+ return;
615
+ this._lastPoseSeq = msg.seq;
616
+ }
617
+ this._lastPoseFrameAt = Date.now();
618
+ this._handleRobotMessage(msg, true);
619
+ };
620
+ return;
621
+ }
622
+ this._dc = ch;
565
623
  this._dc.onopen = () => {
566
624
  this._dcOpen = true;
567
625
  this._checkSessionReady();
@@ -637,6 +695,14 @@ export class ReachyMini extends EventTarget {
637
695
  this._readAudioParameterResolve(null);
638
696
  this._readAudioParameterResolve = null;
639
697
  }
698
+ if (this._robotNameResolve) {
699
+ this._robotNameResolve(null);
700
+ this._robotNameResolve = null;
701
+ }
702
+ if (this._deleteHfTokenResolve) {
703
+ this._deleteHfTokenResolve(null);
704
+ this._deleteHfTokenResolve = null;
705
+ }
640
706
  this._logSubscribers.clear();
641
707
  this._updateProgressSubscribers.clear();
642
708
  this._rejectPendingMotionCompletions(new Error('Session stopped'));
@@ -717,6 +783,14 @@ export class ReachyMini extends EventTarget {
717
783
  this._readAudioParameterResolve(null);
718
784
  this._readAudioParameterResolve = null;
719
785
  }
786
+ if (this._robotNameResolve) {
787
+ this._robotNameResolve(null);
788
+ this._robotNameResolve = null;
789
+ }
790
+ if (this._deleteHfTokenResolve) {
791
+ this._deleteHfTokenResolve(null);
792
+ this._deleteHfTokenResolve = null;
793
+ }
720
794
  this._logSubscribers.clear();
721
795
  this._updateProgressSubscribers.clear();
722
796
  this._rejectPendingMotionCompletions(new Error('Disconnected'));
@@ -1192,6 +1266,43 @@ export class ReachyMini extends EventTarget {
1192
1266
  setMicrophoneVolume(volume) {
1193
1267
  return this._slotRoundtrip(() => this._micVolumeResolve, (next) => { this._micVolumeResolve = next; }, { type: 'set_microphone_volume', volume: clampVolume(volume) });
1194
1268
  }
1269
+ /**
1270
+ * Query the persisted robot display name. Resolves the stored name,
1271
+ * `null` when none is set / the channel isn't open / the daemon predates
1272
+ * the `get_robot_name` command.
1273
+ */
1274
+ getRobotName() {
1275
+ return this._slotRoundtrip(() => this._robotNameResolve, (next) => { this._robotNameResolve = next; }, { type: 'get_robot_name' });
1276
+ }
1277
+ /**
1278
+ * Set and persist the robot display name on the robot. Resolves with the
1279
+ * stored (trimmed) name, or `null` on error / channel-closed. Applied live
1280
+ * by the daemon (status + central relay + mDNS), so it takes effect right
1281
+ * away without a restart; the persisted name also overrides --robot-name
1282
+ * on the next start.
1283
+ */
1284
+ setRobotName(name) {
1285
+ return this._slotRoundtrip(() => this._robotNameResolve, (next) => { this._robotNameResolve = next; }, { type: 'set_robot_name', name });
1286
+ }
1287
+ /**
1288
+ * Sign this robot out of Hugging Face: asks the daemon to delete its
1289
+ * stored HF token, which de-registers the robot from the central
1290
+ * signaling relay (it disappears from its owner's robot list until it
1291
+ * is set up again). Works over the WebRTC data channel, so it reaches
1292
+ * the robot remotely (no LAN HTTP path required).
1293
+ *
1294
+ * Resolves `true` when the daemon acked success, `false` on a daemon
1295
+ * error, or `null` when no ack arrives before the timeout (e.g. a
1296
+ * daemon that predates the `delete_hf_token` command silently drops
1297
+ * it). Rejects if the data channel isn't open. Note the sign-out
1298
+ * drops the central relay, so the session may tear down right after
1299
+ * the ack - callers should treat a post-call session drop as expected,
1300
+ * and a successful sign-out may surface as `null` if teardown races
1301
+ * ahead of the ack.
1302
+ */
1303
+ signOut() {
1304
+ return this._slotRoundtrip(() => this._deleteHfTokenResolve, (next) => { this._deleteHfTokenResolve = next; }, { type: 'delete_hf_token' });
1305
+ }
1195
1306
  applyAudioConfig(config, { verify = true } = {}) {
1196
1307
  return this._slotRoundtrip(() => this._applyAudioConfigResolve, (next) => { this._applyAudioConfigResolve = next; }, { type: 'apply_audio_config', config, verify }).then((v) => v === true);
1197
1308
  }
@@ -1273,6 +1384,30 @@ export class ReachyMini extends EventTarget {
1273
1384
  requestState() {
1274
1385
  return this._sendCommand({ type: 'get_state' });
1275
1386
  }
1387
+ /**
1388
+ * Ask the daemon to *push* the robot state (~30 Hz) over the dedicated
1389
+ * unreliable/unordered `pose` data channel instead of polling get_state.
1390
+ * Fires `state` events as frames arrive. No-op against an older daemon (no
1391
+ * pose channel) - fall back to `requestState()` polling there.
1392
+ *
1393
+ * Refcounted: pair every `subscribePose()` with exactly one
1394
+ * `unsubscribePose()`. Multiple consumers share a single daemon-side
1395
+ * subscription; the daemon only stops pushing once the last one releases.
1396
+ * If the channel isn't open yet (or the session later reconnects), the
1397
+ * subscription is (re-)asserted from `_checkSessionReady`.
1398
+ */
1399
+ subscribePose() {
1400
+ this._poseSubRefs++;
1401
+ return this._sendCommand({ type: 'subscribe_pose' });
1402
+ }
1403
+ /** Release one pose-stream consumer; sends `unsubscribe_pose` on the last. */
1404
+ unsubscribePose() {
1405
+ if (this._poseSubRefs > 0)
1406
+ this._poseSubRefs--;
1407
+ if (this._poseSubRefs > 0)
1408
+ return true; // still wanted by another consumer
1409
+ return this._sendCommand({ type: 'unsubscribe_pose' });
1410
+ }
1276
1411
  // ─── Audio ───────────────────────────────────────────────────────────
1277
1412
  setAudioMuted(muted) {
1278
1413
  this._audioMuted = muted;
@@ -1653,7 +1788,22 @@ export class ReachyMini extends EventTarget {
1653
1788
  if (this._iceConnected && this._dcOpen && this._sessionResolve) {
1654
1789
  this._state = 'streaming';
1655
1790
  this.requestState();
1656
- this._stateRefreshInterval = setInterval(() => this.requestState(), 500);
1791
+ // Re-assert a pose subscription that was requested before the data
1792
+ // channel was open, or lost on reconnect (a fresh peer starts
1793
+ // unsubscribed on the daemon). Sent raw so it doesn't touch the
1794
+ // local refcount, which already reflects the live consumer count.
1795
+ if (this._poseSubRefs > 0)
1796
+ this._sendCommand({ type: 'subscribe_pose' });
1797
+ // A fresh session has received no pose frame yet, so a timestamp
1798
+ // left over from the previous one must not hold off the poll.
1799
+ this._lastPoseFrameAt = 0;
1800
+ this._stateRefreshInterval = setInterval(() => {
1801
+ // Skip while the pose stream is already feeding state; see
1802
+ // POSE_STREAM_FRESH_MS.
1803
+ if (Date.now() - this._lastPoseFrameAt < POSE_STREAM_FRESH_MS)
1804
+ return;
1805
+ this.requestState();
1806
+ }, 500);
1657
1807
  this._emit('streaming', { sessionId: this._sessionId, robotId: this._selectedRobotId });
1658
1808
  this._sessionResolve();
1659
1809
  this._sessionResolve = null;
@@ -1797,7 +1947,12 @@ export class ReachyMini extends EventTarget {
1797
1947
  this._emit('error', { source: 'webrtc', error: e });
1798
1948
  }
1799
1949
  }
1800
- _handleRobotMessage(data) {
1950
+ /**
1951
+ * @param fromPoseStream Frame came from the pushed `pose` channel rather
1952
+ * than the reliable control channel. Only those may refresh the state
1953
+ * mirror while the stream is live (see the `data.state` branch).
1954
+ */
1955
+ _handleRobotMessage(data, fromPoseStream = false) {
1801
1956
  // JSON-RPC frames (app control surface) are handled separately from
1802
1957
  // the legacy {command|type} robot messages that share this channel.
1803
1958
  if (data.jsonrpc === '2.0') {
@@ -1828,6 +1983,20 @@ export class ReachyMini extends EventTarget {
1828
1983
  }
1829
1984
  return;
1830
1985
  }
1986
+ if (data.command === 'get_robot_name' || data.command === 'set_robot_name') {
1987
+ if (this._robotNameResolve) {
1988
+ this._robotNameResolve(data.status === 'error' ? null : (data.name ?? null));
1989
+ this._robotNameResolve = null;
1990
+ }
1991
+ return;
1992
+ }
1993
+ if (data.command === 'delete_hf_token') {
1994
+ if (this._deleteHfTokenResolve) {
1995
+ this._deleteHfTokenResolve(data.status === 'error' ? false : true);
1996
+ this._deleteHfTokenResolve = null;
1997
+ }
1998
+ return;
1999
+ }
1831
2000
  if (data.command === 'apply_audio_config') {
1832
2001
  if (this._applyAudioConfigResolve) {
1833
2002
  this._applyAudioConfigResolve(data.error ? false : !!data.applied);
@@ -1924,7 +2093,18 @@ export class ReachyMini extends EventTarget {
1924
2093
  }
1925
2094
  return;
1926
2095
  }
1927
- if (data.state) {
2096
+ // Only the stream may write the mirror while the stream is live. The
2097
+ // poll stands down in that case (see POSE_STREAM_FRESH_MS), but it
2098
+ // can't unsend a request already in flight: `get_state` rides the
2099
+ // reliable channel, so its reply queues behind whatever else is on it
2100
+ // - a `upload_move_*` burst, typically - and can land hundreds of ms
2101
+ // after the snapshot it carries. Having no `seq`, it slips past the
2102
+ // stale-frame guard and rewinds every consumer to a pose from before
2103
+ // the upload, until the next pushed frame puts them back. That reads
2104
+ // as a one-frame flick to the pre-move pose right as an animation
2105
+ // starts. Nothing is lost by dropping it: pushed frames carry the same
2106
+ // fields (daemon-side `build_state_dict` feeds both).
2107
+ if (data.state && (fromPoseStream || Date.now() - this._lastPoseFrameAt >= POSE_STREAM_FRESH_MS)) {
1928
2108
  const s = data.state;
1929
2109
  if (s.head_pose)
1930
2110
  this._robotState.head = s.head_pose.flat();