@relaymessenger/sdk 0.3.6-staging.3 → 0.3.6-staging.30

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 (70) hide show
  1. package/README.md +490 -20
  2. package/dist/a2ui.d.ts +79 -0
  3. package/dist/a2ui.d.ts.map +1 -0
  4. package/dist/a2ui.js +99 -0
  5. package/dist/a2ui.js.map +1 -0
  6. package/dist/buttons.d.ts +69 -0
  7. package/dist/buttons.d.ts.map +1 -0
  8. package/dist/buttons.js +141 -0
  9. package/dist/buttons.js.map +1 -0
  10. package/dist/calls/call-room.d.ts +110 -0
  11. package/dist/calls/call-room.d.ts.map +1 -0
  12. package/dist/calls/call-room.js +616 -0
  13. package/dist/calls/call-room.js.map +1 -0
  14. package/dist/calls/engine-werift-video.d.ts +70 -0
  15. package/dist/calls/engine-werift-video.d.ts.map +1 -0
  16. package/dist/calls/engine-werift-video.js +594 -0
  17. package/dist/calls/engine-werift-video.js.map +1 -0
  18. package/dist/calls/engine-werift.d.ts +48 -0
  19. package/dist/calls/engine-werift.d.ts.map +1 -0
  20. package/dist/calls/engine-werift.js +457 -0
  21. package/dist/calls/engine-werift.js.map +1 -0
  22. package/dist/calls/index.d.ts +11 -0
  23. package/dist/calls/index.d.ts.map +1 -0
  24. package/dist/calls/index.js +11 -0
  25. package/dist/calls/index.js.map +1 -0
  26. package/dist/calls/transport.d.ts +466 -0
  27. package/dist/calls/transport.d.ts.map +1 -0
  28. package/dist/calls/transport.js +1409 -0
  29. package/dist/calls/transport.js.map +1 -0
  30. package/dist/calls/video-frame.d.ts +56 -0
  31. package/dist/calls/video-frame.d.ts.map +1 -0
  32. package/dist/calls/video-frame.js +245 -0
  33. package/dist/calls/video-frame.js.map +1 -0
  34. package/dist/calls/video-rtp.d.ts +51 -0
  35. package/dist/calls/video-rtp.d.ts.map +1 -0
  36. package/dist/calls/video-rtp.js +294 -0
  37. package/dist/calls/video-rtp.js.map +1 -0
  38. package/dist/calls/video.d.ts +188 -0
  39. package/dist/calls/video.d.ts.map +1 -0
  40. package/dist/calls/video.js +228 -0
  41. package/dist/calls/video.js.map +1 -0
  42. package/dist/client.d.ts +52 -24
  43. package/dist/client.d.ts.map +1 -1
  44. package/dist/client.js +131 -41
  45. package/dist/client.js.map +1 -1
  46. package/dist/index.d.ts +7 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +7 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/links.d.ts +57 -0
  51. package/dist/links.d.ts.map +1 -0
  52. package/dist/links.js +126 -0
  53. package/dist/links.js.map +1 -0
  54. package/dist/operations.d.ts +41 -25
  55. package/dist/operations.d.ts.map +1 -1
  56. package/dist/operations.js +55 -30
  57. package/dist/operations.js.map +1 -1
  58. package/dist/payment.d.ts +67 -0
  59. package/dist/payment.d.ts.map +1 -0
  60. package/dist/payment.js +147 -0
  61. package/dist/payment.js.map +1 -0
  62. package/dist/selection.d.ts +38 -0
  63. package/dist/selection.d.ts.map +1 -0
  64. package/dist/selection.js +132 -0
  65. package/dist/selection.js.map +1 -0
  66. package/dist/types.d.ts +731 -56
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/websocket.d.ts +2 -2
  69. package/dist/websocket.d.ts.map +1 -1
  70. package/package.json +37 -3
package/dist/types.d.ts CHANGED
@@ -11,24 +11,22 @@ export interface CallContact {
11
11
  handle: string;
12
12
  kind: "user" | "agent";
13
13
  }
14
+ export type CallTerminalStatus = "completed" | "no-answer" | "canceled" | "busy" | "failed";
14
15
  export interface Call {
15
16
  id: UUID;
16
17
  chat_id: UUID;
17
18
  from: CallContact;
18
19
  to: [CallContact];
19
- mode: "audio";
20
- status: "ringing" | "connecting" | "active" | "ended";
20
+ /** `ringing` and `in-progress` are live. Terminal states set `ended_at`. */
21
+ status: "ringing" | "in-progress" | CallTerminalStatus;
21
22
  revision: number;
22
23
  created_at: string;
23
24
  ringing_at: string;
24
25
  answered_at: string | null;
25
- connected_at: string | null;
26
26
  ended_at: string | null;
27
- end_reason: "completed" | "declined" | "canceled" | "no_answer" | "disconnected" | "failed" | null;
28
27
  }
29
28
  export interface CallCreateParams {
30
29
  to: [string];
31
- mode: "audio";
32
30
  }
