@bridgething/lib 0.1.2

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/bindings/client.d.ts +1904 -0
  4. package/dist/bindings/client.d.ts.map +1 -0
  5. package/dist/bindings/client.js +2 -0
  6. package/dist/bindings/client.js.map +1 -0
  7. package/dist/bindings/gateway.d.ts +1508 -0
  8. package/dist/bindings/gateway.d.ts.map +1 -0
  9. package/dist/bindings/gateway.js +2 -0
  10. package/dist/bindings/gateway.js.map +1 -0
  11. package/dist/bindings/shared.d.ts +1485 -0
  12. package/dist/bindings/shared.d.ts.map +1 -0
  13. package/dist/bindings/shared.js +3 -0
  14. package/dist/bindings/shared.js.map +1 -0
  15. package/dist/bindings/stock.d.ts +14 -0
  16. package/dist/bindings/stock.d.ts.map +1 -0
  17. package/dist/bindings/stock.js +3 -0
  18. package/dist/bindings/stock.js.map +1 -0
  19. package/dist/bindings/wire.d.ts +47 -0
  20. package/dist/bindings/wire.d.ts.map +1 -0
  21. package/dist/bindings/wire.js +3 -0
  22. package/dist/bindings/wire.js.map +1 -0
  23. package/dist/codec.d.ts +66 -0
  24. package/dist/codec.d.ts.map +1 -0
  25. package/dist/codec.js +180 -0
  26. package/dist/codec.js.map +1 -0
  27. package/dist/framing.d.ts +34 -0
  28. package/dist/framing.d.ts.map +1 -0
  29. package/dist/framing.js +69 -0
  30. package/dist/framing.js.map +1 -0
  31. package/dist/index.d.ts +19 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +20 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/logger.d.ts +21 -0
  36. package/dist/logger.d.ts.map +1 -0
  37. package/dist/logger.js +23 -0
  38. package/dist/logger.js.map +1 -0
  39. package/dist/uuid-fields.generated.d.ts +7 -0
  40. package/dist/uuid-fields.generated.d.ts.map +1 -0
  41. package/dist/uuid-fields.generated.js +15 -0
  42. package/dist/uuid-fields.generated.js.map +1 -0
  43. package/dist/uuid.d.ts +6 -0
  44. package/dist/uuid.d.ts.map +1 -0
  45. package/dist/uuid.js +20 -0
  46. package/dist/uuid.js.map +1 -0
  47. package/dist/version.d.ts +2 -0
  48. package/dist/version.d.ts.map +1 -0
  49. package/dist/version.js +3 -0
  50. package/dist/version.js.map +1 -0
  51. package/package.json +87 -0
