@customerhero/js 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -105,7 +105,10 @@ var en = {
105
105
  drop_files_here: "Drop files here",
106
106
  incident_dismiss: "Dismiss",
107
107
  incident_default_link_label: "Learn more",
108
- attachment_unsupported_type: "Unsupported file type"
108
+ attachment_unsupported_type: "Unsupported file type",
109
+ attachment_open: "Open attachment",
110
+ attachment_image_alt: "Image attachment",
111
+ attachment_location: "Shared location"
109
112
  };
110
113
 
111
114
  // src/i18n/locales/es.ts
@@ -136,7 +139,10 @@ var es = {
136
139
  drop_files_here: "Suelta los archivos aqu\xED",
137
140
  incident_dismiss: "Descartar",
138
141
  incident_default_link_label: "M\xE1s informaci\xF3n",
139
- attachment_unsupported_type: "Tipo de archivo no admitido"
142
+ attachment_unsupported_type: "Tipo de archivo no admitido",
143
+ attachment_open: "Abrir adjunto",
144
+ attachment_image_alt: "Imagen adjunta",
145
+ attachment_location: "Ubicaci\xF3n compartida"
140
146
  };
141
147
 
142
148
  // src/i18n/locales/pt-BR.ts
@@ -167,7 +173,10 @@ var ptBR = {
167
173
  drop_files_here: "Solte os arquivos aqui",
168
174
  incident_dismiss: "Dispensar",
169
175
  incident_default_link_label: "Saiba mais",
170
- attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado"
176
+ attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado",
177
+ attachment_open: "Abrir anexo",
178
+ attachment_image_alt: "Imagem anexada",
179
+ attachment_location: "Localiza\xE7\xE3o compartilhada"
171
180
  };
172
181
 
173
182
  // src/i18n/locales/pt-PT.ts
@@ -198,7 +207,10 @@ var ptPT = {
198
207
  drop_files_here: "Largue os ficheiros aqui",
199
208
  incident_dismiss: "Dispensar",
200
209
  incident_default_link_label: "Saiba mais",
201
- attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado"
210
+ attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado",
211
+ attachment_open: "Abrir anexo",
212
+ attachment_image_alt: "Imagem anexa",
213
+ attachment_location: "Localiza\xE7\xE3o partilhada"
202
214
  };
203
215
 
204
216
  // src/i18n/locales/fr.ts
@@ -229,7 +241,10 @@ var fr = {
229
241
  drop_files_here: "D\xE9posez les fichiers ici",
230
242
  incident_dismiss: "Ignorer",
231
243
  incident_default_link_label: "En savoir plus",
232
- attachment_unsupported_type: "Type de fichier non pris en charge"
244
+ attachment_unsupported_type: "Type de fichier non pris en charge",
245
+ attachment_open: "Ouvrir la pi\xE8ce jointe",
246
+ attachment_image_alt: "Pi\xE8ce jointe (image)",
247
+ attachment_location: "Position partag\xE9e"
233
248
  };
234
249
 
235
250
  // src/i18n/locales/de.ts
@@ -260,7 +275,10 @@ var de = {
260
275
  drop_files_here: "Dateien hier ablegen",
261
276
  incident_dismiss: "Schlie\xDFen",
262
277
  incident_default_link_label: "Mehr erfahren",
263
- attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt"
278
+ attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt",
279
+ attachment_open: "Anhang \xF6ffnen",
280
+ attachment_image_alt: "Bildanhang",
281
+ attachment_location: "Geteilter Standort"
264
282
  };
265
283
 
266
284
  // src/i18n/locales/it.ts
@@ -291,7 +309,10 @@ var it = {
291
309
  drop_files_here: "Trascina qui i file",
292
310
  incident_dismiss: "Chiudi",
293
311
  incident_default_link_label: "Scopri di pi\xF9",
294
- attachment_unsupported_type: "Tipo di file non supportato"
312
+ attachment_unsupported_type: "Tipo di file non supportato",
313
+ attachment_open: "Apri allegato",
314
+ attachment_image_alt: "Allegato immagine",
315
+ attachment_location: "Posizione condivisa"
295
316
  };
296
317
 
297
318
  // src/i18n/locales/nl.ts
@@ -322,7 +343,10 @@ var nl = {
322
343
  drop_files_here: "Sleep bestanden hier",
323
344
  incident_dismiss: "Sluiten",
324
345
  incident_default_link_label: "Meer informatie",
325
- attachment_unsupported_type: "Bestandstype niet ondersteund"
346
+ attachment_unsupported_type: "Bestandstype niet ondersteund",
347
+ attachment_open: "Bijlage openen",
348
+ attachment_image_alt: "Afbeeldingsbijlage",
349
+ attachment_location: "Gedeelde locatie"
326
350
  };
