@helpai/elements 0.63.3 → 0.63.4
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/configurator.mjs +1 -1
- package/elements-web-component.esm.js +1 -1
- package/elements-web-component.esm.js.map +1 -1
- package/elements.cjs.js +1 -1
- package/elements.cjs.js.map +1 -1
- package/elements.esm.js +1 -1
- package/elements.esm.js.map +1 -1
- package/elements.js +1 -1
- package/elements.js.map +1 -1
- package/index.d.ts +3 -3
- package/index.mjs +1 -1
- package/package.json +1 -1
- package/schema.json +2 -2
- package/schema.mjs +1 -1
- package/web-component.mjs +1 -1
package/schema.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{z as e}from"zod";const t=e.object({url:e.string().min(1).max(2048).describe(`Public URL of the image. Must be a full URL or root-relative path.`),alt:e.string().min(1).max(200).optional().describe(`Alt text for screen readers. Omit only for purely decorative images.`)}).strict().describe(`A single image asset (logo, hero, icon).`),n=e.object({id:e.string().min(1).max(100).optional().describe(`Stable id used as React key + analytics target.`),label:e.string().min(1).max(120).describe(`Visible link text.`),href:e.string().min(1).max(2048).optional().describe(`Click target. Optional — when omitted the link renders as a non-clickable heading.`),icon:e.string().min(1).max(100).optional().describe(`Built-in icon preset name (chat / spark / message / help / wand) or a custom string.`),description:e.string().min(1).max(300).optional().describe(`Subtitle shown below the label. Used by link cards in page mode.`)}).loose().describe(`A navigation link / link card.`),r=e.string().min(1).max(120).describe("Any CSS length — `640px`, `80vh`, `calc(100vh - 64px)`, etc. Validated only for size, not syntax."),i=e.string().min(1).max(120).describe("Any CSS colour — hex, `rgb()`, `hsl()`, `oklch()`, a named colour, or a `var(--token)`."),a=e.string().min(1).max(35).describe("BCP-47 locale tag (e.g. `en`, `fr-CA`, `zh-Hant-HK`)."),ee=e.uuidv7().describe(`UUID v7 (RFC 9562) — the single id format for visitor / conversation / message / file / content ids.`),o=e.enum([`normal`,`expanded`,`fullscreen`,`auto`]),s=e.object({enabled:e.boolean().default(!1).describe(`Show a corner-grip handle the user can drag to resize the panel.`),minWidth:r.optional().describe(`Smallest width the user can drag the panel to.`),maxWidth:r.optional().describe(`Largest width the user can drag the panel to.`),minHeight:r.optional().describe(`Smallest height the user can drag the panel to.`),maxHeight:r.optional().describe(`Largest height the user can drag the panel to.`)}).loose().describe("Drag-resize controls. When `enabled`, a corner grip lets users resize the panel within the optional min/max bounds.").meta({examples:[{enabled:!1},{enabled:!0,minWidth:`320px`,maxWidth:`720px`,minHeight:`400px`,maxHeight:`90vh`}]}),te=e.object({width:r.optional().describe("Panel width (CSS length). Mode-specific defaults — floating `380px`, modal `min(960px, 92vw)`, drawer `min(440px, calc(100vw - 32px))`. Set this to override; inline/standalone/page modes ignore it."),height:r.optional().describe("Panel height (CSS length). Mode-specific defaults — floating `600px`, modal `min(720px, 88vh)`, drawer `100vh` (clamped to `100vh − inset-y × 2`). Set this to override."),expanded:e.object({width:r.optional().describe(`Width when the user clicks the expand button.`),height:r.optional().describe(`Height when the user clicks the expand button.`)}).loose().optional().describe("Dimensions when the panel is in its `expanded` tier (between normal and fullscreen). Applies to floating / modal / drawer; ignored in inline / standalone / page where the panel always fills its parent."),resize:s.optional().describe(`Drag-resize controls — adds a corner grip the user can drag.`),inset:r.optional().describe("Drawer-mode edge inset — gap from each viewport edge (top/bottom/left/right). Single value applied to all four sides. Defaults to `3vh` vertical / `12px` horizontal. Use `0` for a full-edge drawer (no gap), or `5vh` for a centered-looking flyout with extra breathing room. Ignored by every other mode."),initialSize:o.default(`normal`).describe("Which size tier to open with on the first mount: `normal` / `expanded` / `fullscreen` / `auto` (picks expanded above `autoSizeBreakpoint` viewport width)."),autoSizeBreakpoint:e.number().int().min(0).max(1e4).default(900).describe("Viewport width (px) above which `initialSize: auto` resolves to `expanded` instead of `normal`.")}).loose().describe("Panel dimensions and drawer inset. Width/height override the mode-specific defaults (floating compact popover, modal centered dialog, drawer flyout). `inset` only affects drawer mode.").meta({examples:[{width:`420px`,height:`640px`},{width:`min(560px, 92vw)`,height:`min(640px, 90vh)`},{width:`420px`,expanded:{width:`640px`,height:`780px`},initialSize:`auto`,autoSizeBreakpoint:900},{width:`min(1100px, 95vw)`,height:`min(820px, 92vh)`},{width:`360px`,inset:`8vh`},{width:`420px`,height:`100vh`,inset:`0`},{width:`420px`,height:`60vh`,inset:`20vh`}]}),ne=e.enum([`floating`,`inline`,`standalone`,`page`,`modal`,`drawer`]),re=e.enum([`bottom-right`,`bottom-left`,`top-right`,`top-left`]),c=e.object({mode:ne.default(`floating`).describe("Rendering shape. `floating` (FAB + popover), `inline` (in-flow block), `standalone` (full viewport), `page` (sidebar + chat), `modal` (centered overlay), `drawer` (side dock)."),position:re.default(`bottom-right`).describe("Anchor corner. `floating` uses it for the FAB; `drawer` uses the `*-left` / `*-right` suffix to pick the dock side. Ignored in other modes."),iframe:e.boolean().default(!1).describe(`Wrap the widget in a same-origin iframe for stricter JS + CSS isolation from the host page. Composes with every mode.`),size:te.optional().describe("Panel dimensions. Mode-aware defaults (floating compact popover, modal centered dialog, drawer flyout) — fields here override them. Includes `inset` (drawer flyout gap), `expanded` tier, drag-resize grip.")}).loose().describe(`Layout fundamentals — mode, anchor corner, iframe isolation, panel size + drawer inset.`).meta({examples:[{mode:`floating`,position:`bottom-right`},{mode:`modal`,size:{width:`min(1100px, 95vw)`,height:`min(820px, 92vh)`}},{mode:`drawer`,position:`bottom-right`},{mode:`drawer`,position:`top-right`,size:{width:`360px`,inset:`8vh`}},{mode:`drawer`,position:`bottom-right`,size:{width:`420px`,height:`100vh`,inset:`0`}}]}),l=e.enum([`streaming`,`buffered`]),u=e.object({startMinimized:e.boolean().default(!0).describe("Don't auto-open the floating panel on first visit. `true` (default) shows the FAB collapsed; `false` opens the panel on mount."),responseMode:l.default(`streaming`).describe("How the assistant's reply arrives. `streaming` (default) types tokens as they generate; `buffered` waits + shows the full reply at once."),showReasoning:e.boolean().default(!1).describe('Show the model\'s reasoning ("thoughts") as a collapsible block above each answer. `false` (default) hides it — a loading indicator still shows while the model works. Reasoning is never persisted; it only appears live.'),showToolCalls:e.boolean().default(!1).describe("Show automatic tool/function calls the model makes (e.g. search) as collapsible detail+result cards in the transcript. `false` (default) hides them. Interactive tools (ask-questions / approval) always show."),showSources:e.boolean().default(!1).describe("Show the citation sources behind an answer (web links + document/file references) in the transcript. `false` (default) hides them."),disableMessageFeedback:e.boolean().default(!1).describe("Turn OFF the 👍/👎 feedback controls under each rateable reply (AI or operator). Unset/`false` = shown (default), `true` = hidden. A choice fires the `messageFeedback` event and is POSTed best-effort to `/pai/message-feedback`."),autoSendSuggestions:e.boolean().default(!1).describe("Auto-send a suggestion chip's text the moment it's tapped. `false` (default) fills the composer with the text so the visitor can edit before sending; `true` sends it immediately.")}).loose().describe(`Conversation behaviour — lifecycle, streaming, and the transcript surface (scroll, feedback).`).meta({examples:[{startMinimized:!0,responseMode:`streaming`},{startMinimized:!1,responseMode:`buffered`,disableMessageFeedback:!0}]}),d=e.enum([`auto`,`light`,`dark`]),f=e.object({accent:i.optional().describe(`Brand accent colour. Drives the FAB, send button, links, and active states. CSS colour.`),accentText:i.optional().describe(`Foreground colour rendered ON the accent (FAB icon, send-button glyph). CSS colour.`),radius:r.optional().describe("Corner radius for the panel + buttons. CSS length (`8px`, `0.75rem`, `12px`)."),fontFamily:e.string().min(1).max(200).optional().describe("Font stack used inside the widget. Standard CSS `font-family` value."),contentMaxWidth:r.optional().describe("Max width of the readable content column (messages, history, home, composer) on a wide surface — content centres, full-bleed bars keep their edges. CSS length; default `768px`. Set `100%` to fill the surface (no cap). Modal + drawer already fill their card by default.")}).loose().describe(`Theme token overrides. Any field left unset falls through to the brand's default theme.`).meta({examples:[{accent:`#10b981`,radius:`12px`},{accent:`#7c3aed`,accentText:`#ffffff`,radius:`16px`,fontFamily:`'Inter', system-ui`},{accent:`oklch(0.7 0.2 145)`,radius:`0.5rem`},{accent:`#5b5bd6`,contentMaxWidth:`960px`}]}),p=e.union([d,f]).describe(`'auto' | 'light' | 'dark', or a tokens override object.`).meta({examples:[`auto`,`dark`,{accent:`#10b981`,radius:`12px`},{accent:`#7c3aed`,accentText:`#fff`,radius:`16px`,fontFamily:`'Inter', system-ui`}]}),m=e.enum([`circle`,`pill`,`bar`,`minimal`]),h=e.enum([`sm`,`md`,`lg`]),g=e.enum([`pill`,`bubble`,`callout`]),_=e.enum([`auto`,`horizontal`,`vertical`]),v=e.object({text:e.string().min(1).max(500).default(`👋 Hi! Need any help?`).describe("The message to show in the bubble. Defaults to a friendly greeting; replace with your own copy (e.g. 'Click here →'). May also be an i18n key (e.g. `launcherCallout`) resolved against `i18n.strings` for per-locale copy; a non-key literal renders as-is."),shape:g.default(`pill`).describe("Visual shape — `pill` (slim label + arrow), `bubble` (speech-bubble tail), `callout` (loud variant)."),position:_.default(`auto`).describe("Where the bubble sits relative to the FAB. `auto` (default) picks the side facing into the page. `horizontal` anchors beside the FAB (left/right depending on the FAB's corner). `vertical` anchors above/below the FAB. Concrete left/right/top/bottom is derived from the FAB's corner so the bubble always stays on-screen."),delayMs:e.number().int().min(0).max(6e4).default(1200).describe(`How long to wait after page load before the bubble appears, in milliseconds.`),autoDismissMs:e.number().int().min(0).max(6e5).default(0).describe("Auto-hide the bubble after this many milliseconds. `0` (default) keeps it until the user dismisses."),animated:e.boolean().default(!0).describe("Subtle horizontal nudge to draw the eye. Disabled automatically by `prefers-reduced-motion`."),persistent:e.boolean().default(!0).describe("How dismissals stick. `true` (default) — re-show on every visit regardless of prior dismissal (the 'recurring greeting' behaviour). `false` — clicking X stores the message text and that exact message stays hidden across visits (the 'one-time hint' behaviour).")}).loose().describe(`Pre-engagement message bubble next to the FAB. Use it for a greeting ('Hi, need help?'), an attention-grabbing nudge ('Click here →'), or any one-time onboarding tip — same component, configured for the use case.`),y=e.object({variant:m.default(`circle`).describe("FAB visual style. `circle` — round bubble (icon only). `pill` — icon + label. `bar` — wide rectangular button. `minimal` — text-only outline."),size:h.default(`md`).describe(`FAB size preset — small / medium / large.`),label:e.string().max(200).optional().describe("Text rendered on the FAB (only shown for `pill` / `bar` / `minimal` variants)."),icon:e.string().max(8e3).optional().describe("Icon shown on the FAB / drawer edge tab. Built-in presets: `chat` / `message` / `bubbles` / `spark` / `wand` / `bot` / `help` / `lifebuoy` / `headset`. Anything else is treated as raw SVG."),hidden:e.boolean().default(!1).describe("Hide the FAB entirely (page brings its own trigger that calls `instance.open()`)."),callout:v.optional()}).loose().describe(`Floating-launcher (FAB) appearance and behaviour. The FAB is the round button in the corner that opens the chat panel. Floating mode only.`).meta({examples:[{variant:`circle`,size:`md`},{variant:`pill`,label:`Ask AI`,icon:`spark`},{variant:`circle`,callout:{text:`👋 Need help?`,shape:`bubble`,persistent:!0}},{variant:`circle`,callout:{text:`Click to start`,shape:`pill`,delayMs:1200}}]}),b=e.enum([`local`,`server`,`disabled`]),x=e.union([e.string().min(1).max(200),e.object({code:e.string().min(1).max(200),config:e.record(e.string(),e.unknown()).optional()}).loose()]),S=e.object({disableFileUpload:e.boolean().default(!1).describe("Turn OFF file uploads — hide the paperclip button + reject drag/drop/paste. Unset/`false` = enabled (default), `true` = disabled."),voice:b.default(`local`).describe("Voice input mode. `local` — Web Speech API in the browser (free, runs on-device). `server` — record audio + upload to the transcribe endpoint. `disabled` — hide the mic button."),tools:e.array(x).max(200).optional().describe("Backend tools the assistant may invoke. Bare codes (`'tool:send-money'`) or rich refs (`{ code, config }`)."),disableHumanInLoop:e.boolean().default(!1).describe("Turn OFF the human-in-the-loop tool UI — the inline ask-questions form + approve/reject controls for gated tools. Unset/`false` = shown (default), `true` = suppressed (the wire still carries the signals)."),enableOperatorRequest:e.boolean().default(!1).describe("Opt IN operator control — expose the 'Talk to an operator' affordance + connected-to-operator states for this deployment. Unset/`false` = off (default), `true` = on. Unlike the `disable*` flags this is a positive opt-in for a new capability.")}).loose().describe(`Capability flags — file upload, voice mode, and the tools the assistant may invoke.`).meta({examples:[{voice:`local`},{disableFileUpload:!0,voice:`disabled`},{voice:`server`,tools:[`tool:send-money`]}]}),C=e.enum([`clear`,`expand`,`fullscreen`,`sound`,`history`,`language`,`theme`,`textSize`,`close`]),w=e.array(C).max(10).describe("Which actions the header exposes. `history` + `close` are dedicated buttons; the rest appear in the ⋯ menu. Unlisted actions are hidden; order is irrelevant. Pick from: `clear`, `expand`, `fullscreen`, `sound`, `history`, `language`, `theme`, `textSize`, `close`. Per-mode defaults live in `DEFAULT_ACTIONS_BY_MODE`.").meta({examples:[[`theme`,`history`,`close`,`clear`,`fullscreen`,`sound`,`language`],[`theme`,`history`,`clear`,`language`],[`close`]]}),T=e.object({actions:w.optional().describe(`Which header actions are enabled (history/✕ buttons + ⋯ menu).`)}).loose().describe(`Panel-header configuration.`).meta({examples:[{actions:[`theme`,`history`,`close`,`clear`,`fullscreen`]}]}),E=e.enum([`messageReceived`,`messageSent`,`error`,`voiceStart`,`voiceStop`]),D=e.object({enabled:e.boolean().default(!0).describe(`Master on/off for audible notifications. On by default — browser autoplay policy still requires a prior user gesture before any sound plays.`),volume:e.number().min(0).max(1).default(.3).describe("Global volume 0..1. `0.3` (default) is intentionally subtle."),events:e.partialRecord(E,e.union([e.boolean(),e.string().min(1).max(2048)])).optional().describe("Per-event override map. Value: `true` = built-in tone, `false` = silent, `string` = URL to a custom audio file (mp3/wav/ogg).")}).loose().describe("Audible notifications. `events` accepts true (default tone), false (off), or a URL to an audio file.").meta({examples:[{enabled:!0,volume:.3},{enabled:!0,volume:.5,events:{messageReceived:!0,error:!1}},{enabled:!0,events:{messageReceived:`https://cdn.help.ai/ping.mp3`}}]}),O=e.object({enabled:e.boolean().default(!0).describe(`Master on/off. Default: on for touch devices, silently ignored elsewhere.`),events:e.partialRecord(E,e.union([e.boolean(),e.number().int(),e.array(e.number().int())])).optional().describe("Per-event vibration pattern. Value: `true` = default pattern, `false` = silent, number = single vibrate ms, array = `[vibrate, pause, vibrate, …]`.")}).loose().describe("Touch-device vibration. `events` accepts true (default), number (single vibrate ms), or [vibrate,pause,vibrate,…].").meta({examples:[{enabled:!0},{enabled:!0,events:{messageReceived:30,error:[40,60,40]}}]}),k=e.object({sound:D.optional(),haptics:O.optional()}).loose().describe(`Audible + tactile feedback.`).meta({examples:[{sound:{enabled:!0,volume:.3},haptics:{enabled:!0}},{sound:{enabled:!1},haptics:{enabled:!1}}]}),A=e.enum([`circle`,`square`,`pill`]),j=e.enum([`arrowUp`,`paperPlane`,`send`,`chevron`]),M=e.enum([`filled`,`outline`,`ghost`]),N=e.object({shape:A.default(`circle`).describe("Send button outline shape — `circle` / `square` / `pill`."),icon:j.default(`arrowUp`).describe("Icon inside the send button — `arrowUp` / `paperPlane` / `send` / `chevron`."),variant:M.default(`filled`).describe("Fill treatment — `filled` (solid accent), `outline` (border only), `ghost` (no border, no fill).")}).loose().describe(`Send-button styling — shape, icon, and fill treatment.`).meta({examples:[{shape:`circle`,icon:`arrowUp`,variant:`filled`},{shape:`pill`,icon:`send`,variant:`outline`},{shape:`square`,icon:`paperPlane`,variant:`ghost`}]}),P=e.object({maxBytes:e.number().int().min(0).max(1024*1024*1024).default(10*1024*1024).describe("Maximum size per uploaded file, in bytes. `10 MiB` (10485760) by default."),maxCount:e.number().int().min(0).max(100).default(10).describe(`Maximum number of attachments per message.`),accept:e.string().max(2e3).default(`*/*`).describe("Allowed MIME types — comma-separated `accept` attribute string, e.g. `image/*,application/pdf`.")}).loose().describe(`Client-side attachment limits. Server enforcement is still required.`).meta({examples:[{maxBytes:10485760,maxCount:10,accept:`*/*`},{maxBytes:5242880,maxCount:3,accept:`image/*,application/pdf`}]}),F=e.object({sendButton:N.optional(),attachments:P.optional()}).loose().describe(`Composer chrome — send-button styling + attachment limits.`).meta({examples:[{sendButton:{shape:`circle`,icon:`arrowUp`,variant:`filled`}},{sendButton:{shape:`pill`,icon:`send`,variant:`outline`}},{attachments:{maxBytes:5242880,maxCount:3,accept:`image/*,application/pdf`}}]}),I=e.object({text:e.string().max(200).optional().describe("Visible attribution text (e.g. `Powered by Help AI`)."),href:e.url().max(2048).optional().describe("Click target — the attribution becomes a link. Must be a full URL (`https://…`)."),logoUrl:e.url().max(2048).optional().describe(`Small logo rendered before the text. Must be a full URL.`)}).loose().describe(`"Powered by …" attribution shown below the composer.`).meta({examples:[{text:`Powered by Help AI`},{text:`Powered by Help AI`,href:`https://help.ai`,logoUrl:`https://help.ai/logo.svg`}]}),L=e.object({poweredBy:I.optional(),composerDisclaimer:e.string().max(500).optional().describe(`Small muted text under the composer (like ChatGPT's 'ChatGPT can make mistakes.'). Empty = hidden.`)}).loose().describe(`Footer — attribution + composer disclaimer.`).meta({examples:[{poweredBy:{text:`Powered by Help AI`,href:`https://help.ai`}},{composerDisclaimer:`AI responses may be inaccurate.`}]}),R=e.enum([`text`,`email`,`tel`,`url`,`number`,`date`,`time`,`textarea`,`select`,`radio`,`checkbox`,`multiselect`]),z=e.object({value:e.string().min(1).max(200).describe(`The value recorded when this choice is picked.`),label:e.string().min(1).max(200).optional().describe("Display text; falls back to `value`."),description:e.string().max(280).optional().describe(`Optional sub-label under the choice.`)}).loose(),B=e.object({pattern:e.string().max(500).optional().describe("Regex source string — text-like fields (e.g. `^\\d{5}$`)."),minLength:e.number().int().min(0).max(1e4).optional(),maxLength:e.number().int().min(1).max(1e4).optional(),min:e.number().optional().describe("Minimum — `number` fields."),max:e.number().optional().describe("Maximum — `number` fields."),minSelections:e.number().int().min(0).max(50).optional().describe("Minimum picks — `multiselect`."),maxSelections:e.number().int().min(1).max(50).optional().describe("Maximum picks — `multiselect`.")}).loose(),V=e.object({name:e.string().min(1).max(80).describe("Stable key the answer is recorded under (e.g. `email`)."),label:e.string().min(1).max(200).describe(`Visible field label.`),type:R.describe(`Field renderer + built-in validation (email/tel/url/number/date/time checked).`),placeholder:e.string().max(200).optional(),required:e.boolean().optional().default(!0).describe("Must be answered to submit. `false` allows skipping."),defaultValue:e.string().max(2e3).optional().describe("Pre-filled value (comma-join for `multiselect`)."),options:e.array(z).max(50).optional().describe("Choices for `select` / `radio` / `multiselect`."),validation:B.optional(),allowOther:e.boolean().optional().describe("`select`/`radio`/`multiselect` — allow a free-text 'Other' answer."),validationHint:e.string().max(280).optional().describe(`Small helper line under the field.`)}).loose(),H=e.string().regex(/^(pre-chat|conversation-closed|panel-close|manual|after-messages:\d+|idle:\d+|page-area:.+)$/,`Unrecognised form trigger`).describe("When the form fires: `pre-chat`, `after-messages:N`, `conversation-closed`, `panel-close`, `idle:Nseconds`, `page-area:<area>`, or `manual`."),U=e.object({missingContext:e.array(e.string().max(80)).max(20).optional().describe("Only show if `userContext` lacks ALL of these keys (progressive profiling)."),pageArea:e.union([e.string().max(64),e.array(e.string().max(64)).max(20)]).optional().describe("Only on these `pageContext.area` values."),minMessages:e.number().int().min(0).max(1e3).optional(),maxMessages:e.number().int().min(0).max(1e3).optional()}).loose(),ie=e.object({value:e.string().min(1).max(200).describe("The canonical option `value` this localizes."),label:e.string().min(1).max(200).optional(),description:e.string().max(280).optional()}).loose(),W=e.object({name:e.string().min(1).max(80).describe("The canonical field `name` this localizes."),label:e.string().min(1).max(200).optional(),placeholder:e.string().max(200).optional(),validationHint:e.string().max(280).optional(),options:e.array(ie).max(50).optional()}).loose(),G=e.object({locale:a,title:e.string().max(120).optional(),description:e.string().max(500).optional(),submitLabel:e.string().max(60).optional(),fields:e.array(W).max(50).optional()}).loose(),K=e.object({id:e.string().min(1).max(80).describe("Stable id — persistence dedupe + `manual` openForm(id)."),on:e.union([H,e.array(H).min(1).max(8)]).describe(`Trigger(s) that surface this form.`),when:U.optional().describe(`Extra eligibility predicate evaluated when a trigger fires.`),fields:e.array(V).max(20).default([]).describe(`The questions, in order. ≥1 required to show.`),title:e.string().max(120).optional(),description:e.string().max(500).optional(),submitLabel:e.string().max(60).optional(),skippable:e.boolean().default(!1).describe(`Show a Skip control so the visitor can dismiss the form.`),frequency:e.enum([`once`,`conversation`,`always`]).default(`once`).describe("`once` (per device, persisted), `conversation` (re-eligible each new conversation), or `always`."),mirrorToContext:e.boolean().default(!0).describe("Mirror the answers into `userContext` so they ride every request. Set `false` for PII (DOB, policy #, symptoms) — those then go only to the submit endpoint."),reopenable:e.boolean().default(!0).describe('Skipped marker offers a "Fill out" button that reopens the form. Set `false` when a skip must be final (e.g. a consent ask that should not be re-surfaced).'),reviewable:e.boolean().default(!0).describe("Submitted marker expands in place to a read-only list of the visitor's answers. Set `false` for sensitive answers that shouldn't linger on screen."),defaultLocale:a.optional().describe(`BCP-47 locale the top-level strings (title / fields copy) are authored in.`),translations:e.array(G).max(50).optional().describe("Per-locale string overrides — the data module trims to the bootstrap `?locale=` (≤1); the widget overlays it onto the default copy.")}).loose(),q=e.array(K).max(20).describe("Event-driven forms — an ordered list (order = priority). Each binds to trigger event(s), gates the chat until submit/skip, dedupes by frequency, and records via `endpoints.submitForm`. Generic across verticals.").meta({examples:[[{id:`intake`,on:`pre-chat`,fields:[{name:`email`,label:`Email`,type:`email`}]}],[{id:`lead`,on:`pre-chat`,title:`Before we start`,fields:[{name:`name`,label:`Your name`,type:`text`},{name:`email`,label:`Work email`,type:`email`}]},{id:`csat`,on:`conversation-closed`,frequency:`always`,fields:[{name:`rating`,label:`How did we do?`,type:`radio`,options:[{value:`good`},{value:`bad`}]}]},{id:`appointment`,on:[`page-area:booking`,`manual`],mirrorToContext:!1,fields:[{name:`department`,label:`Department`,type:`select`,options:[{value:`dermatology`},{value:`cardiology`}]},{name:`date`,label:`Preferred date`,type:`date`},{name:`consent`,label:`I consent to be contacted`,type:`checkbox`}]}]]}),J=e.record(e.string(),e.string()),Y=e.union([J,e.record(a,J)]).describe(`Per-instance UI string overrides. Flat = active-locale only; nested = multi-locale map. Both forms are partial — missing keys fall through to built-in defaults.`).meta({examples:[{send:`Click`,stop:`Halt`,composerPlaceholder:`Type your question…`},{en:{send:`Send`,composerPlaceholder:`Type a message…`},fr:{send:`Envoyer`,composerPlaceholder:`Tapez un message…`}}]}),X=e.object({locale:a.optional().describe("BCP-47 locale tag forced for this widget instance (e.g. `fr-CA`). Page-owner explicit override."),defaultLocale:e.union([e.literal(`auto`),a]).default(`auto`).describe("Initial / fallback locale for users who haven't picked one. `auto` sniffs `navigator.language`."),availableLocales:e.array(a).max(200).optional().describe(`BCP-47 locale tags shown in the runtime language switcher. Hidden when fewer than 2 entries.`),strings:Y.optional()}).loose().describe(`Locale + i18n overrides.`).meta({examples:[{defaultLocale:`auto`},{defaultLocale:`en`,availableLocales:[`en`,`fr`,`de`]},{locale:`fr-CA`,strings:{send:`Envoyer`}}]}),ae=e.enum([`chat`,`home`,`help`,`news`]),oe=e.object({label:e.string().min(1).max(40).describe("Tab label — an i18n key (resolved against the i18n strings, e.g. `tabHome`) or a literal. Translations ride `i18n.strings`."),layout:ae.describe("UI layout that renders this tab: `chat` (the conversation), `home`, `help`, or `news`."),contentTags:e.array(e.string().max(60)).max(20).optional().describe("Content tags this tab scopes to — the `tags` filter on `GET /content` (matches content tagged with ANY of them). Omit for the `chat` layout."),id:e.string().max(60).optional().describe("Stable id for navigation + last-tab persistence. Defaults to the first `contentTags` entry, else `layout`."),brandName:e.string().max(80).optional().describe("`home` — hero wordmark (e.g. your company name)."),hideGreeting:e.boolean().optional().describe("`home` — hide the greeting hero. Unset/`false` = shown (default), `true` = hidden."),greetingText:e.string().max(280).optional().describe("`home` — override the greeting headline (default 'How can we help?'); supports a `{name}` token."),userAvatars:e.array(e.object({name:e.string().min(1).max(80),avatar:e.string().max(2048).optional().describe("Image URL; falls back to initials of `name`."),role:e.string().max(80).optional()}).loose()).max(10).optional().describe("`home` — team/agent avatars shown in the hero."),hideSearchBar:e.boolean().optional().describe("`home` — hide the 'Search for help' bar. Unset/`false` = shown (default), `true` = hidden."),hideRecentConversations:e.boolean().optional().describe("`home` — hide the visitor's most recent conversation card. Unset/`false` = shown (default), `true` = hidden."),status:e.object({text:e.string().min(1).max(120).optional().describe("`home` — status line; an i18n key or a literal (resolved via `localizeText`). Omit to use the built-in generic `homeStatus` string (localized, no custom key needed)."),level:e.string().max(40).optional().describe("`home` — status severity, drives the status icon colour. Free text; `operational` (green, default), `degraded` (amber), and `down` (red) are styled, any other value falls back to the operational style.").meta({examples:[`operational`,`degraded`,`down`]}),url:e.string().max(2048).optional().describe(`Opens in an in-widget iframe when tapped.`)}).optional().describe("`home` — system-status card. Omit to hide."),contentBlockTitle:e.string().max(80).optional().describe("`home` — heading for the content list built from `contentTags` (default 'Popular articles').")}).loose(),se=e.array(oe).max(4).describe("Messenger tabs — an ordered list of up to 4 tabs, each picking a `layout` + optional content `contentTags` (the content scope) + a translatable `label`. One tab → no tab bar (just that content); zero → an empty state. Floating / drawer / modal only.").meta({examples:[[{label:`tabConversations`,layout:`chat`}],[{label:`tabHome`,layout:`home`,brandName:`Acme`,contentBlockTitle:`Popular articles`,contentTags:[`popular`]},{label:`tabConversations`,layout:`chat`},{label:`tabHelp`,layout:`help`,contentTags:[`help`,`guides`]},{label:`tabNews`,layout:`news`,contentTags:[`news`]}]]}),ce=e.object({enabled:e.boolean().optional().describe("Master switch. Default `true` — the widget always fires; the data module gates ingestion per deployment server-side. Set `false` to silence the client entirely."),endpoint:e.url().max(2048).optional().describe("Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif` (e.g. `https://help.ai/api/data/pai/elements-px.gif`). Must be a full URL."),sampleRate:e.number().min(0).max(1).optional().describe("Per-visitor sampling 0..1 (decided once per page load, keeping funnels intact). Default `1`."),token:e.string().max(512).optional().describe("Anti-forgery token, echoed as `tk=` on every hit. Server-issued in the `/handshake` response — never set by hand (see `docs/api/tracking-collector.md`).")}).loose().describe(`Anonymous usage tracking for the widget owner — GA-style pixel events (open, send, form submit, …) with page / device / locale dimensions. Never includes message content; visitors are identified only by the widget's anonymous visitorId.`).meta({examples:[{enabled:!0},{enabled:!0,sampleRate:.5}]}),le=e.object({upload:e.string().min(1).max(2048).default(`/pai/upload-file`),transcribe:e.string().min(1).max(2048).default(`/pai/transcribe-audio`),submitForm:e.string().min(1).max(2048).default(`/pai/submit-form`).describe("Form submission endpoint. The widget POSTs each completed form's values here (fire-and-forget), keyed by the same visitorId + conversationId as the conversation; the payload carries `formId` + `trigger` so the backend can route. Optional — a 404 is ignored.")}).loose().describe("HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`dataApiBaseUrl`); absolute URLs are accepted too.").meta({examples:[{upload:`/pai/upload-file`,transcribe:`/pai/transcribe-audio`},{upload:`https://help.ai/uploads/presign`},{submitForm:`https://crm.acme.com/leads`}]}),ue=e.object({id:e.string().min(1).max(200).optional().describe(`Host's stable id for the user — informational context the agent/backend can key on (not auth).`),email:e.string().min(1).max(320).optional().describe(`User email — surfaced to the agent for context (optional).`),name:e.string().min(1).max(200).optional().describe("Display name — shown in the Home greeting (`{name}`) and conversation transcripts (optional)."),plan:e.string().min(1).max(120).optional().describe("Subscription / pricing tier, e.g. `pro` (optional)."),role:e.string().min(1).max(120).optional().describe("The user's role on the host site, e.g. `admin` (optional)."),phone:e.string().min(1).max(40).optional().describe(`Phone number (optional).`)}).catchall(e.union([e.string(),e.number(),e.boolean()])).describe("Host-asserted end-user context (informational, untrusted — not authentication). Recognised `id` / `email` / `name` / `plan` / `role` / `phone` plus any extra custom scalar fields forwarded to the agent.").meta({examples:[{id:`u_123`},{id:`u_123`,email:`alex@acme.com`,name:`Alex Lee`,plan:`pro`}]}),de=[`home`,`docs`,`help-desk`,`support`,`pricing`,`checkout`,`orders`,`account`,`blog`],fe=e.object({area:e.string().min(1).max(64).optional().describe(`Host-defined surface the visitor is on. Free-form; suggested: ${de.join(` | `)}.`),url:e.string().min(1).max(2048).optional().describe(`Full page URL. Auto-filled from the host page when omitted.`),path:e.string().min(1).max(2048).optional().describe("Page path, e.g. `/pricing/enterprise`."),title:e.string().min(1).max(300).optional().describe(`Human-readable page title.`)}).catchall(e.union([e.string(),e.number(),e.boolean()])).describe("Host-asserted page/visit context (informational, untrusted). Where the visitor is + the surface (`area`) they're using, plus any custom scalar fields, forwarded to the agent.").meta({examples:[{area:`pricing`,path:`/pricing`},{area:`help-desk`}]}),Z=e.object({widgetId:e.string().min(1).max(80).default(`default`).describe(`Stable per-instance id used to namespace localStorage keys. Set this when mounting more than one widget on the same page so their conversation state doesn't collide.`),publicKey:e.string().min(1).max(200).optional().describe("Workspace-scoped public key (`agent_pk_…`) issued from the dashboard. Sent on every API call as the `x-public-key` header."),aiAgentDeploymentId:e.string().min(1).max(200).optional().describe("Deployment UUID from the dashboard. Picks which agent / settings bundle answers this mount. Sent as `x-ai-agent-deployment-id`."),baseUrl:e.string().min(1).max(2048).optional().describe("MAIN site origin (e.g. `https://help.ai`) — the API modules derive from it: agent API at `${baseUrl}/api/agent`, data API at `${baseUrl}/api/data`. Set this to point at your staging / self-hosted / custom backend. Default: the brand's `defaultBaseUrl` baked at build time."),agentApiBaseUrl:e.string().min(1).max(2048).optional().describe("Full agent-API base — set it to reach a STANDALONE `module-help-ai-agent-api` directly (local module on its own port, e.g. `http://localhost:3087`; routes attach as-is: `/pai/handshake`). Precedence: this option > derived from the main origin (`${baseUrl}/api/agent`). Not server-pushable."),dataApiBaseUrl:e.string().min(1).max(2048).optional().describe("Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) — the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived from the main origin (`${baseUrl}/api/data`)."),userContext:ue.optional(),pageContext:fe.optional(),endpoints:le.optional(),debug:e.union([e.boolean(),e.enum([`off`,`error`,`warn`,`info`,`debug`,`trace`])]).optional().describe('Console log verbosity. `false` / `"off"` silences everything (default in production). `true` → `"debug"`. Levels `error` / `warn` / `info` / `debug` / `trace` gate output additively. Use `"trace"` to capture per-chunk SSE frames + every state transition. Also toggleable at runtime via `chat.setDebug(level)` or `?<brand>-debug=trace` in the page URL — the URL beats this option, this option beats the persisted `localStorage` value.')}).loose().describe("Where the widget talks to and how it authenticates. Owned by the embedding developer (typically baked into the page template / env var) — distinct from `userPrefs`, which is the dashboard-pushable UX surface.").meta({examples:[{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,widgetId:`support`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,baseUrl:`https://api.acme.com`}]}),Q=e.object({presentation:c.optional(),behavior:u.optional(),theme:p.default(`auto`).describe("Theme preference (`auto` follows OS) or a tokens override object (`accent`, `radius`, `fontFamily`)."),launcher:y.optional(),header:T.optional(),composer:F.optional(),feedback:k.optional(),i18n:X.optional(),footer:L.optional(),features:S.optional(),forms:q.optional(),modules:se.optional(),tracking:ce.optional()}).loose().describe("Portal-configurable widget settings — fourteen sections, one per dashboard tab. The backend pushes this same shape on `/pai/handshake` under `config`.").meta({examples:[{presentation:{mode:`floating`,position:`bottom-right`},theme:`auto`},{presentation:{mode:`floating`},theme:{accent:`#7c3aed`,radius:`12px`},launcher:{variant:`pill`,label:`Ask AI`,callout:{text:`👋 Need help?`}}},{presentation:{mode:`inline`},behavior:{responseMode:`streaming`},features:{voice:`local`}}]}),$=Z.extend({...Q.shape,site:e.unknown().optional().describe('Site config — applies in `mode: "page"`. Comes from the handshake response, not user-edited.'),blocks:e.unknown().optional().describe('Blocks (nav + link cards) — applies in `mode: "page"`. Comes from the handshake response.')}).describe("Full client widget config — connection (where + auth) + widget settings (look + behaviour) + page-mode extras. This is what the runtime parses on `mount()` / `init()`. Mode-specific constraints (e.g. `position` only meaningful in `floating`) are NOT enforced here — the runtime silently ignores irrelevant fields rather than rejecting them so the same object can flow across mode changes.").meta({examples:[{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,presentation:{mode:`floating`},theme:`auto`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,presentation:{mode:`modal`,size:{width:`720px`,height:`640px`}}}]}),pe=$.partial(),me=Q.partial(),he=Z.partial(),ge=Q.partial().omit({forms:!0}).extend({dataApiBaseUrl:e.string().min(1).max(2048).optional(),storageVersion:e.string().min(1).max(64).optional()}),_e=e.object({title:e.string().min(1).max(120).optional().describe(`Brand / site name. Used as the logo's alt-text fallback.`),logo:t.optional().describe(`Brand logo shown at the top of the page-mode sidebar.`),logoDark:t.optional().describe("Optional dark-theme logo variant. Falls back to `logo` when the active theme is light or `logoDark` is unset.")}).loose(),ve=e.object({navigation:e.array(n).max(100).optional().describe(`Sidebar navigation links (vertical list, primary nav).`),linkCards:e.array(n).max(100).optional().describe("Sidebar link cards (richer entries with optional `description`).")}).loose(),ye=e.object({id:e.string(),role:e.enum([`assistant`,`system`]),text:e.string()}).loose(),be=e.object({id:e.string(),label:e.string(),text:e.string().optional()}).loose(),xe=e.enum([`conflict`,`expired`,`invalid`]),Se=e.object({deployment:e.object({id:e.string(),name:e.string(),slug:e.string().optional(),publicKey:e.string().optional()}).loose(),agent:e.object({id:e.string(),name:e.string(),title:e.string().optional(),status:e.enum([`online`,`away`,`offline`]).optional()}).loose(),config:ge.optional(),site:_e.optional(),blocks:ve.optional(),welcome:e.object({messages:e.array(ye).optional(),suggestions:e.array(be).optional()}).loose().optional(),visitorId:e.string(),conversationId:e.string(),userPrefs:e.record(e.string(),e.unknown()).optional(),rebind:e.object({visitorId:xe.optional(),conversationId:xe.optional()}).loose().optional()}).loose(),Ce=[`theme`,`header`,`composer`,`footer`,`i18n`,`features`,`feedback`,`tracking`],we={floating:[`presentation`,`behavior`,`modules`,`launcher`],inline:[`presentation`,`behavior`],modal:[`presentation`,`behavior`,`modules`],drawer:[`presentation`,`behavior`,`modules`,`launcher`],page:[`presentation`],standalone:[`presentation`]};function Te(e){let t=[...we[e],...Ce],n={};for(let e of t)n[e]=!0;return Q.pick(n)}const Ee=[`floating`,`inline`,`standalone`,`page`,`modal`,`drawer`];function De(){return{$schema:`https://json-schema.org/draft/2020-12/schema`,title:`@helpai/elements config`,description:`Canonical config schemas for the embeddable AI agent elements widget.`,definitions:{WidgetConfig:e.toJSONSchema($),HandshakeResponse:e.toJSONSchema(Se)}}}export{Ee as ALL_MODES,de as PAGE_AREA_SUGGESTIONS,C as actionNameSchema,t as assetSchema,P as attachmentLimitsSchema,u as behaviorSchema,ve as blocksConfigSchema,_ as calloutPositionSchema,g as calloutShapeSchema,F as composerOptionsSchema,he as connectionConfigPartialSchema,Z as connectionConfigSchema,i as cssColorSchema,r as cssLengthSchema,De as emitJsonSchema,le as endpointsSchema,S as featureFlagsSchema,E as feedbackEventSchema,k as feedbackSchema,z as fieldOptionSchema,ie as fieldOptionTranslationSchema,R as fieldTypeSchema,B as fieldValidationSchema,L as footerSchema,U as formConditionSchema,K as formDefSchema,V as formFieldSchema,W as formFieldTranslationSchema,G as formTranslationSchema,H as formTriggerSchema,q as formsSchema,Se as handshakeResponseSchema,O as hapticsOptionsSchema,w as headerActionsSchema,T as headerSchema,X as i18nSchema,o as initialSizeSchema,v as launcherCalloutSchema,y as launcherOptionsSchema,h as launcherSizeSchema,m as launcherVariantSchema,n as linkSchema,a as localeSchema,ne as modeSchema,ae as moduleLayoutSchema,oe as moduleSchema,se as modulesSchema,fe as pageContextSchema,re as positionSchema,I as poweredBySchema,c as presentationSchema,s as resizeOptionsSchema,l as responseModeSchema,j as sendButtonIconSchema,N as sendButtonOptionsSchema,A as sendButtonShapeSchema,M as sendButtonVariantSchema,ge as serverConfigSchema,_e as siteConfigSchema,te as sizeOptionsSchema,D as soundOptionsSchema,Y as stringsOverrideSchema,p as themeFieldSchema,f as themeOverridesSchema,d as themePreferenceSchema,x as toolRefSchema,ce as trackingSchema,ue as userContextSchema,ee as uuid7Schema,b as voiceModeSchema,pe as widgetConfigPartialSchema,$ as widgetConfigSchema,me as widgetSettingsPartialSchema,Q as widgetSettingsSchema,Te as widgetSettingsSchemaForMode};
|
|
1
|
+
import{z as e}from"zod";const t=e.object({url:e.string().min(1).max(2048).describe(`Public URL of the image. Must be a full URL or root-relative path.`),alt:e.string().min(1).max(200).optional().describe(`Alt text for screen readers. Omit only for purely decorative images.`)}).strict().describe(`A single image asset (logo, hero, icon).`),n=e.object({id:e.string().min(1).max(100).optional().describe(`Stable id used as React key + analytics target.`),label:e.string().min(1).max(120).describe(`Visible link text.`),href:e.string().min(1).max(2048).optional().describe(`Click target. Optional — when omitted the link renders as a non-clickable heading.`),icon:e.string().min(1).max(100).optional().describe(`Built-in icon preset name (chat / spark / message / help / wand) or a custom string.`),description:e.string().min(1).max(300).optional().describe(`Subtitle shown below the label. Used by link cards in page mode.`)}).loose().describe(`A navigation link / link card.`),r=e.string().min(1).max(120).describe("Any CSS length — `640px`, `80vh`, `calc(100vh - 64px)`, etc. Validated only for size, not syntax."),i=e.string().min(1).max(120).describe("Any CSS colour — hex, `rgb()`, `hsl()`, `oklch()`, a named colour, or a `var(--token)`."),a=e.string().min(1).max(35).describe("BCP-47 locale tag (e.g. `en`, `fr-CA`, `zh-Hant-HK`)."),ee=e.uuidv7().describe(`UUID v7 (RFC 9562) — the single id format for visitor / conversation / message / file / content ids.`),o=e.enum([`normal`,`expanded`,`fullscreen`,`auto`]),s=e.object({enabled:e.boolean().default(!1).describe(`Show a corner-grip handle the user can drag to resize the panel.`),minWidth:r.optional().describe(`Smallest width the user can drag the panel to.`),maxWidth:r.optional().describe(`Largest width the user can drag the panel to.`),minHeight:r.optional().describe(`Smallest height the user can drag the panel to.`),maxHeight:r.optional().describe(`Largest height the user can drag the panel to.`)}).loose().describe("Drag-resize controls. When `enabled`, a corner grip lets users resize the panel within the optional min/max bounds.").meta({examples:[{enabled:!1},{enabled:!0,minWidth:`320px`,maxWidth:`720px`,minHeight:`400px`,maxHeight:`90vh`}]}),te=e.object({width:r.optional().describe("Panel width (CSS length). Mode-specific defaults — floating `380px`, modal `min(960px, 92vw)`, drawer `min(440px, calc(100vw - 32px))`. Set this to override; inline/standalone/page modes ignore it."),height:r.optional().describe("Panel height (CSS length). Mode-specific defaults — floating `600px`, modal `min(720px, 88vh)`, drawer `100vh` (clamped to `100vh − inset-y × 2`). Set this to override."),expanded:e.object({width:r.optional().describe(`Width when the user clicks the expand button.`),height:r.optional().describe(`Height when the user clicks the expand button.`)}).loose().optional().describe("Dimensions when the panel is in its `expanded` tier (between normal and fullscreen). Applies to floating / modal / drawer; ignored in inline / standalone / page where the panel always fills its parent."),resize:s.optional().describe(`Drag-resize controls — adds a corner grip the user can drag.`),inset:r.optional().describe("Drawer-mode edge inset — gap from each viewport edge (top/bottom/left/right). Single value applied to all four sides. Defaults to `3vh` vertical / `12px` horizontal. Use `0` for a full-edge drawer (no gap), or `5vh` for a centered-looking flyout with extra breathing room. Ignored by every other mode."),initialSize:o.default(`normal`).describe("Which size tier to open with on the first mount: `normal` / `expanded` / `fullscreen` / `auto` (picks expanded above `autoSizeBreakpoint` viewport width)."),autoSizeBreakpoint:e.number().int().min(0).max(1e4).default(900).describe("Viewport width (px) above which `initialSize: auto` resolves to `expanded` instead of `normal`.")}).loose().describe("Panel dimensions and drawer inset. Width/height override the mode-specific defaults (floating compact popover, modal centered dialog, drawer flyout). `inset` only affects drawer mode.").meta({examples:[{width:`420px`,height:`640px`},{width:`min(560px, 92vw)`,height:`min(640px, 90vh)`},{width:`420px`,expanded:{width:`640px`,height:`780px`},initialSize:`auto`,autoSizeBreakpoint:900},{width:`min(1100px, 95vw)`,height:`min(820px, 92vh)`},{width:`360px`,inset:`8vh`},{width:`420px`,height:`100vh`,inset:`0`},{width:`420px`,height:`60vh`,inset:`20vh`}]}),ne=e.enum([`floating`,`inline`,`standalone`,`page`,`modal`,`drawer`]),re=e.enum([`bottom-right`,`bottom-left`,`top-right`,`top-left`]),c=e.object({mode:ne.default(`floating`).describe("Rendering shape. `floating` (FAB + popover), `inline` (in-flow block), `standalone` (full viewport), `page` (sidebar + chat), `modal` (centered overlay), `drawer` (side dock)."),position:re.default(`bottom-right`).describe("Anchor corner. `floating` uses it for the FAB; `drawer` uses the `*-left` / `*-right` suffix to pick the dock side. Ignored in other modes."),iframe:e.boolean().default(!1).describe(`Wrap the widget in a same-origin iframe for stricter JS + CSS isolation from the host page. Composes with every mode.`),size:te.optional().describe("Panel dimensions. Mode-aware defaults (floating compact popover, modal centered dialog, drawer flyout) — fields here override them. Includes `inset` (drawer flyout gap), `expanded` tier, drag-resize grip.")}).loose().describe(`Layout fundamentals — mode, anchor corner, iframe isolation, panel size + drawer inset.`).meta({examples:[{mode:`floating`,position:`bottom-right`},{mode:`modal`,size:{width:`min(1100px, 95vw)`,height:`min(820px, 92vh)`}},{mode:`drawer`,position:`bottom-right`},{mode:`drawer`,position:`top-right`,size:{width:`360px`,inset:`8vh`}},{mode:`drawer`,position:`bottom-right`,size:{width:`420px`,height:`100vh`,inset:`0`}}]}),l=e.enum([`streaming`,`buffered`]),u=e.object({startMinimized:e.boolean().default(!0).describe("Don't auto-open the floating panel on first visit. `true` (default) shows the FAB collapsed; `false` opens the panel on mount."),responseMode:l.default(`streaming`).describe("How the assistant's reply arrives. `streaming` (default) types tokens as they generate; `buffered` waits + shows the full reply at once."),showReasoning:e.boolean().default(!1).describe('Show the model\'s reasoning ("thoughts") as a collapsible block above each answer. `false` (default) hides it — a loading indicator still shows while the model works. Reasoning is never persisted; it only appears live.'),showToolCalls:e.boolean().default(!1).describe("Show automatic tool/function calls the model makes (e.g. search) as collapsible detail+result cards in the transcript. `false` (default) hides them. Interactive tools (ask-questions / approval) always show."),showSources:e.boolean().default(!1).describe("Show the citation sources behind an answer (web links + document/file references) in the transcript. `false` (default) hides them."),disableMessageFeedback:e.boolean().default(!1).describe("Turn OFF the 👍/👎 feedback controls under each rateable reply (AI or operator). Unset/`false` = shown (default), `true` = hidden. A choice fires the `messageFeedback` event and is POSTed best-effort to `/pai/message-feedback`."),autoSendSuggestions:e.boolean().default(!1).describe("Auto-send a suggestion chip's text the moment it's tapped. `false` (default) fills the composer with the text so the visitor can edit before sending; `true` sends it immediately.")}).loose().describe(`Conversation behaviour — lifecycle, streaming, and the transcript surface (scroll, feedback).`).meta({examples:[{startMinimized:!0,responseMode:`streaming`},{startMinimized:!1,responseMode:`buffered`,disableMessageFeedback:!0}]}),d=e.enum([`auto`,`light`,`dark`]),f=e.object({accent:i.optional().describe(`Brand accent colour. Drives the FAB, send button, links, and active states. CSS colour.`),accentText:i.optional().describe(`Foreground colour rendered ON the accent (FAB icon, send-button glyph). CSS colour.`),radius:r.optional().describe("Corner radius for the panel + buttons. CSS length (`8px`, `0.75rem`, `12px`)."),fontFamily:e.string().min(1).max(200).optional().describe("Font stack used inside the widget. Standard CSS `font-family` value."),contentMaxWidth:r.optional().describe("Max width of the readable content column (messages, history, home, composer) on a wide surface — content centres, full-bleed bars keep their edges. CSS length; default `768px`. Set `100%` to fill the surface (no cap). Modal + drawer already fill their card by default.")}).loose().describe(`Theme token overrides. Any field left unset falls through to the brand's default theme.`).meta({examples:[{accent:`#10b981`,radius:`12px`},{accent:`#7c3aed`,accentText:`#ffffff`,radius:`16px`,fontFamily:`'Inter', system-ui`},{accent:`oklch(0.7 0.2 145)`,radius:`0.5rem`},{accent:`#5b5bd6`,contentMaxWidth:`960px`}]}),p=e.union([d,f]).describe(`'auto' | 'light' | 'dark', or a tokens override object.`).meta({examples:[`auto`,`dark`,{accent:`#10b981`,radius:`12px`},{accent:`#7c3aed`,accentText:`#fff`,radius:`16px`,fontFamily:`'Inter', system-ui`}]}),m=e.enum([`circle`,`pill`,`bar`,`minimal`]),h=e.enum([`sm`,`md`,`lg`]),g=e.enum([`pill`,`bubble`,`callout`]),_=e.enum([`auto`,`horizontal`,`vertical`]),v=e.object({text:e.string().min(1).max(500).default(`👋 Hi! Need any help?`).describe("The message to show in the bubble. Defaults to a friendly greeting; replace with your own copy (e.g. 'Click here →'). May also be an i18n key (e.g. `launcherCallout`) resolved against `i18n.strings` for per-locale copy; a non-key literal renders as-is."),shape:g.default(`pill`).describe("Visual shape — `pill` (slim label + arrow), `bubble` (speech-bubble tail), `callout` (loud variant)."),position:_.default(`auto`).describe("Where the bubble sits relative to the FAB. `auto` (default) picks the side facing into the page. `horizontal` anchors beside the FAB (left/right depending on the FAB's corner). `vertical` anchors above/below the FAB. Concrete left/right/top/bottom is derived from the FAB's corner so the bubble always stays on-screen."),delayMs:e.number().int().min(0).max(6e4).default(1200).describe(`How long to wait after page load before the bubble appears, in milliseconds.`),autoDismissMs:e.number().int().min(0).max(6e5).default(0).describe("Auto-hide the bubble after this many milliseconds. `0` (default) keeps it until the user dismisses."),animated:e.boolean().default(!0).describe("Subtle horizontal nudge to draw the eye. Disabled automatically by `prefers-reduced-motion`."),persistent:e.boolean().default(!0).describe("How dismissals stick. `true` (default) — re-show on every visit regardless of prior dismissal (the 'recurring greeting' behaviour). `false` — clicking X stores the message text and that exact message stays hidden across visits (the 'one-time hint' behaviour).")}).loose().describe(`Pre-engagement message bubble next to the FAB. Use it for a greeting ('Hi, need help?'), an attention-grabbing nudge ('Click here →'), or any one-time onboarding tip — same component, configured for the use case.`),y=e.object({variant:m.default(`circle`).describe("FAB visual style. `circle` — round bubble (icon only). `pill` — icon + label. `bar` — wide rectangular button. `minimal` — text-only outline."),size:h.default(`md`).describe(`FAB size preset — small / medium / large.`),label:e.string().max(200).optional().describe("Text rendered on the FAB (only shown for `pill` / `bar` / `minimal` variants)."),icon:e.string().max(8e3).optional().describe("Icon shown on the FAB / drawer edge tab. Built-in presets: `chat` / `message` / `bubbles` / `spark` / `wand` / `bot` / `help` / `lifebuoy` / `headset`. Anything else is treated as raw SVG."),hidden:e.boolean().default(!1).describe("Hide the FAB entirely (page brings its own trigger that calls `instance.open()`)."),callout:v.optional()}).loose().describe(`Floating-launcher (FAB) appearance and behaviour. The FAB is the round button in the corner that opens the chat panel. Floating mode only.`).meta({examples:[{variant:`circle`,size:`md`},{variant:`pill`,label:`Ask AI`,icon:`spark`},{variant:`circle`,callout:{text:`👋 Need help?`,shape:`bubble`,persistent:!0}},{variant:`circle`,callout:{text:`Click to start`,shape:`pill`,delayMs:1200}}]}),b=e.enum([`local`,`server`,`disabled`]),x=e.union([e.string().min(1).max(200),e.object({code:e.string().min(1).max(200),config:e.record(e.string(),e.unknown()).optional()}).loose()]),S=e.object({disableFileUpload:e.boolean().default(!1).describe("Turn OFF file uploads — hide the paperclip button + reject drag/drop/paste. Unset/`false` = enabled (default), `true` = disabled."),voice:b.default(`local`).describe("Voice input mode. `local` — Web Speech API in the browser (free, runs on-device). `server` — record audio + upload to the transcribe endpoint. `disabled` — hide the mic button."),tools:e.array(x).max(200).optional().describe("Backend tools the assistant may invoke. Bare codes (`'tool:send-money'`) or rich refs (`{ code, config }`)."),disableHumanInLoop:e.boolean().default(!1).describe("Turn OFF the human-in-the-loop tool UI — the inline ask-questions form + approve/reject controls for gated tools. Unset/`false` = shown (default), `true` = suppressed (the wire still carries the signals)."),enableOperatorRequest:e.boolean().default(!1).describe("Opt IN operator control — expose the 'Talk to an operator' affordance + connected-to-operator states for this deployment. Unset/`false` = off (default), `true` = on. Unlike the `disable*` flags this is a positive opt-in for a new capability.")}).loose().describe(`Capability flags — file upload, voice mode, and the tools the assistant may invoke.`).meta({examples:[{voice:`local`},{disableFileUpload:!0,voice:`disabled`},{voice:`server`,tools:[`tool:send-money`]}]}),C=e.enum([`clear`,`expand`,`fullscreen`,`sound`,`history`,`language`,`theme`,`textSize`,`close`]),w=e.array(C).max(10).describe("Which actions the header exposes. `history` + `close` are dedicated buttons; the rest appear in the ⋯ menu. Unlisted actions are hidden; order is irrelevant. Pick from: `clear`, `expand`, `fullscreen`, `sound`, `history`, `language`, `theme`, `textSize`, `close`. Per-mode defaults live in `DEFAULT_ACTIONS_BY_MODE`.").meta({examples:[[`theme`,`history`,`close`,`clear`,`fullscreen`,`sound`,`language`],[`theme`,`history`,`clear`,`language`],[`close`]]}),T=e.object({actions:w.optional().describe(`Which header actions are enabled (history/✕ buttons + ⋯ menu).`)}).loose().describe(`Panel-header configuration.`).meta({examples:[{actions:[`theme`,`history`,`close`,`clear`,`fullscreen`]}]}),E=e.enum([`messageReceived`,`messageSent`,`error`,`voiceStart`,`voiceStop`]),D=e.object({enabled:e.boolean().default(!0).describe(`Master on/off for audible notifications. On by default — browser autoplay policy still requires a prior user gesture before any sound plays.`),volume:e.number().min(0).max(1).default(.3).describe("Global volume 0..1. `0.3` (default) is intentionally subtle."),events:e.partialRecord(E,e.union([e.boolean(),e.string().min(1).max(2048)])).optional().describe("Per-event override map. Value: `true` = built-in tone, `false` = silent, `string` = URL to a custom audio file (mp3/wav/ogg).")}).loose().describe("Audible notifications. `events` accepts true (default tone), false (off), or a URL to an audio file.").meta({examples:[{enabled:!0,volume:.3},{enabled:!0,volume:.5,events:{messageReceived:!0,error:!1}},{enabled:!0,events:{messageReceived:`https://cdn.help.ai/ping.mp3`}}]}),O=e.object({enabled:e.boolean().default(!0).describe(`Master on/off. Default: on for touch devices, silently ignored elsewhere.`),events:e.partialRecord(E,e.union([e.boolean(),e.number().int(),e.array(e.number().int())])).optional().describe("Per-event vibration pattern. Value: `true` = default pattern, `false` = silent, number = single vibrate ms, array = `[vibrate, pause, vibrate, …]`.")}).loose().describe("Touch-device vibration. `events` accepts true (default), number (single vibrate ms), or [vibrate,pause,vibrate,…].").meta({examples:[{enabled:!0},{enabled:!0,events:{messageReceived:30,error:[40,60,40]}}]}),k=e.object({sound:D.optional(),haptics:O.optional()}).loose().describe(`Audible + tactile feedback.`).meta({examples:[{sound:{enabled:!0,volume:.3},haptics:{enabled:!0}},{sound:{enabled:!1},haptics:{enabled:!1}}]}),A=e.enum([`circle`,`square`,`pill`]),j=e.enum([`arrowUp`,`paperPlane`,`send`,`chevron`]),M=e.enum([`filled`,`outline`,`ghost`]),N=e.object({shape:A.default(`circle`).describe("Send button outline shape — `circle` / `square` / `pill`."),icon:j.default(`arrowUp`).describe("Icon inside the send button — `arrowUp` / `paperPlane` / `send` / `chevron`."),variant:M.default(`filled`).describe("Fill treatment — `filled` (solid accent), `outline` (border only), `ghost` (no border, no fill).")}).loose().describe(`Send-button styling — shape, icon, and fill treatment.`).meta({examples:[{shape:`circle`,icon:`arrowUp`,variant:`filled`},{shape:`pill`,icon:`send`,variant:`outline`},{shape:`square`,icon:`paperPlane`,variant:`ghost`}]}),P=e.object({maxBytes:e.number().int().min(0).max(1024*1024*1024).default(10*1024*1024).describe("Maximum size per uploaded file, in bytes. `10 MiB` (10485760) by default."),maxCount:e.number().int().min(0).max(100).default(10).describe(`Maximum number of attachments per message.`),accept:e.string().max(2e3).default(`*/*`).describe("Allowed MIME types — comma-separated `accept` attribute string, e.g. `image/*,application/pdf`.")}).loose().describe(`Client-side attachment limits. Server enforcement is still required.`).meta({examples:[{maxBytes:10485760,maxCount:10,accept:`*/*`},{maxBytes:5242880,maxCount:3,accept:`image/*,application/pdf`}]}),F=e.object({sendButton:N.optional(),attachments:P.optional()}).loose().describe(`Composer chrome — send-button styling + attachment limits.`).meta({examples:[{sendButton:{shape:`circle`,icon:`arrowUp`,variant:`filled`}},{sendButton:{shape:`pill`,icon:`send`,variant:`outline`}},{attachments:{maxBytes:5242880,maxCount:3,accept:`image/*,application/pdf`}}]}),I=e.object({text:e.string().max(200).optional().describe("Visible attribution text (e.g. `Powered by Help AI`)."),href:e.url().max(2048).optional().describe("Click target — the attribution becomes a link. Must be a full URL (`https://…`)."),logoUrl:e.url().max(2048).optional().describe(`Small logo rendered before the text. Must be a full URL.`)}).loose().describe(`"Powered by …" attribution shown below the composer.`).meta({examples:[{text:`Powered by Help AI`},{text:`Powered by Help AI`,href:`https://help.ai`,logoUrl:`https://help.ai/logo.svg`}]}),L=e.object({poweredBy:I.optional(),composerDisclaimer:e.string().max(500).optional().describe(`Small muted text under the composer (like ChatGPT's 'ChatGPT can make mistakes.'). Empty = hidden.`)}).loose().describe(`Footer — attribution + composer disclaimer.`).meta({examples:[{poweredBy:{text:`Powered by Help AI`,href:`https://help.ai`}},{composerDisclaimer:`AI responses may be inaccurate.`}]}),R=e.enum([`text`,`email`,`tel`,`url`,`number`,`date`,`time`,`textarea`,`select`,`radio`,`checkbox`,`multiselect`]),z=e.object({value:e.string().min(1).max(200).describe(`The value recorded when this choice is picked.`),label:e.string().min(1).max(200).optional().describe("Display text; falls back to `value`."),description:e.string().max(280).optional().describe(`Optional sub-label under the choice.`)}).loose(),B=e.object({pattern:e.string().max(500).optional().describe("Regex source string — text-like fields (e.g. `^\\d{5}$`)."),minLength:e.number().int().min(0).max(1e4).optional(),maxLength:e.number().int().min(1).max(1e4).optional(),min:e.number().optional().describe("Minimum — `number` fields."),max:e.number().optional().describe("Maximum — `number` fields."),minSelections:e.number().int().min(0).max(50).optional().describe("Minimum picks — `multiselect`."),maxSelections:e.number().int().min(1).max(50).optional().describe("Maximum picks — `multiselect`.")}).loose(),V=e.object({name:e.string().min(1).max(80).describe("Stable key the answer is recorded under (e.g. `email`)."),label:e.string().min(1).max(200).describe(`Visible field label.`),type:R.describe(`Field renderer + built-in validation (email/tel/url/number/date/time checked).`),placeholder:e.string().max(200).optional(),required:e.boolean().optional().default(!0).describe("Must be answered to submit. `false` allows skipping."),defaultValue:e.string().max(2e3).optional().describe("Pre-filled value (comma-join for `multiselect`)."),options:e.array(z).max(50).optional().describe("Choices for `select` / `radio` / `multiselect`."),validation:B.optional(),allowOther:e.boolean().optional().describe("`select`/`radio`/`multiselect` — allow a free-text 'Other' answer."),validationHint:e.string().max(280).optional().describe(`Small helper line under the field.`)}).loose(),H=e.string().regex(/^(pre-chat|conversation-closed|panel-close|manual|after-messages:\d+|idle:\d+|page-area:.+)$/,`Unrecognised form trigger`).describe("When the form fires: `pre-chat`, `after-messages:N`, `conversation-closed`, `panel-close`, `idle:Nseconds`, `page-area:<area>`, or `manual`."),U=e.object({missingContext:e.array(e.string().max(80)).max(20).optional().describe("Only show if `userContext` lacks ALL of these keys (progressive profiling)."),pageArea:e.union([e.string().max(64),e.array(e.string().max(64)).max(20)]).optional().describe("Only on these `pageContext.area` values."),minMessages:e.number().int().min(0).max(1e3).optional(),maxMessages:e.number().int().min(0).max(1e3).optional()}).loose(),ie=e.object({value:e.string().min(1).max(200).describe("The canonical option `value` this localizes."),label:e.string().min(1).max(200).optional(),description:e.string().max(280).optional()}).loose(),W=e.object({name:e.string().min(1).max(80).describe("The canonical field `name` this localizes."),label:e.string().min(1).max(200).optional(),placeholder:e.string().max(200).optional(),validationHint:e.string().max(280).optional(),options:e.array(ie).max(50).optional()}).loose(),G=e.object({locale:a,title:e.string().max(120).optional(),description:e.string().max(500).optional(),submitLabel:e.string().max(60).optional(),fields:e.array(W).max(50).optional()}).loose(),K=e.object({id:e.string().min(1).max(80).describe("Stable id — persistence dedupe + `manual` openForm(id)."),on:e.union([H,e.array(H).min(1).max(8)]).describe(`Trigger(s) that surface this form.`),when:U.optional().describe(`Extra eligibility predicate evaluated when a trigger fires.`),fields:e.array(V).max(20).default([]).describe(`The questions, in order. ≥1 required to show.`),title:e.string().max(120).optional(),description:e.string().max(500).optional(),submitLabel:e.string().max(60).optional(),skippable:e.boolean().default(!1).describe(`Show a Skip control so the visitor can dismiss the form.`),frequency:e.enum([`once`,`conversation`,`always`]).default(`once`).describe("`once` (per device, persisted), `conversation` (re-eligible each new conversation), or `always`."),mirrorToContext:e.boolean().default(!0).describe("Mirror the answers into `userContext` so they ride every request. Set `false` for PII (DOB, policy #, symptoms) — those then go only to the submit endpoint."),reopenable:e.boolean().default(!0).describe('Skipped marker offers a "Fill out" button that reopens the form. Set `false` when a skip must be final (e.g. a consent ask that should not be re-surfaced).'),reviewable:e.boolean().default(!0).describe("Submitted marker expands in place to a read-only list of the visitor's answers. Set `false` for sensitive answers that shouldn't linger on screen."),defaultLocale:a.optional().describe(`BCP-47 locale the top-level strings (title / fields copy) are authored in.`),translations:e.array(G).max(50).optional().describe("Per-locale string overrides — the data module trims to the bootstrap `?locale=` (≤1); the widget overlays it onto the default copy.")}).loose(),q=e.array(K).max(20).describe("Event-driven forms — an ordered list (order = priority). Each binds to trigger event(s), gates the chat until submit/skip, dedupes by frequency, and records via `endpoints.submitForm`. Generic across verticals.").meta({examples:[[{id:`intake`,on:`pre-chat`,fields:[{name:`email`,label:`Email`,type:`email`}]}],[{id:`signal`,on:`pre-chat`,title:`Before we start`,fields:[{name:`name`,label:`Your name`,type:`text`},{name:`email`,label:`Work email`,type:`email`}]},{id:`csat`,on:`conversation-closed`,frequency:`always`,fields:[{name:`rating`,label:`How did we do?`,type:`radio`,options:[{value:`good`},{value:`bad`}]}]},{id:`appointment`,on:[`page-area:booking`,`manual`],mirrorToContext:!1,fields:[{name:`department`,label:`Department`,type:`select`,options:[{value:`dermatology`},{value:`cardiology`}]},{name:`date`,label:`Preferred date`,type:`date`},{name:`consent`,label:`I consent to be contacted`,type:`checkbox`}]}]]}),J=e.record(e.string(),e.string()),Y=e.union([J,e.record(a,J)]).describe(`Per-instance UI string overrides. Flat = active-locale only; nested = multi-locale map. Both forms are partial — missing keys fall through to built-in defaults.`).meta({examples:[{send:`Click`,stop:`Halt`,composerPlaceholder:`Type your question…`},{en:{send:`Send`,composerPlaceholder:`Type a message…`},fr:{send:`Envoyer`,composerPlaceholder:`Tapez un message…`}}]}),X=e.object({locale:a.optional().describe("BCP-47 locale tag forced for this widget instance (e.g. `fr-CA`). Page-owner explicit override."),defaultLocale:e.union([e.literal(`auto`),a]).default(`auto`).describe("Initial / fallback locale for users who haven't picked one. `auto` sniffs `navigator.language`."),availableLocales:e.array(a).max(200).optional().describe(`BCP-47 locale tags shown in the runtime language switcher. Hidden when fewer than 2 entries.`),strings:Y.optional()}).loose().describe(`Locale + i18n overrides.`).meta({examples:[{defaultLocale:`auto`},{defaultLocale:`en`,availableLocales:[`en`,`fr`,`de`]},{locale:`fr-CA`,strings:{send:`Envoyer`}}]}),ae=e.enum([`chat`,`home`,`help`,`news`]),oe=e.object({label:e.string().min(1).max(40).describe("Tab label — an i18n key (resolved against the i18n strings, e.g. `tabHome`) or a literal. Translations ride `i18n.strings`."),layout:ae.describe("UI layout that renders this tab: `chat` (the conversation), `home`, `help`, or `news`."),contentTags:e.array(e.string().max(60)).max(20).optional().describe("Content tags this tab scopes to — the `tags` filter on `GET /content` (matches content tagged with ANY of them). Omit for the `chat` layout."),id:e.string().max(60).optional().describe("Stable id for navigation + last-tab persistence. Defaults to the first `contentTags` entry, else `layout`."),brandName:e.string().max(80).optional().describe("`home` — hero wordmark (e.g. your company name)."),hideGreeting:e.boolean().optional().describe("`home` — hide the greeting hero. Unset/`false` = shown (default), `true` = hidden."),greetingText:e.string().max(280).optional().describe("`home` — override the greeting headline (default 'How can we help?'); supports a `{name}` token."),userAvatars:e.array(e.object({name:e.string().min(1).max(80),avatar:e.string().max(2048).optional().describe("Image URL; falls back to initials of `name`."),role:e.string().max(80).optional()}).loose()).max(10).optional().describe("`home` — team/agent avatars shown in the hero."),hideSearchBar:e.boolean().optional().describe("`home` — hide the 'Search for help' bar. Unset/`false` = shown (default), `true` = hidden."),hideRecentConversations:e.boolean().optional().describe("`home` — hide the visitor's most recent conversation card. Unset/`false` = shown (default), `true` = hidden."),status:e.object({text:e.string().min(1).max(120).optional().describe("`home` — status line; an i18n key or a literal (resolved via `localizeText`). Omit to use the built-in generic `homeStatus` string (localized, no custom key needed)."),level:e.string().max(40).optional().describe("`home` — status severity, drives the status icon colour. Free text; `operational` (green, default), `degraded` (amber), and `down` (red) are styled, any other value falls back to the operational style.").meta({examples:[`operational`,`degraded`,`down`]}),url:e.string().max(2048).optional().describe(`Opens in an in-widget iframe when tapped.`)}).optional().describe("`home` — system-status card. Omit to hide."),contentBlockTitle:e.string().max(80).optional().describe("`home` — heading for the content list built from `contentTags` (default 'Popular articles').")}).loose(),se=e.array(oe).max(4).describe("Messenger tabs — an ordered list of up to 4 tabs, each picking a `layout` + optional content `contentTags` (the content scope) + a translatable `label`. One tab → no tab bar (just that content); zero → an empty state. Floating / drawer / modal only.").meta({examples:[[{label:`tabConversations`,layout:`chat`}],[{label:`tabHome`,layout:`home`,brandName:`Acme`,contentBlockTitle:`Popular articles`,contentTags:[`popular`]},{label:`tabConversations`,layout:`chat`},{label:`tabHelp`,layout:`help`,contentTags:[`help`,`guides`]},{label:`tabNews`,layout:`news`,contentTags:[`news`]}]]}),ce=e.object({enabled:e.boolean().optional().describe("Master switch. Default `true` — the widget always fires; the data module gates ingestion per deployment server-side. Set `false` to silence the client entirely."),endpoint:e.url().max(2048).optional().describe("Pixel collector URL. Default: `${dataApiBaseUrl}/pai/elements-px.gif` (e.g. `https://help.ai/api/data/pai/elements-px.gif`). Must be a full URL."),sampleRate:e.number().min(0).max(1).optional().describe("Per-visitor sampling 0..1 (decided once per page load, keeping funnels intact). Default `1`."),token:e.string().max(512).optional().describe("Anti-forgery token, echoed as `tk=` on every hit. Server-issued in the `/handshake` response — never set by hand (see `docs/api/tracking-collector.md`).")}).loose().describe(`Anonymous usage tracking for the widget owner — GA-style pixel events (open, send, form submit, …) with page / device / locale dimensions. Never includes message content; visitors are identified only by the widget's anonymous visitorId.`).meta({examples:[{enabled:!0},{enabled:!0,sampleRate:.5}]}),le=e.object({upload:e.string().min(1).max(2048).default(`/pai/upload-file`),transcribe:e.string().min(1).max(2048).default(`/pai/transcribe-audio`),submitForm:e.string().min(1).max(2048).default(`/pai/submit-form`).describe("Form submission endpoint. The widget POSTs each completed form's values here (fire-and-forget), keyed by the same visitorId + conversationId as the conversation; the payload carries `formId` + `trigger` so the backend can route. Optional — a 404 is ignored.")}).loose().describe("HTTP endpoint overrides. `upload` / `transcribe` paths are appended to the agent base (`${baseUrl}/api/agent`), `submitForm` to the data base (`dataApiBaseUrl`); absolute URLs are accepted too.").meta({examples:[{upload:`/pai/upload-file`,transcribe:`/pai/transcribe-audio`},{upload:`https://help.ai/uploads/presign`},{submitForm:`https://crm.acme.com/contacts`}]}),ue=e.object({id:e.string().min(1).max(200).optional().describe(`Host's stable id for the user — informational context the agent/backend can key on (not auth).`),email:e.string().min(1).max(320).optional().describe(`User email — surfaced to the agent for context (optional).`),name:e.string().min(1).max(200).optional().describe("Display name — shown in the Home greeting (`{name}`) and conversation transcripts (optional)."),plan:e.string().min(1).max(120).optional().describe("Subscription / pricing tier, e.g. `pro` (optional)."),role:e.string().min(1).max(120).optional().describe("The user's role on the host site, e.g. `admin` (optional)."),phone:e.string().min(1).max(40).optional().describe(`Phone number (optional).`)}).catchall(e.union([e.string(),e.number(),e.boolean()])).describe("Host-asserted end-user context (informational, untrusted — not authentication). Recognised `id` / `email` / `name` / `plan` / `role` / `phone` plus any extra custom scalar fields forwarded to the agent.").meta({examples:[{id:`u_123`},{id:`u_123`,email:`alex@acme.com`,name:`Alex Lee`,plan:`pro`}]}),de=[`home`,`docs`,`help-desk`,`support`,`pricing`,`checkout`,`orders`,`account`,`blog`],fe=e.object({area:e.string().min(1).max(64).optional().describe(`Host-defined surface the visitor is on. Free-form; suggested: ${de.join(` | `)}.`),url:e.string().min(1).max(2048).optional().describe(`Full page URL. Auto-filled from the host page when omitted.`),path:e.string().min(1).max(2048).optional().describe("Page path, e.g. `/pricing/enterprise`."),title:e.string().min(1).max(300).optional().describe(`Human-readable page title.`)}).catchall(e.union([e.string(),e.number(),e.boolean()])).describe("Host-asserted page/visit context (informational, untrusted). Where the visitor is + the surface (`area`) they're using, plus any custom scalar fields, forwarded to the agent.").meta({examples:[{area:`pricing`,path:`/pricing`},{area:`help-desk`}]}),Z=e.object({widgetId:e.string().min(1).max(80).default(`default`).describe(`Stable per-instance id used to namespace localStorage keys. Set this when mounting more than one widget on the same page so their conversation state doesn't collide.`),publicKey:e.string().min(1).max(200).optional().describe("Workspace-scoped public key (`agent_pk_…`) issued from the dashboard. Sent on every API call as the `x-public-key` header."),aiAgentDeploymentId:e.string().min(1).max(200).optional().describe("Deployment UUID from the dashboard. Picks which agent / settings bundle answers this mount. Sent as `x-ai-agent-deployment-id`."),baseUrl:e.string().min(1).max(2048).optional().describe("MAIN site origin (e.g. `https://help.ai`) — the API modules derive from it: agent API at `${baseUrl}/api/agent`, data API at `${baseUrl}/api/data`. Set this to point at your staging / self-hosted / custom backend. Default: the brand's `defaultBaseUrl` baked at build time."),agentApiBaseUrl:e.string().min(1).max(2048).optional().describe("Full agent-API base — set it to reach a STANDALONE `module-help-ai-agent-api` directly (local module on its own port, e.g. `http://localhost:3087`; routes attach as-is: `/pai/handshake`). Precedence: this option > derived from the main origin (`${baseUrl}/api/agent`). Not server-pushable."),dataApiBaseUrl:e.string().min(1).max(2048).optional().describe("Full data-API base (e.g. `https://help.ai/api/data`, or a standalone local module like `http://localhost:3106`) — the service serving content, form definitions (`GET /forms`), and form submissions at root-level paths. Precedence: this option > server-pushed `config.dataApiBaseUrl` > derived from the main origin (`${baseUrl}/api/data`)."),userContext:ue.optional(),pageContext:fe.optional(),endpoints:le.optional(),debug:e.union([e.boolean(),e.enum([`off`,`error`,`warn`,`info`,`debug`,`trace`])]).optional().describe('Console log verbosity. `false` / `"off"` silences everything (default in production). `true` → `"debug"`. Levels `error` / `warn` / `info` / `debug` / `trace` gate output additively. Use `"trace"` to capture per-chunk SSE frames + every state transition. Also toggleable at runtime via `chat.setDebug(level)` or `?<brand>-debug=trace` in the page URL — the URL beats this option, this option beats the persisted `localStorage` value.')}).loose().describe("Where the widget talks to and how it authenticates. Owned by the embedding developer (typically baked into the page template / env var) — distinct from `userPrefs`, which is the dashboard-pushable UX surface.").meta({examples:[{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,widgetId:`support`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,baseUrl:`https://api.acme.com`}]}),Q=e.object({presentation:c.optional(),behavior:u.optional(),theme:p.default(`auto`).describe("Theme preference (`auto` follows OS) or a tokens override object (`accent`, `radius`, `fontFamily`)."),launcher:y.optional(),header:T.optional(),composer:F.optional(),feedback:k.optional(),i18n:X.optional(),footer:L.optional(),features:S.optional(),forms:q.optional(),modules:se.optional(),tracking:ce.optional()}).loose().describe("Portal-configurable widget settings — fourteen sections, one per dashboard tab. The backend pushes this same shape on `/pai/handshake` under `config`.").meta({examples:[{presentation:{mode:`floating`,position:`bottom-right`},theme:`auto`},{presentation:{mode:`floating`},theme:{accent:`#7c3aed`,radius:`12px`},launcher:{variant:`pill`,label:`Ask AI`,callout:{text:`👋 Need help?`}}},{presentation:{mode:`inline`},behavior:{responseMode:`streaming`},features:{voice:`local`}}]}),$=Z.extend({...Q.shape,site:e.unknown().optional().describe('Site config — applies in `mode: "page"`. Comes from the handshake response, not user-edited.'),blocks:e.unknown().optional().describe('Blocks (nav + link cards) — applies in `mode: "page"`. Comes from the handshake response.')}).describe("Full client widget config — connection (where + auth) + widget settings (look + behaviour) + page-mode extras. This is what the runtime parses on `mount()` / `init()`. Mode-specific constraints (e.g. `position` only meaningful in `floating`) are NOT enforced here — the runtime silently ignores irrelevant fields rather than rejecting them so the same object can flow across mode changes.").meta({examples:[{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,presentation:{mode:`floating`},theme:`auto`},{publicKey:`agent_pk_demo`,aiAgentDeploymentId:`01900000-0000-7000-8000-000000000001`,presentation:{mode:`modal`,size:{width:`720px`,height:`640px`}}}]}),pe=$.partial(),me=Q.partial(),he=Z.partial(),ge=Q.partial().omit({forms:!0}).extend({dataApiBaseUrl:e.string().min(1).max(2048).optional(),storageVersion:e.string().min(1).max(64).optional()}),_e=e.object({title:e.string().min(1).max(120).optional().describe(`Brand / site name. Used as the logo's alt-text fallback.`),logo:t.optional().describe(`Brand logo shown at the top of the page-mode sidebar.`),logoDark:t.optional().describe("Optional dark-theme logo variant. Falls back to `logo` when the active theme is light or `logoDark` is unset.")}).loose(),ve=e.object({navigation:e.array(n).max(100).optional().describe(`Sidebar navigation links (vertical list, primary nav).`),linkCards:e.array(n).max(100).optional().describe("Sidebar link cards (richer entries with optional `description`).")}).loose(),ye=e.object({id:e.string(),role:e.enum([`assistant`,`system`]),text:e.string()}).loose(),be=e.object({id:e.string(),label:e.string(),text:e.string().optional()}).loose(),xe=e.enum([`conflict`,`expired`,`invalid`]),Se=e.object({deployment:e.object({id:e.string(),name:e.string(),slug:e.string().optional(),publicKey:e.string().optional()}).loose(),agent:e.object({id:e.string(),name:e.string(),title:e.string().optional(),status:e.enum([`online`,`away`,`offline`]).optional()}).loose(),config:ge.optional(),site:_e.optional(),blocks:ve.optional(),welcome:e.object({messages:e.array(ye).optional(),suggestions:e.array(be).optional()}).loose().optional(),visitorId:e.string(),conversationId:e.string(),userPrefs:e.record(e.string(),e.unknown()).optional(),rebind:e.object({visitorId:xe.optional(),conversationId:xe.optional()}).loose().optional()}).loose(),Ce=[`theme`,`header`,`composer`,`footer`,`i18n`,`features`,`feedback`,`tracking`],we={floating:[`presentation`,`behavior`,`modules`,`launcher`],inline:[`presentation`,`behavior`],modal:[`presentation`,`behavior`,`modules`],drawer:[`presentation`,`behavior`,`modules`,`launcher`],page:[`presentation`],standalone:[`presentation`]};function Te(e){let t=[...we[e],...Ce],n={};for(let e of t)n[e]=!0;return Q.pick(n)}const Ee=[`floating`,`inline`,`standalone`,`page`,`modal`,`drawer`];function De(){return{$schema:`https://json-schema.org/draft/2020-12/schema`,title:`@helpai/elements config`,description:`Canonical config schemas for the embeddable AI agent elements widget.`,definitions:{WidgetConfig:e.toJSONSchema($),HandshakeResponse:e.toJSONSchema(Se)}}}export{Ee as ALL_MODES,de as PAGE_AREA_SUGGESTIONS,C as actionNameSchema,t as assetSchema,P as attachmentLimitsSchema,u as behaviorSchema,ve as blocksConfigSchema,_ as calloutPositionSchema,g as calloutShapeSchema,F as composerOptionsSchema,he as connectionConfigPartialSchema,Z as connectionConfigSchema,i as cssColorSchema,r as cssLengthSchema,De as emitJsonSchema,le as endpointsSchema,S as featureFlagsSchema,E as feedbackEventSchema,k as feedbackSchema,z as fieldOptionSchema,ie as fieldOptionTranslationSchema,R as fieldTypeSchema,B as fieldValidationSchema,L as footerSchema,U as formConditionSchema,K as formDefSchema,V as formFieldSchema,W as formFieldTranslationSchema,G as formTranslationSchema,H as formTriggerSchema,q as formsSchema,Se as handshakeResponseSchema,O as hapticsOptionsSchema,w as headerActionsSchema,T as headerSchema,X as i18nSchema,o as initialSizeSchema,v as launcherCalloutSchema,y as launcherOptionsSchema,h as launcherSizeSchema,m as launcherVariantSchema,n as linkSchema,a as localeSchema,ne as modeSchema,ae as moduleLayoutSchema,oe as moduleSchema,se as modulesSchema,fe as pageContextSchema,re as positionSchema,I as poweredBySchema,c as presentationSchema,s as resizeOptionsSchema,l as responseModeSchema,j as sendButtonIconSchema,N as sendButtonOptionsSchema,A as sendButtonShapeSchema,M as sendButtonVariantSchema,ge as serverConfigSchema,_e as siteConfigSchema,te as sizeOptionsSchema,D as soundOptionsSchema,Y as stringsOverrideSchema,p as themeFieldSchema,f as themeOverridesSchema,d as themePreferenceSchema,x as toolRefSchema,ce as trackingSchema,ue as userContextSchema,ee as uuid7Schema,b as voiceModeSchema,pe as widgetConfigPartialSchema,$ as widgetConfigSchema,me as widgetSettingsPartialSchema,Q as widgetSettingsSchema,Te as widgetSettingsSchemaForMode};
|
|
2
2
|
//# sourceMappingURL=schema.mjs.map
|
package/web-component.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import{Component as e,h as t,render as n}from"preact";import{useCallback as r,us
|
|
|
4
4
|
`,`.__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}
|
|
5
5
|
`,`:host([data-mode="page"]){min-height:0}:host([data-mode="page"]) .__P__-page-shell{display:grid;grid-template-columns:280px 1fr;width:100%;height:100%;min-height:0;background:var(--__P__-bg);color:var(--__P__-fg);transition:grid-template-columns var(--__P__-dur-base) var(--__P__-ease-in-out)}:host([data-mode="page"]) .__P__-page-shell[data-sidebar-collapsed=true]{grid-template-columns:48px 1fr}:host([data-mode="page"]) .__P__-page-chat{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}:host([data-mode="page"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-width:0;min-height:0;flex:1 1 0}:host([data-mode="page"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;border-radius:0;border:0;box-shadow:none;animation:none}:host([data-mode="page"]) .__P__-sidebar{border-inline-end:1px solid var(--__P__-border);display:flex;flex-direction:column;overflow:hidden;background:var(--__P__-surface)}:host([data-mode="page"]) .__P__-sidebar-header{padding:var(--__P__-space-4) var(--__P__-space-5);border-bottom:1px solid var(--__P__-border);display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-2);min-height:56px;box-sizing:border-box}:host([data-mode="page"]) .__P__-sidebar[data-collapsed=true] .__P__-sidebar-header{padding:var(--__P__-space-4) var(--__P__-space-2);justify-content:center}:host([data-mode="page"]) .__P__-sidebar[data-collapsed=true] .__P__-sidebar-logo,:host([data-mode="page"]) .__P__-sidebar[data-collapsed=true] .__P__-sidebar-title{display:none}:host([data-mode="page"]) .__P__-sidebar-toggle{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid var(--__P__-border);border-radius:6px;background:transparent;color:var(--__P__-fg);cursor:pointer;transition:background .12s,border-color .12s}:host([data-mode="page"]) .__P__-sidebar-toggle:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}:host([data-mode="page"]) .__P__-sidebar-toggle:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}:host([data-mode="page"]) .__P__-sidebar-logo{height:32px;display:block}:host([data-mode="page"]) .__P__-sidebar-title{font-size:var(--__P__-text-md);font-weight:600}:host([data-mode="page"]) .__P__-sidebar-section{padding:var(--__P__-space-3) var(--__P__-space-4);border-bottom:1px solid var(--__P__-border)}:host([data-mode="page"]) .__P__-sidebar-nav{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}:host([data-mode="page"]) .__P__-sidebar-nav-item{display:flex;align-items:center;gap:10px;padding:var(--__P__-space-2) var(--__P__-space-3);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);text-decoration:none;font-size:calc(14px * var(--__P__-text-scale));transition:background var(--__P__-dur-quick) var(--__P__-ease-out)}:host([data-mode="page"]) .__P__-sidebar-nav-item:hover{background:var(--__P__-hover)}:host([data-mode="page"]) .__P__-sidebar-nav-item:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}:host([data-mode="page"]) .__P__-sidebar-cards{display:grid;grid-template-columns:1fr;gap:var(--__P__-space-2)}:host([data-mode="page"]) .__P__-sidebar-card{display:block;padding:10px 12px;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-sm);text-decoration:none;color:var(--__P__-fg);transition:border-color var(--__P__-dur-quick) var(--__P__-ease-out)}:host([data-mode="page"]) .__P__-sidebar-card:hover{border-color:var(--__P__-accent)}:host([data-mode="page"]) .__P__-sidebar-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}:host([data-mode="page"]) .__P__-sidebar-card-label{font-weight:600;font-size:calc(14px * var(--__P__-text-scale))}:host([data-mode="page"]) .__P__-sidebar-card-desc{font-size:var(--__P__-text-xs);color:var(--__P__-muted);margin-top:2px}:host([data-mode="page"]) .__P__-sidebar-conversations{flex:1 1 auto;overflow-y:auto;padding:var(--__P__-space-3) var(--__P__-space-4)}:host([data-mode="page"]) .__P__-page-chat{display:flex;flex-direction:column;overflow:hidden}@media(max-width:768px){:host([data-mode="page"]) .__P__-page-shell{grid-template-columns:1fr}:host([data-mode="page"]) .__P__-sidebar{display:none}}
|
|
6
6
|
`].join(`
|
|
7
|
-
`).replace(/__P__/g,`helpai`).replaceAll(`__BRAND_ACCENT_TEXT__`,`#FFFFFF`).replaceAll(`__BRAND_ACCENT__`,`#5B5BD6`).replaceAll(`__BRAND_RADIUS__`,`12px`).replaceAll(`__BRAND_FONT__`,`Inter, system-ui, -apple-system, 'Segoe UI', sans-serif`),ft=M.scope(`mount`),pt=new WeakMap,mt={floating:`all: initial; position: fixed; z-index: 2147483600;`,flow:`all: initial; display: block; position: relative; width: 100%; height: 100%; z-index: 1; contain: size;`,viewport:`all: initial; display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1;`};function ht(e,t){e.style.cssText=mt[t]}function gt(e){return e===`floating`||e===`modal`||e===`drawer`?`floating`:e===`standalone`||e===`page`?`viewport`:`flow`}function _t(e={}){let t=e.position??`flow`;ft.debug(`createShadowMount`,{position:t,hasTarget:!!e.target,hasHost:!!e.existingHost});let n=`${v.cssPrefix}-chat-host`;typeof customElements<`u`&&!customElements.get(n)&&customElements.define(n,class extends HTMLElement{});let r;e.existingHost?r=e.existingHost:(r=document.createElement(n),(e.target??document.body).appendChild(r)),r.setAttribute(`data-brand`,v.id),r.style.cssText=mt[t];let i=r.shadowRoot??r.attachShadow({mode:`open`}),a=r.ownerDocument;if(!vt(i,a)){let e=a.createElement(`style`);e.textContent=dt,i.appendChild(e)}let o=document.createElement(`div`);return o.className=`${v.cssPrefix}-app`,i.appendChild(o),{appRoot:o,destroy:()=>r.remove(),hostElement:r,shadowRoot:i}}function vt(e,t){if(!(`adoptedStyleSheets`in e))return!1;let n=t.defaultView;if(!n||typeof n.CSSStyleSheet!=`function`)return!1;let r=pt.get(t);if(!r)try{r=new n.CSSStyleSheet,r.replaceSync(dt),pt.set(t,r)}catch{return!1}try{return e.adoptedStyleSheets=[r],!0}catch{return!1}}function yt(e,t){let n=v.cssPrefix;t.accent&&e.style.setProperty(`--${n}-accent-user`,t.accent),t.accentText&&e.style.setProperty(`--${n}-accent-text-user`,t.accentText),t.radius&&e.style.setProperty(`--${n}-radius`,t.radius),t.fontFamily&&e.style.setProperty(`--${n}-font`,t.fontFamily),t.contentMaxWidth&&e.style.setProperty(`--${n}-conversation-max`,t.contentMaxWidth)}function bt(e,t){e.dataset.theme=t}function xt(e,t){let n=v.cssPrefix;t.width!==void 0&&e.style.setProperty(`--${n}-panel-w`,t.width),t.height!==void 0&&e.style.setProperty(`--${n}-panel-h`,t.height),t.expanded?.width!==void 0&&e.style.setProperty(`--${n}-expanded-w`,t.expanded.width),t.expanded?.height!==void 0&&e.style.setProperty(`--${n}-expanded-h`,t.expanded.height),t.inset!==void 0&&e.style.setProperty(`--${n}-panel-inset`,t.inset)}function St(e,t){e.dataset.position=t}function Ct(e,t){e.dataset.mode=t}function wt(e,t){bt(e,t.themeMode),yt(e,t.themeOverrides),St(e,t.position),xt(e,t.size)}function V(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Tt(e){return V(e)}function Et(e){return!(!V(e)||e.navigation!==void 0&&!Array.isArray(e.navigation)||e.linkCards!==void 0&&!Array.isArray(e.linkCards))}function Dt(e){return`${v.cssPrefix}:${e}`}function Ot(e,t){let n=Object.entries(t).map(([t,n])=>{let r=Dt(t),i=e=>n(e.detail);return e.addEventListener(r,i),[r,i]});return()=>{for(let[t,r]of n)e.removeEventListener(t,r)}}function kt(e,t,n){return e===`page`?`page`:e===`standalone`?`standalone`:e===`inline`?t===`fullscreen`?`fullscreen`:`inline`:e===`modal`||e===`drawer`?n?t===`fullscreen`?`fullscreen`:e:`closed`:n?t===`fullscreen`?`fullscreen`:t===`expanded`?`expanded`:`open`:`closed`}function At(e,t,n){if(e===`standalone`||e===`page`)return`fullscreen`;let r=t.initialSize;return r===`expanded`||r===`fullscreen`||r===`normal`?r:r===`auto`&&n>=(t.autoSizeBreakpoint??900)?`expanded`:`normal`}function jt(e,t,n,r=null){return{panelOpen:e.mode===`inline`||e.mode===`standalone`||e.mode===`page`||(n??!e.startMinimized),panelSize:e.mode!==`standalone`&&e.mode!==`page`&&e.mode!==`inline`&&r?r:At(e.mode,e.size,t)}}function Mt(){return typeof window>`u`?0:window.innerWidth}function Nt(e){return{headers(){let t={};return e.aiAgentDeploymentId&&(t[`x-ai-agent-deployment-id`]=e.aiAgentDeploymentId),e.publicKey&&(t[e.publicKeyHeader??`x-public-key`]=e.publicKey),t}}}const Pt=`0.63.
|
|
7
|
+
`).replace(/__P__/g,`helpai`).replaceAll(`__BRAND_ACCENT_TEXT__`,`#FFFFFF`).replaceAll(`__BRAND_ACCENT__`,`#5B5BD6`).replaceAll(`__BRAND_RADIUS__`,`12px`).replaceAll(`__BRAND_FONT__`,`Inter, system-ui, -apple-system, 'Segoe UI', sans-serif`),ft=M.scope(`mount`),pt=new WeakMap,mt={floating:`all: initial; position: fixed; z-index: 2147483600;`,flow:`all: initial; display: block; position: relative; width: 100%; height: 100%; z-index: 1; contain: size;`,viewport:`all: initial; display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1;`};function ht(e,t){e.style.cssText=mt[t]}function gt(e){return e===`floating`||e===`modal`||e===`drawer`?`floating`:e===`standalone`||e===`page`?`viewport`:`flow`}function _t(e={}){let t=e.position??`flow`;ft.debug(`createShadowMount`,{position:t,hasTarget:!!e.target,hasHost:!!e.existingHost});let n=`${v.cssPrefix}-chat-host`;typeof customElements<`u`&&!customElements.get(n)&&customElements.define(n,class extends HTMLElement{});let r;e.existingHost?r=e.existingHost:(r=document.createElement(n),(e.target??document.body).appendChild(r)),r.setAttribute(`data-brand`,v.id),r.style.cssText=mt[t];let i=r.shadowRoot??r.attachShadow({mode:`open`}),a=r.ownerDocument;if(!vt(i,a)){let e=a.createElement(`style`);e.textContent=dt,i.appendChild(e)}let o=document.createElement(`div`);return o.className=`${v.cssPrefix}-app`,i.appendChild(o),{appRoot:o,destroy:()=>r.remove(),hostElement:r,shadowRoot:i}}function vt(e,t){if(!(`adoptedStyleSheets`in e))return!1;let n=t.defaultView;if(!n||typeof n.CSSStyleSheet!=`function`)return!1;let r=pt.get(t);if(!r)try{r=new n.CSSStyleSheet,r.replaceSync(dt),pt.set(t,r)}catch{return!1}try{return e.adoptedStyleSheets=[r],!0}catch{return!1}}function yt(e,t){let n=v.cssPrefix;t.accent&&e.style.setProperty(`--${n}-accent-user`,t.accent),t.accentText&&e.style.setProperty(`--${n}-accent-text-user`,t.accentText),t.radius&&e.style.setProperty(`--${n}-radius`,t.radius),t.fontFamily&&e.style.setProperty(`--${n}-font`,t.fontFamily),t.contentMaxWidth&&e.style.setProperty(`--${n}-conversation-max`,t.contentMaxWidth)}function bt(e,t){e.dataset.theme=t}function xt(e,t){let n=v.cssPrefix;t.width!==void 0&&e.style.setProperty(`--${n}-panel-w`,t.width),t.height!==void 0&&e.style.setProperty(`--${n}-panel-h`,t.height),t.expanded?.width!==void 0&&e.style.setProperty(`--${n}-expanded-w`,t.expanded.width),t.expanded?.height!==void 0&&e.style.setProperty(`--${n}-expanded-h`,t.expanded.height),t.inset!==void 0&&e.style.setProperty(`--${n}-panel-inset`,t.inset)}function St(e,t){e.dataset.position=t}function Ct(e,t){e.dataset.mode=t}function wt(e,t){bt(e,t.themeMode),yt(e,t.themeOverrides),St(e,t.position),xt(e,t.size)}function V(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Tt(e){return V(e)}function Et(e){return!(!V(e)||e.navigation!==void 0&&!Array.isArray(e.navigation)||e.linkCards!==void 0&&!Array.isArray(e.linkCards))}function Dt(e){return`${v.cssPrefix}:${e}`}function Ot(e,t){let n=Object.entries(t).map(([t,n])=>{let r=Dt(t),i=e=>n(e.detail);return e.addEventListener(r,i),[r,i]});return()=>{for(let[t,r]of n)e.removeEventListener(t,r)}}function kt(e,t,n){return e===`page`?`page`:e===`standalone`?`standalone`:e===`inline`?t===`fullscreen`?`fullscreen`:`inline`:e===`modal`||e===`drawer`?n?t===`fullscreen`?`fullscreen`:e:`closed`:n?t===`fullscreen`?`fullscreen`:t===`expanded`?`expanded`:`open`:`closed`}function At(e,t,n){if(e===`standalone`||e===`page`)return`fullscreen`;let r=t.initialSize;return r===`expanded`||r===`fullscreen`||r===`normal`?r:r===`auto`&&n>=(t.autoSizeBreakpoint??900)?`expanded`:`normal`}function jt(e,t,n,r=null){return{panelOpen:e.mode===`inline`||e.mode===`standalone`||e.mode===`page`||(n??!e.startMinimized),panelSize:e.mode!==`standalone`&&e.mode!==`page`&&e.mode!==`inline`&&r?r:At(e.mode,e.size,t)}}function Mt(){return typeof window>`u`?0:window.innerWidth}function Nt(e){return{headers(){let t={};return e.aiAgentDeploymentId&&(t[`x-ai-agent-deployment-id`]=e.aiAgentDeploymentId),e.publicKey&&(t[e.publicKeyHeader??`x-public-key`]=e.publicKey),t}}}const Pt=`0.63.4`;function H(e){"@babel/helpers - typeof";return H=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},H(e)}function Ft(e,t){if(H(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(H(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function It(e){var t=Ft(e,`string`);return H(t)==`symbol`?t:t+``}function U(e,t,n){return(t=It(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Lt=class extends Error{constructor(e,t,n,r){super(e),this.code=t,this.status=n,this.cause=r,this.name=`StreamError`}};const Rt=M.scope(`parser`);async function*zt(e,t){if(!e.ok){let t=await e.text().catch(()=>``);throw new Lt(`server responded ${e.status}: ${t.slice(0,200)}`,`server`,e.status)}for await(let n of Bt(e,t)){let e=Vt(n);if(e===`done`)return;e&&(yield e)}}async function*Bt(e,t){if(!e.body)throw new Lt(`response has no body`,`no-body`);let n=e.body.pipeThrough(new TextDecoderStream).getReader(),r=``;try{for(;;){if(t.aborted)throw new DOMException(`aborted`,`AbortError`);let{done:e,value:i}=await n.read();if(e){let e=r.trim();e&&(yield e);return}r+=i;let a;for(;(a=r.indexOf(`
|
|
8
8
|
|
|
9
9
|
`))!==-1;){let e=r.slice(0,a);r=r.slice(a+2),yield e}}}finally{n.releaseLock()}}function Vt(e){let t=``,n;for(let r of e.split(`
|
|
10
10
|
`))if(!(r===``||r.startsWith(`:`))){if(r.startsWith(`data:`)){let e=r.slice(5).replace(/^ /,``);t=t?`${t}\n${e}`:e;continue}r.startsWith(`id:`)&&(n=r.slice(3).trim())}if(t===`[DONE]`)return`done`;if(!t)return null;try{let e=JSON.parse(t);return Rt.trace(`chunk`,{type:e.type,eventId:n}),{chunk:e,eventId:n}}catch(e){return Rt.trace(`frame parse failed`,{err:e,payload:t.slice(0,200)}),null}}function Ht(e){let t=new TextEncoder().encode(e),n=``;for(let e of t)n+=String.fromCharCode(e);return btoa(n).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}const Ut=e=>e&&Object.keys(e).length>0?e:void 0;function Wt(e,t){let n=Ut(e),r=Ut(t);if(!n&&!r)return;let i={};return n&&(i.user=n),r&&(i.page=r),Ht(JSON.stringify(i))}function Gt(e){if(!e)return;let t=Date.parse(e);return Number.isFinite(t)?t:void 0}function Kt(e){return`tool-${e.startsWith(`tool:`)?e.slice(5):e}`}function qt(e){return e.startsWith(`tool-`)?e.slice(5):e}const Jt={handshake:`/pai/handshake`,streamMessage:`/pai/stream-message`,streamResume:`/pai/stream-resume`,cancelStream:`/pai/cancel-stream`,listConversations:`/pai/list-conversations`,listMessages:`/pai/list-messages`,updateSettings:`/pai/update-settings`,markRead:`/pai/mark-read`,messageFeedback:`/pai/message-feedback`,requestOperator:`/pai/request-operator`,bootstrap:`/pai/bootstrap`,content:`/pai/content`,submitForm:`/pai/submit-form`};function Yt(e){let t=e??{},n=t.controlMode;return{controlMode:n===`awaiting_operator`||n===`operator`?n:`ai-agent`,assignedOperatorInitials:typeof t.assignedOperatorInitials==`string`&&t.assignedOperatorInitials?t.assignedOperatorInitials:void 0,operatorAvailable:typeof t.operatorAvailable==`boolean`?t.operatorAvailable:void 0}}function Xt(e){let t=e?.suggestions;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let{id:t,label:r,text:i}=e;typeof r!=`string`||!r||n.push({id:typeof t==`string`&&t?t:`s${n.length}`,label:r,text:typeof i==`string`&&i?i:r})}return n}function Zt(e){let t=e.messages.map(e=>({id:e.serverMessageId??e.id,parts:en(e),role:e.role,createdAt:e.createdAt===void 0?void 0:new Date(e.createdAt).toISOString()})),n={messages:t,conversationId:e.conversationId,trigger:e.trigger??`submit-message`},r=t.at(-1)?.id;r&&(n.messageId=r),e.visitorId&&(n.visitorId=e.visitorId),e.userPrefs&&(n.userPrefs=e.userPrefs);let i=e.tools?.map($t).filter(e=>e!==null);return i?.length&&(n.data={tools:i}),n}function Qt(e){return e.state===`output-available`||e.state===`output-error`||e.state===`output-denied`||e.approval?.approved!==void 0}function $t(e){return typeof e==`string`?e?{code:e}:null:e?.code?e:null}function en(e){let t=[];for(let n of e.parts)if(n.kind===`step-start`&&t.push({type:`step-start`}),n.kind===`reasoning`&&n.text&&t.push({type:`reasoning`,text:n.text,state:n.done?`done`:`streaming`}),n.kind===`text`&&n.text&&t.push({text:n.text,type:`text`}),n.kind===`file`&&n.url&&t.push({mediaType:n.mediaType,type:`file`,url:n.url}),n.kind===`tool`&&Qt(n)){let e={type:Kt(n.toolName),toolCallId:n.toolCallId,state:n.state};n.input!==void 0&&(e.input=n.input),n.output!==void 0&&(e.output=n.output),n.error!==void 0&&(e.errorText=n.error),n.approval&&n.approval.approved!==void 0&&(e.approval=n.approval),t.push(e)}for(let n of e.attachments??[])n.url&&t.push({type:`file`,url:n.url,mediaType:n.mediaType,filename:n.name,fileId:n.id,fileSize:n.size});return t}const W=M.scope(`transport`),tn=new Set([408,425,429,500,502,503,504]);function nn(e){return 400*2**e+Math.floor(Math.random()*250)}function rn(e){let t=e.get(`retry-after`);if(!t)return null;let n=Number(t),r=Number.isFinite(n)?n*1e3:Date.parse(t)-Date.now();return Number.isFinite(r)&&r>=0?Math.min(r,3e4):null}function an(e,t){return new Promise(n=>{if(t?.aborted)return n();let r=setTimeout(a,e),i=()=>a();t?.addEventListener(`abort`,i,{once:!0});function a(){clearTimeout(r),t?.removeEventListener(`abort`,i),n()}})}var on=class{constructor(e){this.ttlMs=e,U(this,`map`,new Map)}getOrFetch(e,t){let n=this.map.get(e);if(n&&Date.now()-n.at<this.ttlMs)return n.result;let r={at:Date.now(),result:t().then(e=>(r.value=e,e)).catch(t=>{throw this.map.delete(e),t})};return this.map.set(e,r),r.result}peek(e){let t=this.map.get(e);if(t?.value!==void 0&&Date.now()-t.at<this.ttlMs)return t.value}clear(){this.map.clear()}},sn=class{constructor(e){this.opts=e,U(this,`visitorId`,void 0),U(this,`conversationId`,void 0),U(this,`resumeStatus`,void 0),U(this,`userContext`,void 0),U(this,`pageContext`,void 0),U(this,`locale`,void 0),U(this,`conversationsCache`,new on(1e4)),U(this,`contentCache`,new on(6e4))}setContext(e,t){this.userContext=e,this.pageContext=t}setLocale(e){this.locale=e}primeIdentity(e,t){e&&(this.visitorId=e),t&&(this.conversationId=t)}envelope(){let e={_ev:Pt};this.visitorId&&(e.visitorId=this.visitorId),this.conversationId&&(e.conversationId=this.conversationId),this.locale&&(e.locale=this.locale);let t=Wt(this.userContext,this.pageContext);return t&&(e.context=t),e}withEnvelope(e){return{...this.envelope(),...e}}appendEnvelope(e){for(let[t,n]of Object.entries(this.envelope()))e.append(t,n);return e}withEnvelopeQuery(e){let t=new URL(this.url(e));for(let[e,n]of Object.entries(this.envelope()))t.searchParams.has(e)||t.searchParams.set(e,n);return t.toString()}async handshake(e){W.debug(`handshake →`,{visitorId:e.visitorId,conversationId:e.conversationId,locale:e.locale});let t=await this.postJson(Jt.handshake,e,`handshake`);return W.debug(`handshake ←`,{visitorId:t.visitorId,conversationId:t.conversationId,hasWelcome:!!t.welcome,hasConfig:!!t.config,rebind:t.rebind}),ln(t)||W.warn(`handshake response did not match expected shape; using raw response`,{response:t}),this.visitorId=t.visitorId??e.visitorId,this.conversationId=t.conversationId,t}async uploadFile(e){W.debug(`uploadFile →`,{name:e.name,size:e.size,type:e.type});let t=new FormData;t.append(`file`,e,e.name);let n=await this.postForm(this.uploadPath,t,`upload`);return W.debug(`uploadFile ←`,{id:n.id,url:n.url}),n}async transcribe(e,t=`audio/webm`){W.debug(`transcribe →`,{size:e.size,mimeType:t});let n=new FormData;n.append(`audio`,e,`voice.${cn(t)}`),n.append(`mimeType`,t);let r=await this.postForm(this.transcribePath,n,`transcribe`);return W.debug(`transcribe ←`,{textLen:r.text.length}),r}localeCacheKey(e){return`${this.locale??``}|${JSON.stringify(e,Object.keys(e).toSorted())}`}peekConversations(e={}){return this.conversationsCache.peek(this.localeCacheKey(e))}listConversations(e={}){return this.conversationsCache.getOrFetch(this.localeCacheKey(e),()=>this.fetchConversations(e))}async fetchConversations(e){let t=new URL(this.url(Jt.listConversations));e.visitorId&&t.searchParams.set(`visitorId`,e.visitorId),e.limit&&t.searchParams.set(`limit`,String(e.limit)),e.cursor&&t.searchParams.set(`cursor`,e.cursor),W.debug(`listConversations →`,{visitorId:e.visitorId??this.visitorId,limit:e.limit,cursor:e.cursor});let n=await this.getJson(t.toString(),`listConversations`),r=n.conversations??[];return W.debug(`listConversations ←`,{count:r.length,nextCursor:n.nextCursor}),{conversations:r,nextCursor:n.nextCursor}}async loadConversation(e){let t=new URL(this.url(Jt.listMessages));t.searchParams.set(`conversationId`,e),W.debug(`loadConversation →`,{conversationId:e,visitorId:this.visitorId});let n=await this.getJson(t.toString(),`loadConversation`),r=n.messages??[];return W.debug(`loadConversation ←`,{conversationId:n.conversationId,canContinue:n.canContinue,messageCount:r.length,hasSuggestions:!!n.suggestions}),{...n,messages:r,canContinue:n.canContinue??!0}}async markRead(e){if(!(!this.visitorId||!e)){this.conversationsCache.clear(),W.debug(`markRead →`,{conversationId:e,visitorId:this.visitorId});try{await this.postJson(Jt.markRead,{conversationId:e},`markRead`)}catch(e){W.debug(`markRead failed (non-fatal)`,{err:e})}}}async requestOperator(){if(!(!this.visitorId||!this.conversationId)){W.debug(`requestOperator →`,{conversationId:this.conversationId,visitorId:this.visitorId});try{return(await this.postJson(Jt.requestOperator,{},`requestOperator`)).controlState}catch(e){W.debug(`requestOperator failed (non-fatal)`,{err:e});return}}}listContent(e={}){return this.contentCache.getOrFetch(this.localeCacheKey(e),()=>this.fetchContent(e))}async fetchContent(e){let t=new URL(this.dataUrl(Jt.content));for(let[n,r]of Object.entries(e))r!==void 0&&t.searchParams.set(n,Array.isArray(r)?r.join(`,`):String(r));W.debug(`listContent →`,e);let n=await this.getJson(t.toString(),`listContent`),r=(n.items??[]).map(e=>O(e,this.locale));return W.debug(`listContent ←`,{count:r.length,total:n.pagination?.total}),{...n,items:r}}async bootstrap(e){let t=new URL(this.dataUrl(Jt.bootstrap));e&&t.searchParams.set(`conversationId`,e),W.debug(`bootstrap →`,{conversationId:e??this.conversationId});let n=await this.getJson(t.toString(),`bootstrap`),r=n.forms??[],i=n.formSubmissions??[];return W.debug(`bootstrap ←`,{forms:r.length,formSubmissions:i.length}),{forms:r,formSubmissions:i}}async saveUserPrefs(e){W.debug(`saveUserPrefs →`,{visitorId:this.visitorId,conversationId:this.conversationId,settingsKeys:Object.keys(e)});let t=await this.postJson(Jt.updateSettings,{userPrefs:e},`saveUserPrefs`);return W.debug(`saveUserPrefs ←`,{success:t.success}),t}get uploadPath(){return this.opts.endpoints?.upload??`/pai/upload-file`}get transcribePath(){return this.opts.endpoints?.transcribe??`/pai/transcribe-audio`}get submitFormPath(){return this.opts.endpoints?.submitForm??Jt.submitForm}async submitForm(e){W.debug(`submitForm →`,{formId:e.formId,trigger:e.trigger,fields:Object.keys(e.values).length});try{await this.postJson(this.dataUrl(this.submitFormPath),e,`submitForm`)}catch(e){W.debug(`submitForm failed (non-fatal)`,{err:e})}}async submitFeedback(e){W.debug(`submitFeedback →`,{messageId:e.messageId,value:e.value});try{await this.postJson(Jt.messageFeedback,{messageId:e.messageId,set:{feedback:e.value}},`submitFeedback`)}catch(e){W.debug(`submitFeedback failed (non-fatal)`,{err:e})}}sendMessage(e){this.conversationsCache.clear(),W.debug(`message →`,{conversationId:e.conversationId,visitorId:e.visitorId,messageId:e.messageId,messageCount:e.messages.length,trigger:e.trigger,tools:e.data?.tools?.map(e=>e.code)});let t=new AbortController,n=new Set;return{iter:this.runStream(e,t,n),cancel:()=>this.cancelStream(t,e.conversationId),detach:()=>t.abort()}}resumeStream(){let e=new AbortController,t=new Set;this.resumeStatus=void 0;let n=this.resumeStreamGen(e,t,!0),r=()=>e.abort();return{iter:n,cancel:r,detach:r}}resumeChannel(){let e=new AbortController;return{iter:this.resumeChannelGen(e),stop:()=>e.abort()}}async*resumeChannelGen(e){for(let t=1;!e.signal.aborted;t++){if(t>1&&(await an(Math.min(250*(t-1),5e3),e.signal),e.signal.aborted))return;let n;try{n=await this.fetchImpl(this.resumeUrl(),{method:`GET`,credentials:`omit`,headers:{accept:`text/event-stream`,...this.opts.auth.headers()},signal:e.signal})}catch(n){if(e.signal.aborted)return;W.debug(`resume-channel fetch failed — reconnecting`,{attempt:t,err:n});continue}if(!n.ok||!n.body){W.debug(`resume-channel → endpoint unavailable`,{status:n.status});return}if(!(n.headers.get(`content-type`)??``).includes(`text/event-stream`)){let e=await n.json().then(e=>e.status).catch(()=>void 0);if(e===`pending`){W.debug(`resume-channel → pending (still registering); reconnecting`,{attempt:t});continue}W.debug(`resume-channel → no live operator-control stream (status); stopping`,{status:e});return}try{for await(let r of zt(n,e.signal)){if(e.signal.aborted)return;t=1,yield r}}catch(t){if(e.signal.aborted)return;W.debug(`resume-channel segment dropped — reconnecting`,{err:t})}}}async*runStream(e,t,n){(yield*this.drain(this.openMessageStream(e,t.signal),n,t))||(yield*this.resumeStreamGen(t,n,!1))}async*resumeStreamGen(e,t,n){for(let r=1;r<=3&&!e.signal.aborted;r++){if((!n||r>1)&&(await an(400*r,e.signal),e.signal.aborted))return;let i;try{i=await this.fetchImpl(this.resumeUrl(t.size),{method:`GET`,credentials:`omit`,headers:{accept:`text/event-stream`,...this.opts.auth.headers()},signal:e.signal})}catch(t){if(e.signal.aborted)return;W.debug(`resume fetch failed — retrying`,{attempt:r,err:t});continue}if(i.status===204||!i.ok){W.debug(`resume → no in-flight stream`,{status:i.status});return}if(!(i.headers.get(`content-type`)??``).includes(`text/event-stream`)){let e=await i.json().then(e=>e.status).catch(()=>void 0);if(W.debug(`resume → no live stream (status response)`,{status:e,attempt:r}),e===`pending`&&r<3)continue;this.resumeStatus=e===`needs-generation`?`needs-generation`:`completed`;return}this.resumeStatus=`live`;let a=t.size;if(yield*this.drain(zt(i,e.signal),t,e))return;if(t.size===a){W.debug(`resume → stream closed with no new events; nothing to resume`);return}}if(!e.signal.aborted)throw new Lt(`stream incomplete after resume attempts`,`server`)}async*drain(e,t,n){let r=!1;try{for await(let i of e){if(n.signal.aborted)return!0;if(i.eventId){if(t.has(i.eventId))continue;t.add(i.eventId)}yield i,(i.chunk.type===`finish`||i.chunk.type===`error`)&&(r=!0)}}catch(e){if(n.signal.aborted)return!0;if(e instanceof Lt&&e.status!==void 0)throw e;W.debug(`stream segment dropped`,{err:e})}return r}cancelStream(e,t){e.signal.aborted||(W.debug(`cancel stream`,{conversationId:t,visitorId:this.visitorId}),e.abort(),!(!this.visitorId||!t)&&this.fetchImpl(this.url(Jt.cancelStream),{method:`POST`,credentials:`omit`,headers:{"content-type":`application/json`,...this.opts.auth.headers()},body:JSON.stringify(this.withEnvelope({})),keepalive:!0}).catch(e=>W.debug(`cancel POST failed (non-fatal)`,{err:e})))}async*openMessageStream(e,t){yield*zt(await this.fetchImpl(this.url(Jt.streamMessage),{method:`POST`,credentials:`omit`,headers:{accept:`text/event-stream`,"content-type":`application/json`,...this.opts.auth.headers()},body:JSON.stringify(this.withEnvelope(e)),signal:t}),t)}resumeUrl(e){let t=new URL(this.withEnvelopeQuery(Jt.streamResume));return e!==void 0&&t.searchParams.set(`resumeAt`,String(e)),t.toString()}async postJson(e,t,n){let r=await this.fetchWithRetry(()=>[this.url(e),{method:`POST`,credentials:`omit`,headers:{"content-type":`application/json`,...this.opts.auth.headers()},body:JSON.stringify(this.withEnvelope(t))}],n);return this.assertOk(r,n)}async postForm(e,t,n){let r=await this.fetchImpl(this.url(e),{method:`POST`,credentials:`omit`,headers:this.opts.auth.headers(),body:this.appendEnvelope(t)});return this.assertOk(r,n)}async getJson(e,t){let n=await this.fetchWithRetry(()=>[this.withEnvelopeQuery(e),{method:`GET`,credentials:`omit`,headers:{accept:`application/json`,...this.opts.auth.headers()}}],t);return this.assertOk(n,t)}async fetchWithRetry(e,t){for(let n=0;;n++){let[r,i]=e(),a;try{a=await this.fetchImpl(r,i)}catch(e){if(n>=3)throw new Lt(`${t} failed: network error`,`network`,void 0,e);W.debug(`request network error — retrying`,{label:t,attempt:n}),await an(nn(n));continue}if(a.ok||!tn.has(a.status)||n>=3)return a;let o=rn(a.headers)??nn(n);W.debug(`request retryable status — retrying`,{label:t,status:a.status,attempt:n,wait:o}),await an(o)}}async assertOk(e,t){if(!e.ok)throw new Lt(`${t} failed: ${e.status}`,`server`,e.status);return await e.json()}url(e){return/^https?:\/\//i.test(e)?e:`${this.opts.agentApiBaseUrl}${e}`}dataUrl(e){return/^https?:\/\//i.test(e)?e:`${this.opts.dataApiBaseUrl}${e}`}get fetchImpl(){return this.opts.fetchImpl??globalThis.fetch.bind(globalThis)}};function cn(e){return e.includes(`webm`)?`webm`:e.includes(`ogg`)?`ogg`:e.includes(`mp4`)||e.includes(`m4a`)?`m4a`:e.includes(`mpeg`)?`mp3`:e.includes(`wav`)?`wav`:`bin`}function ln(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.visitorId==`string`&&typeof t.conversationId==`string`}function un(e,t){let n=e?[{kind:`text`,id:`t0`,textSig:d(e),doneSig:d(!0)}]:[];return{id:ot(),role:`user`,createdAt:Date.now(),status:`complete`,attachments:t,partsSig:d(n)}}function dn(){return{id:ot(),role:`assistant`,createdAt:Date.now(),status:`streaming`,partsSig:d([])}}function fn(e){let t=ot();return pn({id:t,role:e.role,createdAt:Date.now(),status:`complete`,ephemeral:!0,parts:[{kind:`text`,id:`${t}-t0`,text:e.text,done:!0}]})}function pn(e){return{id:e.id,role:e.role,createdAt:e.createdAt,status:e.status,canceled:e.canceled,errorText:e.errorText,finishReason:e.finishReason,serverMessageId:e.serverMessageId,ephemeral:e.ephemeral,attachments:e.attachments,feedback:e.feedback,partsSig:d(e.parts.map(En))}}function mn(e){let t=e.parts.map((t,n)=>t.type===`text`?{kind:`text`,id:`${e.id}-t${n}`,textSig:d(t.text),doneSig:d(!0)}:t.type===`reasoning`?{kind:`reasoning`,id:`${e.id}-r${n}`,textSig:d(t.text),doneSig:d(t.state!==`streaming`)}:t.type===`step-start`?{kind:`step-start`,id:`${e.id}-ss${n}`}:t.type===`file`?{kind:`file`,url:t.url,mediaType:t.mediaType}:t.type===`source-url`?{kind:`source`,sourceId:t.sourceId,url:t.url,title:t.title}:t.type===`source-document`?{kind:`source`,sourceId:t.sourceId,title:t.title,filename:t.filename,mediaType:t.mediaType}:t.type===`data-suggestions`?null:t.type.startsWith(`tool-`)?{kind:`tool`,toolCallId:t.toolCallId,toolName:qt(t.type),inputPartialSig:d(``),inputSig:d(t.input),outputSig:d(t.output),errorSig:d(t.errorText),stateSig:d(t.state),approvalSig:d(t.approval)}:null).filter(e=>e!==null),n=e.parts.find(e=>e.type===`data-suggestions`);return{id:e.id,role:e.role,operatorInitials:e.operatorInitials,suggestions:n?.type===`data-suggestions`?Xt(n.data):void 0,serverMessageId:e.id,createdAt:Gt(e.createdAt)??Date.now(),status:e.status===`failed`?`error`:`complete`,canceled:e.status===`canceled`,feedback:e.feedback??null,partsSig:d(t)}}function hn(e,t){let n=e.findIndex(e=>e.id===t.id);return n>=0?{list:e.map((e,r)=>r===n?t:e),appended:!1}:{list:[...e,t],appended:!0}}const gn=new Set([`completed`,`failed`,`canceled`]);function _n(e){return!e.parts.some(e=>e.type===`text`&&e.text.trim()!==``||e.type.startsWith(`tool-`)||e.type===`file`||e.type===`source-url`||e.type===`source-document`)}function vn(e){return e.role===`assistant`&&e.status!=null&&!gn.has(e.status)&&_n(e)}function yn(e){return e.filter(e=>!vn(e)).map(mn)}function bn(e){return{id:e.id,role:e.role,createdAt:e.createdAt,status:e.status,canceled:e.canceled,errorText:e.errorText,finishReason:e.finishReason,serverMessageId:e.serverMessageId,ephemeral:e.ephemeral,attachments:e.attachments,parts:e.partsSig.value.map(Dn)}}function xn(e){let t=``;for(let n of e.partsSig.value)n.kind===`text`&&(t+=n.textSig.value);return t}function Sn(e){return xn(e).trim()===``&&!e.partsSig.value.some(e=>e.kind===`tool`||e.kind===`file`||e.kind===`source`)}function Cn(e){return e.role===`assistant`&&e.status!==`streaming`&&Sn(e)}function wn(e){return e.canceled===!0&&Cn(e)}function Tn(e,t){return e.pausedTurn?Cn(e)?`drop`:`complete-paused`:t||Cn(e)?`error`:`complete`}function En(e){return e.kind===`text`||e.kind===`reasoning`?{kind:e.kind,id:e.id,textSig:d(e.text),doneSig:d(e.done)}:e.kind===`tool`?{kind:`tool`,toolCallId:e.toolCallId,toolName:e.toolName,inputPartialSig:d(e.inputPartial),inputSig:d(e.input),outputSig:d(e.output),errorSig:d(e.error),stateSig:d(e.state),approvalSig:d(e.approval)}:e}function Dn(e){return e.kind===`text`||e.kind===`reasoning`?{kind:e.kind,id:e.id,text:e.textSig.value,done:e.doneSig.value}:e.kind===`tool`?{kind:`tool`,toolCallId:e.toolCallId,toolName:e.toolName,inputPartial:e.inputPartialSig.value,input:e.inputSig.value,output:e.outputSig.value,error:e.errorSig.value,state:e.stateSig.value,approval:e.approvalSig.value}:e}const On=M.scope(`reducer`);var kn=class{constructor(e){this.messagesSig=e,U(this,`active`,null),U(this,`openTextParts`,new Map),U(this,`partSeq`,0)}attach(e){this.active=e,this.openTextParts.clear()}detach(){this.active=null,this.openTextParts.clear()}ensureTextPart(e,t,n){let r=`${t}:${n}`,i=this.openTextParts.get(r);if(i)return i;let a={kind:t,id:`${n}#${this.partSeq++}`,textSig:d(``),doneSig:d(!1)};return this.openTextParts.set(r,a),jn(e,a),a}apply(e){let t=this.active;if(t)switch(e.type){case`start`:e.messageId&&(t.serverMessageId=e.messageId);return;case`finish-step`:this.openTextParts.clear();return;case`start-step`:jn(t,{kind:`step-start`,id:`ss-${this.partSeq++}`});return;case`finish`:On.debug(`finish`,{reason:e.finishReason,canContinue:e.canContinue}),t.status=`complete`,e.finishReason&&(t.finishReason=e.finishReason),this.bumpDone(t);return;case`error`:On.warn(`stream error chunk`,{errorText:e.errorText}),t.status=`error`,t.errorText=e.errorText,this.bumpDone(t);return;case`text-start`:this.ensureTextPart(t,`text`,e.id);return;case`text-delta`:{let n=this.ensureTextPart(t,`text`,e.id);n.textSig.value+=e.delta;return}case`text-end`:this.ensureTextPart(t,`text`,e.id).doneSig.value=!0;return;case`reasoning-start`:this.ensureTextPart(t,`reasoning`,e.id).doneSig.value=!1;return;case`reasoning-delta`:{let n=this.ensureTextPart(t,`reasoning`,e.id);n.textSig.value+=e.delta;return}case`reasoning-end`:this.ensureTextPart(t,`reasoning`,e.id).doneSig.value=!0;return;case`tool-input-start`:case`tool-input-delta`:case`tool-input-available`:case`tool-output-available`:case`tool-output-error`:case`tool-output-denied`:case`tool-approval-request`:Nn(t,e);return;case`file`:jn(t,{kind:`file`,url:e.url,mediaType:e.mediaType});return;case`source-url`:Mn(t,{kind:`source`,sourceId:e.sourceId,url:e.url,title:e.title});return;case`source-document`:Mn(t,{kind:`source`,sourceId:e.sourceId,title:e.title,filename:e.filename,mediaType:e.mediaType});return;case`data-notification`:return;case`data-conversation-rebind`:return;case`data-suggestions`:t.suggestions=Xt(e.data);return;case`data-control-state`:t.pausedTurn=!0;return;case`data-message`:return;default:}}bumpDone(e){e.partsSig.value=[...e.partsSig.value],this.messagesSig.value=[...this.messagesSig.value]}};function An(e,t,n){let r=e.partsSig.value.find(e=>e.kind===`tool`&&e.toolCallId===t);if(r)return r;let i={kind:`tool`,toolCallId:t,toolName:n??`tool`,inputPartialSig:d(``),inputSig:d(void 0),outputSig:d(void 0),errorSig:d(void 0),stateSig:d(`input-streaming`),approvalSig:d(void 0)};return jn(e,i),i}function jn(e,t){e.partsSig.value=[...e.partsSig.value,t]}function Mn(e,t){e.partsSig.value.some(e=>e.kind===`source`&&e.sourceId===t.sourceId)||jn(e,t)}function Nn(e,t){switch(t.type){case`tool-input-start`:An(e,t.toolCallId,t.toolName);return;case`tool-input-delta`:{let n=An(e,t.toolCallId);n.inputPartialSig.value+=t.inputTextDelta;return}case`tool-input-available`:{let n=An(e,t.toolCallId,t.toolName);n.inputSig.value=t.input,n.stateSig.value=`input-available`;return}case`tool-approval-request`:{let n=An(e,t.toolCallId,t.toolName);n.approvalSig.value={id:t.approvalId},n.stateSig.value=`approval-requested`;return}case`tool-output-available`:{let n=An(e,t.toolCallId);n.outputSig.value=t.output,n.stateSig.value=`output-available`;return}case`tool-output-error`:{let n=An(e,t.toolCallId);n.errorSig.value=t.errorText,n.stateSig.value=`output-error`;return}case`tool-output-denied`:{let n=An(e,t.toolCallId);n.stateSig.value=`output-denied`;return}default:return}}const Pn=M.scope(`feedback:audio`);var Fn=class{constructor(){U(this,`ctx`,null),U(this,`master`,null),U(this,`buffers`,new Map)}unlock(){if(this.ctx){this.ctx.state===`suspended`&&this.ctx.resume();return}let e=globalThis.AudioContext??globalThis.webkitAudioContext;if(e)try{this.ctx=new e,this.master=this.ctx.createGain(),this.master.gain.value=1,this.master.connect(this.ctx.destination)}catch(e){Pn.warn(`AudioContext init failed`,{err:e})}}setVolume(e){if(!this.master||!this.ctx)return;let t=Math.max(0,Math.min(1,e));this.master.gain.setTargetAtTime(t,this.ctx.currentTime,.01)}playTone(e){let t=this.ctx,n=this.master;if(!t||!n||t.state!==`running`)return;let r=t.currentTime,i=e.noteMs/1e3;e.notes.forEach((a,o)=>{let s=t.createOscillator();s.type=e.type,s.frequency.value=a;let c=t.createGain(),l=r+o*i;c.gain.setValueAtTime(1e-4,l),c.gain.exponentialRampToValueAtTime(e.peakGain,l+.005),c.gain.exponentialRampToValueAtTime(1e-4,l+i),s.connect(c).connect(n),s.start(l),s.stop(l+i+.01)})}async playUrl(e){let t=this.ctx,n=this.master;if(!t||!n||t.state!==`running`)return;let r=await this.getBuffer(e);if(!r)return;let i=t.createBufferSource();i.buffer=r,i.connect(n),i.start()}destroy(){this.ctx&&this.ctx.close().catch(()=>void 0),this.ctx=null,this.master=null,this.buffers.clear()}async getBuffer(e){if(!this.ctx)return null;let t=this.buffers.get(e);if(t)return t instanceof Promise,t;let n=this.ctx,r=fetch(e).then(e=>e.ok?e.arrayBuffer():Promise.reject(Error(`fetch ${e.status}`))).then(e=>n.decodeAudioData(e)).then(t=>(this.buffers.set(e,t),t)).catch(t=>(Pn.warn(`audio fetch/decode failed`,{url:e,err:t}),this.buffers.delete(e),null));return this.buffers.set(e,r),r}};const In={messageReceived:10,messageSent:0,error:[20,40,20],voiceStart:10,voiceStop:0},Ln={messageReceived:{notes:[880,1318.51],noteMs:90,type:`sine`,peakGain:.45},messageSent:{notes:[1568],noteMs:60,type:`sine`,peakGain:.25},error:{notes:[523.25,392],noteMs:120,type:`triangle`,peakGain:.55},voiceStart:{notes:[1318.51],noteMs:50,type:`sine`,peakGain:.3},voiceStop:{notes:[880],noteMs:50,type:`sine`,peakGain:.3}};let Rn=null,zn=0;function Bn(){return typeof navigator<`u`&&typeof navigator.vibrate==`function`}function Vn(){if(typeof document>`u`)return null;let e=document.createElement(`input`);e.type=`checkbox`,e.setAttribute(`switch`,``),e.setAttribute(`aria-hidden`,`true`),e.tabIndex=-1,e.id=`__${v.cssPrefix}_haptic_${Math.random().toString(36).slice(2)}`;let t=document.createElement(`label`);t.htmlFor=e.id,t.setAttribute(`aria-hidden`,`true`);let n=`position:absolute!important;width:1px!important;height:1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;opacity:0!important;pointer-events:none!important;`;return e.style.cssText=n,t.style.cssText=n,document.body.append(e,t),{input:e,label:t}}function Hn(e){if(!(e===0||Array.isArray(e)&&e.every(e=>e===0))){if(Bn())try{navigator.vibrate(e);return}catch{}if(Rn||(Rn=Vn()),Rn)try{Rn.label.click()}catch{}}}function Un(){zn++;let e=!1;return()=>{e||(e=!0,zn=Math.max(0,zn-1),zn===0&&Rn&&(Rn.input.remove(),Rn.label.remove(),Rn=null))}}const Wn=M.scope(`feedback`);var Gn=class{constructor(e,t){U(this,`mutedSig`,d(!1)),U(this,`audio`,new Fn),U(this,`releaseHaptics`,void 0),U(this,`sound`,void 0),U(this,`haptics`,void 0),U(this,`lastPlayed`,new Map),U(this,`reducedMotionMq`,null),this.sound=e,this.haptics=t,this.releaseHaptics=Un(),this.audio.setVolume(this.effectiveVolume()),typeof matchMedia<`u`&&(this.reducedMotionMq=matchMedia(`(prefers-reduced-motion: reduce)`))}unlock(){this.audio.unlock(),this.audio.setVolume(this.effectiveVolume())}update(e,t){this.sound=e,this.haptics=t,this.audio.setVolume(this.effectiveVolume())}setMuted(e){this.mutedSig.value!==e&&(this.mutedSig.value=e)}toggleMuted(){this.mutedSig.value=!this.mutedSig.value}play(e){this.mutedSig.value||this.isDeduped(e)||(this.lastPlayed.set(e,performance.now()),this.sound.enabled&&this.playSound(e),this.haptics.enabled&&this.isTouchDevice()&&this.playHaptic(e))}destroy(){this.audio.destroy(),this.releaseHaptics()}isDeduped(e){let t=this.lastPlayed.get(e);return t!==void 0&&performance.now()-t<100}playSound(e){let t=this.sound.events?.[e];if(t===!1)return;if(typeof t==`string`){this.audio.playUrl(t).catch(e=>Wn.warn(`audio play failed`,{err:e,url:t}));return}let n=Ln[e];n&&this.audio.playTone(n)}playHaptic(e){if(this.reducedMotionMq?.matches)return;let t=this.haptics.events?.[e];t!==!1&&Hn(t===!0||t===void 0?In[e]:t)}effectiveVolume(){let e=this.sound.volume??.3;return this.reducedMotionMq?.matches?e*.5:e}isTouchDevice(){return typeof window>`u`?!1:matchMedia(`(hover: none) and (pointer: coarse)`).matches}};function Kn(e,t){return e instanceof Lt&&e.status===429?t.errorRateLimited:t.errorGeneric}const G={fill:`none`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:2,viewBox:`0 0 24 24`},qn=`${v.cssPrefix}-icon-dir`,Jn=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M21 12a8 8 0 0 1-12 6.93L3 21l1.65-5.16A8 8 0 1 1 21 12Z`})}),Yn=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M18 6 6 18M6 6l12 12`})}),Xn=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M12 5v14M5 12h14`})}),Zn=()=>g(`svg`,{...G,class:qn,"aria-hidden":`true`,children:[h(`path`,{d:`m22 2-7 20-4-9-9-4Z`}),h(`path`,{d:`M22 2 11 13`})]}),Qn=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M12 19V5M5 12l7-7 7 7`})}),$n=()=>h(`svg`,{...G,class:qn,"aria-hidden":`true`,children:h(`path`,{d:`M3 20V4l18 8-18 8Z`})}),er=()=>h(`svg`,{...G,class:qn,"aria-hidden":`true`,children:h(`path`,{d:`m9 18 6-6-6-6`})}),tr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`rect`,{x:`6`,y:`6`,width:`12`,height:`12`,rx:`2`})}),nr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`m21 11-9 9a5.5 5.5 0 0 1-7.78-7.78l8.49-8.49a3.67 3.67 0 0 1 5.19 5.19l-8.49 8.49a1.83 1.83 0 0 1-2.6-2.6l7.78-7.78`})}),rr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`rect`,{x:`9`,y:`2`,width:`6`,height:`12`,rx:`3`}),h(`path`,{d:`M5 10a7 7 0 0 0 14 0M12 19v3`})]}),ir=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M3 8V3h5M21 8V3h-5M3 16v5h5M21 16v5h-5`})}),ar=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M8 3v5H3M16 3v5h5M8 21v-5H3M16 21v-5h5`})}),or=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M3 3h7v2H5v5H3zM21 3h-7v2h5v5h2zM3 21h7v-2H5v-5H3zM21 21h-7v-2h5v-5h2z`})}),sr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M10 3v5H3M14 3v5h7M10 21v-5H3M14 21v-5h7`})}),cr=()=>h(`svg`,{...G,"aria-hidden":`true`,viewBox:`0 0 10 10`,children:h(`path`,{d:`M9 1L1 9M9 5L5 9M9 9H9`,strokeWidth:`1.5`})}),lr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`5`,r:`1.5`,fill:`currentColor`,stroke:`none`}),h(`circle`,{cx:`12`,cy:`12`,r:`1.5`,fill:`currentColor`,stroke:`none`}),h(`circle`,{cx:`12`,cy:`19`,r:`1.5`,fill:`currentColor`,stroke:`none`})]}),ur=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M11 5 6 9H2v6h4l5 4zM15 9a5 5 0 0 1 0 6M18 7a9 9 0 0 1 0 10`})}),dr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M11 5 6 9H2v6h4l5 4zM22 9l-6 6M16 9l6 6`})}),fr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M3 18 8 6l5 12M4.7 14h6.6`}),h(`path`,{d:`M14.5 18l3.2-7 3.2 7M15.6 15.8h4.2`})]}),pr=()=>h(`svg`,{...G,class:qn,"aria-hidden":`true`,children:h(`path`,{d:`m5 6 6 6-6 6M13 6l6 6-6 6`})}),mr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M20 6 9 17l-5-5`})}),hr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M3 3v6h6`}),h(`path`,{d:`M3.05 13A9 9 0 1 0 6 5.3L3 9`}),h(`path`,{d:`M12 7v5l3 2`})]}),gr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`10`}),h(`path`,{d:`M2 12h20`}),h(`path`,{d:`M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z`})]}),_r=()=>h(`svg`,{...G,class:qn,"aria-hidden":`true`,children:h(`path`,{d:`M19 12H5M12 19l-7-7 7-7`})}),vr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M12 20h9`}),h(`path`,{d:`M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z`})]}),yr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`m6 9 6 6 6-6`})}),br=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z`}),h(`path`,{d:`M14 2v6h6`})]}),xr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`m12 3-1.5 4.5L6 9l4.5 1.5L12 15l1.5-4.5L18 9l-4.5-1.5Z`}),h(`path`,{d:`M19 15v4M17 17h4M5 3v2M4 4h2`})]}),Sr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z`})}),Cr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`10`}),h(`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`}),h(`path`,{d:`M12 17h.01`})]}),wr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`m15 4 3 3-9 9-3-3z`}),h(`path`,{d:`M18 2v2M20 4h2M3 20l3-3M3 16h2M5 14v2`})]}),Tr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`rect`,{x:`4`,y:`8`,width:`16`,height:`12`,rx:`2`}),h(`path`,{d:`M12 8V4`}),h(`circle`,{cx:`12`,cy:`3`,r:`1`}),h(`path`,{d:`M2 14h2M20 14h2M9 13h.01M15 13h.01M9.5 17h5`})]}),Er=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M4 14v-2a8 8 0 0 1 16 0v2`}),h(`rect`,{x:`2`,y:`14`,width:`4`,height:`6`,rx:`1.5`}),h(`rect`,{x:`18`,y:`14`,width:`4`,height:`6`,rx:`1.5`}),h(`path`,{d:`M20 20v1a3 3 0 0 1-3 3h-5`})]}),Dr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`10`}),h(`circle`,{cx:`12`,cy:`12`,r:`4`}),h(`path`,{d:`m4.93 4.93 4.24 4.24M14.83 14.83l4.24 4.24M14.83 9.17l4.24-4.24M4.93 19.07l4.24-4.24`})]}),Or=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`11`,cy:`11`,r:`7`}),h(`path`,{d:`m21 21-4.3-4.3`})]}),kr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`9`}),h(`path`,{d:`m8.5 12 2.5 2.5 4.5-5`})]}),Ar=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M3 9.5 12 3l9 6.5`}),h(`path`,{d:`M5 9v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9`})]}),jr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`m3 11 15-5v12L3 13z`}),h(`path`,{d:`M3 11v2a2 2 0 0 0 2 2h1V9H5a2 2 0 0 0-2 2z`}),h(`path`,{d:`M7 15v3a2 2 0 0 0 4 0v-2`}),h(`path`,{d:`M21 10a3 3 0 0 1 0 4`})]}),Mr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z`}),h(`path`,{d:`M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1`})]}),Nr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`4`}),h(`path`,{d:`M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41`})]}),Pr=()=>h(`svg`,{...G,"aria-hidden":`true`,children:h(`path`,{d:`M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z`})}),Fr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`9`}),h(`path`,{d:`M12 3v18`}),h(`path`,{d:`M12 3a9 9 0 0 1 0 18z`,fill:`currentColor`,stroke:`none`})]}),Ir=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`10.5`,cy:`10.5`,r:`6.5`}),h(`path`,{d:`M8 11a2.5 2.5 0 0 0 5 0`}),h(`path`,{d:`m20 20-4.4-4.4`})]}),Lr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M12 3.5 13.6 9 19 10.5 13.6 12 12 17.5 10.4 12 5 10.5 10.4 9z`}),h(`path`,{d:`M18.5 4v3M20 5.5h-3M5.5 16v2.5M6.75 17.25h-2.5`})]}),Rr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M4 18h16`}),h(`path`,{d:`M5 18a7 7 0 0 1 14 0`}),h(`path`,{d:`M12 8V6`}),h(`path`,{d:`M10 6h4`})]}),zr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M7 11V6.5a1.5 1.5 0 0 1 3 0V10`}),h(`path`,{d:`M10 10V5.5a1.5 1.5 0 0 1 3 0V10`}),h(`path`,{d:`M13 10V6.5a1.5 1.5 0 0 1 3 0V12`}),h(`path`,{d:`M16 9.5a1.5 1.5 0 0 1 3 0v2.5a7 7 0 0 1-7 7 7 7 0 0 1-6.4-4.2L4 12.5a1.5 1.5 0 0 1 2.6-1.5L7 11`})]}),Br=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`rect`,{x:`9`,y:`9`,width:`11`,height:`11`,rx:`2`}),h(`path`,{d:`M5 15a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2`})]}),Vr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1z`}),h(`path`,{d:`M7 10l4-7a2.5 2.5 0 0 1 2.5 2.5V8h5a2 2 0 0 1 2 2.3l-1.2 8A2 2 0 0 1 17.3 20H7`})]}),Hr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`path`,{d:`M17 14V3h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1z`}),h(`path`,{d:`M17 14l-4 7a2.5 2.5 0 0 1-2.5-2.5V16h-5a2 2 0 0 1-2-2.3l1.2-8A2 2 0 0 1 6.7 4H17`})]}),Ur=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`3.5`}),h(`path`,{d:`M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9l-2.1 2.1M7 17l-2.1 2.1`})]}),Wr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`9`}),h(`path`,{d:`M12 7v5l3 2`})]}),Gr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`9`}),h(`path`,{d:`m8.5 12 2.5 2.5 4.5-5`})]}),Kr=()=>g(`svg`,{...G,"aria-hidden":`true`,children:[h(`circle`,{cx:`12`,cy:`12`,r:`9`}),h(`path`,{d:`m15 9-6 6M9 9l6 6`})]}),qr={chat:Jn,message:Sr,bubbles:Mr,spark:xr,wand:wr,bot:Tr,help:Cr,lifebuoy:Dr,headset:Er,search:Ir,sparkles:Lr,concierge:Rr,wave:zr},K=v.cssPrefix,q={launcher:`${K}-launcher`,callout:`${K}-callout`,calloutDismiss:`${K}-callout-dismiss`,panel:`${K}-panel`,panelHeader:`${K}-panel-header`,resizeGrip:`${K}-resize-grip`,scrollToBottom:`${K}-scroll-to-bottom`,actionHistory:`${K}-action-history`,actionClose:`${K}-action-close`,langSegment:`${K}-lang-segment`,composer:`${K}-composer`,composerInput:`${K}-composer-input`,composerSend:`${K}-composer-send`,composerStop:`${K}-composer-stop`,composerAttach:`${K}-composer-attach`,composerFileInput:`${K}-composer-file-input`,composerVoice:`${K}-composer-voice`,attachmentChip:`${K}-attachment-chip`,attachmentRemove:`${K}-attachment-remove`,suggestion:`${K}-suggestion`,messageBubble:`${K}-message`,messageRetry:`${K}-message-retry`,messageFeedback:`${K}-message-feedback`,feedbackUp:`${K}-feedback-up`,feedbackDown:`${K}-feedback-down`,messageCopy:`${K}-message-copy`,historyPane:`${K}-history-pane`,historyBack:`${K}-history-back`,historyItem:`${K}-history-item`,sidebar:`${K}-sidebar`,sidebarToggle:`${K}-sidebar-toggle`,sidebarNewConversation:`${K}-sidebar-new-conversation`,sidebarItem:`${K}-sidebar-item`,messengerHome:`${K}-messenger-home`,modulesEmpty:`${K}-modules-empty`,tab:`${K}-tab`,tabBadge:`${K}-tab-badge`,homeView:`${K}-home-view`,homeGreeting:`${K}-home-greeting`,homeBrand:`${K}-home-brand`,backHeader:`${K}-back-header`,contentView:`${K}-content-view`,contentScroll:`${K}-content-scroll`,homeSearch:`${K}-home-search`,helpSearch:`${K}-help-search`,homeRecent:`${K}-home-recent`,homeContentRow:`${K}-home-content-row`,helpArticle:`${K}-help-article`,newsItem:`${K}-news-item`,formGate:`${K}-form-gate`,formDone:`${K}-form-done`,formDoneToggle:`${K}-form-done-toggle`,formAnswers:`${K}-form-answers`,formFill:`${K}-form-fill`,formSubmit:`${K}-form-submit`,formSkip:`${K}-form-skip`,formField:`${K}-form-field`,toolAskQuestions:`${K}-tool-ask-questions`,toolInputSubmit:`${K}-tool-input-submit`,toolInputSkip:`${K}-tool-input-skip`,toolApproval:`${K}-tool-approval`,toolApprove:`${K}-tool-approve`,toolReject:`${K}-tool-reject`,toolEdit:`${K}-tool-edit`,toolDecision:`${K}-tool-decision`,toolAskSummary:`${K}-ask-questions-summary`,toolAskOptions:`${K}-ask-questions-options-toggle`,toolCall:`${K}-tool-call`,source:`${K}-source`,operatorRequest:`${K}-operator-request`,operatorBanner:`${K}-operator-banner`};function Jr(e,t){return`${e}-${t}`}const Yr=v.cssPrefix;function Xr({onToggle:e,launcher:t,strings:n,leaving:r,edgeTab:i}){let a=t.variant!==`circle`&&!!t.label;return g(`button`,{type:`button`,class:`${Yr}-fab`,"data-variant":t.variant,"data-size":t.size,"data-edge-tab":i?`true`:void 0,"data-leaving":r?`true`:void 0,"data-testid":q.launcher,onClick:e,"aria-label":n.launcherOpen,children:[Zr(t.icon),a?h(`span`,{class:`${Yr}-fab-label`,children:T(n,t.label??``)}):null]})}function Zr(e){let t=qr[e];return t?h(t,{}):h(Qr,{source:e})}function Qr({source:e}){return h(`span`,{ref:t=>{t&&$r(t,e)},"aria-hidden":`true`})}function $r(e,t){if(e.dataset.svgMounted!==t)try{let n=new DOMParser().parseFromString(t,`image/svg+xml`).documentElement;n&&n.tagName.toLowerCase()===`svg`&&(e.replaceChildren(document.importNode(n,!0)),e.dataset.svgMounted=t)}catch{}}function ei({callout:e,launcherPosition:t,strings:n,closeLabel:r,onDismiss:a}){let[o,s]=c(!1);return i(()=>{let t=setTimeout(()=>s(!0),e.delayMs);return()=>clearTimeout(t)},[e.delayMs]),i(()=>{if(!o||e.autoDismissMs<=0)return;let t=setTimeout(a,e.autoDismissMs);return()=>clearTimeout(t)},[o,e.autoDismissMs,a]),o?g(`div`,{class:`${Yr}-callout`,role:`status`,"data-shape":e.shape,"data-position":ti(e.position,t),"data-animated":e.animated?`true`:void 0,"data-testid":q.callout,children:[h(`span`,{children:T(n,e.text)}),h(`button`,{type:`button`,class:`${Yr}-callout-close`,onClick:a,"aria-label":r,title:r,"data-testid":q.calloutDismiss,children:h(Yn,{})})]}):null}function ti(e,t){let n=t.endsWith(`-right`),r=t.startsWith(`bottom-`);return e===`vertical`?r?`top`:`bottom`:n?`left`:`right`}function ni({panelEl:e,resize:t,position:n,initialSize:r,onSizeChange:a,strings:o}){let c=v.cssPrefix,l=s(null);if(i(()=>{if(!e)return;let n=e.style;t.minWidth&&n.setProperty(`--${c}-resize-min-w`,t.minWidth),t.maxWidth&&n.setProperty(`--${c}-resize-max-w`,t.maxWidth),t.minHeight&&n.setProperty(`--${c}-resize-min-h`,t.minHeight),t.maxHeight&&n.setProperty(`--${c}-resize-max-h`,t.maxHeight),r&&(n.setProperty(`--${c}-widget-w`,`${r.width}px`),n.setProperty(`--${c}-widget-h`,`${r.height}px`))},[e,t.minWidth,t.maxWidth,t.minHeight,t.maxHeight,c,r]),!e)return null;let u=n.startsWith(`top-`),d=n.endsWith(`-right`),f=`${c}-resize-grip ${c}-resize-grip--${u?`bottom`:`top`}-${d?`left`:`right`}`,p=t=>{if(!e)return;let n=t.currentTarget,r=e.getBoundingClientRect();l.current={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,startW:r.width,startH:r.height,dirX:d?-1:1,dirY:u?1:-1},n.setPointerCapture(t.pointerId),e.setAttribute(`data-resizing`,``),t.preventDefault()},m=t=>{let n=l.current;if(!n||t.pointerId!==n.pointerId||!e)return;let r=(t.clientX-n.startX)*n.dirX,i=(t.clientY-n.startY)*n.dirY;e.style.setProperty(`--${c}-widget-w`,`${n.startW+r}px`),e.style.setProperty(`--${c}-widget-h`,`${n.startH+i}px`)},g=t=>{let n=l.current;if(!n||t.pointerId!==n.pointerId||!e)return;t.currentTarget.releasePointerCapture(t.pointerId),e.removeAttribute(`data-resizing`);let r=e.getBoundingClientRect();a({width:Math.round(r.width),height:Math.round(r.height)}),l.current=null};return h(`div`,{class:f,role:`separator`,"aria-orientation":`vertical`,"aria-label":o.resizeHandle,title:o.resizeHandle,onPointerDown:p,onPointerMove:m,onPointerUp:g,onPointerCancel:g,"data-testid":q.resizeGrip,children:h(cr,{})})}const ri=v.cssPrefix,ii=`.${ri}-header, .${ri}-back-header, .${ri}-home-hero`;function ai(e,t){i(()=>{if(!t||!e)return;let n=e=>Number.parseFloat(e)||0,r=(e,t)=>Math.min(t,Math.max(-t,e)),i=null,a=t=>{let r=t.target;if(!(r instanceof Element)||!r.closest(ii)||r.closest(`button, a, input, textarea, select, [role="tab"], [contenteditable]`))return;let a=e.getBoundingClientRect();i={id:t.pointerId,x:t.clientX,y:t.clientY,dx:n(e.style.getPropertyValue(`--${ri}-modal-dx`)),dy:n(e.style.getPropertyValue(`--${ri}-modal-dy`)),maxX:(window.innerWidth+a.width)/2-56,maxY:(window.innerHeight+a.height)/2-56},e.dataset.dragging=`true`,t.preventDefault()},o=t=>{if(!i||t.pointerId!==i.id)return;let n=r(i.dx+t.clientX-i.x,i.maxX),a=r(i.dy+t.clientY-i.y,i.maxY);e.style.setProperty(`--${ri}-modal-dx`,`${n}px`),e.style.setProperty(`--${ri}-modal-dy`,`${a}px`)},s=t=>{!i||t.pointerId!==i.id||(i=null,delete e.dataset.dragging)};return e.addEventListener(`pointerdown`,a),window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s),window.addEventListener(`pointercancel`,s),()=>{e.removeEventListener(`pointerdown`,a),window.removeEventListener(`pointermove`,o),window.removeEventListener(`pointerup`,s),window.removeEventListener(`pointercancel`,s)}},[e,t])}function oi(e,t,n){switch(e){case`clear`:case`sound`:case`history`:case`language`:case`theme`:case`textSize`:return!0;case`expand`:return t===`floating`;case`fullscreen`:return t!==`standalone`;case`close`:return t===`standalone`||t===`page`?!1:t!==`inline`||n===`fullscreen`}}function si(e,t,n){return oi(`close`,e,t)?n.includes(`close`):!1}function ci(e,t){return e===`inline`&&t===`fullscreen`?`exit-fullscreen`:`close`}function li(e){let t=t=>{if(t.key!==`Tab`)return;let n=[...e.querySelectorAll(`a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]):not([type="hidden"]),select:not([disabled]),[tabindex]:not([tabindex="-1"])`)].filter(e=>e.offsetParent!==null||e===document.activeElement);if(n.length===0){t.preventDefault();return}let r=n[0],i=n[n.length-1];if(!r||!i)return;let a=e.getRootNode().activeElement;t.shiftKey&&a===r?(t.preventDefault(),i.focus()):!t.shiftKey&&a===i&&(t.preventDefault(),r.focus())};return e.addEventListener(`keydown`,t),()=>e.removeEventListener(`keydown`,t)}function ui(e){return e.trim().split(/\s+/).slice(0,2).map(e=>e.charAt(0).toUpperCase()).join(``)}const di=v.cssPrefix;function fi({agent:e,strings:t}){let n=e.status??`online`,r=T(t,e.name),i=e.title?T(t,e.title):null;return g(`div`,{class:`${di}-agent`,children:[h(`div`,{class:`${di}-agent-avatar`,"data-status":n,children:e.avatar?h(`img`,{src:e.avatar,alt:``}):h(`span`,{children:ui(r)})}),g(`div`,{class:`${di}-agent-meta`,children:[h(`strong`,{children:r}),i?h(`span`,{children:i}):null]})]})}const pi=M.scope(`attachments`);function mi(e,t,n){let r=_i(e),i=[],a=[],o=bi(n.accept),s=t.reduce((e,t)=>e+t.size,0),c=t.length;for(let e of r){let t=gi(e,c,s,n,o);if(t){a.push({file:e,reason:t});continue}i.push(yi(e)),s+=e.size,c+=1}return(i.length||a.length)&&pi.debug(`ingest`,{accepted:i.length,rejected:a.map(e=>({name:e.file.name,reason:e.reason}))}),{accepted:i,rejected:a}}function hi(e){try{URL.revokeObjectURL(e.previewUrl)}catch(e){pi.debug(`revokeObjectURL failed`,{error:e})}}function gi(e,t,n,r,i){return t>=r.maxCount?`count`:n+e.size>r.maxBytes?`bytes`:xi(e,i)?null:`mime`}function _i(e){return e?Array.isArray(e)?e.filter(e=>e instanceof File):[...e].map(e=>e instanceof File?e:vi(e)).filter(e=>e!==null):[]}function vi(e){let t=e;return!t?.getAsFile||t.kind!==`file`?null:t.getAsFile()}function yi(e){return{file:e,id:ot(),mediaType:e.type||`application/octet-stream`,name:e.name||`pasted-file`,previewUrl:URL.createObjectURL(e),size:e.size}}function bi(e){return e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean).map(e=>{if(e.startsWith(`.`))return{kind:`ext`,ext:e};let[t=`*`,n=`*`]=e.split(`/`);return{kind:`mime`,type:t,subtype:n}})}function xi(e,t){if(t.length===0)return!0;let[n=`*`,r=`*`]=(e.type||``).toLowerCase().split(`/`),i=(e.name||``).toLowerCase();return t.some(e=>e.kind===`ext`?i.endsWith(e.ext):(e.type===`*`||e.type===n)&&(e.subtype===`*`||e.subtype===r))}const Si=v.cssPrefix;function Ci({attachment:e,onRemove:t}){let n=e.mediaType.startsWith(`image/`);return g(`span`,{class:`${Si}-attachment-chip`,title:e.name,"data-testid":Jr(q.attachmentChip,e.id),children:[n?h(`img`,{class:`${Si}-attachment-thumb`,src:e.previewUrl,alt:``}):h(`span`,{class:`${Si}-attachment-thumb`,"aria-hidden":`true`,children:h(br,{})}),h(`span`,{class:`${Si}-attachment-name`,children:e.name}),h(`button`,{type:`button`,class:`${Si}-attachment-remove`,onClick:t,"aria-label":`Remove ${e.name}`,"data-testid":Jr(q.attachmentRemove,e.id),children:h(Yn,{})})]})}const wi={isSupported:!1,start:()=>void 0,stop:()=>void 0};function Ti(e,t,n){return e===`disabled`?wi:e===`server`?ki(n):Ei(t)}function Ei(e){let t=Di();if(!t)return wi;let n=null;return{isSupported:!0,start(r,i){n=new t,n.continuous=!0,n.interimResults=!0,n.lang=e,n.addEventListener(`result`,e=>{let t=e,n=``,i=!1;for(let e=t.resultIndex;e<t.results.length;e++){let r=t.results[e];r&&(n+=r[0].transcript,r.isFinal&&(i=!0))}r(n,i)});let a=()=>{n=null,i()};n.addEventListener(`end`,a),n.addEventListener(`error`,a),n.start()},stop(){n?.stop()}}}function Di(){return window.SpeechRecognition??window.webkitSpeechRecognition}const Oi=[`audio/webm;codecs=opus`,`audio/webm`,`audio/ogg;codecs=opus`,`audio/mp4`];function ki(e){if(typeof MediaRecorder>`u`||!navigator?.mediaDevices?.getUserMedia)return wi;let t=null,n=null,r=[],i=()=>{for(let e of n?.getTracks()??[])e.stop();n=null};return{isSupported:!0,async start(a,o){try{n=await navigator.mediaDevices.getUserMedia({audio:!0});let s=Ai();t=new MediaRecorder(n,s?{mimeType:s}:void 0),r=[],t.addEventListener(`dataavailable`,e=>{e.data.size>0&&r.push(e.data)}),t.addEventListener(`stop`,async()=>{let n=t?.mimeType??`audio/webm`;i();let s=new Blob(r,{type:n});r=[];try{let{text:t}=await e(s,n);t&&a(t,!0)}catch{}finally{o()}}),t.start()}catch{i(),o()}},stop(){t?.stop()}}}function Ai(){for(let e of Oi)if(MediaRecorder.isTypeSupported(e))return e}const ji=v.cssPrefix,Mi=M.scope(`composer`);function Ni(e){return e.reduce((e,t)=>e+t.size,0)}const Pi={arrowUp:Qn,paperPlane:Zn,send:$n,chevron:er};function Fi({options:e,transport:t,feedback:n,bus:r,isStreaming:a,operatorRequestEnabled:o,controlMode:l,onRequestOperator:u,onSend:d,onStop:f,attachApiRef:p}){let m=e.strings,[_,v]=c(``),[y,b]=c([]),[x,S]=c(!1),C=s(null),w=s(null),T=e.features.fileUpload,E=e.features.voice,[D,O]=c(()=>Ti(E,e.locale,(e,n)=>t.transcribe(e,n)));i(()=>{x||E===`disabled`||O(Ti(E,e.locale,(e,n)=>t.transcribe(e,n)))},[e.locale,E,t,x]),i(()=>{let e=C.current;if(!e)return;let t=e.getRootNode(),n=`activeElement`in t?t.activeElement:null;n&&e.closest(`.${ji}-panel`)?.contains(n)||e.focus({preventScroll:!0})},[]),i(()=>{let e=C.current;if(!e)return;if(_.length===0){e.style.height=``;return}e.style.height=`auto`;let t=parseFloat(getComputedStyle(e).fontSize)*.7,n=Math.min(e.scrollHeight,160);e.style.height=`${n<40+t?40:n}px`},[_]);let k=s(y);k.current=y,i(()=>()=>k.current.forEach(hi),[]),i(()=>{if(p)return p.current={attachFromDrop:t=>{let n=mi(t,k.current,e.attachments);n.accepted.length!==0&&(Mi.info(`attach (drop)`,{count:n.accepted.length,totalBytes:Ni(n.accepted)}),r.emit(`attach`,{count:n.accepted.length,totalBytes:Ni(n.accepted)}),b(e=>[...e,...n.accepted]))},fill:e=>{v(e);let t=C.current;t&&(t.focus({preventScroll:!0}),requestAnimationFrame(()=>t.setSelectionRange(t.value.length,t.value.length)))}},()=>{p.current&&(p.current=null)}},[p,e.attachments]),i(()=>{let t=C.current;if(!t)return;let n=t.closest(`.${ji}-panel`);if(!n)return;let i=n=>{let i=n.clipboardData;if(!i)return;let a=n.target?.closest?.(`input, textarea, [contenteditable]:not([contenteditable='false'])`);if(a&&a!==t)return;if(T){let t=mi(i.items,k.current,e.attachments);if(t.accepted.length>0){n.preventDefault(),Mi.info(`attach (paste)`,{count:t.accepted.length,totalBytes:Ni(t.accepted)}),r.emit(`attach`,{count:t.accepted.length,totalBytes:Ni(t.accepted)}),b(e=>[...e,...t.accepted]);return}}if(a===t)return;let o=i.getData(`text/plain`);o&&(n.preventDefault(),v(e=>e+o),t.focus())};return n.addEventListener(`paste`,i),()=>n.removeEventListener(`paste`,i)},[T,e.attachments,ji]);let A=()=>{let e=_.trim();!e&&y.length===0||a||(d(e,y),v(``),b([]))},ee=e=>{e.key!==`Enter`||e.shiftKey||e.isComposing||(e.preventDefault(),a?f():A())},te=t=>{let n=t.target,i=mi(n.files,y,e.attachments);i.accepted.length>0&&(Mi.info(`attach (file picker)`,{count:i.accepted.length,totalBytes:Ni(i.accepted)}),r.emit(`attach`,{count:i.accepted.length,totalBytes:Ni(i.accepted)}),b(e=>[...e,...i.accepted])),n.value=``},ne=e=>{Mi.info(`removeAttachment`,{id:e}),r.emit(`removeAttachment`,{id:e}),b(t=>{let n=t.find(t=>t.id===e);return n&&hi(n),t.filter(t=>t.id!==e)})},j=s(null),re=()=>{if(D.isSupported){if(x){let e=j.current?Date.now()-j.current:0;Mi.info(`voiceStop`,{durationMs:e}),r.emit(`voiceStop`,{durationMs:e}),D.stop(),S(!1),n.play(`voiceStop`),j.current=null;return}j.current=Date.now(),Mi.info(`voiceStart`),r.emit(`voiceStart`,void 0),S(!0),n.play(`voiceStart`),D.start((e,t)=>v(n=>t?`${n}${e} `:n),()=>{if(S(!1),j.current){let e=Date.now()-j.current;Mi.debug(`voiceStop (auto)`,{durationMs:e}),r.emit(`voiceStop`,{durationMs:e}),j.current=null}})}},ie=Pi[e.composer.sendButton.icon];return g(`div`,{class:`${ji}-composer`,"data-testid":q.composer,children:[y.length>0?h(`div`,{class:`${ji}-attachments`,children:y.map(e=>h(Ci,{attachment:e,onRemove:()=>ne(e.id)},e.id))}):null,g(`div`,{class:`${ji}-composer-row`,children:[g(`div`,{class:`${ji}-composer-actions`,children:[T?h(`button`,{type:`button`,class:`${ji}-icon-btn`,onClick:()=>w.current?.click(),"aria-label":m.attach,"data-testid":q.composerAttach,children:h(nr,{})}):null,D.isSupported?h(`button`,{type:`button`,class:`${ji}-icon-btn`,onClick:re,"aria-label":x?m.micStop:m.micStart,"aria-pressed":x,"data-recording":x?`true`:void 0,"data-testid":q.composerVoice,children:h(rr,{})}):null,o&&l===`ai-agent`&&u?h(`button`,{type:`button`,class:`${ji}-icon-btn`,onClick:u,"aria-label":m.talkToOperator,title:m.talkToOperator,"data-testid":q.operatorRequest,children:h(Er,{})}):null]}),h(`textarea`,{ref:C,class:`${ji}-textarea`,rows:1,value:_,placeholder:m.composerPlaceholder,onInput:e=>v(e.target.value),onKeyDown:ee,"aria-label":m.composerPlaceholder,"data-testid":q.composerInput}),a?h(`button`,{type:`button`,class:`${ji}-send`,onClick:f,"aria-label":m.stop,"data-testid":q.composerStop,children:h(tr,{})}):h(`button`,{type:`button`,class:`${ji}-send`,"data-shape":e.composer.sendButton.shape,"data-variant":e.composer.sendButton.variant,onClick:A,disabled:!_.trim()&&y.length===0,"aria-label":m.send,"data-testid":q.composerSend,children:h(ie,{})})]}),h(`input`,{ref:w,type:`file`,multiple:!0,accept:e.attachments.accept,onChange:te,class:`${ji}-sr-only`,"data-testid":q.composerFileInput})]})}const Ii=v.cssPrefix;function Li({visible:e,strings:t}){return e?h(`div`,{class:`${Ii}-dropzone`,role:`status`,"aria-live":`polite`,children:t.dropZone}):null}function Ri({containerRef:e,onDrop:t}){let[n,r]=c(!1);return i(()=>{let n=e.current;if(!n)return;let i=0,a=e=>{i+=1,e.dataTransfer?.types.includes(`Files`)&&(e.preventDefault(),r(!0))},o=()=>{--i,!(i>0)&&(i=0,r(!1))},s=e=>{e.dataTransfer?.types.includes(`Files`)&&e.preventDefault()},c=e=>{i=0,r(!1),e.dataTransfer&&(e.preventDefault(),t(e.dataTransfer.items))};return n.addEventListener(`dragenter`,a),n.addEventListener(`dragleave`,o),n.addEventListener(`dragover`,s),n.addEventListener(`drop`,c),()=>{n.removeEventListener(`dragenter`,a),n.removeEventListener(`dragleave`,o),n.removeEventListener(`dragover`,s),n.removeEventListener(`drop`,c)}},[e,t]),{visible:n}}function zi({itemCount:e,initialFocusIndex:t}){let[n,a]=c(!1),o=s(null),l=s(null),[u,d]=c(-1),f=r(()=>{a(!1),d(-1),o.current?.focus()},[]),p=r(()=>a(e=>!e),[]);return i(()=>{if(!n)return;let e=e=>{let t=l.current,n=o.current;if(!t||!n)return;let r=e.composedPath();r.includes(t)||r.includes(n)||(a(!1),d(-1))};return document.addEventListener(`click`,e,!0),()=>document.removeEventListener(`click`,e,!0)},[n]),i(()=>{if(!n||e===0)return;let r=t?.()??0;d(r<0||r>=e?0:r)},[n,e,t]),i(()=>{!n||u<0||(l.current?.querySelectorAll(`[role='menuitem']`))?.[u]?.focus()},[n,u]),{open:n,focusIndex:u,triggerRef:o,menuRef:l,toggle:p,close:f,onTriggerKey:r(e=>{(e.key===`ArrowDown`||e.key===`Enter`||e.key===` `)&&(e.preventDefault(),a(!0))},[]),onMenuKey:r(t=>{if(e!==0)switch(t.key){case`Escape`:t.preventDefault(),f();return;case`ArrowDown`:t.preventDefault(),d(t=>(t+1)%e);return;case`ArrowUp`:t.preventDefault(),d(t=>(t-1+e)%e);return;case`Home`:t.preventDefault(),d(0);return;case`End`:t.preventDefault(),d(e-1)}},[e,f])}}function Bi({items:e,triggerLabel:t}){let n=v.cssPrefix,r=zi({itemCount:e.length}),i=e=>{e.disabled||(e.onSelect?.(),e.keepOpen||r.close())},a=(e,t)=>e.onSelectValue?.(t),o=(e,t)=>{let n=t.segments;if(!n?.length)return;let r=Math.max(0,n.findIndex(e=>e.value===t.value)),i=-1;if(e.key===`ArrowRight`||e.key===`Enter`||e.key===` `)i=(r+1)%n.length;else if(e.key===`ArrowLeft`)i=(r-1+n.length)%n.length;else return;e.preventDefault(),e.stopPropagation(),a(t,n[i].value)};return g(`div`,{class:`${n}-menu-wrap`,children:[h(`button`,{ref:r.triggerRef,type:`button`,class:`${n}-icon-btn`,"aria-label":t,"aria-haspopup":`menu`,"aria-expanded":r.open,title:t,onClick:r.toggle,onKeyDown:r.onTriggerKey,children:h(lr,{})}),r.open?h(`div`,{ref:r.menuRef,class:`${n}-menu`,role:`menu`,"aria-label":t,onKeyDown:r.onMenuKey,tabIndex:-1,children:e.map(e=>e.segments?g(`div`,{role:`menuitem`,class:`${n}-menu-item ${n}-menu-item-segmented`,"aria-label":e.label,tabIndex:-1,onKeyDown:t=>o(t,e),children:[e.icon?h(`span`,{class:`${n}-menu-icon`,children:e.icon}):null,h(`span`,{class:`${n}-menu-label`,children:e.label}),h(`span`,{class:`${n}-segmented`,role:`group`,"aria-label":e.label,children:e.segments.map(t=>{let r=t.value===e.value;return h(`button`,{type:`button`,role:`menuitemradio`,"aria-checked":r,class:`${n}-segment`,"data-on":r?`true`:void 0,lang:t.lang,title:t.value,tabIndex:-1,"data-testid":`${q.langSegment}-${t.value}`,onClick:()=>a(e,t.value),children:t.label},t.value)})})]},e.id):g(`button`,{type:`button`,role:`menuitem`,class:`${n}-menu-item`,"aria-pressed":e.type===`switch`?e.on:void 0,disabled:e.disabled,onClick:()=>i(e),children:[e.icon?h(`span`,{class:`${n}-menu-icon`,children:e.icon}):null,h(`span`,{class:`${n}-menu-label`,children:e.label}),e.type===`switch`&&e.on?h(`span`,{class:`${n}-menu-check`,"aria-hidden":`true`,children:h(mr,{})}):null]},e.id))}):null]})}const Vi=v.cssPrefix;function Hi(e){let t=typeof matchMedia!=`function`||matchMedia(`(prefers-color-scheme: dark)`).matches;return e===`auto`?t?`light`:`dark`:t?e===`light`?`dark`:`auto`:e===`dark`?`light`:`auto`}const Ui={normal:`large`,large:`small`,small:`normal`};function Wi(e){return h(e===`light`?Nr:e===`dark`?Pr:Fr,{})}function Gi(e){return(e.split(`-`)[0]??e).toUpperCase()}function Ki({panelProps:e,variant:t}){let{options:n,panelSize:r,feedback:i,onClose:a,onClear:o,onExpand:s,onFullscreen:c,onSoundToggle:l}=e,{onToggleHistory:u,onLocaleChange:d,onThemeChange:p,onTextSizeChange:m}=e,_=n.strings,v=n.mode,y=t===`chat`,b=f(()=>i.mutedSig.value).value,x=new Set(n.actions),S=e=>x.has(e),C=typeof matchMedia==`function`&&matchMedia(`(max-width: 640px)`).matches,w=e=>!C&&oi(e,v,r),T=n.themeMode,E={auto:_.themeAuto,light:_.themeLight,dark:_.themeDark},D=n.textSize,O={small:_.textSizeSmall,normal:_.textSizeNormal,large:_.textSizeLarge},k=[];if(y&&S(`clear`)&&k.push({id:`clear`,icon:h(vr,{}),label:_.newConversation,onSelect:o}),S(`expand`)&&w(`expand`)){let e=r===`expanded`;k.push({id:`expand`,icon:h(e?ar:ir,{}),label:e?_.collapse:_.expand,type:`switch`,on:e,onSelect:s})}if(S(`fullscreen`)&&w(`fullscreen`)){let e=r===`fullscreen`;k.push({id:`fullscreen`,icon:h(e?sr:or,{}),label:e?_.exitFullscreen:_.fullscreen,type:`switch`,on:e,onSelect:c})}y&&S(`sound`)&&k.push({id:`sound`,icon:h(b?dr:ur,{}),label:b?_.soundOff:_.soundOn,type:`switch`,on:!b,onSelect:l}),S(`theme`)&&k.push({id:`theme`,icon:Wi(T),label:`${_.theme}: ${E[T]}`,onSelect:()=>p(Hi(T)),keepOpen:!0}),S(`textSize`)&&k.push({id:`textSize`,icon:h(fr,{}),label:`${_.textSize}: ${O[D]}`,onSelect:()=>m(Ui[D]),keepOpen:!0}),S(`language`)&&n.availableLocales.length>1&&k.push({id:`language`,icon:h(gr,{}),label:_.language,segments:n.availableLocales.map(e=>({value:e,label:Gi(e),lang:e})),value:n.locale,onSelectValue:d});let A=!!a&&si(v,r,n.actions),ee=y&&S(`history`);return g(`div`,{class:`${Vi}-header-actions`,children:[ee?h(`button`,{type:`button`,class:`${Vi}-icon-btn`,onClick:u,"aria-label":_.history,title:_.history,"data-testid":q.actionHistory,children:h(hr,{})}):null,k.length>0?h(Bi,{items:k,triggerLabel:_.moreActions}):null,A?h(`button`,{type:`button`,class:`${Vi}-icon-btn`,onClick:a,"aria-label":_.close,title:_.close,"data-testid":q.actionClose,children:h(Yn,{})}):null]})}const qi=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Ji=/^https?:\/\/[^\s.]+\.[^\s]+$/i,Yi=/^[+]?[\d\s().-]{6,}$/;function Xi(e,t){return e.replace(/\{(\w+)\}/g,(e,n)=>String(t[n]??`{${n}}`))}function Zi(e){return Array.isArray(e)?e.length:e&&e.trim()?1:0}function Qi(e,t,n){let r=e.required??!0,i=e.validation;if(e.type===`multiselect`){let e=Zi(t);return r&&e===0?n.formRequired:e===0?void 0:i?.minSelections!=null&&e<i.minSelections?Xi(n.formChooseAtLeast,{min:i.minSelections}):i?.maxSelections!=null&&e>i.maxSelections?Xi(n.formChooseAtMost,{max:i.maxSelections}):void 0}let a=typeof t==`string`?t.trim():``;if(!a)return r?n.formRequired:void 0;switch(e.type){case`email`:if(!qi.test(a))return n.formInvalidEmail;break;case`url`:if(!Ji.test(a))return n.formInvalidUrl;break;case`tel`:if(!Yi.test(a))return n.formInvalidTel;break;case`number`:{let e=Number(a);if(!Number.isFinite(e))return n.formInvalidNumber;if(i?.min!=null&&e<i.min)return Xi(n.formNumberTooSmall,{min:i.min});if(i?.max!=null&&e>i.max)return Xi(n.formNumberTooLarge,{max:i.max});break}default:break}if(i?.minLength!=null&&a.length<i.minLength)return Xi(n.formTooShort,{min:i.minLength});if(i?.maxLength!=null&&a.length>i.maxLength)return Xi(n.formTooLong,{max:i.maxLength});if(i?.pattern)try{if(!new RegExp(i.pattern).test(a))return n.formPatternMismatch}catch{}}function $i(e,t,n){let r={};for(let i of e){let e=Qi(i,t[i.name],n);e&&(r[i.name]=e)}return r}function ea(e){let t={};for(let[n,r]of Object.entries(e)){let e=Array.isArray(r)?r.join(`, `):r;e&&e.trim()&&(t[n]=e.trim())}return t}const J=v.cssPrefix,ta=`__other__`;function na({fields:e,strings:t,submitLabel:n,onSubmit:r,skipLabel:i,onSkip:a,footerHint:o,submitOnEnter:s,disabled:l,initialValues:u,hideActions:d,fieldTypeLabels:f,rootTestId:p,submitTestId:m,skipTestId:_}){let[v,y]=c(()=>({...oa(e),...u})),[b,x]=c({}),[S,C]=c({}),w=e=>{S[e]&&C(t=>({...t,[e]:``}))},T=(e,t)=>{y(n=>({...n,[e]:t})),w(e)},E=(e,t)=>{x(n=>({...n,[e]:t})),w(e)},D=n=>{if(n.preventDefault(),l)return;let i=sa(e,v,b),a=$i(e,i,t);if(Object.keys(a).length>0){C(a);return}r(ea(i))};return g(`form`,{class:`${J}-form`,onSubmit:D,onKeyDown:e=>{!s||e.key!==`Enter`||e.shiftKey||e.isComposing||e.target?.tagName===`TEXTAREA`&&D(e)},"data-testid":p,noValidate:!0,children:[e.map(e=>h(ra,{field:e,value:v[e.name],otherText:b[e.name]??``,error:S[e.name],disabled:l,typeLabel:f?.[e.name],strings:t,onChange:t=>T(e.name,t),onOtherChange:t=>E(e.name,t)},e.name)),d?null:g(`div`,{class:`${J}-form-actions`,children:[o?h(`span`,{class:`${J}-form-hint`,children:o}):null,i&&a?h(`button`,{type:`button`,class:`${J}-form-skip`,onClick:a,disabled:l,"data-testid":_,children:i}):null,h(`button`,{type:`submit`,class:`${J}-form-submit`,disabled:l,"data-testid":m,children:n})]})]})}function ra({field:e,value:t,otherText:n,error:r,disabled:i,typeLabel:a,strings:o,onChange:s,onOtherChange:c}){let l=ia({field:e,value:t,otherText:n,disabled:i,strings:o,onChange:s,onOtherChange:c,fieldTid:Jr(q.formField,e.name)});return g(`label`,{class:`${J}-field`,"data-field":e.name,"data-invalid":r?`true`:void 0,children:[g(`span`,{class:`${J}-field-head`,children:[g(`span`,{class:`${J}-field-label`,children:[e.label,e.required??!0?h(`span`,{class:`${J}-field-req`,"aria-hidden":`true`,children:` *`}):null]}),a?h(`span`,{class:`${J}-field-type`,children:a}):null]}),l,e.validationHint&&!r?h(`span`,{class:`${J}-field-hint`,children:e.validationHint}):null,r?h(`span`,{class:`${J}-field-error`,role:`alert`,children:r}):null]})}function ia(e){let{field:t,value:n,otherText:r,disabled:i,strings:a,onChange:o,onOtherChange:s,fieldTid:c}=e,l=typeof n==`string`?n:``;switch(t.type){case`textarea`:return h(`textarea`,{class:`${J}-field-input`,rows:3,value:l,placeholder:t.placeholder,disabled:i,onInput:e=>o(e.target.value),"data-testid":c});case`select`:return g(`select`,{class:`${J}-field-input`,value:l,disabled:i,onChange:e=>o(e.target.value),"data-testid":c,children:[h(`option`,{value:``,children:t.placeholder??`—`}),(t.options??[]).map(e=>h(`option`,{value:e.value,children:e.label??e.value},e.value))]});case`radio`:{let e=t.allowOther&&l===ta;return g(`div`,{class:`${J}-field-choices`,role:`radiogroup`,"data-testid":c,children:[(t.options??[]).map(e=>g(`label`,{class:`${J}-choice`,children:[h(`input`,{type:`radio`,name:`${J}-${t.name}`,checked:l===e.value,disabled:i,onChange:()=>o(e.value)}),h(`span`,{children:e.label??e.value})]},e.value)),t.allowOther?g(`label`,{class:`${J}-choice`,children:[h(`input`,{type:`radio`,name:`${J}-${t.name}`,checked:l===ta,disabled:i,onChange:()=>o(ta)}),h(`span`,{children:a.formOther})]}):null,e?h(`input`,{class:`${J}-field-input`,value:r,placeholder:t.placeholder??a.formOtherPlaceholder,disabled:i,onInput:e=>s(e.target.value)}):null]})}case`checkbox`:return g(`label`,{class:`${J}-choice`,children:[h(`input`,{type:`checkbox`,checked:l===`true`,disabled:i,onChange:e=>o(e.target.checked?`true`:``),"data-testid":c}),h(`span`,{children:t.placeholder??t.label})]});case`multiselect`:{let e=Array.isArray(n)?n:[],l=(t,n)=>o(n?[...e,t]:e.filter(e=>e!==t));return g(`div`,{class:`${J}-field-choices`,"data-testid":c,children:[(t.options??[]).map(t=>g(`label`,{class:`${J}-choice`,children:[h(`input`,{type:`checkbox`,checked:e.includes(t.value),disabled:i,onChange:e=>l(t.value,e.target.checked)}),h(`span`,{children:t.label??t.value})]},t.value)),t.allowOther||(t.options??[]).length===0?h(`textarea`,{class:`${J}-field-input`,rows:2,value:r,placeholder:t.placeholder??a.formOtherPlaceholder,disabled:i,onInput:e=>s(e.target.value)}):null]})}default:return h(`input`,{class:`${J}-field-input`,type:aa(t.type),value:l,placeholder:t.placeholder,disabled:i,onInput:e=>o(e.target.value),"data-testid":c})}}function aa(e){switch(e){case`number`:case`email`:case`tel`:case`url`:case`date`:case`time`:return e;default:return`text`}}function oa(e){let t={};for(let n of e)n.defaultValue!=null&&(t[n.name]=n.type===`multiselect`?n.defaultValue.split(`,`).map(e=>e.trim()).filter(Boolean):n.defaultValue);return t}function sa(e,t,n){let r={...t};for(let i of e){let e=n[i.name]?.trim();if(i.type===`radio`&&i.allowOther&&t[i.name]===ta)r[i.name]=e??``;else if(i.type===`multiselect`&&e){let n=e.split(/[,\n;]+/).map(e=>e.trim()).filter(Boolean),a=Array.isArray(t[i.name])?t[i.name]:[];r[i.name]=[...a,...n]}}return r}const ca=v.cssPrefix;function la({form:e,strings:t,onSubmit:n,onSkip:r}){return g(`div`,{class:`${ca}-form-gate`,"data-testid":q.formGate,children:[e.title?h(`h3`,{class:`${ca}-form-gate-title`,children:e.title}):null,e.description?h(`p`,{class:`${ca}-form-gate-desc`,children:e.description}):null,h(na,{fields:e.fields,strings:t,submitLabel:e.submitLabel??t.formSubmit,onSubmit:n,skipLabel:e.skippable?t.formSkip:void 0,onSkip:e.skippable?r:void 0,submitTestId:q.formSubmit,skipTestId:q.formSkip})]})}function ua({marker:e,strings:t,onFill:n}){let r=e.outcome===`skipped`,i=r?t.formSkipped:t.formSubmitted,a=e.title?g(m,{children:[h(`span`,{children:e.title}),h(`span`,{class:`${ca}-sr-only`,children:i})]}):h(`span`,{children:i}),o=e.form?.reviewable??!1,s=!r&&o&&e.values&&Object.keys(e.values).length>0?e.values:null;if(s){let t=t=>e.form?.fields.find(e=>e.name===t)?.label??t;return g(`details`,{class:`${ca}-form-done`,"data-outcome":e.outcome,"data-testid":q.formDone,children:[g(`summary`,{class:`${ca}-form-done-summary`,"data-testid":q.formDoneToggle,children:[h(mr,{}),a,h(er,{})]}),h(`dl`,{class:`${ca}-form-answers`,"data-testid":q.formAnswers,children:Object.entries(s).map(([e,n])=>g(`div`,{class:`${ca}-form-answer`,children:[h(`dt`,{children:t(e)}),h(`dd`,{children:n})]},e))})]})}return g(`div`,{class:`${ca}-form-done`,"data-outcome":e.outcome,"data-testid":q.formDone,role:`status`,children:[h(r?pr:mr,{}),a,r&&e.form?.reopenable&&n?h(`button`,{type:`button`,class:`${ca}-form-done-fill`,"data-testid":q.formFill,onClick:n,children:t.formFillOut}):null]})}function da(e){if(!e)return!1;let t=e.startsWith(`tool:`)?e.slice(5):e;return t===`ask-user-questions`||t===`ask_user_questions`}function fa({textSig:e,doneSig:t}){let n=s(null);return a(()=>{let r=n.current;if(!r)return;r.classList.add(`${v.cssPrefix}-md`);let i=_.default_renderer(r),a=_.parser(i),o=0,s=u(()=>{let n=e.value,s=t.value;n.length<o&&(r.replaceChildren(),i=_.default_renderer(r),a=_.parser(i),o=0);let c=n.slice(o);c&&_.parser_write(a,c),o=n.length,s&&_.parser_end(a)}),c=new MutationObserver(e=>{for(let t of e)for(let e of t.addedNodes){if(!(e instanceof HTMLElement))continue;let t=e.matches?.(`a`)?[e]:[...e.querySelectorAll?.(`a`)??[]];for(let e of t)ma(e)}});c.observe(r,{childList:!0,subtree:!0});for(let e of r.querySelectorAll(`a`))ma(e);let l=e=>{let t=e.target?.closest?.(`a`);if(!t||!(t instanceof HTMLAnchorElement))return;let n=t.getAttribute(`href`)??``;!n||n.startsWith(`#`)||(e.preventDefault(),window.open(n,`_blank`,`noopener,noreferrer`))};return r.addEventListener(`click`,l),()=>{s(),c.disconnect(),r.removeEventListener(`click`,l)}},[e,t]),h(`div`,{ref:n})}function pa({text:e}){return h(fa,{textSig:o(()=>d(e),[e]),doneSig:o(()=>d(!0),[])})}function ma(e){let t=e.getAttribute(`href`)??``;if(!t||t.startsWith(`#`))return;e.target!==`_blank`&&(e.target=`_blank`);let n=new Set((e.rel||``).split(/\s+/).filter(Boolean));n.add(`noopener`),n.add(`noreferrer`),e.rel=[...n].join(` `)}const ha=v.cssPrefix;function ga({messageId:e,initial:t,strings:n,onFeedback:r}){let[i,a]=c(t),o=t=>{let n=i===t?null:t;a(n),r(e,n)};return g(`div`,{class:`${ha}-feedback`,role:`group`,"data-testid":q.messageFeedback,children:[h(`button`,{type:`button`,class:`${ha}-msg-action`,"data-active":i===`up`?`true`:void 0,"aria-pressed":i===`up`,"aria-label":n.feedbackUp,title:n.feedbackUp,onClick:()=>o(`up`),"data-testid":q.feedbackUp,children:h(Vr,{})}),h(`button`,{type:`button`,class:`${ha}-msg-action`,"data-active":i===`down`?`true`:void 0,"aria-pressed":i===`down`,"aria-label":n.feedbackDown,title:n.feedbackDown,onClick:()=>o(`down`),"data-testid":q.feedbackDown,children:h(Hr,{})}),h(`span`,{class:`${ha}-sr-only`,role:`status`,"aria-live":`polite`,children:i?n.feedbackThanks:``})]})}const _a=v.cssPrefix;function va({part:e,strings:t}){let n=e.title||e.filename||e.url||t.sources;return e.url?g(`a`,{class:`${_a}-source`,href:e.url,target:`_blank`,rel:`noreferrer noopener`,"data-testid":q.source,children:[h(`span`,{class:`${_a}-source-icon`,"aria-hidden":`true`,children:`🔗`}),h(`span`,{class:`${_a}-source-label`,children:n})]}):g(`span`,{class:`${_a}-source`,"data-testid":q.source,children:[h(`span`,{class:`${_a}-source-icon`,"aria-hidden":`true`,children:`📄`}),h(`span`,{class:`${_a}-source-label`,children:n})]})}const ya=v.cssPrefix;function ba(e){return e.startsWith(`tool:`)||e.startsWith(`tool-`)?e.slice(5):e}function xa(e,t){let n=e===`output-available`||e===`output-error`||e===`output-denied`,r=e===`approval-responded`||t?.approved!==void 0;return{terminal:n,responded:r,decided:n||r}}function Sa({status:e,icon:t,label:n}){return g(`span`,{class:`${ya}-toolui-badge ${ya}-toolui-status`,"data-status":e,children:[h(`span`,{class:`${ya}-toolui-status-icon`,children:t}),n]})}function Ca(e,t){return e===`output-error`?`error`:e===`output-denied`||t?.approved===!1?`denied`:e===`output-available`?`completed`:e===`approval-responded`||t?.approved===!0?`responded`:e===`approval-requested`?`awaiting`:`running`}function wa({status:e}){return h(e===`denied`||e===`error`||e===`superseded`?Kr:e===`completed`||e===`responded`?Gr:Wr,{})}function Ta(e,t){switch(e){case`awaiting`:return t.statusAwaiting;case`responded`:return t.statusResponded;case`completed`:return t.statusCompleted;case`denied`:return t.statusDenied;case`error`:return t.statusError;case`superseded`:return t.statusSuperseded;default:return t.statusRunning}}function Ea({state:e,approval:t,strings:n,superseded:r}){let i=Ca(e,t),a=r&&(i===`awaiting`||i===`running`)?`superseded`:i;return h(Sa,{status:a,icon:h(wa,{status:a}),label:Ta(a,n)})}function Da({name:e,state:t,approval:n,strings:r,superseded:i}){return g(m,{children:[g(`span`,{class:`${ya}-toolui-name-pill`,children:[h(Ur,{}),h(`span`,{class:`${ya}-toolui-name-text`,children:e})]}),h(Ea,{state:t,approval:n,strings:r,superseded:i}),h(`span`,{class:`${ya}-toolui-chevron`,children:h(yr,{})})]})}function Oa({part:e,strings:t,testid:n,superseded:r}){let i=f(()=>e.inputSig.value),a=f(()=>e.outputSig.value),o=f(()=>e.errorSig.value),s=f(()=>e.stateSig.value),c=f(()=>e.approvalSig.value);return g(`details`,{class:`${ya}-toolui ${ya}-toolui-collapsible`,"data-testid":n,children:[h(`summary`,{class:`${ya}-toolui-head`,children:h(Da,{name:ba(e.toolName),state:s.value,approval:c.value,strings:t,superseded:r})}),h(ka,{label:t.toolParameters,value:i.value}),a.value===void 0?null:h(ka,{label:t.toolResult,value:a.value}),o.value?h(ka,{label:t.statusError,value:o.value,error:!0}):null]})}function ka({label:e,value:t,error:n}){let r=n?String(t??``):ja(Aa(t));return r?g(`div`,{class:`${ya}-toolui-section`,children:[h(`span`,{class:`${ya}-toolui-label`,children:e}),h(`pre`,{class:`${ya}-toolui-code`,"data-error":n?`true`:void 0,children:r})]}):null}function Aa(e){if(e&&typeof e==`object`){let t=e;if(t.storage===`tool-result-ref`&&`summary`in t)return t.summary}return e}function ja(e){if(e==null)return``;try{let t=typeof e==`string`?e:JSON.stringify(e,null,2);return!t||t===`{}`||t===`[]`||t===`""`?``:t.length>800?`${t.slice(0,800)}…`:t}catch{return``}}const Ma=v.cssPrefix;function Na({part:e,strings:t,active:n,superseded:r=!1,onDecision:i,onEdit:a}){let o=f(()=>e.approvalSig.value),s=f(()=>e.stateSig.value),c=ba(e.toolName),l=o.value?.approved,{terminal:u,responded:d,decided:p}=xa(s.value,o.value),_=d&&n&&!u,v=r&&!p,y=e.toolCallId;return g(`div`,{class:`${Ma}-toolui-group`,"data-testid":p?q.toolDecision:q.toolApproval,children:[h(Oa,{part:e,strings:t,superseded:v}),v||u?null:g(`div`,{class:`${Ma}-toolui ${Ma}-toolui-body`,children:[d?g(m,{children:[g(`p`,{class:`${Ma}-toolui-prompt`,children:[t.approvalYourResponse.replace(`{decision}`,l?t.approve:t.reject),o.value?.reason?` — ${o.value.reason}`:``]}),_?h(`p`,{class:`${Ma}-toolui-subtle`,children:t.approvalEditHint}):null,!_&&!u?h(`p`,{class:`${Ma}-toolui-subtle`,children:t.approvalSubmitting}):null]}):g(m,{children:[h(`p`,{class:`${Ma}-toolui-prompt`,children:t.approvalPrompt.replace(`{tool}`,c)}),h(`p`,{class:`${Ma}-toolui-subtle`,children:t.approvalBody})]}),!p&&!r?g(`div`,{class:`${Ma}-toolui-actions`,children:[h(`button`,{type:`button`,class:`${Ma}-form-skip`,onClick:()=>i(y,!1),"data-testid":q.toolReject,children:t.reject}),h(`button`,{type:`button`,class:`${Ma}-form-submit`,onClick:()=>i(y,!0),"data-testid":q.toolApprove,children:t.approve})]}):null,_?h(`div`,{class:`${Ma}-toolui-actions`,children:h(`button`,{type:`button`,class:`${Ma}-form-skip`,onClick:()=>a(y),"data-testid":q.toolEdit,children:t.edit})}):null]})]})}const Pa=new Set([`text`,`email`,`phone`,`number`,`date`,`single-select`,`multi-select`,`boolean`]);function Fa(e){let t=e&&typeof e==`object`?e:{},n=(Array.isArray(t.questions)?t.questions:[]).map(Ia).filter(e=>e!==null);return{intro:za(t.intro),questions:n}}function Ia(e,t){if(!e||typeof e!=`object`)return null;let n=e,r=Pa.has(n.type)?n.type:`text`;return{key:za(n.key)??`q${t+1}`,question:za(n.question)??`Please provide the missing information.`,type:r,options:Array.isArray(n.options)?n.options.filter(e=>typeof e==`string`&&e.trim().length>0):void 0,required:typeof n.required==`boolean`?n.required:void 0,helpText:za(n.helpText)}}function La(e){switch(e){case`text`:return`textarea`;case`phone`:return`tel`;case`single-select`:case`boolean`:return`radio`;case`multi-select`:return`multiselect`;default:return e}}function Ra(e,t,n){return e.questions.map(e=>{let r=La(e.type),i=e.type===`boolean`?[{value:`yes`,label:t},{value:`no`,label:n}]:(e.options??[]).map(e=>({value:e,label:e}));return{name:e.key,label:e.question,type:r,required:e.required??!1,options:i.length>0?i:void 0,validationHint:e.helpText}})}function za(e){return typeof e==`string`&&e.trim()?e.trim():void 0}const Y=v.cssPrefix,Ba={text:`qtypeText`,email:`qtypeEmail`,phone:`qtypePhone`,number:`qtypeNumber`,date:`qtypeDate`,"single-select":`qtypeChooseOne`,"multi-select":`qtypeChooseAny`,boolean:`qtypeBoolean`};function Va(e,t){let n={};for(let r of e)n[r.key]=t[Ba[r.type]];return n}function Ha({part:e,strings:t,active:n,superseded:r=!1,onDecision:i,onEdit:a}){let o=f(()=>e.stateSig.value).value,s=f(()=>e.approvalSig.value).value,l=f(()=>Fa(e.inputSig.value)).value,{terminal:u,decided:d}=xa(o,s),p=d&&s?.approved===!0,m=!d&&!r,_=!m&&!p,v=p&&n&&!u,y=l.questions,[b,x]=c(null),S=b??(m||p),[C,w]=c(!1),T=y.length>1?Jn:Cr,E=m?t.inputRequired:t.inputBadge,D=m?h(Ua,{req:l,strings:t,resolve:(t,n)=>i(e.toolCallId,n,t)}):C?h(na,{fields:Ra(l,t.confirmYes,t.confirmNo),strings:t,submitLabel:t.inputSubmit,onSubmit:()=>{},disabled:!0,hideActions:!0,fieldTypeLabels:Va(y,t),initialValues:p?Ya(y,s?.reason):void 0}):h(Wa,{questions:y,answers:p?Ja(s?.reason):{},strings:t});return g(`details`,{class:`${Y}-toolui ${Y}-toolui-collapsible${r?` ${Y}-toolui-stale`:``}`,open:S,onToggle:e=>{let t=e.currentTarget.open;t!==S&&x(t)},"data-testid":m?q.toolAskQuestions:q.toolDecision,children:[g(`summary`,{class:`${Y}-toolui-head`,children:[g(`span`,{class:`${Y}-toolui-q-pill`,children:[h(T,{}),E]}),g(`span`,{class:`${Y}-toolui-head-end`,children:[m?null:h(Sa,{status:_?`superseded`:`completed`,icon:h(_?Kr:Gr,{}),label:_?t.inputSkipped:t.inputAnswered}),h(`span`,{class:`${Y}-toolui-chevron`,children:h(yr,{})})]})]}),g(`div`,{class:`${Y}-toolui-collapse-body`,children:[l.intro?h(`div`,{class:`${Y}-toolui-desc`,children:l.intro}):null,D,m?null:g(`div`,{class:`${Y}-toolui-footer`,children:[g(`button`,{type:`button`,class:`${Y}-toolui-options-toggle`,onClick:()=>w(e=>!e),"data-testid":q.toolAskOptions,children:[h(`span`,{class:`${Y}-toolui-options-chevron${C?` ${Y}-open`:``}`,children:h(yr,{})}),C?t.hideOptions:t.showOptions]}),v?h(`button`,{type:`button`,class:`${Y}-form-skip`,onClick:()=>a(e.toolCallId),"data-testid":q.toolEdit,children:t.edit}):null]})]})]})}function Ua({req:e,strings:t,resolve:n}){let r=Ra(e,t.confirmYes,t.confirmNo),i=e.questions.length===1&&e.questions[0]?.type===`text`;return h(na,{fields:r,strings:t,submitLabel:t.inputSubmit,footerHint:i?t.inputSubmitHint:void 0,onSubmit:t=>n(Ka(e.questions,t),!0),skipLabel:t.inputSkip,onSkip:()=>n(void 0,!1),submitOnEnter:i,fieldTypeLabels:Va(e.questions,t),submitTestId:q.toolInputSubmit,skipTestId:q.toolInputSkip})}function Wa({questions:e,answers:t,strings:n}){return h(`div`,{class:`${Y}-toolui-summary`,"data-testid":q.toolAskSummary,children:e.map(e=>g(`div`,{class:`${Y}-field`,children:[h(`span`,{class:`${Y}-field-head`,children:g(`span`,{class:`${Y}-field-label`,children:[e.question,e.required?h(`span`,{class:`${Y}-field-req`,"aria-hidden":`true`,children:` *`}):null]})}),h(`p`,{class:`${Y}-toolui-answer`,children:Ga(e,t[e.key],n)||`—`})]},e.key))})}function Ga(e,t,n){return e.type===`boolean`?t===`yes`?n.confirmYes:t===`no`?n.confirmNo:t??``:t??``}function Ka(e,t){let n=e.flatMap(e=>{let n=t[e.key];if(n==null||n.trim()===``)return[];let r=e.type===`multi-select`?n.split(`,`).map(e=>e.trim()).filter(Boolean):n;return[{key:e.key,value:r}]});return JSON.stringify({answers:n})}function qa(e){if(!e)return{};let t=(()=>{try{return JSON.parse(e)}catch{return}})()?.answers;if(!Array.isArray(t))return{};let n={};for(let e of t)if(e&&typeof e==`object`&&`key`in e){let{key:t,value:r}=e;if(typeof t!=`string`)continue;typeof r==`string`?n[t]=r:Array.isArray(r)&&(n[t]=r.filter(e=>typeof e==`string`))}return n}function Ja(e){let t=qa(e),n={};for(let[e,r]of Object.entries(t))n[e]=Array.isArray(r)?r.join(`, `):r;return n}function Ya(e,t){let n=qa(t),r={};for(let t of e){let e=n[t.key];e!==void 0&&(t.type===`multi-select`?r[t.key]=Array.isArray(e)?e:[e]:r[t.key]=Array.isArray(e)?e[0]??``:e)}return r}function Xa({part:e,strings:t}){let n=f(()=>e.inputSig.value),r=f(()=>e.outputSig.value),i=f(()=>e.errorSig.value);return f(()=>!!ja(n.value)||!!i.value||!!ja(Aa(r.value))).value?h(Oa,{part:e,strings:t,testid:q.toolCall}):null}const X=v.cssPrefix;function Za({message:e,strings:t,responseMode:n,showReasoning:r,showToolCalls:i,showSources:a,interactive:o=!1,superseded:s=!1,tool:c,onRetry:l,enableMessageFeedback:u=!1,onFeedback:d,controlMode:p}){let m=f(()=>e.partsSig.value).value,_=f(()=>Cn(e)),v=f(()=>wn(e)),y=f(()=>e.partsSig.value.some(e=>e.kind===`text`&&e.textSig.value.length>0)),b=f(()=>r&&e.partsSig.value.some(e=>e.kind===`reasoning`)),x=f(()=>{let t=e.partsSig.value,n=-1;for(let e=0;e<t.length;e++){let r=t[e]?.kind;(r===`text`||r===`file`||r===`source`)&&(n=e)}return n}),S=p===`awaiting_operator`||p===`operator`,C=e.role===`assistant`&&e.status===`streaming`&&!S,w=n===`buffered`&&C,T=C&&!y.value,E=C&&!w&&!(b.value&&T);if(v.value)return null;let D=$a(e.createdAt),O=e.role===`assistant`||e.role===`operator`,k=u&&!!d&&!!e.serverMessageId&&O&&!C&&e.status!==`error`&&!_.value,A=m.filter(e=>e.kind===`text`).map(e=>e.textSig.value).join(`
|