claudius-chat-widget 1.14.0 → 1.16.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.d.cts CHANGED
@@ -15,6 +15,29 @@ export declare interface AnalyticsPluginOptions {
15
15
  includeContent?: boolean;
16
16
  }
17
17
 
18
+ /**
19
+ * Client-side attachment limits. Pass to {@link ChatWidget} via the
20
+ * `attachments` prop (or `true` for the defaults). The worker enforces its own
21
+ * limits independently; keep the two in sync so uploads aren't rejected late.
22
+ */
23
+ export declare interface AttachmentsOptions {
24
+ /**
25
+ * Largest file accepted, in bytes.
26
+ * @defaultValue `5 * 1024 * 1024` (5 MB)
27
+ */
28
+ maxSizeBytes?: number;
29
+ /**
30
+ * Maximum number of files per message.
31
+ * @defaultValue `5`
32
+ */
33
+ maxCount?: number;
34
+ /**
35
+ * Accepted MIME types.
36
+ * @defaultValue `["image/jpeg", "image/png", "image/gif", "image/webp", "application/pdf"]`
37
+ */
38
+ allowedTypes?: string[];
39
+ }
40
+
18
41
  /**
19
42
  * Context for {@link ClaudiusPlugin.onBeforeSend}. Adds the ability to
20
43
  * short-circuit the request before it reaches the network.
@@ -74,6 +97,12 @@ export declare interface CannedRule {
74
97
  * per-attempt timeouts, and automatic retries with backoff for transient
75
98
  * failures (HTTP 429/503, network errors, timeouts).
76
99
  *
100
+ * Conversations without inline attachment bytes are posted as JSON. When any
101
+ * message carries an attachment with `data`, the request is sent as
102
+ * `multipart/form-data`: a `payload` field holding the JSON body (attachment
103
+ * refs without their bytes) plus one file part per attachment, named after
104
+ * the attachment id.
105
+ *
77
106
  * @example
78
107
  * ```ts
79
108
  * const client = new ChatApiClient("https://api.example.com");
@@ -106,6 +135,12 @@ export declare class ChatApiClient {
106
135
  * @throws {@link ChatApiError} when the request fails after all retries.
107
136
  */
108
137
  sendMessage(messages: ChatMessage[]): Promise<ChatResponse>;
138
+ /**
139
+ * Build the request body: JSON by default, multipart when any attachment
140
+ * still carries inline bytes. A fresh body is built per attempt so retries
141
+ * never reuse a consumed stream.
142
+ */
143
+ private buildRequest;
109
144
  /**
110
145
  * Send the conversation to the streaming chat endpoint and resolve with the
111
146
  * assistant's full reply once the stream completes. Text deltas are
@@ -193,6 +228,34 @@ export declare class ChatApiClient {
193
228
  retryAfter?: number | undefined);
194
229
  }
195
230
 
231
+ /**
232
+ * A file (image or PDF) attached to a user message.
233
+ *
234
+ * Bytes travel inline as base64 `data` until the worker stores them (R2
235
+ * backend), after which the widget keeps only the storage `key` and a signed
236
+ * preview `url`. Persisted history never includes `data`; an attachment with
237
+ * neither `data` nor `key` is shown by name only and described to the model
238
+ * as no longer available.
239
+ */
240
+ export declare interface ChatAttachment {
241
+ /** Client-generated id, unique within the conversation. */
242
+ id: string;
243
+ /** Original filename. */
244
+ name: string;
245
+ /** MIME type, e.g. `"image/png"` or `"application/pdf"`. */
246
+ mediaType: string;
247
+ /** Size in bytes. */
248
+ size: number;
249
+ /** Base64-encoded bytes without a `data:` prefix. */
250
+ data?: string;
251
+ /** Worker storage key, present once the worker's R2 backend stored the file. */
252
+ key?: string;
253
+ /** Signed preview/download URL for a stored file, valid until {@link ChatAttachment.expiresAt}. */
254
+ url?: string;
255
+ /** ISO 8601 timestamp after which the stored file and its `url` expire. */
256
+ expiresAt?: string;
257
+ }
258
+
196
259
  /**
197
260
  * Error response body returned by the Worker when a chat request fails.
198
261
  */