@@ -0,0 +1,1508 @@
1
+ import type { AcceptCallAction, AncsAuthState, ArtProfile, BridgeThingMeta, BrowseResult, CallEndReason, CommunicationsState, CompanionAuthorityScope, ConfigEntry, DismissReason, DtmfTone, EndCallAction, FavoritesPage, ForwardMessage, GatewayCapabilities, GeoAccuracy, GeoError, HttpHeader, InitiateCallType, ItemKind, ItemRef, LibraryError, LogEntry, LogLevel, LogSource, NetError, NetFetchRequest, NetFetchResponse, NluResolvedIntent, Notification, OtaError, OtaKind, OtaProgress, PhoneCall, PhoneCallService, PhoneState, PlayContext, PlayerState, Position, QueueItem, QueuePosition, RangePart, RangeSpec, RecommendationsResult, RepeatMode, SearchResult, StreamBegin, StreamChunk, StreamEnd, StreamError, TimeInfo, TunnelClosed, TunnelData, TunnelError, VoiceDispatchErrorCode, VoiceDispatchTarget, WebappError, WebappInfo, WsError, WsFrame } from './shared';
2
+ import type { MsgMeta, WireError } from './wire';
3
+ /**
4
+ * Invalidate the daemon-side cached asset for `id`. The companion's
5
+ * escape hatch when it knows an asset it previously served is stale.
6
+ */
7
+ export type AssetClear = {
8
+ id: string;
9
+ };
10
+ /**
11
+ * Typed terminal response for an `AssetRequest`. Small assets arrive
12
+ * inline; larger ones declare a stream whose ref id is the originating
13
+ * request id, with the bytes following as `TransferFragment` events on
14
+ * the bulk lane (so now-playing traffic preempts them between
15
+ * fragments).
16
+ */
17
+ export type AssetGotReply = {
18
+ id: string;
19
+ mime: string | null;
20
+ body: TransferBody;
21
+ };
22
+ /**
23
+ * Domain error response for an `AssetRequest`: the companion does not
24
+ * have the requested asset.
25
+ */
26
+ export type AssetNotFoundReply = {
27
+ id: string;
28
+ };
29
+ export type AssetRequest = {
30
+ id: string;
31
+ requestId: string;
32
+ };
33
+ export type AuthorityClaim = {
34
+ scope: CompanionAuthorityScope;
35
+ appBundle: string | null;
36
+ };
37
+ export type AuthorityRelease = {
38
+ scope: CompanionAuthorityScope;
39
+ };
40
+ export type BridgeToGatewayAssetMsg = {
41
+ event: 'request';
42
+ data: AssetRequest;
43
+ };
44
+ export type BridgeToGatewayAudioMsg = {
45
+ event: 'volumeUp';
46
+ } | {
47
+ event: 'volumeDown';
48
+ } | {
49
+ event: 'setVolume';
50
+ data: SetVolume;
51
+ } | {
52
+ event: 'muteToggle';
53
+ } | {
54
+ event: 'setMute';
55
+ data: SetMute;
56
+ } | {
57
+ event: 'tts';
58
+ data: Tts;
59
+ } | {
60
+ event: 'ttsCancel';
61
+ data: TtsCancel;
62
+ } | {
63
+ event: 'ttsCancelAll';
64
+ } | {
65
+ event: 'earcon';
66
+ data: Earcon;
67
+ };
68
+ export type BridgeToGatewayGeoMsg = {
69
+ event: 'watch';
70
+ data: GeoWatch;
71
+ } | {
72
+ event: 'unwatch';
73
+ } | {
74
+ event: 'getOnce';
75
+ data: GeoGetOnce;
76
+ };
77
+ export type BridgeToGatewayLibraryMsg = {
78
+ event: 'browse';
79
+ data: LibraryBrowseRequest;
80
+ } | {
81
+ event: 'resolveContext';
82
+ data: LibraryResolveContextRequest;
83
+ } | {
84
+ event: 'search';
85
+ data: LibrarySearchRequest;
86
+ } | {
87
+ event: 'recommendations';
88
+ data: LibraryRecommendationsRequest;
89
+ } | {
90
+ event: 'favoritesList';
91
+ data: LibraryFavoritesListRequest;
92
+ } | {
93
+ event: 'favoritesContains';
94
+ data: LibraryFavoritesContainsRequest;
95
+ } | {
96
+ event: 'favoritesToggle';
97
+ data: FavoritesToggle;
98
+ } | {
99
+ event: 'favoritesSet';
100
+ data: FavoritesSet;
101
+ } | {
102
+ event: 'favoritesSetMany';
103
+ data: FavoritesSetMany;
104
+ };
105
+ export type BridgeToGatewayLyricsMsg = {
106
+ event: 'get';
107
+ data: LyricsRequest;
108
+ };
109
+ /**
110
+ * bridgething -> gateway
111
+ * messages from bridgething to the gateway (mobile or desktop app).
112
+ *
113
+ * these messages will pass over bluetooth.
114
+ */
115
+ export type BridgeToGatewayMsg = {
116
+ id: string;
117
+ meta: MsgMeta;
118
+ data: BridgeToGatewayMsgData;
119
+ };
120
+ export type BridgeToGatewayMsgData = {
121
+ type: 'version';
122
+ data: BridgeThingMeta;
123
+ } | {
124
+ type: 'asset';
125
+ data: BridgeToGatewayAssetMsg;
126
+ } | {
127
+ type: 'audio';
128
+ data: BridgeToGatewayAudioMsg;
129
+ } | {
130
+ type: 'geo';
131
+ data: BridgeToGatewayGeoMsg;
132
+ } | {
133
+ type: 'library';
134
+ data: BridgeToGatewayLibraryMsg;
135
+ } | {
136
+ type: 'lyrics';
137
+ data: BridgeToGatewayLyricsMsg;
138
+ } | {
139
+ type: 'net';
140
+ data: BridgeToGatewayNetMsg;
141
+ } | {
142
+ type: 'notifications';
143
+ data: BridgeToGatewayNotificationsMsg;
144
+ } | {
145
+ type: 'phone';
146
+ data: BridgeToGatewayPhoneMsg;
147
+ } | {
148
+ type: 'player';
149
+ data: BridgeToGatewayPlayerMsg;
150
+ } | {
151
+ type: 'system';
152
+ data: BridgeToGatewaySystemMsg;
153
+ } | {
154
+ type: 'transfer';
155
+ data: BridgeToGatewayTransferMsg;
156
+ } | {
157
+ type: 'tunnel';
158
+ data: BridgeToGatewayTunnelMsg;
159
+ } | {
160
+ type: 'voice';
161
+ data: BridgeToGatewayVoiceMsg;
162
+ } | {
163
+ type: 'webapp';
164
+ data: BridgeToGatewayWebappMsg;
165
+ } | {
166
+ type: 'forward';
167
+ data: ForwardMessage;
168
+ } | {
169
+ type: 'error';
170
+ data: WireError;
171
+ } | {
172
+ type: 'ack';
173
+ } | {
174
+ type: 'done';
175
+ };
176
+ export type BridgeToGatewayNetMsg = {
177
+ event: 'fetch';
178
+ data: NetFetchRequestMsg;
179
+ } | {
180
+ event: 'wsOpen';
181
+ data: NetWsOpen;
182
+ } | {
183
+ event: 'wsClose';
184
+ data: NetWsClose;
185
+ } | {
186
+ event: 'wsSend';
187
+ data: NetWsSend;
188
+ } | {
189
+ event: 'streamOpen';
190
+ data: NetStreamOpen;
191
+ } | {
192
+ event: 'streamCancel';
193
+ data: NetStreamCancel;
194
+ };
195
+ export type BridgeToGatewayNotificationsMsg = {
196
+ event: 'invokePositive';
197
+ data: NotificationInvoke;
198
+ } | {
199
+ event: 'invokeNegative';
200
+ data: NotificationInvoke;
201
+ } | {
202
+ event: 'ancsAuthStateChanged';
203
+ data: AncsAuthState;
204
+ };
205
+ export type BridgeToGatewayPhoneMsg = {
206
+ event: 'answer';
207
+ data: PhoneCallAction;
208
+ } | {
209
+ event: 'accept';
210
+ data: PhoneAcceptAction;
211
+ } | {
212
+ event: 'decline';
213
+ data: PhoneCallAction;
214
+ } | {
215
+ event: 'end';
216
+ data: PhoneCallAction;
217
+ } | {
218
+ event: 'endTyped';
219
+ data: PhoneEndAction;
220
+ } | {
221
+ event: 'hold';
222
+ data: PhoneCallAction;
223
+ } | {
224
+ event: 'unhold';
225
+ data: PhoneCallAction;
226
+ } | {
227
+ event: 'initiate';
228
+ data: PhoneInitiateAction;
229
+ } | {
230
+ event: 'swap';
231
+ } | {
232
+ event: 'merge';
233
+ } | {
234
+ event: 'mute';
235
+ data: PhoneMuteAction;
236
+ } | {
237
+ event: 'dtmf';
238
+ data: PhoneDtmfAction;
239
+ } | {
240
+ event: 'stateGet';
241
+ };
242
+ /**
243
+ * Bridge -> gateway player verbs. The companion-side SDK dispatches each
244
+ * to its native player integration (Spotify SDK, Apple Music SDK,
245
+ * MediaSession). Routing for `Play(uri)` is gated on
246
+ * `Capabilities.uri_schemes` - daemon never forwards a URI no
247
+ * connected gateway claims.
248
+ */
249
+ export type BridgeToGatewayPlayerMsg = {
250
+ event: 'play';
251
+ data: PlayUri;
252
+ } | {
253
+ event: 'queue';
254
+ data: QueueUri;
255
+ } | {
256
+ event: 'pause';
257
+ } | {
258
+ event: 'resume';
259
+ } | {
260
+ event: 'skipNext';
261
+ } | {
262
+ event: 'skipPrev';
263
+ } | {
264
+ event: 'skipToIndex';
265
+ data: SkipToIndex;
266
+ } | {
267
+ event: 'seekTo';
268
+ data: SeekTo;
269
+ } | {
270
+ event: 'setShuffle';
271
+ data: SetShuffle;
272
+ } | {
273
+ event: 'setRepeat';
274
+ data: SetRepeat;
275
+ } | {
276
+ event: 'setSpeed';
277
+ data: SetSpeed;
278
+ } | {
279
+ event: 'setCrossfade';
280
+ data: SetCrossfade;
281
+ };
282
+ export type BridgeToGatewaySystemMsg = {
283
+ event: 'otaProgress';
284
+ data: OtaProgress;
285
+ } | {
286
+ event: 'otaError';
287
+ data: OtaError;
288
+ } | {
289
+ event: 'otaBeginAck';
290
+ data: OtaBeginAck;
291
+ } | {
292
+ event: 'otaBeginRejected';
293
+ data: OtaBeginRejected;
294
+ } | {
295
+ event: 'otaAssetRange';
296
+ data: OtaAssetRange;
297
+ } | {
298
+ event: 'otaAssetRangeAbandon';
299
+ data: OtaAssetRangeAbandon;
300
+ } | {
301
+ event: 'deviceNickname';
302
+ data: DeviceNicknameReply;
303
+ } | {
304
+ event: 'deviceNicknameRejected';
305
+ data: DeviceNicknameRejected;
306
+ } | {
307
+ event: 'deviceNicknameChanged';
308
+ data: DeviceNicknameReply;
309
+ } | {
310
+ event: 'logsTailReply';
311
+ data: LogsTailReply;
312
+ } | {
313
+ event: 'logsSubscribeReply';
314
+ data: LogsSubscribeReply;
315
+ } | {
316
+ event: 'logEntry';
317
+ data: LogEntry;
318
+ } | {
319
+ event: 'keepalive';
320
+ data: KeepalivePing;
321
+ };
322
+ export type BridgeToGatewayTransferMsg = {
323
+ event: 'ack';
324
+ data: TransferAck;
325
+ };
326
+ export type BridgeToGatewayTunnelMsg = {
327
+ event: 'open';
328
+ data: TunnelOpen;
329
+ } | {
330
+ event: 'data';
331
+ data: TunnelData;
332
+ } | {
333
+ event: 'close';
334
+ data: TunnelClosed;
335
+ };
336
+ export type BridgeToGatewayVoiceMsg = {
337
+ event: 'streamOpen';
338
+ data: VoiceStreamOpen;
339
+ } | {
340
+ event: 'frame';
341
+ data: VoiceFrame;
342
+ } | {
343
+ event: 'streamClose';
344
+ data: VoiceStreamClose;
345
+ } | {
346
+ event: 'dispatched';
347
+ data: VoiceDispatched;
348
+ } | {
349
+ event: 'dispatchFailed';
350
+ data: VoiceDispatchFailed;
351
+ };
352
+ export type BridgeToGatewayWebappMsg = {
353
+ event: 'webapps';
354
+ data: WebappList;
355
+ } | {
356
+ event: 'active';
357
+ data: WebappActive;
358
+ } | {
359
+ event: 'switched';
360
+ data: WebappActive;
361
+ } | {
362
+ event: 'uninstalled';
363
+ data: WebappActive;
364
+ } | {
365
+ event: 'webappError';
366
+ data: WebappError;
367
+ } | {
368
+ event: 'icon';
369
+ data: WebappIconReply;
370
+ } | {
371
+ event: 'configGet';
372
+ data: WebappConfigGetReply;
373
+ } | {
374
+ event: 'configList';
375
+ data: WebappConfigListReply;
376
+ } | {
377
+ event: 'configAck';
378
+ data: WebappConfigAck;
379
+ } | {
380
+ event: 'webappInstalled';
381
+ data: WebappInfo;
382
+ } | {
383
+ event: 'activeChanged';
384
+ data: WebappActiveChanged;
385
+ };
386
+ export type BrowseReply = {
387
+ result: BrowseResult;
388
+ };
389
+ export type ChromeNavigate = {
390
+ url: string;
391
+ };
392
+ /**
393
+ * Companion-side cellular / call-control snapshot. Announce-on-connect
394
+ * pattern: companion sends an initial `CommunicationsSnapshot` after
395
+ * announce, then re-sends on any field change.
396
+ */
397
+ export type CommunicationsSnapshot = {
398
+ state: CommunicationsState;
399
+ };
400
+ /**
401
+ * Resolved metadata for a single context uri (playlist / album / show /
402
+ * artist), used to populate a stock preset's name + cover art.
403
+ */
404
+ export type ContextResolveReply = {
405
+ name: string | null;
406
+ artworkId: string | null;
407
+ subtitle: string | null;
408
+ };
409
+ /**
410
+ * Domain-error response to `DeviceSetNickname`: nickname rejected at
411
+ * the daemon edge (too long, contains nul, etc).
412
+ */
413
+ export type DeviceNicknameRejected = {
414
+ reason: string;
415
+ };
416
+ /**
417
+ * Current device nickname. Reply to `DeviceGetNickname` and
418
+ * `DeviceSetNickname`, plus the event payload for
419
+ * `DeviceNicknameChanged` broadcasts.
420
+ */
421
+ export type DeviceNicknameReply = {
422
+ nickname: string | null;
423
+ };
424
+ /**
425
+ * Set the device nickname. Empty string clears (treated as None). The
426
+ * daemon broadcasts `DeviceNicknameChanged` to gateway + client peers
427
+ * after writing the KV slot. Length-capped at 64 chars.
428
+ */
429
+ export type DeviceSetNickname = {
430
+ nickname: string;
431
+ };
432
+ /**
433
+ * Play a named earcon from `AudioCapabilities.earcons`. Unknown names
434
+ * surface as `AudioError::EarconNotFound`.
435
+ */
436
+ export type Earcon = {
437
+ name: string;
438
+ };
439
+ /**
440
+ * Fired when the favorited / liked status of an item changes -
441
+ * regardless of whether it was driven by the daemon (FavoritesToggle/Set
442
+ * command) or by the user mutating it on the gateway-side app directly.
443
+ */
444
+ export type FavoriteChanged = {
445
+ uri: string;
446
+ liked: boolean;
447
+ };
448
+ /**
449
+ * Batch favorites-contains reply. `liked` is index-aligned with the
450
+ * request's `uris`.
451
+ */
452
+ export type FavoritesContainsReply = {
453
+ liked: Array<boolean>;
454
+ };
455
+ export type FavoritesListReply = {
456
+ page: FavoritesPage;
457
+ };
458
+ export type FavoritesSet = {
459
+ item: ItemRef;
460
+ liked: boolean;
461
+ };
462
+ /**
463
+ * Bulk favorites mutation. `entries` are independent `FavoritesSet`
464
+ * applications; gateway returns once it has issued each underlying
465
+ * platform call. Per-entry errors are not surfaced - companion logs
466
+ * and best-efforts the rest. Webapps observing partial success listen
467
+ * for `FavoriteChanged` events.
468
+ */
469
+ export type FavoritesSetMany = {
470
+ entries: Array<FavoritesSet>;
471
+ };
472
+ export type FavoritesToggle = {
473
+ item: ItemRef;
474
+ };
475
+ export type GatewayToBridgeAssetMsg = {
476
+ event: 'clear';
477
+ data: AssetClear;
478
+ } | {
479
+ event: 'got';
480
+ data: AssetGotReply;
481
+ } | {
482
+ event: 'notFound';
483
+ data: AssetNotFoundReply;
484
+ };
485
+ export type GatewayToBridgeAudioMsg = {
486
+ event: 'ttsStarted';
487
+ data: TtsStarted;
488
+ } | {
489
+ event: 'ttsEnded';
490
+ data: TtsEnded;
491
+ } | {
492
+ event: 'volumeChanged';
493
+ data: VolumeChanged;
494
+ };
495
+ /**
496
+ * Companion declares per-scope authority. `Release` is the "stop
497
+ * preferring my data for this scope" signal. Non-now-playing claims
498
+ * fall back automatically after `STALE_TIMEOUT`; the now-playing scopes
499
+ * hold until release / disconnect / app-change arbitration.
500
+ */
501
+ export type GatewayToBridgeAuthorityMsg = {
502
+ event: 'claim';
503
+ data: AuthorityClaim;
504
+ } | {
505
+ event: 'release';
506
+ data: AuthorityRelease;
507
+ };
508
+ /**
509
+ * Companion-driven capabilities surface. The companion sends `Announce`
510
+ * immediately on session-up (before any other surface activity) and
511
+ * re-sends on any change. The daemon's PeerTracker flips
512
+ * `companion_active` on receipt and seeds initial snapshots for every
513
+ * surface where the companion is claiming authority.
514
+ */
515
+ export type GatewayToBridgeCapabilitiesMsg = {
516
+ event: 'announce';
517
+ data: GatewayCapabilities;
518
+ };
519
+ export type GatewayToBridgeChromeMsg = {
520
+ event: 'navigate';
521
+ data: ChromeNavigate;
522
+ };
523
+ export type GatewayToBridgeGeoMsg = {
524
+ event: 'position';
525
+ data: Position;
526
+ } | {
527
+ event: 'getOnceReply';
528
+ data: GeoGetOnceReply;
529
+ } | {
530
+ event: 'errorReply';
531
+ data: GeoErrorReply;
532
+ };
533
+ export type GatewayToBridgeLibraryMsg = {
534
+ event: 'browseReply';
535
+ data: BrowseReply;
536
+ } | {
537
+ event: 'contextResolveReply';
538
+ data: ContextResolveReply;
539
+ } | {
540
+ event: 'searchReply';
541
+ data: SearchReply;
542
+ } | {
543
+ event: 'recommendationsReply';
544
+ data: RecommendationsReply;
545
+ } | {
546
+ event: 'favoritesListReply';
547
+ data: FavoritesListReply;
548
+ } | {
549
+ event: 'favoritesContainsReply';
550
+ data: FavoritesContainsReply;
551
+ } | {
552
+ event: 'libraryErrorReply';
553
+ data: LibraryErrorReply;
554
+ } | {
555
+ event: 'favoriteChanged';
556
+ data: FavoriteChanged;
557
+ } | {
558
+ event: 'libraryChanged';
559
+ data: LibraryChanged;
560
+ };
561
+ export type GatewayToBridgeLyricsMsg = {
562
+ event: 'lyricsReply';
563
+ data: LyricsReply;
564
+ } | {
565
+ event: 'lyricsErrorReply';
566
+ data: LyricsErrorReply;
567
+ };
568
+ /**
569
+ * gateway -> bridgething
570
+ * messages from the gateway (mobile or desktop app) to bridgething.
571
+ *
572
+ * these messages will pass over bluetooth.
573
+ */
574
+ export type GatewayToBridgeMsg = {
575
+ id: string;
576
+ meta: MsgMeta;
577
+ data: GatewayToBridgeMsgData;
578
+ };
579
+ export type GatewayToBridgeMsgData = {
580
+ type: 'asset';
581
+ data: GatewayToBridgeAssetMsg;
582
+ } | {
583
+ type: 'audio';
584
+ data: GatewayToBridgeAudioMsg;
585
+ } | {
586
+ type: 'authority';
587
+ data: GatewayToBridgeAuthorityMsg;
588
+ } | {
589
+ type: 'capabilities';
590
+ data: GatewayToBridgeCapabilitiesMsg;
591
+ } | {
592
+ type: 'chrome';
593
+ data: GatewayToBridgeChromeMsg;
594
+ } | {
595
+ type: 'geo';
596
+ data: GatewayToBridgeGeoMsg;
597
+ } | {
598
+ type: 'library';
599
+ data: GatewayToBridgeLibraryMsg;
600
+ } | {
601
+ type: 'lyrics';
602
+ data: GatewayToBridgeLyricsMsg;
603
+ } | {
604
+ type: 'net';
605
+ data: GatewayToBridgeNetMsg;
606
+ } | {
607
+ type: 'notifications';
608
+ data: GatewayToBridgeNotificationsMsg;
609
+ } | {
610
+ type: 'phone';
611
+ data: GatewayToBridgePhoneMsg;
612
+ } | {
613
+ type: 'player';
614
+ data: GatewayToBridgePlayerMsg;
615
+ } | {
616
+ type: 'system';
617
+ data: GatewayToBridgeSystemMsg;
618
+ } | {
619
+ type: 'time';
620
+ data: GatewayToBridgeTimeMsg;
621
+ } | {
622
+ type: 'transfer';
623
+ data: GatewayToBridgeTransferMsg;
624
+ } | {
625
+ type: 'tunnel';
626
+ data: GatewayToBridgeTunnelMsg;
627
+ } | {
628
+ type: 'voice';
629
+ data: GatewayToBridgeVoiceMsg;
630
+ } | {
631
+ type: 'webapp';
632
+ data: GatewayToBridgeWebappMsg;
633
+ } | {
634
+ type: 'error';
635
+ data: WireError;
636
+ };
637
+ export type GatewayToBridgeNetMsg = {
638
+ event: 'fetchReply';
639
+ data: NetFetchReply;
640
+ } | {
641
+ event: 'fetchErrorReply';
642
+ data: NetFetchErrorReply;
643
+ } | {
644
+ event: 'wsOpenReply';
645
+ data: NetWsOpenReply;
646
+ } | {
647
+ event: 'wsErrorReply';
648
+ data: NetWsErrorReply;
649
+ } | {
650
+ event: 'wsMessage';
651
+ data: NetWsMessage;
652
+ } | {
653
+ event: 'wsClosed';
654
+ data: NetWsClosed;
655
+ } | {
656
+ event: 'wsErrorEvent';
657
+ data: NetWsErrorEvent;
658
+ } | {
659
+ event: 'streamBegin';
660
+ data: StreamBegin;
661
+ } | {
662
+ event: 'streamChunk';
663
+ data: StreamChunk;
664
+ } | {
665
+ event: 'streamEnd';
666
+ data: StreamEnd;
667
+ } | {
668
+ event: 'streamError';
669
+ data: StreamError;
670
+ };
671
+ export type GatewayToBridgeNotificationsMsg = {
672
+ event: 'posted';
673
+ data: Notification;
674
+ } | {
675
+ event: 'updated';
676
+ data: Notification;
677
+ } | {
678
+ event: 'removed';
679
+ data: NotificationRemoved;
680
+ };
681
+ export type GatewayToBridgePhoneMsg = {
682
+ event: 'snapshot';
683
+ data: PhoneStateReply;
684
+ } | {
685
+ event: 'communicationsSnapshot';
686
+ data: CommunicationsSnapshot;
687
+ } | {
688
+ event: 'callStarted';
689
+ data: PhoneCall;
690
+ } | {
691
+ event: 'callUpdated';
692
+ data: PhoneCall;
693
+ } | {
694
+ event: 'callEnded';
695
+ data: PhoneCallEnded;
696
+ } | {
697
+ event: 'stateReply';
698
+ data: PhoneStateReply;
699
+ };
700
+ /**
701
+ * Gateway -> bridge player events. The companion is authoritative for
702
+ * now-playing: `Snapshot` carries the full player state and is the sole
703
+ * metadata/playback source (driven by the dealer push). `QueueChanged`
704
+ * carries a full queue replacement when the upcoming list materially
705
+ * changes; the daemon derives the post-advance next from the held
706
+ * snapshot, so a plain advance costs no queue traffic.
707
+ */
708
+ export type GatewayToBridgePlayerMsg = {
709
+ event: 'snapshot';
710
+ data: PlayerState;
711
+ } | {
712
+ event: 'queueChanged';
713
+ data: QueueSnapshot;
714
+ } | {
715
+ event: 'requestSpotifyWake';
716
+ };
717
+ export type GatewayToBridgeSystemMsg = {
718
+ event: 'otaBegin';
719
+ data: OtaBegin;
720
+ } | {
721
+ event: 'otaAbandon';
722
+ data: OtaAbandon;
723
+ } | {
724
+ event: 'otaActivate';
725
+ data: OtaActivate;
726
+ } | {
727
+ event: 'cancelUpdate';
728
+ } | {
729
+ event: 'otaAssetRangeReply';
730
+ data: OtaAssetRangeReply;
731
+ } | {
732
+ event: 'otaAssetRangeRejected';
733
+ data: OtaAssetRangeRejected;
734
+ } | {
735
+ event: 'deviceGetNickname';
736
+ } | {
737
+ event: 'deviceSetNickname';
738
+ data: DeviceSetNickname;
739
+ } | {
740
+ event: 'logsTail';
741
+ data: LogsTail;
742
+ } | {
743
+ event: 'logsSubscribe';
744
+ data: LogsSubscribe;
745
+ } | {
746
+ event: 'logsUnsubscribe';
747
+ data: LogsUnsubscribe;
748
+ } | {
749
+ event: 'keepaliveAck';
750
+ data: KeepaliveAck;
751
+ };
752
+ /**
753
+ * Companion-driven time surface. Companion sends `Snapshot` at announce
754
+ * (announce-on-connect rule for any surface where companion claims
755
+ * authority - Time always seeds) and again on tz / locale / clock-skew
756
+ * changes.
757
+ */
758
+ export type GatewayToBridgeTimeMsg = {
759
+ event: 'snapshot';
760
+ data: TimeInfo;
761
+ };
762
+ export type GatewayToBridgeTransferMsg = {
763
+ event: 'fragment';
764
+ data: TransferFragment;
765
+ } | {
766
+ event: 'abandon';
767
+ data: TransferAbandon;
768
+ };
769
+ export type GatewayToBridgeTunnelMsg = {
770
+ event: 'openReply';
771
+ data: TunnelOpenReply;
772
+ } | {
773
+ event: 'errorReply';
774
+ data: TunnelErrorReply;
775
+ } | {
776
+ event: 'data';
777
+ data: TunnelData;
778
+ } | {
779
+ event: 'closed';
780
+ data: TunnelClosed;
781
+ };
782
+ export type GatewayToBridgeVoiceMsg = {
783
+ event: 'micOpen';
784
+ data: VoiceMicOpen;
785
+ } | {
786
+ event: 'micClose';
787
+ } | {
788
+ event: 'dispatch';
789
+ data: VoiceDispatch;
790
+ };
791
+ export type GatewayToBridgeWebappMsg = {
792
+ event: 'list';
793
+ } | {
794
+ event: 'getActive';
795
+ } | {
796
+ event: 'switchTo';
797
+ data: WebappSwitchTo;
798
+ } | {
799
+ event: 'uninstall';
800
+ data: WebappUninstall;
801
+ } | {
802
+ event: 'icon';
803
+ data: WebappIcon;
804
+ } | {
805
+ event: 'configGet';
806
+ data: WebappConfigGet;
807
+ } | {
808
+ event: 'configList';
809
+ data: WebappConfigList;
810
+ } | {
811
+ event: 'configSet';
812
+ data: WebappConfigSet;
813
+ } | {
814
+ event: 'configDelete';
815
+ data: WebappConfigDelete;
816
+ };
817
+ export type GeoErrorReply = {
818
+ error: GeoError;
819
+ };
820
+ export type GeoGetOnce = {
821
+ accuracy: GeoAccuracy;
822
+ };
823
+ export type GeoGetOnceReply = {
824
+ position: Position;
825
+ };
826
+ /**
827
+ * Bridge -> companion watch forward. The daemon aggregates webapp
828
+ * watches and re-issues this with the most-demanding accuracy +
829
+ * fastest interval. `min_interval_ms = 0` lets the gateway pick.
830
+ */
831
+ export type GeoWatch = {
832
+ accuracy: GeoAccuracy;
833
+ minIntervalMs: number;
834
+ };
835
+ /**
836
+ * Companion's reply to a `BridgeToGatewaySystemMsg::Keepalive`; echoes `seq`.
837
+ */
838
+ export type KeepaliveAck = {
839
+ seq: number;
840
+ };
841
+ /**
842
+ * Periodic liveness probe the daemon sends over the iAP2 EA link.
843
+ */
844
+ export type KeepalivePing = {
845
+ seq: number;
846
+ };
847
+ export type LibraryBrowseRequest = {
848
+ /**
849
+ * Drilldown node id from a prior `BrowseFolder`. `None` means "root".
850
+ */
851
+ nodeId: string | null;
852
+ limit: number;
853
+ offset: number;
854
+ /**
855
+ * Root only: cap on the number of folders returned. `None` returns every folder.
856
+ */
857
+ sections?: number | null;
858
+ /**
859
+ * Root only: preview children per folder. `None` is the gateway default; `0` skips preview
860
+ * hydration entirely and returns a cheap index of node ids, titles, and totals.
861
+ */
862
+ preview?: number | null;
863
+ };
864
+ /**
865
+ * Fired when the user mutates their library on the gateway-side app while
866
+ * connected (a like, a playlist edit) and the change did NOT originate from a
867
+ * daemon command - so the daemon must invalidate any cached browse / home view.
868
+ */
869
+ export type LibraryChanged = {
870
+ scope: LibraryScope;
871
+ };
872
+ export type LibraryErrorReply = {
873
+ error: LibraryError;
874
+ };
875
+ /**
876
+ * Batch "is each of these favorited?" lookup. Mirrors Spotify's
877
+ * `GET /me/tracks/contains` shape. Reply `liked` is index-aligned with
878
+ * the request `uris`.
879
+ */
880
+ export type LibraryFavoritesContainsRequest = {
881
+ uris: Array<string>;
882
+ };
883
+ export type LibraryFavoritesListRequest = {
884
+ limit: number;
885
+ offset: number;
886
+ };
887
+ /**
888
+ * Recommendations seeded by up to 5 items. The daemon caps the seed
889
+ * list at the platform-permissive limit (Spotify hard-caps at 5
890
+ * combined seeds across tracks/artists/genres). Gateway decides how to
891
+ * distribute seeds across its native API surfaces.
892
+ */
893
+ export type LibraryRecommendationsRequest = {
894
+ seeds: Array<ItemRef>;
895
+ kind: ItemKind | null;
896
+ limit: number;
897
+ offset: number;
898
+ };
899
+ /**
900
+ * Resolve a single context uri (playlist / album / show / artist) to its
901
+ * name + cover art. Used to populate a stock preset slot the device only
902
+ * knows by `context_uri`.
903
+ */
904
+ export type LibraryResolveContextRequest = {
905
+ uri: string;
906
+ };
907
+ /**
908
+ * Which slice of the user's library changed, so a consumer can scope a
909
+ * refetch. The daemon invalidates its home cache on any scope; the
910
+ * distinction is informational for richer webapp consumers.
911
+ */
912
+ export type LibraryScope = 'saved' | 'playlists';
913
+ export type LibrarySearchRequest = {
914
+ query: string;
915
+ kinds: Array<ItemKind> | null;
916
+ limit: number;
917
+ offset: number;
918
+ };
919
+ /**
920
+ * Open a streaming daemon-log subscription over the gateway. The daemon
921
+ * returns an opaque token; the companion releases it via `LogsUnsubscribe`.
922
+ * Scoped to the gateway peer - auto-released when the peer disconnects.
923
+ */
924
+ export type LogsSubscribe = {
925
+ source: LogSource;
926
+ levels: Array<LogLevel>;
927
+ filter: string | null;
928
+ };
929
+ /**
930
+ * Reply to a gateway `LogsSubscribe`: the opaque token to pass back to
931
+ * `LogsUnsubscribe`.
932
+ */
933
+ export type LogsSubscribeReply = {
934
+ token: string;
935
+ };
936
+ /**
937
+ * Pull a one-shot batch of recent daemon log entries over the gateway.
938
+ * Mirrors the client `LogsTail`; both feed the same `LogTap` ring.
939
+ */
940
+ export type LogsTail = {
941
+ source: LogSource;
942
+ levels: Array<LogLevel>;
943
+ filter: string | null;
944
+ maxLines: number;
945
+ };
946
+ /**
947
+ * One-shot reply to a gateway `LogsTail`.
948
+ */
949
+ export type LogsTailReply = {
950
+ entries: Array<LogEntry>;
951
+ };
952
+ export type LogsUnsubscribe = {
953
+ token: string;
954
+ };
955
+ export type LyricLine = {
956
+ startMs: number;
957
+ text: string;
958
+ };
959
+ export type Lyrics = {
960
+ synced: Array<LyricLine> | null;
961
+ plain: string | null;
962
+ source: string;
963
+ };
964
+ export type LyricsErrorReply = {
965
+ message: string;
966
+ };
967
+ /**
968
+ * Reply to `LyricsRequest`. `lyrics: None` means the resolver chain ran
969
+ * to completion without a hit (e.g. lrclib 404, no fallback configured)
970
+ * and is distinct from `LyricsErrorReply` which signals a transient
971
+ * failure (network, parse, resolver-internal error).
972
+ */
973
+ export type LyricsReply = {
974
+ lyrics: Lyrics | null;
975
+ };
976
+ export type LyricsRequest = {
977
+ track: TrackIdentity;
978
+ };
979
+ export type NetFetchErrorReply = {
980
+ error: NetError;
981
+ };
982
+ export type NetFetchReply = {
983
+ response: NetFetchResponse;
984
+ };
985
+ export type NetFetchRequestMsg = {
986
+ request: NetFetchRequest;
987
+ };
988
+ export type NetStreamCancel = {
989
+ streamId: string;
990
+ };
991
+ export type NetStreamOpen = {
992
+ streamId: string;
993
+ request: NetFetchRequest;
994
+ };
995
+ export type NetWsClose = {
996
+ connectionId: string;
997
+ code: number | null;
998
+ reason: string | null;
999
+ };
1000
+ export type NetWsClosed = {
1001
+ connectionId: string;
1002
+ code: number;
1003
+ reason: string;
1004
+ };
1005
+ export type NetWsErrorEvent = {
1006
+ connectionId: string;
1007
+ error: WsError;
1008
+ };
1009
+ export type NetWsErrorReply = {
1010
+ error: WsError;
1011
+ };
1012
+ export type NetWsMessage = {
1013
+ connectionId: string;
1014
+ frame: WsFrame;
1015
+ };
1016
+ export type NetWsOpen = {
1017
+ connectionId: string;
1018
+ url: string;
1019
+ protocols: Array<string> | null;
1020
+ headers: Array<HttpHeader> | null;
1021
+ };
1022
+ export type NetWsOpenReply = {
1023
+ acceptedProtocol: string | null;
1024
+ };
1025
+ export type NetWsSend = {
1026
+ connectionId: string;
1027
+ frame: WsFrame;
1028
+ };
1029
+ export type NotificationInvoke = {
1030
+ id: string;
1031
+ };
1032
+ export type NotificationRemoved = {
1033
+ id: string;
1034
+ reason: DismissReason;
1035
+ };
1036
+ /**
1037
+ * Drop the daemon-side partial for `update_id`. After `CancelUpdate`
1038
+ * keeps the partial for resume; `OtaAbandon` is the explicit clean-up
1039
+ * when the companion no longer wants to retry this artifact.
1040
+ */
1041
+ export type OtaAbandon = {
1042
+ updateId: string;
1043
+ };
1044
+ /**
1045
+ * Commit every staged bandaid piece (daemon / hub / stock) as one
1046
+ * transaction, then restart bridgething.service once. Bandaid pushes
1047
+ * (`OtaKind::Daemon`, `OtaKind::BuiltinWebapp`) stage at stream
1048
+ * completion (phase reaches `Writing`/100, the daemon does NOT restart); the
1049
+ * companion sends `OtaActivate` after the final piece to swap them all
1050
+ * live with a single restart. Image OTAs never use this -- they reboot
1051
+ * at write completion.
1052
+ *
1053
+ * `expected` is the set of `update_id`s the companion staged this
1054
+ * batch. The daemon errors the activate if its staged set does not
1055
+ * match exactly, which guards a desync where a daemon crash dropped the
1056
+ * in-memory staged set between staging and activation.
1057
+ */
1058
+ export type OtaActivate = {
1059
+ expected: Array<string>;
1060
+ };
1061
+ /**
1062
+ * Daemon asks the pinned companion to serve byte ranges from an asset
1063
+ * it should have cached (and can refetch from `OtaBegin.update_url_base`
1064
+ * on cache miss). Triggered by an inbound HTTP-Range request from
1065
+ * libswupdate's delta downloader hitting the daemon's loopback proxy.
1066
+ * Range count is bounded daemon-side; companions just serve whatever
1067
+ * arrives.
1068
+ */
1069
+ export type OtaAssetRange = {
1070
+ updateId: string;
1071
+ asset: string;
1072
+ ranges: Array<RangeSpec>;
1073
+ };
1074
+ /**
1075
+ * Daemon-side cancel for an in-flight range request: libcurl gave up
1076
+ * (timeout, OTA failed, daemon is shutting down). Companion stops the
1077
+ * fragment stream for `request_id` and frees any resources it held
1078
+ * open.
1079
+ */
1080
+ export type OtaAssetRangeAbandon = {
1081
+ requestId: string;
1082
+ };
1083
+ /**
1084
+ * Domain-error response to `OtaAssetRange`: the companion can't serve
1085
+ * the requested ranges (asset unknown for this `update_id`, refetch
1086
+ * from `update_url_base` failed, sha mismatch on refetched asset, etc).
1087
+ * The daemon surfaces this to libswupdate as a `502 Bad Gateway` and
1088
+ * the running OTA fails.
1089
+ */
1090
+ export type OtaAssetRangeRejected = {
1091
+ reason: string;
1092
+ };
1093
+ /**
1094
+ * Successful response to `OtaAssetRange`. The companion has the asset
1095
+ * (or refetched it from `update_url_base`) and serves the resolved
1096
+ * ranges in `body`: small results inline, larger ones as a fragment
1097
+ * stream whose offsets are stream-relative (0..sum of part lengths,
1098
+ * parts concatenated in declaration order - the daemon's HTTP-Range
1099
+ * writer maps them to absolute positions via `parts`). `total_size` is
1100
+ * the asset's full byte length (for `Content-Range` totals).
1101
+ */
1102
+ export type OtaAssetRangeReply = {
1103
+ totalSize: number;
1104
+ parts: Array<RangePart>;
1105
+ body: TransferBody;
1106
+ };
1107
+ /**
1108
+ * Companion-initiated OTA: opens or resumes a streaming push of an
1109
+ * update artifact identified by its sha256. The daemon responds with
1110
+ * `OtaBeginAck { resume_from_offset }` (the byte offset the first
1111
+ * `TransferFragment` should start at, 0 for fresh pushes) or
1112
+ * `OtaBeginRejected { reason }`.
1113
+ *
1114
+ * `kind` selects the backend. See `OtaKind`.
1115
+ *
1116
+ * `update_id` is the sha256 of the artifact, hex-encoded. Content-
1117
+ * addressed so resume across daemon restarts and retries-after-failure
1118
+ * both work without companion-side state to track. `transfer.id` is
1119
+ * minted per attempt and only correlates the fragment stream; the
1120
+ * daemon binds it to the `update_id`-keyed partial, so a reconnect
1121
+ * with a fresh transfer id still resumes the same bytes.
1122
+ *
1123
+ * `update_url_base` is image-kind only: the server prefix the companion
1124
+ * may refetch the .zck delta from on cache miss while serving range
1125
+ * requests during the Writing phase. Ignored for non-image kinds.
1126
+ */
1127
+ export type OtaBegin = {
1128
+ kind: OtaKind;
1129
+ updateId: string;
1130
+ updateUrlBase: string | null;
1131
+ transfer: TransferRef;
1132
+ };
1133
+ /**
1134
+ * Successful response to `OtaBegin`. `resume_from_offset` is the byte
1135
+ * offset the first `TransferFragment` should start at: 0 for fresh pushes, or
1136
+ * the daemon's recovered partial length for a resume.
1137
+ */
1138
+ export type OtaBeginAck = {
1139
+ resumeFromOffset: number;
1140
+ };
1141
+ /**
1142
+ * Domain-error response to `OtaBegin`: the daemon refuses to start
1143
+ * or resume this push (already-running OTA, conflicting in-flight
1144
+ * update_id with mismatched size/sha, budget exhausted).
1145
+ */
1146
+ export type OtaBeginRejected = {
1147
+ reason: string;
1148
+ };
1149
+ export type PhoneAcceptAction = {
1150
+ callId: string;
1151
+ action: AcceptCallAction;
1152
+ };
1153
+ export type PhoneCallAction = {
1154
+ callId: string;
1155
+ };
1156
+ export type PhoneCallEnded = {
1157
+ callId: string;
1158
+ reason: CallEndReason;
1159
+ };
1160
+ export type PhoneDtmfAction = {
1161
+ callId: string | null;
1162
+ tone: DtmfTone;
1163
+ };
1164
+ export type PhoneEndAction = {
1165
+ callId: string;
1166
+ action: EndCallAction;
1167
+ };
1168
+ export type PhoneInitiateAction = {
1169
+ kind: InitiateCallType;
1170
+ destinationId: string | null;
1171
+ service: PhoneCallService | null;
1172
+ addressBookId: string | null;
1173
+ };
1174
+ export type PhoneMuteAction = {
1175
+ mute: boolean;
1176
+ };
1177
+ /**
1178
+ * Typed reply payload for `PhoneStateGet` and the unsolicited
1179
+ * announce-time snapshot the companion proactively pushes per the
1180
+ * announce-on-connect rule.
1181
+ */
1182
+ export type PhoneStateReply = {
1183
+ state: PhoneState;
1184
+ };
1185
+ /**
1186
+ * Play a URI on the gateway. `context` lets the gateway honor playlist
1187
+ * / album semantics for skip-next when both sides understand the
1188
+ * scheme. The daemon parses the scheme and only forwards if a
1189
+ * connected gateway claims it; otherwise returns `PlayerError::SchemeUnclaimed`.
1190
+ */
1191
+ export type PlayUri = {
1192
+ uri: string;
1193
+ context: PlayContext | null;
1194
+ };
1195
+ /**
1196
+ * Full queue replacement from the companion. `order` is the upcoming
1197
+ * queue as a list of item uris, current excluded; `items` carries full
1198
+ * metadata for every uri in `order`, so the daemon rebuilds the queue
1199
+ * from the snapshot alone. The companion sends one only when the upcoming
1200
+ * list materially changes (context switch, reorder, add-to-queue), never
1201
+ * on a plain advance - the daemon derives the post-advance next by
1202
+ * locating the now-playing track in the held queue. Both sides drop this
1203
+ * state on disconnect; no deltas, revisions, or resync to track.
1204
+ */
1205
+ export type QueueSnapshot = {
1206
+ order: Array<string>;
1207
+ items: Array<QueueItem>;
1208
+ };
1209
+ export type QueueUri = {
1210
+ uri: string;
1211
+ position: QueuePosition;
1212
+ };
1213
+ export type RecommendationsReply = {
1214
+ result: RecommendationsResult;
1215
+ };
1216
+ export type SearchReply = {
1217
+ result: SearchResult;
1218
+ };
1219
+ export type SeekTo = {
1220
+ positionMs: number;
1221
+ };
1222
+ /**
1223
+ * `duration_ms = None` turns crossfade off; `Some(0)` is also off but
1224
+ * distinguishes intent.
1225
+ */
1226
+ export type SetCrossfade = {
1227
+ durationMs: number | null;
1228
+ };
1229
+ export type SetMute = {
1230
+ muted: boolean;
1231
+ };
1232
+ export type SetRepeat = {
1233
+ mode: RepeatMode;
1234
+ };
1235
+ export type SetShuffle = {
1236
+ on: boolean;
1237
+ };
1238
+ /**
1239
+ * Set absolute playback rate. `1.0` is normal speed; gateways with
1240
+ * limited speed support clamp to their nearest supported value.
1241
+ */
1242
+ export type SetSpeed = {
1243
+ speed: number;
1244
+ };
1245
+ export type SetVolume = {
1246
+ level: number;
1247
+ };
1248
+ export type SkipToIndex = {
1249
+ index: number;
1250
+ };
1251
+ /**
1252
+ * Identifies a track for lyrics lookup. Different resolvers consume
1253
+ * different subsets: lrclib does signature lookup (artist + track +
1254
+ * album + duration), other resolvers may use ISRC or platform-specific
1255
+ * ids. Populate what's available; resolvers ignore the rest.
1256
+ */
1257
+ export type TrackIdentity = {
1258
+ artist: string;
1259
+ track: string;
1260
+ album: string | null;
1261
+ durationMs: number | null;
1262
+ isrc: string | null;
1263
+ };
1264
+ /**
1265
+ * Sender-side abort of an in-flight transfer (source lost the bytes,
1266
+ * upstream fetch failed). The receiver drops the bound sink; partial
1267
+ * disk state is kept for resumable transfers and discarded otherwise.
1268
+ */
1269
+ export type TransferAbandon = {
1270
+ transferId: string;
1271
+ reason: string;
1272
+ };
1273
+ /**
1274
+ * Receiver-side progress for an in-flight fragment stream: cumulative contiguous bytes received.
1275
+ */
1276
+ export type TransferAck = {
1277
+ transferId: string;
1278
+ received: number;
1279
+ };
1280
+ /**
1281
+ * Standard embedding for a byte payload that may or may not warrant a
1282
+ * fragment stream. Senders pick by size: a small payload rides inline
1283
+ * in the carrying message (one frame, no machinery); a large one
1284
+ * declares a stream and fragments follow. Receivers resolve both arms
1285
+ * through one path.
1286
+ */
1287
+ export type TransferBody = {
1288
+ type: 'inline';
1289
+ data: Uint8Array;
1290
+ } | {
1291
+ type: 'stream';
1292
+ data: TransferRef;
1293
+ };
1294
+ /**
1295
+ * One slice of a transfer's bytes. Variable-size and offset-addressed:
1296
+ * fragments are sent in offset order on the transfer's priority lane,
1297
+ * sized by the sender to its preemption budget. Receivers route by
1298
+ * `transfer_id` to the sink bound when the transfer opened.
1299
+ */
1300
+ export type TransferFragment = {
1301
+ transferId: string;
1302
+ offset: number;
1303
+ bytes: Uint8Array;
1304
+ };
1305
+ /**
1306
+ * Handle to a fragment stream, embedded in the typed message that
1307
+ * opens a transfer (a pull reply or a push begin). The bytes travel
1308
+ * out-of-band as `TransferFragment` events keyed by `id`; the
1309
+ * transfer completes when `total_size` bytes have arrived. For pull
1310
+ * replies `id` is the originating request id.
1311
+ */
1312
+ export type TransferRef = {
1313
+ id: string;
1314
+ totalSize: number;
1315
+ sha256: string | null;
1316
+ };
1317
+ /**
1318
+ * Fire-and-forget TTS request. `id` is webapp-assigned (no request
1319
+ * round-trip) and used for cancellation + matching back-to-back
1320
+ * `TtsStarted`/`TtsEnded` events. `voice` selects from
1321
+ * `AudioCapabilities.voices`; `None` uses the gateway's default.
1322
+ */
1323
+ export type Tts = {
1324
+ id: string;
1325
+ text: string;
1326
+ voice: string | null;
1327
+ };
1328
+ export type TtsCancel = {
1329
+ id: string;
1330
+ };
1331
+ /**
1332
+ * Fired when the TTS request finished. `completed` is true when the
1333
+ * full text was spoken; false when preempted, cancelled, or the
1334
+ * companion dropped it.
1335
+ */
1336
+ export type TtsEnded = {
1337
+ id: string;
1338
+ completed: boolean;
1339
+ };
1340
+ /**
1341
+ * Fired when the companion has begun speaking the TTS request with this
1342
+ * id. May arrive after `TtsEnded` is dropped (e.g. companion preempted
1343
+ * before speech started); webapps should treat both as best-effort.
1344
+ */
1345
+ export type TtsStarted = {
1346
+ id: string;
1347
+ };
1348
+ export type TunnelErrorReply = {
1349
+ error: TunnelError;
1350
+ };
1351
+ export type TunnelOpen = {
1352
+ tunnelId: string;
1353
+ host: string;
1354
+ port: number;
1355
+ };
1356
+ export type TunnelOpenReply = Record<symbol, never>;
1357
+ /**
1358
+ * Why the gateway is opening the mic. The daemon currently treats every
1359
+ * reason the same (open and stream); the field is kept so future policy
1360
+ * (hotword vs. assistant routing, VAD timeout per reason) has the shape
1361
+ * it needs.
1362
+ */
1363
+ export type VoiceCaptureReason = 'pushToTalk' | 'assistant' | 'wakeWord';
1364
+ export type VoiceCloseReason = 'endOfSpeech' | 'cancelled' | 'muted' | 'error';
1365
+ /**
1366
+ * The companion has resolved a captured utterance into an NluResolvedIntent
1367
+ * (fast-path or LLM stage on the phone, plus SpotifyResolver decoration on
1368
+ * catalog slots) and is asking the daemon to dispatch. The daemon's
1369
+ * dispatcher picks the target: stock playback, active-webapp forward, or
1370
+ * OPEN_WEBAPP switch. Outcome is broadcast via `BridgeToGatewayVoiceMsg::
1371
+ * Dispatched` / `DispatchFailed`.
1372
+ */
1373
+ export type VoiceDispatch = {
1374
+ resolved: NluResolvedIntent;
1375
+ };
1376
+ /**
1377
+ * Terminal failure for an inbound `VoiceDispatch`. Daemon could not
1378
+ * route the resolved intent; companion presents the appropriate UX.
1379
+ */
1380
+ export type VoiceDispatchFailed = {
1381
+ code: VoiceDispatchErrorCode;
1382
+ intent: string;
1383
+ webappId: string | null;
1384
+ msg: string;
1385
+ };
1386
+ /**
1387
+ * Notification that an inbound `VoiceDispatch` was routed. `target`
1388
+ * describes where the daemon sent it; the daemon's own action surfaces
1389
+ * (Player events, WebappActive changes) are the source of truth for the
1390
+ * effect - this event is purely so the companion can render confirmation
1391
+ * UI without polling state.
1392
+ */
1393
+ export type VoiceDispatched = {
1394
+ target: VoiceDispatchTarget;
1395
+ intent: string;
1396
+ webappId: string | null;
1397
+ };
1398
+ /**
1399
+ * PCM frame format the daemon ships in `Frame` payloads. Voice capture
1400
+ * runs at a fixed format per session; format is announced once on
1401
+ * `StreamOpen` and held constant through `StreamClose`.
1402
+ */
1403
+ export type VoiceFormat = {
1404
+ sampleRateHz: number;
1405
+ channels: number;
1406
+ bitsPerSample: number;
1407
+ };
1408
+ /**
1409
+ * One PCM frame in an active capture session. Sent on the Bulk lane so
1410
+ * it interleaves between Normal-priority traffic. `seq` increments
1411
+ * from 0; gaps mean the daemon dropped frames under backpressure and
1412
+ * the companion should treat them as silence rather than retransmit.
1413
+ */
1414
+ export type VoiceFrame = {
1415
+ streamId: string;
1416
+ seq: number;
1417
+ pcm: Uint8Array;
1418
+ };
1419
+ export type VoiceMicOpen = {
1420
+ reason: VoiceCaptureReason;
1421
+ };
1422
+ export type VoiceStreamClose = {
1423
+ streamId: string;
1424
+ reason: VoiceCloseReason;
1425
+ };
1426
+ /**
1427
+ * Daemon opens a capture session. The companion is expected to begin
1428
+ * consuming `Frame`s with the same `stream_id` until a `StreamClose`
1429
+ * for that id arrives.
1430
+ */
1431
+ export type VoiceStreamOpen = {
1432
+ streamId: string;
1433
+ format: VoiceFormat;
1434
+ };
1435
+ /**
1436
+ * Volume / mute snapshot. Fired on any change to either; webapps treat
1437
+ * `level` as the canonical value.
1438
+ */
1439
+ export type VolumeChanged = {
1440
+ level: number;
1441
+ muted: boolean;
1442
+ };
1443
+ export type WebappActive = {
1444
+ id: string | null;
1445
+ name: string | null;
1446
+ };
1447
+ /**
1448
+ * Event payload for an active-webapp change (any initiator). Distinct from
1449
+ * `WebappActive` (a request response) so it carries the new app's declared
1450
+ * art profile; the companion reads `art` directly to size its pushes.
1451
+ */
1452
+ export type WebappActiveChanged = {
1453
+ id: string | null;
1454
+ name: string | null;
1455
+ art: ArtProfile | null;
1456
+ };
1457
+ /**
1458
+ * Ack for WebappConfigSet / WebappConfigDelete. The `value` field
1459
+ * echoes what's now stored after the write (None for delete).
1460
+ */
1461
+ export type WebappConfigAck = {
1462
+ key: string;
1463
+ value: string | null;
1464
+ };
1465
+ export type WebappConfigDelete = {
1466
+ id: string;
1467
+ key: string;
1468
+ };
1469
+ export type WebappConfigGet = {
1470
+ id: string;
1471
+ key: string;
1472
+ };
1473
+ export type WebappConfigGetReply = {
1474
+ key: string;
1475
+ value: string | null;
1476
+ };
1477
+ export type WebappConfigList = {
1478
+ id: string;
1479
+ };
1480
+ export type WebappConfigListReply = {
1481
+ entries: Array<ConfigEntry>;
1482
+ };
1483
+ export type WebappConfigSet = {
1484
+ id: string;
1485
+ key: string;
1486
+ value: string;
1487
+ };
1488
+ /**
1489
+ * Icon byte fetch. Daemon reads the icon declared by the manifest from
1490
+ * the bundle directory and returns the bytes + mime.
1491
+ */
1492
+ export type WebappIcon = {
1493
+ id: string;
1494
+ };
1495
+ export type WebappIconReply = {
1496
+ bytes: Uint8Array;
1497
+ mime: string | null;
1498
+ };
1499
+ export type WebappList = {
1500
+ webapps: Array<WebappInfo>;
1501
+ };
1502
+ export type WebappSwitchTo = {
1503
+ id: string;
1504
+ };
1505
+ export type WebappUninstall = {
1506
+ id: string;
1507
+ };
1508
+ //# sourceMappingURL=gateway.d.ts.map