@unboundcx/sdk 4.0.10 → 4.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.0.10",
3
+ "version": "4.0.12",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,7 +28,7 @@ message AudioRequest {
28
28
  string language = 4;
29
29
 
30
30
  // Transcription engine to use
31
- // Options: "whisper", "google"
31
+ // Options: "whisper", "google", "groq"
32
32
  string engine = 5;
33
33
 
34
34
  // Audio configuration
@@ -66,28 +66,48 @@ message AudioRequest {
66
66
  // VAD event timestamp
67
67
  int64 vad_timestamp = 15;
68
68
 
69
- // Playbook identifier (optional - links transcription to a playbook session)
69
+ // Optional playbook ID for real-time agent scoring
70
70
  string playbook_id = 16;
71
71
 
72
- // Bridge identifier (optional - links related transcription streams)
73
- // When multiple bridged call legs have transcription active,
74
- // bridge_id lets the transcription service correlate them
72
+ // Bridge ID linking related transcription streams (e.g., both legs of a bridged call)
73
+ // Empty string = not part of any bridge. Dynamic: can appear, change, or disappear mid-stream.
75
74
  string bridge_id = 17;
76
75
 
77
- // Task identifier (optional - links transcription to a specific task)
76
+ // Optional task ID for playbook session tracking
78
77
  string task_id = 18;
79
78
 
80
- // Worker identifier (optional)
79
+ // Optional worker ID for playbook session tracking
81
80
  string worker_id = 19;
82
81
 
83
- // Generate subject from transcription (optional)
82
+ // Enable real-time subject generation from customer transcripts
83
+ // Requires task_id to be set for SDK task update
84
84
  bool generate_subject = 20;
85
85
 
86
- // Generate transcript summary (optional)
86
+ // Enable end-of-call transcript summary generation
87
+ // Requires task_id to be set for SDK task update
87
88
  bool generate_transcript_summary = 21;
88
89
 
89
- // Generate sentiment analysis (optional)
90
+ // Enable real-time sentiment analysis with multi-signal fusion
91
+ // Requires task_id to be set for SDK task update
90
92
  bool generate_sentiment = 22;
93
+
94
+ // ── Meet (video-room) session metadata — additive, optional ──────────────
95
+ // Video room ID this stream belongs to (Meet sessions only). Also used as
96
+ // the conversation identifier for Meet sessions.
97
+ string video_room_id = 23;
98
+
99
+ // Video room participant ID (Meet sessions only)
100
+ string participant_id = 24;
101
+
102
+ // Display name of the participant (Meet sessions only)
103
+ string display_name = 25;
104
+
105
+ // Opt-in server-side VAD: when true, this repo runs its own energy-based
106
+ // silence detector over incoming PCM chunks and injects synthetic
107
+ // speaking_started/speaking_stopped vad_events (media-manager-parity
108
+ // SilenceDetector), instead of relying on client-sent vad_event fields.
109
+ // Defaults to false/unset: existing (non-Meet) callers are unaffected.
110
+ bool server_vad = 26;
91
111
  }
92
112
 
93
113
  // Audio configuration
@@ -156,6 +176,28 @@ message TranscriptResponse {
156
176
 
157
177
  // Speaker role (echoed back from AudioRequest)
158
178
  string role = 11;
179
+
180
+ // Sentiment score (-100 to +100, 0 if sentiment not enabled)
181
+ float sentiment_score = 12;
182
+
183
+ // Sentiment trend ('improving', 'stable', 'declining', empty if not enabled)
184
+ string sentiment_trend = 13;
185
+
186
+ // Unique message ID for correlating transcript with its sentiment update
187
+ string message_id = 14;
188
+
189
+ // Whether this message is a sentiment enrichment update (not a new transcript)
190
+ bool is_sentiment_update = 15;
191
+
192
+ // ── Meet (video-room) session metadata — additive, optional, echoed back ─
193
+ // Video room ID (echoed back from AudioRequest, Meet sessions only)
194
+ string video_room_id = 16;
195
+
196
+ // Video room participant ID (echoed back from AudioRequest, Meet sessions only)
197
+ string participant_id = 17;
198
+
199
+ // Display name of the participant (echoed back from AudioRequest, Meet sessions only)
200
+ string display_name = 18;
159
201
  }
160
202
 
161
203
  // Word-level information
@@ -118,6 +118,10 @@ export class SttStream extends EventEmitter {
118
118
  // sipCallId: string, // NEW
119
119
  // side: string, // NEW
120
120
  // role: string // NEW
121
+ // videoRoomId: string, // NEW (meet sessions only, else '')
122
+ // participantId: string, // NEW (meet sessions only, else '')
123
+ // displayName: string, // NEW (meet sessions only, else '')
124
+ // messageId: string // NEW (proto field 14)
121
125
  // }
122
126
 
123
127
  if (response.transcript) {
@@ -134,6 +138,11 @@ export class SttStream extends EventEmitter {
134
138
  sipCallId: response.sipCallId || response.sip_call_id || '',
135
139
  side: response.side || '',
136
140
  role: response.role || '',
141
+ // Meet (video-room) session metadata (NEW, additive, '' when not a meet session)
142
+ videoRoomId: response.videoRoomId || response.video_room_id || '',
143
+ participantId: response.participantId || response.participant_id || '',
144
+ displayName: response.displayName || response.display_name || '',
145
+ messageId: response.messageId || response.message_id || '',
137
146
  };
138
147
 
139
148
  this.emit('transcript', transcriptData);
@@ -154,6 +163,10 @@ export class SttStream extends EventEmitter {
154
163
  * @param {string} streamMetadata.role - Optional speaker role (e.g., 'customer', 'agent', 'system')
155
164
  * @param {boolean} streamMetadata.isLastChunk - If true, marks this specific stream as complete
156
165
  * @returns {boolean} - True if write successful
166
+ *
167
+ * Meet (video-room) session metadata is not per-chunk — it is sent once in the
168
+ * first-chunk session config, read from stream options: options.videoRoomId,
169
+ * options.participantId, options.displayName, options.serverVad. See constructor.
157
170
  */
158
171
  write(audioChunk, streamMetadata = {}) {
159
172
  if (this.isClosed) {
@@ -205,6 +218,11 @@ export class SttStream extends EventEmitter {
205
218
  generate_transcript_summary: this.options.generateTranscriptSummary || false,
206
219
  generate_sentiment: this.options.generateSentiment || false,
207
220
  bridge_id: bridgeId,
221
+ // Meet (video-room) session metadata (NEW, additive, optional)
222
+ video_room_id: this.options.videoRoomId || '',
223
+ participant_id: this.options.participantId || '',
224
+ display_name: this.options.displayName || '',
225
+ server_vad: this.options.serverVad || false,
208
226
  };
209
227
 
210
228
  this.grpcCall.write(request);
package/services/ai.js CHANGED
@@ -224,6 +224,27 @@ export class GenerativeService {
224
224
  return result;
225
225
  }
226
226
 
227
+ /**
228
+ * Summarize chat/transcript content (running summary, chapters, title)
229
+ * @param {Object} payload
230
+ * @param {string} [payload.domain] - Summary domain (e.g. 'meeting')
231
+ * @param {string} [payload.mode] - Summary mode
232
+ * @param {Array} [payload.lines] - Transcript/chat lines to summarize
233
+ * @param {Array} [payload.chatMessages] - Chat messages to summarize
234
+ * @param {string} [payload.runningSummary] - Existing running summary to extend
235
+ * @param {boolean} [payload.includeChapters] - Include chapter breakdown
236
+ * @param {boolean} [payload.includeTitle] - Include a generated title
237
+ * @returns {Promise<Object>} Summary result
238
+ */
239
+ async summarize(payload = {}) {
240
+ const params = {
241
+ body: payload,
242
+ };
243
+
244
+ const result = await this.sdk._fetch('/ai/summarize', 'POST', params);
245
+ return result;
246
+ }
247
+
227
248
  /**
228
249
  * List available chat tools and their metadata
229
250
  * @returns {Promise<Object>} { tools: Array<{ name, label, description, configRequirements }>, count: number }
@@ -611,6 +632,11 @@ export class SpeechToTextService {
611
632
  * @param {string} [options.playbookId] - Playbook ID
612
633
  * @param {string} [options.name] - Session name
613
634
  * @param {Object} [options.metadata] - Additional metadata
635
+ * @param {string} [options.videoRoomId] - Video (Meet) room ID this stream belongs to
636
+ * @param {string} [options.videoParticipantId] - Video (Meet) room participant ID
637
+ * @param {string} [options.displayName] - Participant display name (Meet sessions)
638
+ * @param {string} [options.role] - Speaker role (e.g. 'participant', 'host')
639
+ * @param {boolean} [options.serverVad] - Opt-in server-side VAD (Meet sessions; defaults false)
614
640
  * @returns {Promise<SttStream>} Stream object with write() method and transcript events
615
641
  *
616
642
  * @example
@@ -658,6 +684,11 @@ export class SpeechToTextService {
658
684
  metadata,
659
685
  sipCallId,
660
686
  cdrId,
687
+ videoRoomId,
688
+ videoParticipantId,
689
+ displayName,
690
+ role,
691
+ serverVad,
661
692
  } = options;
662
693
 
663
694
  // Validate parameters
@@ -689,6 +720,11 @@ export class SpeechToTextService {
689
720
  metadata,
690
721
  sipCallId,
691
722
  cdrId,
723
+ videoRoomId,
724
+ videoParticipantId,
725
+ displayName,
726
+ role,
727
+ serverVad,
692
728
  },
693
729
  {
694
730
  engine: { type: 'string', required: false },
@@ -717,6 +753,11 @@ export class SpeechToTextService {
717
753
  metadata: { type: 'object', required: false },
718
754
  sipCallId: { type: 'string', required: false },
719
755
  cdrId: { type: 'string', required: false },
756
+ videoRoomId: { type: 'string', required: false },
757
+ videoParticipantId: { type: 'string', required: false },
758
+ displayName: { type: 'string', required: false },
759
+ role: { type: 'string', required: false },
760
+ serverVad: { type: 'boolean', required: false },
720
761
  },
721
762
  );
722
763
 
@@ -736,6 +777,10 @@ export class SpeechToTextService {
736
777
  sipCallId,
737
778
  cdrId,
738
779
  name,
780
+ videoRoomId,
781
+ videoParticipantId,
782
+ displayName,
783
+ role,
739
784
  metadata: {
740
785
  ...metadata,
741
786
  languageCode,
@@ -773,6 +818,12 @@ export class SpeechToTextService {
773
818
  vadEnabled,
774
819
  minSilenceDuration,
775
820
  speechPadMs,
821
+ // SttStream reads these as videoRoomId/participantId/displayName/serverVad
822
+ // for the gRPC first-chunk session config.
823
+ videoRoomId,
824
+ participantId: videoParticipantId,
825
+ displayName,
826
+ serverVad,
776
827
  };
777
828
 
778
829
  return new SttStream(this.sdk, session, streamOptions);
@@ -883,6 +934,8 @@ export class SpeechToTextService {
883
934
  side,
884
935
  bridgeId,
885
936
  sentiment,
937
+ videoRoomId,
938
+ videoParticipantId,
886
939
  },
887
940
  ) {
888
941
  this.sdk.validateParams(
@@ -902,6 +955,8 @@ export class SpeechToTextService {
902
955
  side: { type: 'string', required: false },
903
956
  bridgeId: { type: 'string', required: false },
904
957
  sentiment: { type: 'object', required: false },
958
+ videoRoomId: { type: 'string', required: false },
959
+ videoParticipantId: { type: 'string', required: false },
905
960
  },
906
961
  );
907
962
 
@@ -920,6 +975,8 @@ export class SpeechToTextService {
920
975
  side,
921
976
  bridgeId,
922
977
  sentiment,
978
+ videoRoomId,
979
+ videoParticipantId,
923
980
  },
924
981
  };
925
982
 
@@ -3,19 +3,38 @@ export class GoogleCalendarService {
3
3
  this.sdk = sdk;
4
4
  }
5
5
 
6
- async setupWebhook({ calendarId, eventTypes, webhookUrl, expirationTime }) {
6
+ async setupWebhook({
7
+ calendarId,
8
+ eventTypes,
9
+ webhookUrl,
10
+ expirationTime,
11
+ recordTypeId,
12
+ } = {}) {
13
+ // Only calendarId is required. The server derives the webhook URL itself
14
+ // (per-environment: https://login.<API_BASE_URL>/webhooks/google/...) and
15
+ // watches all event types, so eventTypes/webhookUrl are optional. They
16
+ // were previously marked required, which broke the common
17
+ // setupWebhook({ calendarId }) call site (createRoom) with
18
+ // "Missing required parameter eventTypes".
19
+ // recordTypeId is optional: callers (e.g. createRoom) pass the meeting's
20
+ // already-resolved recordTypeId so the webhook row inherits it; if omitted
21
+ // the server resolves a fallback via findRecordTypeId.
7
22
  this.sdk.validateParams(
8
- { calendarId, eventTypes, webhookUrl },
23
+ { calendarId, eventTypes, webhookUrl, recordTypeId },
9
24
  {
10
25
  calendarId: { type: 'string', required: true },
11
- eventTypes: { type: 'array', required: true },
12
- webhookUrl: { type: 'string', required: true },
26
+ eventTypes: { type: 'array', required: false },
27
+ webhookUrl: { type: 'string', required: false },
13
28
  expirationTime: { type: 'number', required: false },
29
+ recordTypeId: { type: 'string', required: false },
14
30
  },
15
31
  );
16
32
 
17
- const webhookData = { calendarId, eventTypes, webhookUrl };
33
+ const webhookData = { calendarId };
34
+ if (eventTypes) webhookData.eventTypes = eventTypes;
35
+ if (webhookUrl) webhookData.webhookUrl = webhookUrl;
18
36
  if (expirationTime) webhookData.expirationTime = expirationTime;
37
+ if (recordTypeId) webhookData.recordTypeId = recordTypeId;
19
38
 
20
39
  const params = {
21
40
  body: webhookData,
package/services/video.js CHANGED
@@ -221,6 +221,13 @@ export class VideoService {
221
221
  startMicrophoneMutedAfter,
222
222
  enableChat,
223
223
  engagementSessionId,
224
+ startRecordingOn,
225
+ startTranscribingOn,
226
+ syncToCalendar,
227
+ source,
228
+ calendarId,
229
+ eventId,
230
+ calendarProvider,
224
231
  }) {
225
232
  this.sdk.validateParams(
226
233
  {
@@ -241,6 +248,13 @@ export class VideoService {
241
248
  startMicrophoneMutedAfter,
242
249
  enableChat,
243
250
  engagementSessionId,
251
+ startRecordingOn,
252
+ startTranscribingOn,
253
+ syncToCalendar,
254
+ source,
255
+ calendarId,
256
+ eventId,
257
+ calendarProvider,
244
258
  },
245
259
  {
246
260
  name: { type: 'string', required: false },
@@ -260,6 +274,13 @@ export class VideoService {
260
274
  startMicrophoneMutedAfter: { type: 'number', required: false },
261
275
  enableChat: { type: 'boolean', required: false },
262
276
  engagementSessionId: { type: 'string', required: false },
277
+ startRecordingOn: { type: 'boolean', required: false },
278
+ startTranscribingOn: { type: 'boolean', required: false },
279
+ syncToCalendar: { type: 'boolean', required: false },
280
+ source: { type: 'string', required: false },
281
+ calendarId: { type: 'string', required: false },
282
+ eventId: { type: 'string', required: false },
283
+ calendarProvider: { type: 'string', required: false },
263
284
  },
264
285
  );
265
286
  const params = {
@@ -281,6 +302,13 @@ export class VideoService {
281
302
  startMicrophoneMutedAfter,
282
303
  enableChat,
283
304
  engagementSessionId,
305
+ startRecordingOn,
306
+ startTranscribingOn,
307
+ syncToCalendar,
308
+ source,
309
+ calendarId,
310
+ eventId,
311
+ calendarProvider,
284
312
  },
285
313
  };
286
314
  const result = await this.sdk._fetch(`/video`, 'POST', params);
@@ -459,7 +487,7 @@ export class VideoService {
459
487
  return result;
460
488
  }
461
489
 
462
- async deleteRoom(roomId) {
490
+ async deleteRoom(roomId, options = {}) {
463
491
  this.sdk.validateParams(
464
492
  { roomId },
465
493
  {
@@ -467,6 +495,9 @@ export class VideoService {
467
495
  },
468
496
  );
469
497
  const params = {};
498
+ if (options && options.deleteCalendarEvent === true) {
499
+ params.body = { deleteCalendarEvent: true };
500
+ }
470
501
  const result = await this.sdk._fetch(`/video/${roomId}`, 'DELETE', params);
471
502
  return result;
472
503
  }
@@ -618,6 +649,26 @@ export class VideoService {
618
649
  return result;
619
650
  }
620
651
 
652
+ // Persist a rolled-up quality summary to MySQL (one row per participant
653
+ // per meeting). Internal endpoint, called by app1-video-server on
654
+ // participant.leave. Long-term home for billing (bytes) and "was this
655
+ // meeting good?" support lookups, surviving ClickHouse TTL expiry.
656
+ async submitParticipantSummary(roomId, participantId, summary) {
657
+ this.sdk.validateParams(
658
+ { roomId, participantId, summary },
659
+ {
660
+ roomId: { type: 'string', required: true },
661
+ participantId: { type: 'string', required: true },
662
+ summary: { type: 'object', required: true },
663
+ },
664
+ );
665
+ return this.sdk._fetch(
666
+ `/internal/video/${roomId}/participants/${participantId}/summary`,
667
+ 'POST',
668
+ { body: summary },
669
+ );
670
+ }
671
+
621
672
  async submitSurvey({
622
673
  videoRoomId,
623
674
  participantId,
@@ -749,6 +800,42 @@ export class VideoService {
749
800
  return result;
750
801
  }
751
802
 
803
+ /**
804
+ * Get the live transcription transcript for a video room, paged.
805
+ * @param {string} roomId - The video room ID
806
+ * @param {Object} [options] - Paging options
807
+ * @param {number} [options.limit] - Max rows to return
808
+ * @param {number} [options.offset] - Row offset
809
+ * @returns {Promise} Paged transcript rows, ordered by timestamp/createdAt ascending
810
+ */
811
+ async getTranscript(roomId, options = {}) {
812
+ this.sdk.validateParams(
813
+ { roomId },
814
+ {
815
+ roomId: { type: 'string', required: true },
816
+ },
817
+ );
818
+
819
+ const validationSchema = {};
820
+ if ('limit' in options) validationSchema.limit = { type: 'number' };
821
+ if ('offset' in options) validationSchema.offset = { type: 'number' };
822
+
823
+ if (Object.keys(validationSchema).length > 0) {
824
+ this.sdk.validateParams(options, validationSchema);
825
+ }
826
+
827
+ const params = {
828
+ query: options,
829
+ };
830
+
831
+ const result = await this.sdk._fetch(
832
+ `/video/${roomId}/transcript`,
833
+ 'GET',
834
+ params,
835
+ );
836
+ return result;
837
+ }
838
+
752
839
  /**
753
840
  * Edit a chat message in a video room
754
841
  * Only the participant who created the message can edit it
@@ -943,4 +1030,182 @@ export class VideoService {
943
1030
  const result = await this.sdk._fetch('/video/settings/user', 'GET', params);
944
1031
  return result;
945
1032
  }
1033
+
1034
+ /**
1035
+ * Get the AI-generated summary for a video room's transcript
1036
+ * @param {string} roomId - The video room ID
1037
+ * @returns {Promise} Meeting summary
1038
+ */
1039
+ async getSummary(roomId) {
1040
+ this.sdk.validateParams(
1041
+ { roomId },
1042
+ {
1043
+ roomId: { type: 'string', required: true },
1044
+ },
1045
+ );
1046
+
1047
+ const result = await this.sdk._fetch(`/video/${roomId}/summary`, 'GET');
1048
+ return result;
1049
+ }
1050
+
1051
+ /**
1052
+ * Host-only edit of a video room's post-meeting AI summary
1053
+ * @param {string} roomId - The video room ID
1054
+ * @param {Object} update
1055
+ * @param {Object} update.summaryJson - {title, summary, actionItems, chapters}
1056
+ * @returns {Promise} Update result
1057
+ */
1058
+ async updateSummary(roomId, { summaryJson }) {
1059
+ this.sdk.validateParams(
1060
+ { roomId, summaryJson },
1061
+ {
1062
+ roomId: { type: 'string', required: true },
1063
+ summaryJson: { type: 'object', required: true },
1064
+ },
1065
+ );
1066
+
1067
+ const params = {
1068
+ body: { summaryJson },
1069
+ };
1070
+
1071
+ const result = await this.sdk._fetch(
1072
+ `/video/${roomId}/summary`,
1073
+ 'PATCH',
1074
+ params,
1075
+ );
1076
+ return result;
1077
+ }
1078
+
1079
+ /**
1080
+ * Generate a "catch me up" recap of a video room's transcript so far
1081
+ * @param {string} roomId - The video room ID
1082
+ * @returns {Promise} Catch-up summary
1083
+ */
1084
+ async catchMeUp(roomId) {
1085
+ this.sdk.validateParams(
1086
+ { roomId },
1087
+ {
1088
+ roomId: { type: 'string', required: true },
1089
+ },
1090
+ );
1091
+
1092
+ const result = await this.sdk._fetch(
1093
+ `/video/${roomId}/catch-me-up`,
1094
+ 'POST',
1095
+ {},
1096
+ );
1097
+ return result;
1098
+ }
1099
+
1100
+ /**
1101
+ * Ask the room-scoped AI assistant a question, grounded in the meeting
1102
+ * transcript so far
1103
+ * @param {string} roomId - The video room ID
1104
+ * @param {Object} params
1105
+ * @param {string} params.question - The question to ask
1106
+ * @param {Array<{role: 'user'|'assistant', content: string}>} [params.history] - Prior turns
1107
+ * @returns {Promise} Assistant answer
1108
+ */
1109
+ async assistantChat(roomId, { question, history } = {}) {
1110
+ this.sdk.validateParams(
1111
+ { roomId, question },
1112
+ {
1113
+ roomId: { type: 'string', required: true },
1114
+ question: { type: 'string', required: true },
1115
+ },
1116
+ );
1117
+
1118
+ const body = { question };
1119
+ if (history !== undefined) {
1120
+ body.history = history;
1121
+ }
1122
+
1123
+ const result = await this.sdk._fetch(`/video/${roomId}/assistant`, 'POST', {
1124
+ body,
1125
+ });
1126
+ return result;
1127
+ }
1128
+
1129
+ /**
1130
+ * Update the text of a transcript message
1131
+ * @param {string} roomId - The video room ID
1132
+ * @param {string} messageId - The transcript message ID
1133
+ * @param {Object} update
1134
+ * @param {string} update.text - New transcript text
1135
+ * @returns {Promise} Updated transcript message
1136
+ */
1137
+ async updateTranscriptMessage(roomId, messageId, { text }) {
1138
+ this.sdk.validateParams(
1139
+ { roomId, messageId, text },
1140
+ {
1141
+ roomId: { type: 'string', required: true },
1142
+ messageId: { type: 'string', required: true },
1143
+ text: { type: 'string', required: true },
1144
+ },
1145
+ );
1146
+
1147
+ const params = {
1148
+ body: { text },
1149
+ };
1150
+
1151
+ const result = await this.sdk._fetch(
1152
+ `/video/${roomId}/transcript/${messageId}`,
1153
+ 'PATCH',
1154
+ params,
1155
+ );
1156
+ return result;
1157
+ }
1158
+
1159
+ /**
1160
+ * Redact a transcript message
1161
+ * @param {string} roomId - The video room ID
1162
+ * @param {string} messageId - The transcript message ID
1163
+ * @returns {Promise} Redaction result
1164
+ */
1165
+ async redactTranscriptMessage(roomId, messageId) {
1166
+ this.sdk.validateParams(
1167
+ { roomId, messageId },
1168
+ {
1169
+ roomId: { type: 'string', required: true },
1170
+ messageId: { type: 'string', required: true },
1171
+ },
1172
+ );
1173
+
1174
+ const result = await this.sdk._fetch(
1175
+ `/video/${roomId}/transcript/${messageId}/redact`,
1176
+ 'POST',
1177
+ {},
1178
+ );
1179
+ return result;
1180
+ }
1181
+
1182
+ /**
1183
+ * Rename a speaker in the transcript for a video room
1184
+ * @param {string} roomId - The video room ID
1185
+ * @param {Object} update
1186
+ * @param {string} update.participantId - Participant ID whose transcript speaker name to update
1187
+ * @param {string} update.displayName - New display name
1188
+ * @returns {Promise} Update result
1189
+ */
1190
+ async renameTranscriptSpeaker(roomId, { participantId, displayName }) {
1191
+ this.sdk.validateParams(
1192
+ { roomId, participantId, displayName },
1193
+ {
1194
+ roomId: { type: 'string', required: true },
1195
+ participantId: { type: 'string', required: true },
1196
+ displayName: { type: 'string', required: true },
1197
+ },
1198
+ );
1199
+
1200
+ const params = {
1201
+ body: { participantId, displayName },
1202
+ };
1203
+
1204
+ const result = await this.sdk._fetch(
1205
+ `/video/${roomId}/transcript-speakers`,
1206
+ 'PATCH',
1207
+ params,
1208
+ );
1209
+ return result;
1210
+ }
946
1211
  }