@@ -211,10 +274,12 @@ export declare class ChatApiClient {
211
274
  id: string;
212
275
  /** Who authored the message. */
213
276
  role: "user" | "assistant";
214
- /** Plain-text message body. */
277
+ /** Plain-text message body. May be empty when the message only carries attachments. */
215
278
  content: string;
216
279
  /** Sources cited by the assistant for this message, when any. */
217
280
  sources?: Source[];
281
+ /** Files attached by the user to this message, when any. */
282
+ attachments?: ChatAttachment[];
218
283
  /** Tools the assistant called while producing this message, when any. */
219
284
  toolUses?: ToolUse[];
220
285
  }
@@ -237,6 +302,8 @@ export declare class ChatApiClient {
237
302
  sources?: Source[];
238
303
  /** Tools the assistant called while producing the reply, when any. */
239
304
  toolUses?: ToolUse[];
305
+ /** Attachments the worker stored while handling this request, when any. */
306
+ attachments?: StoredAttachment[];
240
307
  }
241
308
 
242
309
  /**
@@ -280,7 +347,7 @@ export declare class ChatApiClient {
280
347
  * <ChatWidget apiUrl="https://api.example.com" title="Support" />
281
348
  * ```
282
349
  */
283
- export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, streaming, }: ChatWidgetProps): JSX_2.Element;
350
+ export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, streaming, attachments, voice, }: ChatWidgetProps): JSX_2.Element;
284
351
 
285
352
  /**
286
353
  * Props for the {@link ChatWidget} component.
@@ -339,6 +406,25 @@ export declare class ChatApiClient {
339
406
  * @defaultValue `true`
340
407
  */
341
408
  streaming?: boolean;
409
+ /**
410
+ * Let visitors attach images and PDFs (click, drag-and-drop, or paste).
411
+ * `true` enables the defaults (5 MB per file, 5 files per message, JPEG /
412
+ * PNG / GIF / WebP / PDF); pass an {@link AttachmentsOptions} to tune them.
413
+ * The worker must allow attachments too (it does by default).
414
+ * @defaultValue `false`
415
+ */
416
+ attachments?: boolean | AttachmentsOptions;
417
+ /**
418
+ * Voice features built on the browser's Web Speech API: a mic button for
419
+ * dictating messages and a read-aloud control on assistant replies. `true`
420
+ * enables both (click-to-toggle mic, no auto-submit); pass a
421
+ * {@link VoiceOptions} to choose hold-to-talk, auto-submit, a language, or
422
+ * to switch either half off. Each half renders only where the browser
423
+ * supports it. The widget never handles audio itself, but the browser's
424
+ * speech service may process it remotely; see the Voice guide.
425
+ * @defaultValue `false`
426
+ */
427
+ voice?: boolean | VoiceOptions;
342
428
  }
343
429
 
344
430
  /** An analytics event emitted by {@link pluginAnalytics}. */