33
31
  export interface CallCreateOptions extends RequestOptions {
34
32
  /** Reuse this key and request after an uncertain response. */
@@ -45,49 +43,291 @@ export interface CallListResponse {
45
43
  export interface CallResponse {
46
44
  call: Call;
47
45
  }
48
- export interface CallAudioFormat {
49
- encoding: "pcm_s16le";
50
- sample_rate: 48000;
51
- channels: 2;
46
+ /** A participant's published local track, named on the SFU. */
47
+ export type CallRoomTrackName = "audio" | "video";
48
+ export interface CallRoomParticipant {
49
+ contact_id: UUID;
50
+ kind: "user" | "agent";
51
+ attached: boolean;
52
+ track: "audio" | null;
53
+ muted: boolean;
54
+ connected: boolean;
55
+ /** Camera sending, from this participant's `userUpdate`. */
56
+ video?: boolean;
57
+ /** Tracks this participant has published: `[]` before its first offer, then `["audio"]` or `["audio", "video"]`. */
58
+ tracks?: CallRoomTrackName[];
59
+ /**
60
+ * The other participant's tracks this participant is receiving now: its
61
+ * pull answer is applied and it sent `connected` for it. Reset on restart.
62
+ */
63
+ receiving?: CallRoomTrackName[];
52
64
  }
53
- export type CallConnectionCreateParams = {
54
- transport: "websocket";
55
- } | {
56
- transport: "webrtc";
65
+ export interface CallRoomJoinFrame {
66
+ type: "join";
67
+ }
68
+ export interface CallRoomPublishOfferFrame {
69
+ type: "offer";
57
70
  session_description: {
58
71
  type: "offer";
59
72
  sdp: string;
60
73
  };
74
+ /** One or two tracks, `audio` first, no duplicate names. */
61
75
  tracks: [{
62
76
  mid: string;
63
- name: "microphone";
77
+ name: "audio";
78
+ }] | [{
79
+ mid: string;
80
+ name: "audio";
81
+ }, {
82
+ mid: string;
83
+ name: "video";
84
+ }] | [{
85
+ mid: string;
86
+ name: "video";
64
87
  }];
65
- };
66
- export interface CallWebSocketConnection {
67
- id: UUID;
68
- call_id: UUID;
69
- transport: "websocket";
70
- url: string;
71
- /** Ephemeral Relay grant, supplied as the media WebSocket bearer token. */
72
- token: string;
73
- expires_at: string;
74
- audio_format: CallAudioFormat;
88
+ /** The previous session is dead: publish on a brand-new session from a new peer connection. */
89
+ restart?: boolean;
75
90
  }
76
- export interface CallWebRTCConnection {
77
- id: UUID;
78
- call_id: UUID;
79
- transport: "webrtc";
91
+ export interface CallRoomAnswerFrame {
92
+ type: "answer";
80
93
  session_description: {
81
94
  type: "answer";
82
95
  sdp: string;
83
96
  };
84
97
  }
85
- export interface CallConnectionResponse {
86
- connection: CallWebSocketConnection | CallWebRTCConnection;
98
+ export interface CallRoomConnectedFrame {
99
+ type: "connected";
100
+ }
101
+ export interface CallRoomUserUpdateFrame {
102
+ type: "userUpdate";
103
+ muted: boolean;
104
+ /** Camera sending. Omitted keeps the last value. */
105
+ video?: boolean;
106
+ }
107
+ export interface CallRoomEndFrame {
108
+ type: "end";
109
+ }
110
+ export interface CallRoomHeartbeatFrame {
111
+ type: "heartbeat";
112
+ }
113
+ export type CallRoomClientFrame = CallRoomJoinFrame | CallRoomPublishOfferFrame | CallRoomAnswerFrame | CallRoomConnectedFrame | CallRoomUserUpdateFrame | CallRoomEndFrame | CallRoomHeartbeatFrame;
114
+ export interface CallRoomStateFrame {
115
+ type: "roomState";
116
+ call: Call;
117
+ participants: [CallRoomParticipant, CallRoomParticipant];
118
+ }
119
+ export interface CallRoomServerAnswerFrame {
120
+ type: "answer";
121
+ session_description: {
122
+ type: "answer";
123
+ sdp: string;
124
+ };
87
125
  }
126
+ export interface CallRoomSubscriptionOfferFrame {
127
+ type: "offer";
128
+ session_description: {
129
+ type: "offer";
130
+ sdp: string;
131
+ };
132
+ /** The other participant's track this renegotiation pulls. */
133
+ track: CallRoomTrackName;
134
+ }
135
+ export interface CallRoomEndedFrame {
136
+ type: "ended";
137
+ reason: CallTerminalStatus;
138
+ }
139
+ export type CallRoomErrorCode = "invalid_frame" | "not_allowed" | "media_unavailable";
140
+ export interface CallRoomErrorFrame {
141
+ type: "error";
142
+ code: CallRoomErrorCode;
143
+ message: string;
144
+ }
145
+ /** Standard `RTCIceServer`: STUN or TURN URLs, with credentials on TURN servers. */
146
+ export interface CallRoomIceServer {
147
+ urls: string[];
148
+ username?: string;
149
+ credential?: string;
150
+ }
151
+ /**
152
+ * STUN and TURN servers for this participant's peer connection, sent after
153
+ * every accepted `join` and before the first `roomState` (Orange Meets shape:
154
+ * Cloudflare TURN credentials minted by the server).
155
+ */
156
+ export interface CallRoomIceServersFrame {
157
+ type: "iceServers";
158
+ ice_servers: CallRoomIceServer[];
159
+ }
160
+ export type CallRoomServerFrame = CallRoomIceServersFrame | CallRoomStateFrame | CallRoomServerAnswerFrame | CallRoomSubscriptionOfferFrame | CallRoomEndedFrame | CallRoomErrorFrame;
88
161
  export type CallWebhookEvent = RelayWebhookEnvelope<CallResponse, "call.created" | "call.updated" | "call.ended">;
162
+ /** Subscription mode only. One coupon or one promotion code from your connected Stripe account, never both. */
163
+ export interface PaymentDiscount {
164
+ /** The id of a coupon on your connected Stripe account. */
165
+ coupon?: string;
166
+ /** The id of a promotion code (`promo_...`), not the code a customer types. */
167
+ promotion_code?: string;
168
+ /** Your own name for the discount, stored and returned with the request. */
169
+ label?: string;
170
+ }
171
+ /**
172
+ * `POST /v1/payment_requests`. Payment mode needs `amount` and `currency`;
173
+ * subscription mode needs `price_id` and takes the currency from the price.
174
+ */
175
+ export interface PaymentRequestCreateParams {
176
+ /** Payment mode: what to charge, in the currency's minor units. */
177
+ amount?: number;
178
+ /** Payment mode: a 3-letter ISO 4217 code, returned lowercase. */
179
+ currency?: string;
180
+ /** The card's title line and the checkout's product name. Trimmed; 1 to 32 characters. */
181
+ description: string;
182
+ category: PaymentCategory;
183
+ /** Up to 49 keys of your own; keys starting with `relay_` are reserved. */
184
+ metadata?: Record<string, string>;
185
+ /** Defaults to `payment`. */
186
+ mode?: PaymentMode;
187
+ /** Subscription mode: an active recurring Price on your connected Stripe account. */
188
+ price_id?: string;
189
+ /** Subscription mode: units of the price. Defaults to 1. */
190
+ quantity?: number;
191
+ /** An existing Customer on your connected Stripe account (`cus_...`). */
192
+ customer_id?: string;
193
+ discount?: PaymentDiscount;
194
+ /** Optional HTTPS product picture; Relay copies it into its own image store. */
195
+ image_url?: string;
196
+ }
197
+ export interface PaymentRequestCreateOptions extends RequestOptions {
198
+ /** Reusing a key with the same body returns the first request (200); with a different body, 409. */
199
+ idempotencyKey?: string;
200
+ }
201
+ /** The ids of the Stripe objects on your connected account. */
202
+ export interface PaymentRequestStripe {
203
+ /** The one PaymentIntent the person pays (`pi_...`). */
204
+ payment_intent_id: string;
205
+ customer_id?: string;
206
+ /** Subscription mode (`sub_...`). */
207
+ subscription_id?: string;
208
+ }
209
+ export interface PaymentRequest {
210
+ id: UUID;
211
+ object: "payment_request";
212
+ status: PaymentStatus;
213
+ mode: PaymentMode;
214
+ /** What the person is charged at checkout, in minor units. */
215
+ amount: number;
216
+ /** Relay's 5% fee in minor units. */
217
+ application_fee_amount: number;
218
+ currency: string;
219
+ description: string;
220
+ category: PaymentCategory;
221
+ /** Relay's pay page for this request. Send it back unchanged in a `payment` part. */
222
+ checkout_url: string;
223
+ /** 23 hours after creation; the request then moves to `expired`. */
224
+ expires_at: string;
225
+ metadata: Record<string, string>;
226
+ image_url?: string;
227
+ price_id?: string;
228
+ quantity?: number;
229
+ interval?: PaymentRecurring["interval"];
230
+ interval_count?: number;
231
+ discount?: PaymentDiscount;
232
+ stripe: PaymentRequestStripe;
233
+ /** Absent until the request succeeds. */
234
+ paid_at?: string;
235
+ created_at: string;
236
+ updated_at: string;
237
+ }
238
+ export interface PaymentRequestListParams {
239
+ cursor?: string;
240
+ /** 1 to 100; defaults to 20. */
241
+ limit?: number;
242
+ status?: PaymentStatus;
243
+ }
244
+ export interface PaymentRequestListResponse {
245
+ payment_requests: PaymentRequest[];
246
+ next_cursor: string | null;
247
+ }
248
+ /** `POST /v1/chats/{chatId}/location/request` answers with this once the request is in the chat. */
249
+ export interface LocationRequestResponse {
250
+ success: true;
251
+ message: "Location request sent";
252
+ }
253
+ /** One person sharing their location with your agent, as a GeoJSON Feature (RFC 7946). */
254
+ export interface LocationFeature {
255
+ type: "Feature";
256
+ geometry: {
257
+ type: "Point";
258
+ /** `[longitude, latitude]`, longitude first. */
259
+ coordinates: [number, number];
260
+ };
261
+ properties: {
262
+ /** Handle of the person sharing. */
263
+ handle: string;
264
+ /** When this position arrived. */
265
+ updated_at: string;
266
+ };
267
+ }
268
+ /**
269
+ * `GET /v1/chats/{chatId}/location`: one Feature per person sharing with your
270
+ * agent in the chat; `features` is empty when nobody is sharing.
271
+ */
272
+ export interface GetChatLocationResponse {
273
+ success: true;
274
+ data: {
275
+ type: "FeatureCollection";
276
+ features: LocationFeature[];
277
+ };
278
+ }
279
+ /** `location.sharing.started`: a person started sharing their location with your agent. */
280
+ export interface LocationSharingStartedEvent {
281
+ /** Handle of the person who started sharing. */
282
+ shared_by: string;
283
+ /** Handle of your agent. */
284
+ shared_with: string;
285
+ chat_id: UUID;
286
+ began_at: string;
287
+ /** When the share ends by itself; null when it has no end. */
288
+ ends_at: string | null;
289
+ }
290
+ /** `location.sharing.stopped`: the person stopped sharing, or the share reached its end. */
291
+ export interface LocationSharingStoppedEvent {
292
+ /** Handle of the person who stopped sharing. */
293
+ shared_by: string;
294
+ /** Handle of your agent. */
295
+ shared_with: string;
296
+ chat_id: UUID;
297
+ began_at: string;
298
+ /** When the share ended. Equals the share's `ends_at` when it ran out. */
299
+ ended_at: string;
300
+ }
301
+ export type LocationSharingStartedWebhookEvent = RelayWebhookEnvelope<LocationSharingStartedEvent, "location.sharing.started">;
302
+ export type LocationSharingStoppedWebhookEvent = RelayWebhookEnvelope<LocationSharingStoppedEvent, "location.sharing.stopped">;
303
+ export type PaymentWebhookEvent = RelayWebhookEnvelope<PaymentRequest, "payment.succeeded" | "payment.canceled" | "payment.expired">;
89
304
  export type DeliveryStatus = "sent" | "delivered" | "read";
90
305
  export type ReactionType = "love" | "like" | "dislike" | "laugh" | "emphasize" | "question" | "custom";
306
+ export interface ChatActivity {
307
+ id: UUID;
308
+ text: string;
309
+ emoji: string | null;
310
+ updated_at: string;
311
+ expires_at: string;
312
+ }
313
+ export interface ChatActivityResponse {
314
+ chat_id: UUID;
315
+ agent_id: UUID;
316
+ version: string;
317
+ activity: ChatActivity | null;
318
+ }
319
+ export interface ChatSetActivityParams {
320
+ /** 1–21 visible characters, at most 1024 UTF-8 bytes. */
321
+ text: string;
322
+ /** One Unicode emoji, or null. */
323
+ emoji?: string | null;
324
+ /** Omit to start/replace; supply the current ID to refresh/update. */
325
+ activity_id?: UUID;
326
+ }
327
+ export interface ChatClearActivityParams {
328
+ /** Clear only this task. A stale or missing activity is a successful no-op. */
329
+ activity_id?: UUID;
330
+ }
91
331
  interface ChatHandleBase {
92
332
  id: UUID;
93
333
  handle: string;
@@ -97,10 +337,12 @@ interface ChatHandleBase {
97
337
  is_me?: boolean | null;
98
338
  display_name: string | null;
99
339
  image_url: string | null;
100
- about: string | null;
340
+ subtitle: string | null;
101
341
  verified: boolean;
102
342
  /** True when the caller holds this Handle as a Contact. */
103
343
  is_contact: boolean;
344
+ activity_version?: string;
345
+ activity?: ChatActivity | null;
104
346
  }
105
347
  export interface UserChatHandle extends ChatHandleBase {
106
348
  kind: "user";
@@ -130,32 +372,346 @@ export interface LinkPart {
130
372
  type: "link";
131
373
  value: string;
132
374
  }
133
- /** One button in a `buttons`. Exactly one of `id` or `url`. */
375
+ /**
376
+ * One button in a `buttons`. A tap on a plain button sends its `label` back
377
+ * as the person's next message: one `text` part whose value is the label,
378
+ * with `reply_to` naming the `buttons` part. A `url` button opens the page
379
+ * in the app and sends nothing.
380
+ */
134
381
  export interface ButtonItem {
135
- /** Callback button: the tap arrives as a `button_reply` carrying this id. */
136
- id?: string;
137
- /** Link button: the tap opens this HTTPS URL and sends nothing. */
382
+ /** Link button: the tap opens this HTTPS URL instead of sending the label. */
138
383
  url?: string;
384
+ /** The button's visible text, 1 to 80 characters, and what a tap sends. */
139
385
  label: string;
140
386
  }
141
387
  /**
142
388
  * Agent-only: a vertical stack of 1 to 5 text-only buttons under the message.
143
- * Only button_reply may target this part; ordinary replies and reactions may not.
389
+ * At most one per message. The only reply it accepts is a tap; reactions may
390
+ * not target it.
144
391
  */
145
392
  export interface ButtonsPart {
146
393
  type: "buttons";
147
394
  items: ButtonItem[];
148
395
  }
396
+ /** Stable machine value and independently editable visible label. */
397
+ export interface SelectionOption {
398
+ /** Unique case-sensitive ASCII token, 1–100 characters. Never derived from label. */
399
+ value: string;
400
+ /** Trimmed visible label, 1–80 characters. */
401
+ label: string;
402
+ }
403
+ /** Agent-only, 1–25 options; requires nonblank text and cannot mix with buttons. */
404
+ export interface SelectionPart {
405
+ type: "selection";
406
+ /** The text is the prompt's title; the person checks any number of options and submits them once, and checking sends nothing. */
407
+ options: SelectionOption[];
408
+ }
409
+ export interface SelectionPartResponse extends SelectionPart {
410
+ /** Durable response state for this viewer across devices. Existing Chat rules allow at most one human user; only that user can respond, once; reopening an answered selection shows what they chose without letting them change it. */
411
+ readonly has_responded: boolean;
412
+ /** The values the authenticated viewer chose, in source-option order, identical on every one of that user's devices; null until the viewer answers, when the answer Message no longer exists, and always for an agent viewer. */
413
+ readonly selected_values: string[] | null;
414
+ reactions: null;
415
+ }
416
+ /**
417
+ * User-only metadata after canonical text (literal '• ' + each source
418
+ * label, joined with '\n'), with explicit reply_to. Exact legacy comma-joined
419
+ * labels are accepted by the server only for compatibility, never parsed for IDs.
420
+ */
421
+ export interface SelectionResponsePart {
422
+ type: "selection_response";
423
+ /**
424
+ * Unique known values, nonempty and in source-option order, authoritative with
425
+ * reply_to. New preceding text is literal '• ' + each source label joined with
426
+ * '\n'. The server accepts exact legacy comma-joined labels for compatibility
427
+ * only, never arbitrary label parsing. iOS may draw a checkmark in place of
428
+ * each bullet and repeat the prompt's title, as presentation only; portable
429
+ * text remains bullets.
430
+ */
431
+ selected_values: string[];
432
+ }
433
+ /** Metadata only: contributes no visible fallback text. */
434
+ export interface SelectionResponsePartResponse extends SelectionResponsePart {
435
+ }
436
+ /** What is being paid for (PayPal Orders v2 `items[].category`); App Store rules decide where each is payable. */
437
+ export type PaymentCategory = "physical_goods" | "digital_goods" | "donation";
438
+ /** A payment request's lifecycle. It leaves `requested` exactly once, only on Stripe's word or your cancel. */
439
+ export type PaymentStatus = "requested" | "succeeded" | "canceled" | "expired";
440
+ /** `payment` collects one charge; `subscription` starts a Stripe subscription from a recurring price. */
441
+ export type PaymentMode = "payment" | "subscription";
442
+ /** A subscription's renewal cadence, read from its Stripe Price. */
443
+ export interface PaymentRecurring {
444
+ interval: "day" | "week" | "month" | "year";
445
+ /** Intervals per renewal (3 with `month` is quarterly). */
446
+ interval_count: number;
447
+ }
448
+ /**
449
+ * A request to pay, drawn as a card. `checkout_url` is the only field: pass
450
+ * back exactly what `paymentRequests.create` returned. The card's amount and
451
+ * title are read from that request, never from the message. Sent only by the
452
+ * agent that created the request, while it is `requested`; it must be the only
453
+ * part of its message.
454
+ */
455
+ export interface PaymentPart {
456
+ type: "payment";
457
+ /** At most 2048 characters. */
458
+ checkout_url: string;
459
+ }
460
+ /** A payment card as every reader sees it, read from the payment request. `status` changes in place. */
461
+ export interface PaymentPartResponse {
462
+ type: "payment";
463
+ payment_request_id: UUID;
464
+ checkout_url: string;
465
+ /** Minor units. For a subscription, what the first period costs. */
466
+ amount: number;
467
+ currency: string;
468
+ /** The card's title line. */
469
+ description: string;
470
+ category: PaymentCategory;
471
+ mode: PaymentMode;
472
+ recurring?: PaymentRecurring;
473
+ /** The request's product picture, when it has one. */
474
+ image_url?: string;
475
+ status: PaymentStatus;
476
+ /** Only a person can react to a payment. */
477
+ reactions: Reaction[] | null;
478
+ }
479
+ /**
480
+ * The payer's receipt: Relay adds one message from the person who paid, a
481
+ * reply to the `payment` card, when a request succeeds. It arrives as
482
+ * `message.received`. Only Relay writes this part.
483
+ */
484
+ export interface PaymentReceiptPartResponse {
485
+ type: "payment_receipt";
486
+ payment_request_id: UUID;
487
+ description: string;
488
+ /** What was paid, in minor units. For a subscription, what the first period cost. */
489
+ amount: number;
490
+ currency: string;
491
+ mode: PaymentMode;
492
+ recurring?: PaymentRecurring;
493
+ reactions: Reaction[] | null;
494
+ }
495
+ /**
496
+ * An agent's request for the person's location, sent with
497
+ * `chats.location.request`. It cannot be sent as a message part. A client that
498
+ * does not draw it shows the Message's text, "<agent display name> requested
499
+ * your location".
500
+ */
501
+ export interface LocationRequestPartResponse {
502
+ type: "location_request";
503
+ reactions: Reaction[] | null;
504
+ }
505
+ /**
506
+ * A person's location share, the card the person's app draws. It carries the
507
+ * share's state, never its position: read the position with
508
+ * `chats.location.retrieve`. It cannot be sent as a message part. A share whose
509
+ * `ends_at` has passed reads as `ended` with `ended_at` equal to `ends_at`.
510
+ */
511
+ export interface LocationPartResponse {
512
+ type: "location";
513
+ state: "live" | "ended";
514
+ began_at: string | null;
515
+ /** When the share ends by itself; null when it has no end. */
516
+ ends_at: string | null;
517
+ ended_at: string | null;
518
+ reactions: Reaction[] | null;
519
+ }
520
+ /**
521
+ * A place sent once: a person's current location, a dropped pin, or a place an
522
+ * agent names (Relay-Server contract `PlacePart`; WhatsApp Cloud API's location
523
+ * fields). `name` and `address` are 1 to 256 characters after trimming.
524
+ */
525
+ export interface PlacePart {
526
+ type: "place";
527
+ /** Latitude in degrees (WGS 84), -90 to 90. */
528
+ latitude: number;
529
+ /** Longitude in degrees (WGS 84), -180 to 180. */
530
+ longitude: number;
531
+ name?: string;
532
+ address?: string;
533
+ }
534
+ /** A place as its sender sent it; `name` and `address` are absent when left out. */
535
+ export interface PlacePartResponse extends PlacePart {
536
+ reactions: Reaction[] | null;
537
+ }
149
538
  /**
150
- * A user's tap on a `buttons` item. Must be the only part, and
151
- * `reply_to` must name the message and part index of the `buttons`.
539
+ * A2UI v0.9.1 (https://a2ui.org), the messages a card is made of. The shapes
540
+ * are A2UI's own JSON schemas (`specification/v0_9_1/json/*.json` in
541
+ * google/A2UI): `server_to_client.json` for what an agent sends to draw a
542
+ * card, `client_to_server.json` for a tap (`action`) and an `error`. The
543
+ * version enum is A2UI's (`v0.9` or `v0.9.1`); Relay's contract names v0.9.1.
152
544
  */
153
- export interface ButtonReplyPart {
154
- type: "button_reply";
545
+ export type A2uiVersion = "v0.9" | "v0.9.1";
546
+ /**
547
+ * One component of a surface: `id`, the catalog's `component` name, and that
548
+ * component's own properties, for example
549
+ * `{ id: "title", component: "Text", text: "Lakers win tonight?" }`. The
550
+ * catalog named by `createSurface.catalogId` defines them: Relay refuses a
551
+ * component, property or value that catalog does not define.
552
+ */
553
+ export interface A2uiComponent {
155
554
  id: string;
156
- label: string;
555
+ component: string;
556
+ [property: string]: unknown;
557
+ }
558
+ /** A2UI `createSurface`: starts a surface drawn by the Message that carries it. */
559
+ export interface A2uiCreateSurfaceMessage {
560
+ version: A2uiVersion;
561
+ createSurface: {
562
+ surfaceId: string;
563
+ /** A catalog Relay draws; see `A2uiClientCapabilities`. */
564
+ catalogId: string;
565
+ /** Theme values the catalog defines, for example `{ primaryColor: "#FF0000" }`. */
566
+ theme?: Record<string, unknown>;
567
+ /** When true, every tap on the surface carries the surface's data model in `metadata.a2uiClientDataModel`. */
568
+ sendDataModel?: boolean;
569
+ };
570
+ }
571
+ /** A2UI `updateComponents`: adds or replaces components by `id`. A surface's first update holds the component with the id `root`. */
572
+ export interface A2uiUpdateComponentsMessage {
573
+ version: A2uiVersion;
574
+ updateComponents: {
575
+ surfaceId: string;
576
+ components: A2uiComponent[];
577
+ };
157
578
  }
158
- export type MessagePart = TextPart | MediaPart | LinkPart | ButtonsPart | ButtonReplyPart;
579
+ /**
580
+ * A2UI `updateDataModel`: replaces (or creates) the value at `path`, a JSON
581
+ * Pointer; no `path`, or `/`, is the whole data model. No `value` removes the
582
+ * key at `path`.
583
+ */
584
+ export interface A2uiUpdateDataModelMessage {
585
+ version: A2uiVersion;
586
+ updateDataModel: {
587
+ surfaceId: string;
588
+ path?: string;
589
+ value?: unknown;
590
+ };
591
+ }
592
+ /** A2UI `deleteSurface`: removes the surface for everyone. */
593
+ export interface A2uiDeleteSurfaceMessage {
594
+ version: A2uiVersion;
595
+ deleteSurface: {
596
+ surfaceId: string;
597
+ };
598
+ }
599
+ /** What an agent sends to draw, change or remove a card (A2UI `server_to_client.json`). */
600
+ export type A2uiServerToClientMessage = A2uiCreateSurfaceMessage | A2uiUpdateComponentsMessage | A2uiUpdateDataModelMessage | A2uiDeleteSurfaceMessage;
601
+ /** The body of an A2UI `action` message: a tap on a Button. */
602
+ export interface A2uiAction {
603
+ /** The Button's `action.event.name`. */
604
+ name: string;
605
+ surfaceId: string;
606
+ /** The `id` of the Button that was tapped. */
607
+ sourceComponentId: string;
608
+ /** ISO 8601 time of the tap. */
609
+ timestamp: string;
610
+ /** The Button's `action.event.context`, with every data binding resolved. */
611
+ context: Record<string, unknown>;
612
+ }
613
+ /** A2UI `action`: a person (or an agent) tapped a Button on a surface. */
614
+ export interface A2uiActionMessage {
615
+ version: A2uiVersion;
616
+ action: A2uiAction;
617
+ }
618
+ /** A2UI's validation error: `path` is a JSON Pointer to the field that failed. */
619
+ export interface A2uiValidationError {
620
+ code: "VALIDATION_FAILED";
621
+ surfaceId: string;
622
+ path: string;
623
+ message: string;
624
+ }
625
+ /** A2UI's generic error: any other `code`. */
626
+ export interface A2uiGenericError {
627
+ code: string;
628
+ surfaceId: string;
629
+ message: string;
630
+ [property: string]: unknown;
631
+ }
632
+ /** A2UI `error`: a renderer (or an agent) reports that it could not use a message. */
633
+ export interface A2uiErrorMessage {
634
+ version: A2uiVersion;
635
+ error: A2uiValidationError | A2uiGenericError;
636
+ }
637
+ /**
638
+ * A2UI's `error` message in its validation format, as Relay writes it for a
639
+ * message it did not apply. `surfaceId` is empty when the message named none;
640
+ * `path` points inside the failing message's body, as in A2UI's own example
641
+ * `/components/0/text`, and is empty when the whole message is at fault.
642
+ */
643
+ export interface A2uiValidationErrorMessage {
644
+ version: "v0.9.1";
645
+ error: A2uiValidationError;
646
+ }
647
+ /** One A2UI message of a send that Relay did not apply, where it sits in the request, and A2UI's `error` message for it. */
648
+ export interface A2uiFailure {
649
+ /** The data part's index in `parts`; null when the fault is in `metadata.a2uiClientDataModel`. */
650
+ part_index: number | null;
651
+ /** The message's index in that part's `data`; null when the part itself, or the metadata, is at fault. */
652
+ data_index: number | null;
653
+ a2ui_message: A2uiValidationErrorMessage;
654
+ }
655
+ /** What a renderer sends back (A2UI `client_to_server.json`). */
656
+ export type A2uiClientToServerMessage = A2uiActionMessage | A2uiErrorMessage;
657
+ /** Any A2UI v0.9.1 message a data part may carry. */
658
+ export type A2uiMessage = A2uiServerToClientMessage | A2uiClientToServerMessage;
659
+ /**
660
+ * A data part holding A2UI v0.9.1 messages, in order: Relay's REST shape of
661
+ * A2A's DataPart. A Message may carry any number of data parts beside its
662
+ * other parts. Relay applies each A2UI message on its own, checked against
663
+ * A2UI's schemas and the surface's catalog: the ones that fail come back in
664
+ * the response's `a2ui_errors`, and a send that applies nothing is refused
665
+ * (404, 409 or 422) with `a2ui_errors` in the error body. Only an agent sends
666
+ * `createSurface`, `updateComponents`, `updateDataModel` and `deleteSurface`;
667
+ * a send that only changes an earlier card adds no Message and returns that
668
+ * card. An `action` or `error` reaches only its sender and the agent that
669
+ * created the surface it names.
670
+ */
671
+ export interface DataPart {
672
+ type: "data";
673
+ media_type: "application/a2ui+json";
674
+ data: A2uiMessage[];
675
+ }
676
+ /**
677
+ * A data part as a reader receives it: the `action` and `error` messages it
678
+ * carried, as sent, when the reader sent them or created the surface they
679
+ * name; then, for each surface it created, every A2UI message accepted for
680
+ * that surface since, in order. Replay the list to draw the card.
681
+ */
682
+ export interface DataPartResponse extends DataPart {
683
+ reactions: Reaction[] | null;
684
+ }
685
+ /** A2UI's `a2uiClientDataModel` (`client_data_model.json`): each surface's data model, by surface id. */
686
+ export interface A2uiClientDataModel {
687
+ version: A2uiVersion;
688
+ surfaces: Record<string, Record<string, unknown>>;
689
+ }
690
+ /**
691
+ * A2UI's `a2uiClientCapabilities` (`client_capabilities.json`, keyed by the
692
+ * protocol family `v0.9`): the catalogs Relay's app draws, in order of
693
+ * preference. Relay's catalog (`RELAY_A2UI_CATALOG_ID`) is every basic catalog
694
+ * component and function plus `PaymentRequest`.
695
+ */
696
+ export interface A2uiClientCapabilities {
697
+ "v0.9": {
698
+ supportedCatalogIds: string[];
699
+ inlineCatalogs?: Array<Record<string, unknown>>;
700
+ };
701
+ }
702
+ /**
703
+ * A2A Message metadata. A tap on a surface that set `sendDataModel` carries
704
+ * `a2uiClientDataModel`. Each surface's data model reaches only the sender and
705
+ * the agent that created that surface, unchanged.
706
+ */
707
+ export interface MessageMetadata {
708
+ a2uiClientDataModel?: A2uiClientDataModel;
709
+ }
710
+ /** The metadata on every `message.received`: the reader's A2UI catalogs, and the sender's data model for the surfaces this agent created, when it sent one. */
711
+ export interface MessageReceivedMetadata extends MessageMetadata {
712
+ a2uiClientCapabilities: A2uiClientCapabilities;
713
+ }
714
+ export type MessagePart = TextPart | MediaPart | LinkPart | ButtonsPart | SelectionPart | SelectionResponsePart | PaymentPart | DataPart | PlacePart;
159
715
  export interface TextPartResponse extends TextPart {
160
716
  mentions?: Array<{
161
717
  id: string;
@@ -187,9 +743,6 @@ export interface LinkPartResponse extends LinkPart {
187
743
  export interface ButtonsPartResponse extends ButtonsPart {
188
744
  reactions: Reaction[] | null;
189
745
  }
190
- export interface ButtonReplyPartResponse extends ButtonReplyPart {
191
- reactions: Reaction[] | null;
192
- }
193
746
  export interface SystemEventParty {
194
747
  id: UUID;
195
748
  handle: string;
@@ -200,7 +753,16 @@ export interface TypingIndicatorWebhookData {
200
753
  chat_id: UUID;
201
754
  contact: TypingContact;
202
755
  }
203
- export type SystemEventType = "chat_created" | "participant_added" | "participant_removed" | "group_name_updated" | "group_icon_updated" | "contact_card_shared";
756
+ export type SystemEventType = "chat_created" | "participant_added" | "participant_removed" | "group_name_updated" | "group_icon_updated" | "contact_card_shared" | "call";
757
+ export interface CallMarker {
758
+ id: UUID;
759
+ status: Call["status"];
760
+ answered_at: string | null;
761
+ ended_at: string | null;
762
+ from: CallContact;
763
+ to: [CallContact];
764
+ duration_seconds: number | null;
765
+ }
204
766
  export interface SystemEvent {
205
767
  type: SystemEventType;
206
768
  actor: SystemEventParty;
@@ -208,15 +770,17 @@ export interface SystemEvent {
208
770
  value: string | null;
209
771
  icon_attachment_id: UUID | null;
210
772
  contact_card: ContactCardItem | null;
773
+ call: CallMarker | null;
211
774
  }
212
775
  export interface SystemPartResponse {
213
776
  type: "system";
214
777
  value: string;
215
778
  reactions: null;
216
779
  }
217
- export type MessagePartResponse = TextPartResponse | MediaPartResponse | LinkPartResponse | ButtonsPartResponse | ButtonReplyPartResponse | SystemPartResponse;
218
- /** Ordinary replies target text, media, link, or button_reply, never buttons or system.
219
- * A button_reply instead targets the originating buttons part. */
780
+ export type MessagePartResponse = TextPartResponse | MediaPartResponse | LinkPartResponse | ButtonsPartResponse | SelectionPartResponse | SelectionResponsePartResponse | PaymentPartResponse | PaymentReceiptPartResponse | DataPartResponse | LocationRequestPartResponse | LocationPartResponse | PlacePartResponse | SystemPartResponse;
781
+ /** Ordinary replies target text, media, or link, never system. A buttons part
782
+ * accepts only a tap: one text part equal to one of its plain labels. A selection
783
+ * requires explicit part_index and exactly text then selection_response metadata. */
220
784
  export interface ReplyTo {
221
785
  message_id: UUID;
222
786
  part_index?: number;
@@ -224,6 +788,11 @@ export interface ReplyTo {
224
788
  export interface MessageContent {
225
789
  parts: MessagePart[];
226
790
  reply_to?: ReplyTo;
791
+ /**
792
+ * A2A Message metadata. A tap (an A2UI `action`) on a surface that set
793
+ * `sendDataModel` must carry `a2uiClientDataModel`.
794
+ */
795
+ metadata?: MessageMetadata;
227
796
  idempotency_key?: string;
228
797
  /**
229
798
  * Send the Message with no banner and no sound on the recipient's device.
@@ -234,7 +803,7 @@ export interface MessageContent {
234
803
  }
235
804
  /**
236
805
  * The Message a send returns. A send never produces a system Message, so its
237
- * parts are only text, media, link, buttons or button_reply, and it carries no `system_event`.
806
+ * parts exclude system parts, and it carries no `system_event`.
238
807
  * `is_system_message` is on the wire and is always `false` here; the contract's
239
808
  * `SentMessage` does not declare it yet.
240
809
  * Read paths (`chats.messages.list`, `messages.listMessagesThread`) return
@@ -242,7 +811,8 @@ export interface MessageContent {
242
811
  */
243
812
  export interface SentMessage {
244
813
  id: UUID;
245
- parts: Array<TextPartResponse | MediaPartResponse | LinkPartResponse | ButtonsPartResponse | ButtonReplyPartResponse>;
814
+ parts: Array<TextPartResponse | MediaPartResponse | LinkPartResponse | ButtonsPartResponse | SelectionPartResponse | SelectionResponsePartResponse | PaymentPartResponse | PaymentReceiptPartResponse | DataPartResponse | LocationRequestPartResponse | LocationPartResponse | PlacePartResponse>;
815
+ metadata?: MessageMetadata;
246
816
  created_at: string;
247
817
  sent_at: string | null;
248
818
  delivered_at?: string | null;
@@ -263,6 +833,7 @@ export interface Message {
263
833
  from_handle?: ChatHandle | null;
264
834
  parts?: MessagePartResponse[] | null;
265
835
  reply_to?: ReplyTo | null;
836
+ metadata?: MessageMetadata;
266
837
  is_system_message: boolean;
267
838
  system_event?: SystemEvent | null;
268
839
  is_from_me: boolean;
@@ -313,6 +884,11 @@ export interface ChatCreateParams {
313
884
  message: MessageContent;
314
885
  }
315
886
  export interface ChatCreateResponse {
887
+ /**
888
+ * The A2UI messages of the send that were not applied, each with its place
889
+ * in the request and A2UI's `error` message for it. The rest was applied.
890
+ */
891
+ a2ui_errors?: A2uiFailure[];
316
892
  chat: Pick<Chat, "id" | "display_name" | "is_group" | "handles"> & {
317
893
  message: SentMessage;
318
894
  };
@@ -353,6 +929,11 @@ export interface MessageSendParams {
353
929
  message: MessageContent;
354
930
  }
355
931
  export interface MessageSendResponse {
932
+ /**
933
+ * The A2UI messages of the send that were not applied, each with its place
934
+ * in the request and A2UI's `error` message for it. The rest was applied.
935
+ */
936
+ a2ui_errors?: A2uiFailure[];
356
937
  chat_id: UUID;
357
938
  message: SentMessage;
358
939
  }
@@ -362,6 +943,11 @@ export interface MessageCreateParams {
362
943
  "Idempotency-Key"?: string;
363
944
  }
364
945
  export interface MessageCreateResponse {
946
+ /**
947
+ * The A2UI messages of the send that were not applied, each with its place
948
+ * in the request and A2UI's `error` message for it. The rest was applied.
949
+ */
950
+ a2ui_errors?: A2uiFailure[];
365
951
  from: string;
366
952
  chat_id: UUID;
367
953
  created_new_chat: boolean;
@@ -380,7 +966,11 @@ export interface MessageListParams {
380
966
  order?: "asc" | "desc";
381
967
  }
382
968
  export type MessageThreadParams = MessageListParams;
383
- /** Target text, media, link, or button_reply; buttons and system cannot receive reactions. */
969
+ /**
970
+ * Target text, media, link, or payment; buttons, selection, selection_response
971
+ * and system cannot receive reactions. Only a person can react to a payment;
972
+ * an agent reacting to one gets a 403.
973
+ */
384
974
  export interface MessageAddReactionParams {
385
975
  operation: "add" | "remove";
386
976
  type: ReactionType;
@@ -487,12 +1077,88 @@ export interface WebhookSubscriptionUpdateParams {
487
1077
  export interface WebhookSubscriptionListResponse {
488
1078
  subscriptions: WebhookSubscription[];
489
1079
  }
1080
+ /** Where the directory files the agent. */
1081
+ export type AgentCategory = "productivity" | "business" | "finance" | "shopping" | "travel" | "health-fitness" | "lifestyle" | "social" | "education" | "entertainment" | "utilities" | "developer-tools";
1082
+ /**
1083
+ * `public` agents are listed in the directory and found by task; `unlisted`
1084
+ * agents answer by handle only.
1085
+ */
1086
+ export type AgentVisibility = "public" | "unlisted";
1087
+ /** One thing the agent does, in the A2A AgentSkill shape. */
1088
+ export interface AgentSkill {
1089
+ id: string;
1090
+ name: string;
1091
+ description: string;
1092
+ tags: string[];
1093
+ examples: string[];
1094
+ }
1095
+ export interface ContactLookup {
1096
+ id: UUID;
1097
+ handle: string;
1098
+ display_name: string;
1099
+ kind: "user" | "agent";
1100
+ image_url: string | null;
1101
+ image_color: string | null;
1102
+ verified: boolean;
1103
+ /** The agent's name. Agents only. */
1104
+ name?: string;
1105
+ /** The one line under the agent's name. Agents only. */
1106
+ subtitle?: string | null;
1107
+ /** The agent's paragraph. Agents only. */
1108
+ description?: string | null;
1109
+ /** Where the directory files the agent. Agents only. */
1110
+ category?: AgentCategory | null;
1111
+ /** What the agent does, at most ten skills. Agents only. */
1112
+ skills?: AgentSkill[];
1113
+ /** Whether the agent is listed in the directory. Agents only. */
1114
+ visibility?: AgentVisibility;
1115
+ /**
1116
+ * Who made the agent: its organization, by the name the organization gave
1117
+ * in the Relay Console. Null when the organization has not given a name.
1118
+ * Agents only.
1119
+ */
1120
+ creator?: AgentCreator | null;
1121
+ }
1122
+ /** The organization that made an agent. */
1123
+ export interface AgentCreator {
1124
+ kind: "organization";
1125
+ name: string;
1126
+ /** The maker's Relay Handle. Null until Relay stores one. */
1127
+ handle: string | null;
1128
+ }
1129
+ /**
1130
+ * Look up one contact by Relay Handle, or find public agents by task. Send
1131
+ * exactly one of the two.
1132
+ */
1133
+ export type ContactLookupParams =
1134
+ /** Relay Handle, trimmed and lowercased by the Server before validation. */
1135
+ {
1136
+ handle: string;
1137
+ }
1138
+ /** What you need done, in plain words; at most 200 characters. */
1139
+ | {
1140
+ task: string;
1141
+ };
1142
+ /**
1143
+ * A handle lookup answers with one `contact`; a task search answers with
1144
+ * `contacts`, verified agents first and at most twenty, empty when nothing
1145
+ * matches.
1146
+ */
1147
+ export type ContactLookupResponse = {
1148
+ contact: ContactLookup;
1149
+ } | {
1150
+ contacts: ContactLookup[];
1151
+ };
490
1152
  export interface ContactCardItem {
1153
+ /** Detailed agent description, up to 2000 characters. Public agents cannot clear it. */
1154
+ description?: string | null;
491
1155
  handle: string;
492
1156
  first_name: string;
493
1157
  last_name: string | null;
494
1158
  image_url: string | null;
495
1159
  is_active: boolean;
1160
+ /** Whether Relay has verified this agent. Always false for a user. */
1161
+ is_verified?: boolean;
496
1162
  kind: "user" | "agent";
497
1163
  }
498
1164
  export interface ContactCardCreateParams {
@@ -512,8 +1178,10 @@ export interface ContactCardRetrieveResponse {
512
1178
  contact_cards: ContactCardItem[];
513
1179
  }
514
1180
  export interface ContactCardUpdateParams {
515
- /** Server contract 3097dda: trimmed about text, 1 to 60 characters. */
516
- about?: string;
1181
+ /** Detailed agent description, up to 2000 characters. Public agents cannot clear it. */
1182
+ description?: string | null;
1183
+ /** The one line under the name, 1 to 60 characters. */
1184
+ subtitle?: string;
517
1185
  handle: string;
518
1186
  first_name?: string;
519
1187
  last_name?: string | null;
@@ -609,6 +1277,13 @@ export interface MessageWebhookData {
609
1277
  */
610
1278
  silent?: boolean;
611
1279
  reply_to?: ReplyTo | null;
1280
+ /**
1281
+ * A2A Message metadata. Every `message.received` carries it, with the
1282
+ * reader's `a2uiClientCapabilities` and, when the sender sent one, its
1283
+ * `a2uiClientDataModel` for the surfaces this agent created (see
1284
+ * `MessageReceivedMetadata`).
1285
+ */
1286
+ metadata?: Partial<MessageReceivedMetadata>;
612
1287
  }
613
1288
  /**
614
1289
  * `message.failed`. Relay commits a Message before it answers, so a Message
@@ -658,8 +1333,8 @@ export type ContactAddedWebhookEvent = ContactAddedWebhook;
658
1333
  export type ContactRemovedWebhookEvent = ContactRemovedWebhook;
659
1334
  type MessageWebhookEventType = "message.sent" | "message.received" | "message.read" | "message.delivered";
660
1335
  type TypingIndicatorWebhookEventType = "chat.typing_indicator.started" | "chat.typing_indicator.stopped";
661
- type OtherWebhookEventType = Exclude<WebhookEventType, MessageWebhookEventType | TypingIndicatorWebhookEventType | "contact.added" | "contact.removed" | "message.failed" | "call.created" | "call.updated" | "call.ended">;
662
- export type RelayWebhookEvent = RelayWebhookEnvelope<MessageWebhookData, MessageWebhookEventType> | RelayWebhookEnvelope<TypingIndicatorWebhookData, TypingIndicatorWebhookEventType> | MessageFailedWebhook | ContactAddedWebhookEvent | ContactRemovedWebhookEvent | CallWebhookEvent | RelayWebhookEnvelope<Record<string, unknown>, OtherWebhookEventType>;
1336
+ type OtherWebhookEventType = Exclude<WebhookEventType, MessageWebhookEventType | TypingIndicatorWebhookEventType | "contact.added" | "contact.removed" | "message.failed" | "call.created" | "call.updated" | "call.ended" | "payment.succeeded" | "payment.canceled" | "payment.expired" | "location.sharing.started" | "location.sharing.stopped">;
1337
+ export type RelayWebhookEvent = RelayWebhookEnvelope<MessageWebhookData, MessageWebhookEventType> | RelayWebhookEnvelope<TypingIndicatorWebhookData, TypingIndicatorWebhookEventType> | MessageFailedWebhook | ContactAddedWebhookEvent | ContactRemovedWebhookEvent | CallWebhookEvent | PaymentWebhookEvent | LocationSharingStartedWebhookEvent | LocationSharingStoppedWebhookEvent | RelayWebhookEnvelope<Record<string, unknown>, OtherWebhookEventType>;
663
1338
  /** Existing Relay avatar gradient pairs, ordered top then base. */
664
1339
  export type AgentImageGradient = readonly ["EC8A3C", "C85F1C"] | readonly ["E0567A", "AD2A52"] | readonly ["D05FC6", "93217E"] | readonly ["8F6CF2", "5F38CF"] | readonly ["5B9BFA", "0B52C0"] | readonly ["2596A6", "116A79"] | readonly ["2FA46A", "137347"];
665
1340
  export interface AgentImageBackground {