rio-assist-widget 0.1.10 → 0.1.14

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.
@@ -19,13 +19,20 @@ export type ChatMessage = {
19
19
  timestamp: number;
20
20
  };
21
21
 
22
- type ConversationItem = {
23
- id: string;
24
- title: string;
25
- updatedAt: string;
26
- };
27
-
28
- export class RioAssistWidget extends LitElement {
22
+ type ConversationItem = {
23
+ id: string;
24
+ title: string;
25
+ updatedAt: string;
26
+ };
27
+
28
+ export type HeaderActionConfig = {
29
+ id?: string;
30
+ iconUrl: string;
31
+ ariaLabel?: string;
32
+ onClick?: () => void;
33
+ };
34
+
35
+ export class RioAssistWidget extends LitElement {
29
36
  static styles = widgetStyles;
30
37
 
31
38
  static properties = {
@@ -44,11 +51,15 @@ export class RioAssistWidget extends LitElement {
44
51
  showConversations: { type: Boolean, state: true },
45
52
  conversationSearch: { type: String, state: true },
46
53
  conversationMenuId: { state: true },
47
- conversationMenuPlacement: { state: true },
48
- isFullscreen: { type: Boolean, state: true },
49
- conversationScrollbar: { state: true },
54
+ conversationMenuPlacement: { state: true },
55
+ isFullscreen: { type: Boolean, state: true },
56
+ conversationScrollbar: { state: true },
50
57
  showNewConversationShortcut: { type: Boolean, state: true },
51
58
  conversations: { state: true },
59
+ conversationHistoryLoading: { type: Boolean, state: true },
60
+ activeConversationTitle: { state: true },
61
+ headerActions: { attribute: false },
62
+ homeUrl: { type: String, attribute: 'data-home-url' },
52
63
  };
53
64
 
54
65
  open = false;
@@ -83,25 +94,88 @@ export class RioAssistWidget extends LitElement {
83
94
 
84
95
  conversationMenuPlacement: 'above' | 'below' = 'below';
85
96
 
86
- isFullscreen = false;
87
-
88
- showNewConversationShortcut = false;
89
-
90
- conversationScrollbar = {
91
- height: 0,
92
- top: 0,
93
- visible: false,
94
- };
97
+ isFullscreen = false;
98
+
99
+ showNewConversationShortcut = false;
100
+
101
+ conversationScrollbar = {
102
+ height: 0,
103
+ top: 0,
104
+ visible: false,
105
+ };
106
+
107
+ conversationHistoryLoading = false;
108
+
109
+ private refreshConversationsAfterResponse = false;
110
+
111
+ activeConversationTitle: string | null = null;
112
+
113
+ headerActions: HeaderActionConfig[] = [];
114
+
115
+ homeUrl = '';
116
+
117
+ private generateConversationId() {
118
+ if (!this.conversationUserId) {
119
+ this.conversationUserId = this.inferUserIdFromToken();
120
+ }
121
+
122
+ const userSegment = this.conversationUserId ?? 'user';
123
+ const id = `default-${userSegment}-${this.randomId(8)}`;
124
+ console.info('[RioAssist][conversation] gerando conversationId', id);
125
+ return id;
126
+ }
127
+
128
+ private inferUserIdFromToken(): string | null {
129
+ const token = this.rioToken.trim();
130
+ if (!token || !token.includes('.')) {
131
+ return null;
132
+ }
133
+
134
+ const [, payload] = token.split('.');
135
+ try {
136
+ const decoded = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')));
137
+ const candidate =
138
+ decoded?.userId ??
139
+ decoded?.user_id ??
140
+ decoded?.sub ??
141
+ decoded?.id ??
142
+ decoded?.email ??
143
+ decoded?.username;
144
+
145
+ if (candidate && typeof candidate === 'string') {
146
+ return candidate.replace(/[^a-zA-Z0-9_-]/g, '');
147
+ }
148
+ } catch {
149
+ return null;
150
+ }
151
+
152
+ return null;
153
+ }
154
+
155
+ private randomId(length: number) {
156
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
157
+ let result = '';
158
+ for (let i = 0; i < length; i += 1) {
159
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
160
+ }
161
+ return result;
162
+ }
95
163
 
96
164
  private conversationScrollbarRaf: number | null = null;
97
165
 
98
- private rioClient: RioWebsocketClient | null = null;
99
-
100
- private rioUnsubscribe: (() => void) | null = null;
101
-
102
- private loadingTimer: number | null = null;
103
-
104
- private conversationScrollbarDraggingId: number | null = null;
166
+ private rioClient: RioWebsocketClient | null = null;
167
+
168
+ private rioUnsubscribe: (() => void) | null = null;
169
+
170
+ private loadingTimer: number | null = null;
171
+
172
+ private currentConversationId: string | null = null;
173
+
174
+ private conversationCounter = 0;
175
+
176
+ private conversationUserId: string | null = null;
177
+
178
+ private conversationScrollbarDraggingId: number | null = null;
105
179
 
106
180
  private conversationScrollbarDragState: {
107
181
  startY: number;
@@ -224,13 +298,28 @@ export class RioAssistWidget extends LitElement {
224
298
  this.requestConversationHistory();
225
299
  }
226
300
 
227
- toggleNewConversationShortcut() {
228
- this.showNewConversationShortcut = !this.showNewConversationShortcut;
229
- }
230
-
231
- handleConversationSearch(event: InputEvent) {
232
- this.conversationSearch = (event.target as HTMLInputElement).value;
233
- }
301
+ toggleNewConversationShortcut() {
302
+ this.showNewConversationShortcut = !this.showNewConversationShortcut;
303
+ }
304
+
305
+ handleConversationSelect(conversationId: string) {
306
+ if (!conversationId) {
307
+ return;
308
+ }
309
+
310
+ this.showConversations = false;
311
+ this.conversationMenuId = null;
312
+ this.errorMessage = '';
313
+ this.currentConversationId = conversationId;
314
+ this.activeConversationTitle = this.lookupConversationTitle(conversationId);
315
+
316
+ console.info('[RioAssist][history] carregando conversa', conversationId);
317
+ this.requestConversationHistory(conversationId);
318
+ }
319
+
320
+ handleConversationSearch(event: InputEvent) {
321
+ this.conversationSearch = (event.target as HTMLInputElement).value;
322
+ }
234
323
 
235
324
  handleConversationMenuToggle(event: Event, id: string) {
236
325
  event.stopPropagation();
@@ -267,24 +356,70 @@ export class RioAssistWidget extends LitElement {
267
356
  }
268
357
  }
269
358
 
270
- handleConversationAction(action: 'rename' | 'delete', id: string) {
271
- this.conversationMenuId = null;
272
- const conversation = this.conversations.find((item) => item.id === id);
273
- if (!conversation) {
274
- return;
359
+ handleConversationAction(action: 'rename' | 'delete', id: string) {
360
+ this.conversationMenuId = null;
361
+ const conversation = this.conversations.find((item) => item.id === id);
362
+ if (!conversation) {
363
+ return;
275
364
  }
276
365
 
277
- const message = `${
278
- action === 'rename' ? 'Renomear' : 'Excluir'
279
- } "${conversation.title}"`;
280
- console.info(`[Mock] ${message}`);
281
- }
282
-
283
- handleCloseAction() {
284
- if (this.isFullscreen) {
285
- this.exitFullscreen(true);
286
- return;
287
- }
366
+ const message = `${
367
+ action === 'rename' ? 'Renomear' : 'Excluir'
368
+ } "${conversation.title}"`;
369
+ console.info(`[Mock] ${message}`);
370
+ }
371
+
372
+ handleHomeNavigation() {
373
+ const detail = { url: this.homeUrl || null };
374
+ const allowed = this.dispatchEvent(
375
+ new CustomEvent('rioassist:home', {
376
+ detail,
377
+ bubbles: true,
378
+ composed: true,
379
+ cancelable: true,
380
+ }),
381
+ );
382
+
383
+ if (!allowed) {
384
+ return;
385
+ }
386
+
387
+ if (this.homeUrl) {
388
+ window.location.assign(this.homeUrl);
389
+ }
390
+ }
391
+
392
+ handleHeaderActionClick(action: HeaderActionConfig, index: number) {
393
+ const detail = {
394
+ index,
395
+ id: action.id ?? null,
396
+ ariaLabel: action.ariaLabel ?? null,
397
+ iconUrl: action.iconUrl,
398
+ };
399
+
400
+ const allowed = this.dispatchEvent(
401
+ new CustomEvent('rioassist:header-action', {
402
+ detail,
403
+ bubbles: true,
404
+ composed: true,
405
+ cancelable: true,
406
+ }),
407
+ );
408
+
409
+ if (!allowed) {
410
+ return;
411
+ }
412
+
413
+ if (typeof action.onClick === 'function') {
414
+ action.onClick();
415
+ }
416
+ }
417
+
418
+ handleCloseAction() {
419
+ if (this.isFullscreen) {
420
+ this.exitFullscreen(true);
421
+ return;
422
+ }
288
423
 
289
424
  if (this.showConversations) {
290
425
  this.closeConversationsPanel();
@@ -316,23 +451,25 @@ export class RioAssistWidget extends LitElement {
316
451
  }
317
452
  }
318
453
 
319
- handleCreateConversation() {
320
- if (!this.hasActiveConversation) {
321
- return;
322
- }
323
-
324
- this.clearLoadingGuard();
325
- this.isLoading = false;
326
- this.messages = [];
327
- this.message = '';
328
- this.errorMessage = '';
329
- this.showConversations = false;
330
- this.teardownRioClient();
331
- this.showNewConversationShortcut = false;
332
- this.dispatchEvent(
333
- new CustomEvent('rioassist:new-conversation', {
334
- bubbles: true,
335
- composed: true,
454
+ handleCreateConversation() {
455
+ if (!this.hasActiveConversation) {
456
+ return;
457
+ }
458
+
459
+ this.clearLoadingGuard();
460
+ this.isLoading = false;
461
+ this.messages = [];
462
+ this.message = '';
463
+ this.errorMessage = '';
464
+ this.showConversations = false;
465
+ this.teardownRioClient();
466
+ this.currentConversationId = this.generateConversationId();
467
+ this.activeConversationTitle = null;
468
+ this.showNewConversationShortcut = false;
469
+ this.dispatchEvent(
470
+ new CustomEvent('rioassist:new-conversation', {
471
+ bubbles: true,
472
+ composed: true,
336
473
  }),
337
474
  );
338
475
  }
@@ -494,13 +631,18 @@ export class RioAssistWidget extends LitElement {
494
631
  timestamp: Date.now(),
495
632
  };
496
633
  }
497
-
634
+
498
635
  private async processMessage(rawValue: string) {
499
636
  const content = rawValue.trim();
500
637
  if (!content || this.isLoading) {
501
638
  return;
502
639
  }
503
640
 
641
+ if (!this.currentConversationId) {
642
+ this.currentConversationId = this.generateConversationId();
643
+ this.activeConversationTitle = null;
644
+ }
645
+
504
646
  const wasEmptyConversation = this.messages.length === 0;
505
647
 
506
648
  this.dispatchEvent(
@@ -519,20 +661,21 @@ export class RioAssistWidget extends LitElement {
519
661
  this.messages = [...this.messages, userMessage];
520
662
  if (wasEmptyConversation) {
521
663
  this.showNewConversationShortcut = true;
664
+ this.refreshConversationsAfterResponse = true;
522
665
  }
523
666
  this.message = '';
524
667
  this.errorMessage = '';
525
668
  this.isLoading = true;
526
669
  this.startLoadingGuard();
527
670
 
528
- try {
529
- const client = this.ensureRioClient();
530
- await client.sendMessage(content);
531
- } catch (error) {
532
- this.clearLoadingGuard();
533
- this.isLoading = false;
534
- this.errorMessage = error instanceof Error
535
- ? error.message
671
+ try {
672
+ const client = this.ensureRioClient();
673
+ await client.sendMessage(content, this.currentConversationId);
674
+ } catch (error) {
675
+ this.clearLoadingGuard();
676
+ this.isLoading = false;
677
+ this.errorMessage = error instanceof Error
678
+ ? error.message
536
679
  : 'Nao foi possivel enviar a mensagem para o agente.';
537
680
  }
538
681
  }
@@ -559,14 +702,26 @@ export class RioAssistWidget extends LitElement {
559
702
  private handleIncomingMessage(message: RioIncomingMessage) {
560
703
  if (this.isHistoryPayload(message)) {
561
704
  this.logHistoryPayload(message);
562
- this.applyConversationHistory(message.data);
705
+ this.handleHistoryPayload(message.data);
563
706
  return;
564
707
  }
565
708
 
709
+ console.info('[RioAssist][ws] resposta de mensagem recebida', {
710
+ action: message.action ?? 'message',
711
+ text: message.text,
712
+ raw: message.raw,
713
+ data: message.data,
714
+ });
715
+
566
716
  const assistantMessage = this.createMessage('assistant', message.text);
567
717
  this.messages = [...this.messages, assistantMessage];
568
718
  this.clearLoadingGuard();
569
719
  this.isLoading = false;
720
+
721
+ if (this.refreshConversationsAfterResponse) {
722
+ this.refreshConversationsAfterResponse = false;
723
+ this.requestConversationHistory();
724
+ }
570
725
  }
571
726
 
572
727
  private teardownRioClient() {
@@ -591,9 +746,32 @@ export class RioAssistWidget extends LitElement {
591
746
  limit,
592
747
  });
593
748
 
749
+ this.conversationHistoryLoading = true;
594
750
  await client.requestHistory({ conversationId, limit });
595
751
  } catch (error) {
596
752
  console.error('[RioAssist][history] erro ao solicitar historico', error);
753
+ this.conversationHistoryLoading = false;
754
+ }
755
+ }
756
+
757
+ private handleHistoryPayload(payload: unknown) {
758
+ const entries = this.extractHistoryEntries(payload);
759
+ const conversationId = this.extractConversationId(payload);
760
+
761
+ if (conversationId !== null && conversationId !== undefined) {
762
+ this.applyMessageHistory(entries, conversationId);
763
+ return;
764
+ }
765
+
766
+ if (this.isMessageHistoryEntries(entries)) {
767
+ this.applyMessageHistory(entries);
768
+ return;
769
+ }
770
+
771
+ this.applyConversationHistoryFromEntries(entries);
772
+
773
+ if (this.refreshConversationsAfterResponse) {
774
+ this.refreshConversationsAfterResponse = false;
597
775
  }
598
776
  }
599
777
 
@@ -630,11 +808,11 @@ export class RioAssistWidget extends LitElement {
630
808
  console.info(label, message.raw);
631
809
  }
632
810
 
633
- private applyConversationHistory(payload: unknown) {
634
- const entries = this.extractHistoryEntries(payload);
811
+ private applyConversationHistoryFromEntries(entries: unknown[]) {
635
812
  if (entries.length === 0) {
636
813
  console.info('[RioAssist][history] payload sem itens para montar lista de conversas');
637
814
  this.conversations = [];
815
+ this.conversationHistoryLoading = false;
638
816
  return;
639
817
  }
640
818
 
@@ -674,9 +852,44 @@ export class RioAssistWidget extends LitElement {
674
852
  });
675
853
 
676
854
  this.conversations = conversations;
855
+ this.conversationHistoryLoading = false;
856
+ this.syncActiveConversationTitle();
677
857
  console.info('[RioAssist][history] conversas normalizadas', conversations);
678
858
  }
679
859
 
860
+ private applyMessageHistory(entries: unknown[], conversationId?: string | null) {
861
+ if (entries.length === 0) {
862
+ console.info('[RioAssist][history] lista de mensagens vazia', { conversationId });
863
+ this.messages = [];
864
+ this.showConversations = false;
865
+ this.clearLoadingGuard();
866
+ this.isLoading = false;
867
+ this.conversationHistoryLoading = false;
868
+ return;
869
+ }
870
+
871
+ const normalized = entries.flatMap((entry, index) =>
872
+ this.normalizeHistoryMessages(entry as Record<string, unknown>, index),
873
+ );
874
+
875
+ if (conversationId) {
876
+ this.currentConversationId = conversationId;
877
+ }
878
+
879
+ this.messages = normalized;
880
+ this.showConversations = false;
881
+ this.clearLoadingGuard();
882
+ this.isLoading = false;
883
+ this.showNewConversationShortcut = normalized.length > 0;
884
+ this.conversationHistoryLoading = false;
885
+ this.refreshConversationsAfterResponse = false;
886
+
887
+ console.info('[RioAssist][history] mensagens carregadas', {
888
+ conversationId: conversationId ?? null,
889
+ total: normalized.length,
890
+ });
891
+ }
892
+
680
893
  private extractHistoryEntries(payload: unknown): unknown[] {
681
894
  if (Array.isArray(payload)) {
682
895
  return payload;
@@ -709,6 +922,62 @@ export class RioAssistWidget extends LitElement {
709
922
  return [];
710
923
  }
711
924
 
925
+ private extractConversationId(payload: unknown): string | null | undefined {
926
+ if (payload && typeof payload === 'object') {
927
+ const record = payload as Record<string, unknown>;
928
+ const candidates = [
929
+ record.conversationId,
930
+ record.conversationUUID,
931
+ record.conversationUuid,
932
+ record.uuid,
933
+ record.id,
934
+ ];
935
+
936
+ for (const candidate of candidates) {
937
+ if (candidate === null) {
938
+ return null;
939
+ }
940
+
941
+ if (candidate !== undefined) {
942
+ return String(candidate);
943
+ }
944
+ }
945
+ }
946
+
947
+ return undefined;
948
+ }
949
+
950
+ private isMessageHistoryEntries(entries: unknown[]) {
951
+ return entries.some((entry) => this.looksLikeMessageHistoryEntry(entry));
952
+ }
953
+
954
+ private looksLikeMessageHistoryEntry(entry: unknown) {
955
+ if (!entry || typeof entry !== 'object') {
956
+ return false;
957
+ }
958
+
959
+ const item = entry as Record<string, unknown>;
960
+ const role = item.role ?? item.sender ?? item.from ?? item.author ?? item.type;
961
+ if (typeof role === 'string' && role.trim().length > 0) {
962
+ return true;
963
+ }
964
+
965
+ if (
966
+ typeof item.content === 'string' ||
967
+ typeof item.message === 'string' ||
968
+ typeof item.text === 'string' ||
969
+ typeof item.response === 'string'
970
+ ) {
971
+ return true;
972
+ }
973
+
974
+ if (Array.isArray(item.parts) && item.parts.length > 0) {
975
+ return true;
976
+ }
977
+
978
+ return false;
979
+ }
980
+
712
981
  private normalizeConversationItem(
713
982
  value: Record<string, unknown>,
714
983
  index: number,
@@ -751,6 +1020,176 @@ export class RioAssistWidget extends LitElement {
751
1020
  return { id, title, updatedAt };
752
1021
  }
753
1022
 
1023
+ private normalizeHistoryMessages(
1024
+ value: Record<string, unknown>,
1025
+ index: number,
1026
+ ): ChatMessage[] {
1027
+ const messages: ChatMessage[] = [];
1028
+
1029
+ const rawUserText = value.message ?? value.question ?? value.query ?? value.text ?? value.content;
1030
+ const userText = typeof rawUserText === 'string' ? rawUserText.trim() : '';
1031
+
1032
+ const rawResponseText =
1033
+ value.response ?? value.answer ?? value.reply ?? value.completion ?? value.body ?? value.preview;
1034
+ const responseText = typeof rawResponseText === 'string' ? rawResponseText.trim() : '';
1035
+
1036
+ const rawId = value.id ?? value.messageId ?? value.uuid ?? value.conversationMessageId;
1037
+ const baseId = rawId !== undefined && rawId !== null
1038
+ ? String(rawId)
1039
+ : `history-${index + 1}`;
1040
+
1041
+ const userTimestampValue =
1042
+ value.timestamp ??
1043
+ value.createdAt ??
1044
+ value.created_at ??
1045
+ value.date ??
1046
+ value.time;
1047
+ const assistantTimestampValue =
1048
+ value.responseTimestamp ??
1049
+ value.responseTime ??
1050
+ value.responseDate ??
1051
+ value.response_at ??
1052
+ value.updatedAt ??
1053
+ value.updated_at;
1054
+
1055
+ const userTimestamp = this.parseTimestamp(userTimestampValue);
1056
+ const assistantTimestamp = this.parseTimestamp(
1057
+ assistantTimestampValue,
1058
+ userTimestamp + 1,
1059
+ );
1060
+
1061
+ if (responseText) {
1062
+ if (userText) {
1063
+ messages.push({
1064
+ id: `${baseId}-user`,
1065
+ role: 'user',
1066
+ text: userText,
1067
+ html: this.renderMarkdown(userText),
1068
+ timestamp: userTimestamp,
1069
+ });
1070
+ }
1071
+
1072
+ messages.push({
1073
+ id: `${baseId}-assistant`,
1074
+ role: 'assistant',
1075
+ text: responseText,
1076
+ html: this.renderMarkdown(responseText),
1077
+ timestamp: assistantTimestamp,
1078
+ });
1079
+ } else if (userText) {
1080
+ // Se n�o tiver resposta, n�o exibimos a mensagem do usuario isolada.
1081
+ return [];
1082
+ }
1083
+
1084
+ if (messages.length > 0) {
1085
+ return messages;
1086
+ }
1087
+
1088
+ const fallback = this.normalizeSingleHistoryMessage(value, index);
1089
+ return fallback ? [fallback] : [];
1090
+ }
1091
+
1092
+ private normalizeSingleHistoryMessage(
1093
+ value: Record<string, unknown>,
1094
+ index: number,
1095
+ ): ChatMessage | null {
1096
+ const rawText =
1097
+ value.text ??
1098
+ value.message ??
1099
+ value.content ??
1100
+ value.response ??
1101
+ value.body ??
1102
+ value.preview;
1103
+
1104
+ const text = typeof rawText === 'string' && rawText.trim().length > 0
1105
+ ? rawText
1106
+ : '';
1107
+
1108
+ if (!text) {
1109
+ return null;
1110
+ }
1111
+
1112
+ const role = this.normalizeRole(
1113
+ value.role ??
1114
+ value.sender ??
1115
+ value.from ??
1116
+ value.author ??
1117
+ value.type ??
1118
+ value.direction,
1119
+ );
1120
+
1121
+ const rawId = value.id ?? value.messageId ?? value.uuid ?? value.conversationMessageId;
1122
+ const id = rawId !== undefined && rawId !== null
1123
+ ? String(rawId)
1124
+ : `history-message-${index + 1}`;
1125
+
1126
+ const timestampValue =
1127
+ value.timestamp ??
1128
+ value.createdAt ??
1129
+ value.created_at ??
1130
+ value.updatedAt ??
1131
+ value.updated_at ??
1132
+ value.date ??
1133
+ value.time;
1134
+
1135
+ const timestamp = this.parseTimestamp(timestampValue);
1136
+
1137
+ return {
1138
+ id,
1139
+ role,
1140
+ text,
1141
+ html: this.renderMarkdown(text),
1142
+ timestamp,
1143
+ };
1144
+ }
1145
+
1146
+ private normalizeRole(value: unknown): ChatRole {
1147
+ if (typeof value === 'string') {
1148
+ const normalized = value.toLowerCase();
1149
+ if (normalized.includes('user') || normalized.includes('client')) {
1150
+ return 'user';
1151
+ }
1152
+ if (normalized.includes('assistant') || normalized.includes('agent') || normalized.includes('bot')) {
1153
+ return 'assistant';
1154
+ }
1155
+ }
1156
+
1157
+ return 'assistant';
1158
+ }
1159
+
1160
+ private parseTimestamp(value: unknown, fallback?: number) {
1161
+ const parsed = Date.parse(this.toIsoString(value));
1162
+ if (Number.isFinite(parsed)) {
1163
+ return parsed;
1164
+ }
1165
+
1166
+ if (Number.isFinite(fallback ?? NaN)) {
1167
+ return fallback as number;
1168
+ }
1169
+
1170
+ return Date.now();
1171
+ }
1172
+
1173
+ private lookupConversationTitle(conversationId: string | null) {
1174
+ if (!conversationId) {
1175
+ return null;
1176
+ }
1177
+
1178
+ const found = this.conversations.find((item) => item.id === conversationId);
1179
+ return found ? found.title : null;
1180
+ }
1181
+
1182
+ private syncActiveConversationTitle() {
1183
+ if (!this.currentConversationId) {
1184
+ return;
1185
+ }
1186
+
1187
+ const title = this.lookupConversationTitle(this.currentConversationId);
1188
+ if (title) {
1189
+ this.activeConversationTitle = title;
1190
+ }
1191
+ }
1192
+
754
1193
  private toIsoString(value: unknown) {
755
1194
  if (typeof value === 'string' || typeof value === 'number') {
756
1195
  const date = new Date(value);