@@ -449,6 +535,9 @@ export declare class ChatApiClient {
449
535
  * Every user-facing string the widget renders. Pass a {@link ClaudiusTranslations}
450
536
  * (or a partial override) to localize the UI. English is the source of truth;
451
537
  * see {@link defaultTranslations}.
538
+ *
539
+ * Strings containing `{name}` / `{max}` placeholders are interpolated at
540
+ * render time.
452
541
  */
453
542
  export declare interface ClaudiusTranslations {
454
543
  /** Chat window header title. */
@@ -479,6 +568,42 @@ export declare class ChatApiClient {
479
568
  openChat: string;
480
569
  /** Accessible label for dismissing the greeting bubble. */
481
570
  dismissGreeting: string;
571
+ /** Accessible label for the attach-file button and file picker. */
572
+ attachFile: string;
573
+ /** Accessible label prefix for removing a pending attachment (filename is appended). */
574
+ removeAttachment: string;
575
+ /** Accessible label for the list of pending attachments. */
576
+ attachmentsLabel: string;
577
+ /** Overlay hint shown while dragging files over the composer. */
578
+ dropFilesHint: string;
579
+ /** Validation message for an oversized file; supports `{name}` and `{max}`. */
580
+ attachmentTooLarge: string;
581
+ /** Validation message for a disallowed file type; supports `{name}`. */
582
+ attachmentTypeNotAllowed: string;
583
+ /** Validation message when the per-message file limit is hit; supports `{max}`. */
584
+ attachmentTooMany: string;
585
+ /** Accessible label for the mic button in toggle mode (state is exposed via `aria-pressed`). */
586
+ voiceInput: string;
587
+ /** Accessible label for the mic button in hold mode. */
588
+ voiceInputHold: string;
589
+ /** Placeholder shown in the message input while dictation is listening. */
590
+ voiceListening: string;
591
+ /** Shown when the browser or the visitor has blocked microphone access. */
592
+ voicePermissionDenied: string;
593
+ /** Shown when dictation ended without hearing any speech. */
594
+ voiceNoSpeech: string;
595
+ /** Shown when no microphone is available. */
596
+ voiceNoMicrophone: string;
597
+ /** Shown when the browser's speech service cannot be reached or does not support the language. */
598
+ voiceUnavailable: string;
599
+ /** Accessible label for the button that reads an assistant message aloud. */
600
+ readAloud: string;
601
+ /** Accessible label for pausing read-aloud playback. */
602
+ pauseReading: string;
603
+ /** Accessible label for resuming paused read-aloud playback. */
604
+ resumeReading: string;
605
+ /** Accessible label for stopping read-aloud playback. */
606
+ stopReading: string;
482
607
  /** Generic fallback error message. */
483
608
  errorGeneric: string;
484
609
  /** Error shown when the network request fails. */
@@ -489,6 +614,10 @@ export declare class ChatApiClient {
489
614
  errorRateLimitMinute: string;
490
615
  /** Error shown when rate-limited (per-hour limit). */
491
616
  errorRateLimitHour: string;
617
+ /** Error shown when the worker rejects an attachment (type, size, count, or content). */
618
+ errorAttachmentRejected: string;
619
+ /** Error shown when the worker's daily upload quota is exhausted. */
620
+ errorAttachmentQuota: string;
492
621
  /** Label for the retry action on a failed message. */
493
622
  errorRetry: string;
494
623
  }
@@ -511,6 +640,9 @@ export declare class ChatApiClient {
511
640
  constructor();
512
641
  }
513
642
 
643
+ /** Defaults applied when attachments are enabled with `true` or a partial config. */
644
+ export declare const DEFAULT_ATTACHMENT_OPTIONS: ResolvedAttachmentsConfig;
645
+
514
646
  /**
515
647
  * Default PII patterns: email addresses, North-American-style phone numbers,
516
648
  * US Social Security numbers, and 13–16 digit card-like sequences. These are
@@ -647,6 +779,12 @@ export declare class ChatApiClient {
647
779
  /** Replace every match of every pattern in `text` with `replacement`. */
648
780
  export declare function redactText(text: string, patterns: readonly RegExp[], replacement: string): string;
649
781
 
782
+ /** {@link AttachmentsOptions} with every field filled in. */
783
+ export declare type ResolvedAttachmentsConfig = Required<AttachmentsOptions>;
784
+
785
+ /** {@link VoiceOptions} with every field filled in. */
786
+ export declare type ResolvedVoiceConfig = Required<VoiceOptions>;
787
+
650
788
  /**
651
789
  * Resolve the final translations for a locale, applying any per-string
652
790
  * overrides on top of the chosen locale's defaults.
@@ -677,6 +815,21 @@ export declare class ChatApiClient {
677
815
  type: "blog" | "page" | "external";
678
816
  }
679
817
 
818
+ /**
819
+ * Storage metadata the worker returns for each attachment it persisted while
820
+ * handling a request (R2 backend only).
821
+ */
822
+ export declare interface StoredAttachment {
823
+ /** The {@link ChatAttachment.id} this entry describes. */
824
+ id: string;
825
+ /** Worker storage key to reference the file on later turns. */
826
+ key: string;
827
+ /** Signed preview/download URL, when the worker can serve the file. */
828
+ url?: string;
829
+ /** ISO 8601 expiry of the stored file. */
830
+ expiresAt: string;
831
+ }
832
+
680
833
  declare const THEME_COLOR_TOKENS: readonly ["accent", "accentText", "accentSoft", "accentTextMuted", "surface", "surfaceMuted", "text", "textMuted", "border", "userBubble", "userBubbleText", "assistantBubble", "assistantBubbleText", "field", "error", "errorSurface", "errorText", "link", "scrim"];
681
834
 
682
835
  declare const THEME_FONT_TOKENS: readonly ["heading", "body"];
@@ -762,6 +915,45 @@ export declare class ChatApiClient {
762
915
  /** A URL match: a case-insensitive substring, or a regular expression. */
763
916
  export declare type UrlPattern = string | RegExp;
764
917
 
918
+ /**
919
+ * How the mic button records: `"toggle"` starts on one click and stops on the
920
+ * next; `"hold"` records only while the button is held down.
921
+ */
922
+ export declare type VoiceInputMode = "toggle" | "hold";
923
+
924
+ /**
925
+ * Voice features. Pass to {@link ChatWidget} via the `voice` prop (or `true`
926
+ * for the defaults). Both halves rely on the browser's Web Speech API and
927
+ * render nothing where it is missing.
928
+ */
929
+ export declare interface VoiceOptions {
930
+ /**
931
+ * Show the mic button for dictating messages.
932
+ * @defaultValue `true`
933
+ */
934
+ input?: boolean;
935
+ /**
936
+ * Show the read-aloud control on completed assistant messages.
937
+ * @defaultValue `true`
938
+ */
939
+ output?: boolean;
940
+ /**
941
+ * How the mic button records.
942
+ * @defaultValue `"toggle"`
943
+ */
944
+ mode?: VoiceInputMode;
945
+ /**
946
+ * Send the dictated message as soon as recognition ends.
947
+ * @defaultValue `false`
948
+ */
949
+ autoSubmit?: boolean;
950
+ /**
951
+ * BCP-47 language tag for recognition and playback (e.g. `"en-GB"`).
952
+ * Defaults to a tag derived from the widget locale.
953
+ */
954
+ lang?: string;
955
+ }
956
+
765
957
  /** Corner of the viewport the widget docks to. */
766
958
  export declare type WidgetPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
767
959
 
package/dist/index.d.ts CHANGED
@@ -15,6 +15,29 @@ export declare interface AnalyticsPluginOptions {
15
15
  includeContent?: boolean;
16
16
  }
17
17
 
18
+ /**
19
+ * Client-side attachment limits. Pass to {@link ChatWidget} via the
20
+ * `attachments` prop (or `true` for the defaults). The worker enforces its own
21
+ * limits independently; keep the two in sync so uploads aren't rejected late.
22
+ */
23
+ export declare interface AttachmentsOptions {
24
+ /**
25
+ * Largest file accepted, in bytes.
26
+ * @defaultValue `5 * 1024 * 1024` (5 MB)
27
+ */
28
+ maxSizeBytes?: number;
29
+ /**
30
+ * Maximum number of files per message.
31
+ * @defaultValue `5`
32
+ */
33
+ maxCount?: number;
34
+ /**
35
+ * Accepted MIME types.
36
+ * @defaultValue `["image/jpeg", "image/png", "image/gif", "image/webp", "application/pdf"]`
37
+ */
38
+ allowedTypes?: string[];
39
+ }
40
+
18
41
  /**
19
42
  * Context for {@link ClaudiusPlugin.onBeforeSend}. Adds the ability to
20
43
  * short-circuit the request before it reaches the network.
@@ -74,6 +97,12 @@ export declare interface CannedRule {
74
97
  * per-attempt timeouts, and automatic retries with backoff for transient
75
98
  * failures (HTTP 429/503, network errors, timeouts).
76
99
  *
100
+ * Conversations without inline attachment bytes are posted as JSON. When any
101
+ * message carries an attachment with `data`, the request is sent as
102
+ * `multipart/form-data`: a `payload` field holding the JSON body (attachment
103
+ * refs without their bytes) plus one file part per attachment, named after
104
+ * the attachment id.
105
+ *
77
106
  * @example
78
107
  * ```ts
79
108
  * const client = new ChatApiClient("https://api.example.com");
@@ -106,6 +135,12 @@ export declare class ChatApiClient {
106
135
  * @throws {@link ChatApiError} when the request fails after all retries.
107
136
  */
108
137
  sendMessage(messages: ChatMessage[]): Promise<ChatResponse>;
138
+ /**
139
+ * Build the request body: JSON by default, multipart when any attachment
140
+ * still carries inline bytes. A fresh body is built per attempt so retries
141
+ * never reuse a consumed stream.
142
+ */
143
+ private buildRequest;
109
144
  /**
110
145
  * Send the conversation to the streaming chat endpoint and resolve with the
111
146
  * assistant's full reply once the stream completes. Text deltas are
@@ -193,6 +228,34 @@ export declare class ChatApiClient {
193
228
  retryAfter?: number | undefined);
194
229
  }
195
230
 
231
+ /**
232
+ * A file (image or PDF) attached to a user message.
233
+ *
234
+ * Bytes travel inline as base64 `data` until the worker stores them (R2
235
+ * backend), after which the widget keeps only the storage `key` and a signed
236
+ * preview `url`. Persisted history never includes `data`; an attachment with
237
+ * neither `data` nor `key` is shown by name only and described to the model
238
+ * as no longer available.
239
+ */
240
+ export declare interface ChatAttachment {
241
+ /** Client-generated id, unique within the conversation. */
242
+ id: string;
243
+ /** Original filename. */
244
+ name: string;
245
+ /** MIME type, e.g. `"image/png"` or `"application/pdf"`. */
246
+ mediaType: string;
247
+ /** Size in bytes. */
248
+ size: number;
249
+ /** Base64-encoded bytes without a `data:` prefix. */
250
+ data?: string;
251
+ /** Worker storage key, present once the worker's R2 backend stored the file. */
252
+ key?: string;
253
+ /** Signed preview/download URL for a stored file, valid until {@link ChatAttachment.expiresAt}. */
254
+ url?: string;
255
+ /** ISO 8601 timestamp after which the stored file and its `url` expire. */
256
+ expiresAt?: string;
257
+ }
258
+
196
259
  /**
197
260
  * Error response body returned by the Worker when a chat request fails.
198
261
  */
@@ -211,10 +274,12 @@ export declare class ChatApiClient {
211
274
  id: string;
212
275
  /** Who authored the message. */
213
276
  role: "user" | "assistant";
214
- /** Plain-text message body. */
277
+ /** Plain-text message body. May be empty when the message only carries attachments. */
215
278
  content: string;
216
279
  /** Sources cited by the assistant for this message, when any. */
217
280
  sources?: Source[];
281
+ /** Files attached by the user to this message, when any. */
282
+ attachments?: ChatAttachment[];
218
283
  /** Tools the assistant called while producing this message, when any. */
219
284
  toolUses?: ToolUse[];
220
285
  }
@@ -237,6 +302,8 @@ export declare class ChatApiClient {
237
302
  sources?: Source[];
238
303
  /** Tools the assistant called while producing the reply, when any. */
239
304
  toolUses?: ToolUse[];
305
+ /** Attachments the worker stored while handling this request, when any. */
306
+ attachments?: StoredAttachment[];
240
307
  }
241
308
 
242
309
  /**
@@ -280,7 +347,7 @@ export declare class ChatApiClient {
280
347
  * <ChatWidget apiUrl="https://api.example.com" title="Support" />
281
348
  * ```
282
349
  */
283
- export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, streaming, }: ChatWidgetProps): JSX_2.Element;
350
+ export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, streaming, attachments, voice, }: ChatWidgetProps): JSX_2.Element;
284
351
 