327
351
 
328
352
  // src/i18n/locales/pl.ts
@@ -353,7 +377,10 @@ var pl = {
353
377
  drop_files_here: "Upu\u015B\u0107 pliki tutaj",
354
378
  incident_dismiss: "Zamknij",
355
379
  incident_default_link_label: "Dowiedz si\u0119 wi\u0119cej",
356
- attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku"
380
+ attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku",
381
+ attachment_open: "Otw\xF3rz za\u0142\u0105cznik",
382
+ attachment_image_alt: "Za\u0142\u0105cznik obrazu",
383
+ attachment_location: "Udost\u0119pniona lokalizacja"
357
384
  };
358
385
 
359
386
  // src/i18n/locales/tr.ts
@@ -384,7 +411,10 @@ var tr = {
384
411
  drop_files_here: "Dosyalar\u0131 buraya b\u0131rak",
385
412
  incident_dismiss: "Kapat",
386
413
  incident_default_link_label: "Daha fazla bilgi",
387
- attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC"
414
+ attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC",
415
+ attachment_open: "Eki a\xE7",
416
+ attachment_image_alt: "Resim eki",
417
+ attachment_location: "Payla\u015F\u0131lan konum"
388
418
  };
389
419
 
390
420
  // src/i18n/locales/ar.ts
@@ -415,7 +445,10 @@ var ar = {
415
445
  drop_files_here: "\u0623\u0641\u0644\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627",
416
446
  incident_dismiss: "\u0625\u063A\u0644\u0627\u0642",
417
447
  incident_default_link_label: "\u0627\u0639\u0631\u0641 \u0627\u0644\u0645\u0632\u064A\u062F",
418
- attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645"
448
+ attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645",
449
+ attachment_open: "\u0641\u062A\u062D \u0627\u0644\u0645\u0631\u0641\u0642",
450
+ attachment_image_alt: "\u0635\u0648\u0631\u0629 \u0645\u0631\u0641\u0642\u0629",
451
+ attachment_location: "\u0645\u0648\u0642\u0639 \u0645\u0634\u062A\u0631\u0643"
419
452
  };
420
453
 
421
454
  // src/i18n/locales/ja.ts
@@ -446,7 +479,10 @@ var ja = {
446
479
  drop_files_here: "\u30D5\u30A1\u30A4\u30EB\u3092\u3053\u3053\u306B\u30C9\u30ED\u30C3\u30D7",
447
480
  incident_dismiss: "\u9589\u3058\u308B",
448
481
  incident_default_link_label: "\u8A73\u7D30\u3092\u898B\u308B",
449
- attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F"
482
+ attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F",
483
+ attachment_open: "\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F",
484
+ attachment_image_alt: "\u753B\u50CF\u306E\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB",
485
+ attachment_location: "\u5171\u6709\u3055\u308C\u305F\u4F4D\u7F6E\u60C5\u5831"
450
486
  };
451
487
 
452
488
  // src/i18n/locales/ko.ts
@@ -477,7 +513,10 @@ var ko = {
477
513
  drop_files_here: "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uAE30",
478
514
  incident_dismiss: "\uB2EB\uAE30",
479
515
  incident_default_link_label: "\uC790\uC138\uD788 \uC54C\uC544\uBCF4\uAE30",
480
- attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD"
516
+ attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD",
517
+ attachment_open: "\uCCA8\uBD80 \uD30C\uC77C \uC5F4\uAE30",
518
+ attachment_image_alt: "\uC774\uBBF8\uC9C0 \uCCA8\uBD80 \uD30C\uC77C",
519
+ attachment_location: "\uACF5\uC720\uB41C \uC704\uCE58"
481
520
  };
482
521
 
483
522
  // src/i18n/locales/zh-CN.ts
@@ -508,7 +547,10 @@ var zhCN = {
508
547
  drop_files_here: "\u5C06\u6587\u4EF6\u62D6\u653E\u5230\u6B64\u5904",
509
548
  incident_dismiss: "\u5173\u95ED",
510
549
  incident_default_link_label: "\u4E86\u89E3\u66F4\u591A",
511
- attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B"
550
+ attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B",
551
+ attachment_open: "\u6253\u5F00\u9644\u4EF6",
552
+ attachment_image_alt: "\u56FE\u7247\u9644\u4EF6",
553
+ attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
512
554
  };
