@pollen-robotics/reachy-mini-sdk 1.9.0 → 1.10.0-dev.0.main.60dddbe
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/reachy-mini.d.ts +53 -0
- package/dist/lib/reachy-mini.d.ts.map +1 -1
- package/dist/lib/reachy-mini.js +199 -1
- package/dist/lib/reachy-mini.js.map +1 -1
- package/dist/lib/types.d.ts +11 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/host/dist/chunks/{mountHost-DjE5zE9R.js → mountHost-DztGlWwu.js} +21939 -21928
- package/host/dist/chunks/{reachy-mini-CdsdQLIU.js → reachy-mini-DCbCDwyd.js} +227 -88
- package/host/dist/components/ConnectingView.d.ts.map +1 -1
- package/host/dist/components/ErrorView.d.ts.map +1 -1
- package/host/dist/components/LeavingView.d.ts.map +1 -1
- package/host/dist/components/PickerView.d.ts.map +1 -1
- package/host/dist/components/PostOAuthSplash.d.ts.map +1 -1
- package/host/dist/components/TopBar.d.ts.map +1 -1
- package/host/dist/components/WelcomeBackOverlay.d.ts.map +1 -1
- package/host/dist/entry/auto.js +2 -2
- package/host/dist/entry/embed.js +1 -1
- package/host/dist/index.js +2 -2
- package/package.json +3 -3
|
@@ -44,10 +44,15 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
|
|
|
44
44
|
private _volumeResolve;
|
|
45
45
|
private _micVolumeResolve;
|
|
46
46
|
private _trackedFaceResolve;
|
|
47
|
+
private _robotNameResolve;
|
|
48
|
+
private _deleteHfTokenResolve;
|
|
47
49
|
private _applyAudioConfigResolve;
|
|
48
50
|
private _readAudioParameterResolve;
|
|
49
51
|
private readonly _logSubscribers;
|
|
50
52
|
private readonly _updateProgressSubscribers;
|
|
53
|
+
private _rpcCounter;
|
|
54
|
+
private readonly _pendingRpc;
|
|
55
|
+
private readonly _rpcListeners;
|
|
51
56
|
private _broadcastWaiters;
|
|
52
57
|
private _activeMoveUploadId;
|
|
53
58
|
private _activeAudioUploadId;
|
|
@@ -235,6 +240,37 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
|
|
|
235
240
|
setVolume(volume: number): Promise<number | null>;
|
|
236
241
|
getMicrophoneVolume(): Promise<number | null>;
|
|
237
242
|
setMicrophoneVolume(volume: number): Promise<number | null>;
|
|
243
|
+
/**
|
|
244
|
+
* Query the persisted robot display name. Resolves the stored name,
|
|
245
|
+
* `null` when none is set / the channel isn't open / the daemon predates
|
|
246
|
+
* the `get_robot_name` command.
|
|
247
|
+
*/
|
|
248
|
+
getRobotName(): Promise<string | null>;
|
|
249
|
+
/**
|
|
250
|
+
* Set and persist the robot display name on the robot. Resolves with the
|
|
251
|
+
* stored (trimmed) name, or `null` on error / channel-closed. Applied live
|
|
252
|
+
* by the daemon (status + central relay + mDNS), so it takes effect right
|
|
253
|
+
* away without a restart; the persisted name also overrides --robot-name
|
|
254
|
+
* on the next start.
|
|
255
|
+
*/
|
|
256
|
+
setRobotName(name: string): Promise<string | null>;
|
|
257
|
+
/**
|
|
258
|
+
* Sign this robot out of Hugging Face: asks the daemon to delete its
|
|
259
|
+
* stored HF token, which de-registers the robot from the central
|
|
260
|
+
* signaling relay (it disappears from its owner's robot list until it
|
|
261
|
+
* is set up again). Works over the WebRTC data channel, so it reaches
|
|
262
|
+
* the robot remotely (no LAN HTTP path required).
|
|
263
|
+
*
|
|
264
|
+
* Resolves `true` when the daemon acked success, `false` on a daemon
|
|
265
|
+
* error, or `null` when no ack arrives before the timeout (e.g. a
|
|
266
|
+
* daemon that predates the `delete_hf_token` command silently drops
|
|
267
|
+
* it). Rejects if the data channel isn't open. Note the sign-out
|
|
268
|
+
* drops the central relay, so the session may tear down right after
|
|
269
|
+
* the ack - callers should treat a post-call session drop as expected,
|
|
270
|
+
* and a successful sign-out may surface as `null` if teardown races
|
|
271
|
+
* ahead of the ack.
|
|
272
|
+
*/
|
|
273
|
+
signOut(): Promise<boolean | null>;
|
|
238
274
|
applyAudioConfig(config: AudioConfigEntry[], { verify }?: ApplyAudioConfigOptions): Promise<boolean>;
|
|
239
275
|
readAudioParameter(name: string): Promise<number[] | null>;
|
|
240
276
|
/**
|
|
@@ -270,6 +306,23 @@ export declare class ReachyMini extends EventTarget implements ReachyMiniInstanc
|
|
|
270
306
|
private _awaitDataChannelDrain;
|
|
271
307
|
private _sendToServer;
|
|
272
308
|
private _sendCommand;
|
|
309
|
+
/**
|
|
310
|
+
* Call a JSON-RPC method on the robot/app over the DataChannel and await
|
|
311
|
+
* its result. This is the one way to drive an on-robot app (start/stop it
|
|
312
|
+
* via `apps.*`, or drive a running app via its own namespace, e.g.
|
|
313
|
+
* `conversation.say`). Rejects on the JSON-RPC error, a closed channel, or
|
|
314
|
+
* timeout.
|
|
315
|
+
*/
|
|
316
|
+
rpcCall<T = unknown>(method: string, params?: Record<string, unknown>, opts?: {
|
|
317
|
+
timeoutMs?: number;
|
|
318
|
+
}): Promise<T>;
|
|
319
|
+
/**
|
|
320
|
+
* Subscribe to a JSON-RPC notification (one-way event) pushed by the
|
|
321
|
+
* robot/app, e.g. `conversation.turn`. Returns an unsubscribe function.
|
|
322
|
+
*/
|
|
323
|
+
onNotification(method: string, cb: (params: Record<string, unknown>) => void): () => void;
|
|
324
|
+
private _rejectPendingRpc;
|
|
325
|
+
private _handleRpcMessage;
|
|
273
326
|
private _checkSessionReady;
|
|
274
327
|
private _handleSignalingMessage;
|
|
275
328
|
private _handleEndSession;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reachy-mini.d.ts","sourceRoot":"","sources":["../../lib/reachy-mini.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwBH,OAAO,KAAK,EACR,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EAEjB,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,cAAc,EACd,wBAAwB,EAExB,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,UAAU,EAEV,oBAAoB,EACpB,kBAAkB,EACrB,MAAM,YAAY,CAAC;AAmBpB,kEAAkE;AAClE,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,sBAAsB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"reachy-mini.d.ts","sourceRoot":"","sources":["../../lib/reachy-mini.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/reachy-mini.js
CHANGED
|
@@ -40,6 +40,20 @@ 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
|
+
* Fail-open ceiling for a single `_slotRoundtrip` request/response.
|
|
45
|
+
* Every slot command has a strict "one reply per request" contract, so
|
|
46
|
+
* a missing reply means the daemon either never got it or - crucially -
|
|
47
|
+
* predates that command entirely: an older daemon silently drops an
|
|
48
|
+
* unknown `type` and sends nothing back, which would otherwise leave the
|
|
49
|
+
* caller's promise pending forever (e.g. a newer SDK calling a command a
|
|
50
|
+
* 1.8.x daemon doesn't implement). Resolving `null` on timeout maps
|
|
51
|
+
* cleanly onto the "unsupported / failed" value every slot caller already
|
|
52
|
+
* handles. 4 s is comfortably above a WebRTC data-channel round trip on a
|
|
53
|
+
* congested phone link while still failing fast enough that a gated UI
|
|
54
|
+
* doesn't feel hung.
|
|
55
|
+
*/
|
|
56
|
+
const SLOT_ROUNDTRIP_TIMEOUT_MS = 4000;
|
|
43
57
|
export class ReachyMini extends EventTarget {
|
|
44
58
|
// ─── Config ──────────────────────────────────────────────────────────
|
|
45
59
|
_signalingUrl;
|
|
@@ -79,6 +93,8 @@ export class ReachyMini extends EventTarget {
|
|
|
79
93
|
_volumeResolve = null;
|
|
80
94
|
_micVolumeResolve = null;
|
|
81
95
|
_trackedFaceResolve = null;
|
|
96
|
+
_robotNameResolve = null;
|
|
97
|
+
_deleteHfTokenResolve = null;
|
|
82
98
|
// applyAudioConfig() / readAudioParameter() share the same single-slot
|
|
83
99
|
// pattern as the volume helpers. Separate slots so the two can be
|
|
84
100
|
// in-flight concurrently without collision.
|
|
@@ -87,6 +103,13 @@ export class ReachyMini extends EventTarget {
|
|
|
87
103
|
// ─── Log subscribers ─────────────────────────────────────────────────
|
|
88
104
|
_logSubscribers = new Set();
|
|
89
105
|
_updateProgressSubscribers = new Set();
|
|
106
|
+
// ─── JSON-RPC app control (over the same DataChannel) ────────────────
|
|
107
|
+
// rpcCall() sends {jsonrpc,id,method,params} and awaits the matching
|
|
108
|
+
// response; onNotification() subscribes to one-way events (no id) the
|
|
109
|
+
// robot/app pushes (conversation.phase/turn/transcript, ...).
|
|
110
|
+
_rpcCounter = 0;
|
|
111
|
+
_pendingRpc = new Map();
|
|
112
|
+
_rpcListeners = new Map();
|
|
90
113
|
// ─── Broadcast waiters (playMove / playUploadedAudio) ────────────────
|
|
91
114
|
_broadcastWaiters = [];
|
|
92
115
|
// ─── Active upload ids for no-arg cancels ────────────────────────────
|
|
@@ -616,9 +639,18 @@ export class ReachyMini extends EventTarget {
|
|
|
616
639
|
this._readAudioParameterResolve(null);
|
|
617
640
|
this._readAudioParameterResolve = null;
|
|
618
641
|
}
|
|
642
|
+
if (this._robotNameResolve) {
|
|
643
|
+
this._robotNameResolve(null);
|
|
644
|
+
this._robotNameResolve = null;
|
|
645
|
+
}
|
|
646
|
+
if (this._deleteHfTokenResolve) {
|
|
647
|
+
this._deleteHfTokenResolve(null);
|
|
648
|
+
this._deleteHfTokenResolve = null;
|
|
649
|
+
}
|
|
619
650
|
this._logSubscribers.clear();
|
|
620
651
|
this._updateProgressSubscribers.clear();
|
|
621
652
|
this._rejectPendingMotionCompletions(new Error('Session stopped'));
|
|
653
|
+
this._rejectPendingRpc(new Error('Session stopped'));
|
|
622
654
|
// Tear down resilience plumbing BEFORE closing `_pc` so a
|
|
623
655
|
// queued grace callback can't dereference a dead handle.
|
|
624
656
|
this._clearIceGrace();
|
|
@@ -695,6 +727,14 @@ export class ReachyMini extends EventTarget {
|
|
|
695
727
|
this._readAudioParameterResolve(null);
|
|
696
728
|
this._readAudioParameterResolve = null;
|
|
697
729
|
}
|
|
730
|
+
if (this._robotNameResolve) {
|
|
731
|
+
this._robotNameResolve(null);
|
|
732
|
+
this._robotNameResolve = null;
|
|
733
|
+
}
|
|
734
|
+
if (this._deleteHfTokenResolve) {
|
|
735
|
+
this._deleteHfTokenResolve(null);
|
|
736
|
+
this._deleteHfTokenResolve = null;
|
|
737
|
+
}
|
|
698
738
|
this._logSubscribers.clear();
|
|
699
739
|
this._updateProgressSubscribers.clear();
|
|
700
740
|
this._rejectPendingMotionCompletions(new Error('Disconnected'));
|
|
@@ -1170,6 +1210,43 @@ export class ReachyMini extends EventTarget {
|
|
|
1170
1210
|
setMicrophoneVolume(volume) {
|
|
1171
1211
|
return this._slotRoundtrip(() => this._micVolumeResolve, (next) => { this._micVolumeResolve = next; }, { type: 'set_microphone_volume', volume: clampVolume(volume) });
|
|
1172
1212
|
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Query the persisted robot display name. Resolves the stored name,
|
|
1215
|
+
* `null` when none is set / the channel isn't open / the daemon predates
|
|
1216
|
+
* the `get_robot_name` command.
|
|
1217
|
+
*/
|
|
1218
|
+
getRobotName() {
|
|
1219
|
+
return this._slotRoundtrip(() => this._robotNameResolve, (next) => { this._robotNameResolve = next; }, { type: 'get_robot_name' });
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Set and persist the robot display name on the robot. Resolves with the
|
|
1223
|
+
* stored (trimmed) name, or `null` on error / channel-closed. Applied live
|
|
1224
|
+
* by the daemon (status + central relay + mDNS), so it takes effect right
|
|
1225
|
+
* away without a restart; the persisted name also overrides --robot-name
|
|
1226
|
+
* on the next start.
|
|
1227
|
+
*/
|
|
1228
|
+
setRobotName(name) {
|
|
1229
|
+
return this._slotRoundtrip(() => this._robotNameResolve, (next) => { this._robotNameResolve = next; }, { type: 'set_robot_name', name });
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Sign this robot out of Hugging Face: asks the daemon to delete its
|
|
1233
|
+
* stored HF token, which de-registers the robot from the central
|
|
1234
|
+
* signaling relay (it disappears from its owner's robot list until it
|
|
1235
|
+
* is set up again). Works over the WebRTC data channel, so it reaches
|
|
1236
|
+
* the robot remotely (no LAN HTTP path required).
|
|
1237
|
+
*
|
|
1238
|
+
* Resolves `true` when the daemon acked success, `false` on a daemon
|
|
1239
|
+
* error, or `null` when no ack arrives before the timeout (e.g. a
|
|
1240
|
+
* daemon that predates the `delete_hf_token` command silently drops
|
|
1241
|
+
* it). Rejects if the data channel isn't open. Note the sign-out
|
|
1242
|
+
* drops the central relay, so the session may tear down right after
|
|
1243
|
+
* the ack - callers should treat a post-call session drop as expected,
|
|
1244
|
+
* and a successful sign-out may surface as `null` if teardown races
|
|
1245
|
+
* ahead of the ack.
|
|
1246
|
+
*/
|
|
1247
|
+
signOut() {
|
|
1248
|
+
return this._slotRoundtrip(() => this._deleteHfTokenResolve, (next) => { this._deleteHfTokenResolve = next; }, { type: 'delete_hf_token' });
|
|
1249
|
+
}
|
|
1173
1250
|
applyAudioConfig(config, { verify = true } = {}) {
|
|
1174
1251
|
return this._slotRoundtrip(() => this._applyAudioConfigResolve, (next) => { this._applyAudioConfigResolve = next; }, { type: 'apply_audio_config', config, verify }).then((v) => v === true);
|
|
1175
1252
|
}
|
|
@@ -1199,7 +1276,29 @@ export class ReachyMini extends EventTarget {
|
|
|
1199
1276
|
const prev = getSlot();
|
|
1200
1277
|
if (prev)
|
|
1201
1278
|
prev(null);
|
|
1202
|
-
|
|
1279
|
+
let timer;
|
|
1280
|
+
// Single settle path shared by the daemon response, supersession
|
|
1281
|
+
// by a newer call, and the fail-open timeout below. It clears the
|
|
1282
|
+
// timer once and detaches itself from the slot only if it's still
|
|
1283
|
+
// the current occupant, so a stale settle (timed-out or superseded)
|
|
1284
|
+
// can't clear a newer call's slot registration. The message handler
|
|
1285
|
+
// stores `settle` (not `resolve`), so every response route funnels
|
|
1286
|
+
// through here.
|
|
1287
|
+
// Note: slots are keyed by command type, not request id, so this
|
|
1288
|
+
// does not prevent a genuinely late daemon reply from being routed
|
|
1289
|
+
// to a newer same-command caller — that cross-talk is inherent to
|
|
1290
|
+
// the single-flight slot design and unchanged here.
|
|
1291
|
+
const settle = (v) => {
|
|
1292
|
+
if (timer !== undefined) {
|
|
1293
|
+
clearTimeout(timer);
|
|
1294
|
+
timer = undefined;
|
|
1295
|
+
}
|
|
1296
|
+
if (getSlot() === settle)
|
|
1297
|
+
setSlot(null);
|
|
1298
|
+
resolve(v);
|
|
1299
|
+
};
|
|
1300
|
+
setSlot(settle);
|
|
1301
|
+
timer = setTimeout(() => settle(null), SLOT_ROUNDTRIP_TIMEOUT_MS);
|
|
1203
1302
|
this._sendCommand(command);
|
|
1204
1303
|
});
|
|
1205
1304
|
}
|
|
@@ -1526,6 +1625,85 @@ export class ReachyMini extends EventTarget {
|
|
|
1526
1625
|
this._dc.send(JSON.stringify(cmd));
|
|
1527
1626
|
return true;
|
|
1528
1627
|
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Call a JSON-RPC method on the robot/app over the DataChannel and await
|
|
1630
|
+
* its result. This is the one way to drive an on-robot app (start/stop it
|
|
1631
|
+
* via `apps.*`, or drive a running app via its own namespace, e.g.
|
|
1632
|
+
* `conversation.say`). Rejects on the JSON-RPC error, a closed channel, or
|
|
1633
|
+
* timeout.
|
|
1634
|
+
*/
|
|
1635
|
+
rpcCall(method, params = {}, opts = {}) {
|
|
1636
|
+
const timeoutMs = opts.timeoutMs ?? 20000;
|
|
1637
|
+
const id = `rpc-${++this._rpcCounter}`;
|
|
1638
|
+
if (!this._sendCommand({ jsonrpc: '2.0', id, method, params })) {
|
|
1639
|
+
return Promise.reject(new Error(`rpcCall(${method}): data channel not open`));
|
|
1640
|
+
}
|
|
1641
|
+
return new Promise((resolve, reject) => {
|
|
1642
|
+
const timer = setTimeout(() => {
|
|
1643
|
+
this._pendingRpc.delete(id);
|
|
1644
|
+
reject(new Error(`rpcCall(${method}) timed out after ${timeoutMs}ms`));
|
|
1645
|
+
}, timeoutMs);
|
|
1646
|
+
this._pendingRpc.set(id, {
|
|
1647
|
+
resolve: (v) => resolve(v),
|
|
1648
|
+
reject,
|
|
1649
|
+
timer,
|
|
1650
|
+
});
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
/**
|
|
1654
|
+
* Subscribe to a JSON-RPC notification (one-way event) pushed by the
|
|
1655
|
+
* robot/app, e.g. `conversation.turn`. Returns an unsubscribe function.
|
|
1656
|
+
*/
|
|
1657
|
+
onNotification(method, cb) {
|
|
1658
|
+
let set = this._rpcListeners.get(method);
|
|
1659
|
+
if (!set) {
|
|
1660
|
+
set = new Set();
|
|
1661
|
+
this._rpcListeners.set(method, set);
|
|
1662
|
+
}
|
|
1663
|
+
set.add(cb);
|
|
1664
|
+
return () => {
|
|
1665
|
+
this._rpcListeners.get(method)?.delete(cb);
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
_rejectPendingRpc(err) {
|
|
1669
|
+
for (const pending of this._pendingRpc.values()) {
|
|
1670
|
+
clearTimeout(pending.timer);
|
|
1671
|
+
pending.reject(err);
|
|
1672
|
+
}
|
|
1673
|
+
this._pendingRpc.clear();
|
|
1674
|
+
}
|
|
1675
|
+
_handleRpcMessage(data) {
|
|
1676
|
+
// Response to an rpcCall (correlated by id)...
|
|
1677
|
+
if ('id' in data && data.id != null && ('result' in data || 'error' in data)) {
|
|
1678
|
+
const pending = this._pendingRpc.get(data.id);
|
|
1679
|
+
if (!pending)
|
|
1680
|
+
return;
|
|
1681
|
+
this._pendingRpc.delete(data.id);
|
|
1682
|
+
clearTimeout(pending.timer);
|
|
1683
|
+
if ('error' in data && data.error) {
|
|
1684
|
+
const err = data.error;
|
|
1685
|
+
const e = new Error(err.message ?? 'rpc error');
|
|
1686
|
+
e.reason = err.data?.reason;
|
|
1687
|
+
pending.reject(e);
|
|
1688
|
+
}
|
|
1689
|
+
else {
|
|
1690
|
+
pending.resolve(data.result);
|
|
1691
|
+
}
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
// ...or a one-way notification (event): dispatch to listeners.
|
|
1695
|
+
if (typeof data.method === 'string') {
|
|
1696
|
+
const params = data.params ?? {};
|
|
1697
|
+
for (const cb of this._rpcListeners.get(data.method) ?? []) {
|
|
1698
|
+
try {
|
|
1699
|
+
cb(params);
|
|
1700
|
+
}
|
|
1701
|
+
catch (e) {
|
|
1702
|
+
console.error(`onNotification(${data.method}) threw:`, e);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1529
1707
|
_checkSessionReady() {
|
|
1530
1708
|
if (this._iceConnected && this._dcOpen && this._sessionResolve) {
|
|
1531
1709
|
this._state = 'streaming';
|
|
@@ -1675,6 +1853,12 @@ export class ReachyMini extends EventTarget {
|
|
|
1675
1853
|
}
|
|
1676
1854
|
}
|
|
1677
1855
|
_handleRobotMessage(data) {
|
|
1856
|
+
// JSON-RPC frames (app control surface) are handled separately from
|
|
1857
|
+
// the legacy {command|type} robot messages that share this channel.
|
|
1858
|
+
if (data.jsonrpc === '2.0') {
|
|
1859
|
+
this._handleRpcMessage(data);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1678
1862
|
if ('version' in data && this._versionResolve) {
|
|
1679
1863
|
this._versionResolve(data.version);
|
|
1680
1864
|
this._versionResolve = null;
|
|
@@ -1699,6 +1883,20 @@ export class ReachyMini extends EventTarget {
|
|
|
1699
1883
|
}
|
|
1700
1884
|
return;
|
|
1701
1885
|
}
|
|
1886
|
+
if (data.command === 'get_robot_name' || data.command === 'set_robot_name') {
|
|
1887
|
+
if (this._robotNameResolve) {
|
|
1888
|
+
this._robotNameResolve(data.status === 'error' ? null : (data.name ?? null));
|
|
1889
|
+
this._robotNameResolve = null;
|
|
1890
|
+
}
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
if (data.command === 'delete_hf_token') {
|
|
1894
|
+
if (this._deleteHfTokenResolve) {
|
|
1895
|
+
this._deleteHfTokenResolve(data.status === 'error' ? false : true);
|
|
1896
|
+
this._deleteHfTokenResolve = null;
|
|
1897
|
+
}
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1702
1900
|
if (data.command === 'apply_audio_config') {
|
|
1703
1901
|
if (this._applyAudioConfigResolve) {
|
|
1704
1902
|
this._applyAudioConfigResolve(data.error ? false : !!data.applied);
|