@helpai/elements 0.62.1 → 0.63.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/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, H as HandshakeResponse, L as Link, S as ServerConfig, b as SiteConfig, W as WidgetConfig, c as WidgetConfigPartial, d as WidgetSettings, e as WidgetSettingsPartial } from './deployment-i9cta98X.js';
2
- import 'zod';
3
-
1
+ import { z } from "zod";
2
+ //#region src/core/storage.d.ts
4
3
  /**
5
4
  * Pluggable client-side key-value storage.
6
5
  *
@@ -19,14 +18,15 @@ import 'zod';
19
18
  * serialises typed values to JSON before calling `set`.
20
19
  */
21
20
  interface ClientStorage {
22
- /** Returns the stored string for `key`, or `null` when absent / unreadable. */
23
- get(key: string): string | null;
24
- /** Stores `value` under `key`. Best-effort — silent on quota / disabled storage. */
25
- set(key: string, value: string): void;
26
- /** Removes `key`. No-op if absent. */
27
- remove(key: string): void;
21
+ /** Returns the stored string for `key`, or `null` when absent / unreadable. */
22
+ get(key: string): string | null;
23
+ /** Stores `value` under `key`. Best-effort — silent on quota / disabled storage. */
24
+ set(key: string, value: string): void;
25
+ /** Removes `key`. No-op if absent. */
26
+ remove(key: string): void;
28
27
  }
29
-
28
+ //#endregion
29
+ //#region src/i18n/strings.d.ts
30
30
  /**
31
31
  * UI strings — built-in defaults, type contracts, and runtime resolution.
32
32
  *
@@ -40,7 +40,7 @@ interface ClientStorage {
40
40
  * populated {@link Strings} map. UI components then read `strings.send` as a
41
41
  * normal property access — no per-render lookup, no per-render allocation.
42
42
  */
43
- 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" | "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";
43
+ 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" | "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
44
  /** A partial map for one locale — what overrides look like on the wire. */
45
45
  type LocaleStrings = Partial<Record<StringKey, string>>;
46
46
  /**
@@ -64,44 +64,12 @@ type Strings = Record<StringKey, string>;
64
64
  * top-level value is an object, the whole override is treated as nested.
65
65
  */
66
66
  type StringsOverride = LocaleStrings | Partial<Record<string, LocaleStrings>>;
67
-
68
- /**
69
- * Per-widget client-side state.
70
- *
71
- * Storage holds three things, each under its own key:
72
- *
73
- * 1. **`visitorId`** — anonymous browser-level identifier, minted once and
74
- * reused forever. **Brand-global** (NOT scoped to widget/deployment): one
75
- * anonymous "who is this browser" id, shared across every widget + deployment
76
- * of this brand. Sent on every backend request.
77
- * 2. **`conversationId`** — the active conversation thread. The backend is the
78
- * source of truth for messages; we store only the id and re-fetch on
79
- * reload via `transport.loadConversation()`.
80
- * 3. **`userPrefs`** — user preferences (locale, panel size from drag,
81
- * sound mute). Cached locally for instant render-before-network, then
82
- * reconciled with the server's copy on each `connect()`.
83
- *
84
- * Everything EXCEPT `visitorId` is namespaced as
85
- * `${brand.cssPrefix}.${widgetId}.${aiAgentDeploymentId}.${field}` (the deployment id
86
- * is dropped when absent) so two widgets — or two AI agent deployments — keep
87
- * their state cleanly separated; pointing a widget at a different
88
- * `aiAgentDeploymentId` starts from fresh conversation / prefs / panel state.
89
- * `visitorId` is the deliberate exception: it stays global so the same browser
90
- * is one anonymous visitor everywhere (`${brand.cssPrefix}.visitorId`).
91
- *
92
- * A `storageVersion` (when set) folds a `.v<version>` segment into EVERY key —
93
- * including the global `visitorId` — so bumping it force-resets the entire
94
- * client-side namespace for all users (a full fresh start: new visitor id,
95
- * conversation, prefs, panel state). Unset → the unversioned keys.
96
- *
97
- * Storage is pluggable via {@link ClientStorage} — pass a custom adapter
98
- * to add encryption, logging, or use a non-localStorage backend.
99
- */
100
-
67
+ //#endregion
68
+ //#region src/core/persistence.d.ts
101
69
  /** Drag-resized panel dimensions. Persisted only when resize is enabled. */
102
70
  interface WidgetSize {
103
- width: number;
104
- height: number;
71
+ width: number;
72
+ height: number;
105
73
  }
106
74
  /**
107
75
  * User-changeable preferences. Sent to the backend on every request as a
@@ -112,52 +80,81 @@ interface WidgetSize {
112
80
  * default. Empty object `{}` means "no preference recorded yet."
113
81
  */
114
82
  interface UserPrefs {
115
- /** BCP-47 tag picked from the language switcher. */
116
- locale?: string;
117
- /** Drag-resized panel dimensions. */
118
- widgetSize?: WidgetSize;
119
- /** Sound on/off toggle (icon button). */
120
- soundMuted?: boolean;
121
- /** Theme picked from the theme switcher. */
122
- themeMode?: "auto" | "light" | "dark";
123
- /** Text size picked from the text-size switcher. */
124
- textSize?: "small" | "normal" | "large";
83
+ /** BCP-47 tag picked from the language switcher. */
84
+ locale?: string;
85
+ /** Drag-resized panel dimensions. */
86
+ widgetSize?: WidgetSize;
87
+ /** Sound on/off toggle (icon button). */
88
+ soundMuted?: boolean;
89
+ /** Theme picked from the theme switcher. */
90
+ themeMode?: "auto" | "light" | "dark";
91
+ /** Text size picked from the text-size switcher. */
92
+ textSize?: "small" | "normal" | "large";
125
93
  }
126
-
127
- /** A 👍/👎 reaction on an assistant message; `null` clears a prior choice. */
94
+ //#endregion
95
+ //#region src/stream/types.d.ts
96
+ /** A 👍/👎 reaction on a rateable (assistant/operator) message; `null` clears a prior choice. */
128
97
  type FeedbackValue = "up" | "down" | null;
129
-
98
+ //#endregion
99
+ //#region src/stream/protocol.d.ts
130
100
  /** A tool reference on the wire: `{ code, config }`. `config` is opaque. */
131
101
  interface ToolRef {
132
- code: string;
133
- config?: Record<string, unknown>;
102
+ code: string;
103
+ config?: Record<string, unknown>;
104
+ }
105
+ /**
106
+ * Who is driving replies in a conversation — the widget mirrors the backend `controlMode`.
107
+ * - `ai-agent`: the AI agent answers (normal operation).
108
+ * - `awaiting_operator`: operator-control requested, AI paused, waiting in the operator queue.
109
+ * - `operator`: a workspace operator took over and is replying; AI paused.
110
+ *
111
+ * Carried on `HandshakeResponse.controlState`, `LoadConversationResponse.controlState` (resume +
112
+ * history-switch), and the `data-control-state` stream part (on the reply stream and the held-open
113
+ * resume during operator-control). Absent / unknown → treated as `"ai-agent"`.
114
+ */
115
+ type ControlMode = "ai-agent" | "awaiting_operator" | "operator";
116
+ /**
117
+ * The control-state snapshot the widget reads to render composer/typing/banner state. The optional
118
+ * `operatorAvailable` (set on the operator-request response + the awaiting terminal part) tells the
119
+ * widget whether to show "connecting…" or the async-capture ("leave your details") copy.
120
+ */
121
+ interface ControlState {
122
+ controlMode: ControlMode;
123
+ /**
124
+ * The operator's 2-letter initials (operator mode only) — shown in the bubble chrome + banner. The
125
+ * visitor never sees the full name (privacy); the backend derives the initials. `assignedOperatorId`
126
+ * also rides the wire but the widget doesn't render it, so it isn't modeled here.
127
+ */
128
+ assignedOperatorInitials?: string;
129
+ /** Whether anyone was in the operator pool when operator-control was requested (awaiting mode advisory). */
130
+ operatorAvailable?: boolean;
134
131
  }
135
132
  /** One-shot bot persona shown in the panel header. */
136
133
  interface ConversationAgent {
137
- name: string;
138
- /** Image URL or data URI. When omitted, initials render from `name`. */
139
- avatar?: string;
140
- /** Subtitle ("AI Assistant", "Support team", …). */
141
- title?: string;
142
- /** Presence indicator. Default: `'online'`. */
143
- status?: "online" | "away" | "offline";
134
+ name: string;
135
+ /** Image URL or data URI. When omitted, initials render from `name`. */
136
+ avatar?: string;
137
+ /** Subtitle ("AI Assistant", "Support team", …). */
138
+ title?: string;
139
+ /** Presence indicator. Default: `'online'`. */
140
+ status?: "online" | "away" | "offline";
144
141
  }
145
142
  /** A clickable quick-reply chip. */
146
143
  interface ConversationSuggestion {
147
- id: string;
148
- /** What the chip displays. */
149
- label: string;
150
- /** What actually gets sent when clicked. Defaults to `label`. */
151
- text?: string;
144
+ id: string;
145
+ /** What the chip displays. */
146
+ label: string;
147
+ /** What actually gets sent when clicked. Defaults to `label`. */
148
+ text?: string;
152
149
  }
153
150
  /** Welcome payload pushed into the message list on first open. */
154
151
  interface ConversationWelcome {
155
- messages?: Array<{
156
- id: string;
157
- role: "assistant" | "system";
158
- text: string;
159
- }>;
160
- suggestions?: ConversationSuggestion[];
152
+ messages?: Array<{
153
+ id: string;
154
+ role: "assistant" | "system";
155
+ text: string;
156
+ }>;
157
+ suggestions?: ConversationSuggestion[];
161
158
  }
162
159
  /**
163
160
  * Response from `POST /pai/handshake` — the widget's one mount-time
@@ -173,53 +170,56 @@ interface ConversationWelcome {
173
170
  * widget in French when they open it on their laptop (assuming the same
174
171
  * `visitorId`, e.g. via authenticated conversation — out of scope for v1).
175
172
  */
