@helpai/elements 1.7.0 → 1.9.0

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