285
352
  /**
286
353
  * Props for the {@link ChatWidget} component.
@@ -339,6 +406,25 @@ export declare class ChatApiClient {
339
406
  * @defaultValue `true`
340
407
  */
341
408
  streaming?: boolean;
409
+ /**
410
+ * Let visitors attach images and PDFs (click, drag-and-drop, or paste).
411
+ * `true` enables the defaults (5 MB per file, 5 files per message, JPEG /
412
+ * PNG / GIF / WebP / PDF); pass an {@link AttachmentsOptions} to tune them.
413
+ * The worker must allow attachments too (it does by default).
414
+ * @defaultValue `false`
415
+ */
416
+ attachments?: boolean | AttachmentsOptions;
417
+ /**
418
+ * Voice features built on the browser's Web Speech API: a mic button for
419
+ * dictating messages and a read-aloud control on assistant replies. `true`
420
+ * enables both (click-to-toggle mic, no auto-submit); pass a
421
+ * {@link VoiceOptions} to choose hold-to-talk, auto-submit, a language, or
422
+ * to switch either half off. Each half renders only where the browser
423
+ * supports it. The widget never handles audio itself, but the browser's
424
+ * speech service may process it remotely; see the Voice guide.
425
+ * @defaultValue `false`
426
+ */
427
+ voice?: boolean | VoiceOptions;
342
428
  }
