claudius-chat-widget 1.8.2 → 1.9.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/claudius.cjs +2 -2
- package/dist/claudius.iife.js +10 -10
- package/dist/claudius.js +762 -556
- package/dist/index.d.cts +255 -1
- package/dist/index.d.ts +255 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
|
+
/** Options for {@link pluginAnalytics}. */
|
|
4
|
+
export declare interface AnalyticsPluginOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Sink called once per chat lifecycle event. Wire it to your analytics
|
|
7
|
+
* provider (Google Analytics, PostHog, Segment, a custom endpoint, ...).
|
|
8
|
+
*/
|
|
9
|
+
onEvent: (event: ClaudiusAnalyticsEvent) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Include message text in `message_sent` / `message_received` events. Set to
|
|
12
|
+
* `false` to record only the character count and avoid logging user content.
|
|
13
|
+
* @defaultValue `true`
|
|
14
|
+
*/
|
|
15
|
+
includeContent?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Context for {@link ClaudiusPlugin.onBeforeSend}. Adds the ability to
|
|
20
|
+
* short-circuit the request before it reaches the network.
|
|
21
|
+
*/
|
|
22
|
+
export declare interface BeforeSendContext extends PluginContext {
|
|
23
|
+
/**
|
|
24
|
+
* Skip the network request and render this assistant reply instead. The
|
|
25
|
+
* (possibly modified) user message is still shown. Stops the hook chain —
|
|
26
|
+
* later plugins' `onBeforeSend` hooks do not run.
|
|
27
|
+
*/
|
|
28
|
+
respondWith(reply: string | PluginReply): void;
|
|
29
|
+
/**
|
|
30
|
+
* Cancel the send entirely: no request is made and nothing is rendered (the
|
|
31
|
+
* user message is dropped). Stops the hook chain. Use for client-only
|
|
32
|
+
* commands the chat should swallow.
|
|
33
|
+
*/
|
|
34
|
+
abort(reason?: string): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
3
37
|
/** Names of the built-in themes shipped in {@link builtinThemes}. */
|
|
4
38
|
export declare type BuiltinThemeName = "default" | "minimal" | "playful" | "corporate";
|
|
5
39
|
|
|
@@ -10,6 +44,31 @@ export declare type BuiltinThemeName = "default" | "minimal" | "playful" | "corp
|
|
|
10
44
|
*/
|
|
11
45
|
export declare const builtinThemes: Record<BuiltinThemeName, ClaudiusTheme>;
|
|
12
46
|
|
|
47
|
+
/** Options for {@link pluginCannedResponses}. */
|
|
48
|
+
export declare interface CannedResponsesOptions {
|
|
49
|
+
/** Rules evaluated in order; the first match wins. */
|
|
50
|
+
rules: CannedRule[];
|
|
51
|
+
/**
|
|
52
|
+
* Make `string` matchers case-sensitive.
|
|
53
|
+
* @defaultValue `false`
|
|
54
|
+
*/
|
|
55
|
+
caseSensitive?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A single intent-matching rule for {@link pluginCannedResponses}. */
|
|
59
|
+
export declare interface CannedRule {
|
|
60
|
+
/**
|
|
61
|
+
* How to match the user's message:
|
|
62
|
+
* - `string` — case-insensitive substring match (see
|
|
63
|
+
* {@link CannedResponsesOptions.caseSensitive}).
|
|
64
|
+
* - `RegExp` — tested against the message content.
|
|
65
|
+
* - function — receives the content and returns whether it matches.
|
|
66
|
+
*/
|
|
67
|
+
match: string | RegExp | ((content: string) => boolean);
|
|
68
|
+
/** The reply rendered when the rule matches. */
|
|
69
|
+
reply: string | PluginReply;
|
|
70
|
+
}
|
|
71
|
+
|
|
13
72
|
/**
|
|
14
73
|
* Typed client for the Claudius Worker chat API. Handles debouncing,
|
|
15
74
|
* per-attempt timeouts, and automatic retries with backoff for transient
|
|
@@ -158,7 +217,7 @@ export declare class ChatApiClient {
|
|
|
158
217
|
* <ChatWidget apiUrl="https://api.example.com" title="Support" />
|
|
159
218
|
* ```
|
|
160
219
|
*/
|
|
161
|
-
export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, }: ChatWidgetProps): JSX_2.Element;
|
|
220
|
+
export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, }: ChatWidgetProps): JSX_2.Element;
|
|
162
221
|
|
|
163
222
|
/**
|
|
164
223
|
* Props for the {@link ChatWidget} component.
|
|
@@ -203,6 +262,82 @@ export declare class ChatApiClient {
|
|
|
203
262
|
translations?: Partial<ClaudiusTranslations>;
|
|
204
263
|
/** Proactive open/greeting rules evaluated against the current page. */
|
|
205
264
|
triggers?: Trigger[];
|
|
265
|
+
/**
|
|
266
|
+
* Middleware run around each message: `onBeforeSend`, `onAfterReceive`, and
|
|
267
|
+
* `onError`. Hooks run in array order and may modify, replace, or
|
|
268
|
+
* short-circuit messages. See {@link ClaudiusPlugin}.
|
|
269
|
+
*/
|
|
270
|
+
plugins?: ClaudiusPlugin[];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** An analytics event emitted by {@link pluginAnalytics}. */
|
|
274
|
+
export declare type ClaudiusAnalyticsEvent = {
|
|
275
|
+
/** Event discriminant. */
|
|
276
|
+
type: "message_sent";
|
|
277
|
+
/** Always `"user"`. */
|
|
278
|
+
role: "user";
|
|
279
|
+
/** Message text, or `""` when `includeContent` is `false`. */
|
|
280
|
+
content: string;
|
|
281
|
+
/** Length of the message in characters. */
|
|
282
|
+
chars: number;
|
|
283
|
+
} | {
|
|
284
|
+
/** Event discriminant. */
|
|
285
|
+
type: "message_received";
|
|
286
|
+
/** Always `"assistant"`. */
|
|
287
|
+
role: "assistant";
|
|
288
|
+
/** Reply text, or `""` when `includeContent` is `false`. */
|
|
289
|
+
content: string;
|
|
290
|
+
/** Length of the reply in characters. */
|
|
291
|
+
chars: number;
|
|
292
|
+
} | {
|
|
293
|
+
/** Event discriminant. */
|
|
294
|
+
type: "chat_error";
|
|
295
|
+
/** The error message. */
|
|
296
|
+
message: string;
|
|
297
|
+
/** Machine-readable error code, when available (e.g. `"TIMEOUT"`). */
|
|
298
|
+
code?: string;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* A client-side middleware that runs around the chat message lifecycle. Pass
|
|
303
|
+
* an array of plugins to {@link ChatWidget} via the `plugins` prop; hooks run
|
|
304
|
+
* in array order.
|
|
305
|
+
*
|
|
306
|
+
* Hooks may be async, and may modify, replace, or short-circuit messages. A
|
|
307
|
+
* hook that throws is caught and logged — a misbehaving plugin will not break
|
|
308
|
+
* the chat — so security-sensitive transforms (e.g. PII redaction) should be
|
|
309
|
+
* written defensively.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const logger: ClaudiusPlugin = {
|
|
314
|
+
* name: "logger",
|
|
315
|
+
* onBeforeSend: (message) => { console.log("sending", message.content); },
|
|
316
|
+
* onAfterReceive: (message) => { console.log("received", message.content); },
|
|
317
|
+
* };
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
export declare interface ClaudiusPlugin {
|
|
321
|
+
/** Stable identifier, used in log messages. */
|
|
322
|
+
name: string;
|
|
323
|
+
/**
|
|
324
|
+
* Runs before the user message is sent. Return a {@link ChatMessage} to
|
|
325
|
+
* replace it (the returned message is both displayed and sent), return
|
|
326
|
+
* nothing to leave it unchanged, or call {@link BeforeSendContext.respondWith}
|
|
327
|
+
* / {@link BeforeSendContext.abort} to short-circuit.
|
|
328
|
+
*/
|
|
329
|
+
onBeforeSend?(message: ChatMessage, ctx: BeforeSendContext): MaybePromise<ChatMessage | void>;
|
|
330
|
+
/**
|
|
331
|
+
* Runs after the assistant reply is received, before it is rendered. Return
|
|
332
|
+
* a {@link ChatMessage} to replace it, or nothing to leave it unchanged.
|
|
333
|
+
*/
|
|
334
|
+
onAfterReceive?(message: ChatMessage, ctx: PluginContext): MaybePromise<ChatMessage | void>;
|
|
335
|
+
/**
|
|
336
|
+
* Runs when a send fails. Observe the error, or call
|
|
337
|
+
* {@link ErrorContext.respondWith} to render a fallback reply instead of the
|
|
338
|
+
* error UI.
|
|
339
|
+
*/
|
|
340
|
+
onError?(error: Error, ctx: ErrorContext): MaybePromise<void>;
|
|
206
341
|
}
|
|
207
342
|
|
|
208
343
|
/**
|
|
@@ -299,6 +434,14 @@ export declare class ChatApiClient {
|
|
|
299
434
|
constructor();
|
|
300
435
|
}
|
|
301
436
|
|
|
437
|
+
/**
|
|
438
|
+
* Default PII patterns: email addresses, North-American-style phone numbers,
|
|
439
|
+
* US Social Security numbers, and 13–16 digit card-like sequences. These are
|
|
440
|
+
* intentionally conservative starting points — tune {@link RedactPiiOptions.patterns}
|
|
441
|
+
* for your data.
|
|
442
|
+
*/
|
|
443
|
+
export declare const DEFAULT_PII_PATTERNS: readonly RegExp[];
|
|
444
|
+
|
|
302
445
|
/** The default (English) translations, used when no locale or override applies. */
|
|
303
446
|
export declare const defaultTranslations: ClaudiusTranslations;
|
|
304
447
|
|
|
@@ -310,12 +453,123 @@ export declare class ChatApiClient {
|
|
|
310
453
|
*/
|
|
311
454
|
export declare function detectLocale(): LocaleCode;
|
|
312
455
|
|
|
456
|
+
/**
|
|
457
|
+
* Context for {@link ClaudiusPlugin.onError}. Adds the ability to recover from
|
|
458
|
+
* a failed send by rendering a reply in place of the error UI.
|
|
459
|
+
*/
|
|
460
|
+
export declare interface ErrorContext extends PluginContext {
|
|
461
|
+
/**
|
|
462
|
+
* Recover from the failure by rendering this assistant reply instead of the
|
|
463
|
+
* error state. Stops the hook chain — later plugins' `onError` hooks do not
|
|
464
|
+
* run.
|
|
465
|
+
*/
|
|
466
|
+
respondWith(reply: string | PluginReply): void;
|
|
467
|
+
}
|
|
468
|
+
|
|
313
469
|
/** BCP-47 primary language subtags the widget ships built-in translations for. */
|
|
314
470
|
export declare type LocaleCode = "en" | "es" | "fr" | "de";
|
|
315
471
|
|
|
316
472
|
/** Built-in translations keyed by {@link LocaleCode}. */
|
|
317
473
|
export declare const locales: Record<LocaleCode, ClaudiusTranslations>;
|
|
318
474
|
|
|
475
|
+
/** A value that may be returned synchronously or as a promise. */
|
|
476
|
+
export declare type MaybePromise<T> = T | Promise<T>;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Reference plugin that emits a structured analytics event for every message
|
|
480
|
+
* sent, every reply received, and every error. It never modifies messages.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```ts
|
|
484
|
+
* <ChatWidget
|
|
485
|
+
* apiUrl={url}
|
|
486
|
+
* plugins={[pluginAnalytics({ onEvent: (e) => gtag("event", e.type, e) })]}
|
|
487
|
+
* />
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
export declare function pluginAnalytics(options: AnalyticsPluginOptions): ClaudiusPlugin;
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Reference plugin that answers matching messages locally, without calling the
|
|
494
|
+
* API. The first rule whose matcher fires short-circuits the send via
|
|
495
|
+
* `ctx.respondWith`, so the network is never hit for that turn.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* <ChatWidget
|
|
500
|
+
* apiUrl={url}
|
|
501
|
+
* plugins={[pluginCannedResponses({
|
|
502
|
+
* rules: [
|
|
503
|
+
* { match: "hours", reply: "We're open 9-5, Mon-Fri." },
|
|
504
|
+
* { match: /pricing|cost/i, reply: "See https://example.com/pricing." },
|
|
505
|
+
* ],
|
|
506
|
+
* })]}
|
|
507
|
+
* />
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
export declare function pluginCannedResponses(options: CannedResponsesOptions): ClaudiusPlugin;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Read-only context shared by every plugin hook.
|
|
514
|
+
*
|
|
515
|
+
* `messages` is a snapshot of the conversation at the moment the hook runs:
|
|
516
|
+
* in {@link ClaudiusPlugin.onBeforeSend} it excludes the in-flight user
|
|
517
|
+
* message; in {@link ClaudiusPlugin.onAfterReceive} and
|
|
518
|
+
* {@link ClaudiusPlugin.onError} it includes it.
|
|
519
|
+
*/
|
|
520
|
+
export declare interface PluginContext {
|
|
521
|
+
/** Conversation snapshot, oldest message first. Treat as immutable. */
|
|
522
|
+
readonly messages: readonly ChatMessage[];
|
|
523
|
+
/** The Worker chat endpoint URL the widget posts to. */
|
|
524
|
+
readonly apiUrl: string;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Reference plugin that strips PII from the user's message before it leaves the
|
|
529
|
+
* browser. The redacted text is what gets displayed and sent, so the user sees
|
|
530
|
+
* that redaction happened. Optionally redacts assistant replies too.
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* <ChatWidget apiUrl={url} plugins={[pluginRedactPII()]} />
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
export declare function pluginRedactPII(options?: RedactPiiOptions): ClaudiusPlugin;
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* A synthesized assistant reply, produced by a plugin instead of (or in
|
|
541
|
+
* recovery from) a network round-trip. Passed to
|
|
542
|
+
* {@link BeforeSendContext.respondWith} and {@link ErrorContext.respondWith}.
|
|
543
|
+
*/
|
|
544
|
+
export declare interface PluginReply {
|
|
545
|
+
/** The assistant reply text to render. */
|
|
546
|
+
content: string;
|
|
547
|
+
/** Optional sources to attach to the synthesized reply. */
|
|
548
|
+
sources?: Source[];
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** Options for {@link pluginRedactPII}. */
|
|
552
|
+
export declare interface RedactPiiOptions {
|
|
553
|
+
/**
|
|
554
|
+
* Patterns to redact. Each must carry the global (`g`) flag.
|
|
555
|
+
* @defaultValue {@link DEFAULT_PII_PATTERNS}
|
|
556
|
+
*/
|
|
557
|
+
patterns?: readonly RegExp[];
|
|
558
|
+
/**
|
|
559
|
+
* Text substituted for each match.
|
|
560
|
+
* @defaultValue `"[redacted]"`
|
|
561
|
+
*/
|
|
562
|
+
replacement?: string;
|
|
563
|
+
/**
|
|
564
|
+
* Also redact the assistant's replies, not just outgoing user messages.
|
|
565
|
+
* @defaultValue `false`
|
|
566
|
+
*/
|
|
567
|
+
redactReplies?: boolean;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** Replace every match of every pattern in `text` with `replacement`. */
|
|
571
|
+
export declare function redactText(text: string, patterns: readonly RegExp[], replacement: string): string;
|
|
572
|
+
|
|
319
573
|
/**
|
|
320
574
|
* Resolve the final translations for a locale, applying any per-string
|
|
321
575
|
* overrides on top of the chosen locale's defaults.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
|
+
/** Options for {@link pluginAnalytics}. */
|
|
4
|
+
export declare interface AnalyticsPluginOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Sink called once per chat lifecycle event. Wire it to your analytics
|
|
7
|
+
* provider (Google Analytics, PostHog, Segment, a custom endpoint, ...).
|
|
8
|
+
*/
|
|
9
|
+
onEvent: (event: ClaudiusAnalyticsEvent) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Include message text in `message_sent` / `message_received` events. Set to
|
|
12
|
+
* `false` to record only the character count and avoid logging user content.
|
|
13
|
+
* @defaultValue `true`
|
|
14
|
+
*/
|
|
15
|
+
includeContent?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Context for {@link ClaudiusPlugin.onBeforeSend}. Adds the ability to
|
|
20
|
+
* short-circuit the request before it reaches the network.
|
|
21
|
+
*/
|
|
22
|
+
export declare interface BeforeSendContext extends PluginContext {
|
|
23
|
+
/**
|
|
24
|
+
* Skip the network request and render this assistant reply instead. The
|
|
25
|
+
* (possibly modified) user message is still shown. Stops the hook chain —
|
|
26
|
+
* later plugins' `onBeforeSend` hooks do not run.
|
|
27
|
+
*/
|
|
28
|
+
respondWith(reply: string | PluginReply): void;
|
|
29
|
+
/**
|
|
30
|
+
* Cancel the send entirely: no request is made and nothing is rendered (the
|
|
31
|
+
* user message is dropped). Stops the hook chain. Use for client-only
|
|
32
|
+
* commands the chat should swallow.
|
|
33
|
+
*/
|
|
34
|
+
abort(reason?: string): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
3
37
|
/** Names of the built-in themes shipped in {@link builtinThemes}. */
|
|
4
38
|
export declare type BuiltinThemeName = "default" | "minimal" | "playful" | "corporate";
|
|
5
39
|
|
|
@@ -10,6 +44,31 @@ export declare type BuiltinThemeName = "default" | "minimal" | "playful" | "corp
|
|
|
10
44
|
*/
|
|
11
45
|
export declare const builtinThemes: Record<BuiltinThemeName, ClaudiusTheme>;
|
|
12
46
|
|
|
47
|
+
/** Options for {@link pluginCannedResponses}. */
|
|
48
|
+
export declare interface CannedResponsesOptions {
|
|
49
|
+
/** Rules evaluated in order; the first match wins. */
|
|
50
|
+
rules: CannedRule[];
|
|
51
|
+
/**
|
|
52
|
+
* Make `string` matchers case-sensitive.
|
|
53
|
+
* @defaultValue `false`
|
|
54
|
+
*/
|
|
55
|
+
caseSensitive?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A single intent-matching rule for {@link pluginCannedResponses}. */
|
|
59
|
+
export declare interface CannedRule {
|
|
60
|
+
/**
|
|
61
|
+
* How to match the user's message:
|
|
62
|
+
* - `string` — case-insensitive substring match (see
|
|
63
|
+
* {@link CannedResponsesOptions.caseSensitive}).
|
|
64
|
+
* - `RegExp` — tested against the message content.
|
|
65
|
+
* - function — receives the content and returns whether it matches.
|
|
66
|
+
*/
|
|
67
|
+
match: string | RegExp | ((content: string) => boolean);
|
|
68
|
+
/** The reply rendered when the rule matches. */
|
|
69
|
+
reply: string | PluginReply;
|
|
70
|
+
}
|
|
71
|
+
|
|
13
72
|
/**
|
|
14
73
|
* Typed client for the Claudius Worker chat API. Handles debouncing,
|
|
15
74
|
* per-attempt timeouts, and automatic retries with backoff for transient
|
|
@@ -158,7 +217,7 @@ export declare class ChatApiClient {
|
|
|
158
217
|
* <ChatWidget apiUrl="https://api.example.com" title="Support" />
|
|
159
218
|
* ```
|
|
160
219
|
*/
|
|
161
|
-
export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, }: ChatWidgetProps): JSX_2.Element;
|
|
220
|
+
export declare function ChatWidget({ apiUrl, title, subtitle, welcomeMessage, placeholder, persistMessages, storageKeyPrefix, requestTimeoutMs, theme, accentColor, position, locale, translations: translationOverrides, triggers, plugins, }: ChatWidgetProps): JSX_2.Element;
|
|
162
221
|
|
|
163
222
|
/**
|
|
164
223
|
* Props for the {@link ChatWidget} component.
|
|
@@ -203,6 +262,82 @@ export declare class ChatApiClient {
|
|
|
203
262
|
translations?: Partial<ClaudiusTranslations>;
|
|
204
263
|
/** Proactive open/greeting rules evaluated against the current page. */
|
|
205
264
|
triggers?: Trigger[];
|
|
265
|
+
/**
|
|
266
|
+
* Middleware run around each message: `onBeforeSend`, `onAfterReceive`, and
|
|
267
|
+
* `onError`. Hooks run in array order and may modify, replace, or
|
|
268
|
+
* short-circuit messages. See {@link ClaudiusPlugin}.
|
|
269
|
+
*/
|
|
270
|
+
plugins?: ClaudiusPlugin[];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** An analytics event emitted by {@link pluginAnalytics}. */
|
|
274
|
+
export declare type ClaudiusAnalyticsEvent = {
|
|
275
|
+
/** Event discriminant. */
|
|
276
|
+
type: "message_sent";
|
|
277
|
+
/** Always `"user"`. */
|
|
278
|
+
role: "user";
|
|
279
|
+
/** Message text, or `""` when `includeContent` is `false`. */
|
|
280
|
+
content: string;
|
|
281
|
+
/** Length of the message in characters. */
|
|
282
|
+
chars: number;
|
|
283
|
+
} | {
|
|
284
|
+
/** Event discriminant. */
|
|
285
|
+
type: "message_received";
|
|
286
|
+
/** Always `"assistant"`. */
|
|
287
|
+
role: "assistant";
|
|
288
|
+
/** Reply text, or `""` when `includeContent` is `false`. */
|
|
289
|
+
content: string;
|
|
290
|
+
/** Length of the reply in characters. */
|
|
291
|
+
chars: number;
|
|
292
|
+
} | {
|
|
293
|
+
/** Event discriminant. */
|
|
294
|
+
type: "chat_error";
|
|
295
|
+
/** The error message. */
|
|
296
|
+
message: string;
|
|
297
|
+
/** Machine-readable error code, when available (e.g. `"TIMEOUT"`). */
|
|
298
|
+
code?: string;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* A client-side middleware that runs around the chat message lifecycle. Pass
|
|
303
|
+
* an array of plugins to {@link ChatWidget} via the `plugins` prop; hooks run
|
|
304
|
+
* in array order.
|
|
305
|
+
*
|
|
306
|
+
* Hooks may be async, and may modify, replace, or short-circuit messages. A
|
|
307
|
+
* hook that throws is caught and logged — a misbehaving plugin will not break
|
|
308
|
+
* the chat — so security-sensitive transforms (e.g. PII redaction) should be
|
|
309
|
+
* written defensively.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const logger: ClaudiusPlugin = {
|
|
314
|
+
* name: "logger",
|
|
315
|
+
* onBeforeSend: (message) => { console.log("sending", message.content); },
|
|
316
|
+
* onAfterReceive: (message) => { console.log("received", message.content); },
|
|
317
|
+
* };
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
export declare interface ClaudiusPlugin {
|
|
321
|
+
/** Stable identifier, used in log messages. */
|
|
322
|
+
name: string;
|
|
323
|
+
/**
|
|
324
|
+
* Runs before the user message is sent. Return a {@link ChatMessage} to
|
|
325
|
+
* replace it (the returned message is both displayed and sent), return
|
|
326
|
+
* nothing to leave it unchanged, or call {@link BeforeSendContext.respondWith}
|
|
327
|
+
* / {@link BeforeSendContext.abort} to short-circuit.
|
|
328
|
+
*/
|
|
329
|
+
onBeforeSend?(message: ChatMessage, ctx: BeforeSendContext): MaybePromise<ChatMessage | void>;
|
|
330
|
+
/**
|
|
331
|
+
* Runs after the assistant reply is received, before it is rendered. Return
|
|
332
|
+
* a {@link ChatMessage} to replace it, or nothing to leave it unchanged.
|
|
333
|
+
*/
|
|
334
|
+
onAfterReceive?(message: ChatMessage, ctx: PluginContext): MaybePromise<ChatMessage | void>;
|
|
335
|
+
/**
|
|
336
|
+
* Runs when a send fails. Observe the error, or call
|
|
337
|
+
* {@link ErrorContext.respondWith} to render a fallback reply instead of the
|
|
338
|
+
* error UI.
|
|
339
|
+
*/
|
|
340
|
+
onError?(error: Error, ctx: ErrorContext): MaybePromise<void>;
|
|
206
341
|
}
|
|
207
342
|
|
|
208
343
|
/**
|
|
@@ -299,6 +434,14 @@ export declare class ChatApiClient {
|
|
|
299
434
|
constructor();
|
|
300
435
|
}
|
|
301
436
|
|
|
437
|
+
/**
|
|
438
|
+
* Default PII patterns: email addresses, North-American-style phone numbers,
|
|
439
|
+
* US Social Security numbers, and 13–16 digit card-like sequences. These are
|
|
440
|
+
* intentionally conservative starting points — tune {@link RedactPiiOptions.patterns}
|
|
441
|
+
* for your data.
|
|
442
|
+
*/
|
|
443
|
+
export declare const DEFAULT_PII_PATTERNS: readonly RegExp[];
|
|
444
|
+
|
|
302
445
|
/** The default (English) translations, used when no locale or override applies. */
|
|
303
446
|
export declare const defaultTranslations: ClaudiusTranslations;
|
|
304
447
|
|
|
@@ -310,12 +453,123 @@ export declare class ChatApiClient {
|
|
|
310
453
|
*/
|
|
311
454
|
export declare function detectLocale(): LocaleCode;
|
|
312
455
|
|
|
456
|
+
/**
|
|
457
|
+
* Context for {@link ClaudiusPlugin.onError}. Adds the ability to recover from
|
|
458
|
+
* a failed send by rendering a reply in place of the error UI.
|
|
459
|
+
*/
|
|
460
|
+
export declare interface ErrorContext extends PluginContext {
|
|
461
|
+
/**
|
|
462
|
+
* Recover from the failure by rendering this assistant reply instead of the
|
|
463
|
+
* error state. Stops the hook chain — later plugins' `onError` hooks do not
|
|
464
|
+
* run.
|
|
465
|
+
*/
|
|
466
|
+
respondWith(reply: string | PluginReply): void;
|
|
467
|
+
}
|
|
468
|
+
|
|
313
469
|
/** BCP-47 primary language subtags the widget ships built-in translations for. */
|
|
314
470
|
export declare type LocaleCode = "en" | "es" | "fr" | "de";
|
|
315
471
|
|
|
316
472
|
/** Built-in translations keyed by {@link LocaleCode}. */
|
|
317
473
|
export declare const locales: Record<LocaleCode, ClaudiusTranslations>;
|
|
318
474
|
|
|
475
|
+
/** A value that may be returned synchronously or as a promise. */
|
|
476
|
+
export declare type MaybePromise<T> = T | Promise<T>;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Reference plugin that emits a structured analytics event for every message
|
|
480
|
+
* sent, every reply received, and every error. It never modifies messages.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```ts
|
|
484
|
+
* <ChatWidget
|
|
485
|
+
* apiUrl={url}
|
|
486
|
+
* plugins={[pluginAnalytics({ onEvent: (e) => gtag("event", e.type, e) })]}
|
|
487
|
+
* />
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
export declare function pluginAnalytics(options: AnalyticsPluginOptions): ClaudiusPlugin;
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Reference plugin that answers matching messages locally, without calling the
|
|
494
|
+
* API. The first rule whose matcher fires short-circuits the send via
|
|
495
|
+
* `ctx.respondWith`, so the network is never hit for that turn.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* <ChatWidget
|
|
500
|
+
* apiUrl={url}
|
|
501
|
+
* plugins={[pluginCannedResponses({
|
|
502
|
+
* rules: [
|
|
503
|
+
* { match: "hours", reply: "We're open 9-5, Mon-Fri." },
|
|
504
|
+
* { match: /pricing|cost/i, reply: "See https://example.com/pricing." },
|
|
505
|
+
* ],
|
|
506
|
+
* })]}
|
|
507
|
+
* />
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
export declare function pluginCannedResponses(options: CannedResponsesOptions): ClaudiusPlugin;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Read-only context shared by every plugin hook.
|
|
514
|
+
*
|
|
515
|
+
* `messages` is a snapshot of the conversation at the moment the hook runs:
|
|
516
|
+
* in {@link ClaudiusPlugin.onBeforeSend} it excludes the in-flight user
|
|
517
|
+
* message; in {@link ClaudiusPlugin.onAfterReceive} and
|
|
518
|
+
* {@link ClaudiusPlugin.onError} it includes it.
|
|
519
|
+
*/
|
|
520
|
+
export declare interface PluginContext {
|
|
521
|
+
/** Conversation snapshot, oldest message first. Treat as immutable. */
|
|
522
|
+
readonly messages: readonly ChatMessage[];
|
|
523
|
+
/** The Worker chat endpoint URL the widget posts to. */
|
|
524
|
+
readonly apiUrl: string;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Reference plugin that strips PII from the user's message before it leaves the
|
|
529
|
+
* browser. The redacted text is what gets displayed and sent, so the user sees
|
|
530
|
+
* that redaction happened. Optionally redacts assistant replies too.
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* <ChatWidget apiUrl={url} plugins={[pluginRedactPII()]} />
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
export declare function pluginRedactPII(options?: RedactPiiOptions): ClaudiusPlugin;
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* A synthesized assistant reply, produced by a plugin instead of (or in
|
|
541
|
+
* recovery from) a network round-trip. Passed to
|
|
542
|
+
* {@link BeforeSendContext.respondWith} and {@link ErrorContext.respondWith}.
|
|
543
|
+
*/
|
|
544
|
+
export declare interface PluginReply {
|
|
545
|
+
/** The assistant reply text to render. */
|
|
546
|
+
content: string;
|
|
547
|
+
/** Optional sources to attach to the synthesized reply. */
|
|
548
|
+
sources?: Source[];
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** Options for {@link pluginRedactPII}. */
|
|
552
|
+
export declare interface RedactPiiOptions {
|
|
553
|
+
/**
|
|
554
|
+
* Patterns to redact. Each must carry the global (`g`) flag.
|
|
555
|
+
* @defaultValue {@link DEFAULT_PII_PATTERNS}
|
|
556
|
+
*/
|
|
557
|
+
patterns?: readonly RegExp[];
|
|
558
|
+
/**
|
|
559
|
+
* Text substituted for each match.
|
|
560
|
+
* @defaultValue `"[redacted]"`
|
|
561
|
+
*/
|
|
562
|
+
replacement?: string;
|
|
563
|
+
/**
|
|
564
|
+
* Also redact the assistant's replies, not just outgoing user messages.
|
|
565
|
+
* @defaultValue `false`
|
|
566
|
+
*/
|
|
567
|
+
redactReplies?: boolean;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** Replace every match of every pattern in `text` with `replacement`. */
|
|
571
|
+
export declare function redactText(text: string, patterns: readonly RegExp[], replacement: string): string;
|
|
572
|
+
|
|
319
573
|
/**
|
|
320
574
|
* Resolve the final translations for a locale, applying any per-string
|
|
321
575
|
* overrides on top of the chosen locale's defaults.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudius-chat-widget",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.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": [
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"test:coverage": "vitest run --coverage",
|
|
64
64
|
"e2e": "playwright test",
|
|
65
65
|
"e2e:ui": "playwright test --ui",
|
|
66
|
-
"e2e:install": "playwright install chromium",
|
|
66
|
+
"e2e:install": "playwright install chromium webkit",
|
|
67
67
|
"lint": "eslint src/",
|
|
68
68
|
"lint:fix": "eslint src/ --fix",
|
|
69
69
|
"format": "prettier --write \"src/**/*.{ts,tsx,css}\"",
|