513
555
 
514
556
  // src/i18n/locales/zh-TW.ts
@@ -539,7 +581,10 @@ var zhTW = {
539
581
  drop_files_here: "\u5C07\u6A94\u6848\u62D6\u653E\u5230\u6B64\u8655",
540
582
  incident_dismiss: "\u95DC\u9589",
541
583
  incident_default_link_label: "\u77AD\u89E3\u66F4\u591A",
542
- attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B"
584
+ attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B",
585
+ attachment_open: "\u958B\u555F\u9644\u4EF6",
586
+ attachment_image_alt: "\u5716\u7247\u9644\u4EF6",
587
+ attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
543
588
  };
544
589
 
545
590
  // src/i18n/index.ts
@@ -1319,12 +1364,15 @@ var CustomerHeroChat = class {
1319
1364
  const { chatbotId, apiBase } = this.state.config;
1320
1365
  const { conversationId } = this.state;
1321
1366
  if (!conversationId) return;
1367
+ const readToken = this.storage?.getItem(`ch_conv_token_${chatbotId}`);
1368
+ const messagesUrl = `${apiBase}/api/chat/${chatbotId}/messages/${conversationId}`;
1322
1369
  try {
1323
1370
  const response = await fetch(
1324
- `${apiBase}/api/chat/${chatbotId}/messages/${conversationId}`
1371
+ readToken ? `${messagesUrl}?t=${encodeURIComponent(readToken)}` : messagesUrl
1325
1372
  );
1326
1373
  if (!response.ok) {
1327
1374
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1375
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1328
1376
  this.setState({ conversationId: null });
1329
1377
  return;
1330
1378
  }
@@ -1336,7 +1384,8 @@ var CustomerHeroChat = class {
1336
1384
  content: m.content,
1337
1385
  ...m.sources ? { sources: m.sources } : {},
1338
1386
  ...m.blocks ? { blocks: m.blocks } : {},
1339
- ...m.suggestions ? { suggestions: m.suggestions } : {}
1387
+ ...m.suggestions ? { suggestions: m.suggestions } : {},
1388
+ ...m.attachments?.length ? { attachments: m.attachments } : {}
1340
1389
  }));
1341
1390
  const lastBotIndex = findLastIndex(
1342
1391
  messages,
@@ -1440,6 +1489,16 @@ var CustomerHeroChat = class {
1440
1489
  }
1441
1490
  break;
1442
1491
  }