343
429
 
344
430
  /** An analytics event emitted by {@link pluginAnalytics}. */
@@ -449,6 +535,9 @@ export declare class ChatApiClient {
449
535
  * Every user-facing string the widget renders. Pass a {@link ClaudiusTranslations}
450
536
  * (or a partial override) to localize the UI. English is the source of truth;
451
537
  * see {@link defaultTranslations}.
538
+ *
539
+ * Strings containing `{name}` / `{max}` placeholders are interpolated at
540
+ * render time.
452
541
  */
453
542
  export declare interface ClaudiusTranslations {
454
543
  /** Chat window header title. */
@@ -479,6 +568,42 @@ export declare class ChatApiClient {
479
568
  openChat: string;
480
569
  /** Accessible label for dismissing the greeting bubble. */
481
570
  dismissGreeting: string;
571
+ /** Accessible label for the attach-file button and file picker. */
572
+ attachFile: string;
573
+ /** Accessible label prefix for removing a pending attachment (filename is appended). */
574
+ removeAttachment: string;
575
+ /** Accessible label for the list of pending attachments. */
576
+ attachmentsLabel: string;
577
+ /** Overlay hint shown while dragging files over the composer. */
578
+ dropFilesHint: string;
579
+ /** Validation message for an oversized file; supports `{name}` and `{max}`. */
580
+ attachmentTooLarge: string;
581
+ /** Validation message for a disallowed file type; supports `{name}`. */
582
+ attachmentTypeNotAllowed: string;
583
+ /** Validation message when the per-message file limit is hit; supports `{max}`. */
584
+ attachmentTooMany: string;
585
+ /** Accessible label for the mic button in toggle mode (state is exposed via `aria-pressed`). */
586
+ voiceInput: string;
587
+ /** Accessible label for the mic button in hold mode. */
588
+ voiceInputHold: string;
589
+ /** Placeholder shown in the message input while dictation is listening. */
590
+ voiceListening: string;
591
+ /** Shown when the browser or the visitor has blocked microphone access. */
592
+ voicePermissionDenied: string;
593
+ /** Shown when dictation ended without hearing any speech. */
594
+ voiceNoSpeech: string;
595
+ /** Shown when no microphone is available. */
596
+ voiceNoMicrophone: string;
597
+ /** Shown when the browser's speech service cannot be reached or does not support the language. */
598
+ voiceUnavailable: string;
599
+ /** Accessible label for the button that reads an assistant message aloud. */
600
+ readAloud: string;
601
+ /** Accessible label for pausing read-aloud playback. */
602
+ pauseReading: string;
603
+ /** Accessible label for resuming paused read-aloud playback. */
604
+ resumeReading: string;
605
+ /** Accessible label for stopping read-aloud playback. */
606
+ stopReading: string;
482
607
  /** Generic fallback error message. */
483
608
  errorGeneric: string;
484
609
  /** Error shown when the network request fails. */
@@ -489,6 +614,10 @@ export declare class ChatApiClient {
489
614
  errorRateLimitMinute: string;
490
615
  /** Error shown when rate-limited (per-hour limit). */
491
616
  errorRateLimitHour: string;
617
+ /** Error shown when the worker rejects an attachment (type, size, count, or content). */
618
+ errorAttachmentRejected: string;
619
+ /** Error shown when the worker's daily upload quota is exhausted. */
620
+ errorAttachmentQuota: string;
492
621
  /** Label for the retry action on a failed message. */
493
622
  errorRetry: string;
494
623
  }
@@ -511,6 +640,9 @@ export declare class ChatApiClient {
511
640
  constructor();
512
641
  }
513
642
 
643
+ /** Defaults applied when attachments are enabled with `true` or a partial config. */
644
+ export declare const DEFAULT_ATTACHMENT_OPTIONS: ResolvedAttachmentsConfig;
645
+
514
646
  /**
515
647
  * Default PII patterns: email addresses, North-American-style phone numbers,
516
648
  * US Social Security numbers, and 13–16 digit card-like sequences. These are
@@ -647,6 +779,12 @@ export declare class ChatApiClient {
647
779
  /** Replace every match of every pattern in `text` with `replacement`. */
648
780
  export declare function redactText(text: string, patterns: readonly RegExp[], replacement: string): string;
649
781
 
782
+ /** {@link AttachmentsOptions} with every field filled in. */
783
+ export declare type ResolvedAttachmentsConfig = Required<AttachmentsOptions>;
784
+
785
+ /** {@link VoiceOptions} with every field filled in. */
786
+ export declare type ResolvedVoiceConfig = Required<VoiceOptions>;
787
+
650
788
  /**
651
789
  * Resolve the final translations for a locale, applying any per-string
652
790
  * overrides on top of the chosen locale's defaults.
@@ -677,6 +815,21 @@ export declare class ChatApiClient {
677
815
  type: "blog" | "page" | "external";
678
816
  }
679
817
 
818
+ /**
819
+ * Storage metadata the worker returns for each attachment it persisted while
820
+ * handling a request (R2 backend only).
821
+ */
822
+ export declare interface StoredAttachment {
823
+ /** The {@link ChatAttachment.id} this entry describes. */
824
+ id: string;
825
+ /** Worker storage key to reference the file on later turns. */
826
+ key: string;
827
+ /** Signed preview/download URL, when the worker can serve the file. */
828
+ url?: string;
829
+ /** ISO 8601 expiry of the stored file. */
830
+ expiresAt: string;
831
+ }
832
+
680
833
  declare const THEME_COLOR_TOKENS: readonly ["accent", "accentText", "accentSoft", "accentTextMuted", "surface", "surfaceMuted", "text", "textMuted", "border", "userBubble", "userBubbleText", "assistantBubble", "assistantBubbleText", "field", "error", "errorSurface", "errorText", "link", "scrim"];
681
834
 
682
835
  declare const THEME_FONT_TOKENS: readonly ["heading", "body"];
@@ -762,6 +915,45 @@ export declare class ChatApiClient {
762
915
  /** A URL match: a case-insensitive substring, or a regular expression. */
763
916
  export declare type UrlPattern = string | RegExp;
764
917
 
918
+ /**
919
+ * How the mic button records: `"toggle"` starts on one click and stops on the
920
+ * next; `"hold"` records only while the button is held down.
921
+ */
922
+ export declare type VoiceInputMode = "toggle" | "hold";
923
+
924
+ /**
925
+ * Voice features. Pass to {@link ChatWidget} via the `voice` prop (or `true`
926
+ * for the defaults). Both halves rely on the browser's Web Speech API and
927
+ * render nothing where it is missing.
928
+ */
929
+ export declare interface VoiceOptions {
930
+ /**
931
+ * Show the mic button for dictating messages.
932
+ * @defaultValue `true`
933
+ */
934
+ input?: boolean;
935
+ /**
936
+ * Show the read-aloud control on completed assistant messages.
937
+ * @defaultValue `true`
938
+ */
939
+ output?: boolean;
940
+ /**
941
+ * How the mic button records.
942
+ * @defaultValue `"toggle"`
943
+ */
944
+ mode?: VoiceInputMode;
945
+ /**
946
+ * Send the dictated message as soon as recognition ends.
947
+ * @defaultValue `false`
948
+ */
949
+ autoSubmit?: boolean;
950
+ /**
951
+ * BCP-47 language tag for recognition and playback (e.g. `"en-GB"`).
952
+ * Defaults to a tag derived from the widget locale.
953
+ */
954
+ lang?: string;
955
+ }
956
+
765
957
  /** Corner of the viewport the widget docks to. */
766
958
  export declare type WidgetPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
767
959
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudius-chat-widget",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "type": "module",
5
5
  "description": "Embeddable AI chat widget powered by Claude. Drop-in React component or standalone script embed, backed by a Cloudflare Worker.",
6
6
  "keywords": [