@runtypelabs/persona 1.36.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/README.md +1080 -0
- package/dist/index.cjs +140 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2626 -0
- package/dist/index.d.ts +2626 -0
- package/dist/index.global.js +1843 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +140 -0
- package/dist/index.js.map +1 -0
- package/dist/install.global.js +2 -0
- package/dist/install.global.js.map +1 -0
- package/dist/widget.css +1627 -0
- package/package.json +79 -0
- package/src/@types/idiomorph.d.ts +37 -0
- package/src/client.test.ts +387 -0
- package/src/client.ts +1589 -0
- package/src/components/composer-builder.ts +530 -0
- package/src/components/feedback.ts +379 -0
- package/src/components/forms.ts +170 -0
- package/src/components/header-builder.ts +455 -0
- package/src/components/header-layouts.ts +303 -0
- package/src/components/launcher.ts +193 -0
- package/src/components/message-bubble.ts +528 -0
- package/src/components/messages.ts +54 -0
- package/src/components/panel.ts +204 -0
- package/src/components/reasoning-bubble.ts +144 -0
- package/src/components/registry.ts +87 -0
- package/src/components/suggestions.ts +97 -0
- package/src/components/tool-bubble.ts +288 -0
- package/src/defaults.ts +321 -0
- package/src/index.ts +175 -0
- package/src/install.ts +284 -0
- package/src/plugins/registry.ts +77 -0
- package/src/plugins/types.ts +95 -0
- package/src/postprocessors.ts +194 -0
- package/src/runtime/init.ts +162 -0
- package/src/session.ts +376 -0
- package/src/styles/tailwind.css +20 -0
- package/src/styles/widget.css +1627 -0
- package/src/types.ts +1635 -0
- package/src/ui.ts +3341 -0
- package/src/utils/actions.ts +227 -0
- package/src/utils/attachment-manager.ts +384 -0
- package/src/utils/code-generators.test.ts +500 -0
- package/src/utils/code-generators.ts +1806 -0
- package/src/utils/component-middleware.ts +137 -0
- package/src/utils/component-parser.ts +119 -0
- package/src/utils/constants.ts +16 -0
- package/src/utils/content.ts +306 -0
- package/src/utils/dom.ts +25 -0
- package/src/utils/events.ts +41 -0
- package/src/utils/formatting.test.ts +166 -0
- package/src/utils/formatting.ts +470 -0
- package/src/utils/icons.ts +92 -0
- package/src/utils/message-id.ts +37 -0
- package/src/utils/morph.ts +36 -0
- package/src/utils/positioning.ts +17 -0
- package/src/utils/storage.ts +72 -0
- package/src/utils/theme.ts +105 -0
- package/src/widget.css +1 -0
- package/widget.css +1 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,1635 @@
|
|
|
1
|
+
import type { AgentWidgetPlugin } from "./plugins/types";
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Multi-Modal Content Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Text content part for multi-modal messages
|
|
9
|
+
*/
|
|
10
|
+
export type TextContentPart = {
|
|
11
|
+
type: 'text';
|
|
12
|
+
text: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Image content part for multi-modal messages
|
|
17
|
+
* Supports base64 data URIs or URLs
|
|
18
|
+
*/
|
|
19
|
+
export type ImageContentPart = {
|
|
20
|
+
type: 'image';
|
|
21
|
+
image: string; // base64 data URI or URL
|
|
22
|
+
mimeType?: string;
|
|
23
|
+
alt?: string; // optional alt text for accessibility
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* File content part for multi-modal messages
|
|
28
|
+
* Supports PDF, TXT, DOCX, and other document types
|
|
29
|
+
*/
|
|
30
|
+
export type FileContentPart = {
|
|
31
|
+
type: 'file';
|
|
32
|
+
data: string; // base64 data URI
|
|
33
|
+
mimeType: string;
|
|
34
|
+
filename: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Union type for all content part types
|
|
39
|
+
*/
|
|
40
|
+
export type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Message content can be a simple string or an array of content parts
|
|
44
|
+
*/
|
|
45
|
+
export type MessageContent = string | ContentPart[];
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Context and Middleware Types
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export type AgentWidgetContextProviderContext = {
|
|
52
|
+
messages: AgentWidgetMessage[];
|
|
53
|
+
config: AgentWidgetConfig;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type AgentWidgetContextProvider = (
|
|
57
|
+
context: AgentWidgetContextProviderContext
|
|
58
|
+
) =>
|
|
59
|
+
| Record<string, unknown>
|
|
60
|
+
| void
|
|
61
|
+
| Promise<Record<string, unknown> | void>;
|
|
62
|
+
|
|
63
|
+
export type AgentWidgetRequestPayloadMessage = {
|
|
64
|
+
role: AgentWidgetMessageRole;
|
|
65
|
+
content: MessageContent;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type AgentWidgetRequestPayload = {
|
|
70
|
+
messages: AgentWidgetRequestPayloadMessage[];
|
|
71
|
+
flowId?: string;
|
|
72
|
+
context?: Record<string, unknown>;
|
|
73
|
+
metadata?: Record<string, unknown>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type AgentWidgetRequestMiddlewareContext = {
|
|
77
|
+
payload: AgentWidgetRequestPayload;
|
|
78
|
+
config: AgentWidgetConfig;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type AgentWidgetRequestMiddleware = (
|
|
82
|
+
context: AgentWidgetRequestMiddlewareContext
|
|
83
|
+
) => AgentWidgetRequestPayload | void | Promise<AgentWidgetRequestPayload | void>;
|
|
84
|
+
|
|
85
|
+
export type AgentWidgetParsedAction = {
|
|
86
|
+
type: string;
|
|
87
|
+
payload: Record<string, unknown>;
|
|
88
|
+
raw?: unknown;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type AgentWidgetActionParserInput = {
|
|
92
|
+
text: string;
|
|
93
|
+
message: AgentWidgetMessage;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type AgentWidgetActionParser = (
|
|
97
|
+
input: AgentWidgetActionParserInput
|
|
98
|
+
) => AgentWidgetParsedAction | null | undefined;
|
|
99
|
+
|
|
100
|
+
export type AgentWidgetActionHandlerResult = {
|
|
101
|
+
handled?: boolean;
|
|
102
|
+
displayText?: string;
|
|
103
|
+
persistMessage?: boolean; // If false, prevents message from being saved to history
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type AgentWidgetActionContext = {
|
|
107
|
+
message: AgentWidgetMessage;
|
|
108
|
+
metadata: Record<string, unknown>;
|
|
109
|
+
updateMetadata: (
|
|
110
|
+
updater: (prev: Record<string, unknown>) => Record<string, unknown>
|
|
111
|
+
) => void;
|
|
112
|
+
document: Document | null;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export type AgentWidgetActionHandler = (
|
|
116
|
+
action: AgentWidgetParsedAction,
|
|
117
|
+
context: AgentWidgetActionContext
|
|
118
|
+
) => AgentWidgetActionHandlerResult | void;
|
|
119
|
+
|
|
120
|
+
export type AgentWidgetStoredState = {
|
|
121
|
+
messages?: AgentWidgetMessage[];
|
|
122
|
+
metadata?: Record<string, unknown>;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export interface AgentWidgetStorageAdapter {
|
|
126
|
+
load?: () =>
|
|
127
|
+
| AgentWidgetStoredState
|
|
128
|
+
| null
|
|
129
|
+
| Promise<AgentWidgetStoredState | null>;
|
|
130
|
+
save?: (state: AgentWidgetStoredState) => void | Promise<void>;
|
|
131
|
+
clear?: () => void | Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type AgentWidgetVoiceStateEvent = {
|
|
135
|
+
active: boolean;
|
|
136
|
+
source: "user" | "auto" | "restore" | "system";
|
|
137
|
+
timestamp: number;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export type AgentWidgetActionEventPayload = {
|
|
141
|
+
action: AgentWidgetParsedAction;
|
|
142
|
+
message: AgentWidgetMessage;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Feedback event payload for upvote/downvote actions on messages
|
|
147
|
+
*/
|
|
148
|
+
export type AgentWidgetMessageFeedback = {
|
|
149
|
+
type: "upvote" | "downvote";
|
|
150
|
+
messageId: string;
|
|
151
|
+
message: AgentWidgetMessage;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Configuration for message action buttons (copy, upvote, downvote)
|
|
156
|
+
*
|
|
157
|
+
* **Client Token Mode**: When using `clientToken`, feedback is automatically
|
|
158
|
+
* sent to your Travrse backend. Just enable the buttons and you're done!
|
|
159
|
+
* The `onFeedback` and `onCopy` callbacks are optional for additional local handling.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* // With clientToken - feedback is automatic!
|
|
164
|
+
* config: {
|
|
165
|
+
* clientToken: 'ct_live_...',
|
|
166
|
+
* messageActions: {
|
|
167
|
+
* showUpvote: true,
|
|
168
|
+
* showDownvote: true,
|
|
169
|
+
* // No onFeedback needed - sent to backend automatically
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export type AgentWidgetMessageActionsConfig = {
|
|
175
|
+
/**
|
|
176
|
+
* Enable/disable message actions entirely
|
|
177
|
+
* @default true
|
|
178
|
+
*/
|
|
179
|
+
enabled?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Show copy button
|
|
182
|
+
* @default true
|
|
183
|
+
*/
|
|
184
|
+
showCopy?: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Show upvote button.
|
|
187
|
+
* When using `clientToken`, feedback is sent to the backend automatically.
|
|
188
|
+
* @default false
|
|
189
|
+
*/
|
|
190
|
+
showUpvote?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Show downvote button.
|
|
193
|
+
* When using `clientToken`, feedback is sent to the backend automatically.
|
|
194
|
+
* @default false
|
|
195
|
+
*/
|
|
196
|
+
showDownvote?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Visibility mode: 'always' shows buttons always, 'hover' shows on hover only
|
|
199
|
+
* @default 'hover'
|
|
200
|
+
*/
|
|
201
|
+
visibility?: "always" | "hover";
|
|
202
|
+
/**
|
|
203
|
+
* Horizontal alignment of action buttons
|
|
204
|
+
* @default 'right'
|
|
205
|
+
*/
|
|
206
|
+
align?: "left" | "center" | "right";
|
|
207
|
+
/**
|
|
208
|
+
* Layout style for action buttons
|
|
209
|
+
* - 'pill-inside': Compact floating pill around just the buttons (default for hover)
|
|
210
|
+
* - 'row-inside': Full-width row at the bottom of the message
|
|
211
|
+
* @default 'pill-inside'
|
|
212
|
+
*/
|
|
213
|
+
layout?: "pill-inside" | "row-inside";
|
|
214
|
+
/**
|
|
215
|
+
* Callback when user submits feedback (upvote/downvote).
|
|
216
|
+
*
|
|
217
|
+
* **Note**: When using `clientToken`, feedback is AUTOMATICALLY sent to your
|
|
218
|
+
* backend via `/v1/client/feedback`. This callback is called IN ADDITION to
|
|
219
|
+
* the automatic submission, useful for updating local UI or analytics.
|
|
220
|
+
*/
|
|
221
|
+
onFeedback?: (feedback: AgentWidgetMessageFeedback) => void;
|
|
222
|
+
/**
|
|
223
|
+
* Callback when user copies a message.
|
|
224
|
+
*
|
|
225
|
+
* **Note**: When using `clientToken`, copy events are AUTOMATICALLY tracked
|
|
226
|
+
* via `/v1/client/feedback`. This callback is called IN ADDITION to the
|
|
227
|
+
* automatic tracking.
|
|
228
|
+
*/
|
|
229
|
+
onCopy?: (message: AgentWidgetMessage) => void;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export type AgentWidgetStateEvent = {
|
|
233
|
+
open: boolean;
|
|
234
|
+
source: "user" | "auto" | "api" | "system";
|
|
235
|
+
timestamp: number;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export type AgentWidgetStateSnapshot = {
|
|
239
|
+
open: boolean;
|
|
240
|
+
launcherEnabled: boolean;
|
|
241
|
+
voiceActive: boolean;
|
|
242
|
+
streaming: boolean;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export type AgentWidgetControllerEventMap = {
|
|
246
|
+
"assistant:message": AgentWidgetMessage;
|
|
247
|
+
"assistant:complete": AgentWidgetMessage;
|
|
248
|
+
"voice:state": AgentWidgetVoiceStateEvent;
|
|
249
|
+
"action:detected": AgentWidgetActionEventPayload;
|
|
250
|
+
"widget:opened": AgentWidgetStateEvent;
|
|
251
|
+
"widget:closed": AgentWidgetStateEvent;
|
|
252
|
+
"widget:state": AgentWidgetStateSnapshot;
|
|
253
|
+
"message:feedback": AgentWidgetMessageFeedback;
|
|
254
|
+
"message:copy": AgentWidgetMessage;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
export type AgentWidgetFeatureFlags = {
|
|
258
|
+
showReasoning?: boolean;
|
|
259
|
+
showToolCalls?: boolean;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export type AgentWidgetTheme = {
|
|
263
|
+
primary?: string;
|
|
264
|
+
secondary?: string;
|
|
265
|
+
surface?: string;
|
|
266
|
+
muted?: string;
|
|
267
|
+
accent?: string;
|
|
268
|
+
container?: string;
|
|
269
|
+
border?: string;
|
|
270
|
+
divider?: string;
|
|
271
|
+
messageBorder?: string;
|
|
272
|
+
inputBackground?: string;
|
|
273
|
+
callToAction?: string;
|
|
274
|
+
callToActionBackground?: string;
|
|
275
|
+
sendButtonBackgroundColor?: string;
|
|
276
|
+
sendButtonTextColor?: string;
|
|
277
|
+
sendButtonBorderColor?: string;
|
|
278
|
+
closeButtonColor?: string;
|
|
279
|
+
closeButtonBackgroundColor?: string;
|
|
280
|
+
closeButtonBorderColor?: string;
|
|
281
|
+
clearChatIconColor?: string;
|
|
282
|
+
clearChatBackgroundColor?: string;
|
|
283
|
+
clearChatBorderColor?: string;
|
|
284
|
+
tooltipBackground?: string;
|
|
285
|
+
tooltipForeground?: string;
|
|
286
|
+
micIconColor?: string;
|
|
287
|
+
micBackgroundColor?: string;
|
|
288
|
+
micBorderColor?: string;
|
|
289
|
+
recordingIconColor?: string;
|
|
290
|
+
recordingBackgroundColor?: string;
|
|
291
|
+
recordingBorderColor?: string;
|
|
292
|
+
inputFontFamily?: "sans-serif" | "serif" | "mono";
|
|
293
|
+
inputFontWeight?: string;
|
|
294
|
+
radiusSm?: string;
|
|
295
|
+
radiusMd?: string;
|
|
296
|
+
radiusLg?: string;
|
|
297
|
+
launcherRadius?: string;
|
|
298
|
+
buttonRadius?: string;
|
|
299
|
+
/**
|
|
300
|
+
* Border style for the chat panel container.
|
|
301
|
+
* @example "1px solid #e5e7eb" | "none"
|
|
302
|
+
* @default "1px solid var(--tvw-cw-border)"
|
|
303
|
+
*/
|
|
304
|
+
panelBorder?: string;
|
|
305
|
+
/**
|
|
306
|
+
* Box shadow for the chat panel container.
|
|
307
|
+
* @example "0 25px 50px -12px rgba(0,0,0,0.25)" | "none"
|
|
308
|
+
* @default "0 25px 50px -12px rgba(0,0,0,0.25)"
|
|
309
|
+
*/
|
|
310
|
+
panelShadow?: string;
|
|
311
|
+
/**
|
|
312
|
+
* Border radius for the chat panel container.
|
|
313
|
+
* @example "16px" | "0"
|
|
314
|
+
* @default "16px"
|
|
315
|
+
*/
|
|
316
|
+
panelBorderRadius?: string;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export type AgentWidgetLauncherConfig = {
|
|
320
|
+
enabled?: boolean;
|
|
321
|
+
title?: string;
|
|
322
|
+
subtitle?: string;
|
|
323
|
+
textHidden?: boolean;
|
|
324
|
+
iconUrl?: string;
|
|
325
|
+
agentIconText?: string;
|
|
326
|
+
agentIconName?: string;
|
|
327
|
+
agentIconHidden?: boolean;
|
|
328
|
+
position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
329
|
+
autoExpand?: boolean;
|
|
330
|
+
width?: string;
|
|
331
|
+
/**
|
|
332
|
+
* When true, the widget panel will fill the full height of its container.
|
|
333
|
+
* Useful for sidebar layouts where the chat should take up the entire viewport height.
|
|
334
|
+
* The widget will use flex layout to ensure header stays at top, messages scroll in middle,
|
|
335
|
+
* and composer stays fixed at bottom.
|
|
336
|
+
*
|
|
337
|
+
* @default false
|
|
338
|
+
*/
|
|
339
|
+
fullHeight?: boolean;
|
|
340
|
+
/**
|
|
341
|
+
* When true, the widget panel will be positioned as a sidebar flush with the viewport edges.
|
|
342
|
+
* The panel will have:
|
|
343
|
+
* - No border-radius (square corners)
|
|
344
|
+
* - No margins (flush with top, left/right, and bottom edges)
|
|
345
|
+
* - Full viewport height
|
|
346
|
+
* - Subtle shadow on the edge facing the content
|
|
347
|
+
* - No border between footer and messages
|
|
348
|
+
*
|
|
349
|
+
* Use with `position` to control which side ('bottom-left' for left sidebar, 'bottom-right' for right sidebar).
|
|
350
|
+
* Automatically enables fullHeight when true.
|
|
351
|
+
*
|
|
352
|
+
* @default false
|
|
353
|
+
*/
|
|
354
|
+
sidebarMode?: boolean;
|
|
355
|
+
/**
|
|
356
|
+
* Width of the sidebar panel when sidebarMode is true.
|
|
357
|
+
* @default "420px"
|
|
358
|
+
*/
|
|
359
|
+
sidebarWidth?: string;
|
|
360
|
+
/**
|
|
361
|
+
* Offset (in pixels) to subtract from the calculated panel height.
|
|
362
|
+
* Useful for adjusting the panel height when there are other fixed elements on the page.
|
|
363
|
+
* Only applies when not in fullHeight or sidebarMode.
|
|
364
|
+
*
|
|
365
|
+
* @default 0
|
|
366
|
+
*/
|
|
367
|
+
heightOffset?: number;
|
|
368
|
+
callToActionIconText?: string;
|
|
369
|
+
callToActionIconName?: string;
|
|
370
|
+
callToActionIconColor?: string;
|
|
371
|
+
callToActionIconBackgroundColor?: string;
|
|
372
|
+
callToActionIconHidden?: boolean;
|
|
373
|
+
callToActionIconPadding?: string;
|
|
374
|
+
agentIconSize?: string;
|
|
375
|
+
callToActionIconSize?: string;
|
|
376
|
+
headerIconSize?: string;
|
|
377
|
+
headerIconName?: string;
|
|
378
|
+
headerIconHidden?: boolean;
|
|
379
|
+
closeButtonSize?: string;
|
|
380
|
+
closeButtonColor?: string;
|
|
381
|
+
closeButtonBackgroundColor?: string;
|
|
382
|
+
closeButtonBorderWidth?: string;
|
|
383
|
+
closeButtonBorderColor?: string;
|
|
384
|
+
closeButtonBorderRadius?: string;
|
|
385
|
+
closeButtonPaddingX?: string;
|
|
386
|
+
closeButtonPaddingY?: string;
|
|
387
|
+
closeButtonPlacement?: "inline" | "top-right";
|
|
388
|
+
closeButtonIconName?: string;
|
|
389
|
+
closeButtonIconText?: string;
|
|
390
|
+
closeButtonTooltipText?: string;
|
|
391
|
+
closeButtonShowTooltip?: boolean;
|
|
392
|
+
clearChat?: AgentWidgetClearChatConfig;
|
|
393
|
+
/**
|
|
394
|
+
* Border style for the launcher button.
|
|
395
|
+
* @example "1px solid #e5e7eb" | "2px solid #3b82f6" | "none"
|
|
396
|
+
* @default "1px solid #e5e7eb"
|
|
397
|
+
*/
|
|
398
|
+
border?: string;
|
|
399
|
+
/**
|
|
400
|
+
* Box shadow for the launcher button.
|
|
401
|
+
* @example "0 10px 15px -3px rgba(0,0,0,0.1)" | "none"
|
|
402
|
+
* @default "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)"
|
|
403
|
+
*/
|
|
404
|
+
shadow?: string;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
export type AgentWidgetSendButtonConfig = {
|
|
408
|
+
borderWidth?: string;
|
|
409
|
+
borderColor?: string;
|
|
410
|
+
paddingX?: string;
|
|
411
|
+
paddingY?: string;
|
|
412
|
+
iconText?: string;
|
|
413
|
+
iconName?: string;
|
|
414
|
+
useIcon?: boolean;
|
|
415
|
+
tooltipText?: string;
|
|
416
|
+
showTooltip?: boolean;
|
|
417
|
+
backgroundColor?: string;
|
|
418
|
+
textColor?: string;
|
|
419
|
+
size?: string;
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
export type AgentWidgetClearChatConfig = {
|
|
423
|
+
enabled?: boolean;
|
|
424
|
+
placement?: "inline" | "top-right";
|
|
425
|
+
iconName?: string;
|
|
426
|
+
iconColor?: string;
|
|
427
|
+
backgroundColor?: string;
|
|
428
|
+
borderWidth?: string;
|
|
429
|
+
borderColor?: string;
|
|
430
|
+
borderRadius?: string;
|
|
431
|
+
size?: string;
|
|
432
|
+
paddingX?: string;
|
|
433
|
+
paddingY?: string;
|
|
434
|
+
tooltipText?: string;
|
|
435
|
+
showTooltip?: boolean;
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
export type AgentWidgetStatusIndicatorConfig = {
|
|
439
|
+
visible?: boolean;
|
|
440
|
+
idleText?: string;
|
|
441
|
+
connectingText?: string;
|
|
442
|
+
connectedText?: string;
|
|
443
|
+
errorText?: string;
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
export type AgentWidgetVoiceRecognitionConfig = {
|
|
447
|
+
enabled?: boolean;
|
|
448
|
+
pauseDuration?: number;
|
|
449
|
+
iconName?: string;
|
|
450
|
+
iconSize?: string;
|
|
451
|
+
iconColor?: string;
|
|
452
|
+
backgroundColor?: string;
|
|
453
|
+
borderColor?: string;
|
|
454
|
+
borderWidth?: string;
|
|
455
|
+
paddingX?: string;
|
|
456
|
+
paddingY?: string;
|
|
457
|
+
tooltipText?: string;
|
|
458
|
+
showTooltip?: boolean;
|
|
459
|
+
recordingIconColor?: string;
|
|
460
|
+
recordingBackgroundColor?: string;
|
|
461
|
+
recordingBorderColor?: string;
|
|
462
|
+
showRecordingIndicator?: boolean;
|
|
463
|
+
autoResume?: boolean | "assistant";
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
export type AgentWidgetToolCallConfig = {
|
|
467
|
+
backgroundColor?: string;
|
|
468
|
+
borderColor?: string;
|
|
469
|
+
borderWidth?: string;
|
|
470
|
+
borderRadius?: string;
|
|
471
|
+
headerBackgroundColor?: string;
|
|
472
|
+
headerTextColor?: string;
|
|
473
|
+
headerPaddingX?: string;
|
|
474
|
+
headerPaddingY?: string;
|
|
475
|
+
contentBackgroundColor?: string;
|
|
476
|
+
contentTextColor?: string;
|
|
477
|
+
contentPaddingX?: string;
|
|
478
|
+
contentPaddingY?: string;
|
|
479
|
+
codeBlockBackgroundColor?: string;
|
|
480
|
+
codeBlockBorderColor?: string;
|
|
481
|
+
codeBlockTextColor?: string;
|
|
482
|
+
toggleTextColor?: string;
|
|
483
|
+
labelTextColor?: string;
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
export type AgentWidgetSuggestionChipsConfig = {
|
|
487
|
+
fontFamily?: "sans-serif" | "serif" | "mono";
|
|
488
|
+
fontWeight?: string;
|
|
489
|
+
paddingX?: string;
|
|
490
|
+
paddingY?: string;
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Interface for pluggable stream parsers that extract text from streaming responses.
|
|
495
|
+
* Parsers handle incremental parsing to extract text values from structured formats (JSON, XML, etc.).
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```typescript
|
|
499
|
+
* const jsonParser: AgentWidgetStreamParser = {
|
|
500
|
+
* processChunk: async (content) => {
|
|
501
|
+
* // Extract text from JSON - return null if not JSON or text not available yet
|
|
502
|
+
* if (!content.trim().startsWith('{')) return null;
|
|
503
|
+
* const match = content.match(/"text"\s*:\s*"([^"]*)"/);
|
|
504
|
+
* return match ? match[1] : null;
|
|
505
|
+
* },
|
|
506
|
+
* getExtractedText: () => extractedText
|
|
507
|
+
* };
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
export interface AgentWidgetStreamParserResult {
|
|
511
|
+
/**
|
|
512
|
+
* The extracted text to display (may be partial during streaming)
|
|
513
|
+
*/
|
|
514
|
+
text: string | null;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* The raw accumulated content. Built-in parsers always populate this so
|
|
518
|
+
* downstream middleware (action handlers, logging, etc.) can
|
|
519
|
+
* inspect/parse the original structured payload.
|
|
520
|
+
*/
|
|
521
|
+
raw?: string;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export interface AgentWidgetStreamParser {
|
|
525
|
+
/**
|
|
526
|
+
* Process a chunk of content and return the extracted text (if available).
|
|
527
|
+
* This method is called for each chunk as it arrives during streaming.
|
|
528
|
+
* Return null if the content doesn't match this parser's format or if text is not yet available.
|
|
529
|
+
*
|
|
530
|
+
* @param accumulatedContent - The full accumulated content so far (including new chunk)
|
|
531
|
+
* @returns The extracted text value and optionally raw content, or null if not yet available or format doesn't match
|
|
532
|
+
*/
|
|
533
|
+
processChunk(accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> | AgentWidgetStreamParserResult | string | null;
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Get the currently extracted text value (may be partial).
|
|
537
|
+
* This is called synchronously to get the latest extracted text without processing.
|
|
538
|
+
*
|
|
539
|
+
* @returns The currently extracted text value, or null if not yet available
|
|
540
|
+
*/
|
|
541
|
+
getExtractedText(): string | null;
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Clean up any resources when parsing is complete.
|
|
545
|
+
*/
|
|
546
|
+
close?(): Promise<void> | void;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Component renderer function signature for custom components
|
|
552
|
+
*/
|
|
553
|
+
export type AgentWidgetComponentRenderer = (
|
|
554
|
+
props: Record<string, unknown>,
|
|
555
|
+
context: {
|
|
556
|
+
message: AgentWidgetMessage;
|
|
557
|
+
config: AgentWidgetConfig;
|
|
558
|
+
updateProps: (newProps: Record<string, unknown>) => void;
|
|
559
|
+
}
|
|
560
|
+
) => HTMLElement;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Result from custom SSE event parser
|
|
564
|
+
*/
|
|
565
|
+
export type AgentWidgetSSEEventResult = {
|
|
566
|
+
/** Text content to display */
|
|
567
|
+
text?: string;
|
|
568
|
+
/** Whether the stream is complete */
|
|
569
|
+
done?: boolean;
|
|
570
|
+
/** Error message if an error occurred */
|
|
571
|
+
error?: string;
|
|
572
|
+
} | null;
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Custom SSE event parser function
|
|
576
|
+
* Allows transforming non-standard SSE event formats to persona's expected format
|
|
577
|
+
*/
|
|
578
|
+
export type AgentWidgetSSEEventParser = (
|
|
579
|
+
eventData: unknown
|
|
580
|
+
) => AgentWidgetSSEEventResult | Promise<AgentWidgetSSEEventResult>;
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Custom fetch function for full control over API requests
|
|
584
|
+
* Use this for custom authentication, request transformation, etc.
|
|
585
|
+
*/
|
|
586
|
+
export type AgentWidgetCustomFetch = (
|
|
587
|
+
url: string,
|
|
588
|
+
init: RequestInit,
|
|
589
|
+
payload: AgentWidgetRequestPayload
|
|
590
|
+
) => Promise<Response>;
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Dynamic headers function - called before each request
|
|
594
|
+
*/
|
|
595
|
+
export type AgentWidgetHeadersFunction = () => Record<string, string> | Promise<Record<string, string>>;
|
|
596
|
+
|
|
597
|
+
// ============================================================================
|
|
598
|
+
// Client Token Types
|
|
599
|
+
// ============================================================================
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Session information returned after client token initialization.
|
|
603
|
+
* Contains session ID, expiry time, flow info, and config from the server.
|
|
604
|
+
*/
|
|
605
|
+
export type ClientSession = {
|
|
606
|
+
/** Unique session identifier */
|
|
607
|
+
sessionId: string;
|
|
608
|
+
/** When the session expires */
|
|
609
|
+
expiresAt: Date;
|
|
610
|
+
/** Flow information */
|
|
611
|
+
flow: {
|
|
612
|
+
id: string;
|
|
613
|
+
name: string;
|
|
614
|
+
description: string | null;
|
|
615
|
+
};
|
|
616
|
+
/** Configuration from the server */
|
|
617
|
+
config: {
|
|
618
|
+
welcomeMessage: string | null;
|
|
619
|
+
placeholder: string;
|
|
620
|
+
theme: Record<string, unknown> | null;
|
|
621
|
+
};
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Raw API response from /v1/client/init endpoint
|
|
626
|
+
*/
|
|
627
|
+
export type ClientInitResponse = {
|
|
628
|
+
session_id: string;
|
|
629
|
+
expires_at: string;
|
|
630
|
+
flow: {
|
|
631
|
+
id: string;
|
|
632
|
+
name: string;
|
|
633
|
+
description: string | null;
|
|
634
|
+
};
|
|
635
|
+
config: {
|
|
636
|
+
welcome_message: string | null;
|
|
637
|
+
placeholder: string;
|
|
638
|
+
theme: Record<string, unknown> | null;
|
|
639
|
+
};
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Request payload for /v1/client/chat endpoint
|
|
644
|
+
*/
|
|
645
|
+
export type ClientChatRequest = {
|
|
646
|
+
session_id: string;
|
|
647
|
+
messages: Array<{
|
|
648
|
+
id?: string;
|
|
649
|
+
role: 'user' | 'assistant' | 'system';
|
|
650
|
+
content: MessageContent;
|
|
651
|
+
}>;
|
|
652
|
+
/** ID for the expected assistant response message */
|
|
653
|
+
assistant_message_id?: string;
|
|
654
|
+
metadata?: Record<string, unknown>;
|
|
655
|
+
context?: Record<string, unknown>;
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Feedback types supported by the API
|
|
660
|
+
*/
|
|
661
|
+
export type ClientFeedbackType = 'upvote' | 'downvote' | 'copy' | 'csat' | 'nps';
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Request payload for /v1/client/feedback endpoint
|
|
665
|
+
*/
|
|
666
|
+
export type ClientFeedbackRequest = {
|
|
667
|
+
session_id: string;
|
|
668
|
+
/** Required for upvote, downvote, copy feedback types */
|
|
669
|
+
message_id?: string;
|
|
670
|
+
type: ClientFeedbackType;
|
|
671
|
+
/** Required for csat (1-5) and nps (0-10) feedback types */
|
|
672
|
+
rating?: number;
|
|
673
|
+
/** Optional comment for any feedback type */
|
|
674
|
+
comment?: string;
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// ============================================================================
|
|
678
|
+
// Layout Configuration Types
|
|
679
|
+
// ============================================================================
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Context provided to header render functions
|
|
683
|
+
*/
|
|
684
|
+
export type HeaderRenderContext = {
|
|
685
|
+
config: AgentWidgetConfig;
|
|
686
|
+
onClose?: () => void;
|
|
687
|
+
onClearChat?: () => void;
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Context provided to message render functions
|
|
692
|
+
*/
|
|
693
|
+
export type MessageRenderContext = {
|
|
694
|
+
message: AgentWidgetMessage;
|
|
695
|
+
config: AgentWidgetConfig;
|
|
696
|
+
streaming: boolean;
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Context provided to slot render functions
|
|
701
|
+
*/
|
|
702
|
+
export type SlotRenderContext = {
|
|
703
|
+
config: AgentWidgetConfig;
|
|
704
|
+
defaultContent: () => HTMLElement | null;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Header layout configuration
|
|
709
|
+
* Allows customization of the header section appearance and behavior
|
|
710
|
+
*/
|
|
711
|
+
export type AgentWidgetHeaderLayoutConfig = {
|
|
712
|
+
/**
|
|
713
|
+
* Layout preset: "default" | "minimal" | "expanded"
|
|
714
|
+
* - default: Standard layout with icon, title, subtitle, and buttons
|
|
715
|
+
* - minimal: Simplified layout with just title and close button
|
|
716
|
+
* - expanded: Full branding area with additional content space
|
|
717
|
+
*/
|
|
718
|
+
layout?: "default" | "minimal" | "expanded";
|
|
719
|
+
/** Show/hide the header icon */
|
|
720
|
+
showIcon?: boolean;
|
|
721
|
+
/** Show/hide the title */
|
|
722
|
+
showTitle?: boolean;
|
|
723
|
+
/** Show/hide the subtitle */
|
|
724
|
+
showSubtitle?: boolean;
|
|
725
|
+
/** Show/hide the close button */
|
|
726
|
+
showCloseButton?: boolean;
|
|
727
|
+
/** Show/hide the clear chat button */
|
|
728
|
+
showClearChat?: boolean;
|
|
729
|
+
/**
|
|
730
|
+
* Custom renderer for complete header override
|
|
731
|
+
* When provided, replaces the entire header with custom content
|
|
732
|
+
*/
|
|
733
|
+
render?: (context: HeaderRenderContext) => HTMLElement;
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Avatar configuration for message bubbles
|
|
738
|
+
*/
|
|
739
|
+
export type AgentWidgetAvatarConfig = {
|
|
740
|
+
/** Whether to show avatars */
|
|
741
|
+
show?: boolean;
|
|
742
|
+
/** Position of avatar relative to message bubble */
|
|
743
|
+
position?: "left" | "right";
|
|
744
|
+
/** URL or emoji for user avatar */
|
|
745
|
+
userAvatar?: string;
|
|
746
|
+
/** URL or emoji for assistant avatar */
|
|
747
|
+
assistantAvatar?: string;
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Timestamp configuration for message bubbles
|
|
752
|
+
*/
|
|
753
|
+
export type AgentWidgetTimestampConfig = {
|
|
754
|
+
/** Whether to show timestamps */
|
|
755
|
+
show?: boolean;
|
|
756
|
+
/** Position of timestamp relative to message */
|
|
757
|
+
position?: "inline" | "below";
|
|
758
|
+
/** Custom formatter for timestamp display */
|
|
759
|
+
format?: (date: Date) => string;
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Message layout configuration
|
|
764
|
+
* Allows customization of how chat messages are displayed
|
|
765
|
+
*/
|
|
766
|
+
export type AgentWidgetMessageLayoutConfig = {
|
|
767
|
+
/**
|
|
768
|
+
* Layout preset: "bubble" | "flat" | "minimal"
|
|
769
|
+
* - bubble: Standard chat bubble appearance (default)
|
|
770
|
+
* - flat: Flat messages without bubble styling
|
|
771
|
+
* - minimal: Minimal styling with reduced padding/borders
|
|
772
|
+
*/
|
|
773
|
+
layout?: "bubble" | "flat" | "minimal";
|
|
774
|
+
/** Avatar configuration */
|
|
775
|
+
avatar?: AgentWidgetAvatarConfig;
|
|
776
|
+
/** Timestamp configuration */
|
|
777
|
+
timestamp?: AgentWidgetTimestampConfig;
|
|
778
|
+
/** Group consecutive messages from the same role */
|
|
779
|
+
groupConsecutive?: boolean;
|
|
780
|
+
/**
|
|
781
|
+
* Custom renderer for user messages
|
|
782
|
+
* When provided, replaces the default user message rendering
|
|
783
|
+
*/
|
|
784
|
+
renderUserMessage?: (context: MessageRenderContext) => HTMLElement;
|
|
785
|
+
/**
|
|
786
|
+
* Custom renderer for assistant messages
|
|
787
|
+
* When provided, replaces the default assistant message rendering
|
|
788
|
+
*/
|
|
789
|
+
renderAssistantMessage?: (context: MessageRenderContext) => HTMLElement;
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Available layout slots for content injection
|
|
794
|
+
*/
|
|
795
|
+
export type WidgetLayoutSlot =
|
|
796
|
+
| "header-left"
|
|
797
|
+
| "header-center"
|
|
798
|
+
| "header-right"
|
|
799
|
+
| "body-top"
|
|
800
|
+
| "messages"
|
|
801
|
+
| "body-bottom"
|
|
802
|
+
| "footer-top"
|
|
803
|
+
| "composer"
|
|
804
|
+
| "footer-bottom";
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Slot renderer function signature
|
|
808
|
+
* Returns HTMLElement to render in the slot, or null to use default content
|
|
809
|
+
*/
|
|
810
|
+
export type SlotRenderer = (context: SlotRenderContext) => HTMLElement | null;
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Main layout configuration
|
|
814
|
+
* Provides comprehensive control over widget layout and appearance
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```typescript
|
|
818
|
+
* config: {
|
|
819
|
+
* layout: {
|
|
820
|
+
* header: { layout: "minimal" },
|
|
821
|
+
* messages: {
|
|
822
|
+
* avatar: { show: true, assistantAvatar: "/bot.png" },
|
|
823
|
+
* timestamp: { show: true, position: "below" }
|
|
824
|
+
* },
|
|
825
|
+
* slots: {
|
|
826
|
+
* "footer-top": () => {
|
|
827
|
+
* const el = document.createElement("div");
|
|
828
|
+
* el.textContent = "Powered by AI";
|
|
829
|
+
* return el;
|
|
830
|
+
* }
|
|
831
|
+
* }
|
|
832
|
+
* }
|
|
833
|
+
* }
|
|
834
|
+
* ```
|
|
835
|
+
*/
|
|
836
|
+
export type AgentWidgetLayoutConfig = {
|
|
837
|
+
/** Header layout configuration */
|
|
838
|
+
header?: AgentWidgetHeaderLayoutConfig;
|
|
839
|
+
/** Message layout configuration */
|
|
840
|
+
messages?: AgentWidgetMessageLayoutConfig;
|
|
841
|
+
/** Slot renderers for custom content injection */
|
|
842
|
+
slots?: Partial<Record<WidgetLayoutSlot, SlotRenderer>>;
|
|
843
|
+
/**
|
|
844
|
+
* Show/hide the header section entirely.
|
|
845
|
+
* When false, the header (including icon, title, buttons) is completely hidden.
|
|
846
|
+
* @default true
|
|
847
|
+
*/
|
|
848
|
+
showHeader?: boolean;
|
|
849
|
+
/**
|
|
850
|
+
* Show/hide the footer/composer section entirely.
|
|
851
|
+
* When false, the footer (including input field, send button, suggestions) is completely hidden.
|
|
852
|
+
* Useful for read-only conversation previews.
|
|
853
|
+
* @default true
|
|
854
|
+
*/
|
|
855
|
+
showFooter?: boolean;
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
// ============================================================================
|
|
859
|
+
// Markdown Configuration Types
|
|
860
|
+
// ============================================================================
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Token types for marked renderer methods
|
|
864
|
+
*/
|
|
865
|
+
export type AgentWidgetMarkdownHeadingToken = {
|
|
866
|
+
type: "heading";
|
|
867
|
+
raw: string;
|
|
868
|
+
depth: 1 | 2 | 3 | 4 | 5 | 6;
|
|
869
|
+
text: string;
|
|
870
|
+
tokens: unknown[];
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
export type AgentWidgetMarkdownCodeToken = {
|
|
874
|
+
type: "code";
|
|
875
|
+
raw: string;
|
|
876
|
+
text: string;
|
|
877
|
+
lang?: string;
|
|
878
|
+
escaped?: boolean;
|
|
879
|
+
};
|
|
880
|
+
|
|
881
|
+
export type AgentWidgetMarkdownBlockquoteToken = {
|
|
882
|
+
type: "blockquote";
|
|
883
|
+
raw: string;
|
|
884
|
+
text: string;
|
|
885
|
+
tokens: unknown[];
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
export type AgentWidgetMarkdownTableToken = {
|
|
889
|
+
type: "table";
|
|
890
|
+
raw: string;
|
|
891
|
+
header: Array<{ text: string; tokens: unknown[] }>;
|
|
892
|
+
rows: Array<Array<{ text: string; tokens: unknown[] }>>;
|
|
893
|
+
align: Array<"left" | "center" | "right" | null>;
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
export type AgentWidgetMarkdownLinkToken = {
|
|
897
|
+
type: "link";
|
|
898
|
+
raw: string;
|
|
899
|
+
href: string;
|
|
900
|
+
title: string | null;
|
|
901
|
+
text: string;
|
|
902
|
+
tokens: unknown[];
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
export type AgentWidgetMarkdownImageToken = {
|
|
906
|
+
type: "image";
|
|
907
|
+
raw: string;
|
|
908
|
+
href: string;
|
|
909
|
+
title: string | null;
|
|
910
|
+
text: string;
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
export type AgentWidgetMarkdownListToken = {
|
|
914
|
+
type: "list";
|
|
915
|
+
raw: string;
|
|
916
|
+
ordered: boolean;
|
|
917
|
+
start: number | "";
|
|
918
|
+
loose: boolean;
|
|
919
|
+
items: unknown[];
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
export type AgentWidgetMarkdownListItemToken = {
|
|
923
|
+
type: "list_item";
|
|
924
|
+
raw: string;
|
|
925
|
+
task: boolean;
|
|
926
|
+
checked?: boolean;
|
|
927
|
+
loose: boolean;
|
|
928
|
+
text: string;
|
|
929
|
+
tokens: unknown[];
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
export type AgentWidgetMarkdownParagraphToken = {
|
|
933
|
+
type: "paragraph";
|
|
934
|
+
raw: string;
|
|
935
|
+
text: string;
|
|
936
|
+
tokens: unknown[];
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
export type AgentWidgetMarkdownCodespanToken = {
|
|
940
|
+
type: "codespan";
|
|
941
|
+
raw: string;
|
|
942
|
+
text: string;
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
export type AgentWidgetMarkdownStrongToken = {
|
|
946
|
+
type: "strong";
|
|
947
|
+
raw: string;
|
|
948
|
+
text: string;
|
|
949
|
+
tokens: unknown[];
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
export type AgentWidgetMarkdownEmToken = {
|
|
953
|
+
type: "em";
|
|
954
|
+
raw: string;
|
|
955
|
+
text: string;
|
|
956
|
+
tokens: unknown[];
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Custom renderer overrides for markdown elements.
|
|
961
|
+
* Each method receives the token and should return an HTML string.
|
|
962
|
+
* Return `false` to use the default renderer.
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* ```typescript
|
|
966
|
+
* renderer: {
|
|
967
|
+
* heading(token) {
|
|
968
|
+
* return `<h${token.depth} class="custom-heading">${token.text}</h${token.depth}>`;
|
|
969
|
+
* },
|
|
970
|
+
* link(token) {
|
|
971
|
+
* return `<a href="${token.href}" target="_blank" rel="noopener">${token.text}</a>`;
|
|
972
|
+
* }
|
|
973
|
+
* }
|
|
974
|
+
* ```
|
|
975
|
+
*/
|
|
976
|
+
export type AgentWidgetMarkdownRendererOverrides = {
|
|
977
|
+
/** Override heading rendering (h1-h6) */
|
|
978
|
+
heading?: (token: AgentWidgetMarkdownHeadingToken) => string | false;
|
|
979
|
+
/** Override code block rendering */
|
|
980
|
+
code?: (token: AgentWidgetMarkdownCodeToken) => string | false;
|
|
981
|
+
/** Override blockquote rendering */
|
|
982
|
+
blockquote?: (token: AgentWidgetMarkdownBlockquoteToken) => string | false;
|
|
983
|
+
/** Override table rendering */
|
|
984
|
+
table?: (token: AgentWidgetMarkdownTableToken) => string | false;
|
|
985
|
+
/** Override link rendering */
|
|
986
|
+
link?: (token: AgentWidgetMarkdownLinkToken) => string | false;
|
|
987
|
+
/** Override image rendering */
|
|
988
|
+
image?: (token: AgentWidgetMarkdownImageToken) => string | false;
|
|
989
|
+
/** Override list rendering (ul/ol) */
|
|
990
|
+
list?: (token: AgentWidgetMarkdownListToken) => string | false;
|
|
991
|
+
/** Override list item rendering */
|
|
992
|
+
listitem?: (token: AgentWidgetMarkdownListItemToken) => string | false;
|
|
993
|
+
/** Override paragraph rendering */
|
|
994
|
+
paragraph?: (token: AgentWidgetMarkdownParagraphToken) => string | false;
|
|
995
|
+
/** Override inline code rendering */
|
|
996
|
+
codespan?: (token: AgentWidgetMarkdownCodespanToken) => string | false;
|
|
997
|
+
/** Override strong/bold rendering */
|
|
998
|
+
strong?: (token: AgentWidgetMarkdownStrongToken) => string | false;
|
|
999
|
+
/** Override emphasis/italic rendering */
|
|
1000
|
+
em?: (token: AgentWidgetMarkdownEmToken) => string | false;
|
|
1001
|
+
/** Override horizontal rule rendering */
|
|
1002
|
+
hr?: () => string | false;
|
|
1003
|
+
/** Override line break rendering */
|
|
1004
|
+
br?: () => string | false;
|
|
1005
|
+
/** Override deleted/strikethrough rendering */
|
|
1006
|
+
del?: (token: { type: "del"; raw: string; text: string; tokens: unknown[] }) => string | false;
|
|
1007
|
+
/** Override checkbox rendering (in task lists) */
|
|
1008
|
+
checkbox?: (token: { checked: boolean }) => string | false;
|
|
1009
|
+
/** Override HTML passthrough */
|
|
1010
|
+
html?: (token: { type: "html"; raw: string; text: string }) => string | false;
|
|
1011
|
+
/** Override text rendering */
|
|
1012
|
+
text?: (token: { type: "text"; raw: string; text: string }) => string | false;
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Markdown parsing options (subset of marked options)
|
|
1017
|
+
*/
|
|
1018
|
+
export type AgentWidgetMarkdownOptions = {
|
|
1019
|
+
/**
|
|
1020
|
+
* Enable GitHub Flavored Markdown (tables, strikethrough, autolinks).
|
|
1021
|
+
* @default true
|
|
1022
|
+
*/
|
|
1023
|
+
gfm?: boolean;
|
|
1024
|
+
/**
|
|
1025
|
+
* Convert \n in paragraphs into <br>.
|
|
1026
|
+
* @default true
|
|
1027
|
+
*/
|
|
1028
|
+
breaks?: boolean;
|
|
1029
|
+
/**
|
|
1030
|
+
* Conform to original markdown.pl as much as possible.
|
|
1031
|
+
* @default false
|
|
1032
|
+
*/
|
|
1033
|
+
pedantic?: boolean;
|
|
1034
|
+
/**
|
|
1035
|
+
* Add id attributes to headings.
|
|
1036
|
+
* @default false
|
|
1037
|
+
*/
|
|
1038
|
+
headerIds?: boolean;
|
|
1039
|
+
/**
|
|
1040
|
+
* Prefix for heading id attributes.
|
|
1041
|
+
* @default ""
|
|
1042
|
+
*/
|
|
1043
|
+
headerPrefix?: string;
|
|
1044
|
+
/**
|
|
1045
|
+
* Mangle email addresses for spam protection.
|
|
1046
|
+
* @default true
|
|
1047
|
+
*/
|
|
1048
|
+
mangle?: boolean;
|
|
1049
|
+
/**
|
|
1050
|
+
* Silent mode - don't throw on parse errors.
|
|
1051
|
+
* @default false
|
|
1052
|
+
*/
|
|
1053
|
+
silent?: boolean;
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
/**
|
|
1057
|
+
* Markdown configuration for customizing how markdown is rendered in chat messages.
|
|
1058
|
+
* Provides three levels of control:
|
|
1059
|
+
*
|
|
1060
|
+
* 1. **CSS Variables** - Override styles via `--cw-md-*` CSS custom properties
|
|
1061
|
+
* 2. **Parsing Options** - Configure marked behavior via `options`
|
|
1062
|
+
* 3. **Custom Renderers** - Full control via `renderer` overrides
|
|
1063
|
+
*
|
|
1064
|
+
* @example
|
|
1065
|
+
* ```typescript
|
|
1066
|
+
* // Level 2: Configure parsing options
|
|
1067
|
+
* config: {
|
|
1068
|
+
* markdown: {
|
|
1069
|
+
* options: {
|
|
1070
|
+
* gfm: true,
|
|
1071
|
+
* breaks: true,
|
|
1072
|
+
* headerIds: true
|
|
1073
|
+
* }
|
|
1074
|
+
* }
|
|
1075
|
+
* }
|
|
1076
|
+
* ```
|
|
1077
|
+
*
|
|
1078
|
+
* @example
|
|
1079
|
+
* ```typescript
|
|
1080
|
+
* // Level 3: Custom renderers
|
|
1081
|
+
* config: {
|
|
1082
|
+
* markdown: {
|
|
1083
|
+
* renderer: {
|
|
1084
|
+
* heading(token) {
|
|
1085
|
+
* return `<h${token.depth} class="custom-h${token.depth}">${token.text}</h${token.depth}>`;
|
|
1086
|
+
* },
|
|
1087
|
+
* link(token) {
|
|
1088
|
+
* return `<a href="${token.href}" target="_blank">${token.text}</a>`;
|
|
1089
|
+
* },
|
|
1090
|
+
* table(token) {
|
|
1091
|
+
* // Wrap tables in a scrollable container
|
|
1092
|
+
* return `<div class="table-scroll">${this.parser.parse(token.tokens)}</div>`;
|
|
1093
|
+
* }
|
|
1094
|
+
* }
|
|
1095
|
+
* }
|
|
1096
|
+
* }
|
|
1097
|
+
* ```
|
|
1098
|
+
*/
|
|
1099
|
+
export type AgentWidgetMarkdownConfig = {
|
|
1100
|
+
/**
|
|
1101
|
+
* Markdown parsing options.
|
|
1102
|
+
* These are passed directly to the marked parser.
|
|
1103
|
+
*/
|
|
1104
|
+
options?: AgentWidgetMarkdownOptions;
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Custom renderer overrides for specific markdown elements.
|
|
1108
|
+
* Each method receives a token object and should return an HTML string.
|
|
1109
|
+
* Return `false` to fall back to the default renderer.
|
|
1110
|
+
*/
|
|
1111
|
+
renderer?: AgentWidgetMarkdownRendererOverrides;
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Disable default markdown CSS styles.
|
|
1115
|
+
* When true, the widget won't apply any default styles to markdown elements,
|
|
1116
|
+
* allowing you to provide your own CSS.
|
|
1117
|
+
*
|
|
1118
|
+
* @default false
|
|
1119
|
+
*/
|
|
1120
|
+
disableDefaultStyles?: boolean;
|
|
1121
|
+
};
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Configuration for file attachments in the composer.
|
|
1125
|
+
* Enables users to attach images to their messages.
|
|
1126
|
+
*
|
|
1127
|
+
* @example
|
|
1128
|
+
* ```typescript
|
|
1129
|
+
* config: {
|
|
1130
|
+
* attachments: {
|
|
1131
|
+
* enabled: true,
|
|
1132
|
+
* allowedTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
|
|
1133
|
+
* maxFileSize: 5 * 1024 * 1024, // 5MB
|
|
1134
|
+
* maxFiles: 4
|
|
1135
|
+
* }
|
|
1136
|
+
* }
|
|
1137
|
+
* ```
|
|
1138
|
+
*/
|
|
1139
|
+
export type AgentWidgetAttachmentsConfig = {
|
|
1140
|
+
/**
|
|
1141
|
+
* Enable/disable file attachments.
|
|
1142
|
+
* @default false
|
|
1143
|
+
*/
|
|
1144
|
+
enabled?: boolean;
|
|
1145
|
+
/**
|
|
1146
|
+
* Allowed MIME types for attachments.
|
|
1147
|
+
* @default ['image/png', 'image/jpeg', 'image/gif', 'image/webp']
|
|
1148
|
+
*/
|
|
1149
|
+
allowedTypes?: string[];
|
|
1150
|
+
/**
|
|
1151
|
+
* Maximum file size in bytes.
|
|
1152
|
+
* @default 10485760 (10MB)
|
|
1153
|
+
*/
|
|
1154
|
+
maxFileSize?: number;
|
|
1155
|
+
/**
|
|
1156
|
+
* Maximum number of files per message.
|
|
1157
|
+
* @default 4
|
|
1158
|
+
*/
|
|
1159
|
+
maxFiles?: number;
|
|
1160
|
+
/**
|
|
1161
|
+
* Button icon name (from Lucide icons).
|
|
1162
|
+
* @default 'image-plus'
|
|
1163
|
+
*/
|
|
1164
|
+
buttonIconName?: string;
|
|
1165
|
+
/**
|
|
1166
|
+
* Tooltip text for the attachment button.
|
|
1167
|
+
* @default 'Attach image'
|
|
1168
|
+
*/
|
|
1169
|
+
buttonTooltipText?: string;
|
|
1170
|
+
/**
|
|
1171
|
+
* Callback when a file is rejected (wrong type or too large).
|
|
1172
|
+
*/
|
|
1173
|
+
onFileRejected?: (file: File, reason: 'type' | 'size' | 'count') => void;
|
|
1174
|
+
};
|
|
1175
|
+
|
|
1176
|
+
export type AgentWidgetConfig = {
|
|
1177
|
+
apiUrl?: string;
|
|
1178
|
+
flowId?: string;
|
|
1179
|
+
/**
|
|
1180
|
+
* Client token for direct browser-to-API communication.
|
|
1181
|
+
* When set, the widget uses /v1/client/* endpoints instead of /v1/dispatch.
|
|
1182
|
+
* Mutually exclusive with apiKey/headers authentication.
|
|
1183
|
+
*
|
|
1184
|
+
* @example
|
|
1185
|
+
* ```typescript
|
|
1186
|
+
* config: {
|
|
1187
|
+
* clientToken: 'ct_live_flow01k7_a8b9c0d1e2f3g4h5i6j7k8l9'
|
|
1188
|
+
* }
|
|
1189
|
+
* ```
|
|
1190
|
+
*/
|
|
1191
|
+
clientToken?: string;
|
|
1192
|
+
/**
|
|
1193
|
+
* Callback when session is initialized (client token mode only).
|
|
1194
|
+
* Receives session info including expiry time.
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```typescript
|
|
1198
|
+
* config: {
|
|
1199
|
+
* onSessionInit: (session) => {
|
|
1200
|
+
* console.log('Session started:', session.sessionId);
|
|
1201
|
+
* }
|
|
1202
|
+
* }
|
|
1203
|
+
* ```
|
|
1204
|
+
*/
|
|
1205
|
+
onSessionInit?: (session: ClientSession) => void;
|
|
1206
|
+
/**
|
|
1207
|
+
* Callback when session expires or errors (client token mode only).
|
|
1208
|
+
* Widget should prompt user to refresh.
|
|
1209
|
+
*
|
|
1210
|
+
* @example
|
|
1211
|
+
* ```typescript
|
|
1212
|
+
* config: {
|
|
1213
|
+
* onSessionExpired: () => {
|
|
1214
|
+
* alert('Your session has expired. Please refresh the page.');
|
|
1215
|
+
* }
|
|
1216
|
+
* }
|
|
1217
|
+
* ```
|
|
1218
|
+
*/
|
|
1219
|
+
onSessionExpired?: () => void;
|
|
1220
|
+
/**
|
|
1221
|
+
* Get stored session ID for session resumption (client token mode only).
|
|
1222
|
+
* Called when initializing a new session to check if there's a previous session_id
|
|
1223
|
+
* that should be passed to /client/init to resume the same conversation record.
|
|
1224
|
+
*
|
|
1225
|
+
* @example
|
|
1226
|
+
* ```typescript
|
|
1227
|
+
* config: {
|
|
1228
|
+
* getStoredSessionId: () => {
|
|
1229
|
+
* const stored = localStorage.getItem('session_id');
|
|
1230
|
+
* return stored || null;
|
|
1231
|
+
* }
|
|
1232
|
+
* }
|
|
1233
|
+
* ```
|
|
1234
|
+
*/
|
|
1235
|
+
getStoredSessionId?: () => string | null;
|
|
1236
|
+
/**
|
|
1237
|
+
* Store session ID for session resumption (client token mode only).
|
|
1238
|
+
* Called when a new session is initialized to persist the session_id
|
|
1239
|
+
* so it can be used to resume the conversation later.
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* ```typescript
|
|
1243
|
+
* config: {
|
|
1244
|
+
* setStoredSessionId: (sessionId) => {
|
|
1245
|
+
* localStorage.setItem('session_id', sessionId);
|
|
1246
|
+
* }
|
|
1247
|
+
* }
|
|
1248
|
+
* ```
|
|
1249
|
+
*/
|
|
1250
|
+
setStoredSessionId?: (sessionId: string) => void;
|
|
1251
|
+
/**
|
|
1252
|
+
* Static headers to include with each request.
|
|
1253
|
+
* For dynamic headers (e.g., auth tokens), use `getHeaders` instead.
|
|
1254
|
+
*/
|
|
1255
|
+
headers?: Record<string, string>;
|
|
1256
|
+
/**
|
|
1257
|
+
* Dynamic headers function - called before each request.
|
|
1258
|
+
* Useful for adding auth tokens that may change.
|
|
1259
|
+
* @example
|
|
1260
|
+
* ```typescript
|
|
1261
|
+
* getHeaders: async () => ({
|
|
1262
|
+
* 'Authorization': `Bearer ${await getAuthToken()}`
|
|
1263
|
+
* })
|
|
1264
|
+
* ```
|
|
1265
|
+
*/
|
|
1266
|
+
getHeaders?: AgentWidgetHeadersFunction;
|
|
1267
|
+
copy?: {
|
|
1268
|
+
welcomeTitle?: string;
|
|
1269
|
+
welcomeSubtitle?: string;
|
|
1270
|
+
inputPlaceholder?: string;
|
|
1271
|
+
sendButtonLabel?: string;
|
|
1272
|
+
};
|
|
1273
|
+
theme?: AgentWidgetTheme;
|
|
1274
|
+
/**
|
|
1275
|
+
* Theme colors for dark mode. Applied when dark mode is detected
|
|
1276
|
+
* (when colorScheme is 'dark' or 'auto' with dark mode active).
|
|
1277
|
+
* If not provided, falls back to `theme` colors.
|
|
1278
|
+
*
|
|
1279
|
+
* @example
|
|
1280
|
+
* ```typescript
|
|
1281
|
+
* config: {
|
|
1282
|
+
* theme: { primary: '#111827', surface: '#ffffff' },
|
|
1283
|
+
* darkTheme: { primary: '#f9fafb', surface: '#1f2937' },
|
|
1284
|
+
* colorScheme: 'auto'
|
|
1285
|
+
* }
|
|
1286
|
+
* ```
|
|
1287
|
+
*/
|
|
1288
|
+
darkTheme?: AgentWidgetTheme;
|
|
1289
|
+
/**
|
|
1290
|
+
* Color scheme mode for the widget.
|
|
1291
|
+
* - 'light': Always use light theme (default)
|
|
1292
|
+
* - 'dark': Always use dark theme
|
|
1293
|
+
* - 'auto': Automatically detect from page (HTML class or prefers-color-scheme)
|
|
1294
|
+
*
|
|
1295
|
+
* When 'auto', detection order:
|
|
1296
|
+
* 1. Check if `<html>` has 'dark' class
|
|
1297
|
+
* 2. Fall back to `prefers-color-scheme: dark` media query
|
|
1298
|
+
*
|
|
1299
|
+
* @default 'light'
|
|
1300
|
+
*/
|
|
1301
|
+
colorScheme?: 'auto' | 'light' | 'dark';
|
|
1302
|
+
features?: AgentWidgetFeatureFlags;
|
|
1303
|
+
launcher?: AgentWidgetLauncherConfig;
|
|
1304
|
+
initialMessages?: AgentWidgetMessage[];
|
|
1305
|
+
suggestionChips?: string[];
|
|
1306
|
+
suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
|
|
1307
|
+
debug?: boolean;
|
|
1308
|
+
formEndpoint?: string;
|
|
1309
|
+
launcherWidth?: string;
|
|
1310
|
+
sendButton?: AgentWidgetSendButtonConfig;
|
|
1311
|
+
statusIndicator?: AgentWidgetStatusIndicatorConfig;
|
|
1312
|
+
voiceRecognition?: AgentWidgetVoiceRecognitionConfig;
|
|
1313
|
+
toolCall?: AgentWidgetToolCallConfig;
|
|
1314
|
+
postprocessMessage?: (context: {
|
|
1315
|
+
text: string;
|
|
1316
|
+
message: AgentWidgetMessage;
|
|
1317
|
+
streaming: boolean;
|
|
1318
|
+
raw?: string;
|
|
1319
|
+
}) => string;
|
|
1320
|
+
plugins?: AgentWidgetPlugin[];
|
|
1321
|
+
contextProviders?: AgentWidgetContextProvider[];
|
|
1322
|
+
requestMiddleware?: AgentWidgetRequestMiddleware;
|
|
1323
|
+
actionParsers?: AgentWidgetActionParser[];
|
|
1324
|
+
actionHandlers?: AgentWidgetActionHandler[];
|
|
1325
|
+
storageAdapter?: AgentWidgetStorageAdapter;
|
|
1326
|
+
/**
|
|
1327
|
+
* Registry of custom components that can be rendered from JSON directives.
|
|
1328
|
+
* Components are registered by name and can be invoked via JSON responses
|
|
1329
|
+
* with the format: `{"component": "ComponentName", "props": {...}}`
|
|
1330
|
+
*
|
|
1331
|
+
* @example
|
|
1332
|
+
* ```typescript
|
|
1333
|
+
* config: {
|
|
1334
|
+
* components: {
|
|
1335
|
+
* ProductCard: (props, context) => {
|
|
1336
|
+
* const card = document.createElement("div");
|
|
1337
|
+
* card.innerHTML = `<h3>${props.title}</h3><p>$${props.price}</p>`;
|
|
1338
|
+
* return card;
|
|
1339
|
+
* }
|
|
1340
|
+
* }
|
|
1341
|
+
* }
|
|
1342
|
+
* ```
|
|
1343
|
+
*/
|
|
1344
|
+
components?: Record<string, AgentWidgetComponentRenderer>;
|
|
1345
|
+
/**
|
|
1346
|
+
* Enable component streaming. When true, component props will be updated
|
|
1347
|
+
* incrementally as they stream in from the JSON response.
|
|
1348
|
+
*
|
|
1349
|
+
* @default true
|
|
1350
|
+
*/
|
|
1351
|
+
enableComponentStreaming?: boolean;
|
|
1352
|
+
/**
|
|
1353
|
+
* Custom stream parser for extracting text from streaming structured responses.
|
|
1354
|
+
* Handles incremental parsing of JSON, XML, or other formats.
|
|
1355
|
+
* If not provided, uses the default JSON parser.
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```typescript
|
|
1359
|
+
* streamParser: () => ({
|
|
1360
|
+
* processChunk: async (content) => {
|
|
1361
|
+
* // Return null if not your format, or extracted text if available
|
|
1362
|
+
* if (!content.trim().startsWith('{')) return null;
|
|
1363
|
+
* return extractText(content);
|
|
1364
|
+
* },
|
|
1365
|
+
* getExtractedText: () => extractedText
|
|
1366
|
+
* })
|
|
1367
|
+
* ```
|
|
1368
|
+
*/
|
|
1369
|
+
streamParser?: () => AgentWidgetStreamParser;
|
|
1370
|
+
/**
|
|
1371
|
+
* Additional localStorage key to clear when the clear chat button is clicked.
|
|
1372
|
+
* The widget automatically clears `"persona-chat-history"` by default.
|
|
1373
|
+
* Use this option to clear additional keys (e.g., if you're using a custom storage key).
|
|
1374
|
+
*
|
|
1375
|
+
* @example
|
|
1376
|
+
* ```typescript
|
|
1377
|
+
* config: {
|
|
1378
|
+
* clearChatHistoryStorageKey: "my-custom-chat-history"
|
|
1379
|
+
* }
|
|
1380
|
+
* ```
|
|
1381
|
+
*/
|
|
1382
|
+
clearChatHistoryStorageKey?: string;
|
|
1383
|
+
/**
|
|
1384
|
+
* Built-in parser type selector. Provides an easy way to choose a parser without importing functions.
|
|
1385
|
+
* If both `parserType` and `streamParser` are provided, `streamParser` takes precedence.
|
|
1386
|
+
*
|
|
1387
|
+
* - `"plain"` - Plain text parser (default). Passes through text as-is.
|
|
1388
|
+
* - `"json"` - JSON parser using partial-json. Extracts `text` field from JSON objects incrementally.
|
|
1389
|
+
* - `"regex-json"` - Regex-based JSON parser. Less robust but faster fallback for simple JSON.
|
|
1390
|
+
* - `"xml"` - XML parser. Extracts text content from XML tags.
|
|
1391
|
+
*
|
|
1392
|
+
* @example
|
|
1393
|
+
* ```typescript
|
|
1394
|
+
* config: {
|
|
1395
|
+
* parserType: "json" // Use built-in JSON parser
|
|
1396
|
+
* }
|
|
1397
|
+
* ```
|
|
1398
|
+
*
|
|
1399
|
+
* @example
|
|
1400
|
+
* ```typescript
|
|
1401
|
+
* config: {
|
|
1402
|
+
* parserType: "json",
|
|
1403
|
+
* streamParser: () => customParser() // Custom parser overrides parserType
|
|
1404
|
+
* }
|
|
1405
|
+
* ```
|
|
1406
|
+
*/
|
|
1407
|
+
parserType?: "plain" | "json" | "regex-json" | "xml";
|
|
1408
|
+
/**
|
|
1409
|
+
* Custom fetch function for full control over API requests.
|
|
1410
|
+
* Use this for custom authentication, request/response transformation, etc.
|
|
1411
|
+
*
|
|
1412
|
+
* When provided, this function is called instead of the default fetch.
|
|
1413
|
+
* You receive the URL, RequestInit, and the payload that would be sent.
|
|
1414
|
+
*
|
|
1415
|
+
* @example
|
|
1416
|
+
* ```typescript
|
|
1417
|
+
* config: {
|
|
1418
|
+
* customFetch: async (url, init, payload) => {
|
|
1419
|
+
* // Transform request for your API format
|
|
1420
|
+
* const myPayload = {
|
|
1421
|
+
* flow: { id: 'my-flow-id' },
|
|
1422
|
+
* messages: payload.messages,
|
|
1423
|
+
* options: { stream_response: true }
|
|
1424
|
+
* };
|
|
1425
|
+
*
|
|
1426
|
+
* // Add auth header
|
|
1427
|
+
* const token = await getAuthToken();
|
|
1428
|
+
*
|
|
1429
|
+
* return fetch('/my-api/dispatch', {
|
|
1430
|
+
* method: 'POST',
|
|
1431
|
+
* headers: {
|
|
1432
|
+
* 'Content-Type': 'application/json',
|
|
1433
|
+
* 'Authorization': `Bearer ${token}`
|
|
1434
|
+
* },
|
|
1435
|
+
* body: JSON.stringify(myPayload),
|
|
1436
|
+
* signal: init.signal
|
|
1437
|
+
* });
|
|
1438
|
+
* }
|
|
1439
|
+
* }
|
|
1440
|
+
* ```
|
|
1441
|
+
*/
|
|
1442
|
+
customFetch?: AgentWidgetCustomFetch;
|
|
1443
|
+
/**
|
|
1444
|
+
* Custom SSE event parser for non-standard streaming response formats.
|
|
1445
|
+
*
|
|
1446
|
+
* Use this when your API returns SSE events in a different format than expected.
|
|
1447
|
+
* Return `{ text }` for text chunks, `{ done: true }` for completion,
|
|
1448
|
+
* `{ error }` for errors, or `null` to ignore the event.
|
|
1449
|
+
*
|
|
1450
|
+
* @example
|
|
1451
|
+
* ```typescript
|
|
1452
|
+
* // For Travrse API format
|
|
1453
|
+
* config: {
|
|
1454
|
+
* parseSSEEvent: (data) => {
|
|
1455
|
+
* if (data.type === 'step_chunk' && data.chunk) {
|
|
1456
|
+
* return { text: data.chunk };
|
|
1457
|
+
* }
|
|
1458
|
+
* if (data.type === 'flow_complete') {
|
|
1459
|
+
* return { done: true };
|
|
1460
|
+
* }
|
|
1461
|
+
* if (data.type === 'step_error') {
|
|
1462
|
+
* return { error: data.error };
|
|
1463
|
+
* }
|
|
1464
|
+
* return null; // Ignore other events
|
|
1465
|
+
* }
|
|
1466
|
+
* }
|
|
1467
|
+
* ```
|
|
1468
|
+
*/
|
|
1469
|
+
parseSSEEvent?: AgentWidgetSSEEventParser;
|
|
1470
|
+
/**
|
|
1471
|
+
* Layout configuration for customizing widget appearance and structure.
|
|
1472
|
+
* Provides control over header, messages, and content slots.
|
|
1473
|
+
*
|
|
1474
|
+
* @example
|
|
1475
|
+
* ```typescript
|
|
1476
|
+
* config: {
|
|
1477
|
+
* layout: {
|
|
1478
|
+
* header: { layout: "minimal" },
|
|
1479
|
+
* messages: { avatar: { show: true } }
|
|
1480
|
+
* }
|
|
1481
|
+
* }
|
|
1482
|
+
* ```
|
|
1483
|
+
*/
|
|
1484
|
+
layout?: AgentWidgetLayoutConfig;
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Markdown rendering configuration.
|
|
1488
|
+
* Customize how markdown is parsed and rendered in chat messages.
|
|
1489
|
+
*
|
|
1490
|
+
* Override methods:
|
|
1491
|
+
* 1. **CSS Variables** - Override `--cw-md-*` variables in your stylesheet
|
|
1492
|
+
* 2. **Options** - Configure marked parser behavior
|
|
1493
|
+
* 3. **Renderers** - Custom rendering functions for specific elements
|
|
1494
|
+
* 4. **postprocessMessage** - Complete control over message transformation
|
|
1495
|
+
*
|
|
1496
|
+
* @example
|
|
1497
|
+
* ```typescript
|
|
1498
|
+
* config: {
|
|
1499
|
+
* markdown: {
|
|
1500
|
+
* options: { breaks: true, gfm: true },
|
|
1501
|
+
* renderer: {
|
|
1502
|
+
* link(token) {
|
|
1503
|
+
* return `<a href="${token.href}" target="_blank">${token.text}</a>`;
|
|
1504
|
+
* }
|
|
1505
|
+
* }
|
|
1506
|
+
* }
|
|
1507
|
+
* }
|
|
1508
|
+
* ```
|
|
1509
|
+
*/
|
|
1510
|
+
markdown?: AgentWidgetMarkdownConfig;
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* Configuration for message action buttons (copy, upvote, downvote).
|
|
1514
|
+
* Shows action buttons on assistant messages for user feedback.
|
|
1515
|
+
*
|
|
1516
|
+
* @example
|
|
1517
|
+
* ```typescript
|
|
1518
|
+
* config: {
|
|
1519
|
+
* messageActions: {
|
|
1520
|
+
* enabled: true,
|
|
1521
|
+
* showCopy: true,
|
|
1522
|
+
* showUpvote: true,
|
|
1523
|
+
* showDownvote: true,
|
|
1524
|
+
* visibility: 'hover',
|
|
1525
|
+
* onFeedback: (feedback) => {
|
|
1526
|
+
* console.log('Feedback:', feedback.type, feedback.messageId);
|
|
1527
|
+
* },
|
|
1528
|
+
* onCopy: (message) => {
|
|
1529
|
+
* console.log('Copied message:', message.id);
|
|
1530
|
+
* }
|
|
1531
|
+
* }
|
|
1532
|
+
* }
|
|
1533
|
+
* ```
|
|
1534
|
+
*/
|
|
1535
|
+
messageActions?: AgentWidgetMessageActionsConfig;
|
|
1536
|
+
|
|
1537
|
+
/**
|
|
1538
|
+
* Configuration for file attachments in the composer.
|
|
1539
|
+
* When enabled, users can attach images to their messages.
|
|
1540
|
+
*
|
|
1541
|
+
* @example
|
|
1542
|
+
* ```typescript
|
|
1543
|
+
* config: {
|
|
1544
|
+
* attachments: {
|
|
1545
|
+
* enabled: true,
|
|
1546
|
+
* maxFileSize: 5 * 1024 * 1024, // 5MB
|
|
1547
|
+
* maxFiles: 4
|
|
1548
|
+
* }
|
|
1549
|
+
* }
|
|
1550
|
+
* ```
|
|
1551
|
+
*/
|
|
1552
|
+
attachments?: AgentWidgetAttachmentsConfig;
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
export type AgentWidgetMessageRole = "user" | "assistant" | "system";
|
|
1556
|
+
|
|
1557
|
+
export type AgentWidgetReasoning = {
|
|
1558
|
+
id: string;
|
|
1559
|
+
status: "pending" | "streaming" | "complete";
|
|
1560
|
+
chunks: string[];
|
|
1561
|
+
startedAt?: number;
|
|
1562
|
+
completedAt?: number;
|
|
1563
|
+
durationMs?: number;
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1566
|
+
export type AgentWidgetToolCall = {
|
|
1567
|
+
id: string;
|
|
1568
|
+
name?: string;
|
|
1569
|
+
status: "pending" | "running" | "complete";
|
|
1570
|
+
args?: unknown;
|
|
1571
|
+
chunks?: string[];
|
|
1572
|
+
result?: unknown;
|
|
1573
|
+
duration?: number;
|
|
1574
|
+
startedAt?: number;
|
|
1575
|
+
completedAt?: number;
|
|
1576
|
+
durationMs?: number;
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
export type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool";
|
|
1580
|
+
|
|
1581
|
+
/**
|
|
1582
|
+
* Represents a message in the chat conversation.
|
|
1583
|
+
*
|
|
1584
|
+
* @property id - Unique message identifier
|
|
1585
|
+
* @property role - Message role: "user", "assistant", or "system"
|
|
1586
|
+
* @property content - Message text content (for display)
|
|
1587
|
+
* @property contentParts - Original multi-modal content parts (for API requests)
|
|
1588
|
+
* @property createdAt - ISO timestamp when message was created
|
|
1589
|
+
* @property streaming - Whether message is still streaming (for assistant messages)
|
|
1590
|
+
* @property variant - Message variant for assistant messages: "assistant", "reasoning", or "tool"
|
|
1591
|
+
* @property sequence - Message ordering number
|
|
1592
|
+
* @property reasoning - Reasoning data for assistant reasoning messages
|
|
1593
|
+
* @property toolCall - Tool call data for assistant tool messages
|
|
1594
|
+
* @property tools - Array of tool calls
|
|
1595
|
+
* @property viaVoice - Set to `true` when a user message is sent via voice recognition.
|
|
1596
|
+
* Useful for implementing voice-specific behaviors like auto-reactivation.
|
|
1597
|
+
*/
|
|
1598
|
+
export type AgentWidgetMessage = {
|
|
1599
|
+
id: string;
|
|
1600
|
+
role: AgentWidgetMessageRole;
|
|
1601
|
+
content: string;
|
|
1602
|
+
createdAt: string;
|
|
1603
|
+
/**
|
|
1604
|
+
* Original multi-modal content parts for this message.
|
|
1605
|
+
* When present, this is sent to the API instead of `content`.
|
|
1606
|
+
* The `content` field contains the text-only representation for display.
|
|
1607
|
+
*/
|
|
1608
|
+
contentParts?: ContentPart[];
|
|
1609
|
+
streaming?: boolean;
|
|
1610
|
+
variant?: AgentWidgetMessageVariant;
|
|
1611
|
+
sequence?: number;
|
|
1612
|
+
reasoning?: AgentWidgetReasoning;
|
|
1613
|
+
toolCall?: AgentWidgetToolCall;
|
|
1614
|
+
tools?: AgentWidgetToolCall[];
|
|
1615
|
+
viaVoice?: boolean;
|
|
1616
|
+
/**
|
|
1617
|
+
* Raw structured payload for this message (e.g., JSON action response).
|
|
1618
|
+
* Populated automatically when structured parsers run.
|
|
1619
|
+
*/
|
|
1620
|
+
rawContent?: string;
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
export type AgentWidgetEvent =
|
|
1624
|
+
| { type: "message"; message: AgentWidgetMessage }
|
|
1625
|
+
| { type: "status"; status: "connecting" | "connected" | "error" | "idle" }
|
|
1626
|
+
| { type: "error"; error: Error };
|
|
1627
|
+
|
|
1628
|
+
export type AgentWidgetInitOptions = {
|
|
1629
|
+
target: string | HTMLElement;
|
|
1630
|
+
config?: AgentWidgetConfig;
|
|
1631
|
+
useShadowDom?: boolean;
|
|
1632
|
+
onReady?: () => void;
|
|
1633
|
+
windowKey?: string; // If provided, stores the controller on window[windowKey] for global access
|
|
1634
|
+
debugTools?: boolean;
|
|
1635
|
+
};
|