176
- interface HandshakeResponse {
177
- /**
178
- * Public runtime conversation id. The widget mints this UUIDv7 and the backend
179
- * validates that it belongs to the public deployment + visitor.
180
- */
181
- conversationId: string;
173
+ interface HandshakeResponse$1 {
174
+ /**
175
+ * Public runtime conversation id. The widget mints this UUIDv7 and the backend
176
+ * validates that it belongs to the public deployment + visitor.
177
+ */
178
+ conversationId: string;
179
+ visitorId?: string;
180
+ /** Bot persona in the panel header (name, avatar, status). */
181
+ agent?: ConversationAgent;
182
+ /** Initial assistant messages + quick-reply chips. */
183
+ welcome?: ConversationWelcome;
184
+ /**
185
+ * Deployment-wide widget configuration the dashboard admin saved
186
+ * (mode / theme / launcher / actions / composer / features / …).
187
+ * Client adopts as defaults; customer's `init({...})` still wins
188
+ * per-field. Same for every visitor of this deployment.
189
+ */
190
+ config?: ServerConfig$1;
191
+ /** Page-mode site config (logo, title). Backend ships it whenever the deployment renders the page-shell sidebar. */
192
+ site?: Record<string, unknown>;
193
+ /** Page-mode sidebar blocks (navigation, link cards). Backend ships it whenever the deployment renders the page-shell sidebar. */
194
+ blocks?: Record<string, unknown>;
195
+ /** Current control state — seeds the composer/typing/banner state on connect. Absent → `ai-agent`. */
196
+ controlState?: ControlState;
197
+ /**
198
+ * Server's authoritative copy of the visitor's preferences. When present,
199
+ * client adopts it (overrides local cache) and re-applies it to the UI
200
+ * (locale, panel size, sound mute). Absent → client keeps its cache.
201
+ */
202
+ userPrefs?: UserPrefs;
203
+ /**
204
+ * Optional rebind metadata. When the server returns a `visitorId` /
205
+ * `conversationId` different from what the client sent, this block tells
206
+ * the client WHY — useful for telemetry and the `visitorRebound` /
207
+ * `conversationRebound` events fired into the host page. Server is free to
208
+ * omit it: the client detects rebinding by comparing request vs
209
+ * response ids regardless.
210
+ *
211
+ * Common reasons: `"conflict"` (the id collided with an existing
212
+ * record), `"expired"` (the id is too old to be re-used), `"invalid"`
213
+ * (malformed / not a UUIDv7). Custom strings are passed through to
214
+ * listeners verbatim.
215
+ */
216
+ rebind?: {
182
217
  visitorId?: string;
183
- /** Bot persona in the panel header (name, avatar, status). */
184
- agent?: ConversationAgent;
185
- /** Initial assistant messages + quick-reply chips. */
186
- welcome?: ConversationWelcome;
187
- /**
188
- * Deployment-wide widget configuration the dashboard admin saved
189
- * (mode / theme / launcher / actions / composer / features / …).
190
- * Client adopts as defaults; customer's `init({...})` still wins
191
- * per-field. Same for every visitor of this deployment.
192
- */
193
- config?: ServerConfig;
194
- /** Page-mode site config (logo, title). Backend ships it whenever the deployment renders the page-shell sidebar. */
195
- site?: Record<string, unknown>;
196
- /** Page-mode sidebar blocks (navigation, link cards). Backend ships it whenever the deployment renders the page-shell sidebar. */
197
- blocks?: Record<string, unknown>;
198
- /**
199
- * Server's authoritative copy of the visitor's preferences. When present,
200
- * client adopts it (overrides local cache) and re-applies it to the UI
201
- * (locale, panel size, sound mute). Absent → client keeps its cache.
202
- */
203
- userPrefs?: UserPrefs;
204
- /**
205
- * Optional rebind metadata. When the server returns a `visitorId` /
206
- * `conversationId` different from what the client sent, this block tells
207
- * the client WHY — useful for telemetry and the `visitorRebound` /
208
- * `conversationRebound` events fired into the host page. Server is free to
209
- * omit it: the client detects rebinding by comparing request vs
210
- * response ids regardless.
211
- *
212
- * Common reasons: `"conflict"` (the id collided with an existing
213
- * record), `"expired"` (the id is too old to be re-used), `"invalid"`
214
- * (malformed / not a UUIDv7). Custom strings are passed through to
215
- * listeners verbatim.
216
- */
217
- rebind?: {
218
- visitorId?: string;
219
- conversationId?: string;
220
- };
218
+ conversationId?: string;
219
+ };
221
220
  }
222
-
221
+ //#endregion
222
+ //#region src/core/config/types/common.d.ts
223
223
  /**
224
224
  * Primitive type aliases shared across every config section. Kept in
225
225
  * one file so a domain-specific change (adding a new `Mode` value,
@@ -286,12 +286,8 @@ type ActionName = "clear" | "expand" | "fullscreen" | "sound" | "history" | "lan
286
286
  * set for each mode; a deployment can replace the whole list.
287
287
  */
288
288
  type ActionList = ActionName[];
289
-
290
- /**
291
- * Composer + features. The send-button skin, attachment limits, voice
292
- * mode, file toggle, tool-call gates.
293
- */
294
-
289
+ //#endregion
290
+ //#region src/core/config/types/composer.d.ts
295
291
  /**
296
292
  * How voice input is captured and transcribed.
297
293
  *
@@ -304,45 +300,52 @@ type ActionList = ActionName[];
304
300
  type VoiceMode = "local" | "server" | "disabled";
305
301
  /** Capability flags. Any field left `undefined` uses its default. */
306
302
  interface FeatureFlags {
307
- /** Voice input behaviour (see {@link VoiceMode}). Default: `'local'`. */
308
- voice?: VoiceMode;
309
- /**
310
- * Backend tools the assistant may invoke. Accepts either a bare tool code
311
- * (`"tool:send-money"`) or a rich ref (`{ code, config }`) — the wire
312
- * format always uses the rich shape.
313
- */
314
- tools?: Array<string | ToolRef>;
315
- /**
316
- * Turn OFF the human-in-the-loop tool UI — the inline ask-questions form and the
317
- * approve/reject controls for gated tools. Unset/`false` = shown (default); `true`
318
- * suppresses the UI (the wire still carries the signals; they just won't show).
319
- */
320
- disableHumanInLoop?: boolean;
321
- /**
322
- * Turn OFF file uploads — hide the paperclip button + reject drag/drop/paste.
323
- * Unset/`false` = enabled (default); `true` disables them.
324
- */
325
- disableFileUpload?: boolean;
303
+ /** Voice input behaviour (see {@link VoiceMode}). Default: `'local'`. */
304
+ voice?: VoiceMode;
305
+ /**
306
+ * Backend tools the assistant may invoke. Accepts either a bare tool code
307
+ * (`"tool:send-money"`) or a rich ref (`{ code, config }`) — the wire
308
+ * format always uses the rich shape.
309
+ */
310
+ tools?: Array<string | ToolRef>;
311
+ /**
312
+ * Turn OFF the human-in-the-loop tool UI — the inline ask-questions form and the
313
+ * approve/reject controls for gated tools. Unset/`false` = shown (default); `true`
314
+ * suppresses the UI (the wire still carries the signals; they just won't show).
315
+ */
316
+ disableHumanInLoop?: boolean;
317
+ /**
318
+ * Turn OFF file uploads — hide the paperclip button + reject drag/drop/paste.
319
+ * Unset/`false` = enabled (default); `true` disables them.
320
+ */
321
+ disableFileUpload?: boolean;
322
+ /**
323
+ * Opt IN operator control — exposes the "Talk to an operator" affordance + connected-to-operator
324
+ * states. Positive opt-in (unlike the `disable*` flags) for a new capability; default off.
325
+ */
326
+ enableOperatorRequest?: boolean;
326
327
  }
327
328
  /**
328
- * Features after resolution. The UI reads a POSITIVE `humanInLoop` — `resolveOptions`
329
- * inverts the wire-input `disableHumanInLoop` once here, so no render site does `!disable…`.
329
+ * Features after resolution. The UI reads POSITIVE `humanInLoop`/`fileUpload` — `resolveOptions`
330
+ * inverts the wire-input `disable*` flags once here, so no render site does `!disable…`.
331
+ * `operatorRequest` is already positive at the wire, so it passes through unchanged.
330
332
  */
331
333
  interface ResolvedFeatures {
332
- fileUpload: boolean;
333
- voice: VoiceMode;
334
- humanInLoop: boolean;
335
- tools?: Array<string | ToolRef>;
334
+ fileUpload: boolean;
335
+ voice: VoiceMode;
336
+ humanInLoop: boolean;
337
+ operatorRequest: boolean;
338
+ tools?: Array<string | ToolRef>;
336
339
  }
337
340
  /**
338
341
  * Client-side attachment limits. Server enforcement is still required —
339
342
  * these prevent wasted upload bandwidth and give the user fast feedback.
340
343
  */
341
344
  interface AttachmentLimits {
342
- maxBytes?: number;
343
- maxCount?: number;
344
- /** Comma-separated MIME allowlist, e.g. `'image/*,application/pdf'`. */
345
- accept?: string;
345
+ maxBytes?: number;
346
+ maxCount?: number;
347
+ /** Comma-separated MIME allowlist, e.g. `'image/*,application/pdf'`. */
348
+ accept?: string;
346
349
  }
347
350
  /** Outline shape of the send button. */
348
351
  type SendButtonShape = "circle" | "square" | "pill";
@@ -351,19 +354,20 @@ type SendButtonIcon = "arrowUp" | "paperPlane" | "send" | "chevron";
351
354
  /** Fill/stroke treatment. */
352
355
  type SendButtonVariant = "filled" | "outline" | "ghost";
353
356
  interface SendButtonOptions {
354
- /** Outline shape. Default: `"circle"`. */
355
- shape?: SendButtonShape;
356
- /** Icon inside the button. Default: `"arrowUp"`. */
357
- icon?: SendButtonIcon;
358
- /** Fill treatment. Default: `"filled"`. */
359
- variant?: SendButtonVariant;
357
+ /** Outline shape. Default: `"circle"`. */
358
+ shape?: SendButtonShape;
359
+ /** Icon inside the button. Default: `"arrowUp"`. */
360
+ icon?: SendButtonIcon;
361
+ /** Fill treatment. Default: `"filled"`. */
362
+ variant?: SendButtonVariant;
360
363
  }
361
364
  interface ComposerOptions {
362
- sendButton?: SendButtonOptions;
363
- /** Client-side attachment limits. Server still validates at upload time. */
364
- attachments?: AttachmentLimits;
365
+ sendButton?: SendButtonOptions;
366
+ /** Client-side attachment limits. Server still validates at upload time. */
367
+ attachments?: AttachmentLimits;
365
368
  }
366
-
369
+ //#endregion
370
+ //#region src/core/config/types/feedback.d.ts
367
371
  /**
368
372
  * Audible + tactile feedback knobs. Both default to enabled (browser
369
373
  * autoplay policy still gates audio playback).
@@ -379,12 +383,12 @@ type FeedbackEvent = "messageReceived" | "messageSent" | "error" | "voiceStart"
379
383
  */
380
384
  type SoundEventValue = boolean | string;
381
385
  interface SoundOptions {
382
- /** Master on/off. Default: `false` (opt-in). */
383
- enabled?: boolean;
384
- /** Global volume 0..1. Default: `0.3` (subtle). */
385
- volume?: number;
386
- /** Per-event overrides. Missing keys use the built-in default (see feedback/defaults). */
387
- events?: Partial<Record<FeedbackEvent, SoundEventValue>>;
386
+ /** Master on/off. Default: `false` (opt-in). */
387
+ enabled?: boolean;
388
+ /** Global volume 0..1. Default: `0.3` (subtle). */
389
+ volume?: number;
390
+ /** Per-event overrides. Missing keys use the built-in default (see feedback/defaults). */
391
+ events?: Partial<Record<FeedbackEvent, SoundEventValue>>;
388
392
  }
389
393
  /**
390
394
  * Per-event haptic pattern. Android `navigator.vibrate()` shape.
@@ -399,19 +403,20 @@ interface SoundOptions {
399
403
  */
400
404
  type HapticEventValue = boolean | number | number[];
401
405
  interface HapticsOptions {
402
- /** Default: `true` on touch devices, silently ignored elsewhere. */
403
- enabled?: boolean;
404
- events?: Partial<Record<FeedbackEvent, HapticEventValue>>;
406
+ /** Default: `true` on touch devices, silently ignored elsewhere. */
407
+ enabled?: boolean;
408
+ events?: Partial<Record<FeedbackEvent, HapticEventValue>>;
405
409
  }
406
410
  /**
407
411
  * Section: audible + tactile feedback. Both default to enabled
408
412
  * (browser autoplay policy still gates audio playback).
409
413
  */
410
414
  interface FeedbackOptions {
411
- sound?: SoundOptions;
412
- haptics?: HapticsOptions;
415
+ sound?: SoundOptions;
416
+ haptics?: HapticsOptions;
413
417
  }
414
-
418
+ //#endregion
419
+ //#region src/core/config/types/forms.d.ts
415
420
  /**
416
421
  * Event-driven forms engine — framework-free runtime types (mirror of
417
422
  * `src/schema/widget/forms.ts`). The IIFE path has no Zod, so these plain
@@ -430,41 +435,41 @@ interface FeedbackOptions {
430
435
  type FieldType = "text" | "email" | "tel" | "url" | "number" | "date" | "time" | "textarea" | "select" | "radio" | "checkbox" | "multiselect";
431
436
  /** One choice for `select` / `radio` / `multiselect` fields. */
432
437
  interface FieldOption {
433
- value: string;
434
- /** Display text; falls back to `value`. */
435
- label?: string;
436
- description?: string;
438
+ value: string;
439
+ /** Display text; falls back to `value`. */
440
+ label?: string;
441
+ description?: string;
437
442
  }
438
443
  /** Validation constraints applied client-side (the backend still validates). */
439
444
  interface FieldValidation {
440
- /** Regex source string (anchored as written) — text-like fields. */
441
- pattern?: string;
442
- minLength?: number;
443
- maxLength?: number;
444
- /** Numeric range — `number` fields. */
445
- min?: number;
446
- max?: number;
447
- /** Selection-count bounds — `multiselect` fields. */
448
- minSelections?: number;
449
- maxSelections?: number;
445
+ /** Regex source string (anchored as written) — text-like fields. */
446
+ pattern?: string;
447
+ minLength?: number;
448
+ maxLength?: number;
449
+ /** Numeric range — `number` fields. */
450
+ min?: number;
451
+ max?: number;
452
+ /** Selection-count bounds — `multiselect` fields. */
453
+ minSelections?: number;
454
+ maxSelections?: number;
450
455
  }
451
456
  /** One field in a form. */
452
457
  interface FormField {
453
- /** Stable key the value is recorded under (e.g. `email`). */
454
- name: string;
455
- label: string;
456
- type: FieldType;
457
- placeholder?: string;
458
- required?: boolean;
459
- /** Pre-filled value (string for scalars; comma-joined for `multiselect`). */
460
- defaultValue?: string;
461
- /** Choices for `select` / `radio` / `multiselect`. */
462
- options?: FieldOption[];
463
- validation?: FieldValidation;
464
- /** `select`/`radio`/`multiselect` — allow a free-text "Other" answer. */
465
- allowOther?: boolean;
466
- /** Small helper line under the field. */
467
- validationHint?: string;
458
+ /** Stable key the value is recorded under (e.g. `email`). */
459
+ name: string;
460
+ label: string;
461
+ type: FieldType;
462
+ placeholder?: string;
463
+ required?: boolean;
464
+ /** Pre-filled value (string for scalars; comma-joined for `multiselect`). */
465
+ defaultValue?: string;
466
+ /** Choices for `select` / `radio` / `multiselect`. */
467
+ options?: FieldOption[];
468
+ validation?: FieldValidation;
469
+ /** `select`/`radio`/`multiselect` — allow a free-text "Other" answer. */
470
+ allowOther?: boolean;
471
+ /** Small helper line under the field. */
472
+ validationHint?: string;
468
473
  }
469
474
  /**
470
475
  * Trigger that surfaces a form. Terse string with an optional `:param` so it's
@@ -476,21 +481,21 @@ type FormTrigger = "pre-chat" | `after-messages:${number}` | "conversation-close
476
481
  type TriggerKind = "pre-chat" | "after-messages" | "conversation-closed" | "panel-close" | "idle" | "page-area" | "manual";
477
482
  /** A {@link FormTrigger} parsed into kind + optional param. */
478
483
  interface ParsedTrigger {
479
- kind: TriggerKind;
480
- /** Numeric for `after-messages` / `idle`; string area for `page-area`. */
481
- param?: number | string;
484
+ kind: TriggerKind;
485
+ /** Numeric for `after-messages` / `idle`; string area for `page-area`. */
486
+ param?: number | string;
482
487
  }
483
488
  /**
484
489
  * Extra eligibility predicate, evaluated when a trigger fires. Small and
485
490
  * declarative on purpose — richer routing belongs to the agent / backend.
486
491
  */
487
492
  interface FormCondition {
488
- /** Only show if `userContext` lacks ALL of these keys (progressive profiling). */
489
- missingContext?: string[];
490
- /** Only on these page areas (`pageContext.area`). */
491
- pageArea?: string | string[];
492
- minMessages?: number;
493
- maxMessages?: number;
493
+ /** Only show if `userContext` lacks ALL of these keys (progressive profiling). */
494
+ missingContext?: string[];
495
+ /** Only on these page areas (`pageContext.area`). */
496
+ pageArea?: string | string[];
497
+ minMessages?: number;
498
+ maxMessages?: number;
494
499
  }
495
500
  /**
496
501
  * How often a form may show: `once` per device (persisted), once per
@@ -499,46 +504,46 @@ interface FormCondition {
499
504
  type FormFrequency = "once" | "conversation" | "always";
500
505
  /** One form as authored in config (raw input). */
501
506
  interface FormDef {
502
- /** Stable id — persistence dedupe + `manual` `openForm(id)`. */
503
- id: string;
504
- on: FormTrigger | FormTrigger[];
505
- when?: FormCondition;
506
- fields: FormField[];
507
- title?: string;
508
- description?: string;
509
- submitLabel?: string;
510
- skippable?: boolean;
511
- /** Default `once`. */
512
- frequency?: FormFrequency;
513
- /**
514
- * Mirror the submitted answers into `userContext` so they ride every
515
- * subsequent request (the agent sees them in-conversation). Default `true`.
516
- * Set `false` for PII (DOB, policy #, symptoms) — those then go ONLY to the
517
- * submit endpoint, never onto the always-on context envelope.
518
- */
519
- mirrorToContext?: boolean;
520
- /**
521
- * Skipped marker offers a "Fill out" button that reopens the form (skip is
522
- * a deferral, not a refusal). Default `true`. Set `false` when a skip must
523
- * be final — e.g. a consent ask that should not be re-surfaced.
524
- */
525
- reopenable?: boolean;
526
- /**
527
- * Submitted marker expands in place to a read-only list of the visitor's
528
- * answers. Default `true`. Set `false` to keep the marker plain — e.g.
529
- * sensitive answers that shouldn't linger on screen (pairs with
530
- * `mirrorToContext: false`; the backend should also omit `values` from the
531
- * `/activity` records for such forms).
532
- */
533
- reviewable?: boolean;
534
- /** BCP-47 locale the top-level strings (title / fields copy) are authored in. */
535
- defaultLocale?: string;
536
- /**
537
- * Per-locale string overrides. The data module trims this to the requested
538
- * `?locale=` (≤1 entry); the widget overlays it onto the default copy at
539
- * resolve time (`overlayFormDef`). Absent strings fall back to the default.
540
- */
541
- translations?: FormTranslation[];
507
+ /** Stable id — persistence dedupe + `manual` `openForm(id)`. */
508
+ id: string;
509
+ on: FormTrigger | FormTrigger[];
510
+ when?: FormCondition;
511
+ fields: FormField[];
512
+ title?: string;
513
+ description?: string;
514
+ submitLabel?: string;
515
+ skippable?: boolean;
516
+ /** Default `once`. */
517
+ frequency?: FormFrequency;
518
+ /**
519
+ * Mirror the submitted answers into `userContext` so they ride every
520
+ * subsequent request (the agent sees them in-conversation). Default `true`.
521
+ * Set `false` for PII (DOB, policy #, symptoms) — those then go ONLY to the
522
+ * submit endpoint, never onto the always-on context envelope.
523
+ */
524
+ mirrorToContext?: boolean;
525
+ /**
526
+ * Skipped marker offers a "Fill out" button that reopens the form (skip is
527
+ * a deferral, not a refusal). Default `true`. Set `false` when a skip must
528
+ * be final — e.g. a consent ask that should not be re-surfaced.
529
+ */
530
+ reopenable?: boolean;
531
+ /**
532
+ * Submitted marker expands in place to a read-only list of the visitor's
533
+ * answers. Default `true`. Set `false` to keep the marker plain — e.g.
534
+ * sensitive answers that shouldn't linger on screen (pairs with
535
+ * `mirrorToContext: false`; the backend should also omit `values` from the
536
+ * `/activity` records for such forms).
537
+ */
538
+ reviewable?: boolean;
539
+ /** BCP-47 locale the top-level strings (title / fields copy) are authored in. */
540
+ defaultLocale?: string;
541
+ /**
542
+ * Per-locale string overrides. The data module trims this to the requested
543
+ * `?locale=` (≤1 entry); the widget overlays it onto the default copy at
544
+ * resolve time (`overlayFormDef`). Absent strings fall back to the default.
545
+ */
546
+ translations?: FormTranslation[];
542
547
  }
543
548
  /**
544
549
  * Per-locale overrides of a form's HUMAN-FACING strings only. Structure (field
@@ -552,54 +557,55 @@ interface FormDef {
552
557
  * of `module-help-ai-data-api` `DynamicFormTranslation`.
553
558
  */
554
559
  interface FieldOptionTranslation {
555
- /** The canonical option `value` this localizes. */
556
- value: string;
557
- label?: string;
558
- description?: string;
560
+ /** The canonical option `value` this localizes. */
561
+ value: string;
562
+ label?: string;
563
+ description?: string;
559
564
  }
560
565
  interface FormFieldTranslation {
561
- /** The canonical field `name` this localizes. */
562
- name: string;
563
- label?: string;
564
- placeholder?: string;
565
- validationHint?: string;
566
- options?: FieldOptionTranslation[];
566
+ /** The canonical field `name` this localizes. */
567
+ name: string;
568
+ label?: string;
569
+ placeholder?: string;
570
+ validationHint?: string;
571
+ options?: FieldOptionTranslation[];
567
572
  }
568
573
  interface FormTranslation {
569
- locale: string;
570
- title?: string;
571
- description?: string;
572
- submitLabel?: string;
573
- fields?: FormFieldTranslation[];
574
+ locale: string;
575
+ title?: string;
576
+ description?: string;
577
+ submitLabel?: string;
578
+ fields?: FormFieldTranslation[];
574
579
  }
575
580
  /** The `forms` block is an ordered list (max 20); order = priority. */
576
581
  type FormsOptions = FormDef[];
577
582
  /** A fully-resolved form exposed on {@link ResolvedOptions}. */
578
583
  interface ResolvedForm {
579
- id: string;
580
- triggers: ParsedTrigger[];
581
- when?: FormCondition;
582
- fields: FormField[];
583
- title?: string;
584
- description?: string;
585
- submitLabel?: string;
586
- skippable: boolean;
587
- frequency: FormFrequency;
588
- /** Mirror answers into `userContext` (false → PII, endpoint only). */
589
- mirrorToContext: boolean;
590
- /** Skipped marker offers "Fill out" (false → a skip is final). */
591
- reopenable: boolean;
592
- /** Submitted marker expands to a read-only answers list. */
593
- reviewable: boolean;
584
+ id: string;
585
+ triggers: ParsedTrigger[];
586
+ when?: FormCondition;
587
+ fields: FormField[];
588
+ title?: string;
589
+ description?: string;
590
+ submitLabel?: string;
591
+ skippable: boolean;
592
+ frequency: FormFrequency;
593
+ /** Mirror answers into `userContext` (false → PII, endpoint only). */
594
+ mirrorToContext: boolean;
595
+ /** Skipped marker offers "Fill out" (false → a skip is final). */
596
+ reopenable: boolean;
597
+ /** Submitted marker expands to a read-only answers list. */
598
+ reviewable: boolean;
594
599
  }
595
600
  /** Fully-resolved forms block: ordered list + an event→forms index. */
596
601
  interface ResolvedForms {
597
- /** Forms in declared order (= priority). */
598
- list: ResolvedForm[];
599
- /** Forms keyed by trigger kind, for fast event lookup. */
600
- byTrigger: Partial<Record<TriggerKind, ResolvedForm[]>>;
602
+ /** Forms in declared order (= priority). */
603
+ list: ResolvedForm[];
604
+ /** Forms keyed by trigger kind, for fast event lookup. */
605
+ byTrigger: Partial<Record<TriggerKind, ResolvedForm[]>>;
601
606
  }
602
-
607
+ //#endregion
608
+ //#region src/core/config/types/launcher.d.ts
603
609
  /**
604
610
  * Launcher (floating-mode FAB) + the pre-engagement callout bubble.
605
611
  * Inputs are option-bag shaped; the resolved variant lives in `widget.ts`.
@@ -643,32 +649,33 @@ type CalloutPosition = "auto" | "horizontal" | "vertical";
643
649
  * hidden across visits.
644
650
  */
645
651
  interface LauncherCalloutOptions {
646
- /** Text content. Empty string hides the callout. */
647
- text: string;
648
- /** Visual shape. Default: `"pill"`. */
649
- shape?: CalloutShape;
650
- /** Side of the launcher to anchor on. Default: `"auto"`. */
651
- position?: CalloutPosition;
652
- /** Delay before the bubble appears (ms). Default: `1200`. */
653
- delayMs?: number;
654
- /** Auto-dismiss after this many ms. Default: never (`0`). */
655
- autoDismissMs?: number;
656
- /** Animate with a subtle horizontal nudge. Default: `true`. */
657
- animated?: boolean;
658
- /** Re-show on every visit regardless of prior dismissal. Default: `true`. */
659
- persistent?: boolean;
652
+ /** Text content. Empty string hides the callout. */
653
+ text: string;
654
+ /** Visual shape. Default: `"pill"`. */
655
+ shape?: CalloutShape;
656
+ /** Side of the launcher to anchor on. Default: `"auto"`. */
657
+ position?: CalloutPosition;
658
+ /** Delay before the bubble appears (ms). Default: `1200`. */
659
+ delayMs?: number;
660
+ /** Auto-dismiss after this many ms. Default: never (`0`). */
661
+ autoDismissMs?: number;
662
+ /** Animate with a subtle horizontal nudge. Default: `true`. */
663
+ animated?: boolean;
664
+ /** Re-show on every visit regardless of prior dismissal. Default: `true`. */
665
+ persistent?: boolean;
660
666
  }
661
667
  /** Launcher appearance + behaviour. Only applies in `floating` mode. */
662
668
  interface LauncherOptions {
663
- variant?: LauncherVariant;
664
- size?: LauncherSize;
665
- label?: string;
666
- icon?: LauncherIconPreset | string;
667
- hidden?: boolean;
668
- /** Pre-engagement bubble next to the FAB. See {@link LauncherCalloutOptions}. */
669
- callout?: LauncherCalloutOptions;
669
+ variant?: LauncherVariant;
670
+ size?: LauncherSize;
671
+ label?: string;
672
+ icon?: LauncherIconPreset | string;
673
+ hidden?: boolean;
674
+ /** Pre-engagement bubble next to the FAB. See {@link LauncherCalloutOptions}. */
675
+ callout?: LauncherCalloutOptions;
670
676
  }
671
-
677
+ //#endregion
678
+ //#region src/core/config/types/modules.d.ts
672
679
  /**
673
680
  * Messenger "modules" runtime config types — framework-free mirror of
674
681
  * `src/schema/widget/modules.ts`. The IIFE runtime path has no Zod, so
@@ -682,26 +689,26 @@ interface LauncherOptions {
682
689
  type ModuleLayout = "chat" | "home" | "help" | "news";
683
690
  /** A team/agent avatar shown in the Home hero. */
684
691
  interface ModuleAvatar {
685
- name: string;
686
- /** Image URL; initials of `name` are shown when omitted. */
687
- avatar?: string;
688
- role?: string;
692
+ name: string;
693
+ /** Image URL; initials of `name` are shown when omitted. */
694
+ avatar?: string;
695
+ role?: string;
689
696
  }
690
697
  /** The Home status card. */
691
698
  interface ModuleStatus {
692
- /**
693
- * Status line. An i18n key or a literal (resolved via `localizeText`).
694
- * Omit to use the built-in generic `homeStatus` string — so a deployment can
695
- * show a localized status without authoring copy or a custom key per locale.
696
- */
697
- text?: string;
698
- /**
699
- * Status severity → status-icon colour. Free text; `operational` (default),
700
- * `degraded`, and `down` are styled, any other value uses the operational style.
701
- */
702
- level?: string;
703
- /** Opens in an in-widget iframe when tapped. */
704
- url?: string;
699
+ /**
700
+ * Status line. An i18n key or a literal (resolved via `localizeText`).
701
+ * Omit to use the built-in generic `homeStatus` string — so a deployment can
702
+ * show a localized status without authoring copy or a custom key per locale.
703
+ */
704
+ text?: string;
705
+ /**
706
+ * Status severity → status-icon colour. Free text; `operational` (default),
707
+ * `degraded`, and `down` are styled, any other value uses the operational style.
708
+ */
709
+ level?: string;
710
+ /** Opens in an in-widget iframe when tapped. */
711
+ url?: string;
705
712
  }
706
713
  /**
707
714
  * `home` layout config — flat feature flags (no block authoring). The Home tab
@@ -709,22 +716,22 @@ interface ModuleStatus {
709
716
  * → status → a content list (from the tab's `contentTags`, titled `contentBlockTitle`).
710
717
  */
711
718
  interface HomeConfig {
712
- brandName?: string;
713
- hideGreeting?: boolean;
714
- greetingText?: string;
715
- userAvatars?: ModuleAvatar[];
716
- hideSearchBar?: boolean;
717
- hideRecentConversations?: boolean;
718
- status?: ModuleStatus;
719
- contentBlockTitle?: string;
719
+ brandName?: string;
720
+ hideGreeting?: boolean;
721
+ greetingText?: string;
722
+ userAvatars?: ModuleAvatar[];
723
+ hideSearchBar?: boolean;
724
+ hideRecentConversations?: boolean;
725
+ status?: ModuleStatus;
726
+ contentBlockTitle?: string;
720
727
  }
721
728
  /** One tab as authored in config (raw input). */
722
729
  interface ModuleOptions extends HomeConfig {
723
- label: string;
724
- layout: ModuleLayout;
725
- /** Content tags to scope this tab to (matches content tagged with ANY of them). */
726
- contentTags?: string[];
727
- id?: string;
730
+ label: string;
731
+ layout: ModuleLayout;
732
+ /** Content tags to scope this tab to (matches content tagged with ANY of them). */
733
+ contentTags?: string[];
734
+ id?: string;
728
735
  }
729
736
  /** The `modules` block is an ordered list of tabs (max 4). */
730
737
  type ModulesOptions = ModuleOptions[];
@@ -734,38 +741,34 @@ type ModulesOptions = ModuleOptions[];
734
741
  * `hide*` once, so no render site does `!hide…`. Present only for `home` tabs.
735
742
  */
736
743
  interface ResolvedModule extends Omit<HomeConfig, "hideGreeting" | "hideSearchBar" | "hideRecentConversations"> {
737
- /** Stable id for nav + last-tab persistence (`id` ?? first `contentTags` ?? `layout`, deduped). */
738
- id: string;
739
- /** i18n key or literal — resolved at render via the i18n strings. */
740
- label: string;
741
- layout: ModuleLayout;
742
- /** Content tag scope — the `tags` filter (omitted for `chat`). */
743
- contentTags?: string[];
744
- showGreeting?: boolean;
745
- showSearchBar?: boolean;
746
- showRecentConversations?: boolean;
744
+ /** Stable id for nav + last-tab persistence (`id` ?? first `contentTags` ?? `layout`, deduped). */
745
+ id: string;
746
+ /** i18n key or literal — resolved at render via the i18n strings. */
747
+ label: string;
748
+ layout: ModuleLayout;
749
+ /** Content tag scope — the `tags` filter (omitted for `chat`). */
750
+ contentTags?: string[];
751
+ showGreeting?: boolean;
752
+ showSearchBar?: boolean;
753
+ showRecentConversations?: boolean;
747
754
  }
748
755
  /** Fully-resolved modules block exposed on {@link ResolvedOptions}. */
749
756
  interface ResolvedModules {
750
- /** The tabs, in declared order. Presence = enabled; an empty list = no tabs. */
751
- list: ResolvedModule[];
752
- /** The tabs keyed by `id` (for nav + per-tab config lookup). */
753
- byId: Record<string, ResolvedModule>;
757
+ /** The tabs, in declared order. Presence = enabled; an empty list = no tabs. */
758
+ list: ResolvedModule[];
759
+ /** The tabs keyed by `id` (for nav + per-tab config lookup). */
760
+ byId: Record<string, ResolvedModule>;
754
761
  }
755
-
756
- /**
757
- * Visual presentation — theme tokens, sizing tiers, drag-resize, and
758
- * the `mode` / `position` / `iframe` knobs at the section root.
759
- */
760
-
762
+ //#endregion
763
+ //#region src/core/config/types/presentation.d.ts
761
764
  /** CSS-custom-property overrides applied as inline styles on the host. */
762
765
  interface ThemeOverrides {
763
- accent?: string;
764
- accentText?: string;
765
- radius?: string;
766
- fontFamily?: string;
767
- /** Readable content-column cap (→ `--conversation-max`). CSS length; default `768px`. */
768
- contentMaxWidth?: string;
766
+ accent?: string;
767
+ accentText?: string;
768
+ radius?: string;
769
+ fontFamily?: string;
770
+ /** Readable content-column cap (→ `--conversation-max`). CSS length; default `768px`. */
771
+ contentMaxWidth?: string;
769
772
  }
770
773
  /**
771
774
  * Widget sizing overrides. Each field accepts any valid CSS length
@@ -779,47 +782,47 @@ interface ThemeOverrides {
779
782
  * fills the viewport regardless of other dimensions.
780
783
  */
781
784
  interface SizeOptions {
782
- /** Normal-mode width. Default: mode-specific (see `src/styles/panel.css`). */
785
+ /** Normal-mode width. Default: mode-specific (see `src/styles/panel.css`). */
786
+ width?: string;
787
+ /** Normal-mode height. Default: mode-specific. */
788
+ height?: string;
789
+ /** Dimensions when the user clicks the expand button. */
790
+ expanded?: {
783
791
  width?: string;
784
- /** Normal-mode height. Default: mode-specific. */
785
792
  height?: string;
786
- /** Dimensions when the user clicks the expand button. */
787
- expanded?: {
788
- width?: string;
789
- height?: string;
790
- };
791
- /**
792
- * Edge inset for `drawer` mode — turns the side dock into a flyout
793
- * with the given gap from each viewport edge (`16px`, `2vh`,
794
- * `min(24px, 4vw)`, …). Combine with a partial `height` (`80vh`,
795
- * `min(720px, calc(100vh - 32px))`) for the classic floating
796
- * side-panel look. Ignored by every other mode.
797
- */
798
- inset?: string;
799
- /** Enable + configure user-drag resize of the panel in normal mode. */
800
- resize?: ResizeOptions;
801
- /**
802
- * Which size to open with on the **first** render.
803
- *
804
- * - `"auto"` — pick `expanded` when `window.innerWidth ≥ autoSizeBreakpoint`,
805
- * otherwise `normal`. Lets the backend push a "responsive default" without
806
- * baking the breakpoint into the frontend.
807
- * - `"normal"` — default compact panel (same as omitting the field).
808
- * - `"expanded"` — force-start at the configured `expanded.width/height`.
809
- * - `"fullscreen"` — force-start at viewport fill.
810
- *
811
- * Only applies to the very first mount. The user's last size is
812
- * preserved across close → reopen; a page reload re-evaluates.
813
- * Standalone mode always overrides to `fullscreen`.
814
- *
815
- * Default: `"normal"`.
816
- */
817
- initialSize?: "auto" | "normal" | "expanded" | "fullscreen";
818
- /**
819
- * Viewport-width threshold (px) above which `initialSize: "auto"` picks
820
- * `"expanded"`. Default: `900`.
821
- */
822
- autoSizeBreakpoint?: number;
793
+ };
794
+ /**
795
+ * Edge inset for `drawer` mode — turns the side dock into a flyout
796
+ * with the given gap from each viewport edge (`16px`, `2vh`,
797
+ * `min(24px, 4vw)`, …). Combine with a partial `height` (`80vh`,
798
+ * `min(720px, calc(100vh - 32px))`) for the classic floating
799
+ * side-panel look. Ignored by every other mode.
800
+ */
801
+ inset?: string;
802
+ /** Enable + configure user-drag resize of the panel in normal mode. */
803
+ resize?: ResizeOptions;
804
+ /**
805
+ * Which size to open with on the **first** render.
806
+ *
807
+ * - `"auto"` — pick `expanded` when `window.innerWidth ≥ autoSizeBreakpoint`,
808
+ * otherwise `normal`. Lets the backend push a "responsive default" without
809
+ * baking the breakpoint into the frontend.
810
+ * - `"normal"` — default compact panel (same as omitting the field).
811
+ * - `"expanded"` — force-start at the configured `expanded.width/height`.
812
+ * - `"fullscreen"` — force-start at viewport fill.
813
+ *
814
+ * Only applies to the very first mount. The user's last size is
815
+ * preserved across close → reopen; a page reload re-evaluates.
816
+ * Standalone mode always overrides to `fullscreen`.
817
+ *
818
+ * Default: `"normal"`.
819
+ */
820
+ initialSize?: "auto" | "normal" | "expanded" | "fullscreen";
821
+ /**
822
+ * Viewport-width threshold (px) above which `initialSize: "auto"` picks
823
+ * `"expanded"`. Default: `900`.
824
+ */
825
+ autoSizeBreakpoint?: number;
823
826
  }
824
827
  /**
825
828
  * Drag-resize configuration. When `enabled`, a corner grip appears on the
@@ -827,59 +830,54 @@ interface SizeOptions {
827
830
  * `userPrefs.widgetSize` (cached client-side + synced to the backend).
828
831
  */
829
832
  interface ResizeOptions {
830
- /** Show the resize grip. Default: `false`. */
831
- enabled?: boolean;
832
- minWidth?: string;
833
- maxWidth?: string;
834
- minHeight?: string;
835
- maxHeight?: string;
833
+ /** Show the resize grip. Default: `false`. */
834
+ enabled?: boolean;
835
+ minWidth?: string;
836
+ maxWidth?: string;
837
+ minHeight?: string;
838
+ maxHeight?: string;
836
839
  }
837
840
  /**
838
841
  * Section: how the widget physically presents itself on the page.
839
842
  */
840
843
  interface PresentationOptions {
841
- mode?: Mode;
842
- position?: Position;
843
- /**
844
- * Wrap the widget in a same-origin iframe for strict JS + CSS isolation
845
- * beyond what shadow DOM provides. Composes with every mode.
846
- */
847
- iframe?: boolean;
848
- size?: SizeOptions;
844
+ mode?: Mode;
845
+ position?: Position;
846
+ /**
847
+ * Wrap the widget in a same-origin iframe for strict JS + CSS isolation
848
+ * beyond what shadow DOM provides. Composes with every mode.
849
+ */
850
+ iframe?: boolean;
851
+ size?: SizeOptions;
849
852
  }
850
-
851
- /**
852
- * Misc nested sections: behavior, header, i18n, footer, connection
853
- * (user + endpoints). Keep them in one file because each is small (~5
854
- * fields) and they all live at the top level of `ChatWidgetOptions`.
855
- */
856
-
853
+ //#endregion
854
+ //#region src/core/config/types/sections.d.ts
857
855
  /**
858
856
  * Section: conversation runtime behaviour — auto-open, streaming mode, and the
859
857
  * transcript surface (what renders, how it scrolls, reaction controls).
860
858
  */
861
859
  interface BehaviorOptions {
862
- /** When `true`, don't auto-open the panel on first visit. */
863
- startMinimized?: boolean;
864
- /** Streaming vs. buffered reply delivery. */
865
- responseMode?: ResponseMode;
866
- /** Show the model's reasoning ("thoughts") as a collapsible block. Default `false`. */
867
- showReasoning?: boolean;
868
- /** Show automatic tool/function calls (details + result) in the transcript. Default `false`. */
869
- showToolCalls?: boolean;
870
- /** Show citation sources (web links + document references) in the transcript. Default `false`. */
871
- showSources?: boolean;
872
- /** Turn OFF the 👍/👎 feedback controls on assistant replies. Unset/`false` = shown (default). */
873
- disableMessageFeedback?: boolean;
874
- /** Auto-send a suggestion chip's text on tap. Unset/`false` = fill the composer to edit (default). */
875
- autoSendSuggestions?: boolean;
860
+ /** When `true`, don't auto-open the panel on first visit. */
861
+ startMinimized?: boolean;
862
+ /** Streaming vs. buffered reply delivery. */
863
+ responseMode?: ResponseMode;
864
+ /** Show the model's reasoning ("thoughts") as a collapsible block. Default `false`. */
865
+ showReasoning?: boolean;
866
+ /** Show automatic tool/function calls (details + result) in the transcript. Default `false`. */
867
+ showToolCalls?: boolean;
868
+ /** Show citation sources (web links + document references) in the transcript. Default `false`. */
869
+ showSources?: boolean;
870
+ /** Turn OFF the 👍/👎 feedback controls on rateable (assistant/operator) replies. Unset/`false` = shown (default). */
871
+ disableMessageFeedback?: boolean;
872
+ /** Auto-send a suggestion chip's text on tap. Unset/`false` = fill the composer to edit (default). */
873
+ autoSendSuggestions?: boolean;
876
874
  }
877
875
  /**
878
876
  * Section: panel header actions — the enabled set (`history`/`close` buttons +
879
877
  * ⋯ menu). Unlisted actions are hidden.
880
878
  */
881
879
  interface HeaderOptions {
882
- actions?: ActionList;
880
+ actions?: ActionList;
883
881
  }
884
882
  /**
885
883
  * Section: locale resolution + per-instance string overrides.
@@ -892,35 +890,35 @@ interface HeaderOptions {
892
890
  * 5. `"en"` ultimate fallback.
893
891
  */
894
892
  interface I18nOptions {
895
- locale?: string;
896
- defaultLocale?: "auto" | string;
897
- availableLocales?: string[];
898
- strings?: StringsOverride;
893
+ locale?: string;
894
+ defaultLocale?: "auto" | string;
895
+ availableLocales?: string[];
896
+ strings?: StringsOverride;
899
897
  }
900
898
  /**
901
899
  * "Powered by …" attribution shown below the composer. Any combination of
902
900
  * logo + text + href is valid; all three absent hides the element.
903
901
  */
904
902
  interface PoweredByOption {
905
- /** Visible text (e.g. `"Powered by Help AI"`). */
906
- text?: string;
907
- /** If set, the attribution is an `<a>` pointing here (`noopener noreferrer`). */
908
- href?: string;
909
- /** Optional small logo URL rendered before the text. */
910
- logoUrl?: string;
903
+ /** Visible text (e.g. `"Powered by Help AI"`). */
904
+ text?: string;
905
+ /** If set, the attribution is an `<a>` pointing here (`noopener noreferrer`). */
906
+ href?: string;
907
+ /** Optional small logo URL rendered before the text. */
908
+ logoUrl?: string;
911
909
  }
912
910
  /**
913
911
  * Section: footer area below the composer — brand attribution and
914
912
  * the optional ChatGPT-style "AI can make mistakes" disclaimer.
915
913
  */
916
914
  interface FooterOptions {
917
- /** Optional "Powered by …" attribution rendered below the disclaimer. */
918
- poweredBy?: PoweredByOption;
919
- /**
920
- * Small muted text rendered below the composer. Same pattern as ChatGPT's
921
- * "ChatGPT can make mistakes." When absent / empty, the line is hidden.
922
- */
923
- composerDisclaimer?: string;
915
+ /** Optional "Powered by …" attribution rendered below the disclaimer. */
916
+ poweredBy?: PoweredByOption;
917
+ /**
918
+ * Small muted text rendered below the composer. Same pattern as ChatGPT's
919
+ * "ChatGPT can make mistakes." When absent / empty, the line is hidden.
920
+ */
921
+ composerDisclaimer?: string;
924
922
  }
925
923
  /**
926
924
  * Host-asserted context about the current end-user, forwarded to the backend
@@ -935,17 +933,17 @@ interface FooterOptions {
935
933
  * `sanitizeUserContext` before it goes on the wire.
936
934
  */
937
935
  interface UserContext {
938
- id?: string;
939
- email?: string;
940
- name?: string;
941
- /** Subscription / pricing tier (e.g. `"pro"`). */
942
- plan?: string;
943
- /** The user's role on the host site (e.g. `"admin"`, `"member"`). */
944
- role?: string;
945
- /** Phone number. */
946
- phone?: string;
947
- /** Arbitrary extra scalar context forwarded to the agent. */
948
- [key: string]: string | number | boolean | undefined;
936
+ id?: string;
937
+ email?: string;
938
+ name?: string;
939
+ /** Subscription / pricing tier (e.g. `"pro"`). */
940
+ plan?: string;
941
+ /** The user's role on the host site (e.g. `"admin"`, `"member"`). */
942
+ role?: string;
943
+ /** Phone number. */
944
+ phone?: string;
945
+ /** Arbitrary extra scalar context forwarded to the agent. */
946
+ [key: string]: string | number | boolean | undefined;
949
947
  }
950
948
  /**
951
949
  * Suggested values for {@link PageContext.area} — the host-defined surface the
@@ -963,16 +961,16 @@ type PageArea = "home" | "docs" | "help-desk" | "support" | "pricing" | "checkou
963
961
  * sanitised client-side before sending.
964
962
  */
965
963
  interface PageContext {
966
- /** Host-defined surface the visitor is on (see {@link PageArea}). */
967
- area?: PageArea;
968
- /** Full page URL. Auto-filled from `location.href` when omitted. */
969
- url?: string;
970
- /** Page path, e.g. `/pricing/enterprise`. */
971
- path?: string;
972
- /** Human-readable page title. */
973
- title?: string;
974
- /** Arbitrary extra scalar context about this page / visit. */
975
- [key: string]: string | number | boolean | undefined;
964
+ /** Host-defined surface the visitor is on (see {@link PageArea}). */
965
+ area?: PageArea;
966
+ /** Full page URL. Auto-filled from `location.href` when omitted. */
967
+ url?: string;
968
+ /** Page path, e.g. `/pricing/enterprise`. */
969
+ path?: string;
970
+ /** Human-readable page title. */
971
+ title?: string;
972
+ /** Arbitrary extra scalar context about this page / visit. */
973
+ [key: string]: string | number | boolean | undefined;
976
974
  }
977
975
  /**
978
976
  * Override the HTTP endpoints the widget calls. `upload` / `transcribe`
@@ -982,21 +980,22 @@ interface PageContext {
982
980
  * like a CDN presign service).
983
981
  */
984
982
  interface Endpoints {
985
- /** File upload endpoint. Default: `'/pai/upload-file'`. */
986
- upload?: string;
987
- /** Voice transcription endpoint. Default: `'/pai/transcribe-audio'`. */
988
- transcribe?: string;
989
- /**
990
- * Form submission endpoint. Default: `'/submit-form'`. When any form
991
- * (a pre-chat lead capture, a CSAT survey, etc.) is completed, the widget POSTs
992
- * the captured values here (fire-and-forget), keyed by the same `visitorId` +
993
- * `conversationId` the conversation uses; the payload carries `formId` + `trigger`
994
- * so the backend can route. Optional: a backend that doesn't implement it just
995
- * 404s and the submission is ignored.
996
- */
997
- submitForm?: string;
983
+ /** File upload endpoint. Default: `'/pai/upload-file'`. */
984
+ upload?: string;
985
+ /** Voice transcription endpoint. Default: `'/pai/transcribe-audio'`. */
986
+ transcribe?: string;
987
+ /**
988
+ * Form submission endpoint. Default: `'/submit-form'`. When any form
989
+ * (a pre-chat lead capture, a CSAT survey, etc.) is completed, the widget POSTs
990
+ * the captured values here (fire-and-forget), keyed by the same `visitorId` +
991
+ * `conversationId` the conversation uses; the payload carries `formId` + `trigger`
992
+ * so the backend can route. Optional: a backend that doesn't implement it just
993
+ * 404s and the submission is ignored.
994
+ */
995
+ submitForm?: string;
998
996
  }
999
-
997
+ //#endregion
998
+ //#region src/core/config/types/tracking.d.ts
1000
999
  /**
1001
1000
  * Built-in anonymous usage tracking — utm.gif-style pixel hits that give
1002
1001
  * the widget OWNER (the site embedding it) insights about how visitors
@@ -1013,50 +1012,40 @@ interface Endpoints {
1013
1012
  */
1014
1013
  /** Section: anonymous owner-facing usage tracking. */
1015
1014
  interface TrackingOptions {
1016
- /**
1017
- * Master switch. Default `true` — the widget always fires; the data
1018
- * module gates ingestion per deployment server-side. Set `false`
1019
- * (deployment config or init) to silence the client entirely.
1020
- */
1021
- enabled?: boolean;
1022
- /**
1023
- * Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif`
1024
- * (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
1025
- */
1026
- endpoint?: string;
1027
- /**
1028
- * Per-visitor sampling 0..1. `0.25` tracks ~a quarter of visitors
1029
- * (decided once per page load, so funnels stay intact). Default `1`.
1030
- */
1031
- sampleRate?: number;
1032
- /**
1033
- * Anti-forgery token, echoed as `tk=` on every hit. **Server-issued,
1034
- * never set by hand** — the backend mints it in the
1035
- * `/handshake` response (HMAC over `pk`/`vid`/expiry with a
1036
- * server-side secret; see `docs/api/tracking-collector.md`) and the
1037
- * collector verifies it statelessly. Opaque to the client.
1038
- */
1039
- token?: string;
1015
+ /**
1016
+ * Master switch. Default `true` — the widget always fires; the data
1017
+ * module gates ingestion per deployment server-side. Set `false`
1018
+ * (deployment config or init) to silence the client entirely.
1019
+ */
1020
+ enabled?: boolean;
1021
+ /**
1022
+ * Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif`
1023
+ * (e.g. `https://help.ai/api/data/pai/elements-px.gif`).
1024
+ */
1025
+ endpoint?: string;
1026
+ /**
1027
+ * Per-visitor sampling 0..1. `0.25` tracks ~a quarter of visitors
1028
+ * (decided once per page load, so funnels stay intact). Default `1`.
1029
+ */
1030
+ sampleRate?: number;
1031
+ /**
1032
+ * Anti-forgery token, echoed as `tk=` on every hit. **Server-issued,
1033
+ * never set by hand** — the backend mints it in the
1034
+ * `/handshake` response (HMAC over `pk`/`vid`/expiry with a
1035
+ * server-side secret; see `docs/api/tracking-collector.md`) and the
1036
+ * collector verifies it statelessly. Opaque to the client.
1037
+ */
1038
+ token?: string;
1040
1039
  }
1041
1040
  /** Post-resolve shape — every field concrete (token stays optional: absent until the handshake delivers it). */
1042
1041
  interface ResolvedTracking {
1043
- enabled: boolean;
1044
- endpoint: string;
1045
- sampleRate: number;
1046
- token?: string;
1042
+ enabled: boolean;
1043
+ endpoint: string;
1044
+ sampleRate: number;
1045
+ token?: string;
1047
1046
  }
1048
-
1049
- /**
1050
- * The three composing roots: raw input ({@link ChatWidgetOptions}),
1051
- * post-normalisation runtime shape ({@link ResolvedOptions}), and the
1052
- * subset the server can push back via `/handshake` ({@link
1053
- * ServerConfig}).
1054
- *
1055
- * Internal modules always depend on `ResolvedOptions`. The raw shape
1056
- * lives at the boundary (`init`, `mount`, web component attributes,
1057
- * data-* parsing, server merge) and never escapes.
1058
- */
1059
-
1047
+ //#endregion
1048
+ //#region src/core/config/types/widget.d.ts
1060
1049
  /**
1061
1050
  * Raw options passed to {@link mount}, {@link init}, the Web Component, or
1062
1051
  * the `<script data-*>` auto-boot path. Every field is optional.
@@ -1075,87 +1064,87 @@ interface ResolvedTracking {
1075
1064
  * serialised on the wire.
1076
1065
  */
1077
1066
  interface ChatWidgetOptions {
1078
- /**
1079
- * Stable identifier for this widget instance. Use when mounting more
1080
- * than one widget on the same page (different deployments, different
1081
- * targets). Isolates client-storage namespaces (visitorId, active conversationId,
1082
- * cached userPrefs). Default: `"default"`.
1083
- */
1084
- widgetId?: string;
1085
- /** Workspace-scoped public key (`agent_pk_...`). Sent as `x-public-key`. */
1086
- publicKey?: string;
1087
- /** Deployment ID (UUID). Sent as `x-ai-agent-deployment-id`. */
1088
- aiAgentDeploymentId?: string;
1089
- /**
1090
- * MAIN site origin (no trailing slash, e.g. `https://help.ai`). The API
1091
- * modules derive from it — the production edge mounts the agent API at
1092
- * `${baseUrl}/api/agent` and the data API at `${baseUrl}/api/data`.
1093
- * Defaults to the brand's origin.
1094
- */
1095
- baseUrl?: string;
1096
- /**
1097
- * Agent-API base (no trailing slash) — set it when the
1098
- * `module-help-ai-agent-api` service is reached DIRECTLY (a standalone
1099
- * local module, e.g. `http://localhost:3087`) instead of through the
1100
- * edge. Routes attach as-is (`${agentApiBaseUrl}/pai/handshake`).
1101
- * Precedence: this option > derived from the main origin
1102
- * (`${baseUrl}/api/agent`). Not server-pushable — the handshake already
1103
- * travelled over it.
1104
- */
1105
- agentApiBaseUrl?: string;
1106
- /**
1107
- * Data-API base (no trailing slash) — the `module-help-ai-data-api`
1108
- * service serving content, form definitions, and form submissions at
1109
- * root-level paths (`/content`, `/forms`, `/activity`, `/submit-form`).
1110
- * Set it for a standalone local module (e.g. `http://localhost:3106`).
1111
- * Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived
1112
- * from the main origin (`${baseUrl}/api/data`, e.g.
1113
- * `https://help.ai/api/data`).
1114
- */
1115
- dataApiBaseUrl?: string;
1116
- /** Host-asserted, informational end-user context (untrusted; not auth). */
1117
- userContext?: UserContext;
1118
- /** Host-asserted, informational page/visit context (untrusted; `area`, url, …). */
1119
- pageContext?: PageContext;
1120
- /** HTTP endpoint overrides. */
1121
- endpoints?: Endpoints;
1122
- /**
1123
- * Console log verbosity. `false` / `"off"` silences everything,
1124
- * `true` → `"debug"`. Levels `error` / `warn` / `info` / `debug` /
1125
- * `trace` gate output additively. Runtime-toggleable via
1126
- * `chat.setDebug(level)` or `?<brand>-debug=trace` in the page URL.
1127
- */
1128
- debug?: boolean | "off" | "error" | "warn" | "info" | "debug" | "trace";
1129
- presentation?: PresentationOptions;
1130
- behavior?: BehaviorOptions;
1131
- /** Theme preference (`'auto' | 'light' | 'dark'`) or overrides object. */
1132
- theme?: ThemePreference | ThemeOverrides;
1133
- launcher?: LauncherOptions;
1134
- header?: HeaderOptions;
1135
- composer?: ComposerOptions;
1136
- feedback?: FeedbackOptions;
1137
- i18n?: I18nOptions;
1138
- footer?: FooterOptions;
1139
- /** Capability flags (file upload, voice mode, tools). Server-pushable. */
1140
- features?: FeatureFlags;
1141
- /** Event-driven forms (lead capture, CSAT, intake, consent…). Server-pushable. */
1142
- forms?: FormsOptions;
1143
- /** Messenger modules (Chat / Home / Messages / Help / News tabs). Server-pushable. */
1144
- modules?: ModulesOptions;
1145
- /** Anonymous owner-facing usage tracking (pixel hits). Server-pushable. */
1146
- tracking?: TrackingOptions;
1147
- /**
1148
- * Custom client-side storage adapter. Implements the {@link ClientStorage}
1149
- * interface (`get` / `set` / `remove` / `clear`).
1150
- */
1151
- storage?: ClientStorage;
1152
- onMessage?: (msg: {
1153
- role: string;
1154
- text: string;
1155
- }) => void;
1156
- onOpen?: () => void;
1157
- onClose?: () => void;
1158
- onError?: (err: unknown) => void;
1067
+ /**
1068
+ * Stable identifier for this widget instance. Use when mounting more
1069
+ * than one widget on the same page (different deployments, different
1070
+ * targets). Isolates client-storage namespaces (visitorId, active conversationId,
1071
+ * cached userPrefs). Default: `"default"`.
1072
+ */
1073
+ widgetId?: string;
1074
+ /** Workspace-scoped public key (`agent_pk_...`). Sent as `x-public-key`. */
1075
+ publicKey?: string;
1076
+ /** Deployment ID (UUID). Sent as `x-ai-agent-deployment-id`. */
1077
+ aiAgentDeploymentId?: string;
1078
+ /**
1079
+ * MAIN site origin (no trailing slash, e.g. `https://help.ai`). The API
1080
+ * modules derive from it — the production edge mounts the agent API at
1081
+ * `${baseUrl}/api/agent` and the data API at `${baseUrl}/api/data`.
1082
+ * Defaults to the brand's origin.
1083
+ */
1084
+ baseUrl?: string;
1085
+ /**
1086
+ * Agent-API base (no trailing slash) — set it when the
1087
+ * `module-help-ai-agent-api` service is reached DIRECTLY (a standalone
1088
+ * local module, e.g. `http://localhost:3087`) instead of through the
1089
+ * edge. Routes attach as-is (`${agentApiBaseUrl}/pai/handshake`).
1090
+ * Precedence: this option > derived from the main origin
1091
+ * (`${baseUrl}/api/agent`). Not server-pushable — the handshake already
1092
+ * travelled over it.
1093
+ */
1094
+ agentApiBaseUrl?: string;
1095
+ /**
1096
+ * Data-API base (no trailing slash) — the `module-help-ai-data-api`
1097
+ * service serving content, form definitions, and form submissions at
1098
+ * root-level paths (`/content`, `/forms`, `/activity`, `/submit-form`).
1099
+ * Set it for a standalone local module (e.g. `http://localhost:3106`).
1100
+ * Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived
1101
+ * from the main origin (`${baseUrl}/api/data`, e.g.
1102
+ * `https://help.ai/api/data`).
1103
+ */
1104
+ dataApiBaseUrl?: string;
1105
+ /** Host-asserted, informational end-user context (untrusted; not auth). */
1106
+ userContext?: UserContext;
1107
+ /** Host-asserted, informational page/visit context (untrusted; `area`, url, …). */
1108
+ pageContext?: PageContext;
1109
+ /** HTTP endpoint overrides. */
1110
+ endpoints?: Endpoints;
1111
+ /**
1112
+ * Console log verbosity. `false` / `"off"` silences everything,
1113
+ * `true` → `"debug"`. Levels `error` / `warn` / `info` / `debug` /
1114
+ * `trace` gate output additively. Runtime-toggleable via
1115
+ * `chat.setDebug(level)` or `?<brand>-debug=trace` in the page URL.
1116
+ */
1117
+ debug?: boolean | "off" | "error" | "warn" | "info" | "debug" | "trace";
1118
+ presentation?: PresentationOptions;
1119
+ behavior?: BehaviorOptions;
1120
+ /** Theme preference (`'auto' | 'light' | 'dark'`) or overrides object. */
1121
+ theme?: ThemePreference | ThemeOverrides;
1122
+ launcher?: LauncherOptions;
1123
+ header?: HeaderOptions;
1124
+ composer?: ComposerOptions;
1125
+ feedback?: FeedbackOptions;
1126
+ i18n?: I18nOptions;
1127
+ footer?: FooterOptions;
1128
+ /** Capability flags (file upload, voice mode, tools). Server-pushable. */
1129
+ features?: FeatureFlags;
1130
+ /** Event-driven forms (lead capture, CSAT, intake, consent…). Server-pushable. */
1131
+ forms?: FormsOptions;
1132
+ /** Messenger modules (Chat / Home / Messages / Help / News tabs). Server-pushable. */
1133
+ modules?: ModulesOptions;
1134
+ /** Anonymous owner-facing usage tracking (pixel hits). Server-pushable. */
1135
+ tracking?: TrackingOptions;
1136
+ /**
1137
+ * Custom client-side storage adapter. Implements the {@link ClientStorage}
1138
+ * interface (`get` / `set` / `remove` / `clear`).
1139
+ */
1140
+ storage?: ClientStorage;
1141
+ onMessage?: (msg: {
1142
+ role: string;
1143
+ text: string;
1144
+ }) => void;
1145
+ onOpen?: () => void;
1146
+ onClose?: () => void;
1147
+ onError?: (err: unknown) => void;
1159
1148
  }
1160
1149
  /**
1161
1150
  * Post-normalisation options. Every optional field in {@link ChatWidgetOptions}
@@ -1163,104 +1152,104 @@ interface ChatWidgetOptions {
1163
1152
  * modules depend on this shape, never the raw input.
1164
1153
  */
1165
1154
  interface ResolvedOptions {
1166
- widgetId: string;
1167
- publicKey?: string;
1168
- aiAgentDeploymentId?: string;
1169
- baseUrl: string;
1170
- /** Resolved agent-API base — see {@link ChatWidgetOptions.agentApiBaseUrl}. */
1171
- agentApiBaseUrl: string;
1172
- /** Resolved data-API base — see {@link ChatWidgetOptions.dataApiBaseUrl}. */
1173
- dataApiBaseUrl: string;
1174
- userContext?: UserContext;
1175
- pageContext?: PageContext;
1176
- position: Position;
1177
- themeMode: ThemePreference;
1178
- /** Active text size. Default `normal`; the end-user's pick overrides at runtime. */
1179
- textSize: TextSize;
1180
- themeOverrides: ThemeOverrides;
1181
- mode: Mode;
1182
- iframe: boolean;
1183
- responseMode: ResponseMode;
1184
- /** Show reasoning ("thoughts") as a collapsible block. Default `false`. */
1185
- showReasoning: boolean;
1186
- /** Show automatic tool calls (details + result) in the transcript. Default `false`. */
1187
- showToolCalls: boolean;
1188
- /** Show citation sources (web links + document references) in the transcript. Default `false`. */
1189
- showSources: boolean;
1190
- /** Show 👍/👎 feedback controls on assistant replies. Default `true`. */
1191
- enableMessageFeedback: boolean;
1192
- /** Auto-send a suggestion chip's text on tap (vs. filling the composer to edit). Default `false`. */
1193
- autoSendSuggestions: boolean;
1194
- features: ResolvedFeatures;
1195
- /** Resolved event-driven forms — ordered list + trigger index. */
1196
- forms: ResolvedForms;
1197
- endpoints: Required<Endpoints>;
1198
- attachments: Required<Pick<AttachmentLimits, "maxBytes" | "maxCount">> & {
1199
- accept: string;
1200
- };
1201
- /**
1202
- * Active locale used to compute {@link ResolvedOptions.strings} and carried
1203
- * on every request envelope. Concrete (`"auto"` already resolved to a
1204
- * BCP-47 tag) and clamped into {@link ResolvedOptions.availableLocales}.
1205
- */
1206
- locale: string;
1207
- /**
1208
- * Deployment fallback locale — concrete. The clamp target when the
1209
- * detected / persisted / picked locale isn't in `availableLocales`.
1210
- * Server-authoritative (`config.i18n.defaultLocale` wins over `init`).
1211
- */
1212
- defaultLocale: string;
1213
- /**
1214
- * Locales offered in the language switcher — the deployment's supported
1215
- * set, server-authoritative (`config.i18n.availableLocales` wins over
1216
- * `init`). Single-entry hides the language action.
1217
- */
1218
- availableLocales: string[];
1219
- startMinimized: boolean;
1220
- actions: ActionList;
1221
- size: SizeOptions;
1222
- launcher: Required<Omit<LauncherOptions, "callout" | "label">> & {
1223
- /** Label is optional even after resolution (`circle` variant has no label). */
1224
- label?: string;
1225
- /**
1226
- * Resolved callout config (defaults filled in) — `null` means no
1227
- * callout configured (text was empty / unset).
1228
- */
1229
- callout: Required<LauncherCalloutOptions> | null;
1230
- };
1231
- sound: Required<Omit<SoundOptions, "events">> & {
1232
- events: SoundOptions["events"];
1233
- };
1234
- haptics: Required<Omit<HapticsOptions, "events">> & {
1235
- events: HapticsOptions["events"];
1236
- };
1237
- /**
1238
- * Fully-resolved string map for the active locale. Pre-computed at
1239
- * options-resolve time (and after each server-settings merge) so render
1240
- * paths can read `strings.send` directly without per-call lookup.
1241
- */
1242
- strings: Strings;
1155
+ widgetId: string;
1156
+ publicKey?: string;
1157
+ aiAgentDeploymentId?: string;
1158
+ baseUrl: string;
1159
+ /** Resolved agent-API base — see {@link ChatWidgetOptions.agentApiBaseUrl}. */
1160
+ agentApiBaseUrl: string;
1161
+ /** Resolved data-API base — see {@link ChatWidgetOptions.dataApiBaseUrl}. */
1162
+ dataApiBaseUrl: string;
1163
+ userContext?: UserContext;
1164
+ pageContext?: PageContext;
1165
+ position: Position;
1166
+ themeMode: ThemePreference;
1167
+ /** Active text size. Default `normal`; the end-user's pick overrides at runtime. */
1168
+ textSize: TextSize;
1169
+ themeOverrides: ThemeOverrides;
1170
+ mode: Mode;
1171
+ iframe: boolean;
1172
+ responseMode: ResponseMode;
1173
+ /** Show reasoning ("thoughts") as a collapsible block. Default `false`. */
1174
+ showReasoning: boolean;
1175
+ /** Show automatic tool calls (details + result) in the transcript. Default `false`. */
1176
+ showToolCalls: boolean;
1177
+ /** Show citation sources (web links + document references) in the transcript. Default `false`. */
1178
+ showSources: boolean;
1179
+ /** Show 👍/👎 feedback controls on rateable (assistant/operator) replies. Default `true`. */
1180
+ enableMessageFeedback: boolean;
1181
+ /** Auto-send a suggestion chip's text on tap (vs. filling the composer to edit). Default `false`. */
1182
+ autoSendSuggestions: boolean;
1183
+ features: ResolvedFeatures;
1184
+ /** Resolved event-driven forms — ordered list + trigger index. */
1185
+ forms: ResolvedForms;
1186
+ endpoints: Required<Endpoints>;
1187
+ attachments: Required<Pick<AttachmentLimits, "maxBytes" | "maxCount">> & {
1188
+ accept: string;
1189
+ };
1190
+ /**
1191
+ * Active locale used to compute {@link ResolvedOptions.strings} and carried
1192
+ * on every request envelope. Concrete (`"auto"` already resolved to a
1193
+ * BCP-47 tag) and clamped into {@link ResolvedOptions.availableLocales}.
1194
+ */
1195
+ locale: string;
1196
+ /**
1197
+ * Deployment fallback locale — concrete. The clamp target when the
1198
+ * detected / persisted / picked locale isn't in `availableLocales`.
1199
+ * Server-authoritative (`config.i18n.defaultLocale` wins over `init`).
1200
+ */
1201
+ defaultLocale: string;
1202
+ /**
1203
+ * Locales offered in the language switcher — the deployment's supported
1204
+ * set, server-authoritative (`config.i18n.availableLocales` wins over
1205
+ * `init`). Single-entry hides the language action.
1206
+ */
1207
+ availableLocales: string[];
1208
+ startMinimized: boolean;
1209
+ actions: ActionList;
1210
+ size: SizeOptions;
1211
+ launcher: Required<Omit<LauncherOptions, "callout" | "label">> & {
1212
+ /** Label is optional even after resolution (`circle` variant has no label). */
1213
+ label?: string;
1243
1214
  /**
1244
- * The raw {@link StringsOverride} the page-owner / server supplied —
1245
- * preserved so App can re-resolve into a new locale at runtime when the
1246
- * user picks one from the language switcher (without forcing a re-mount).
1215
+ * Resolved callout config (defaults filled in) — `null` means no
1216
+ * callout configured (text was empty / unset).
1247
1217
  */
1248
- stringsOverride?: StringsOverride;
1249
- composerDisclaimer: string;
1250
- poweredBy: PoweredByOption | null;
1251
- composer: {
1252
- sendButton: Required<SendButtonOptions>;
1253
- };
1254
- /** Resolved messenger modules — per-module config + ordered enabled list + default tab. */
1255
- modules: ResolvedModules;
1256
- /** Resolved anonymous usage tracking. */
1257
- tracking: ResolvedTracking;
1258
- /** Resolved storage adapter — defaults to `LocalStorageAdapter`. */
1259
- storage: ClientStorage;
1260
- onMessage?: ChatWidgetOptions["onMessage"];
1261
- onOpen?: ChatWidgetOptions["onOpen"];
1262
- onClose?: ChatWidgetOptions["onClose"];
1263
- onError?: ChatWidgetOptions["onError"];
1218
+ callout: Required<LauncherCalloutOptions> | null;
1219
+ };
1220
+ sound: Required<Omit<SoundOptions, "events">> & {
1221
+ events: SoundOptions["events"];
1222
+ };
1223
+ haptics: Required<Omit<HapticsOptions, "events">> & {
1224
+ events: HapticsOptions["events"];
1225
+ };
1226
+ /**
1227
+ * Fully-resolved string map for the active locale. Pre-computed at
1228
+ * options-resolve time (and after each server-settings merge) so render
1229
+ * paths can read `strings.send` directly without per-call lookup.
1230
+ */
1231
+ strings: Strings;
1232
+ /**
1233
+ * The raw {@link StringsOverride} the page-owner / server supplied —
1234
+ * preserved so App can re-resolve into a new locale at runtime when the
1235
+ * user picks one from the language switcher (without forcing a re-mount).
1236
+ */
1237
+ stringsOverride?: StringsOverride;
1238
+ composerDisclaimer: string;
1239
+ poweredBy: PoweredByOption | null;
1240
+ composer: {
1241
+ sendButton: Required<SendButtonOptions>;
1242
+ };
1243
+ /** Resolved messenger modules — per-module config + ordered enabled list + default tab. */
1244
+ modules: ResolvedModules;
1245
+ /** Resolved anonymous usage tracking. */
1246
+ tracking: ResolvedTracking;
1247
+ /** Resolved storage adapter — defaults to `LocalStorageAdapter`. */
1248
+ storage: ClientStorage;
1249
+ onMessage?: ChatWidgetOptions["onMessage"];
1250
+ onOpen?: ChatWidgetOptions["onOpen"];
1251
+ onClose?: ChatWidgetOptions["onClose"];
1252
+ onError?: ChatWidgetOptions["onError"];
1264
1253
  }
1265
1254
  /**
1266
1255
  * Shape of the server-pushed `widget` object in `HandshakeResponse`.
@@ -1273,32 +1262,33 @@ interface ResolvedOptions {
1273
1262
  * the data-API (`GET /forms`). A stale backend still pushing
1274
1263
  * `config.forms` is ignored.
1275
1264
  */
1276
- interface ServerConfig {
1277
- /** Data-API base override — adopted only when the host didn't set one. */
1278
- dataApiBaseUrl?: string;
1279
- /**
1280
- * Storage-schema version — the deployment-owned force-reset lever, pushed ONLY
1281
- * via the handshake (deliberately not an embed attribute / `init` option).
1282
- * Pushing a new value abandons every client's prior storage namespace
1283
- * (visitor id, conversation, prefs, panel state, caches) on next load. The
1284
- * widget stashes it and the next mount folds `.v<version>` into every key.
1285
- */
1286
- storageVersion?: string;
1287
- presentation?: PresentationOptions;
1288
- behavior?: BehaviorOptions;
1289
- theme?: ThemePreference | ThemeOverrides;
1290
- launcher?: LauncherOptions;
1291
- header?: HeaderOptions;
1292
- composer?: ComposerOptions;
1293
- feedback?: FeedbackOptions;
1294
- i18n?: I18nOptions;
1295
- footer?: FooterOptions;
1296
- features?: FeatureFlags;
1297
- modules?: ModulesOptions;
1298
- tracking?: TrackingOptions;
1299
- endpoints?: Endpoints;
1265
+ interface ServerConfig$1 {
1266
+ /** Data-API base override — adopted only when the host didn't set one. */
1267
+ dataApiBaseUrl?: string;
1268
+ /**
1269
+ * Storage-schema version — the deployment-owned force-reset lever, pushed ONLY
1270
+ * via the handshake (deliberately not an embed attribute / `init` option).
1271
+ * Pushing a new value abandons every client's prior storage namespace
1272
+ * (visitor id, conversation, prefs, panel state, caches) on next load. The
1273
+ * widget stashes it and the next mount folds `.v<version>` into every key.
1274
+ */
1275
+ storageVersion?: string;
1276
+ presentation?: PresentationOptions;
1277
+ behavior?: BehaviorOptions;
1278
+ theme?: ThemePreference | ThemeOverrides;
1279
+ launcher?: LauncherOptions;
1280
+ header?: HeaderOptions;
1281
+ composer?: ComposerOptions;
1282
+ feedback?: FeedbackOptions;
1283
+ i18n?: I18nOptions;
1284
+ footer?: FooterOptions;
1285
+ features?: FeatureFlags;
1286
+ modules?: ModulesOptions;
1287
+ tracking?: TrackingOptions;
1288
+ endpoints?: Endpoints;
1300
1289
  }
1301
-
1290
+ //#endregion
1291
+ //#region src/core/logger.d.ts
1302
1292
  /**
1303
1293
  * Comprehensive logger for the widget runtime.
1304
1294
  *
@@ -1325,23 +1315,14 @@ interface ServerConfig {
1325
1315
  type LogLevel = "off" | "error" | "warn" | "info" | "debug" | "trace";
1326
1316
  /** One structured line, as forwarded to an external {@link setLogSink} sink. */
1327
1317
  interface LogEntry {
1328
- level: LogLevel;
1329
- /** Subsystem tag, e.g. `"transport"` or `"core:hooks"`. */
1330
- scope: string;
1331
- message: string;
1332
- payload?: unknown;
1318
+ level: LogLevel;
1319
+ /** Subsystem tag, e.g. `"transport"` or `"core:hooks"`. */
1320
+ scope: string;
1321
+ message: string;
1322
+ payload?: unknown;
1333
1323
  }
1334
-
1335
- /**
1336
- * Tiny typed pub/sub for widget lifecycle events.
1337
- *
1338
- * Insulates UI components from the public callback shape, and gives us room
1339
- * to add listeners (analytics, logging) without touching the UI.
1340
- *
1341
- * All listeners are isolated — a throw in one never breaks the widget or
1342
- * prevents other listeners from firing.
1343
- */
1344
-
1324
+ //#endregion
1325
+ //#region src/core/events.d.ts
1345
1326
  /**
1346
1327
  * Payload shape per event. Keyed by event name; use `void` for events that
1347
1328
  * carry no data.
@@ -1352,200 +1333,168 @@ interface LogEntry {
1352
1333
  * structured logger at `info` level when `debug` is enabled.
1353
1334
  */
1354
1335
  interface EventMap {
1355
- /** Panel opened (floating / modal / drawer). */
1356
- open: void;
1357
- /** Panel closed. */
1358
- close: void;
1359
- /** Expanded mode toggled (1.5× size). Payload is the new state. */
1360
- expand: boolean;
1361
- /** Fullscreen mode toggled. Payload is the new state. */
1362
- fullscreen: boolean;
1363
- /** End-user dragged the resize grip — payload is the resolved size. */
1364
- resize: {
1365
- width: number;
1366
- height: number;
1367
- };
1368
- /** A message was exchanged. Fires for both user and assistant messages. */
1369
- message: {
1370
- role: string;
1371
- text: string;
1372
- };
1373
- /** User submitted a message (fires before the request is sent). */
1374
- send: {
1375
- text: string;
1376
- attachmentCount: number;
1377
- };
1378
- /** User cancelled an in-flight stream. */
1379
- stop: void;
1380
- /** Clear / new-conversation requested. */
1381
- clear: void;
1382
- /** User picked a chat from the history pane / sidebar. */
1383
- selectConversation: {
1384
- conversationId: string;
1385
- };
1386
- /** User clicked a suggested-message chip. */
1387
- suggestion: {
1388
- text: string;
1389
- };
1390
- /** History pane toggled. Payload is the resulting view. */
1391
- toggleHistory: {
1392
- view: "chat" | "history";
1393
- };
1394
- /** A form (intake, CSAT, …) was completed or skipped. */
1395
- formSubmit: {
1396
- formId: string;
1397
- values: Record<string, string>;
1398
- skipped: boolean;
1399
- };
1400
- /** User answered an ask-questions tool request (re-POST follows). */
1401
- toolResult: {
1402
- toolCallId: string;
1403
- };
1404
- /** User approved / rejected a gated tool call (re-POST follows). */
1405
- toolDecision: {
1406
- toolCallId: string;
1407
- approved: boolean;
1408
- };
1409
- /**
1410
- * User gave feedback on an assistant reply. `value` is `"up"` / `"down"`, or
1411
- * `null` when they cleared a prior choice. `messageId` is the backend message
1412
- * id. Also POSTed best-effort to `/pai/message-feedback`; a host listener can
1413
- * mirror it to analytics.
1414
- */
1415
- messageFeedback: {
1416
- messageId: string;
1417
- value: FeedbackValue;
1418
- };
1419
- /** A content list (news / help / home block) rendered. */
1420
- contentView: {
1421
- section: string;
1422
- tags?: string;
1423
- count: number;
1424
- };
1425
- /** An article / content item was opened. */
1426
- contentOpen: {
1427
- contentId: string;
1428
- tags?: string;
1429
- };
1430
- /** The help search ran. Length + hit count only — never the query text. */
1431
- contentSearch: {
1432
- queryLength: number;
1433
- hitCount: number;
1434
- };
1435
- /** An opened article was read (dwell threshold passed). Fires once per open. */
1436
- contentRead: {
1437
- contentId: string;
1438
- };
1439
- /** A link inside an opened article was followed. */
1440
- contentLinkClick: {
1441
- contentId: string;
1442
- };
1443
- /** Files attached (drag-drop, file picker, paste). */
1444
- attach: {
1445
- count: number;
1446
- totalBytes: number;
1447
- };
1448
- /** An attachment was removed before send. */
1449
- removeAttachment: {
1450
- id: string;
1451
- };
1452
- /** Voice recording started. */
1453
- voiceStart: void;
1454
- /** Voice recording stopped and was sent for transcription. */
1455
- voiceStop: {
1456
- durationMs: number;
1457
- };
1458
- /** Voice recording cancelled (e.g. user released outside the button). */
1459
- voiceCancel: void;
1460
- /** End-user picked a different UI locale. Payload is the new BCP-47 tag. */
1461
- localeChange: string;
1462
- /** End-user picked a different theme mode (`auto` / `light` / `dark`). */
1463
- themeChange: ThemePreference;
1464
- /** End-user picked a different text size (`small` / `normal` / `large`). */
1465
- textSizeChange: TextSize;
1466
- /** End-user toggled the global sound mute. */
1467
- soundToggle: {
1468
- muted: boolean;
1469
- };
1470
- /** Page-mode sidebar collapsed / expanded. */
1471
- sidebarToggle: {
1472
- collapsed: boolean;
1473
- };
1474
- /** Pre-engagement launcher callout dismissed. */
1475
- calloutDismiss: void;
1476
- /** An unhandled error occurred somewhere in the transport or UI. */
1477
- error: unknown;
1478
- /** Connect bootstrap succeeded. Payload is the typed server response. */
1479
- handshake: HandshakeResponse;
1480
- /**
1481
- * Server rebound the `visitorId` — e.g. the client-minted id
1482
- * conflicted with an existing record, was expired, or otherwise
1483
- * rejected, and the server returned a fresh one in the
1484
- * `/handshake` response. The widget has already adopted the new
1485
- * id and persisted it; this event is informational so host pages
1486
- * can re-link analytics / external systems that pinned the
1487
- * previous value.
1488
- *
1489
- * `reason` is the server's explanation, when provided
1490
- * (`rebind.visitorId` in the handshake response). Common values:
1491
- * `"conflict"` / `"expired"` / `"invalid"`. May be `undefined` if
1492
- * the server didn't include a `rebind` block.
1493
- */
1494
- visitorRebound: {
1495
- previous: string;
1496
- current: string;
1497
- reason?: string;
1498
- };
1499
- /**
1500
- * Server rebound the `conversationId` — same shape and semantics as
1501
- * `visitorRebound` but for the conversation-thread id. Fires when
1502
- * the server's response carries a different `conversationId` than the
1503
- * client sent.
1504
- */
1505
- conversationRebound: {
1506
- previous: string;
1507
- current: string;
1508
- reason?: string;
1509
- };
1336
+ /** Panel opened (floating / modal / drawer). */
1337
+ open: void;
1338
+ /** Panel closed. */
1339
+ close: void;
1340
+ /** Expanded mode toggled (1.5× size). Payload is the new state. */
1341
+ expand: boolean;
1342
+ /** Fullscreen mode toggled. Payload is the new state. */
1343
+ fullscreen: boolean;
1344
+ /** End-user dragged the resize grip — payload is the resolved size. */
1345
+ resize: {
1346
+ width: number;
1347
+ height: number;
1348
+ };
1349
+ /** A message was exchanged. Fires for user, assistant, and operator messages. */
1350
+ message: {
1351
+ role: string;
1352
+ text: string;
1353
+ };
1354
+ /** User submitted a message (fires before the request is sent). */
1355
+ send: {
1356
+ text: string;
1357
+ attachmentCount: number;
1358
+ };
1359
+ /** User cancelled an in-flight stream. */
1360
+ stop: void;
1361
+ /** Clear / new-conversation requested. */
1362
+ clear: void;
1363
+ /** User picked a chat from the history pane / sidebar. */
1364
+ selectConversation: {
1365
+ conversationId: string;
1366
+ };
1367
+ /** User clicked a suggested-message chip. */
1368
+ suggestion: {
1369
+ text: string;
1370
+ };
1371
+ /** History pane toggled. Payload is the resulting view. */
1372
+ toggleHistory: {
1373
+ view: "chat" | "history";
1374
+ };
1375
+ /** A form (intake, CSAT, …) was completed or skipped. */
1376
+ formSubmit: {
1377
+ formId: string;
1378
+ values: Record<string, string>;
1379
+ skipped: boolean;
1380
+ };
1381
+ /** User answered an ask-questions tool request (re-POST follows). */
1382
+ toolResult: {
1383
+ toolCallId: string;
1384
+ };
1385
+ /** User approved / rejected a gated tool call (re-POST follows). */
1386
+ toolDecision: {
1387
+ toolCallId: string;
1388
+ approved: boolean;
1389
+ };
1390
+ /**
1391
+ * User gave feedback on a rateable reply (AI or operator). `value` is `"up"` / `"down"`, or
1392
+ * `null` when they cleared a prior choice. `messageId` is the backend message
1393
+ * id. Also POSTed best-effort to `/pai/message-feedback`; a host listener can
1394
+ * mirror it to analytics.
1395
+ */
1396
+ messageFeedback: {
1397
+ messageId: string;
1398
+ value: FeedbackValue;
1399
+ };
1400
+ /** A content list (news / help / home block) rendered. */
1401
+ contentView: {
1402
+ section: string;
1403
+ tags?: string;
1404
+ count: number;
1405
+ };
1406
+ /** An article / content item was opened. */
1407
+ contentOpen: {
1408
+ contentId: string;
1409
+ tags?: string;
1410
+ };
1411
+ /** The help search ran. Length + hit count only — never the query text. */
1412
+ contentSearch: {
1413
+ queryLength: number;
1414
+ hitCount: number;
1415
+ };
1416
+ /** An opened article was read (dwell threshold passed). Fires once per open. */
1417
+ contentRead: {
1418
+ contentId: string;
1419
+ };
1420
+ /** A link inside an opened article was followed. */
1421
+ contentLinkClick: {
1422
+ contentId: string;
1423
+ };
1424
+ /** Files attached (drag-drop, file picker, paste). */
1425
+ attach: {
1426
+ count: number;
1427
+ totalBytes: number;
1428
+ };
1429
+ /** An attachment was removed before send. */
1430
+ removeAttachment: {
1431
+ id: string;
1432
+ };
1433
+ /** Voice recording started. */
1434
+ voiceStart: void;
1435
+ /** Voice recording stopped and was sent for transcription. */
1436
+ voiceStop: {
1437
+ durationMs: number;
1438
+ };
1439
+ /** Voice recording cancelled (e.g. user released outside the button). */
1440
+ voiceCancel: void;
1441
+ /** End-user picked a different UI locale. Payload is the new BCP-47 tag. */
1442
+ localeChange: string;
1443
+ /** End-user picked a different theme mode (`auto` / `light` / `dark`). */
1444
+ themeChange: ThemePreference;
1445
+ /** End-user picked a different text size (`small` / `normal` / `large`). */
1446
+ textSizeChange: TextSize;
1447
+ /** End-user toggled the global sound mute. */
1448
+ soundToggle: {
1449
+ muted: boolean;
1450
+ };
1451
+ /** Page-mode sidebar collapsed / expanded. */
1452
+ sidebarToggle: {
1453
+ collapsed: boolean;
1454
+ };
1455
+ /** Pre-engagement launcher callout dismissed. */
1456
+ calloutDismiss: void;
1457
+ /** An unhandled error occurred somewhere in the transport or UI. */
1458
+ error: unknown;
1459
+ /** Connect bootstrap succeeded. Payload is the typed server response. */
1460
+ handshake: HandshakeResponse$1;
1461
+ /**
1462
+ * Server rebound the `visitorId` — e.g. the client-minted id
1463
+ * conflicted with an existing record, was expired, or otherwise
1464
+ * rejected, and the server returned a fresh one in the
1465
+ * `/handshake` response. The widget has already adopted the new
1466
+ * id and persisted it; this event is informational so host pages
1467
+ * can re-link analytics / external systems that pinned the
1468
+ * previous value.
1469
+ *
1470
+ * `reason` is the server's explanation, when provided
1471
+ * (`rebind.visitorId` in the handshake response). Common values:
1472
+ * `"conflict"` / `"expired"` / `"invalid"`. May be `undefined` if
1473
+ * the server didn't include a `rebind` block.
1474
+ */
1475
+ visitorRebound: {
1476
+ previous: string;
1477
+ current: string;
1478
+ reason?: string;
1479
+ };
1480
+ /**
1481
+ * Server rebound the `conversationId` — same shape and semantics as
1482
+ * `visitorRebound` but for the conversation-thread id. Fires when
1483
+ * the server's response carries a different `conversationId` than the
1484
+ * client sent.
1485
+ */
1486
+ conversationRebound: {
1487
+ previous: string;
1488
+ current: string;
1489
+ reason?: string;
1490
+ };
1510
1491
  }
1511
1492
  type EventName = keyof EventMap;
1512
-
1513
- /**
1514
- * Derives the `data-mode` attribute value from App state.
1515
- *
1516
- * Kept as a pure helper (no DOM, no React) so tests can pin the critical
1517
- * invariants cheaply:
1518
- *
1519
- * - `isOpen === false` → `"closed"` regardless of `panelSize`.
1520
- * This is the reason closing from fullscreen doesn't hide the launcher:
1521
- * the `[data-mode="fullscreen"] .__P__-fab { display: none }` rule never
1522
- * matches when the widget is closed.
1523
- * - `panelSize` is preserved across close → open, so reopening the widget
1524
- * restores the user's last layout (normal / expanded / fullscreen).
1525
- * - Inline + standalone are terminal modes: they override any panelSize
1526
- * because the widget isn't a popover and can't be "closed".
1527
- */
1528
-
1493
+ //#endregion
1494
+ //#region src/ui/host-mode.d.ts
1529
1495
  type HostMode = "page" | "standalone" | "inline" | "modal" | "drawer" | "fullscreen" | "expanded" | "open" | "closed";
1530
-
1531
- /**
1532
- * Shared widget runtime — the one composition both entry points wrap around
1533
- * `<App>`.
1534
- *
1535
- * `mount()` (`src/index.ts`, programmatic, `widgetId`-keyed registry, returns a
1536
- * handle) and `<web-ai-chat>` (`src/web-component.ts`, declarative, N-per-page,
1537
- * no registry) used to each hand-roll the same four things around the App tree:
1538
- * the ErrorBoundary wrapper, the handshake-config merge, the usage tracker, and
1539
- * the host-attribute application (position / theme / `data-mode`). That parallel
1540
- * code drifted three separate times (mode-merge, tracker, ErrorBoundary). This
1541
- * module is the single source of that composition so it can't drift again — both
1542
- * entry points only own what's genuinely theirs (mount: iframe + handle + hooks
1543
- * + registry; web-component: attribute parsing + the custom-element lifecycle).
1544
- *
1545
- * Lives at the composition-root level (peer to the entry files), not in `core/`,
1546
- * because it imports Preact + UI + shadow adapters — `core/**` is framework-free.
1547
- */
1548
-
1496
+ //#endregion
1497
+ //#region src/boot.d.ts
1549
1498
  /**
1550
1499
  * Determine what `data-mode` the host should start at — matching what App's
1551
1500
  * mount-time `useEffect` will produce on its first render. Used for the initial
@@ -1558,35 +1507,8 @@ type HostMode = "page" | "standalone" | "inline" | "modal" | "drawer" | "fullscr
1558
1507
  * first effect (the closed→open→closed flicker this pins against).
1559
1508
  */
1560
1509
  declare function resolveInitialHostMode(options: ResolvedOptions): HostMode;
1561
-
1562
- /**
1563
- * Global lifecycle-hook registry.
1564
- *
1565
- * Per-instance events (`open`, `close`, `message`, …) are already delivered
1566
- * to subscribers via each widget's {@link EventBus}. That works well for
1567
- * callers who hold a direct handle to the instance — but not for the
1568
- * zero-JS `<script data-*>` embed path, and not for analytics wiring that
1569
- * wants to hear from *every* widget without knowing their ids in advance.
1570
- *
1571
- * This module plugs that gap. Hooks are registered against a widgetId
1572
- * (exact or `"*"`) and an event name (exact or `"*"`), and fire with a
1573
- * unified signature — `(instance, event, data)` — so a single callback can
1574
- * handle any event on any widget:
1575
- *
1576
- * ```ts
1577
- * HelpAI.hook("*", "*", (inst, event, data) => analytics.track(event, { widget: inst.widgetId }));
1578
- * HelpAI.hook("support", "message", (inst, _event, data) => log(`[${inst.widgetId}] ${data.role}: ${data.text}`));
1579
- * ```
1580
- *
1581
- * Registration order is irrelevant — hooks may be added before the bundle
1582
- * loads (via the pre-boot queue) or after any number of instances are
1583
- * already mounted. Live instances are subscribed retroactively.
1584
- *
1585
- * Listeners are isolated: a throw in one never breaks the widget or
1586
- * prevents other listeners from firing. Same contract as the per-instance
1587
- * bus.
1588
- */
1589
-
1510
+ //#endregion
1511
+ //#region src/core/hooks.d.ts
1590
1512
  /** Wildcard that matches every widget id / every event name. */
1591
1513
  declare const HOOK_WILDCARD = "*";
1592
1514
  /**
@@ -1603,116 +1525,2063 @@ declare const HOOK_WILDCARD = "*";
1603
1525
  * ```
1604
1526
  */
1605
1527
  type HookListener = (instance: ChatWidgetInstance, event: EventName, data: unknown) => void;
1606
-
1607
- /**
1608
- * Public ESM entry for `@<brand>/elements`.
1609
- *
1610
- * This module is side-effect free — importing it does not mount anything or
1611
- * touch the DOM. Call {@link mount} or {@link init} to render the widget.
1612
- *
1613
- * The Web Component (`<{brand}-chat>`) lives in a separate sub-entry
1614
- * (`./web-component`) so tree-shakers can drop the custom-element machinery
1615
- * when it isn't used.
1616
- *
1617
- * @example
1618
- * ```ts
1619
- * import { mount } from '@helpai/elements';
1620
- *
1621
- * const chat = mount({
1622
- * publicKey: 'agent_pk_...',
1623
- * mode: 'inline',
1624
- * target: document.getElementById('chat'),
1625
- * });
1626
- *
1627
- * chat.on('message', (m) => console.log(m));
1628
- * ```
1629
- *
1630
- * @packageDocumentation
1631
- */
1632
-
1528
+ //#endregion
1529
+ //#region src/schema/primitives.d.ts
1530
+ /** A single image asset (logo, hero, icon). */
1531
+ declare const assetSchema: z.ZodObject<{
1532
+ url: z.ZodString;
1533
+ alt: z.ZodOptional<z.ZodString>;
1534
+ }, z.core.$strict>;
1535
+ type Asset = z.infer<typeof assetSchema>;
1536
+ /** A navigation link / link card. `href` is optional so it can also be used as a heading. */
1537
+ declare const linkSchema: z.ZodObject<{
1538
+ id: z.ZodOptional<z.ZodString>;
1539
+ label: z.ZodString;
1540
+ href: z.ZodOptional<z.ZodString>;
1541
+ icon: z.ZodOptional<z.ZodString>;
1542
+ description: z.ZodOptional<z.ZodString>;
1543
+ }, z.core.$loose>;
1544
+ type Link = z.infer<typeof linkSchema>;
1545
+ //#endregion
1546
+ //#region src/schema/widget.d.ts
1547
+ /**
1548
+ * Where the widget talks to and how it authenticates. Owned by the
1549
+ * **embedding developer** — typically baked into the page template or
1550
+ * an env var, not user-editable. Distinct from {@link widgetSettingsSchema}
1551
+ * which is the dashboard-pushed UX surface.
1552
+ */
1553
+ declare const connectionConfigSchema: z.ZodObject<{
1554
+ widgetId: z.ZodDefault<z.ZodString>;
1555
+ publicKey: z.ZodOptional<z.ZodString>;
1556
+ aiAgentDeploymentId: z.ZodOptional<z.ZodString>;
1557
+ baseUrl: z.ZodOptional<z.ZodString>;
1558
+ agentApiBaseUrl: z.ZodOptional<z.ZodString>;
1559
+ dataApiBaseUrl: z.ZodOptional<z.ZodString>;
1560
+ userContext: z.ZodOptional<z.ZodObject<{
1561
+ id: z.ZodOptional<z.ZodString>;
1562
+ email: z.ZodOptional<z.ZodString>;
1563
+ name: z.ZodOptional<z.ZodString>;
1564
+ plan: z.ZodOptional<z.ZodString>;
1565
+ role: z.ZodOptional<z.ZodString>;
1566
+ phone: z.ZodOptional<z.ZodString>;
1567
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
1568
+ pageContext: z.ZodOptional<z.ZodObject<{
1569
+ area: z.ZodOptional<z.ZodString>;
1570
+ url: z.ZodOptional<z.ZodString>;
1571
+ path: z.ZodOptional<z.ZodString>;
1572
+ title: z.ZodOptional<z.ZodString>;
1573
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
1574
+ endpoints: z.ZodOptional<z.ZodObject<{
1575
+ upload: z.ZodDefault<z.ZodString>;
1576
+ transcribe: z.ZodDefault<z.ZodString>;
1577
+ submitForm: z.ZodDefault<z.ZodString>;
1578
+ }, z.core.$loose>>;
1579
+ debug: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
1580
+ error: "error";
1581
+ off: "off";
1582
+ warn: "warn";
1583
+ info: "info";
1584
+ debug: "debug";
1585
+ trace: "trace";
1586
+ }>]>>;
1587
+ }, z.core.$loose>;
1588
+ type ConnectionConfig = z.infer<typeof connectionConfigSchema>;
1589
+ /**
1590
+ * Everything that controls **how the widget looks and behaves** —
1591
+ * the UX surface a dashboard / customer-success operator would
1592
+ * configure. The backend pushes this same shape on
1593
+ * `/pai/handshake` (under `config`); the dev configurator lets
1594
+ * you edit it in real time.
1595
+ *
1596
+ * Composed from the section schemas under `./widget/*` so the
1597
+ * dashboard form has obvious tabs without extra metadata.
1598
+ */
1599
+ declare const widgetSettingsSchema: z.ZodObject<{
1600
+ presentation: z.ZodOptional<z.ZodObject<{
1601
+ mode: z.ZodDefault<z.ZodEnum<{
1602
+ floating: "floating";
1603
+ inline: "inline";
1604
+ standalone: "standalone";
1605
+ page: "page";
1606
+ modal: "modal";
1607
+ drawer: "drawer";
1608
+ }>>;
1609
+ position: z.ZodDefault<z.ZodEnum<{
1610
+ "bottom-right": "bottom-right";
1611
+ "bottom-left": "bottom-left";
1612
+ "top-right": "top-right";
1613
+ "top-left": "top-left";
1614
+ }>>;
1615
+ iframe: z.ZodDefault<z.ZodBoolean>;
1616
+ size: z.ZodOptional<z.ZodObject<{
1617
+ width: z.ZodOptional<z.ZodString>;
1618
+ height: z.ZodOptional<z.ZodString>;
1619
+ expanded: z.ZodOptional<z.ZodObject<{
1620
+ width: z.ZodOptional<z.ZodString>;
1621
+ height: z.ZodOptional<z.ZodString>;
1622
+ }, z.core.$loose>>;
1623
+ resize: z.ZodOptional<z.ZodObject<{
1624
+ enabled: z.ZodDefault<z.ZodBoolean>;
1625
+ minWidth: z.ZodOptional<z.ZodString>;
1626
+ maxWidth: z.ZodOptional<z.ZodString>;
1627
+ minHeight: z.ZodOptional<z.ZodString>;
1628
+ maxHeight: z.ZodOptional<z.ZodString>;
1629
+ }, z.core.$loose>>;
1630
+ inset: z.ZodOptional<z.ZodString>;
1631
+ initialSize: z.ZodDefault<z.ZodEnum<{
1632
+ fullscreen: "fullscreen";
1633
+ expanded: "expanded";
1634
+ normal: "normal";
1635
+ auto: "auto";
1636
+ }>>;
1637
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
1638
+ }, z.core.$loose>>;
1639
+ }, z.core.$loose>>;
1640
+ behavior: z.ZodOptional<z.ZodObject<{
1641
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
1642
+ responseMode: z.ZodDefault<z.ZodEnum<{
1643
+ streaming: "streaming";
1644
+ buffered: "buffered";
1645
+ }>>;
1646
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
1647
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
1648
+ showSources: z.ZodDefault<z.ZodBoolean>;
1649
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
1650
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
1651
+ }, z.core.$loose>>;
1652
+ theme: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
1653
+ auto: "auto";
1654
+ light: "light";
1655
+ dark: "dark";
1656
+ }>, z.ZodObject<{
1657
+ accent: z.ZodOptional<z.ZodString>;
1658
+ accentText: z.ZodOptional<z.ZodString>;
1659
+ radius: z.ZodOptional<z.ZodString>;
1660
+ fontFamily: z.ZodOptional<z.ZodString>;
1661
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
1662
+ }, z.core.$loose>]>>;
1663
+ launcher: z.ZodOptional<z.ZodObject<{
1664
+ variant: z.ZodDefault<z.ZodEnum<{
1665
+ circle: "circle";
1666
+ pill: "pill";
1667
+ bar: "bar";
1668
+ minimal: "minimal";
1669
+ }>>;
1670
+ size: z.ZodDefault<z.ZodEnum<{
1671
+ sm: "sm";
1672
+ md: "md";
1673
+ lg: "lg";
1674
+ }>>;
1675
+ label: z.ZodOptional<z.ZodString>;
1676
+ icon: z.ZodOptional<z.ZodString>;
1677
+ hidden: z.ZodDefault<z.ZodBoolean>;
1678
+ callout: z.ZodOptional<z.ZodObject<{
1679
+ text: z.ZodDefault<z.ZodString>;
1680
+ shape: z.ZodDefault<z.ZodEnum<{
1681
+ pill: "pill";
1682
+ bubble: "bubble";
1683
+ callout: "callout";
1684
+ }>>;
1685
+ position: z.ZodDefault<z.ZodEnum<{
1686
+ auto: "auto";
1687
+ horizontal: "horizontal";
1688
+ vertical: "vertical";
1689
+ }>>;
1690
+ delayMs: z.ZodDefault<z.ZodNumber>;
1691
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
1692
+ animated: z.ZodDefault<z.ZodBoolean>;
1693
+ persistent: z.ZodDefault<z.ZodBoolean>;
1694
+ }, z.core.$loose>>;
1695
+ }, z.core.$loose>>;
1696
+ header: z.ZodOptional<z.ZodObject<{
1697
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
1698
+ close: "close";
1699
+ expand: "expand";
1700
+ fullscreen: "fullscreen";
1701
+ clear: "clear";
1702
+ theme: "theme";
1703
+ sound: "sound";
1704
+ history: "history";
1705
+ language: "language";
1706
+ textSize: "textSize";
1707
+ }>>>;
1708
+ }, z.core.$loose>>;
1709
+ composer: z.ZodOptional<z.ZodObject<{
1710
+ sendButton: z.ZodOptional<z.ZodObject<{
1711
+ shape: z.ZodDefault<z.ZodEnum<{
1712
+ circle: "circle";
1713
+ pill: "pill";
1714
+ square: "square";
1715
+ }>>;
1716
+ icon: z.ZodDefault<z.ZodEnum<{
1717
+ send: "send";
1718
+ arrowUp: "arrowUp";
1719
+ paperPlane: "paperPlane";
1720
+ chevron: "chevron";
1721
+ }>>;
1722
+ variant: z.ZodDefault<z.ZodEnum<{
1723
+ filled: "filled";
1724
+ outline: "outline";
1725
+ ghost: "ghost";
1726
+ }>>;
1727
+ }, z.core.$loose>>;
1728
+ attachments: z.ZodOptional<z.ZodObject<{
1729
+ maxBytes: z.ZodDefault<z.ZodNumber>;
1730
+ maxCount: z.ZodDefault<z.ZodNumber>;
1731
+ accept: z.ZodDefault<z.ZodString>;
1732
+ }, z.core.$loose>>;
1733
+ }, z.core.$loose>>;
1734
+ feedback: z.ZodOptional<z.ZodObject<{
1735
+ sound: z.ZodOptional<z.ZodObject<{
1736
+ enabled: z.ZodDefault<z.ZodBoolean>;
1737
+ volume: z.ZodDefault<z.ZodNumber>;
1738
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
1739
+ voiceStart: "voiceStart";
1740
+ voiceStop: "voiceStop";
1741
+ error: "error";
1742
+ messageReceived: "messageReceived";
1743
+ messageSent: "messageSent";
1744
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
1745
+ }, z.core.$loose>>;
1746
+ haptics: z.ZodOptional<z.ZodObject<{
1747
+ enabled: z.ZodDefault<z.ZodBoolean>;
1748
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
1749
+ voiceStart: "voiceStart";
1750
+ voiceStop: "voiceStop";
1751
+ error: "error";
1752
+ messageReceived: "messageReceived";
1753
+ messageSent: "messageSent";
1754
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
1755
+ }, z.core.$loose>>;
1756
+ }, z.core.$loose>>;
1757
+ i18n: z.ZodOptional<z.ZodObject<{
1758
+ locale: z.ZodOptional<z.ZodString>;
1759
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
1760
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
1761
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
1762
+ }, z.core.$loose>>;
1763
+ footer: z.ZodOptional<z.ZodObject<{
1764
+ poweredBy: z.ZodOptional<z.ZodObject<{
1765
+ text: z.ZodOptional<z.ZodString>;
1766
+ href: z.ZodOptional<z.ZodURL>;
1767
+ logoUrl: z.ZodOptional<z.ZodURL>;
1768
+ }, z.core.$loose>>;
1769
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
1770
+ }, z.core.$loose>>;
1771
+ features: z.ZodOptional<z.ZodObject<{
1772
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
1773
+ voice: z.ZodDefault<z.ZodEnum<{
1774
+ local: "local";
1775
+ server: "server";
1776
+ disabled: "disabled";
1777
+ }>>;
1778
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
1779
+ code: z.ZodString;
1780
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1781
+ }, z.core.$loose>]>>>;
1782
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
1783
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
1784
+ }, z.core.$loose>>;
1785
+ forms: z.ZodOptional<z.ZodArray<z.ZodObject<{
1786
+ id: z.ZodString;
1787
+ on: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
1788
+ when: z.ZodOptional<z.ZodObject<{
1789
+ missingContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
1790
+ pageArea: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
1791
+ minMessages: z.ZodOptional<z.ZodNumber>;
1792
+ maxMessages: z.ZodOptional<z.ZodNumber>;
1793
+ }, z.core.$loose>>;
1794
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
1795
+ name: z.ZodString;
1796
+ label: z.ZodString;
1797
+ type: z.ZodEnum<{
1798
+ number: "number";
1799
+ url: "url";
1800
+ email: "email";
1801
+ date: "date";
1802
+ text: "text";
1803
+ tel: "tel";
1804
+ time: "time";
1805
+ textarea: "textarea";
1806
+ select: "select";
1807
+ radio: "radio";
1808
+ checkbox: "checkbox";
1809
+ multiselect: "multiselect";
1810
+ }>;
1811
+ placeholder: z.ZodOptional<z.ZodString>;
1812
+ required: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1813
+ defaultValue: z.ZodOptional<z.ZodString>;
1814
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
1815
+ value: z.ZodString;
1816
+ label: z.ZodOptional<z.ZodString>;
1817
+ description: z.ZodOptional<z.ZodString>;
1818
+ }, z.core.$loose>>>;
1819
+ validation: z.ZodOptional<z.ZodObject<{
1820
+ pattern: z.ZodOptional<z.ZodString>;
1821
+ minLength: z.ZodOptional<z.ZodNumber>;
1822
+ maxLength: z.ZodOptional<z.ZodNumber>;
1823
+ min: z.ZodOptional<z.ZodNumber>;
1824
+ max: z.ZodOptional<z.ZodNumber>;
1825
+ minSelections: z.ZodOptional<z.ZodNumber>;
1826
+ maxSelections: z.ZodOptional<z.ZodNumber>;
1827
+ }, z.core.$loose>>;
1828
+ allowOther: z.ZodOptional<z.ZodBoolean>;
1829
+ validationHint: z.ZodOptional<z.ZodString>;
1830
+ }, z.core.$loose>>>;
1831
+ title: z.ZodOptional<z.ZodString>;
1832
+ description: z.ZodOptional<z.ZodString>;
1833
+ submitLabel: z.ZodOptional<z.ZodString>;
1834
+ skippable: z.ZodDefault<z.ZodBoolean>;
1835
+ frequency: z.ZodDefault<z.ZodEnum<{
1836
+ once: "once";
1837
+ conversation: "conversation";
1838
+ always: "always";
1839
+ }>>;
1840
+ mirrorToContext: z.ZodDefault<z.ZodBoolean>;
1841
+ reopenable: z.ZodDefault<z.ZodBoolean>;
1842
+ reviewable: z.ZodDefault<z.ZodBoolean>;
1843
+ defaultLocale: z.ZodOptional<z.ZodString>;
1844
+ translations: z.ZodOptional<z.ZodArray<z.ZodObject<{
1845
+ locale: z.ZodString;
1846
+ title: z.ZodOptional<z.ZodString>;
1847
+ description: z.ZodOptional<z.ZodString>;
1848
+ submitLabel: z.ZodOptional<z.ZodString>;
1849
+ fields: z.ZodOptional<z.ZodArray<z.ZodObject<{
1850
+ name: z.ZodString;
1851
+ label: z.ZodOptional<z.ZodString>;
1852
+ placeholder: z.ZodOptional<z.ZodString>;
1853
+ validationHint: z.ZodOptional<z.ZodString>;
1854
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
1855
+ value: z.ZodString;
1856
+ label: z.ZodOptional<z.ZodString>;
1857
+ description: z.ZodOptional<z.ZodString>;
1858
+ }, z.core.$loose>>>;
1859
+ }, z.core.$loose>>>;
1860
+ }, z.core.$loose>>>;
1861
+ }, z.core.$loose>>>;
1862
+ modules: z.ZodOptional<z.ZodArray<z.ZodObject<{
1863
+ label: z.ZodString;
1864
+ layout: z.ZodEnum<{
1865
+ home: "home";
1866
+ chat: "chat";
1867
+ help: "help";
1868
+ news: "news";
1869
+ }>;
1870
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1871
+ id: z.ZodOptional<z.ZodString>;
1872
+ brandName: z.ZodOptional<z.ZodString>;
1873
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
1874
+ greetingText: z.ZodOptional<z.ZodString>;
1875
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
1876
+ name: z.ZodString;
1877
+ avatar: z.ZodOptional<z.ZodString>;
1878
+ role: z.ZodOptional<z.ZodString>;
1879
+ }, z.core.$loose>>>;
1880
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
1881
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
1882
+ status: z.ZodOptional<z.ZodObject<{
1883
+ text: z.ZodOptional<z.ZodString>;
1884
+ level: z.ZodOptional<z.ZodString>;
1885
+ url: z.ZodOptional<z.ZodString>;
1886
+ }, z.core.$strip>>;
1887
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
1888
+ }, z.core.$loose>>>;
1889
+ tracking: z.ZodOptional<z.ZodObject<{
1890
+ enabled: z.ZodOptional<z.ZodBoolean>;
1891
+ endpoint: z.ZodOptional<z.ZodURL>;
1892
+ sampleRate: z.ZodOptional<z.ZodNumber>;
1893
+ token: z.ZodOptional<z.ZodString>;
1894
+ }, z.core.$loose>>;
1895
+ }, z.core.$loose>;
1896
+ type WidgetSettings = z.infer<typeof widgetSettingsSchema>;
1897
+ /**
1898
+ * Full client widget config — connection + widget settings + page-mode
1899
+ * extras. The dashboard / dev configurator typically only edits one
1900
+ * of the two halves at a time (`widgetSettingsSchema` for the dashboard
1901
+ * surface, `connectionConfigSchema` for the developer-facing fields).
1902
+ */
1903
+ declare const widgetConfigSchema: z.ZodObject<{
1904
+ widgetId: z.ZodDefault<z.ZodString>;
1905
+ publicKey: z.ZodOptional<z.ZodString>;
1906
+ aiAgentDeploymentId: z.ZodOptional<z.ZodString>;
1907
+ baseUrl: z.ZodOptional<z.ZodString>;
1908
+ agentApiBaseUrl: z.ZodOptional<z.ZodString>;
1909
+ dataApiBaseUrl: z.ZodOptional<z.ZodString>;
1910
+ userContext: z.ZodOptional<z.ZodObject<{
1911
+ id: z.ZodOptional<z.ZodString>;
1912
+ email: z.ZodOptional<z.ZodString>;
1913
+ name: z.ZodOptional<z.ZodString>;
1914
+ plan: z.ZodOptional<z.ZodString>;
1915
+ role: z.ZodOptional<z.ZodString>;
1916
+ phone: z.ZodOptional<z.ZodString>;
1917
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
1918
+ pageContext: z.ZodOptional<z.ZodObject<{
1919
+ area: z.ZodOptional<z.ZodString>;
1920
+ url: z.ZodOptional<z.ZodString>;
1921
+ path: z.ZodOptional<z.ZodString>;
1922
+ title: z.ZodOptional<z.ZodString>;
1923
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
1924
+ endpoints: z.ZodOptional<z.ZodObject<{
1925
+ upload: z.ZodDefault<z.ZodString>;
1926
+ transcribe: z.ZodDefault<z.ZodString>;
1927
+ submitForm: z.ZodDefault<z.ZodString>;
1928
+ }, z.core.$loose>>;
1929
+ debug: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
1930
+ error: "error";
1931
+ off: "off";
1932
+ warn: "warn";
1933
+ info: "info";
1934
+ debug: "debug";
1935
+ trace: "trace";
1936
+ }>]>>;
1937
+ site: z.ZodOptional<z.ZodUnknown>;
1938
+ blocks: z.ZodOptional<z.ZodUnknown>;
1939
+ presentation: z.ZodOptional<z.ZodObject<{
1940
+ mode: z.ZodDefault<z.ZodEnum<{
1941
+ floating: "floating";
1942
+ inline: "inline";
1943
+ standalone: "standalone";
1944
+ page: "page";
1945
+ modal: "modal";
1946
+ drawer: "drawer";
1947
+ }>>;
1948
+ position: z.ZodDefault<z.ZodEnum<{
1949
+ "bottom-right": "bottom-right";
1950
+ "bottom-left": "bottom-left";
1951
+ "top-right": "top-right";
1952
+ "top-left": "top-left";
1953
+ }>>;
1954
+ iframe: z.ZodDefault<z.ZodBoolean>;
1955
+ size: z.ZodOptional<z.ZodObject<{
1956
+ width: z.ZodOptional<z.ZodString>;
1957
+ height: z.ZodOptional<z.ZodString>;
1958
+ expanded: z.ZodOptional<z.ZodObject<{
1959
+ width: z.ZodOptional<z.ZodString>;
1960
+ height: z.ZodOptional<z.ZodString>;
1961
+ }, z.core.$loose>>;
1962
+ resize: z.ZodOptional<z.ZodObject<{
1963
+ enabled: z.ZodDefault<z.ZodBoolean>;
1964
+ minWidth: z.ZodOptional<z.ZodString>;
1965
+ maxWidth: z.ZodOptional<z.ZodString>;
1966
+ minHeight: z.ZodOptional<z.ZodString>;
1967
+ maxHeight: z.ZodOptional<z.ZodString>;
1968
+ }, z.core.$loose>>;
1969
+ inset: z.ZodOptional<z.ZodString>;
1970
+ initialSize: z.ZodDefault<z.ZodEnum<{
1971
+ fullscreen: "fullscreen";
1972
+ expanded: "expanded";
1973
+ normal: "normal";
1974
+ auto: "auto";
1975
+ }>>;
1976
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
1977
+ }, z.core.$loose>>;
1978
+ }, z.core.$loose>>;
1979
+ behavior: z.ZodOptional<z.ZodObject<{
1980
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
1981
+ responseMode: z.ZodDefault<z.ZodEnum<{
1982
+ streaming: "streaming";
1983
+ buffered: "buffered";
1984
+ }>>;
1985
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
1986
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
1987
+ showSources: z.ZodDefault<z.ZodBoolean>;
1988
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
1989
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
1990
+ }, z.core.$loose>>;
1991
+ theme: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
1992
+ auto: "auto";
1993
+ light: "light";
1994
+ dark: "dark";
1995
+ }>, z.ZodObject<{
1996
+ accent: z.ZodOptional<z.ZodString>;
1997
+ accentText: z.ZodOptional<z.ZodString>;
1998
+ radius: z.ZodOptional<z.ZodString>;
1999
+ fontFamily: z.ZodOptional<z.ZodString>;
2000
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
2001
+ }, z.core.$loose>]>>;
2002
+ launcher: z.ZodOptional<z.ZodObject<{
2003
+ variant: z.ZodDefault<z.ZodEnum<{
2004
+ circle: "circle";
2005
+ pill: "pill";
2006
+ bar: "bar";
2007
+ minimal: "minimal";
2008
+ }>>;
2009
+ size: z.ZodDefault<z.ZodEnum<{
2010
+ sm: "sm";
2011
+ md: "md";
2012
+ lg: "lg";
2013
+ }>>;
2014
+ label: z.ZodOptional<z.ZodString>;
2015
+ icon: z.ZodOptional<z.ZodString>;
2016
+ hidden: z.ZodDefault<z.ZodBoolean>;
2017
+ callout: z.ZodOptional<z.ZodObject<{
2018
+ text: z.ZodDefault<z.ZodString>;
2019
+ shape: z.ZodDefault<z.ZodEnum<{
2020
+ pill: "pill";
2021
+ bubble: "bubble";
2022
+ callout: "callout";
2023
+ }>>;
2024
+ position: z.ZodDefault<z.ZodEnum<{
2025
+ auto: "auto";
2026
+ horizontal: "horizontal";
2027
+ vertical: "vertical";
2028
+ }>>;
2029
+ delayMs: z.ZodDefault<z.ZodNumber>;
2030
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
2031
+ animated: z.ZodDefault<z.ZodBoolean>;
2032
+ persistent: z.ZodDefault<z.ZodBoolean>;
2033
+ }, z.core.$loose>>;
2034
+ }, z.core.$loose>>;
2035
+ header: z.ZodOptional<z.ZodObject<{
2036
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
2037
+ close: "close";
2038
+ expand: "expand";
2039
+ fullscreen: "fullscreen";
2040
+ clear: "clear";
2041
+ theme: "theme";
2042
+ sound: "sound";
2043
+ history: "history";
2044
+ language: "language";
2045
+ textSize: "textSize";
2046
+ }>>>;
2047
+ }, z.core.$loose>>;
2048
+ composer: z.ZodOptional<z.ZodObject<{
2049
+ sendButton: z.ZodOptional<z.ZodObject<{
2050
+ shape: z.ZodDefault<z.ZodEnum<{
2051
+ circle: "circle";
2052
+ pill: "pill";
2053
+ square: "square";
2054
+ }>>;
2055
+ icon: z.ZodDefault<z.ZodEnum<{
2056
+ send: "send";
2057
+ arrowUp: "arrowUp";
2058
+ paperPlane: "paperPlane";
2059
+ chevron: "chevron";
2060
+ }>>;
2061
+ variant: z.ZodDefault<z.ZodEnum<{
2062
+ filled: "filled";
2063
+ outline: "outline";
2064
+ ghost: "ghost";
2065
+ }>>;
2066
+ }, z.core.$loose>>;
2067
+ attachments: z.ZodOptional<z.ZodObject<{
2068
+ maxBytes: z.ZodDefault<z.ZodNumber>;
2069
+ maxCount: z.ZodDefault<z.ZodNumber>;
2070
+ accept: z.ZodDefault<z.ZodString>;
2071
+ }, z.core.$loose>>;
2072
+ }, z.core.$loose>>;
2073
+ feedback: z.ZodOptional<z.ZodObject<{
2074
+ sound: z.ZodOptional<z.ZodObject<{
2075
+ enabled: z.ZodDefault<z.ZodBoolean>;
2076
+ volume: z.ZodDefault<z.ZodNumber>;
2077
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2078
+ voiceStart: "voiceStart";
2079
+ voiceStop: "voiceStop";
2080
+ error: "error";
2081
+ messageReceived: "messageReceived";
2082
+ messageSent: "messageSent";
2083
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
2084
+ }, z.core.$loose>>;
2085
+ haptics: z.ZodOptional<z.ZodObject<{
2086
+ enabled: z.ZodDefault<z.ZodBoolean>;
2087
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2088
+ voiceStart: "voiceStart";
2089
+ voiceStop: "voiceStop";
2090
+ error: "error";
2091
+ messageReceived: "messageReceived";
2092
+ messageSent: "messageSent";
2093
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
2094
+ }, z.core.$loose>>;
2095
+ }, z.core.$loose>>;
2096
+ i18n: z.ZodOptional<z.ZodObject<{
2097
+ locale: z.ZodOptional<z.ZodString>;
2098
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
2099
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
2100
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
2101
+ }, z.core.$loose>>;
2102
+ footer: z.ZodOptional<z.ZodObject<{
2103
+ poweredBy: z.ZodOptional<z.ZodObject<{
2104
+ text: z.ZodOptional<z.ZodString>;
2105
+ href: z.ZodOptional<z.ZodURL>;
2106
+ logoUrl: z.ZodOptional<z.ZodURL>;
2107
+ }, z.core.$loose>>;
2108
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
2109
+ }, z.core.$loose>>;
2110
+ features: z.ZodOptional<z.ZodObject<{
2111
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
2112
+ voice: z.ZodDefault<z.ZodEnum<{
2113
+ local: "local";
2114
+ server: "server";
2115
+ disabled: "disabled";
2116
+ }>>;
2117
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
2118
+ code: z.ZodString;
2119
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2120
+ }, z.core.$loose>]>>>;
2121
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
2122
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
2123
+ }, z.core.$loose>>;
2124
+ forms: z.ZodOptional<z.ZodArray<z.ZodObject<{
2125
+ id: z.ZodString;
2126
+ on: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
2127
+ when: z.ZodOptional<z.ZodObject<{
2128
+ missingContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
2129
+ pageArea: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
2130
+ minMessages: z.ZodOptional<z.ZodNumber>;
2131
+ maxMessages: z.ZodOptional<z.ZodNumber>;
2132
+ }, z.core.$loose>>;
2133
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
2134
+ name: z.ZodString;
2135
+ label: z.ZodString;
2136
+ type: z.ZodEnum<{
2137
+ number: "number";
2138
+ url: "url";
2139
+ email: "email";
2140
+ date: "date";
2141
+ text: "text";
2142
+ tel: "tel";
2143
+ time: "time";
2144
+ textarea: "textarea";
2145
+ select: "select";
2146
+ radio: "radio";
2147
+ checkbox: "checkbox";
2148
+ multiselect: "multiselect";
2149
+ }>;
2150
+ placeholder: z.ZodOptional<z.ZodString>;
2151
+ required: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2152
+ defaultValue: z.ZodOptional<z.ZodString>;
2153
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2154
+ value: z.ZodString;
2155
+ label: z.ZodOptional<z.ZodString>;
2156
+ description: z.ZodOptional<z.ZodString>;
2157
+ }, z.core.$loose>>>;
2158
+ validation: z.ZodOptional<z.ZodObject<{
2159
+ pattern: z.ZodOptional<z.ZodString>;
2160
+ minLength: z.ZodOptional<z.ZodNumber>;
2161
+ maxLength: z.ZodOptional<z.ZodNumber>;
2162
+ min: z.ZodOptional<z.ZodNumber>;
2163
+ max: z.ZodOptional<z.ZodNumber>;
2164
+ minSelections: z.ZodOptional<z.ZodNumber>;
2165
+ maxSelections: z.ZodOptional<z.ZodNumber>;
2166
+ }, z.core.$loose>>;
2167
+ allowOther: z.ZodOptional<z.ZodBoolean>;
2168
+ validationHint: z.ZodOptional<z.ZodString>;
2169
+ }, z.core.$loose>>>;
2170
+ title: z.ZodOptional<z.ZodString>;
2171
+ description: z.ZodOptional<z.ZodString>;
2172
+ submitLabel: z.ZodOptional<z.ZodString>;
2173
+ skippable: z.ZodDefault<z.ZodBoolean>;
2174
+ frequency: z.ZodDefault<z.ZodEnum<{
2175
+ once: "once";
2176
+ conversation: "conversation";
2177
+ always: "always";
2178
+ }>>;
2179
+ mirrorToContext: z.ZodDefault<z.ZodBoolean>;
2180
+ reopenable: z.ZodDefault<z.ZodBoolean>;
2181
+ reviewable: z.ZodDefault<z.ZodBoolean>;
2182
+ defaultLocale: z.ZodOptional<z.ZodString>;
2183
+ translations: z.ZodOptional<z.ZodArray<z.ZodObject<{
2184
+ locale: z.ZodString;
2185
+ title: z.ZodOptional<z.ZodString>;
2186
+ description: z.ZodOptional<z.ZodString>;
2187
+ submitLabel: z.ZodOptional<z.ZodString>;
2188
+ fields: z.ZodOptional<z.ZodArray<z.ZodObject<{
2189
+ name: z.ZodString;
2190
+ label: z.ZodOptional<z.ZodString>;
2191
+ placeholder: z.ZodOptional<z.ZodString>;
2192
+ validationHint: z.ZodOptional<z.ZodString>;
2193
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2194
+ value: z.ZodString;
2195
+ label: z.ZodOptional<z.ZodString>;
2196
+ description: z.ZodOptional<z.ZodString>;
2197
+ }, z.core.$loose>>>;
2198
+ }, z.core.$loose>>>;
2199
+ }, z.core.$loose>>>;
2200
+ }, z.core.$loose>>>;
2201
+ modules: z.ZodOptional<z.ZodArray<z.ZodObject<{
2202
+ label: z.ZodString;
2203
+ layout: z.ZodEnum<{
2204
+ home: "home";
2205
+ chat: "chat";
2206
+ help: "help";
2207
+ news: "news";
2208
+ }>;
2209
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2210
+ id: z.ZodOptional<z.ZodString>;
2211
+ brandName: z.ZodOptional<z.ZodString>;
2212
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
2213
+ greetingText: z.ZodOptional<z.ZodString>;
2214
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
2215
+ name: z.ZodString;
2216
+ avatar: z.ZodOptional<z.ZodString>;
2217
+ role: z.ZodOptional<z.ZodString>;
2218
+ }, z.core.$loose>>>;
2219
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
2220
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
2221
+ status: z.ZodOptional<z.ZodObject<{
2222
+ text: z.ZodOptional<z.ZodString>;
2223
+ level: z.ZodOptional<z.ZodString>;
2224
+ url: z.ZodOptional<z.ZodString>;
2225
+ }, z.core.$strip>>;
2226
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
2227
+ }, z.core.$loose>>>;
2228
+ tracking: z.ZodOptional<z.ZodObject<{
2229
+ enabled: z.ZodOptional<z.ZodBoolean>;
2230
+ endpoint: z.ZodOptional<z.ZodURL>;
2231
+ sampleRate: z.ZodOptional<z.ZodNumber>;
2232
+ token: z.ZodOptional<z.ZodString>;
2233
+ }, z.core.$loose>>;
2234
+ }, z.core.$loose>;
2235
+ type WidgetConfig = z.infer<typeof widgetConfigSchema>;
2236
+ /**
2237
+ * Partial schema — used when validating server-pushed patches that
2238
+ * override individual fields on top of the resolved config. Every field
2239
+ * becomes optional; defaults are NOT applied.
2240
+ */
2241
+ declare const widgetConfigPartialSchema: z.ZodObject<{
2242
+ widgetId: z.ZodOptional<z.ZodDefault<z.ZodString>>;
2243
+ publicKey: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2244
+ aiAgentDeploymentId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2245
+ baseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2246
+ agentApiBaseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2247
+ dataApiBaseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2248
+ userContext: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2249
+ id: z.ZodOptional<z.ZodString>;
2250
+ email: z.ZodOptional<z.ZodString>;
2251
+ name: z.ZodOptional<z.ZodString>;
2252
+ plan: z.ZodOptional<z.ZodString>;
2253
+ role: z.ZodOptional<z.ZodString>;
2254
+ phone: z.ZodOptional<z.ZodString>;
2255
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>>;
2256
+ pageContext: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2257
+ area: z.ZodOptional<z.ZodString>;
2258
+ url: z.ZodOptional<z.ZodString>;
2259
+ path: z.ZodOptional<z.ZodString>;
2260
+ title: z.ZodOptional<z.ZodString>;
2261
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>>;
2262
+ endpoints: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2263
+ upload: z.ZodDefault<z.ZodString>;
2264
+ transcribe: z.ZodDefault<z.ZodString>;
2265
+ submitForm: z.ZodDefault<z.ZodString>;
2266
+ }, z.core.$loose>>>;
2267
+ debug: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
2268
+ error: "error";
2269
+ off: "off";
2270
+ warn: "warn";
2271
+ info: "info";
2272
+ debug: "debug";
2273
+ trace: "trace";
2274
+ }>]>>>;
2275
+ site: z.ZodOptional<z.ZodOptional<z.ZodUnknown>>;
2276
+ blocks: z.ZodOptional<z.ZodOptional<z.ZodUnknown>>;
2277
+ presentation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2278
+ mode: z.ZodDefault<z.ZodEnum<{
2279
+ floating: "floating";
2280
+ inline: "inline";
2281
+ standalone: "standalone";
2282
+ page: "page";
2283
+ modal: "modal";
2284
+ drawer: "drawer";
2285
+ }>>;
2286
+ position: z.ZodDefault<z.ZodEnum<{
2287
+ "bottom-right": "bottom-right";
2288
+ "bottom-left": "bottom-left";
2289
+ "top-right": "top-right";
2290
+ "top-left": "top-left";
2291
+ }>>;
2292
+ iframe: z.ZodDefault<z.ZodBoolean>;
2293
+ size: z.ZodOptional<z.ZodObject<{
2294
+ width: z.ZodOptional<z.ZodString>;
2295
+ height: z.ZodOptional<z.ZodString>;
2296
+ expanded: z.ZodOptional<z.ZodObject<{
2297
+ width: z.ZodOptional<z.ZodString>;
2298
+ height: z.ZodOptional<z.ZodString>;
2299
+ }, z.core.$loose>>;
2300
+ resize: z.ZodOptional<z.ZodObject<{
2301
+ enabled: z.ZodDefault<z.ZodBoolean>;
2302
+ minWidth: z.ZodOptional<z.ZodString>;
2303
+ maxWidth: z.ZodOptional<z.ZodString>;
2304
+ minHeight: z.ZodOptional<z.ZodString>;
2305
+ maxHeight: z.ZodOptional<z.ZodString>;
2306
+ }, z.core.$loose>>;
2307
+ inset: z.ZodOptional<z.ZodString>;
2308
+ initialSize: z.ZodDefault<z.ZodEnum<{
2309
+ fullscreen: "fullscreen";
2310
+ expanded: "expanded";
2311
+ normal: "normal";
2312
+ auto: "auto";
2313
+ }>>;
2314
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
2315
+ }, z.core.$loose>>;
2316
+ }, z.core.$loose>>>;
2317
+ behavior: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2318
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
2319
+ responseMode: z.ZodDefault<z.ZodEnum<{
2320
+ streaming: "streaming";
2321
+ buffered: "buffered";
2322
+ }>>;
2323
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
2324
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
2325
+ showSources: z.ZodDefault<z.ZodBoolean>;
2326
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
2327
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
2328
+ }, z.core.$loose>>>;
2329
+ theme: z.ZodOptional<z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
2330
+ auto: "auto";
2331
+ light: "light";
2332
+ dark: "dark";
2333
+ }>, z.ZodObject<{
2334
+ accent: z.ZodOptional<z.ZodString>;
2335
+ accentText: z.ZodOptional<z.ZodString>;
2336
+ radius: z.ZodOptional<z.ZodString>;
2337
+ fontFamily: z.ZodOptional<z.ZodString>;
2338
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
2339
+ }, z.core.$loose>]>>>;
2340
+ launcher: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2341
+ variant: z.ZodDefault<z.ZodEnum<{
2342
+ circle: "circle";
2343
+ pill: "pill";
2344
+ bar: "bar";
2345
+ minimal: "minimal";
2346
+ }>>;
2347
+ size: z.ZodDefault<z.ZodEnum<{
2348
+ sm: "sm";
2349
+ md: "md";
2350
+ lg: "lg";
2351
+ }>>;
2352
+ label: z.ZodOptional<z.ZodString>;
2353
+ icon: z.ZodOptional<z.ZodString>;
2354
+ hidden: z.ZodDefault<z.ZodBoolean>;
2355
+ callout: z.ZodOptional<z.ZodObject<{
2356
+ text: z.ZodDefault<z.ZodString>;
2357
+ shape: z.ZodDefault<z.ZodEnum<{
2358
+ pill: "pill";
2359
+ bubble: "bubble";
2360
+ callout: "callout";
2361
+ }>>;
2362
+ position: z.ZodDefault<z.ZodEnum<{
2363
+ auto: "auto";
2364
+ horizontal: "horizontal";
2365
+ vertical: "vertical";
2366
+ }>>;
2367
+ delayMs: z.ZodDefault<z.ZodNumber>;
2368
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
2369
+ animated: z.ZodDefault<z.ZodBoolean>;
2370
+ persistent: z.ZodDefault<z.ZodBoolean>;
2371
+ }, z.core.$loose>>;
2372
+ }, z.core.$loose>>>;
2373
+ header: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2374
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
2375
+ close: "close";
2376
+ expand: "expand";
2377
+ fullscreen: "fullscreen";
2378
+ clear: "clear";
2379
+ theme: "theme";
2380
+ sound: "sound";
2381
+ history: "history";
2382
+ language: "language";
2383
+ textSize: "textSize";
2384
+ }>>>;
2385
+ }, z.core.$loose>>>;
2386
+ composer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2387
+ sendButton: z.ZodOptional<z.ZodObject<{
2388
+ shape: z.ZodDefault<z.ZodEnum<{
2389
+ circle: "circle";
2390
+ pill: "pill";
2391
+ square: "square";
2392
+ }>>;
2393
+ icon: z.ZodDefault<z.ZodEnum<{
2394
+ send: "send";
2395
+ arrowUp: "arrowUp";
2396
+ paperPlane: "paperPlane";
2397
+ chevron: "chevron";
2398
+ }>>;
2399
+ variant: z.ZodDefault<z.ZodEnum<{
2400
+ filled: "filled";
2401
+ outline: "outline";
2402
+ ghost: "ghost";
2403
+ }>>;
2404
+ }, z.core.$loose>>;
2405
+ attachments: z.ZodOptional<z.ZodObject<{
2406
+ maxBytes: z.ZodDefault<z.ZodNumber>;
2407
+ maxCount: z.ZodDefault<z.ZodNumber>;
2408
+ accept: z.ZodDefault<z.ZodString>;
2409
+ }, z.core.$loose>>;
2410
+ }, z.core.$loose>>>;
2411
+ feedback: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2412
+ sound: z.ZodOptional<z.ZodObject<{
2413
+ enabled: z.ZodDefault<z.ZodBoolean>;
2414
+ volume: z.ZodDefault<z.ZodNumber>;
2415
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2416
+ voiceStart: "voiceStart";
2417
+ voiceStop: "voiceStop";
2418
+ error: "error";
2419
+ messageReceived: "messageReceived";
2420
+ messageSent: "messageSent";
2421
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
2422
+ }, z.core.$loose>>;
2423
+ haptics: z.ZodOptional<z.ZodObject<{
2424
+ enabled: z.ZodDefault<z.ZodBoolean>;
2425
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2426
+ voiceStart: "voiceStart";
2427
+ voiceStop: "voiceStop";
2428
+ error: "error";
2429
+ messageReceived: "messageReceived";
2430
+ messageSent: "messageSent";
2431
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
2432
+ }, z.core.$loose>>;
2433
+ }, z.core.$loose>>>;
2434
+ i18n: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2435
+ locale: z.ZodOptional<z.ZodString>;
2436
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
2437
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
2438
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
2439
+ }, z.core.$loose>>>;
2440
+ footer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2441
+ poweredBy: z.ZodOptional<z.ZodObject<{
2442
+ text: z.ZodOptional<z.ZodString>;
2443
+ href: z.ZodOptional<z.ZodURL>;
2444
+ logoUrl: z.ZodOptional<z.ZodURL>;
2445
+ }, z.core.$loose>>;
2446
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
2447
+ }, z.core.$loose>>>;
2448
+ features: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2449
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
2450
+ voice: z.ZodDefault<z.ZodEnum<{
2451
+ local: "local";
2452
+ server: "server";
2453
+ disabled: "disabled";
2454
+ }>>;
2455
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
2456
+ code: z.ZodString;
2457
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2458
+ }, z.core.$loose>]>>>;
2459
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
2460
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
2461
+ }, z.core.$loose>>>;
2462
+ forms: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
2463
+ id: z.ZodString;
2464
+ on: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
2465
+ when: z.ZodOptional<z.ZodObject<{
2466
+ missingContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
2467
+ pageArea: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
2468
+ minMessages: z.ZodOptional<z.ZodNumber>;
2469
+ maxMessages: z.ZodOptional<z.ZodNumber>;
2470
+ }, z.core.$loose>>;
2471
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
2472
+ name: z.ZodString;
2473
+ label: z.ZodString;
2474
+ type: z.ZodEnum<{
2475
+ number: "number";
2476
+ url: "url";
2477
+ email: "email";
2478
+ date: "date";
2479
+ text: "text";
2480
+ tel: "tel";
2481
+ time: "time";
2482
+ textarea: "textarea";
2483
+ select: "select";
2484
+ radio: "radio";
2485
+ checkbox: "checkbox";
2486
+ multiselect: "multiselect";
2487
+ }>;
2488
+ placeholder: z.ZodOptional<z.ZodString>;
2489
+ required: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2490
+ defaultValue: z.ZodOptional<z.ZodString>;
2491
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2492
+ value: z.ZodString;
2493
+ label: z.ZodOptional<z.ZodString>;
2494
+ description: z.ZodOptional<z.ZodString>;
2495
+ }, z.core.$loose>>>;
2496
+ validation: z.ZodOptional<z.ZodObject<{
2497
+ pattern: z.ZodOptional<z.ZodString>;
2498
+ minLength: z.ZodOptional<z.ZodNumber>;
2499
+ maxLength: z.ZodOptional<z.ZodNumber>;
2500
+ min: z.ZodOptional<z.ZodNumber>;
2501
+ max: z.ZodOptional<z.ZodNumber>;
2502
+ minSelections: z.ZodOptional<z.ZodNumber>;
2503
+ maxSelections: z.ZodOptional<z.ZodNumber>;
2504
+ }, z.core.$loose>>;
2505
+ allowOther: z.ZodOptional<z.ZodBoolean>;
2506
+ validationHint: z.ZodOptional<z.ZodString>;
2507
+ }, z.core.$loose>>>;
2508
+ title: z.ZodOptional<z.ZodString>;
2509
+ description: z.ZodOptional<z.ZodString>;
2510
+ submitLabel: z.ZodOptional<z.ZodString>;
2511
+ skippable: z.ZodDefault<z.ZodBoolean>;
2512
+ frequency: z.ZodDefault<z.ZodEnum<{
2513
+ once: "once";
2514
+ conversation: "conversation";
2515
+ always: "always";
2516
+ }>>;
2517
+ mirrorToContext: z.ZodDefault<z.ZodBoolean>;
2518
+ reopenable: z.ZodDefault<z.ZodBoolean>;
2519
+ reviewable: z.ZodDefault<z.ZodBoolean>;
2520
+ defaultLocale: z.ZodOptional<z.ZodString>;
2521
+ translations: z.ZodOptional<z.ZodArray<z.ZodObject<{
2522
+ locale: z.ZodString;
2523
+ title: z.ZodOptional<z.ZodString>;
2524
+ description: z.ZodOptional<z.ZodString>;
2525
+ submitLabel: z.ZodOptional<z.ZodString>;
2526
+ fields: z.ZodOptional<z.ZodArray<z.ZodObject<{
2527
+ name: z.ZodString;
2528
+ label: z.ZodOptional<z.ZodString>;
2529
+ placeholder: z.ZodOptional<z.ZodString>;
2530
+ validationHint: z.ZodOptional<z.ZodString>;
2531
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2532
+ value: z.ZodString;
2533
+ label: z.ZodOptional<z.ZodString>;
2534
+ description: z.ZodOptional<z.ZodString>;
2535
+ }, z.core.$loose>>>;
2536
+ }, z.core.$loose>>>;
2537
+ }, z.core.$loose>>>;
2538
+ }, z.core.$loose>>>>;
2539
+ modules: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
2540
+ label: z.ZodString;
2541
+ layout: z.ZodEnum<{
2542
+ home: "home";
2543
+ chat: "chat";
2544
+ help: "help";
2545
+ news: "news";
2546
+ }>;
2547
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2548
+ id: z.ZodOptional<z.ZodString>;
2549
+ brandName: z.ZodOptional<z.ZodString>;
2550
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
2551
+ greetingText: z.ZodOptional<z.ZodString>;
2552
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
2553
+ name: z.ZodString;
2554
+ avatar: z.ZodOptional<z.ZodString>;
2555
+ role: z.ZodOptional<z.ZodString>;
2556
+ }, z.core.$loose>>>;
2557
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
2558
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
2559
+ status: z.ZodOptional<z.ZodObject<{
2560
+ text: z.ZodOptional<z.ZodString>;
2561
+ level: z.ZodOptional<z.ZodString>;
2562
+ url: z.ZodOptional<z.ZodString>;
2563
+ }, z.core.$strip>>;
2564
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
2565
+ }, z.core.$loose>>>>;
2566
+ tracking: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2567
+ enabled: z.ZodOptional<z.ZodBoolean>;
2568
+ endpoint: z.ZodOptional<z.ZodURL>;
2569
+ sampleRate: z.ZodOptional<z.ZodNumber>;
2570
+ token: z.ZodOptional<z.ZodString>;
2571
+ }, z.core.$loose>>>;
2572
+ }, z.core.$loose>;
2573
+ type WidgetConfigPartial = z.infer<typeof widgetConfigPartialSchema>;
2574
+ declare const widgetSettingsPartialSchema: z.ZodObject<{
2575
+ presentation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2576
+ mode: z.ZodDefault<z.ZodEnum<{
2577
+ floating: "floating";
2578
+ inline: "inline";
2579
+ standalone: "standalone";
2580
+ page: "page";
2581
+ modal: "modal";
2582
+ drawer: "drawer";
2583
+ }>>;
2584
+ position: z.ZodDefault<z.ZodEnum<{
2585
+ "bottom-right": "bottom-right";
2586
+ "bottom-left": "bottom-left";
2587
+ "top-right": "top-right";
2588
+ "top-left": "top-left";
2589
+ }>>;
2590
+ iframe: z.ZodDefault<z.ZodBoolean>;
2591
+ size: z.ZodOptional<z.ZodObject<{
2592
+ width: z.ZodOptional<z.ZodString>;
2593
+ height: z.ZodOptional<z.ZodString>;
2594
+ expanded: z.ZodOptional<z.ZodObject<{
2595
+ width: z.ZodOptional<z.ZodString>;
2596
+ height: z.ZodOptional<z.ZodString>;
2597
+ }, z.core.$loose>>;
2598
+ resize: z.ZodOptional<z.ZodObject<{
2599
+ enabled: z.ZodDefault<z.ZodBoolean>;
2600
+ minWidth: z.ZodOptional<z.ZodString>;
2601
+ maxWidth: z.ZodOptional<z.ZodString>;
2602
+ minHeight: z.ZodOptional<z.ZodString>;
2603
+ maxHeight: z.ZodOptional<z.ZodString>;
2604
+ }, z.core.$loose>>;
2605
+ inset: z.ZodOptional<z.ZodString>;
2606
+ initialSize: z.ZodDefault<z.ZodEnum<{
2607
+ fullscreen: "fullscreen";
2608
+ expanded: "expanded";
2609
+ normal: "normal";
2610
+ auto: "auto";
2611
+ }>>;
2612
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
2613
+ }, z.core.$loose>>;
2614
+ }, z.core.$loose>>>;
2615
+ behavior: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2616
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
2617
+ responseMode: z.ZodDefault<z.ZodEnum<{
2618
+ streaming: "streaming";
2619
+ buffered: "buffered";
2620
+ }>>;
2621
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
2622
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
2623
+ showSources: z.ZodDefault<z.ZodBoolean>;
2624
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
2625
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
2626
+ }, z.core.$loose>>>;
2627
+ theme: z.ZodOptional<z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
2628
+ auto: "auto";
2629
+ light: "light";
2630
+ dark: "dark";
2631
+ }>, z.ZodObject<{
2632
+ accent: z.ZodOptional<z.ZodString>;
2633
+ accentText: z.ZodOptional<z.ZodString>;
2634
+ radius: z.ZodOptional<z.ZodString>;
2635
+ fontFamily: z.ZodOptional<z.ZodString>;
2636
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
2637
+ }, z.core.$loose>]>>>;
2638
+ launcher: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2639
+ variant: z.ZodDefault<z.ZodEnum<{
2640
+ circle: "circle";
2641
+ pill: "pill";
2642
+ bar: "bar";
2643
+ minimal: "minimal";
2644
+ }>>;
2645
+ size: z.ZodDefault<z.ZodEnum<{
2646
+ sm: "sm";
2647
+ md: "md";
2648
+ lg: "lg";
2649
+ }>>;
2650
+ label: z.ZodOptional<z.ZodString>;
2651
+ icon: z.ZodOptional<z.ZodString>;
2652
+ hidden: z.ZodDefault<z.ZodBoolean>;
2653
+ callout: z.ZodOptional<z.ZodObject<{
2654
+ text: z.ZodDefault<z.ZodString>;
2655
+ shape: z.ZodDefault<z.ZodEnum<{
2656
+ pill: "pill";
2657
+ bubble: "bubble";
2658
+ callout: "callout";
2659
+ }>>;
2660
+ position: z.ZodDefault<z.ZodEnum<{
2661
+ auto: "auto";
2662
+ horizontal: "horizontal";
2663
+ vertical: "vertical";
2664
+ }>>;
2665
+ delayMs: z.ZodDefault<z.ZodNumber>;
2666
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
2667
+ animated: z.ZodDefault<z.ZodBoolean>;
2668
+ persistent: z.ZodDefault<z.ZodBoolean>;
2669
+ }, z.core.$loose>>;
2670
+ }, z.core.$loose>>>;
2671
+ header: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2672
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
2673
+ close: "close";
2674
+ expand: "expand";
2675
+ fullscreen: "fullscreen";
2676
+ clear: "clear";
2677
+ theme: "theme";
2678
+ sound: "sound";
2679
+ history: "history";
2680
+ language: "language";
2681
+ textSize: "textSize";
2682
+ }>>>;
2683
+ }, z.core.$loose>>>;
2684
+ composer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2685
+ sendButton: z.ZodOptional<z.ZodObject<{
2686
+ shape: z.ZodDefault<z.ZodEnum<{
2687
+ circle: "circle";
2688
+ pill: "pill";
2689
+ square: "square";
2690
+ }>>;
2691
+ icon: z.ZodDefault<z.ZodEnum<{
2692
+ send: "send";
2693
+ arrowUp: "arrowUp";
2694
+ paperPlane: "paperPlane";
2695
+ chevron: "chevron";
2696
+ }>>;
2697
+ variant: z.ZodDefault<z.ZodEnum<{
2698
+ filled: "filled";
2699
+ outline: "outline";
2700
+ ghost: "ghost";
2701
+ }>>;
2702
+ }, z.core.$loose>>;
2703
+ attachments: z.ZodOptional<z.ZodObject<{
2704
+ maxBytes: z.ZodDefault<z.ZodNumber>;
2705
+ maxCount: z.ZodDefault<z.ZodNumber>;
2706
+ accept: z.ZodDefault<z.ZodString>;
2707
+ }, z.core.$loose>>;
2708
+ }, z.core.$loose>>>;
2709
+ feedback: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2710
+ sound: z.ZodOptional<z.ZodObject<{
2711
+ enabled: z.ZodDefault<z.ZodBoolean>;
2712
+ volume: z.ZodDefault<z.ZodNumber>;
2713
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2714
+ voiceStart: "voiceStart";
2715
+ voiceStop: "voiceStop";
2716
+ error: "error";
2717
+ messageReceived: "messageReceived";
2718
+ messageSent: "messageSent";
2719
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
2720
+ }, z.core.$loose>>;
2721
+ haptics: z.ZodOptional<z.ZodObject<{
2722
+ enabled: z.ZodDefault<z.ZodBoolean>;
2723
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
2724
+ voiceStart: "voiceStart";
2725
+ voiceStop: "voiceStop";
2726
+ error: "error";
2727
+ messageReceived: "messageReceived";
2728
+ messageSent: "messageSent";
2729
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
2730
+ }, z.core.$loose>>;
2731
+ }, z.core.$loose>>>;
2732
+ i18n: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2733
+ locale: z.ZodOptional<z.ZodString>;
2734
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
2735
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
2736
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
2737
+ }, z.core.$loose>>>;
2738
+ footer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2739
+ poweredBy: z.ZodOptional<z.ZodObject<{
2740
+ text: z.ZodOptional<z.ZodString>;
2741
+ href: z.ZodOptional<z.ZodURL>;
2742
+ logoUrl: z.ZodOptional<z.ZodURL>;
2743
+ }, z.core.$loose>>;
2744
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
2745
+ }, z.core.$loose>>>;
2746
+ features: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2747
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
2748
+ voice: z.ZodDefault<z.ZodEnum<{
2749
+ local: "local";
2750
+ server: "server";
2751
+ disabled: "disabled";
2752
+ }>>;
2753
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
2754
+ code: z.ZodString;
2755
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2756
+ }, z.core.$loose>]>>>;
2757
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
2758
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
2759
+ }, z.core.$loose>>>;
2760
+ forms: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
2761
+ id: z.ZodString;
2762
+ on: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
2763
+ when: z.ZodOptional<z.ZodObject<{
2764
+ missingContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
2765
+ pageArea: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
2766
+ minMessages: z.ZodOptional<z.ZodNumber>;
2767
+ maxMessages: z.ZodOptional<z.ZodNumber>;
2768
+ }, z.core.$loose>>;
2769
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
2770
+ name: z.ZodString;
2771
+ label: z.ZodString;
2772
+ type: z.ZodEnum<{
2773
+ number: "number";
2774
+ url: "url";
2775
+ email: "email";
2776
+ date: "date";
2777
+ text: "text";
2778
+ tel: "tel";
2779
+ time: "time";
2780
+ textarea: "textarea";
2781
+ select: "select";
2782
+ radio: "radio";
2783
+ checkbox: "checkbox";
2784
+ multiselect: "multiselect";
2785
+ }>;
2786
+ placeholder: z.ZodOptional<z.ZodString>;
2787
+ required: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2788
+ defaultValue: z.ZodOptional<z.ZodString>;
2789
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2790
+ value: z.ZodString;
2791
+ label: z.ZodOptional<z.ZodString>;
2792
+ description: z.ZodOptional<z.ZodString>;
2793
+ }, z.core.$loose>>>;
2794
+ validation: z.ZodOptional<z.ZodObject<{
2795
+ pattern: z.ZodOptional<z.ZodString>;
2796
+ minLength: z.ZodOptional<z.ZodNumber>;
2797
+ maxLength: z.ZodOptional<z.ZodNumber>;
2798
+ min: z.ZodOptional<z.ZodNumber>;
2799
+ max: z.ZodOptional<z.ZodNumber>;
2800
+ minSelections: z.ZodOptional<z.ZodNumber>;
2801
+ maxSelections: z.ZodOptional<z.ZodNumber>;
2802
+ }, z.core.$loose>>;
2803
+ allowOther: z.ZodOptional<z.ZodBoolean>;
2804
+ validationHint: z.ZodOptional<z.ZodString>;
2805
+ }, z.core.$loose>>>;
2806
+ title: z.ZodOptional<z.ZodString>;
2807
+ description: z.ZodOptional<z.ZodString>;
2808
+ submitLabel: z.ZodOptional<z.ZodString>;
2809
+ skippable: z.ZodDefault<z.ZodBoolean>;
2810
+ frequency: z.ZodDefault<z.ZodEnum<{
2811
+ once: "once";
2812
+ conversation: "conversation";
2813
+ always: "always";
2814
+ }>>;
2815
+ mirrorToContext: z.ZodDefault<z.ZodBoolean>;
2816
+ reopenable: z.ZodDefault<z.ZodBoolean>;
2817
+ reviewable: z.ZodDefault<z.ZodBoolean>;
2818
+ defaultLocale: z.ZodOptional<z.ZodString>;
2819
+ translations: z.ZodOptional<z.ZodArray<z.ZodObject<{
2820
+ locale: z.ZodString;
2821
+ title: z.ZodOptional<z.ZodString>;
2822
+ description: z.ZodOptional<z.ZodString>;
2823
+ submitLabel: z.ZodOptional<z.ZodString>;
2824
+ fields: z.ZodOptional<z.ZodArray<z.ZodObject<{
2825
+ name: z.ZodString;
2826
+ label: z.ZodOptional<z.ZodString>;
2827
+ placeholder: z.ZodOptional<z.ZodString>;
2828
+ validationHint: z.ZodOptional<z.ZodString>;
2829
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
2830
+ value: z.ZodString;
2831
+ label: z.ZodOptional<z.ZodString>;
2832
+ description: z.ZodOptional<z.ZodString>;
2833
+ }, z.core.$loose>>>;
2834
+ }, z.core.$loose>>>;
2835
+ }, z.core.$loose>>>;
2836
+ }, z.core.$loose>>>>;
2837
+ modules: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
2838
+ label: z.ZodString;
2839
+ layout: z.ZodEnum<{
2840
+ home: "home";
2841
+ chat: "chat";
2842
+ help: "help";
2843
+ news: "news";
2844
+ }>;
2845
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2846
+ id: z.ZodOptional<z.ZodString>;
2847
+ brandName: z.ZodOptional<z.ZodString>;
2848
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
2849
+ greetingText: z.ZodOptional<z.ZodString>;
2850
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
2851
+ name: z.ZodString;
2852
+ avatar: z.ZodOptional<z.ZodString>;
2853
+ role: z.ZodOptional<z.ZodString>;
2854
+ }, z.core.$loose>>>;
2855
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
2856
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
2857
+ status: z.ZodOptional<z.ZodObject<{
2858
+ text: z.ZodOptional<z.ZodString>;
2859
+ level: z.ZodOptional<z.ZodString>;
2860
+ url: z.ZodOptional<z.ZodString>;
2861
+ }, z.core.$strip>>;
2862
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
2863
+ }, z.core.$loose>>>>;
2864
+ tracking: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2865
+ enabled: z.ZodOptional<z.ZodBoolean>;
2866
+ endpoint: z.ZodOptional<z.ZodURL>;
2867
+ sampleRate: z.ZodOptional<z.ZodNumber>;
2868
+ token: z.ZodOptional<z.ZodString>;
2869
+ }, z.core.$loose>>>;
2870
+ }, z.core.$loose>;
2871
+ type WidgetSettingsPartial = z.infer<typeof widgetSettingsPartialSchema>;
2872
+ declare const connectionConfigPartialSchema: z.ZodObject<{
2873
+ widgetId: z.ZodOptional<z.ZodDefault<z.ZodString>>;
2874
+ publicKey: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2875
+ aiAgentDeploymentId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2876
+ baseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2877
+ agentApiBaseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2878
+ dataApiBaseUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2879
+ userContext: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2880
+ id: z.ZodOptional<z.ZodString>;
2881
+ email: z.ZodOptional<z.ZodString>;
2882
+ name: z.ZodOptional<z.ZodString>;
2883
+ plan: z.ZodOptional<z.ZodString>;
2884
+ role: z.ZodOptional<z.ZodString>;
2885
+ phone: z.ZodOptional<z.ZodString>;
2886
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>>;
2887
+ pageContext: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2888
+ area: z.ZodOptional<z.ZodString>;
2889
+ url: z.ZodOptional<z.ZodString>;
2890
+ path: z.ZodOptional<z.ZodString>;
2891
+ title: z.ZodOptional<z.ZodString>;
2892
+ }, z.core.$catchall<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>>;
2893
+ endpoints: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2894
+ upload: z.ZodDefault<z.ZodString>;
2895
+ transcribe: z.ZodDefault<z.ZodString>;
2896
+ submitForm: z.ZodDefault<z.ZodString>;
2897
+ }, z.core.$loose>>>;
2898
+ debug: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
2899
+ error: "error";
2900
+ off: "off";
2901
+ warn: "warn";
2902
+ info: "info";
2903
+ debug: "debug";
2904
+ trace: "trace";
2905
+ }>]>>>;
2906
+ }, z.core.$loose>;
2907
+ type ConnectionConfigPartial = z.infer<typeof connectionConfigPartialSchema>;
2908
+ //#endregion
2909
+ //#region src/schema/deployment.d.ts
2910
+ /**
2911
+ * Server-pushable widget settings. Same surface as the editable
2912
+ * {@link widgetSettingsSchema} but every field is optional (the server
2913
+ * pushes patches, not full configs). Connection fields (publicKey,
2914
+ * aiAgentDeploymentId, baseUrl, user, iframe) are deliberately
2915
+ * excluded — those are client concerns.
2916
+ *
2917
+ * Two deltas vs the editable surface:
2918
+ * - `forms` is omitted — resolved form definitions are served by the
2919
+ * data-API (`GET /forms`), not pushed on the handshake. A stale
2920
+ * backend still sending `config.forms` passes through `.loose()` and is
2921
+ * ignored by the runtime merge.
2922
+ * - `dataApiBaseUrl` is pushable — lets a deployment point the widget at its
2923
+ * data-API base (adopted only when the host didn't set one).
2924
+ * - `storageVersion` is pushable — a handshake-only force-reset lever (never an
2925
+ * embed attribute / `init` option). Bumping it folds a `.v<version>` segment
2926
+ * into every client-storage key on the next load, abandoning the prior
2927
+ * namespace for all visitors.
2928
+ */
2929
+ declare const serverConfigSchema: z.ZodObject<{
2930
+ presentation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2931
+ mode: z.ZodDefault<z.ZodEnum<{
2932
+ floating: "floating";
2933
+ inline: "inline";
2934
+ standalone: "standalone";
2935
+ page: "page";
2936
+ modal: "modal";
2937
+ drawer: "drawer";
2938
+ }>>;
2939
+ position: z.ZodDefault<z.ZodEnum<{
2940
+ "bottom-right": "bottom-right";
2941
+ "bottom-left": "bottom-left";
2942
+ "top-right": "top-right";
2943
+ "top-left": "top-left";
2944
+ }>>;
2945
+ iframe: z.ZodDefault<z.ZodBoolean>;
2946
+ size: z.ZodOptional<z.ZodObject<{
2947
+ width: z.ZodOptional<z.ZodString>;
2948
+ height: z.ZodOptional<z.ZodString>;
2949
+ expanded: z.ZodOptional<z.ZodObject<{
2950
+ width: z.ZodOptional<z.ZodString>;
2951
+ height: z.ZodOptional<z.ZodString>;
2952
+ }, z.core.$loose>>;
2953
+ resize: z.ZodOptional<z.ZodObject<{
2954
+ enabled: z.ZodDefault<z.ZodBoolean>;
2955
+ minWidth: z.ZodOptional<z.ZodString>;
2956
+ maxWidth: z.ZodOptional<z.ZodString>;
2957
+ minHeight: z.ZodOptional<z.ZodString>;
2958
+ maxHeight: z.ZodOptional<z.ZodString>;
2959
+ }, z.core.$loose>>;
2960
+ inset: z.ZodOptional<z.ZodString>;
2961
+ initialSize: z.ZodDefault<z.ZodEnum<{
2962
+ fullscreen: "fullscreen";
2963
+ expanded: "expanded";
2964
+ normal: "normal";
2965
+ auto: "auto";
2966
+ }>>;
2967
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
2968
+ }, z.core.$loose>>;
2969
+ }, z.core.$loose>>>;
2970
+ behavior: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2971
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
2972
+ responseMode: z.ZodDefault<z.ZodEnum<{
2973
+ streaming: "streaming";
2974
+ buffered: "buffered";
2975
+ }>>;
2976
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
2977
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
2978
+ showSources: z.ZodDefault<z.ZodBoolean>;
2979
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
2980
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
2981
+ }, z.core.$loose>>>;
2982
+ theme: z.ZodOptional<z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
2983
+ auto: "auto";
2984
+ light: "light";
2985
+ dark: "dark";
2986
+ }>, z.ZodObject<{
2987
+ accent: z.ZodOptional<z.ZodString>;
2988
+ accentText: z.ZodOptional<z.ZodString>;
2989
+ radius: z.ZodOptional<z.ZodString>;
2990
+ fontFamily: z.ZodOptional<z.ZodString>;
2991
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
2992
+ }, z.core.$loose>]>>>;
2993
+ launcher: z.ZodOptional<z.ZodOptional<z.ZodObject<{
2994
+ variant: z.ZodDefault<z.ZodEnum<{
2995
+ circle: "circle";
2996
+ pill: "pill";
2997
+ bar: "bar";
2998
+ minimal: "minimal";
2999
+ }>>;
3000
+ size: z.ZodDefault<z.ZodEnum<{
3001
+ sm: "sm";
3002
+ md: "md";
3003
+ lg: "lg";
3004
+ }>>;
3005
+ label: z.ZodOptional<z.ZodString>;
3006
+ icon: z.ZodOptional<z.ZodString>;
3007
+ hidden: z.ZodDefault<z.ZodBoolean>;
3008
+ callout: z.ZodOptional<z.ZodObject<{
3009
+ text: z.ZodDefault<z.ZodString>;
3010
+ shape: z.ZodDefault<z.ZodEnum<{
3011
+ pill: "pill";
3012
+ bubble: "bubble";
3013
+ callout: "callout";
3014
+ }>>;
3015
+ position: z.ZodDefault<z.ZodEnum<{
3016
+ auto: "auto";
3017
+ horizontal: "horizontal";
3018
+ vertical: "vertical";
3019
+ }>>;
3020
+ delayMs: z.ZodDefault<z.ZodNumber>;
3021
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
3022
+ animated: z.ZodDefault<z.ZodBoolean>;
3023
+ persistent: z.ZodDefault<z.ZodBoolean>;
3024
+ }, z.core.$loose>>;
3025
+ }, z.core.$loose>>>;
3026
+ header: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3027
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
3028
+ close: "close";
3029
+ expand: "expand";
3030
+ fullscreen: "fullscreen";
3031
+ clear: "clear";
3032
+ theme: "theme";
3033
+ sound: "sound";
3034
+ history: "history";
3035
+ language: "language";
3036
+ textSize: "textSize";
3037
+ }>>>;
3038
+ }, z.core.$loose>>>;
3039
+ composer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3040
+ sendButton: z.ZodOptional<z.ZodObject<{
3041
+ shape: z.ZodDefault<z.ZodEnum<{
3042
+ circle: "circle";
3043
+ pill: "pill";
3044
+ square: "square";
3045
+ }>>;
3046
+ icon: z.ZodDefault<z.ZodEnum<{
3047
+ send: "send";
3048
+ arrowUp: "arrowUp";
3049
+ paperPlane: "paperPlane";
3050
+ chevron: "chevron";
3051
+ }>>;
3052
+ variant: z.ZodDefault<z.ZodEnum<{
3053
+ filled: "filled";
3054
+ outline: "outline";
3055
+ ghost: "ghost";
3056
+ }>>;
3057
+ }, z.core.$loose>>;
3058
+ attachments: z.ZodOptional<z.ZodObject<{
3059
+ maxBytes: z.ZodDefault<z.ZodNumber>;
3060
+ maxCount: z.ZodDefault<z.ZodNumber>;
3061
+ accept: z.ZodDefault<z.ZodString>;
3062
+ }, z.core.$loose>>;
3063
+ }, z.core.$loose>>>;
3064
+ feedback: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3065
+ sound: z.ZodOptional<z.ZodObject<{
3066
+ enabled: z.ZodDefault<z.ZodBoolean>;
3067
+ volume: z.ZodDefault<z.ZodNumber>;
3068
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
3069
+ voiceStart: "voiceStart";
3070
+ voiceStop: "voiceStop";
3071
+ error: "error";
3072
+ messageReceived: "messageReceived";
3073
+ messageSent: "messageSent";
3074
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
3075
+ }, z.core.$loose>>;
3076
+ haptics: z.ZodOptional<z.ZodObject<{
3077
+ enabled: z.ZodDefault<z.ZodBoolean>;
3078
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
3079
+ voiceStart: "voiceStart";
3080
+ voiceStop: "voiceStop";
3081
+ error: "error";
3082
+ messageReceived: "messageReceived";
3083
+ messageSent: "messageSent";
3084
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
3085
+ }, z.core.$loose>>;
3086
+ }, z.core.$loose>>>;
3087
+ i18n: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3088
+ locale: z.ZodOptional<z.ZodString>;
3089
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
3090
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
3091
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
3092
+ }, z.core.$loose>>>;
3093
+ footer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3094
+ poweredBy: z.ZodOptional<z.ZodObject<{
3095
+ text: z.ZodOptional<z.ZodString>;
3096
+ href: z.ZodOptional<z.ZodURL>;
3097
+ logoUrl: z.ZodOptional<z.ZodURL>;
3098
+ }, z.core.$loose>>;
3099
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
3100
+ }, z.core.$loose>>>;
3101
+ features: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3102
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
3103
+ voice: z.ZodDefault<z.ZodEnum<{
3104
+ local: "local";
3105
+ server: "server";
3106
+ disabled: "disabled";
3107
+ }>>;
3108
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
3109
+ code: z.ZodString;
3110
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3111
+ }, z.core.$loose>]>>>;
3112
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
3113
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
3114
+ }, z.core.$loose>>>;
3115
+ modules: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
3116
+ label: z.ZodString;
3117
+ layout: z.ZodEnum<{
3118
+ home: "home";
3119
+ chat: "chat";
3120
+ help: "help";
3121
+ news: "news";
3122
+ }>;
3123
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
3124
+ id: z.ZodOptional<z.ZodString>;
3125
+ brandName: z.ZodOptional<z.ZodString>;
3126
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
3127
+ greetingText: z.ZodOptional<z.ZodString>;
3128
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
3129
+ name: z.ZodString;
3130
+ avatar: z.ZodOptional<z.ZodString>;
3131
+ role: z.ZodOptional<z.ZodString>;
3132
+ }, z.core.$loose>>>;
3133
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
3134
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
3135
+ status: z.ZodOptional<z.ZodObject<{
3136
+ text: z.ZodOptional<z.ZodString>;
3137
+ level: z.ZodOptional<z.ZodString>;
3138
+ url: z.ZodOptional<z.ZodString>;
3139
+ }, z.core.$strip>>;
3140
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
3141
+ }, z.core.$loose>>>>;
3142
+ tracking: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3143
+ enabled: z.ZodOptional<z.ZodBoolean>;
3144
+ endpoint: z.ZodOptional<z.ZodURL>;
3145
+ sampleRate: z.ZodOptional<z.ZodNumber>;
3146
+ token: z.ZodOptional<z.ZodString>;
3147
+ }, z.core.$loose>>>;
3148
+ dataApiBaseUrl: z.ZodOptional<z.ZodString>;
3149
+ storageVersion: z.ZodOptional<z.ZodString>;
3150
+ }, z.core.$loose>;
3151
+ type ServerConfig = z.infer<typeof serverConfigSchema>;
3152
+ /**
3153
+ * Page-mode brand identity rendered at the top of the sidebar.
3154
+ *
3155
+ * Just the two things the widget actually paints: a brand name (used
3156
+ * as the logo's accessible alt-text fallback) and the logo asset
3157
+ * itself, with an optional dark-theme variant. Backend-side concerns
3158
+ * (custom domain, SEO meta tags, theme colours, favicons, hero
3159
+ * images) live outside this widget — the SSR / dashboard / DNS
3160
+ * layers own them.
3161
+ *
3162
+ * `.loose()` so unknown server-pushed fields still validate; only
3163
+ * the rendered subset is typed.
3164
+ */
3165
+ declare const siteConfigSchema: z.ZodObject<{
3166
+ title: z.ZodOptional<z.ZodString>;
3167
+ logo: z.ZodOptional<z.ZodObject<{
3168
+ url: z.ZodString;
3169
+ alt: z.ZodOptional<z.ZodString>;
3170
+ }, z.core.$strict>>;
3171
+ logoDark: z.ZodOptional<z.ZodObject<{
3172
+ url: z.ZodString;
3173
+ alt: z.ZodOptional<z.ZodString>;
3174
+ }, z.core.$strict>>;
3175
+ }, z.core.$loose>;
3176
+ type SiteConfig = z.infer<typeof siteConfigSchema>;
3177
+ /**
3178
+ * Page-mode content blocks rendered in the sidebar.
3179
+ *
3180
+ * The dashboard configures lists of links here; the widget walks
3181
+ * them and renders one section per non-empty list. Each entry
3182
+ * follows {@link linkSchema} (`label` + optional `href` / `icon` /
3183
+ * `description` / `id`).
3184
+ */
3185
+ declare const blocksConfigSchema: z.ZodObject<{
3186
+ navigation: z.ZodOptional<z.ZodArray<z.ZodObject<{
3187
+ id: z.ZodOptional<z.ZodString>;
3188
+ label: z.ZodString;
3189
+ href: z.ZodOptional<z.ZodString>;
3190
+ icon: z.ZodOptional<z.ZodString>;
3191
+ description: z.ZodOptional<z.ZodString>;
3192
+ }, z.core.$loose>>>;
3193
+ linkCards: z.ZodOptional<z.ZodArray<z.ZodObject<{
3194
+ id: z.ZodOptional<z.ZodString>;
3195
+ label: z.ZodString;
3196
+ href: z.ZodOptional<z.ZodString>;
3197
+ icon: z.ZodOptional<z.ZodString>;
3198
+ description: z.ZodOptional<z.ZodString>;
3199
+ }, z.core.$loose>>>;
3200
+ }, z.core.$loose>;
3201
+ type BlocksConfig = z.infer<typeof blocksConfigSchema>;
3202
+ declare const handshakeResponseSchema: z.ZodObject<{
3203
+ deployment: z.ZodObject<{
3204
+ id: z.ZodString;
3205
+ name: z.ZodString;
3206
+ slug: z.ZodOptional<z.ZodString>;
3207
+ publicKey: z.ZodOptional<z.ZodString>;
3208
+ }, z.core.$loose>;
3209
+ agent: z.ZodObject<{
3210
+ id: z.ZodString;
3211
+ name: z.ZodString;
3212
+ title: z.ZodOptional<z.ZodString>;
3213
+ status: z.ZodOptional<z.ZodEnum<{
3214
+ online: "online";
3215
+ away: "away";
3216
+ offline: "offline";
3217
+ }>>;
3218
+ }, z.core.$loose>;
3219
+ config: z.ZodOptional<z.ZodObject<{
3220
+ presentation: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3221
+ mode: z.ZodDefault<z.ZodEnum<{
3222
+ floating: "floating";
3223
+ inline: "inline";
3224
+ standalone: "standalone";
3225
+ page: "page";
3226
+ modal: "modal";
3227
+ drawer: "drawer";
3228
+ }>>;
3229
+ position: z.ZodDefault<z.ZodEnum<{
3230
+ "bottom-right": "bottom-right";
3231
+ "bottom-left": "bottom-left";
3232
+ "top-right": "top-right";
3233
+ "top-left": "top-left";
3234
+ }>>;
3235
+ iframe: z.ZodDefault<z.ZodBoolean>;
3236
+ size: z.ZodOptional<z.ZodObject<{
3237
+ width: z.ZodOptional<z.ZodString>;
3238
+ height: z.ZodOptional<z.ZodString>;
3239
+ expanded: z.ZodOptional<z.ZodObject<{
3240
+ width: z.ZodOptional<z.ZodString>;
3241
+ height: z.ZodOptional<z.ZodString>;
3242
+ }, z.core.$loose>>;
3243
+ resize: z.ZodOptional<z.ZodObject<{
3244
+ enabled: z.ZodDefault<z.ZodBoolean>;
3245
+ minWidth: z.ZodOptional<z.ZodString>;
3246
+ maxWidth: z.ZodOptional<z.ZodString>;
3247
+ minHeight: z.ZodOptional<z.ZodString>;
3248
+ maxHeight: z.ZodOptional<z.ZodString>;
3249
+ }, z.core.$loose>>;
3250
+ inset: z.ZodOptional<z.ZodString>;
3251
+ initialSize: z.ZodDefault<z.ZodEnum<{
3252
+ fullscreen: "fullscreen";
3253
+ expanded: "expanded";
3254
+ normal: "normal";
3255
+ auto: "auto";
3256
+ }>>;
3257
+ autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
3258
+ }, z.core.$loose>>;
3259
+ }, z.core.$loose>>>;
3260
+ behavior: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3261
+ startMinimized: z.ZodDefault<z.ZodBoolean>;
3262
+ responseMode: z.ZodDefault<z.ZodEnum<{
3263
+ streaming: "streaming";
3264
+ buffered: "buffered";
3265
+ }>>;
3266
+ showReasoning: z.ZodDefault<z.ZodBoolean>;
3267
+ showToolCalls: z.ZodDefault<z.ZodBoolean>;
3268
+ showSources: z.ZodDefault<z.ZodBoolean>;
3269
+ disableMessageFeedback: z.ZodDefault<z.ZodBoolean>;
3270
+ autoSendSuggestions: z.ZodDefault<z.ZodBoolean>;
3271
+ }, z.core.$loose>>>;
3272
+ theme: z.ZodOptional<z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
3273
+ auto: "auto";
3274
+ light: "light";
3275
+ dark: "dark";
3276
+ }>, z.ZodObject<{
3277
+ accent: z.ZodOptional<z.ZodString>;
3278
+ accentText: z.ZodOptional<z.ZodString>;
3279
+ radius: z.ZodOptional<z.ZodString>;
3280
+ fontFamily: z.ZodOptional<z.ZodString>;
3281
+ contentMaxWidth: z.ZodOptional<z.ZodString>;
3282
+ }, z.core.$loose>]>>>;
3283
+ launcher: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3284
+ variant: z.ZodDefault<z.ZodEnum<{
3285
+ circle: "circle";
3286
+ pill: "pill";
3287
+ bar: "bar";
3288
+ minimal: "minimal";
3289
+ }>>;
3290
+ size: z.ZodDefault<z.ZodEnum<{
3291
+ sm: "sm";
3292
+ md: "md";
3293
+ lg: "lg";
3294
+ }>>;
3295
+ label: z.ZodOptional<z.ZodString>;
3296
+ icon: z.ZodOptional<z.ZodString>;
3297
+ hidden: z.ZodDefault<z.ZodBoolean>;
3298
+ callout: z.ZodOptional<z.ZodObject<{
3299
+ text: z.ZodDefault<z.ZodString>;
3300
+ shape: z.ZodDefault<z.ZodEnum<{
3301
+ pill: "pill";
3302
+ bubble: "bubble";
3303
+ callout: "callout";
3304
+ }>>;
3305
+ position: z.ZodDefault<z.ZodEnum<{
3306
+ auto: "auto";
3307
+ horizontal: "horizontal";
3308
+ vertical: "vertical";
3309
+ }>>;
3310
+ delayMs: z.ZodDefault<z.ZodNumber>;
3311
+ autoDismissMs: z.ZodDefault<z.ZodNumber>;
3312
+ animated: z.ZodDefault<z.ZodBoolean>;
3313
+ persistent: z.ZodDefault<z.ZodBoolean>;
3314
+ }, z.core.$loose>>;
3315
+ }, z.core.$loose>>>;
3316
+ header: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3317
+ actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
3318
+ close: "close";
3319
+ expand: "expand";
3320
+ fullscreen: "fullscreen";
3321
+ clear: "clear";
3322
+ theme: "theme";
3323
+ sound: "sound";
3324
+ history: "history";
3325
+ language: "language";
3326
+ textSize: "textSize";
3327
+ }>>>;
3328
+ }, z.core.$loose>>>;
3329
+ composer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3330
+ sendButton: z.ZodOptional<z.ZodObject<{
3331
+ shape: z.ZodDefault<z.ZodEnum<{
3332
+ circle: "circle";
3333
+ pill: "pill";
3334
+ square: "square";
3335
+ }>>;
3336
+ icon: z.ZodDefault<z.ZodEnum<{
3337
+ send: "send";
3338
+ arrowUp: "arrowUp";
3339
+ paperPlane: "paperPlane";
3340
+ chevron: "chevron";
3341
+ }>>;
3342
+ variant: z.ZodDefault<z.ZodEnum<{
3343
+ filled: "filled";
3344
+ outline: "outline";
3345
+ ghost: "ghost";
3346
+ }>>;
3347
+ }, z.core.$loose>>;
3348
+ attachments: z.ZodOptional<z.ZodObject<{
3349
+ maxBytes: z.ZodDefault<z.ZodNumber>;
3350
+ maxCount: z.ZodDefault<z.ZodNumber>;
3351
+ accept: z.ZodDefault<z.ZodString>;
3352
+ }, z.core.$loose>>;
3353
+ }, z.core.$loose>>>;
3354
+ feedback: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3355
+ sound: z.ZodOptional<z.ZodObject<{
3356
+ enabled: z.ZodDefault<z.ZodBoolean>;
3357
+ volume: z.ZodDefault<z.ZodNumber>;
3358
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
3359
+ voiceStart: "voiceStart";
3360
+ voiceStop: "voiceStop";
3361
+ error: "error";
3362
+ messageReceived: "messageReceived";
3363
+ messageSent: "messageSent";
3364
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
3365
+ }, z.core.$loose>>;
3366
+ haptics: z.ZodOptional<z.ZodObject<{
3367
+ enabled: z.ZodDefault<z.ZodBoolean>;
3368
+ events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
3369
+ voiceStart: "voiceStart";
3370
+ voiceStop: "voiceStop";
3371
+ error: "error";
3372
+ messageReceived: "messageReceived";
3373
+ messageSent: "messageSent";
3374
+ }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
3375
+ }, z.core.$loose>>;
3376
+ }, z.core.$loose>>>;
3377
+ i18n: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3378
+ locale: z.ZodOptional<z.ZodString>;
3379
+ defaultLocale: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodString]>>;
3380
+ availableLocales: z.ZodOptional<z.ZodArray<z.ZodString>>;
3381
+ strings: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodString>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>]>>;
3382
+ }, z.core.$loose>>>;
3383
+ footer: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3384
+ poweredBy: z.ZodOptional<z.ZodObject<{
3385
+ text: z.ZodOptional<z.ZodString>;
3386
+ href: z.ZodOptional<z.ZodURL>;
3387
+ logoUrl: z.ZodOptional<z.ZodURL>;
3388
+ }, z.core.$loose>>;
3389
+ composerDisclaimer: z.ZodOptional<z.ZodString>;
3390
+ }, z.core.$loose>>>;
3391
+ features: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3392
+ disableFileUpload: z.ZodDefault<z.ZodBoolean>;
3393
+ voice: z.ZodDefault<z.ZodEnum<{
3394
+ local: "local";
3395
+ server: "server";
3396
+ disabled: "disabled";
3397
+ }>>;
3398
+ tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
3399
+ code: z.ZodString;
3400
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3401
+ }, z.core.$loose>]>>>;
3402
+ disableHumanInLoop: z.ZodDefault<z.ZodBoolean>;
3403
+ enableOperatorRequest: z.ZodDefault<z.ZodBoolean>;
3404
+ }, z.core.$loose>>>;
3405
+ modules: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
3406
+ label: z.ZodString;
3407
+ layout: z.ZodEnum<{
3408
+ home: "home";
3409
+ chat: "chat";
3410
+ help: "help";
3411
+ news: "news";
3412
+ }>;
3413
+ contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
3414
+ id: z.ZodOptional<z.ZodString>;
3415
+ brandName: z.ZodOptional<z.ZodString>;
3416
+ hideGreeting: z.ZodOptional<z.ZodBoolean>;
3417
+ greetingText: z.ZodOptional<z.ZodString>;
3418
+ userAvatars: z.ZodOptional<z.ZodArray<z.ZodObject<{
3419
+ name: z.ZodString;
3420
+ avatar: z.ZodOptional<z.ZodString>;
3421
+ role: z.ZodOptional<z.ZodString>;
3422
+ }, z.core.$loose>>>;
3423
+ hideSearchBar: z.ZodOptional<z.ZodBoolean>;
3424
+ hideRecentConversations: z.ZodOptional<z.ZodBoolean>;
3425
+ status: z.ZodOptional<z.ZodObject<{
3426
+ text: z.ZodOptional<z.ZodString>;
3427
+ level: z.ZodOptional<z.ZodString>;
3428
+ url: z.ZodOptional<z.ZodString>;
3429
+ }, z.core.$strip>>;
3430
+ contentBlockTitle: z.ZodOptional<z.ZodString>;
3431
+ }, z.core.$loose>>>>;
3432
+ tracking: z.ZodOptional<z.ZodOptional<z.ZodObject<{
3433
+ enabled: z.ZodOptional<z.ZodBoolean>;
3434
+ endpoint: z.ZodOptional<z.ZodURL>;
3435
+ sampleRate: z.ZodOptional<z.ZodNumber>;
3436
+ token: z.ZodOptional<z.ZodString>;
3437
+ }, z.core.$loose>>>;
3438
+ dataApiBaseUrl: z.ZodOptional<z.ZodString>;
3439
+ storageVersion: z.ZodOptional<z.ZodString>;
3440
+ }, z.core.$loose>>;
3441
+ site: z.ZodOptional<z.ZodObject<{
3442
+ title: z.ZodOptional<z.ZodString>;
3443
+ logo: z.ZodOptional<z.ZodObject<{
3444
+ url: z.ZodString;
3445
+ alt: z.ZodOptional<z.ZodString>;
3446
+ }, z.core.$strict>>;
3447
+ logoDark: z.ZodOptional<z.ZodObject<{
3448
+ url: z.ZodString;
3449
+ alt: z.ZodOptional<z.ZodString>;
3450
+ }, z.core.$strict>>;
3451
+ }, z.core.$loose>>;
3452
+ blocks: z.ZodOptional<z.ZodObject<{
3453
+ navigation: z.ZodOptional<z.ZodArray<z.ZodObject<{
3454
+ id: z.ZodOptional<z.ZodString>;
3455
+ label: z.ZodString;
3456
+ href: z.ZodOptional<z.ZodString>;
3457
+ icon: z.ZodOptional<z.ZodString>;
3458
+ description: z.ZodOptional<z.ZodString>;
3459
+ }, z.core.$loose>>>;
3460
+ linkCards: z.ZodOptional<z.ZodArray<z.ZodObject<{
3461
+ id: z.ZodOptional<z.ZodString>;
3462
+ label: z.ZodString;
3463
+ href: z.ZodOptional<z.ZodString>;
3464
+ icon: z.ZodOptional<z.ZodString>;
3465
+ description: z.ZodOptional<z.ZodString>;
3466
+ }, z.core.$loose>>>;
3467
+ }, z.core.$loose>>;
3468
+ welcome: z.ZodOptional<z.ZodObject<{
3469
+ messages: z.ZodOptional<z.ZodArray<z.ZodObject<{
3470
+ id: z.ZodString;
3471
+ role: z.ZodEnum<{
3472
+ assistant: "assistant";
3473
+ system: "system";
3474
+ }>;
3475
+ text: z.ZodString;
3476
+ }, z.core.$loose>>>;
3477
+ suggestions: z.ZodOptional<z.ZodArray<z.ZodObject<{
3478
+ id: z.ZodString;
3479
+ label: z.ZodString;
3480
+ text: z.ZodOptional<z.ZodString>;
3481
+ }, z.core.$loose>>>;
3482
+ }, z.core.$loose>>;
3483
+ visitorId: z.ZodString;
3484
+ conversationId: z.ZodString;
3485
+ userPrefs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
3486
+ rebind: z.ZodOptional<z.ZodObject<{
3487
+ visitorId: z.ZodOptional<z.ZodEnum<{
3488
+ conflict: "conflict";
3489
+ expired: "expired";
3490
+ invalid: "invalid";
3491
+ }>>;
3492
+ conversationId: z.ZodOptional<z.ZodEnum<{
3493
+ conflict: "conflict";
3494
+ expired: "expired";
3495
+ invalid: "invalid";
3496
+ }>>;
3497
+ }, z.core.$loose>>;
3498
+ }, z.core.$loose>;
3499
+ type HandshakeResponse = z.infer<typeof handshakeResponseSchema>;
3500
+ //#endregion
3501
+ //#region src/index.d.ts
1633
3502
  /**
1634
3503
  * Handle returned by {@link mount} / {@link init}. All methods are safe to call
1635
3504
  * after `destroy()` — they become no-ops rather than throwing.
1636
3505
  */
