@accurix/centrinfo-widget 1.0.0 → 1.0.1
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 +62 -9
- package/dist/cdn/centrinfo-widget.js +2153 -225
- package/dist/cdn/manifest.json +6 -6
- package/dist/config-CCkOySUT.mjs +29 -0
- package/dist/config-CzrfVSPp.cjs +35 -0
- package/dist/index.cjs +2118 -218
- package/dist/index.d.cts +3 -291
- package/dist/index.d.mts +2 -293
- package/dist/index.d.ts +2 -293
- package/dist/index.mjs +2118 -218
- package/dist/runtime.cjs +1 -0
- package/dist/runtime.d.cts +245 -0
- package/dist/runtime.d.mts +245 -0
- package/dist/runtime.mjs +1 -0
- package/dist/types-DQWp12Cg.d.mts +661 -0
- package/dist/types-rfkc-TtX.d.cts +658 -0
- package/package.json +33 -17
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
//#region src/i18n.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Every user-visible chrome string in one place. The widget ships English
|
|
4
|
+
* defaults; a host localises by passing `labels` to `Centrinfo.init()` —
|
|
5
|
+
* any subset is merged over the defaults (see `mergeStrings`). The chat
|
|
6
|
+
* *answers* are already multilingual server-side (the RAG mirrors the
|
|
7
|
+
* visitor's language); this covers the surrounding UI that the backend
|
|
8
|
+
* never produces.
|
|
9
|
+
*/
|
|
10
|
+
interface WidgetStrings {
|
|
11
|
+
openChat: string;
|
|
12
|
+
closeChat: string;
|
|
13
|
+
muteSounds: string;
|
|
14
|
+
unmuteSounds: string;
|
|
15
|
+
/** Header presence line when the org is reachable. */
|
|
16
|
+
statusOnline: string;
|
|
17
|
+
/** Header presence line when bootstrap was loaded with `offline`. */
|
|
18
|
+
statusOffline: string;
|
|
19
|
+
composerPlaceholder: string;
|
|
20
|
+
send: string;
|
|
21
|
+
emoji: string;
|
|
22
|
+
gifs: string;
|
|
23
|
+
attachFile: string;
|
|
24
|
+
recordVoice: string;
|
|
25
|
+
stopRecording: string;
|
|
26
|
+
stop: string;
|
|
27
|
+
copy: string;
|
|
28
|
+
copied: string;
|
|
29
|
+
retry: string;
|
|
30
|
+
clearChat: string;
|
|
31
|
+
clearChatConfirm: string;
|
|
32
|
+
clearChatConfirmBody: string;
|
|
33
|
+
clearConfirmCta: string;
|
|
34
|
+
/** Header "End conversation" button + its confirm dialog + ended-state copy. */
|
|
35
|
+
endChat: string;
|
|
36
|
+
endChatConfirm: string;
|
|
37
|
+
endChatConfirmBody: string;
|
|
38
|
+
endConfirmCta: string;
|
|
39
|
+
conversationEnded: string;
|
|
40
|
+
startNewChat: string;
|
|
41
|
+
/** Past-conversations history. */
|
|
42
|
+
pastConversations: string;
|
|
43
|
+
viewingPast: string;
|
|
44
|
+
backToChat: string;
|
|
45
|
+
historyEnded: string;
|
|
46
|
+
/** Per-message 👍/👎 feedback. */
|
|
47
|
+
feedbackHelpful: string;
|
|
48
|
+
feedbackNotHelpful: string;
|
|
49
|
+
feedbackThanks: string;
|
|
50
|
+
/** End-of-chat CSAT prompt. */
|
|
51
|
+
csatPrompt: string;
|
|
52
|
+
feedbackCommentPlaceholder: string;
|
|
53
|
+
feedbackSend: string;
|
|
54
|
+
cancel: string;
|
|
55
|
+
newMessages: string;
|
|
56
|
+
poweredBy: string;
|
|
57
|
+
searchGifs: string;
|
|
58
|
+
searchingGifs: string;
|
|
59
|
+
noGifs: string;
|
|
60
|
+
assistantTyping: string;
|
|
61
|
+
emptyReply: string;
|
|
62
|
+
errorGeneric: string;
|
|
63
|
+
errorRateLimit: string;
|
|
64
|
+
attaching: string;
|
|
65
|
+
attachTooLarge: string;
|
|
66
|
+
attachFailed: string;
|
|
67
|
+
/** Handoff card (manual follow-up request). */
|
|
68
|
+
handoffTitle: string;
|
|
69
|
+
handoffName: string;
|
|
70
|
+
handoffEmail: string;
|
|
71
|
+
handoffNotify: string;
|
|
72
|
+
sending: string;
|
|
73
|
+
/** Confirmation after a manual submit. `{email}` is replaced with the address (or removed). */
|
|
74
|
+
handoffShared: string;
|
|
75
|
+
/** Generic action-form success fallback + error. */
|
|
76
|
+
formThanks: string;
|
|
77
|
+
formError: string;
|
|
78
|
+
/** Demo-booking picker. */
|
|
79
|
+
bookingPickTime: string;
|
|
80
|
+
bookingDuration: string;
|
|
81
|
+
/** Confirmation after requesting a demo. `{when}` = the chosen slot. */
|
|
82
|
+
bookingRequested: string;
|
|
83
|
+
/** Confirmation when a real calendar event was created. `{when}` = slot. */
|
|
84
|
+
bookingConfirmed: string;
|
|
85
|
+
/** Shown when the chosen slot was just taken by someone else. */
|
|
86
|
+
bookingSlotTaken: string;
|
|
87
|
+
/** Link-mode (Calendly): prompt + CTA + done note + the meeting link label.
|
|
88
|
+
* `{provider}` = the scheduler label (e.g. "Calendly"). */
|
|
89
|
+
bookingViaProvider: string;
|
|
90
|
+
bookingOpenScheduler: string;
|
|
91
|
+
bookingLinkOpened: string;
|
|
92
|
+
bookingMeetingLink: string;
|
|
93
|
+
/** Preview mode (data-preview): canned reply, action note, top banner. */
|
|
94
|
+
previewReply: string;
|
|
95
|
+
previewActionNote: string;
|
|
96
|
+
previewBanner: string;
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/api/types.d.ts
|
|
100
|
+
/** The result metadata that arrives with (or after) an answer. */
|
|
101
|
+
interface TurnResult {
|
|
102
|
+
answer: string;
|
|
103
|
+
sources: Source[];
|
|
104
|
+
suggestedReplies: string[];
|
|
105
|
+
availableActions: string[];
|
|
106
|
+
handoffOffered: boolean;
|
|
107
|
+
/** Contact fields the backend wants inline before handoff, e.g. ["email"]. */
|
|
108
|
+
requestedContactFields?: string[];
|
|
109
|
+
/** True when the backend closed the session (visitor ended it, or 24h idle). */
|
|
110
|
+
conversationEnded?: boolean;
|
|
111
|
+
/** Current live handoff state for the session. */
|
|
112
|
+
liveMode?: 'ai' | 'queued' | 'human';
|
|
113
|
+
/** Human currently assigned to the chat, when liveMode is human. */
|
|
114
|
+
assignedAgentName?: string;
|
|
115
|
+
/** Optional TTS audio for Talkback-enabled assistant replies. */
|
|
116
|
+
audioBase64?: string;
|
|
117
|
+
mimeType?: string;
|
|
118
|
+
visualization?: AnalyticsVisualization;
|
|
119
|
+
}
|
|
120
|
+
interface AnalyticsVisualizationColumn {
|
|
121
|
+
key: string;
|
|
122
|
+
label: string;
|
|
123
|
+
dataType: 'text' | 'number' | 'currency' | 'percent' | 'boolean' | 'date' | 'datetime';
|
|
124
|
+
semanticRole: 'identifier' | 'dimension' | 'measure' | 'date' | 'geography' | 'boolean';
|
|
125
|
+
aggregation?: 'none' | 'sum' | 'avg' | 'count' | 'count_distinct' | 'min' | 'max';
|
|
126
|
+
formatPattern?: string;
|
|
127
|
+
currencyCode?: string;
|
|
128
|
+
description?: string;
|
|
129
|
+
priority?: 'primary' | 'secondary' | 'detail';
|
|
130
|
+
sortable?: boolean;
|
|
131
|
+
filterable?: boolean;
|
|
132
|
+
groupable?: boolean;
|
|
133
|
+
}
|
|
134
|
+
interface AnalyticsVisualizationRecommendation {
|
|
135
|
+
type: 'kpi' | 'table' | 'line' | 'area' | 'bar' | 'stacked_bar' | 'pie' | 'scatter' | 'funnel';
|
|
136
|
+
mode: string;
|
|
137
|
+
categoryField?: string;
|
|
138
|
+
valueFields?: string[];
|
|
139
|
+
seriesField?: string;
|
|
140
|
+
reason?: string;
|
|
141
|
+
confidence?: number;
|
|
142
|
+
}
|
|
143
|
+
interface AnalyticsVisualizationExplanation {
|
|
144
|
+
headline: string;
|
|
145
|
+
summary: string;
|
|
146
|
+
evidence?: string[];
|
|
147
|
+
businessMeaning?: string;
|
|
148
|
+
possibleDrivers?: Array<{
|
|
149
|
+
hypothesis: string;
|
|
150
|
+
howToCheck: string;
|
|
151
|
+
}>;
|
|
152
|
+
recommendations?: Array<{
|
|
153
|
+
action: string;
|
|
154
|
+
why: string;
|
|
155
|
+
successMetric?: string;
|
|
156
|
+
}>;
|
|
157
|
+
forecast?: {
|
|
158
|
+
text: string;
|
|
159
|
+
horizon?: string;
|
|
160
|
+
qualityStatus?: string;
|
|
161
|
+
limitations?: string;
|
|
162
|
+
};
|
|
163
|
+
limitations?: string[];
|
|
164
|
+
followUps?: string[];
|
|
165
|
+
source: 'governed_result' | 'ai_grounded';
|
|
166
|
+
}
|
|
167
|
+
interface AnalyticsVisualization {
|
|
168
|
+
version?: number;
|
|
169
|
+
presentation?: 'kpi' | 'chart' | 'table';
|
|
170
|
+
type: 'kpi' | 'table' | 'bar' | 'line' | 'stacked_bar';
|
|
171
|
+
title?: string;
|
|
172
|
+
label?: string;
|
|
173
|
+
value?: string;
|
|
174
|
+
valueFields?: string[];
|
|
175
|
+
series?: string;
|
|
176
|
+
seriesField?: string;
|
|
177
|
+
columns?: string[];
|
|
178
|
+
rows?: Array<Record<string, unknown>>;
|
|
179
|
+
queryRunId?: string;
|
|
180
|
+
traceId?: string;
|
|
181
|
+
durationMs?: number;
|
|
182
|
+
rowCount?: number;
|
|
183
|
+
truncated?: boolean;
|
|
184
|
+
timezone?: string;
|
|
185
|
+
model?: {
|
|
186
|
+
id?: string;
|
|
187
|
+
name?: string;
|
|
188
|
+
version?: number;
|
|
189
|
+
};
|
|
190
|
+
freshness?: {
|
|
191
|
+
status: 'live' | 'stale' | 'unknown';
|
|
192
|
+
answeredAt?: string;
|
|
193
|
+
};
|
|
194
|
+
reportingPeriod?: {
|
|
195
|
+
label: string;
|
|
196
|
+
start?: string;
|
|
197
|
+
end?: string;
|
|
198
|
+
timezone?: string;
|
|
199
|
+
};
|
|
200
|
+
appliedFilters?: Array<{
|
|
201
|
+
field: string;
|
|
202
|
+
operator: string;
|
|
203
|
+
value: unknown;
|
|
204
|
+
}>;
|
|
205
|
+
columnMetadata?: AnalyticsVisualizationColumn[];
|
|
206
|
+
totals?: Record<string, unknown>;
|
|
207
|
+
currency?: {
|
|
208
|
+
code?: string;
|
|
209
|
+
field?: string;
|
|
210
|
+
source?: 'fixed_metadata' | 'source_field';
|
|
211
|
+
isMixed: boolean;
|
|
212
|
+
};
|
|
213
|
+
chartRecommendation?: AnalyticsVisualizationRecommendation;
|
|
214
|
+
expandable?: boolean;
|
|
215
|
+
tableAvailable?: boolean;
|
|
216
|
+
downloadAvailable?: boolean;
|
|
217
|
+
explanation?: AnalyticsVisualizationExplanation;
|
|
218
|
+
}
|
|
219
|
+
interface SpeechResult {
|
|
220
|
+
providerReady: boolean;
|
|
221
|
+
message?: string;
|
|
222
|
+
audioBase64?: string;
|
|
223
|
+
mimeType?: string;
|
|
224
|
+
}
|
|
225
|
+
interface LiveEvent {
|
|
226
|
+
id: string;
|
|
227
|
+
type: 'chat' | 'handoff_queued' | 'agent_joined' | 'agent_left' | string;
|
|
228
|
+
role?: 'assistant' | 'user' | string;
|
|
229
|
+
content: string;
|
|
230
|
+
authorName?: string;
|
|
231
|
+
createdAt: string;
|
|
232
|
+
}
|
|
233
|
+
interface LiveEventsResult {
|
|
234
|
+
mode: 'ai' | 'queued' | 'human';
|
|
235
|
+
assignedAgentName?: string;
|
|
236
|
+
agentTyping?: boolean;
|
|
237
|
+
agentTypingName?: string;
|
|
238
|
+
conversationEnded?: boolean;
|
|
239
|
+
events: LiveEvent[];
|
|
240
|
+
}
|
|
241
|
+
interface StreamCallbacks {
|
|
242
|
+
/** Called with each incremental text chunk. */
|
|
243
|
+
onChunk: (text: string) => void;
|
|
244
|
+
signal?: AbortSignal;
|
|
245
|
+
/** True only for turns sent from the active Speak-with-AI call. */
|
|
246
|
+
voicePlaybackRequested?: boolean;
|
|
247
|
+
}
|
|
248
|
+
type ActionType = 'contact' | 'inquiry' | 'book-demo' | 'request-callback' | 'subscribe-newsletter';
|
|
249
|
+
interface ActionResult {
|
|
250
|
+
ok: boolean;
|
|
251
|
+
note?: string;
|
|
252
|
+
/** Present on book-a-demo when a connected scheduler fulfilled it live —
|
|
253
|
+
* a real calendar event was created (event mode) or a Calendly link was
|
|
254
|
+
* resolved (link mode). Absent when it fell back to a staff-follow-up request. */
|
|
255
|
+
booking?: DemoBooking;
|
|
256
|
+
}
|
|
257
|
+
/** Outcome of a live book-a-demo (mirrors backend services.PublicDemoBooking). */
|
|
258
|
+
interface DemoBooking {
|
|
259
|
+
mode: 'event' | 'link';
|
|
260
|
+
provider: string;
|
|
261
|
+
confirmed?: boolean;
|
|
262
|
+
eventLink?: string;
|
|
263
|
+
meetingUrl?: string;
|
|
264
|
+
schedulingLink?: string;
|
|
265
|
+
}
|
|
266
|
+
/** A 👍/👎 a visitor left on one assistant reply (POST /public-chat/feedback). */
|
|
267
|
+
interface FeedbackInput {
|
|
268
|
+
sessionId: string;
|
|
269
|
+
/** The widget's local assistant-bubble id — correlates the rating server-side. */
|
|
270
|
+
messageId: string;
|
|
271
|
+
rating: 'up' | 'down';
|
|
272
|
+
/** Optional free text, offered on 👎. */
|
|
273
|
+
comment?: string;
|
|
274
|
+
/** Short context so the owner sees WHAT was rated (truncated server-side). */
|
|
275
|
+
question?: string;
|
|
276
|
+
answer?: string;
|
|
277
|
+
}
|
|
278
|
+
/** A [start, end) window the org's calendar is busy. */
|
|
279
|
+
interface BusyRange {
|
|
280
|
+
start: string;
|
|
281
|
+
end: string;
|
|
282
|
+
}
|
|
283
|
+
/** Booking availability for the picker. */
|
|
284
|
+
interface DemoSlotsResult {
|
|
285
|
+
/** Exact slot instants (UTC ISO) already booked via the widget. */
|
|
286
|
+
taken: string[];
|
|
287
|
+
/** Busy ranges from the connected calendar (Google / Outlook). */
|
|
288
|
+
busy: BusyRange[];
|
|
289
|
+
}
|
|
290
|
+
interface GifResult {
|
|
291
|
+
id: string;
|
|
292
|
+
/** Full GIF URL (what gets sent + rendered). */
|
|
293
|
+
url: string;
|
|
294
|
+
/** Smaller preview URL for the picker grid. */
|
|
295
|
+
preview: string;
|
|
296
|
+
alt: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Transport abstraction so the UI is identical whether it talks to the real
|
|
300
|
+
* backend (`ApiClient`) or the in-memory demo (`MockTransport`).
|
|
301
|
+
*/
|
|
302
|
+
interface Transport {
|
|
303
|
+
bootstrap(): Promise<BootstrapInfo>;
|
|
304
|
+
/** Stream a turn; resolves with final metadata once `done`. */
|
|
305
|
+
stream(question: string, sessionId: string, cb: StreamCallbacks): Promise<TurnResult>;
|
|
306
|
+
/** Poll for staff/system events after a timestamp during live handoff. */
|
|
307
|
+
liveEvents(sessionId: string, after: string): Promise<LiveEventsResult>;
|
|
308
|
+
/** Soft visitor typing hint for the staff console. */
|
|
309
|
+
typing(sessionId: string, isTyping: boolean): Promise<void>;
|
|
310
|
+
action(type: ActionType, payload: Record<string, unknown>): Promise<ActionResult>;
|
|
311
|
+
/** Synthesize short widget UI prompts through the token's configured TTS voice. */
|
|
312
|
+
speak(text: string): Promise<SpeechResult>;
|
|
313
|
+
transcribe(audioBase64: string, mimeType: string, languageHint?: string, durationSeconds?: number): Promise<string>;
|
|
314
|
+
/**
|
|
315
|
+
* Extract text from a visitor-attached image / PDF via the backend's
|
|
316
|
+
* multimodal endpoint (`POST /public-chat/extract`). The returned text is
|
|
317
|
+
* prepended to the visitor's next message so the AI can answer about it.
|
|
318
|
+
* Resolves to '' when extraction is unavailable / fails.
|
|
319
|
+
*/
|
|
320
|
+
extract(fileBase64: string, mimeType: string, filename?: string): Promise<string>;
|
|
321
|
+
/** Search GIFs (Tenor). Returns [] when no key is configured. */
|
|
322
|
+
searchGifs(query: string): Promise<GifResult[]>;
|
|
323
|
+
/**
|
|
324
|
+
* Booking availability within [fromISO, toISO]: `taken` = exact slot instants
|
|
325
|
+
* already booked via the widget; `busy` = ranges the connected calendar
|
|
326
|
+
* (Google / Outlook) is occupied. The picker greys out both. Best-effort —
|
|
327
|
+
* empty when unavailable (the picker then shows everything as open).
|
|
328
|
+
*/
|
|
329
|
+
demoSlots(fromISO: string, toISO: string): Promise<DemoSlotsResult>;
|
|
330
|
+
/**
|
|
331
|
+
* Host-app SSO passthrough. Backend `POST /public-chat/identify`.
|
|
332
|
+
* Best-effort: failures are swallowed; identify never blocks chat
|
|
333
|
+
* (per .claude/PUBLIC_CHAT.md "Identified visitors").
|
|
334
|
+
*/
|
|
335
|
+
identify(sessionId: string, user: WidgetUser): Promise<void>;
|
|
336
|
+
/** End the conversation (`POST /public-chat/end`) — the backend then rejects
|
|
337
|
+
* further turns until the visitor starts a new one. Best-effort. */
|
|
338
|
+
endConversation(sessionId: string): Promise<void>;
|
|
339
|
+
/** Record a 👍/👎 on an assistant reply (`POST /public-chat/feedback`).
|
|
340
|
+
* Best-effort — a failed rating never disrupts the chat. */
|
|
341
|
+
sendFeedback(input: FeedbackInput): Promise<void>;
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/types.d.ts
|
|
345
|
+
/** Public configuration surface passed to `Centrinfo.init()` / <CentrinfoWidget>. */
|
|
346
|
+
interface WidgetConfig {
|
|
347
|
+
/** The org's public chat token (`pub_*`). Required. It IS the org identity. */
|
|
348
|
+
token: string;
|
|
349
|
+
/** Short-lived server-signed context token for governed customer analytics. */
|
|
350
|
+
analyticsContextToken?: string;
|
|
351
|
+
/** Short-lived SDK customer identity JWT for authenticated chat access. */
|
|
352
|
+
identityToken?: string;
|
|
353
|
+
/** Refreshes the customer identity JWT before an authenticated chat turn. */
|
|
354
|
+
getIdentityToken?: () => string | Promise<string>;
|
|
355
|
+
/** API origin. Defaults to the production Centrinfo API. */
|
|
356
|
+
apiBaseUrl?: string;
|
|
357
|
+
/** Brand accent (any CSS color). Overrides the persona/default green. */
|
|
358
|
+
accentColor?: string;
|
|
359
|
+
/** Optional display-name override. Normally loaded from the token bootstrap. */
|
|
360
|
+
agentName?: string;
|
|
361
|
+
/** Optional header avatar URL override. Normally loaded from the token bootstrap. */
|
|
362
|
+
agentAvatarUrl?: string;
|
|
363
|
+
/** Custom launcher icon — an image URL (e.g. the org's logo). Defaults to a chat glyph. */
|
|
364
|
+
launcherIcon?: string;
|
|
365
|
+
/** Tenor API key — enables the GIF picker. Omit to hide the GIF button. */
|
|
366
|
+
gifApiKey?: string;
|
|
367
|
+
/** Force a theme; otherwise follows the host's `prefers-color-scheme`. */
|
|
368
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
369
|
+
/** Open the panel automatically on first load. */
|
|
370
|
+
openByDefault?: boolean;
|
|
371
|
+
/** Play subtle sound effects (open / send / receive). Default true. Visitors can still mute. */
|
|
372
|
+
sound?: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Tappable example questions shown under the greeting until the visitor
|
|
375
|
+
* sends their first message. When omitted, the widget falls back to the
|
|
376
|
+
* `starterQuestions` configured on the token (served by bootstrap).
|
|
377
|
+
*/
|
|
378
|
+
starters?: string[];
|
|
379
|
+
/**
|
|
380
|
+
* Localise the UI chrome. Any subset of `WidgetStrings` is merged over the
|
|
381
|
+
* English defaults — pass e.g. `{ composerPlaceholder: 'Écrivez…' }`. The
|
|
382
|
+
* chat answers themselves are already multilingual server-side.
|
|
383
|
+
*/
|
|
384
|
+
labels?: Partial<WidgetStrings>;
|
|
385
|
+
/**
|
|
386
|
+
* Where the visible transcript is stored across reloads:
|
|
387
|
+
* - `local` (default) — `localStorage`, survives browser restarts (30d TTL).
|
|
388
|
+
* - `session` — `sessionStorage`, cleared when the tab closes (better on
|
|
389
|
+
* shared / kiosk machines so the next visitor can't read prior chats).
|
|
390
|
+
* - `none` — never persisted; the transcript lives only in memory.
|
|
391
|
+
* The backend session id + memory are unaffected — this is purely the
|
|
392
|
+
* locally-rendered history.
|
|
393
|
+
*/
|
|
394
|
+
persistence?: 'local' | 'session' | 'none';
|
|
395
|
+
/**
|
|
396
|
+
* Let visitors attach an image / PDF for the assistant to read (extracted
|
|
397
|
+
* server-side via the multimodal endpoint). Default true; set false to hide
|
|
398
|
+
* the attach button entirely.
|
|
399
|
+
*/
|
|
400
|
+
attachments?: boolean;
|
|
401
|
+
/** Stacking context against the host page. */
|
|
402
|
+
zIndex?: number;
|
|
403
|
+
/** Use the built-in mock transport (local preview, no backend/token needed). */
|
|
404
|
+
demo?: boolean;
|
|
405
|
+
/**
|
|
406
|
+
* Preview mode. Loads the widget's REAL branding (via the bootstrap read)
|
|
407
|
+
* but answers every chat with a canned sample reply instead of calling the
|
|
408
|
+
* AI — so a developer can test the integration anywhere with just the token,
|
|
409
|
+
* at zero AI cost. Remove this flag (or use the normal embed) to go live.
|
|
410
|
+
*/
|
|
411
|
+
preview?: boolean;
|
|
412
|
+
/**
|
|
413
|
+
* Host-app SSO passthrough. When the embedding site has a logged-in
|
|
414
|
+
* user, pass their identity here so the chat session is correlated
|
|
415
|
+
* with them in the org's widget inbox (instead of showing as
|
|
416
|
+
* "Anonymous"). Fully optional — omit for unauthenticated visitors.
|
|
417
|
+
*
|
|
418
|
+
* The widget posts this to `POST /public-chat/identify` once after
|
|
419
|
+
* bootstrap completes. To identify a visitor who logs in MID-SESSION
|
|
420
|
+
* (anonymous chat → sign-in), call `handle.identify(user)` instead.
|
|
421
|
+
* The same `sessionId` survives the identify call, so prior
|
|
422
|
+
* anonymous messages stay attached to the now-known session row.
|
|
423
|
+
*
|
|
424
|
+
* See .claude/PUBLIC_WIDGET_LIBRARY.md "Identified visitors" for
|
|
425
|
+
* what fields to pass + the privacy guidance.
|
|
426
|
+
*/
|
|
427
|
+
user?: WidgetUser;
|
|
428
|
+
/** Which side the launcher + panel dock to. Default 'right'. */
|
|
429
|
+
alignment?: 'left' | 'right';
|
|
430
|
+
/** Horizontal distance (px) from the aligned edge. Default 20. */
|
|
431
|
+
horizontalPadding?: number;
|
|
432
|
+
/** Vertical distance (px) from the bottom. Default 20. */
|
|
433
|
+
verticalPadding?: number;
|
|
434
|
+
/** Hide the built-in launcher button — open the widget via `show()` or a
|
|
435
|
+
* `customLauncherSelector`. Default false. */
|
|
436
|
+
hideDefaultLauncher?: boolean;
|
|
437
|
+
/** CSS selector for host-page element(s) that open the widget on click
|
|
438
|
+
* (your own launcher). Listeners are (re)bound automatically. */
|
|
439
|
+
customLauncherSelector?: string;
|
|
440
|
+
/** Auto-logout (wipe local data) after this many minutes of inactivity.
|
|
441
|
+
* 0 / omitted = never. Use on shared / kiosk devices. */
|
|
442
|
+
sessionDurationMinutes?: number;
|
|
443
|
+
/**
|
|
444
|
+
* How often the open widget refreshes its public token configuration
|
|
445
|
+
* (branding, greeting, starter questions, allowed actions, pause/offline
|
|
446
|
+
* state) from `/public-chat/bootstrap`. Default 30 seconds; set 0 to
|
|
447
|
+
* disable live config refresh for strict traffic budgets.
|
|
448
|
+
*/
|
|
449
|
+
configRefreshSeconds?: number;
|
|
450
|
+
/** A message to proactively show (auto-opens the widget) — e.g.
|
|
451
|
+
* "Questions about pricing? I'm here 👋". Omit to disable. */
|
|
452
|
+
proactiveMessage?: string;
|
|
453
|
+
/** Seconds to wait on the page before showing it. Default 5. */
|
|
454
|
+
proactiveDelaySeconds?: number;
|
|
455
|
+
/** Only fire on pages whose path contains one of these substrings.
|
|
456
|
+
* Omitted/empty = every page. e.g. ['/pricing', '/checkout']. */
|
|
457
|
+
proactiveOnPaths?: string[];
|
|
458
|
+
/** Show a "How was this chat?" CSAT rating when the conversation ends.
|
|
459
|
+
* Default true. */
|
|
460
|
+
csat?: boolean;
|
|
461
|
+
/** Event hooks. */
|
|
462
|
+
onOpen?: () => void;
|
|
463
|
+
onClose?: () => void;
|
|
464
|
+
/** Aliases of onOpen/onClose (Intercom naming). Both fire. */
|
|
465
|
+
onShow?: () => void;
|
|
466
|
+
onHide?: () => void;
|
|
467
|
+
/** Fires whenever the unread-message count changes (drive your own badge). */
|
|
468
|
+
onUnreadChange?: (count: number) => void;
|
|
469
|
+
onMessage?: (msg: {
|
|
470
|
+
role: 'user' | 'assistant';
|
|
471
|
+
content: string;
|
|
472
|
+
}) => void;
|
|
473
|
+
onAction?: (action: string) => void;
|
|
474
|
+
onHandoff?: () => void;
|
|
475
|
+
}
|
|
476
|
+
/** A B2B company / account the visitor belongs to (Intercom "Company object").
|
|
477
|
+
* Folded into the session metadata for the staff inbox. */
|
|
478
|
+
interface WidgetCompany {
|
|
479
|
+
id?: string;
|
|
480
|
+
name?: string;
|
|
481
|
+
plan?: string;
|
|
482
|
+
/** Account creation date — epoch seconds/ms or ISO string. */
|
|
483
|
+
createdAt?: number | string;
|
|
484
|
+
monthlySpend?: number;
|
|
485
|
+
/** Any extra company attributes. */
|
|
486
|
+
[key: string]: string | number | boolean | undefined;
|
|
487
|
+
}
|
|
488
|
+
/** Host-app SSO passthrough payload + data attributes. All fields optional. */
|
|
489
|
+
interface WidgetUser {
|
|
490
|
+
/** Host-app's stable user id (UUID, account number, etc.). Strongly recommended. */
|
|
491
|
+
externalId?: string;
|
|
492
|
+
/** Intercom-style alias for `externalId` (whichever you set is used). */
|
|
493
|
+
userId?: string;
|
|
494
|
+
email?: string;
|
|
495
|
+
firstName?: string;
|
|
496
|
+
lastName?: string;
|
|
497
|
+
/** Single-field name when first/last aren't split host-side. */
|
|
498
|
+
name?: string;
|
|
499
|
+
phone?: string;
|
|
500
|
+
/** Account creation date — epoch seconds/ms or ISO string (a data attribute). */
|
|
501
|
+
createdAt?: number | string;
|
|
502
|
+
/** Avatar image URL (the "Avatar object") — surfaced to staff in the inbox. */
|
|
503
|
+
avatarUrl?: string;
|
|
504
|
+
/** The visitor's company / account (B2B "Company object"). */
|
|
505
|
+
company?: WidgetCompany;
|
|
506
|
+
/**
|
|
507
|
+
* Custom data attributes (plan tier, signup date, segment, …). Merged into
|
|
508
|
+
* the session metadata, same privacy caveat as `metadata` below.
|
|
509
|
+
*/
|
|
510
|
+
customAttributes?: Record<string, string | number | boolean>;
|
|
511
|
+
/**
|
|
512
|
+
* Arbitrary host-app key/values (plan tier, signup date, custom
|
|
513
|
+
* segments). Surfaced as-is in the org's staff inbox. DO NOT pass
|
|
514
|
+
* sensitive data — the widget script runs on the public web and a
|
|
515
|
+
* determined visitor with devtools could inspect it. Safe: plan
|
|
516
|
+
* tier, signup date, segment. Unsafe: card numbers, SSNs, auth
|
|
517
|
+
* tokens, internal admin flags.
|
|
518
|
+
*/
|
|
519
|
+
metadata?: Record<string, string | number | boolean>;
|
|
520
|
+
}
|
|
521
|
+
/** Imperative handle returned by `init()` / `createWidget()`. */
|
|
522
|
+
interface WidgetHandle {
|
|
523
|
+
open: () => void;
|
|
524
|
+
close: () => void;
|
|
525
|
+
toggle: () => void;
|
|
526
|
+
/** Open the panel (alias of `open`, Intercom naming). */
|
|
527
|
+
show: () => void;
|
|
528
|
+
/** Close the panel (alias of `close`, Intercom naming). */
|
|
529
|
+
hide: () => void;
|
|
530
|
+
/** Update the visitor's attributes mid-session (merge). Alias of `identify`. */
|
|
531
|
+
update: (user: WidgetUser) => void;
|
|
532
|
+
/**
|
|
533
|
+
* Identify the visitor mid-session (e.g. after they log in on the
|
|
534
|
+
* host site). The session's prior anonymous messages stay attached
|
|
535
|
+
* — the widget's sessionId is stable across identify. Same merge
|
|
536
|
+
* semantics as boot-time `user`: first-value-wins per field, shallow
|
|
537
|
+
* metadata merge.
|
|
538
|
+
*/
|
|
539
|
+
identify: (user: WidgetUser) => void;
|
|
540
|
+
/** Wipe the locally-rendered transcript + start a fresh backend session. */
|
|
541
|
+
clear: () => void;
|
|
542
|
+
/**
|
|
543
|
+
* Logout: erase ALL of this visitor's locally-stored data (identity,
|
|
544
|
+
* transcripts, conversation history) and reset to a fresh anonymous
|
|
545
|
+
* session. Call on host-app logout / shared devices — à la Intercom
|
|
546
|
+
* `shutdown`. `logout` is an alias.
|
|
547
|
+
*/
|
|
548
|
+
shutdown: () => void;
|
|
549
|
+
logout: () => void;
|
|
550
|
+
destroy: () => void;
|
|
551
|
+
}
|
|
552
|
+
/** A rendered chat message. */
|
|
553
|
+
interface ChatMessage {
|
|
554
|
+
id: string;
|
|
555
|
+
role: 'user' | 'assistant' | 'system';
|
|
556
|
+
content: string;
|
|
557
|
+
/** Human name for live agent replies or system join/leave events. */
|
|
558
|
+
authorName?: string;
|
|
559
|
+
/** Live handoff event type from the backend, e.g. agent_joined. */
|
|
560
|
+
liveEventType?: string;
|
|
561
|
+
/** ISO timestamp for server-originated live events. */
|
|
562
|
+
createdAt?: string;
|
|
563
|
+
/** Inline image (e.g. a GIF the visitor sent). Rendered in the bubble. */
|
|
564
|
+
imageUrl?: string;
|
|
565
|
+
/** Name of a file the visitor attached (rendered as a chip on their bubble). */
|
|
566
|
+
attachmentName?: string;
|
|
567
|
+
sources?: Source[];
|
|
568
|
+
suggestedReplies?: string[];
|
|
569
|
+
availableActions?: string[];
|
|
570
|
+
handoffOffered?: boolean;
|
|
571
|
+
/** Contact fields requested by final API metadata before handoff. */
|
|
572
|
+
requestedContactFields?: string[];
|
|
573
|
+
/** Assistant message awaiting its first token (shows the typing dots). */
|
|
574
|
+
pending?: boolean;
|
|
575
|
+
/** Assistant message actively streaming tokens in (shows the live caret). */
|
|
576
|
+
streaming?: boolean;
|
|
577
|
+
/** Something went wrong producing this turn. */
|
|
578
|
+
error?: boolean;
|
|
579
|
+
/** On an errored turn, the question to re-send when the visitor taps Retry. */
|
|
580
|
+
retryText?: string;
|
|
581
|
+
/** Visitor's 👍/👎 on this assistant reply (persisted so it survives reloads). */
|
|
582
|
+
feedback?: 'up' | 'down';
|
|
583
|
+
visualization?: AnalyticsVisualization;
|
|
584
|
+
}
|
|
585
|
+
interface Source {
|
|
586
|
+
title?: string;
|
|
587
|
+
url?: string;
|
|
588
|
+
}
|
|
589
|
+
interface FeaturedLink {
|
|
590
|
+
label: string;
|
|
591
|
+
url: string;
|
|
592
|
+
}
|
|
593
|
+
/** Visitor identity captured progressively across the chat (persisted locally). */
|
|
594
|
+
interface Visitor {
|
|
595
|
+
name?: string;
|
|
596
|
+
email?: string;
|
|
597
|
+
phone?: string;
|
|
598
|
+
}
|
|
599
|
+
/** Persona + capabilities returned by `GET /public-chat/bootstrap`. */
|
|
600
|
+
interface BootstrapInfo {
|
|
601
|
+
agentName: string;
|
|
602
|
+
agentAvatarUrl?: string;
|
|
603
|
+
greeting: string;
|
|
604
|
+
/** Public module selected on the token: classic chat or assistant card. */
|
|
605
|
+
widgetModule?: 'chat' | 'assistant';
|
|
606
|
+
/** Assistant-card hero media. Video is rendered muted/looping. */
|
|
607
|
+
assistantMediaUrl?: string;
|
|
608
|
+
assistantMediaKind?: 'image' | 'video';
|
|
609
|
+
assistantPrivacyUrl?: string;
|
|
610
|
+
/** Org-token default for widget sounds. Visitors can still mute locally. */
|
|
611
|
+
soundEnabled?: boolean;
|
|
612
|
+
/** TTS output preference. Synthesis is not wired in the SDK yet. */
|
|
613
|
+
voiceOutputEnabled?: boolean;
|
|
614
|
+
voiceProvider?: string;
|
|
615
|
+
voiceId?: string;
|
|
616
|
+
voiceSpeed?: number;
|
|
617
|
+
/** Visitor reply experience: text, spoken voice, or spoken voice with avatar. */
|
|
618
|
+
talkbackMode?: 'text' | 'voice' | 'avatar';
|
|
619
|
+
avatarProvider?: string;
|
|
620
|
+
avatarId?: string;
|
|
621
|
+
allowVoiceInput: boolean;
|
|
622
|
+
/**
|
|
623
|
+
* Token memory controls from the dashboard. Backend memory gates AI context;
|
|
624
|
+
* the SDK mirrors the same switch for locally-rendered transcript history.
|
|
625
|
+
*/
|
|
626
|
+
memoryEnabled: boolean;
|
|
627
|
+
memoryRetentionDays: number;
|
|
628
|
+
memoryMessageCap: number;
|
|
629
|
+
availableActions: string[];
|
|
630
|
+
accentColor?: string;
|
|
631
|
+
/** One-line description under the agent name on the welcome screen (≤500). */
|
|
632
|
+
agentDescription?: string;
|
|
633
|
+
/** Small subtitle under the greeting (≤160). */
|
|
634
|
+
welcomeSubtitle?: string;
|
|
635
|
+
/** Fine-print shown under the composer (≤500). */
|
|
636
|
+
disclaimerText?: string;
|
|
637
|
+
/** Token-configured starter prompts; used when the host didn't pass `starters`. */
|
|
638
|
+
starterQuestions?: string[];
|
|
639
|
+
/** Token-configured manual links shown before the visitor sends a message. */
|
|
640
|
+
featuredLinks?: FeaturedLink[];
|
|
641
|
+
/** True when bootstrap was loaded in the org's offline window. */
|
|
642
|
+
offline?: boolean;
|
|
643
|
+
/** Book-a-demo scheduler status (present only when book-a-demo is enabled).
|
|
644
|
+
* Drives the demo UX: event-mode → in-widget slot picker that creates a real
|
|
645
|
+
* calendar event; link-mode → a "Book on Calendly" link; absent/!connected →
|
|
646
|
+
* slot picker that just files a request for staff to confirm. */
|
|
647
|
+
scheduler?: SchedulerInfo;
|
|
648
|
+
}
|
|
649
|
+
/** Connected book-a-demo scheduler (mirrors backend services.PublicSchedulerInfo). */
|
|
650
|
+
interface SchedulerInfo {
|
|
651
|
+
connected: boolean;
|
|
652
|
+
provider?: string;
|
|
653
|
+
label?: string;
|
|
654
|
+
mode?: 'event' | 'link';
|
|
655
|
+
bookingLink?: string;
|
|
656
|
+
}
|
|
657
|
+
//#endregion
|
|
658
|
+
export { Visitor as a, WidgetUser as c, AnalyticsVisualization as d, DemoSlotsResult as f, WidgetStrings as h, Source as i, ActionResult as l, Transport as m, ChatMessage as n, WidgetConfig as o, GifResult as p, FeaturedLink as r, WidgetHandle as s, BootstrapInfo as t, ActionType as u };
|