@helpai/elements 0.72.1 → 1.1.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 +17 -16
- package/configurator.mjs +1 -1
- package/elements-web-component.esm.js +29 -29
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +29 -29
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +29 -29
- package/elements.esm.js.map +4 -4
- package/elements.js +29 -29
- package/elements.js.map +4 -4
- package/index.d.ts +185 -209
- package/index.mjs +6 -6
- package/package.json +1 -1
- package/schema.d.ts +9 -40
- package/schema.json +11 -85
- package/schema.mjs +1 -1
- package/style.css +1 -1
- package/web-component.d.ts +5 -5
- package/web-component.mjs +6 -6
package/index.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ interface ClientStorage {
|
|
|
32
32
|
*
|
|
33
33
|
* The widget bundles five complete locales (en/fr/ar/es/he — English is also the
|
|
34
34
|
* fallback for any missing key; see {@link BUILTIN_STRINGS}). Further locales, or
|
|
35
|
-
* per-key overrides, are supplied by the page owner (`init({ strings })`)
|
|
36
|
-
* SaaS backend in
|
|
35
|
+
* per-key overrides, are supplied by the page owner (`init({ i18n: { strings } })`)
|
|
36
|
+
* or the SaaS backend in `config.i18n.strings` — both pushed *partially*: only the keys
|
|
37
37
|
* they want to override.
|
|
38
38
|
*
|
|
39
39
|
* To keep render hot-paths cheap, the merged shape is **pre-computed once**
|
|
@@ -41,7 +41,7 @@ interface ClientStorage {
|
|
|
41
41
|
* populated {@link Strings} map. UI components then read `strings.send` as a
|
|
42
42
|
* normal property access — no per-render lookup, no per-render allocation.
|
|
43
43
|
*/
|
|
44
|
-
type StringKey = "launcherOpen" | "launcherLabel" | "panelTitle" | "composerPlaceholder" | "send" | "stop" | "attach" | "micStart" | "micStop" | "micUnsupported" | "expand" | "collapse" | "fullscreen" | "exitFullscreen" | "resizeHandle" | "scrollToBottom" | "close" | "moreActions" | "soundOn" | "soundOff" | "language" | "theme" | "themeAuto" | "themeLight" | "themeDark" | "textSize" | "textSizeSmall" | "textSizeNormal" | "textSizeLarge" | "history" | "historyTitle" | "historyEmpty" | "historyLoading" | "historyBack" | "historyContinue" | "conversationLoading" | "conversationClosed" | "startNewConversation" | "talkToOperator" | "connectingOperator" | "noOperatorAvailable" | "chattingWithOperator" | "cancelOperatorRequest" | "dateToday" | "dateYesterday" | "dateLastWeek" | "dateOlder" | "newConversation" | "dropZone" | "attachmentTooLarge" | "attachmentTooMany" | "attachmentMimeRejected" | "errorRetry" | "errorGeneric" | "errorRateLimited" | "loading" | "thinking" | "thoughts" | "toolResult" | "sources" | "feedbackUp" | "feedbackDown" | "feedbackThanks" | "copy" | "copied" | "collapseSidebar" | "expandSidebar" | "formSubmit" | "formSkip" | "formSubmitted" | "formSkipped" | "formFillOut" | "formRequired" | "formInvalidEmail" | "formInvalidTel" | "formInvalidUrl" | "formInvalidNumber" | "formTooShort" | "formTooLong" | "formNumberTooSmall" | "formNumberTooLarge" | "formPatternMismatch" | "formChooseAtLeast" | "formChooseAtMost" | "formOther" | "formOtherPlaceholder" | "inputRequired" | "inputBadge" | "inputAnswered" | "inputSkipped" | "inputSubmit" | "inputSubmitHint" | "inputSkip" | "showOptions" | "hideOptions" | "qtypeText" | "qtypeEmail" | "qtypePhone" | "qtypeNumber" | "qtypeDate" | "qtypeChooseOne" | "qtypeChooseAny" | "qtypeBoolean" | "confirmYes" | "confirmNo" | "approve" | "reject" | "approvalPrompt" | "approvalBody" | "approvalYourResponse" | "approvalEditHint" | "approvalSubmitting" | "edit" | "toolParameters" | "statusAwaiting" | "statusResponded" | "statusCompleted" | "statusDenied" | "statusError" | "statusRunning" | "statusSuperseded" | "tabHome" | "tabConversations" | "tabHelp" | "tabNews" | "modulesEmpty" | "moduleBack" | "contentLoading" | "homeGreeting" | "homeGreetingNamed" | "homeGreetingLead" | "homeSearchPlaceholder" | "homeContentTitle" | "homeStatus" | "helpTitle" | "helpSearchPlaceholder" | "helpEmpty" | "helpLoading" | "helpSearchEmpty" | "newsTitle" | "newsEmpty" | "newsLoading" | "newsBack" | "newsPublishedAt";
|
|
44
|
+
type StringKey = "launcherOpen" | "launcherLabel" | "panelTitle" | "composerPlaceholder" | "send" | "stop" | "attach" | "micStart" | "micStop" | "micUnsupported" | "expand" | "collapse" | "fullscreen" | "exitFullscreen" | "resizeHandle" | "scrollToBottom" | "close" | "moreActions" | "soundOn" | "soundOff" | "language" | "theme" | "themeAuto" | "themeLight" | "themeDark" | "textSize" | "textSizeSmall" | "textSizeNormal" | "textSizeLarge" | "history" | "historyTitle" | "historyEmpty" | "historyLoading" | "historyBack" | "historyContinue" | "loadMoreConversations" | "conversationLoading" | "loadPreviousMessages" | "conversationClosed" | "startNewConversation" | "talkToOperator" | "connectingOperator" | "noOperatorAvailable" | "chattingWithOperator" | "cancelOperatorRequest" | "dateToday" | "dateYesterday" | "dateLastWeek" | "dateOlder" | "newConversation" | "dropZone" | "attachmentTooLarge" | "attachmentTooMany" | "attachmentMimeRejected" | "errorRetry" | "errorGeneric" | "errorRateLimited" | "loading" | "thinking" | "thoughts" | "toolResult" | "sources" | "feedbackUp" | "feedbackDown" | "feedbackThanks" | "copy" | "copied" | "collapseSidebar" | "expandSidebar" | "formSubmit" | "formSkip" | "formSubmitted" | "formSkipped" | "formFillOut" | "formRequired" | "formInvalidEmail" | "formInvalidTel" | "formInvalidUrl" | "formInvalidNumber" | "formTooShort" | "formTooLong" | "formNumberTooSmall" | "formNumberTooLarge" | "formPatternMismatch" | "formChooseAtLeast" | "formChooseAtMost" | "formOther" | "formOtherPlaceholder" | "inputRequired" | "inputBadge" | "inputAnswered" | "inputSkipped" | "inputSubmit" | "inputSubmitHint" | "inputSkip" | "showOptions" | "hideOptions" | "qtypeText" | "qtypeEmail" | "qtypePhone" | "qtypeNumber" | "qtypeDate" | "qtypeChooseOne" | "qtypeChooseAny" | "qtypeBoolean" | "confirmYes" | "confirmNo" | "approve" | "reject" | "approvalPrompt" | "approvalBody" | "approvalYourResponse" | "approvalEditHint" | "approvalSubmitting" | "edit" | "toolParameters" | "statusAwaiting" | "statusResponded" | "statusCompleted" | "statusDenied" | "statusError" | "statusRunning" | "statusSuperseded" | "tabHome" | "tabConversations" | "tabHelp" | "tabNews" | "modulesEmpty" | "moduleBack" | "contentLoading" | "homeGreeting" | "homeGreetingNamed" | "homeGreetingLead" | "homeSearchPlaceholder" | "homeContentTitle" | "homeStatus" | "helpTitle" | "helpSearchPlaceholder" | "helpEmpty" | "helpLoading" | "helpSearchEmpty" | "newsTitle" | "newsEmpty" | "newsLoading" | "newsBack" | "newsPublishedAt";
|
|
45
45
|
/** A partial map for one locale — what overrides look like on the wire. */
|
|
46
46
|
type LocaleStrings = Partial<Record<StringKey, string>>;
|
|
47
47
|
/**
|
|
@@ -50,8 +50,8 @@ type LocaleStrings = Partial<Record<StringKey, string>>;
|
|
|
50
50
|
*/
|
|
51
51
|
type Strings = Record<StringKey, string>;
|
|
52
52
|
/**
|
|
53
|
-
* Override shape accepted by both `init({ strings })` and the server's
|
|
54
|
-
* `
|
|
53
|
+
* Override shape accepted by both `init({ i18n: { strings } })` and the server's
|
|
54
|
+
* `config.i18n.strings`. Two forms supported:
|
|
55
55
|
*
|
|
56
56
|
* 1. **Flat** — `{ send: "Click", stop: "Halt" }`. Applies to the active
|
|
57
57
|
* locale. Convenient for single-language deployments.
|
|
@@ -66,161 +66,6 @@ type Strings = Record<StringKey, string>;
|
|
|
66
66
|
*/
|
|
67
67
|
type StringsOverride = LocaleStrings | Partial<Record<string, LocaleStrings>>;
|
|
68
68
|
//#endregion
|
|
69
|
-
//#region src/core/persistence.d.ts
|
|
70
|
-
/** Drag-resized panel dimensions. Persisted only when resize is enabled. */
|
|
71
|
-
interface WidgetSize {
|
|
72
|
-
width: number;
|
|
73
|
-
height: number;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* User-changeable preferences. Sent to the backend on every request as a
|
|
77
|
-
* `userPrefs` field so the server can detect drift (e.g. user changed
|
|
78
|
-
* locale on another tab) and reconcile.
|
|
79
|
-
*
|
|
80
|
-
* Every field is optional — an unset key inherits the server / page-owner
|
|
81
|
-
* default. Empty object `{}` means "no preference recorded yet."
|
|
82
|
-
*/
|
|
83
|
-
interface UserPrefs {
|
|
84
|
-
/** BCP-47 tag picked from the language switcher. */
|
|
85
|
-
locale?: string;
|
|
86
|
-
/** Drag-resized panel dimensions. */
|
|
87
|
-
widgetSize?: WidgetSize;
|
|
88
|
-
/** Sound on/off toggle (icon button). */
|
|
89
|
-
soundMuted?: boolean;
|
|
90
|
-
/** Theme picked from the theme switcher. */
|
|
91
|
-
themeMode?: "auto" | "light" | "dark";
|
|
92
|
-
/** Text size picked from the text-size switcher. */
|
|
93
|
-
textSize?: "small" | "normal" | "large";
|
|
94
|
-
}
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region src/stream/types.d.ts
|
|
97
|
-
/** A 👍/👎 reaction on a rateable (assistant/operator) message; `null` clears a prior choice. */
|
|
98
|
-
type FeedbackValue = "up" | "down" | null;
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region src/stream/protocol.d.ts
|
|
101
|
-
/** A tool reference on the wire: `{ code, config }`. `config` is opaque. */
|
|
102
|
-
interface ToolRef {
|
|
103
|
-
code: string;
|
|
104
|
-
config?: Record<string, unknown>;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Who is driving replies in a conversation — the widget mirrors the backend `controlMode`.
|
|
108
|
-
* - `ai-agent`: the AI agent answers (normal operation).
|
|
109
|
-
* - `awaiting_operator`: operator-control requested, the AI no longer answers — the turn routes to the
|
|
110
|
-
* operator — while waiting in the operator queue.
|
|
111
|
-
* - `operator`: a workspace operator took over and is replying.
|
|
112
|
-
*
|
|
113
|
-
* Carried on `HandshakeResponse.controlState`, `LoadConversationResponse.controlState` (resume +
|
|
114
|
-
* history-switch), and the `data-control-state` stream part (on the reply stream). Absent / unknown →
|
|
115
|
-
* treated as `"ai-agent"`.
|
|
116
|
-
*/
|
|
117
|
-
type ControlMode = "ai-agent" | "awaiting_operator" | "operator";
|
|
118
|
-
/**
|
|
119
|
-
* The control-state snapshot the widget reads to render composer/typing/banner state. The optional
|
|
120
|
-
* `operatorAvailable` (set on the operator-request response + the awaiting terminal part) tells the
|
|
121
|
-
* widget whether to show "connecting…" or the async-capture ("leave your details") copy.
|
|
122
|
-
*/
|
|
123
|
-
interface ControlState {
|
|
124
|
-
controlMode: ControlMode;
|
|
125
|
-
/**
|
|
126
|
-
* The operator's 2-letter initials (operator mode only) — shown in the bubble chrome + banner. The
|
|
127
|
-
* visitor never sees the full name (privacy); the backend derives the initials. `assignedOperatorId`
|
|
128
|
-
* also rides the wire but the widget doesn't render it, so it isn't modeled here.
|
|
129
|
-
*/
|
|
130
|
-
assignedOperatorInitials?: string;
|
|
131
|
-
/** Whether anyone was in the operator pool when operator-control was requested (awaiting mode advisory). */
|
|
132
|
-
operatorAvailable?: boolean;
|
|
133
|
-
}
|
|
134
|
-
/** One-shot bot persona shown in the panel header. */
|
|
135
|
-
interface ConversationAgent {
|
|
136
|
-
name: string;
|
|
137
|
-
/** Image URL or data URI. When omitted, initials render from `name`. */
|
|
138
|
-
avatar?: string;
|
|
139
|
-
/** Subtitle ("AI Assistant", "Support team", …). */
|
|
140
|
-
title?: string;
|
|
141
|
-
/** Presence indicator. Default: `'online'`. */
|
|
142
|
-
status?: "online" | "away" | "offline";
|
|
143
|
-
}
|
|
144
|
-
/** A clickable quick-reply chip. */
|
|
145
|
-
interface ConversationSuggestion {
|
|
146
|
-
id: string;
|
|
147
|
-
/** What the chip displays. */
|
|
148
|
-
label: string;
|
|
149
|
-
/** What actually gets sent when clicked. Defaults to `label`. */
|
|
150
|
-
text?: string;
|
|
151
|
-
}
|
|
152
|
-
/** Welcome payload pushed into the message list on first open. */
|
|
153
|
-
interface ConversationWelcome {
|
|
154
|
-
messages?: Array<{
|
|
155
|
-
id: string;
|
|
156
|
-
role: "assistant" | "system";
|
|
157
|
-
text: string;
|
|
158
|
-
}>;
|
|
159
|
-
suggestions?: ConversationSuggestion[];
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Response from `POST /pai/handshake` — the widget's one mount-time
|
|
163
|
-
* round-trip. Deliberately LIGHT: identity + deployment surface only
|
|
164
|
-
* (config, agent persona, welcome, page-mode site/blocks, userPrefs).
|
|
165
|
-
* The conversation THREAD is a separate, lazily-fetched read
|
|
166
|
-
* (`GET /conversation`) that only runs once the widget is activated
|
|
167
|
-
* (opened) — a closed launcher costs the page exactly one request.
|
|
168
|
-
*
|
|
169
|
-
* The `userPrefs` field (when present) is the server's authoritative
|
|
170
|
-
* copy of per-visitor preferences — the client should adopt it and update
|
|
171
|
-
* its local cache. Lets a user picking French on their phone see the
|
|
172
|
-
* widget in French when they open it on their laptop (assuming the same
|
|
173
|
-
* `visitorId`, e.g. via authenticated conversation — out of scope for v1).
|
|
174
|
-
*/
|
|
175
|
-
interface HandshakeResponse$1 {
|
|
176
|
-
/**
|
|
177
|
-
* Public runtime conversation id. The widget mints this UUIDv7 and the backend
|
|
178
|
-
* validates that it belongs to the public deployment + visitor.
|
|
179
|
-
*/
|
|
180
|
-
conversationId: string;
|
|
181
|
-
visitorId?: string;
|
|
182
|
-
/** Bot persona in the panel header (name, avatar, status). */
|
|
183
|
-
agent?: ConversationAgent;
|
|
184
|
-
/** Initial assistant messages + quick-reply chips. */
|
|
185
|
-
welcome?: ConversationWelcome;
|
|
186
|
-
/**
|
|
187
|
-
* Deployment-wide widget configuration the dashboard admin saved
|
|
188
|
-
* (mode / theme / launcher / actions / composer / features / …).
|
|
189
|
-
* Client adopts as defaults; customer's `init({...})` still wins
|
|
190
|
-
* per-field. Same for every visitor of this deployment.
|
|
191
|
-
*/
|
|
192
|
-
config?: ServerConfig$1;
|
|
193
|
-
/** Page-mode site config (logo, title). Backend ships it whenever the deployment renders the page-shell sidebar. */
|
|
194
|
-
site?: Record<string, unknown>;
|
|
195
|
-
/** Page-mode sidebar blocks (navigation, link cards). Backend ships it whenever the deployment renders the page-shell sidebar. */
|
|
196
|
-
blocks?: Record<string, unknown>;
|
|
197
|
-
/** Current control state — seeds the composer/typing/banner state on connect. Absent → `ai-agent`. */
|
|
198
|
-
controlState?: ControlState;
|
|
199
|
-
/**
|
|
200
|
-
* Server's authoritative copy of the visitor's preferences. When present,
|
|
201
|
-
* client adopts it (overrides local cache) and re-applies it to the UI
|
|
202
|
-
* (locale, panel size, sound mute). Absent → client keeps its cache.
|
|
203
|
-
*/
|
|
204
|
-
userPrefs?: UserPrefs;
|
|
205
|
-
/**
|
|
206
|
-
* Optional rebind metadata. When the server returns a `visitorId` /
|
|
207
|
-
* `conversationId` different from what the client sent, this block tells
|
|
208
|
-
* the client WHY — useful for telemetry and the `visitorRebound` /
|
|
209
|
-
* `conversationRebound` events fired into the host page. Server is free to
|
|
210
|
-
* omit it: the client detects rebinding by comparing request vs
|
|
211
|
-
* response ids regardless.
|
|
212
|
-
*
|
|
213
|
-
* Common reasons: `"conflict"` (the id collided with an existing
|
|
214
|
-
* record), `"expired"` (the id is too old to be re-used), `"invalid"`
|
|
215
|
-
* (malformed / not a UUIDv7). Custom strings are passed through to
|
|
216
|
-
* listeners verbatim.
|
|
217
|
-
*/
|
|
218
|
-
rebind?: {
|
|
219
|
-
visitorId?: string;
|
|
220
|
-
conversationId?: string;
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
//#endregion
|
|
224
69
|
//#region src/core/config/types/common.d.ts
|
|
225
70
|
/**
|
|
226
71
|
* Primitive type aliases shared across every config section. Kept in
|
|
@@ -290,6 +135,11 @@ type ActionName = "clear" | "expand" | "fullscreen" | "sound" | "history" | "lan
|
|
|
290
135
|
type ActionList = ActionName[];
|
|
291
136
|
//#endregion
|
|
292
137
|
//#region src/core/config/types/composer.d.ts
|
|
138
|
+
/**
|
|
139
|
+
* Composer chrome and capability flags. `ChatWidgetOptions.composer` owns the
|
|
140
|
+
* send-button skin + attachment limits; `ChatWidgetOptions.features` owns voice,
|
|
141
|
+
* file-upload, HITL, and operator gates.
|
|
142
|
+
*/
|
|
293
143
|
/**
|
|
294
144
|
* How voice input is captured and transcribed.
|
|
295
145
|
*
|
|
@@ -304,12 +154,6 @@ type VoiceMode = "local" | "server" | "disabled";
|
|
|
304
154
|
interface FeatureFlags {
|
|
305
155
|
/** Voice input behaviour (see {@link VoiceMode}). Default: `'local'`. */
|
|
306
156
|
voice?: VoiceMode;
|
|
307
|
-
/**
|
|
308
|
-
* Backend tools the assistant may invoke. Accepts either a bare tool code
|
|
309
|
-
* (`"tool:send-money"`) or a rich ref (`{ code, config }`) — the wire
|
|
310
|
-
* format always uses the rich shape.
|
|
311
|
-
*/
|
|
312
|
-
tools?: Array<string | ToolRef>;
|
|
313
157
|
/**
|
|
314
158
|
* Turn OFF the human-in-the-loop tool UI — the inline ask-questions form and the
|
|
315
159
|
* approve/reject controls for gated tools. Unset/`false` = shown (default); `true`
|
|
@@ -337,7 +181,6 @@ interface ResolvedFeatures {
|
|
|
337
181
|
voice: VoiceMode;
|
|
338
182
|
humanInLoop: boolean;
|
|
339
183
|
operatorRequest: boolean;
|
|
340
|
-
tools?: Array<string | ToolRef>;
|
|
341
184
|
}
|
|
342
185
|
/**
|
|
343
186
|
* Client-side attachment limits. Server enforcement is still required —
|
|
@@ -371,7 +214,7 @@ interface ComposerOptions {
|
|
|
371
214
|
//#endregion
|
|
372
215
|
//#region src/core/config/types/feedback.d.ts
|
|
373
216
|
/**
|
|
374
|
-
* Audible + tactile feedback knobs. Both default to enabled (browser
|
|
217
|
+
* Audible + tactile feedback knobs. Both channels default to enabled (browser
|
|
375
218
|
* autoplay policy still gates audio playback).
|
|
376
219
|
*/
|
|
377
220
|
/** Lifecycle events the feedback bus can react to. */
|
|
@@ -385,7 +228,7 @@ type FeedbackEvent = "messageReceived" | "messageSent" | "error" | "voiceStart"
|
|
|
385
228
|
*/
|
|
386
229
|
type SoundEventValue = boolean | string;
|
|
387
230
|
interface SoundOptions {
|
|
388
|
-
/** Master on/off. Default: `
|
|
231
|
+
/** Master on/off. Default: `true` (browser autoplay policy still applies). */
|
|
389
232
|
enabled?: boolean;
|
|
390
233
|
/** Global volume 0..1. Default: `0.3` (subtle). */
|
|
391
234
|
volume?: number;
|
|
@@ -410,7 +253,7 @@ interface HapticsOptions {
|
|
|
410
253
|
events?: Partial<Record<FeedbackEvent, HapticEventValue>>;
|
|
411
254
|
}
|
|
412
255
|
/**
|
|
413
|
-
* Section: audible + tactile feedback. Both default to enabled
|
|
256
|
+
* Section: audible + tactile feedback. Both channels default to enabled
|
|
414
257
|
* (browser autoplay policy still gates audio playback).
|
|
415
258
|
*/
|
|
416
259
|
interface FeedbackOptions {
|
|
@@ -1006,9 +849,11 @@ interface Endpoints {
|
|
|
1006
849
|
* use the widget: events, pages, devices, locales, funnels.
|
|
1007
850
|
*
|
|
1008
851
|
* Privacy contract (enforced in `src/core/tracking.ts`):
|
|
1009
|
-
* - never sends message text
|
|
852
|
+
* - never sends message text or form values —
|
|
1010
853
|
* event payloads pass through a static per-event allowlist;
|
|
1011
|
-
* - the only identifier is the widget's existing anonymous
|
|
854
|
+
* - the only visitor identifier is the widget's existing anonymous
|
|
855
|
+
* `visitorId`; deployment and anonymous conversation ids provide context;
|
|
856
|
+
* - page metadata is origin + pathname, with query/hash removed;
|
|
1012
857
|
* - geo + browser are derived server-side (IP + User-Agent header),
|
|
1013
858
|
* never collected client-side;
|
|
1014
859
|
* - `navigator.globalPrivacyControl` / Do-Not-Track force it off
|
|
@@ -1028,8 +873,9 @@ interface TrackingOptions {
|
|
|
1028
873
|
*/
|
|
1029
874
|
endpoint?: string;
|
|
1030
875
|
/**
|
|
1031
|
-
* Per-
|
|
1032
|
-
*
|
|
876
|
+
* Per-widget-runtime sampling 0..1. `0.25` samples roughly a quarter of
|
|
877
|
+
* mounted runtimes; one decision is reused for that runtime's funnel.
|
|
878
|
+
* Default `1`.
|
|
1033
879
|
*/
|
|
1034
880
|
sampleRate?: number;
|
|
1035
881
|
/**
|
|
@@ -1061,7 +907,8 @@ interface ResolvedTracking {
|
|
|
1061
907
|
* Issued by the SaaS portal, pasted into their site code.
|
|
1062
908
|
* - **Widget settings (L3)** — nested sections owned by the portal
|
|
1063
909
|
* admin: `presentation`, `behavior`, `theme`, `launcher`, `header`,
|
|
1064
|
-
* `composer`, `
|
|
910
|
+
* `composer`, `feedback`, `i18n`, `footer`, `features`, and the other
|
|
911
|
+
* schema-backed sections below.
|
|
1065
912
|
*
|
|
1066
913
|
* Runtime-only fields (`target`, `storage`, `onMessage` callbacks) live
|
|
1067
914
|
* alongside at the top level — they're function / DOM types that can't be
|
|
@@ -1129,7 +976,7 @@ interface ChatWidgetOptions {
|
|
|
1129
976
|
feedback?: FeedbackOptions;
|
|
1130
977
|
i18n?: I18nOptions;
|
|
1131
978
|
footer?: FooterOptions;
|
|
1132
|
-
/** Capability flags (file upload, voice mode,
|
|
979
|
+
/** Capability flags (file upload, voice mode, HITL, operator request). Server-pushable. */
|
|
1133
980
|
features?: FeatureFlags;
|
|
1134
981
|
/** Event-driven forms (signal capture, CSAT, intake, consent…). Server-pushable. */
|
|
1135
982
|
forms?: FormsOptions;
|
|
@@ -1256,7 +1103,7 @@ interface ResolvedOptions {
|
|
|
1256
1103
|
onError?: ChatWidgetOptions["onError"];
|
|
1257
1104
|
}
|
|
1258
1105
|
/**
|
|
1259
|
-
* Shape of the server-pushed `
|
|
1106
|
+
* Shape of the server-pushed `config` object in `HandshakeResponse`.
|
|
1260
1107
|
*
|
|
1261
1108
|
* Matches a subset of {@link ChatWidgetOptions} — anything the server can
|
|
1262
1109
|
* reasonably dictate (UI, behaviour, routing). Callbacks (`onMessage` etc.)
|
|
@@ -1326,6 +1173,158 @@ interface LogEntry {
|
|
|
1326
1173
|
payload?: unknown;
|
|
1327
1174
|
}
|
|
1328
1175
|
//#endregion
|
|
1176
|
+
//#region src/core/persistence.d.ts
|
|
1177
|
+
/** Drag-resized panel dimensions. Persisted only when resize is enabled. */
|
|
1178
|
+
interface WidgetSize {
|
|
1179
|
+
width: number;
|
|
1180
|
+
height: number;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* User-changeable preferences. Sent to the backend on every request as a
|
|
1184
|
+
* `userPrefs` field so the server can detect drift (e.g. user changed
|
|
1185
|
+
* locale on another tab) and reconcile.
|
|
1186
|
+
*
|
|
1187
|
+
* Every field is optional — an unset key inherits the server / page-owner
|
|
1188
|
+
* default. Empty object `{}` means "no preference recorded yet."
|
|
1189
|
+
*/
|
|
1190
|
+
interface UserPrefs {
|
|
1191
|
+
/** BCP-47 tag picked from the language switcher. */
|
|
1192
|
+
locale?: string;
|
|
1193
|
+
/** Drag-resized panel dimensions. */
|
|
1194
|
+
widgetSize?: WidgetSize;
|
|
1195
|
+
/** Sound on/off toggle (icon button). */
|
|
1196
|
+
soundMuted?: boolean;
|
|
1197
|
+
/** Theme picked from the theme switcher. */
|
|
1198
|
+
themeMode?: "auto" | "light" | "dark";
|
|
1199
|
+
/** Text size picked from the text-size switcher. */
|
|
1200
|
+
textSize?: "small" | "normal" | "large";
|
|
1201
|
+
}
|
|
1202
|
+
//#endregion
|
|
1203
|
+
//#region src/stream/types.d.ts
|
|
1204
|
+
/** A 👍/👎 reaction on a rateable (assistant/operator) message; `null` clears a prior choice. */
|
|
1205
|
+
type FeedbackValue = "up" | "down" | null;
|
|
1206
|
+
//#endregion
|
|
1207
|
+
//#region src/stream/protocol.d.ts
|
|
1208
|
+
/**
|
|
1209
|
+
* Who is driving replies in a conversation — the widget mirrors the backend `controlMode`.
|
|
1210
|
+
* - `ai-agent`: the AI agent answers (normal operation).
|
|
1211
|
+
* - `awaiting_operator`: operator-control requested, the AI no longer answers — the turn routes to the
|
|
1212
|
+
* operator — while waiting in the operator queue.
|
|
1213
|
+
* - `operator`: a workspace operator took over and is replying.
|
|
1214
|
+
*
|
|
1215
|
+
* Carried on `HandshakeResponse.controlState`, `LoadConversationResponse.controlState` (resume +
|
|
1216
|
+
* history-switch), and the `data-control-state` stream part (on the reply stream). Absent / unknown →
|
|
1217
|
+
* treated as `"ai-agent"`.
|
|
1218
|
+
*/
|
|
1219
|
+
type ControlMode = "ai-agent" | "awaiting_operator" | "operator";
|
|
1220
|
+
/**
|
|
1221
|
+
* The control-state snapshot the widget reads to render composer/typing/banner state. The optional
|
|
1222
|
+
* `operatorAvailable` (set on the operator-request response + the awaiting terminal part) tells the
|
|
1223
|
+
* widget whether to show "connecting…" or the async-capture ("leave your details") copy.
|
|
1224
|
+
*/
|
|
1225
|
+
interface ControlState {
|
|
1226
|
+
controlMode: ControlMode;
|
|
1227
|
+
/** Monotonic state version: orders received snapshots and fences request/cancel retries to their observed cycle. */
|
|
1228
|
+
controlRevision?: number;
|
|
1229
|
+
/**
|
|
1230
|
+
* The operator's 2-letter initials (operator mode only) — shown in the bubble chrome + banner. The
|
|
1231
|
+
* visitor never sees the full name (privacy); the backend derives the initials. `assignedOperatorId`
|
|
1232
|
+
* also rides the wire but the widget doesn't render it, so it isn't modeled here.
|
|
1233
|
+
*/
|
|
1234
|
+
assignedOperatorInitials?: string;
|
|
1235
|
+
/** Whether anyone was in the operator pool when operator-control was requested (awaiting mode advisory). */
|
|
1236
|
+
operatorAvailable?: boolean;
|
|
1237
|
+
}
|
|
1238
|
+
/** One-shot bot persona shown in the panel header. */
|
|
1239
|
+
interface ConversationAgent {
|
|
1240
|
+
name: string;
|
|
1241
|
+
/** Image URL or data URI. When omitted, initials render from `name`. */
|
|
1242
|
+
avatar?: string;
|
|
1243
|
+
/** Subtitle ("AI Assistant", "Support team", …). */
|
|
1244
|
+
title?: string;
|
|
1245
|
+
/** Presence indicator. Default: `'online'`. */
|
|
1246
|
+
status?: "online" | "away" | "offline";
|
|
1247
|
+
}
|
|
1248
|
+
/** A clickable quick-reply chip. */
|
|
1249
|
+
interface ConversationSuggestion {
|
|
1250
|
+
id: string;
|
|
1251
|
+
/** What the chip displays. */
|
|
1252
|
+
label: string;
|
|
1253
|
+
/** What actually gets sent when clicked. Defaults to `label`. */
|
|
1254
|
+
text?: string;
|
|
1255
|
+
}
|
|
1256
|
+
/** Welcome payload pushed into the message list on first open. */
|
|
1257
|
+
interface ConversationWelcome {
|
|
1258
|
+
messages?: Array<{
|
|
1259
|
+
id: string;
|
|
1260
|
+
role: "assistant" | "system";
|
|
1261
|
+
text: string;
|
|
1262
|
+
}>;
|
|
1263
|
+
suggestions?: ConversationSuggestion[];
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Response from `POST /pai/handshake` — the widget's one mount-time
|
|
1267
|
+
* round-trip. Deliberately LIGHT: identity + deployment surface only
|
|
1268
|
+
* (config, agent persona, welcome, page-mode site/blocks, userPrefs).
|
|
1269
|
+
* The conversation THREAD is a separate, lazily-fetched read
|
|
1270
|
+
* (`GET /conversation`) that only runs once the widget is activated
|
|
1271
|
+
* (opened) — a closed launcher costs the page exactly one request.
|
|
1272
|
+
*
|
|
1273
|
+
* The `userPrefs` field (when present) is the server's authoritative
|
|
1274
|
+
* copy of per-visitor preferences — the client should adopt it and update
|
|
1275
|
+
* its local cache. Lets a user picking French on their phone see the
|
|
1276
|
+
* widget in French when they open it on their laptop (assuming the same
|
|
1277
|
+
* `visitorId`, e.g. via authenticated conversation — out of scope for v1).
|
|
1278
|
+
*/
|
|
1279
|
+
interface HandshakeResponse$1 {
|
|
1280
|
+
/**
|
|
1281
|
+
* Public runtime conversation id. The widget mints this UUIDv7 and the backend
|
|
1282
|
+
* validates that it belongs to the public deployment + visitor.
|
|
1283
|
+
*/
|
|
1284
|
+
conversationId: string;
|
|
1285
|
+
visitorId?: string;
|
|
1286
|
+
/** Bot persona in the panel header (name, avatar, status). */
|
|
1287
|
+
agent?: ConversationAgent;
|
|
1288
|
+
/** Initial assistant messages + quick-reply chips. */
|
|
1289
|
+
welcome?: ConversationWelcome;
|
|
1290
|
+
/**
|
|
1291
|
+
* Deployment-wide widget configuration the dashboard admin saved
|
|
1292
|
+
* (mode / theme / launcher / actions / composer / features / …).
|
|
1293
|
+
* Client adopts as defaults; customer's `init({...})` still wins
|
|
1294
|
+
* per-field. Same for every visitor of this deployment.
|
|
1295
|
+
*/
|
|
1296
|
+
config?: ServerConfig$1;
|
|
1297
|
+
/** Page-mode site config (logo, title). Backend ships it whenever the deployment renders the page-shell sidebar. */
|
|
1298
|
+
site?: Record<string, unknown>;
|
|
1299
|
+
/** Page-mode sidebar blocks (navigation, link cards). Backend ships it whenever the deployment renders the page-shell sidebar. */
|
|
1300
|
+
blocks?: Record<string, unknown>;
|
|
1301
|
+
/** Current control state — seeds the composer/typing/banner state on connect. Absent → `ai-agent`. */
|
|
1302
|
+
controlState?: ControlState;
|
|
1303
|
+
/**
|
|
1304
|
+
* Server's authoritative copy of the visitor's preferences. When present,
|
|
1305
|
+
* client adopts it (overrides local cache) and re-applies it to the UI
|
|
1306
|
+
* (locale, panel size, sound mute). Absent → client keeps its cache.
|
|
1307
|
+
*/
|
|
1308
|
+
userPrefs?: UserPrefs;
|
|
1309
|
+
/**
|
|
1310
|
+
* Optional rebind metadata. When the server returns a `visitorId` /
|
|
1311
|
+
* `conversationId` different from what the client sent, this block tells
|
|
1312
|
+
* the client WHY — useful for telemetry and the `visitorRebound` /
|
|
1313
|
+
* `conversationRebound` events fired into the host page. Server is free to
|
|
1314
|
+
* omit it: the client detects rebinding by comparing request vs
|
|
1315
|
+
* response ids regardless.
|
|
1316
|
+
*
|
|
1317
|
+
* Common reasons: `"conflict"` (the id collided with an existing
|
|
1318
|
+
* record), `"expired"` (the id is too old to be re-used), `"invalid"`
|
|
1319
|
+
* (malformed / not a UUIDv7). Custom strings are passed through to
|
|
1320
|
+
* listeners verbatim.
|
|
1321
|
+
*/
|
|
1322
|
+
rebind?: {
|
|
1323
|
+
visitorId?: string;
|
|
1324
|
+
conversationId?: string;
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
//#endregion
|
|
1329
1328
|
//#region src/core/events.d.ts
|
|
1330
1329
|
/**
|
|
1331
1330
|
* Payload shape per event. Keyed by event name; use `void` for events that
|
|
@@ -1779,10 +1778,6 @@ declare const widgetSettingsSchema: z.ZodObject<{
|
|
|
1779
1778
|
server: "server";
|
|
1780
1779
|
disabled: "disabled";
|
|
1781
1780
|
}>>;
|
|
1782
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
1783
|
-
code: z.ZodString;
|
|
1784
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1785
|
-
}, z.core.$loose>]>>>;
|
|
1786
1781
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
1787
1782
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
1788
1783
|
}, z.core.$loose>>;
|
|
@@ -1899,10 +1894,10 @@ declare const widgetSettingsSchema: z.ZodObject<{
|
|
|
1899
1894
|
}, z.core.$loose>;
|
|
1900
1895
|
type WidgetSettings = z.infer<typeof widgetSettingsSchema>;
|
|
1901
1896
|
/**
|
|
1902
|
-
* Full
|
|
1903
|
-
* extras. The dashboard / dev configurator typically only
|
|
1904
|
-
*
|
|
1905
|
-
* surface, `connectionConfigSchema` for
|
|
1897
|
+
* Full tooling schema — connection + widget settings + page-mode
|
|
1898
|
+
* handshake extras. The dashboard / dev configurator typically only
|
|
1899
|
+
* edits one part at a time (`widgetSettingsSchema` for the dashboard
|
|
1900
|
+
* surface, `connectionConfigSchema` for developer-facing fields).
|
|
1906
1901
|
*/
|
|
1907
1902
|
declare const widgetConfigSchema: z.ZodObject<{
|
|
1908
1903
|
widgetId: z.ZodDefault<z.ZodString>;
|
|
@@ -2118,10 +2113,6 @@ declare const widgetConfigSchema: z.ZodObject<{
|
|
|
2118
2113
|
server: "server";
|
|
2119
2114
|
disabled: "disabled";
|
|
2120
2115
|
}>>;
|
|
2121
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
2122
|
-
code: z.ZodString;
|
|
2123
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
2124
|
-
}, z.core.$loose>]>>>;
|
|
2125
2116
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
2126
2117
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
2127
2118
|
}, z.core.$loose>>;
|
|
@@ -2456,10 +2447,6 @@ declare const widgetConfigPartialSchema: z.ZodObject<{
|
|
|
2456
2447
|
server: "server";
|
|
2457
2448
|
disabled: "disabled";
|
|
2458
2449
|
}>>;
|
|
2459
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
2460
|
-
code: z.ZodString;
|
|
2461
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
2462
|
-
}, z.core.$loose>]>>>;
|
|
2463
2450
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
2464
2451
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
2465
2452
|
}, z.core.$loose>>>;
|
|
@@ -2754,10 +2741,6 @@ declare const widgetSettingsPartialSchema: z.ZodObject<{
|
|
|
2754
2741
|
server: "server";
|
|
2755
2742
|
disabled: "disabled";
|
|
2756
2743
|
}>>;
|
|
2757
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
2758
|
-
code: z.ZodString;
|
|
2759
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
2760
|
-
}, z.core.$loose>]>>>;
|
|
2761
2744
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
2762
2745
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
2763
2746
|
}, z.core.$loose>>>;
|
|
@@ -2914,9 +2897,10 @@ type ConnectionConfigPartial = z.infer<typeof connectionConfigPartialSchema>;
|
|
|
2914
2897
|
/**
|
|
2915
2898
|
* Server-pushable widget settings. Same surface as the editable
|
|
2916
2899
|
* {@link widgetSettingsSchema} but every field is optional (the server
|
|
2917
|
-
* pushes patches, not full configs).
|
|
2918
|
-
*
|
|
2919
|
-
*
|
|
2900
|
+
* pushes patches, not full configs). Embed identity, host context,
|
|
2901
|
+
* the agent endpoint, storage, and callbacks are deliberately excluded
|
|
2902
|
+
* because they are client concerns. `presentation.iframe` remains a
|
|
2903
|
+
* server-pushable widget setting.
|
|
2920
2904
|
*
|
|
2921
2905
|
* Two deltas vs the editable surface:
|
|
2922
2906
|
* - `forms` is omitted — resolved form definitions are served by the
|
|
@@ -3109,10 +3093,6 @@ declare const serverConfigSchema: z.ZodObject<{
|
|
|
3109
3093
|
server: "server";
|
|
3110
3094
|
disabled: "disabled";
|
|
3111
3095
|
}>>;
|
|
3112
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
3113
|
-
code: z.ZodString;
|
|
3114
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
3115
|
-
}, z.core.$loose>]>>>;
|
|
3116
3096
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
3117
3097
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
3118
3098
|
}, z.core.$loose>>>;
|
|
@@ -3399,10 +3379,6 @@ declare const handshakeResponseSchema: z.ZodObject<{
|
|
|
3399
3379
|
server: "server";
|
|
3400
3380
|
disabled: "disabled";
|
|
3401
3381
|
}>>;
|
|
3402
|
-
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
3403
|
-
code: z.ZodString;
|
|
3404
|
-
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
3405
|
-
}, z.core.$loose>]>>>;
|
|
3406
3382
|
disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
|
|
3407
3383
|
enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
|
|
3408
3384
|
}, z.core.$loose>>>;
|
|
@@ -3593,7 +3569,7 @@ interface ChatWidgetInstance {
|
|
|
3593
3569
|
*
|
|
3594
3570
|
* @example Single widget (default):
|
|
3595
3571
|
* ```ts
|
|
3596
|
-
* mount({ publicKey, mode: 'inline', target: document.getElementById('chat') });
|
|
3572
|
+
* mount({ publicKey, presentation: { mode: 'inline' }, target: document.getElementById('chat') });
|
|
3597
3573
|
* ```
|
|
3598
3574
|
* @example Two widgets on one page:
|
|
3599
3575
|
* ```ts
|