1637
3506
  interface ChatWidgetInstance {
1638
- /** Stable identifier — matches `options.widgetId ?? "default"`. */
1639
- readonly widgetId: string;
1640
- /** Open the floating panel (no-op in `inline` / `standalone` mode). */
1641
- open: () => void;
1642
- /** Close the floating panel (no-op in `inline` / `standalone` mode). */
1643
- close: () => void;
1644
- /** Unmount the widget and release all subscriptions. */
1645
- destroy: () => void;
1646
- /** Toggle fullscreen mode. In `standalone` mode this is a no-op. */
1647
- expand: () => void;
1648
- /**
1649
- * Surface a configured form by id (a form with a `manual` trigger). Lets the
1650
- * host open, say, an appointment or feedback form from its own button. No-op
1651
- * if no form with that id + a `manual` trigger exists.
1652
- */
1653
- openForm: (id: string) => void;
1654
- /**
1655
- * Subscribe to a lifecycle event. Returns an `off` function. See
1656
- * {@link EventMap} for the full set + payload shapes — currently
1657
- * `open | close | message | error | expand | fullscreen |
1658
- * handshake | localeChange`.
1659
- */
1660
- on: <E extends EventName>(name: E, fn: (payload: EventMap[E]) => void) => () => void;
1661
- /**
1662
- * Merge new options into the running instance without a full remount.
1663
- * Useful for theme toggles or other live config tweaks.
1664
- */
1665
- update: (patch: Partial<ChatWidgetOptions>) => void;
1666
- /**
1667
- * Set / merge the host-asserted end-user context (`id`, `email`, `name`, plus
1668
- * any custom scalar fields). Informational only — not auth. Merges into the
1669
- * current context, refreshes the Home greeting, and re-handshakes so the
1670
- * agent gets it. Call this after the visitor logs in. Untrusted input is
1671
- * sanitised; bad fields are dropped with a `warn`.
1672
- *
1673
- * @example
1674
- * ```ts
1675
- * getInstance().setUserContext({ id: "u_1", name: "Mohamed", email: "mo@acme.com", plan: "pro" });
1676
- * ```
1677
- */
1678
- setUserContext: (userContext: UserContext) => void;
1679
- /** Clear the end-user context (e.g. on logout) and re-handshake anonymously. */
1680
- clearUserContext: () => void;
1681
- /**
1682
- * Set / merge the host-asserted page/visit context (`area`, `url`, `path`,
1683
- * `title`, plus custom scalar fields). Use it to tell the agent which surface
1684
- * the visitor is on (e.g. `area: "pricing"`) and update it on SPA navigation.
1685
- * Merges into the current context and re-handshakes.
1686
- *
1687
- * @example
1688
- * ```ts
1689
- * getInstance().setPageContext({ area: "pricing", path: "/pricing/enterprise" });
1690
- * ```
1691
- */
1692
- setPageContext: (pageContext: PageContext) => void;
1693
- /** Clear the page/visit context and re-handshake. */
1694
- clearPageContext: () => void;
1695
- /**
1696
- * Set the runtime log level. Accepts `"off"` / `"error"` / `"warn"` /
1697
- * `"info"` / `"debug"` / `"trace"`, or `true` (→ `"debug"`) /
1698
- * `false` (→ `"off"`), or a number 0..5. Persists to localStorage so
1699
- * a page refresh keeps the same verbosity — useful for asking a
1700
- * customer to reproduce a bug and capture the console transcript.
1701
- *
1702
- * Affects every widget on the page (logger is module-global; setting
1703
- * it from one instance applies everywhere). Equivalent to calling
1704
- * `HelpAI.setDebug(level)` on the brand global.
1705
- */
1706
- setDebug: (level: LogLevel | boolean | number | string) => void;
1707
- /** Current log level. Read-only. */
1708
- readonly debugLevel: () => LogLevel;
1709
- /**
1710
- * Forward every log line (that passes the active level) to an external sink —
1711
- * pipe errors/warnings/debug into Sentry, Datadog, your own logger, etc. Pass
1712
- * `null` to clear. One global sink per bundle (logger is module-global); use
1713
- * `setDebug("trace")` to capture everything, not just warnings + errors.
1714
- */
1715
- onLog: (sink: ((entry: LogEntry) => void) | null) => void;
3507
+ /** Stable identifier — matches `options.widgetId ?? "default"`. */
3508
+ readonly widgetId: string;
3509
+ /** Open the floating panel (no-op in `inline` / `standalone` mode). */
3510
+ open: () => void;
3511
+ /** Close the floating panel (no-op in `inline` / `standalone` mode). */
3512
+ close: () => void;
3513
+ /** Unmount the widget and release all subscriptions. */
3514
+ destroy: () => void;
3515
+ /** Toggle fullscreen mode. In `standalone` mode this is a no-op. */
3516
+ expand: () => void;
3517
+ /**
3518
+ * Surface a configured form by id (a form with a `manual` trigger). Lets the
3519
+ * host open, say, an appointment or feedback form from its own button. No-op
3520
+ * if no form with that id + a `manual` trigger exists.
3521
+ */
3522
+ openForm: (id: string) => void;
3523
+ /**
3524
+ * Subscribe to a lifecycle event. Returns an `off` function. See
3525
+ * {@link EventMap} for the full set + payload shapes — currently
3526
+ * `open | close | message | error | expand | fullscreen |
3527
+ * handshake | localeChange`.
3528
+ */
3529
+ on: <E extends EventName>(name: E, fn: (payload: EventMap[E]) => void) => () => void;
3530
+ /**
3531
+ * Merge new options into the running instance without a full remount.
3532
+ * Useful for theme toggles or other live config tweaks.
3533
+ */
3534
+ update: (patch: Partial<ChatWidgetOptions>) => void;
3535
+ /**
3536
+ * Set / merge the host-asserted end-user context (`id`, `email`, `name`, plus
3537
+ * any custom scalar fields). Informational only — not auth. Merges into the
3538
+ * current context, refreshes the Home greeting, and re-handshakes so the
3539
+ * agent gets it. Call this after the visitor logs in. Untrusted input is
3540
+ * sanitised; bad fields are dropped with a `warn`.
3541
+ *
3542
+ * @example
3543
+ * ```ts
3544
+ * getInstance().setUserContext({ id: "u_1", name: "Mohamed", email: "mo@acme.com", plan: "pro" });
3545
+ * ```
3546
+ */
3547
+ setUserContext: (userContext: UserContext) => void;
3548
+ /** Clear the end-user context (e.g. on logout) and re-handshake anonymously. */
3549
+ clearUserContext: () => void;
3550
+ /**
3551
+ * Set / merge the host-asserted page/visit context (`area`, `url`, `path`,
3552
+ * `title`, plus custom scalar fields). Use it to tell the agent which surface
3553
+ * the visitor is on (e.g. `area: "pricing"`) and update it on SPA navigation.
3554
+ * Merges into the current context and re-handshakes.
3555
+ *
3556
+ * @example
3557
+ * ```ts
3558
+ * getInstance().setPageContext({ area: "pricing", path: "/pricing/enterprise" });
3559
+ * ```
3560
+ */
3561
+ setPageContext: (pageContext: PageContext) => void;
3562
+ /** Clear the page/visit context and re-handshake. */
3563
+ clearPageContext: () => void;
3564
+ /**
3565
+ * Set the runtime log level. Accepts `"off"` / `"error"` / `"warn"` /
3566
+ * `"info"` / `"debug"` / `"trace"`, or `true` (→ `"debug"`) /
3567
+ * `false` (→ `"off"`), or a number 0..5. Persists to localStorage so
3568
+ * a page refresh keeps the same verbosity — useful for asking a
3569
+ * customer to reproduce a bug and capture the console transcript.
3570
+ *
3571
+ * Affects every widget on the page (logger is module-global; setting
3572
+ * it from one instance applies everywhere). Equivalent to calling
3573
+ * `HelpAI.setDebug(level)` on the brand global.
3574
+ */
3575
+ setDebug: (level: LogLevel | boolean | number | string) => void;
3576
+ /** Current log level. Read-only. */
3577
+ readonly debugLevel: () => LogLevel;
3578
+ /**
3579
+ * Forward every log line (that passes the active level) to an external sink —
3580
+ * pipe errors/warnings/debug into Sentry, Datadog, your own logger, etc. Pass
3581
+ * `null` to clear. One global sink per bundle (logger is module-global); use
3582
+ * `setDebug("trace")` to capture everything, not just warnings + errors.
3583
+ */
3584
+ onLog: (sink: ((entry: LogEntry) => void) | null) => void;
1716
3585
  }