1492
+ case "read-token": {
1493
+ const tok = safeParse(evt.data);
1494
+ if (tok?.readToken) {
1495
+ this.storage?.setItem(
1496
+ `ch_conv_token_${chatbotId}`,
1497
+ tok.readToken
1498
+ );
1499
+ }
1500
+ break;
1501
+ }
1443
1502
  case "token": {
1444
1503
  const tok = safeParse(evt.data);
1445
1504
  const text = tok?.text ?? "";
@@ -1552,6 +1611,9 @@ var CustomerHeroChat = class {
1552
1611
  await this.loadHistory();
1553
1612
  return;
1554
1613
  }
1614
+ const decisionBlock = this.state.messages[targetIndex].blocks?.find(
1615
+ (b) => b.type === "action_confirmation" && b.pendingToolCallId === pendingId
1616
+ );
1555
1617
  const messages = this.state.messages.slice();
1556
1618
  const original = messages[targetIndex];
1557
1619
  messages[targetIndex] = {
@@ -1560,7 +1622,8 @@ var CustomerHeroChat = class {
1560
1622
  };
1561
1623
  this.setState({ messages, error: null });
1562
1624
  const { chatbotId, apiBase } = this.state.config;
1563
- const url = `${apiBase}/api/chat/${chatbotId}/tool-calls/${pendingId}/decision`;
1625
+ const href = decision === "approve" ? decisionBlock?.approveHref : decisionBlock?.cancelHref;
1626
+ const url = href ? `${apiBase}${href}` : `${apiBase}/api/chat/${chatbotId}/tool-calls/${pendingId}/decision`;
1564
1627
  try {
1565
1628
  const response = await fetch(url, {
1566
1629
  method: "POST",
@@ -1592,6 +1655,16 @@ var CustomerHeroChat = class {
1592
1655
  }
1593
1656
  break;
1594
1657
  }
1658
+ case "read-token": {
1659
+ const tok = safeParse(evt.data);
1660
+ if (tok?.readToken) {
1661
+ this.storage?.setItem(
1662
+ `ch_conv_token_${chatbotId}`,
1663
+ tok.readToken
1664
+ );
1665
+ }
1666
+ break;
1667
+ }
1595
1668
  case "token": {
1596
1669
  const tok = safeParse(evt.data);
1597
1670
  const text = tok?.text ?? "";
@@ -1698,6 +1771,7 @@ var CustomerHeroChat = class {
1698
1771
  reset() {
1699
1772
  const { chatbotId, welcomeMessage } = this.state.config;
1700
1773
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1774
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1701
1775
  this.setState({
1702
1776
  messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
1703
1777
  conversationId: null,
@@ -1865,6 +1939,7 @@ var CustomerHeroChat = class {
1865
1939
  };
1866
1940
  const { chatbotId, welcomeMessage } = this.state.config;
1867
1941
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1942
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1868
1943
  this.setState({
1869
1944
  messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
1870
1945
  conversationId: null,
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- type TranslationKey = "online" | "typing" | "unable_to_load" | "powered_by" | "new_conversation" | "open_chat" | "close_chat" | "send_message" | "helpful" | "not_helpful" | "menu" | "action_approve" | "action_cancel" | "action_what_will_happen" | "action_already_resolved" | "action_failed" | "status_sending" | "status_sent" | "status_failed" | "screenshot_capture" | "attachment_remove" | "attach_menu_open" | "attach_photo" | "drop_files_here" | "attachment_unsupported_type" | "incident_dismiss" | "incident_default_link_label";
1
+ type TranslationKey = "online" | "typing" | "unable_to_load" | "powered_by" | "new_conversation" | "open_chat" | "close_chat" | "send_message" | "helpful" | "not_helpful" | "menu" | "action_approve" | "action_cancel" | "action_what_will_happen" | "action_already_resolved" | "action_failed" | "status_sending" | "status_sent" | "status_failed" | "screenshot_capture" | "attachment_remove" | "attach_menu_open" | "attach_photo" | "drop_files_here" | "attachment_unsupported_type" | "attachment_open" | "attachment_image_alt" | "attachment_location" | "incident_dismiss" | "incident_default_link_label";
2
2
  type Translations = Record<TranslationKey, string>;
3
3
 
4
4
  declare const SUPPORTED_LOCALES: readonly ["en", "es", "pt-BR", "pt-PT", "fr", "de", "it", "nl", "pl", "tr", "ar", "ja", "ko", "zh-CN", "zh-TW"];
@@ -137,6 +137,27 @@ type ActionConfirmationBlock = {
137
137
  };
138
138
  type MessageBlock = QuickRepliesBlock | ActionConfirmationBlock;
139
139
  type MessageStatus = "sending" | "sent" | "failed";
140
+ /**
141
+ * Attachment hung off a historical message. The widget only ever uploads
142
+ * `image` and `document` kinds, but inbox agents can attach `audio` /
143
+ * `video` / `location` from the dashboard, and the history endpoint returns
144
+ * everything the conversation has accumulated.
145
+ */
146
+ interface MessageAttachment {
147
+ id: string;
148
+ kind: "image" | "document" | "audio" | "video" | "location";
149
+ mimeType: string | null;
150
+ filename: string | null;
151
+ sizeBytes: number | null;
152
+ /** Public R2 URL. Null for `location` attachments (use `location` instead). */
153
+ url: string | null;
154
+ /** Geo payload for `location` attachments. */
155
+ location: {
156
+ label?: string | null;
157
+ latitude: number;
158
+ longitude: number;
159
+ } | null;
160
+ }
140
161
  interface ChatMessage {
141
162
  /** Message ID from the API (only present for bot messages) */
142
163
  id?: string;
@@ -151,6 +172,11 @@ interface ChatMessage {
151
172
  * tappable chips under the most recent bot message only.
152
173
  */
153
174
  suggestions?: string[];
175
+ /**
176
+ * Files / screenshots / locations attached to this message. Populated from
177
+ * the history endpoint on conversation reload.
178
+ */
179
+ attachments?: MessageAttachment[];
154
180
  /** True while this message is still receiving streaming tokens. */
155
181
  streaming?: boolean;
156
182
  /**
@@ -617,4 +643,4 @@ interface StartTriggersRuntimeOptions {
617
643
  }
618
644
  declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
619
645
 
620
- export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
646
+ export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageAttachment, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- type TranslationKey = "online" | "typing" | "unable_to_load" | "powered_by" | "new_conversation" | "open_chat" | "close_chat" | "send_message" | "helpful" | "not_helpful" | "menu" | "action_approve" | "action_cancel" | "action_what_will_happen" | "action_already_resolved" | "action_failed" | "status_sending" | "status_sent" | "status_failed" | "screenshot_capture" | "attachment_remove" | "attach_menu_open" | "attach_photo" | "drop_files_here" | "attachment_unsupported_type" | "incident_dismiss" | "incident_default_link_label";
1
+ type TranslationKey = "online" | "typing" | "unable_to_load" | "powered_by" | "new_conversation" | "open_chat" | "close_chat" | "send_message" | "helpful" | "not_helpful" | "menu" | "action_approve" | "action_cancel" | "action_what_will_happen" | "action_already_resolved" | "action_failed" | "status_sending" | "status_sent" | "status_failed" | "screenshot_capture" | "attachment_remove" | "attach_menu_open" | "attach_photo" | "drop_files_here" | "attachment_unsupported_type" | "attachment_open" | "attachment_image_alt" | "attachment_location" | "incident_dismiss" | "incident_default_link_label";
2
2
  type Translations = Record<TranslationKey, string>;
3
3
 
4
4
  declare const SUPPORTED_LOCALES: readonly ["en", "es", "pt-BR", "pt-PT", "fr", "de", "it", "nl", "pl", "tr", "ar", "ja", "ko", "zh-CN", "zh-TW"];
@@ -137,6 +137,27 @@ type ActionConfirmationBlock = {
137
137
  };
138
138
  type MessageBlock = QuickRepliesBlock | ActionConfirmationBlock;
139
139
  type MessageStatus = "sending" | "sent" | "failed";
140
+ /**
141
+ * Attachment hung off a historical message. The widget only ever uploads
142
+ * `image` and `document` kinds, but inbox agents can attach `audio` /
143
+ * `video` / `location` from the dashboard, and the history endpoint returns
144
+ * everything the conversation has accumulated.
145
+ */
146
+ interface MessageAttachment {
147
+ id: string;
148
+ kind: "image" | "document" | "audio" | "video" | "location";
149
+ mimeType: string | null;
150
+ filename: string | null;
151
+ sizeBytes: number | null;
152
+ /** Public R2 URL. Null for `location` attachments (use `location` instead). */
153
+ url: string | null;
154
+ /** Geo payload for `location` attachments. */
155
+ location: {
156
+ label?: string | null;
157
+ latitude: number;
158
+ longitude: number;
159
+ } | null;
160
+ }
140
161
  interface ChatMessage {
141
162
  /** Message ID from the API (only present for bot messages) */
142
163
  id?: string;
@@ -151,6 +172,11 @@ interface ChatMessage {
151
172
  * tappable chips under the most recent bot message only.
152
173
  */
153
174
  suggestions?: string[];
175
+ /**
176
+ * Files / screenshots / locations attached to this message. Populated from
177
+ * the history endpoint on conversation reload.
178
+ */
179
+ attachments?: MessageAttachment[];
154
180
  /** True while this message is still receiving streaming tokens. */
155
181
  streaming?: boolean;
156
182
  /**
@@ -617,4 +643,4 @@ interface StartTriggersRuntimeOptions {
617
643
  }
618
644
  declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
619
645
 
620
- export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
646
+ export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageAttachment, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
package/dist/index.js CHANGED
@@ -60,7 +60,10 @@ var en = {
60
60
  drop_files_here: "Drop files here",
61
61
  incident_dismiss: "Dismiss",
62
62
  incident_default_link_label: "Learn more",
63
- attachment_unsupported_type: "Unsupported file type"
63
+ attachment_unsupported_type: "Unsupported file type",
64
+ attachment_open: "Open attachment",
65
+ attachment_image_alt: "Image attachment",
66
+ attachment_location: "Shared location"
64
67
  };
65
68
 
66
69
  // src/i18n/locales/es.ts
@@ -91,7 +94,10 @@ var es = {
91
94
  drop_files_here: "Suelta los archivos aqu\xED",
92
95
  incident_dismiss: "Descartar",
93
96
  incident_default_link_label: "M\xE1s informaci\xF3n",
94
- attachment_unsupported_type: "Tipo de archivo no admitido"
97
+ attachment_unsupported_type: "Tipo de archivo no admitido",
98
+ attachment_open: "Abrir adjunto",
99
+ attachment_image_alt: "Imagen adjunta",
100
+ attachment_location: "Ubicaci\xF3n compartida"
95
101
  };
96
102
 
97
103
  // src/i18n/locales/pt-BR.ts
@@ -122,7 +128,10 @@ var ptBR = {
122
128
  drop_files_here: "Solte os arquivos aqui",
123
129
  incident_dismiss: "Dispensar",
124
130
  incident_default_link_label: "Saiba mais",
125
- attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado"
131
+ attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado",
132
+ attachment_open: "Abrir anexo",
133
+ attachment_image_alt: "Imagem anexada",
134
+ attachment_location: "Localiza\xE7\xE3o compartilhada"
126
135
  };
127
136
 
128
137
  // src/i18n/locales/pt-PT.ts
@@ -153,7 +162,10 @@ var ptPT = {
153
162
  drop_files_here: "Largue os ficheiros aqui",
154
163
  incident_dismiss: "Dispensar",
155
164
  incident_default_link_label: "Saiba mais",
156
- attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado"
165
+ attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado",
166
+ attachment_open: "Abrir anexo",
167
+ attachment_image_alt: "Imagem anexa",
168
+ attachment_location: "Localiza\xE7\xE3o partilhada"
157
169
  };
158
170
 
159
171
  // src/i18n/locales/fr.ts
@@ -184,7 +196,10 @@ var fr = {
184
196
  drop_files_here: "D\xE9posez les fichiers ici",
185
197
  incident_dismiss: "Ignorer",
186
198
  incident_default_link_label: "En savoir plus",
187
- attachment_unsupported_type: "Type de fichier non pris en charge"
199
+ attachment_unsupported_type: "Type de fichier non pris en charge",
200
+ attachment_open: "Ouvrir la pi\xE8ce jointe",
201
+ attachment_image_alt: "Pi\xE8ce jointe (image)",
202
+ attachment_location: "Position partag\xE9e"
188
203
  };
189
204
 
190
205
  // src/i18n/locales/de.ts
@@ -215,7 +230,10 @@ var de = {
215
230
  drop_files_here: "Dateien hier ablegen",
216
231
  incident_dismiss: "Schlie\xDFen",
217
232
  incident_default_link_label: "Mehr erfahren",
218
- attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt"
233
+ attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt",
234
+ attachment_open: "Anhang \xF6ffnen",
235
+ attachment_image_alt: "Bildanhang",
236
+ attachment_location: "Geteilter Standort"
219
237
  };
220
238
 
221
239
  // src/i18n/locales/it.ts
@@ -246,7 +264,10 @@ var it = {
246
264
  drop_files_here: "Trascina qui i file",
247
265
  incident_dismiss: "Chiudi",
248
266
  incident_default_link_label: "Scopri di pi\xF9",
249
- attachment_unsupported_type: "Tipo di file non supportato"
267
+ attachment_unsupported_type: "Tipo di file non supportato",
268
+ attachment_open: "Apri allegato",
269
+ attachment_image_alt: "Allegato immagine",
270
+ attachment_location: "Posizione condivisa"
250
271
  };
251
272
 
252
273
  // src/i18n/locales/nl.ts
@@ -277,7 +298,10 @@ var nl = {
277
298
  drop_files_here: "Sleep bestanden hier",
278
299
  incident_dismiss: "Sluiten",
279
300
  incident_default_link_label: "Meer informatie",
280
- attachment_unsupported_type: "Bestandstype niet ondersteund"
301
+ attachment_unsupported_type: "Bestandstype niet ondersteund",
302
+ attachment_open: "Bijlage openen",
303
+ attachment_image_alt: "Afbeeldingsbijlage",
304
+ attachment_location: "Gedeelde locatie"
281
305
  };
282
306
 
283
307
  // src/i18n/locales/pl.ts
@@ -308,7 +332,10 @@ var pl = {
308
332
  drop_files_here: "Upu\u015B\u0107 pliki tutaj",
309
333
  incident_dismiss: "Zamknij",
310
334
  incident_default_link_label: "Dowiedz si\u0119 wi\u0119cej",
311
- attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku"
335
+ attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku",
336
+ attachment_open: "Otw\xF3rz za\u0142\u0105cznik",
337
+ attachment_image_alt: "Za\u0142\u0105cznik obrazu",
338
+ attachment_location: "Udost\u0119pniona lokalizacja"
312
339
  };
313
340
 
314
341
  // src/i18n/locales/tr.ts
@@ -339,7 +366,10 @@ var tr = {
339
366
  drop_files_here: "Dosyalar\u0131 buraya b\u0131rak",
340
367
  incident_dismiss: "Kapat",
341
368
  incident_default_link_label: "Daha fazla bilgi",
342
- attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC"
369
+ attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC",
370
+ attachment_open: "Eki a\xE7",
371
+ attachment_image_alt: "Resim eki",
372
+ attachment_location: "Payla\u015F\u0131lan konum"
343
373
  };
344
374
 
345
375
  // src/i18n/locales/ar.ts
@@ -370,7 +400,10 @@ var ar = {
370
400
  drop_files_here: "\u0623\u0641\u0644\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627",
371
401
  incident_dismiss: "\u0625\u063A\u0644\u0627\u0642",
372
402
  incident_default_link_label: "\u0627\u0639\u0631\u0641 \u0627\u0644\u0645\u0632\u064A\u062F",
373
- attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645"
403
+ attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645",
404
+ attachment_open: "\u0641\u062A\u062D \u0627\u0644\u0645\u0631\u0641\u0642",
405
+ attachment_image_alt: "\u0635\u0648\u0631\u0629 \u0645\u0631\u0641\u0642\u0629",
406
+ attachment_location: "\u0645\u0648\u0642\u0639 \u0645\u0634\u062A\u0631\u0643"
374
407
  };
375
408
 
376
409
  // src/i18n/locales/ja.ts
@@ -401,7 +434,10 @@ var ja = {
401
434
  drop_files_here: "\u30D5\u30A1\u30A4\u30EB\u3092\u3053\u3053\u306B\u30C9\u30ED\u30C3\u30D7",
402
435
  incident_dismiss: "\u9589\u3058\u308B",
403
436
  incident_default_link_label: "\u8A73\u7D30\u3092\u898B\u308B",
404
- attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F"
437
+ attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F",
438
+ attachment_open: "\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F",
439
+ attachment_image_alt: "\u753B\u50CF\u306E\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB",
440
+ attachment_location: "\u5171\u6709\u3055\u308C\u305F\u4F4D\u7F6E\u60C5\u5831"
405
441
  };
406
442
 
407
443
  // src/i18n/locales/ko.ts
@@ -432,7 +468,10 @@ var ko = {
432
468
  drop_files_here: "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uAE30",
433
469
  incident_dismiss: "\uB2EB\uAE30",
434
470
  incident_default_link_label: "\uC790\uC138\uD788 \uC54C\uC544\uBCF4\uAE30",
435
- attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD"
471
+ attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD",
472
+ attachment_open: "\uCCA8\uBD80 \uD30C\uC77C \uC5F4\uAE30",
473
+ attachment_image_alt: "\uC774\uBBF8\uC9C0 \uCCA8\uBD80 \uD30C\uC77C",
474
+ attachment_location: "\uACF5\uC720\uB41C \uC704\uCE58"
436
475
  };
437
476
 
438
477
  // src/i18n/locales/zh-CN.ts
@@ -463,7 +502,10 @@ var zhCN = {
463
502
  drop_files_here: "\u5C06\u6587\u4EF6\u62D6\u653E\u5230\u6B64\u5904",
464
503
  incident_dismiss: "\u5173\u95ED",
465
504
  incident_default_link_label: "\u4E86\u89E3\u66F4\u591A",
466
- attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B"
505
+ attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B",
506
+ attachment_open: "\u6253\u5F00\u9644\u4EF6",
507
+ attachment_image_alt: "\u56FE\u7247\u9644\u4EF6",
508
+ attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
467
509
  };
468
510
 
469
511
  // src/i18n/locales/zh-TW.ts
@@ -494,7 +536,10 @@ var zhTW = {
494
536
  drop_files_here: "\u5C07\u6A94\u6848\u62D6\u653E\u5230\u6B64\u8655",
495
537
  incident_dismiss: "\u95DC\u9589",
496
538
  incident_default_link_label: "\u77AD\u89E3\u66F4\u591A",
497
- attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B"
539
+ attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B",
540
+ attachment_open: "\u958B\u555F\u9644\u4EF6",
541
+ attachment_image_alt: "\u5716\u7247\u9644\u4EF6",
542
+ attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
498
543
  };
499
544
 
500
545
  // src/i18n/index.ts
@@ -1274,12 +1319,15 @@ var CustomerHeroChat = class {
1274
1319
  const { chatbotId, apiBase } = this.state.config;
1275
1320
  const { conversationId } = this.state;
1276
1321
  if (!conversationId) return;
1322
+ const readToken = this.storage?.getItem(`ch_conv_token_${chatbotId}`);
1323
+ const messagesUrl = `${apiBase}/api/chat/${chatbotId}/messages/${conversationId}`;
1277
1324
  try {
1278
1325
  const response = await fetch(
1279
- `${apiBase}/api/chat/${chatbotId}/messages/${conversationId}`
1326
+ readToken ? `${messagesUrl}?t=${encodeURIComponent(readToken)}` : messagesUrl
1280
1327
  );
1281
1328
  if (!response.ok) {
1282
1329
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1330
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1283
1331
  this.setState({ conversationId: null });
1284
1332
  return;
1285
1333
  }
@@ -1291,7 +1339,8 @@ var CustomerHeroChat = class {
1291
1339
  content: m.content,
1292
1340
  ...m.sources ? { sources: m.sources } : {},
1293
1341
  ...m.blocks ? { blocks: m.blocks } : {},
1294
- ...m.suggestions ? { suggestions: m.suggestions } : {}
1342
+ ...m.suggestions ? { suggestions: m.suggestions } : {},
1343
+ ...m.attachments?.length ? { attachments: m.attachments } : {}
1295
1344
  }));
1296
1345
  const lastBotIndex = findLastIndex(
1297
1346
  messages,
@@ -1395,6 +1444,16 @@ var CustomerHeroChat = class {
1395
1444
  }
1396
1445
  break;
1397
1446
  }
1447
+ case "read-token": {
1448
+ const tok = safeParse(evt.data);
1449
+ if (tok?.readToken) {
1450
+ this.storage?.setItem(
1451
+ `ch_conv_token_${chatbotId}`,
1452
+ tok.readToken
1453
+ );
1454
+ }
1455
+ break;
1456
+ }
1398
1457
  case "token": {
1399
1458
  const tok = safeParse(evt.data);
1400
1459
  const text = tok?.text ?? "";
@@ -1507,6 +1566,9 @@ var CustomerHeroChat = class {
1507
1566
  await this.loadHistory();
1508
1567
  return;
1509
1568
  }
1569
+ const decisionBlock = this.state.messages[targetIndex].blocks?.find(
1570
+ (b) => b.type === "action_confirmation" && b.pendingToolCallId === pendingId
1571
+ );
1510
1572
  const messages = this.state.messages.slice();
1511
1573
  const original = messages[targetIndex];
1512
1574
  messages[targetIndex] = {
@@ -1515,7 +1577,8 @@ var CustomerHeroChat = class {
1515
1577
  };
1516
1578
  this.setState({ messages, error: null });
1517
1579
  const { chatbotId, apiBase } = this.state.config;
1518
- const url = `${apiBase}/api/chat/${chatbotId}/tool-calls/${pendingId}/decision`;
1580
+ const href = decision === "approve" ? decisionBlock?.approveHref : decisionBlock?.cancelHref;
1581
+ const url = href ? `${apiBase}${href}` : `${apiBase}/api/chat/${chatbotId}/tool-calls/${pendingId}/decision`;
1519
1582
  try {
1520
1583
  const response = await fetch(url, {
1521
1584
  method: "POST",
@@ -1547,6 +1610,16 @@ var CustomerHeroChat = class {
1547
1610
  }
1548
1611
  break;
1549
1612
  }
1613
+ case "read-token": {
1614
+ const tok = safeParse(evt.data);
1615
+ if (tok?.readToken) {
1616
+ this.storage?.setItem(
1617
+ `ch_conv_token_${chatbotId}`,
1618
+ tok.readToken
1619
+ );
1620
+ }
1621
+ break;
1622
+ }
1550
1623
  case "token": {
1551
1624
  const tok = safeParse(evt.data);
1552
1625
  const text = tok?.text ?? "";
@@ -1653,6 +1726,7 @@ var CustomerHeroChat = class {
1653
1726
  reset() {
1654
1727
  const { chatbotId, welcomeMessage } = this.state.config;
1655
1728
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1729
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1656
1730
  this.setState({
1657
1731
  messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
1658
1732
  conversationId: null,
@@ -1820,6 +1894,7 @@ var CustomerHeroChat = class {
1820
1894
  };
1821
1895
  const { chatbotId, welcomeMessage } = this.state.config;
1822
1896
  this.storage?.removeItem(`ch_conv_${chatbotId}`);
1897
+ this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
1823
1898
  this.setState({
1824
1899
  messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
1825
1900
  conversationId: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@customerhero/js",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "private": false,
5
5
  "description": "Framework-agnostic JavaScript client for the CustomerHero chat widget.",
6
6
  "keywords": [