1717
3586
  /**
1718
3587
  * Mount a new widget. If an instance with the same `widgetId` already
@@ -1729,7 +3598,7 @@ interface ChatWidgetInstance {
1729
3598
  * ```
1730
3599
  */
1731
3600
  declare function mount(opts: ChatWidgetOptions & {
1732
- target?: HTMLElement;
3601
+ target?: HTMLElement;
1733
3602
  }): ChatWidgetInstance;
1734
3603
  /**
1735
3604
  * Idempotent init per `widgetId`. If an instance exists at that slot, its
@@ -1737,7 +3606,7 @@ declare function mount(opts: ChatWidgetOptions & {
1737
3606
  * behaves like {@link mount}. Safe to call on every route change in an SPA.
1738
3607
  */
1739
3608
  declare function init(opts: ChatWidgetOptions & {
1740
- target?: HTMLElement;
3609
+ target?: HTMLElement;
1741
3610
  }): ChatWidgetInstance;
1742
3611
  /**
1743
3612
  * Destroy a specific instance by `widgetId`, or — when no id is supplied —
@@ -1751,7 +3620,6 @@ declare function destroy(widgetId?: string): void;
1751
3620
  declare function getInstance(widgetId?: string): ChatWidgetInstance | null;
1752
3621
  /** All live widget instances on the page. */
1753
3622
  declare function getAllInstances(): ChatWidgetInstance[];
1754
-
1755
3623
  /**
1756
3624
  * Register a lifecycle hook that fires for every matching
1757
3625
  * `(widgetId, event)` pair across all live widgets.
@@ -1783,15 +3651,16 @@ declare function hook(widgetId: string, event: string, listener: HookListener):
1783
3651
  declare const version: string;
1784
3652
  /** Compile-time brand constants inlined at build time (name, CDN URL, theme). */
1785
3653
  declare const brand: {
1786
- readonly id: string;
1787
- readonly name: string;
1788
- readonly global: string;
1789
- readonly tagName: string;
1790
- readonly cssPrefix: string;
1791
- readonly defaultBaseUrl: string;
1792
- readonly displayName: string;
1793
- readonly domain: string;
1794
- readonly siteUrl: string;
3654
+ readonly id: string;
3655
+ readonly name: string;
3656
+ readonly global: string;
3657
+ readonly tagName: string;
3658
+ readonly cssPrefix: string;
3659
+ readonly defaultBaseUrl: string;
3660
+ readonly displayName: string;
3661
+ readonly domain: string;
3662
+ readonly siteUrl: string;
1795
3663
  };
1796
-
1797
- export { type ChatWidgetInstance, type ChatWidgetOptions, type EventMap, type EventName, HOOK_WILDCARD, type HookListener, type LogEntry, type LogLevel, type ResolvedOptions, brand, destroy, getAllInstances, getInstance, hook, init, mount, resolveInitialHostMode, version };
3664
+ //#endregion
3665
+ export { type Asset, type BlocksConfig, ChatWidgetInstance, type ChatWidgetOptions, type ConnectionConfig, type ConnectionConfigPartial, type EventMap, type EventName, HOOK_WILDCARD, type HandshakeResponse, type HookListener, type Link, type LogEntry, type LogLevel, type ResolvedOptions, type ServerConfig, type SiteConfig, type WidgetConfig, type WidgetConfigPartial, type WidgetSettings, type WidgetSettingsPartial, brand, destroy, getAllInstances, getInstance, hook, init, mount, resolveInitialHostMode, version };
3666
+ //# sourceMappingURL=index.d.ts.map