@syntrologie/adapt-chatbot 2.8.0-canary.333 → 2.8.0-canary.335
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/dist/AdaptiveChatBar.d.ts +0 -3
- package/dist/AdaptiveChatBar.d.ts.map +1 -1
- package/dist/AdaptiveChatBar.js +1 -1
- package/dist/ChatSession.d.ts +7 -0
- package/dist/ChatSession.d.ts.map +1 -1
- package/dist/ChatTransport.d.ts.map +1 -1
- package/dist/{chunk-AIPLC647.js → chunk-QC5THSKS.js} +1 -27
- package/dist/chunk-QC5THSKS.js.map +7 -0
- package/dist/runtime.js +28 -2
- package/dist/runtime.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunk-AIPLC647.js.map +0 -7
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
* - `chat-message-sent` ({ text }): the user submitted text via Enter
|
|
8
8
|
* or the send button. The owning code is responsible for pushing
|
|
9
9
|
* this into the conversation history and producing a reply.
|
|
10
|
-
* - `canvas-close`: the user clicked the close ✕ button. Propagated
|
|
11
|
-
* to the canvas overlay so the underlying drawer is dismissed.
|
|
12
10
|
*
|
|
13
11
|
* Wiring contract (props in):
|
|
14
12
|
* - `messages`: the conversation trail, passed straight through to
|
|
@@ -98,7 +96,6 @@ export declare class AdaptiveChatBar extends LitElement {
|
|
|
98
96
|
private _onInput;
|
|
99
97
|
private _onKeyDown;
|
|
100
98
|
private _onSendOrInterrupt;
|
|
101
|
-
private _onClose;
|
|
102
99
|
private _send;
|
|
103
100
|
/**
|
|
104
101
|
* Visitor tapped the intro suggestion button in the empty-state
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdaptiveChatBar.d.ts","sourceRoot":"","sources":["../src/AdaptiveChatBar.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"AdaptiveChatBar.d.ts","sourceRoot":"","sources":["../src/AdaptiveChatBar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAGhD,OAAO,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,OAAgB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;MASxB;IAEF,QAAQ,EAAE,YAAY,EAAE,CAAM;IAE9B;;;;;;;OAOG;IACH,YAAY,SAAM;IAClB;;;;;OAKG;IACH,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAa;IAE3E;;;uDAGmD;IACnD,aAAa,UAAS;IACtB,WAAW,SAAuB;IAClC;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAa;IACzC;;;;;;OAMG;IACH,QAAQ,UAAS;IACjB,MAAM,SAAM;IAEH,gBAAgB,IAAI,WAAW;IAUxC,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,UAAU,CAShB;IAKF,OAAO,CAAC,kBAAkB,CAMxB;IAEF,OAAO,CAAC,KAAK;IAoBb;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB,CAYxB;IAEO,MAAM;CAsChB;AA6OD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
|
package/dist/AdaptiveChatBar.js
CHANGED
package/dist/ChatSession.d.ts
CHANGED
|
@@ -88,6 +88,13 @@ export declare class ChatSession {
|
|
|
88
88
|
* silent loading dots between turns.
|
|
89
89
|
*/
|
|
90
90
|
appendThinkingDelta(delta: string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Replace the active thinking narration outright (vs. appendThinkingDelta's
|
|
93
|
+
* streaming accumulation). Used to surface tool-call progress — e.g.
|
|
94
|
+
* "Searching…" while the agent works a tool — so a long tool phase shows
|
|
95
|
+
* what's happening instead of silent dots. No-op if unchanged.
|
|
96
|
+
*/
|
|
97
|
+
setThinkingText(text: string): void;
|
|
91
98
|
/**
|
|
92
99
|
* End the active thinking turn — drop any narration so the trail
|
|
93
100
|
* stops showing it. Fires on real text-message-start and on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatSession.d.ts","sourceRoot":"","sources":["../src/ChatSession.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatSession.d.ts","sourceRoot":"","sources":["../src/ChatSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatTransport.d.ts","sourceRoot":"","sources":["../src/ChatTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;IACvF;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IAC3D;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IAC7C,QAAQ,EAAE,qBAAqB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatTransport.d.ts","sourceRoot":"","sources":["../src/ChatTransport.ts"],"names":[],"mappings":"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"}
|
|
@@ -69,9 +69,6 @@ var AdaptiveChatBar = class extends LitElement {
|
|
|
69
69
|
}
|
|
70
70
|
this._send();
|
|
71
71
|
};
|
|
72
|
-
this._onClose = () => {
|
|
73
|
-
this.dispatchEvent(new CustomEvent("canvas-close", { bubbles: true, composed: true }));
|
|
74
|
-
};
|
|
75
72
|
/**
|
|
76
73
|
* Visitor tapped the intro suggestion button in the empty-state
|
|
77
74
|
* trail. Submit the configured prompt through the same channel as
|
|
@@ -145,13 +142,6 @@ var AdaptiveChatBar = class extends LitElement {
|
|
|
145
142
|
title=${this.inFlight ? "Interrupt" : "Send"}
|
|
146
143
|
style=${styleMap(sendStyles(this.inFlight))}
|
|
147
144
|
>${this.inFlight ? "\u25A0" : "\u2191"}</button>
|
|
148
|
-
<button
|
|
149
|
-
type="button"
|
|
150
|
-
data-chat-close
|
|
151
|
-
@click=${this._onClose}
|
|
152
|
-
aria-label="Hide chat"
|
|
153
|
-
style=${styleMap(closeStyles())}
|
|
154
|
-
>✕</button>
|
|
155
145
|
</div>
|
|
156
146
|
</div>
|
|
157
147
|
`;
|
|
@@ -290,22 +280,6 @@ function sendStyles(inFlight) {
|
|
|
290
280
|
transition: "background 150ms ease, color 150ms ease, border-color 150ms ease"
|
|
291
281
|
};
|
|
292
282
|
}
|
|
293
|
-
function closeStyles() {
|
|
294
|
-
return {
|
|
295
|
-
width: "28px",
|
|
296
|
-
height: "28px",
|
|
297
|
-
display: "inline-flex",
|
|
298
|
-
alignItems: "center",
|
|
299
|
-
justifyContent: "center",
|
|
300
|
-
borderRadius: "9999px",
|
|
301
|
-
background: "transparent",
|
|
302
|
-
color: "inherit",
|
|
303
|
-
border: "var(--sc-content-bubble-border, 1px solid rgba(255, 255, 255, 0.18))",
|
|
304
|
-
cursor: "pointer",
|
|
305
|
-
flexShrink: "0",
|
|
306
|
-
opacity: "0.7"
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
283
|
function renderHeader() {
|
|
310
284
|
const headerStyles = {
|
|
311
285
|
display: "flex",
|
|
@@ -384,4 +358,4 @@ if (!customElements.get("adaptive-chat-bar")) {
|
|
|
384
358
|
export {
|
|
385
359
|
AdaptiveChatBar
|
|
386
360
|
};
|
|
387
|
-
//# sourceMappingURL=chunk-
|
|
361
|
+
//# sourceMappingURL=chunk-QC5THSKS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/AdaptiveChatBar.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * AdaptiveChatBar \u2014 the canvas lid composition for the chat-canvas\n * experience. Renders the bubble-up trail on top and an always-visible\n * input row below.\n *\n * Wiring contract (events out):\n * - `chat-message-sent` ({ text }): the user submitted text via Enter\n * or the send button. The owning code is responsible for pushing\n * this into the conversation history and producing a reply.\n *\n * Wiring contract (props in):\n * - `messages`: the conversation trail, passed straight through to\n * `<adaptive-chat-trail>`.\n * - `placeholder`: input placeholder copy. Defaults to a generic\n * \"Ask, find, or navigate\u2026\" \u2014 the host (typically the slot's lid\n * widget mount) can override to a context-specific string.\n *\n * Light DOM. Glassmorphism is applied at the input-row level so the\n * trail above floats over the host page without chrome. See PRD \u00A74.4.\n */\n\nimport { html, LitElement, nothing } from 'lit';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport './AdaptiveChatTrail.js';\nimport type { TrailMessage } from './AdaptiveChatTrail.js';\n\nconst DEFAULT_PLACEHOLDER = 'Ask, find, or navigate\u2026';\n\nexport class AdaptiveChatBar extends LitElement {\n static override properties = {\n messages: { attribute: false },\n placeholder: { type: String },\n greeting: { type: String },\n inFlight: { type: Boolean, reflect: true },\n thinkingText: { attribute: false },\n introSuggestion: { attribute: false },\n forceExpanded: { type: Boolean, reflect: true },\n _input: { state: true },\n };\n\n messages: TrailMessage[] = [];\n\n /**\n * Live reasoning narration from the model \u2014 streamed in via\n * AG-UI THINKING_TEXT_MESSAGE_CONTENT events and forwarded by\n * the ChatSession subscription on the host (mountable).\n * Forwarded verbatim to the trail, which renders it in place of\n * the silent loading dots between turns. Empty string when no\n * thinking turn is active.\n */\n thinkingText = '';\n /**\n * Pre-conversation suggestion button \u2014 forwarded to the trail's\n * empty-state pane. When the visitor clicks it the trail emits\n * `trail-intro-suggestion`; we catch that here and submit the\n * configured prompt through the normal send path.\n */\n introSuggestion: { label: string; prompt: string } | undefined = undefined;\n\n /** Pass-through to {@link AdaptiveChatTrail}'s ``forceExpanded`` prop.\n * Hosts that mount the chat-bar in a full-screen surface (mobile\n * panel, agent app, etc.) set this to skip the collapse affordance\n * \u2014 there is no smaller state to fall back to. */\n forceExpanded = false;\n placeholder = DEFAULT_PLACEHOLDER;\n /**\n * Initial assistant message shown before any real conversation\n * starts. Renders inside the trail as a phantom assistant chip\n * when messages.length === 0; auto-disappears as soon as the\n * first user message lands. Mirrors ChatAssistantLit's greeting.\n */\n greeting: string | undefined = undefined;\n /**\n * Whether a chat round-trip is in flight (request sent, awaiting\n * reply). The single send/stop button morphs accordingly: \u2191 when\n * ready, \u23F9 when in-flight. Parent owns this state \u2014 set true after\n * `chat-message-sent` fires, false when the reply lands or the\n * request is aborted. Enter is inert while in-flight.\n */\n inFlight = false;\n _input = '';\n\n override createRenderRoot(): HTMLElement {\n return this;\n }\n\n // Host-level styling (display, width, height, flex, etc.) is owned\n // by the container \u2014 SDK shadow root provides default rules, panel\n // overrides via design tokens (--sc-chat-bar-host-*). This adaptive\n // never sets inline styles on itself. See SmartCanvasElementLit's\n // static styles for the rule.\n\n private _onInput = (e: Event): void => {\n this._input = (e.target as HTMLInputElement).value;\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n // Enter is the send affordance \u2014 while in-flight there's nothing\n // to send, so it's a no-op. Interrupt requires the explicit\n // \u23F9 click to avoid surprise-aborting on a stray keystroke.\n if (this.inFlight) return;\n this._send();\n }\n };\n\n // Single button. Click delegates to send-or-interrupt based on\n // current state. Same DOM node, different behavior \u2014 discoverability\n // wins from the user not having to scan for which control is active.\n private _onSendOrInterrupt = (): void => {\n if (this.inFlight) {\n this.dispatchEvent(new CustomEvent('chat-interrupt', { bubbles: true, composed: true }));\n return;\n }\n this._send();\n };\n\n private _send(): void {\n const text = this._input.trim();\n if (!text) return;\n this.dispatchEvent(\n new CustomEvent<{ text: string }>('chat-message-sent', {\n detail: { text },\n bubbles: true,\n composed: true,\n })\n );\n this._input = '';\n // Drop the input value too \u2014 the input's bound value is `this._input`\n // via the render, but jsdom's two-way binding via property only takes\n // effect after the next render, so set it imperatively for the test\n // and for browser symmetry (most browsers do the right thing here\n // anyway because Lit re-renders on the state change).\n const input = this.querySelector<HTMLInputElement>('input[data-chat-input]');\n if (input) input.value = '';\n }\n\n /**\n * Visitor tapped the intro suggestion button in the empty-state\n * trail. Submit the configured prompt through the same channel as\n * a typed message so listeners (mountable \u2192 chatSession.send) see\n * a uniform shape \u2014 no need for a parallel \"suggestion-sent\" path.\n * The trail's intro pane auto-disappears the moment the first\n * message lands, so this also closes the empty state in one go.\n */\n private _onIntroSuggestion = (e: Event): void => {\n const detail = (e as CustomEvent<{ prompt: string }>).detail;\n if (!detail?.prompt) return;\n e.stopPropagation();\n if (this.inFlight) return;\n this.dispatchEvent(\n new CustomEvent<{ text: string }>('chat-message-sent', {\n detail: { text: detail.prompt },\n bubbles: true,\n composed: true,\n })\n );\n };\n\n override render() {\n return html`\n <div style=${styleMap(rootStyles(this.forceExpanded))}>\n ${this.forceExpanded ? renderHeader() : nothing}\n <adaptive-chat-trail\n .messages=${this.messages}\n .greeting=${this.greeting}\n .forceExpanded=${this.forceExpanded}\n .inFlight=${this.inFlight}\n .thinkingText=${this.thinkingText}\n .introSuggestion=${this.introSuggestion}\n @trail-intro-suggestion=${this._onIntroSuggestion}\n ></adaptive-chat-trail>\n <div style=${styleMap(rowStyles(this.forceExpanded))} data-chat-row>\n <span style=${styleMap(avatarStyles())} aria-hidden=\"true\">\u2726</span>\n <input\n data-chat-input\n type=\"text\"\n placeholder=${this.placeholder}\n .value=${this._input}\n @input=${this._onInput}\n @keydown=${this._onKeyDown}\n style=${styleMap(inputStyles())}\n aria-label=\"Chat input\"\n />\n <button\n type=\"button\"\n data-chat-send\n data-state=${this.inFlight ? 'in-flight' : 'ready'}\n @click=${this._onSendOrInterrupt}\n aria-label=${this.inFlight ? 'Stop' : 'Send message'}\n title=${this.inFlight ? 'Interrupt' : 'Send'}\n style=${styleMap(sendStyles(this.inFlight))}\n >${this.inFlight ? '\u25A0' : '\u2191'}</button>\n </div>\n </div>\n `;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Styles \u2014 kept inline (Lit styleMap) so they participate in light-DOM\n// rendering and pick up host CSS variables (e.g. --sc-tile-background).\n// ---------------------------------------------------------------------------\n\nfunction rootStyles(forceExpanded: boolean): Record<string, string> {\n // When the host expects the chat to fill its container (full-screen\n // panel, agent app), we grow vertically AND wrap the whole widget in\n // its own chrome card \u2014 trail + input read as one cohesive surface\n // instead of a naked trail above a chrome'd input. Floating mounts\n // (bottom-right pinned, etc.) stay chrome-less here because their\n // chrome is owned by the host's positioned wrapper.\n if (!forceExpanded) {\n return {\n display: 'flex',\n flexDirection: 'column',\n gap: '6px',\n width: '100%',\n pointerEvents: 'auto',\n };\n }\n // Input is ABSOLUTELY positioned at the bottom of this chrome card\n // (see rowStyles forceExpanded mode). That guarantees the input is\n // always visible \u2014 even when the lid region is tighter than the\n // chat-bar would naturally want. The flex column above holds\n // header + trail; padding-bottom reserves the input's footprint so\n // trail content can never overlap.\n //\n // Priority of \"what disappears when space is tight\":\n // Trail (shrinks to 0 first via flex: 1 1 0)\n // Header (can shrink via default flex: 0 1 auto)\n // Input (NEVER \u2014 it's positioned absolute, always at the bottom)\n return {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n flex: '1 1 auto',\n minHeight: '0',\n overflow: 'hidden',\n pointerEvents: 'auto',\n background: 'var(--sc-tile-background, rgba(255, 255, 255, 0.92))',\n border: 'var(--sc-tile-border, 1px solid rgba(0, 0, 0, 0.06))',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n boxShadow: 'var(--sc-tile-shadow, 0 12px 32px -16px rgba(0, 0, 0, 0.18))',\n // Reserves room for the absolute-positioned input pill (36px high\n // + 12px from bottom) plus a 16px visual gap above the input.\n padding: '0.75rem 0.75rem calc(36px + 1.75rem)',\n color: 'var(--sc-tile-title-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n // Override the trail's host-layout tokens so the trail (a flex item\n // of this column) shrinks to 0 first when space is tight \u2014 letting\n // the header and absolute-positioned input pill stay pinned. The\n // SDK-level rule in SmartCanvasElementLit consumes these tokens on\n // adaptive-chat-trail's host element. Containers OWN host styling\n // via tokens; the adaptive never sets inline styles on its host.\n ['--sc-chat-trail-host-display']: 'flex',\n ['--sc-chat-trail-host-flex-direction']: 'column',\n ['--sc-chat-trail-host-flex']: '1 1 0',\n ['--sc-chat-trail-host-min-height']: '0',\n ['--sc-chat-trail-host-overflow']: 'hidden',\n };\n}\n\nfunction rowStyles(forceExpanded: boolean): Record<string, string> {\n // forceExpanded \u2014 root container already carries the chrome; row\n // becomes a flat input-pill inside that chrome (subtle border + soft\n // background, no shadow/blur).\n if (forceExpanded) {\n // Absolute-pinned to the chrome card's bottom edge so it never\n // disappears under any container size. The chrome reserves\n // padding-bottom equal to this row's footprint so flex content\n // above (header + trail) can't overlap.\n return {\n position: 'absolute',\n left: '0.75rem',\n right: '0.75rem',\n bottom: '0.75rem',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 14px',\n borderRadius: '9999px',\n background: 'rgba(0, 0, 0, 0.04)',\n border: '1px solid rgba(0, 0, 0, 0.10)',\n color: 'var(--sc-content-text-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n minHeight: '36px',\n };\n }\n // Floating mount \u2014 keeps the original tile-chrome look.\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '10px 12px',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n background: 'var(--sc-tile-background, rgba(15, 19, 24, 0.6))',\n backdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n WebkitBackdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n border: 'var(--sc-tile-border, 1px solid rgba(255, 255, 255, 0.08))',\n boxShadow: 'var(--sc-tile-shadow, 0 2px 12px rgba(0, 0, 0, 0.3))',\n color: 'var(--sc-tile-title-color, #fafafa)',\n fontFamily: 'var(--sc-font-family, inherit)',\n };\n}\n\nfunction avatarStyles(): Record<string, string> {\n return {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n borderRadius: '9999px',\n background: 'hsl(var(--sc-accent-color) / 0.15)',\n border: '1px solid hsl(var(--sc-accent-color) / 0.30)',\n color: 'hsl(var(--sc-accent-color) / 0.95)',\n flexShrink: '0',\n fontSize: '11px',\n };\n}\n\nfunction inputStyles(): Record<string, string> {\n return {\n flex: '1',\n minWidth: '0',\n background: 'transparent',\n border: 'none',\n outline: 'none',\n color: 'inherit',\n fontSize: '13px',\n };\n}\n\nfunction sendStyles(inFlight: boolean): Record<string, string> {\n return {\n width: '28px',\n height: '28px',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '9999px',\n // Ready: filled accent (send is the affordance). In-flight: hollow\n // ring + accent ring (stop is a one-of-a-kind disruptive action,\n // styled differently so the user reads \"this isn't just send\").\n background: inFlight ? 'transparent' : 'hsl(var(--sc-accent-color) / 0.85)',\n color: inFlight ? 'hsl(var(--sc-accent-color) / 0.95)' : 'var(--sc-accent-foreground, #fff)',\n border: inFlight ? '1px solid hsl(var(--sc-accent-color) / 0.55)' : 'none',\n cursor: 'pointer',\n flexShrink: '0',\n transition: 'background 150ms ease, color 150ms ease, border-color 150ms ease',\n };\n}\n\nfunction renderHeader() {\n const headerStyles: Record<string, string> = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '4px 4px 12px',\n borderBottom: '1px solid var(--sc-content-divider-color, rgba(0, 0, 0, 0.08))',\n flex: '0 0 auto',\n };\n const avatar: Record<string, string> = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n borderRadius: '9999px',\n // Track the workspace brand primary so the avatar matches every\n // other green in the canvas (velvet's chip gradient, the status\n // dot below, the send button). Previously the avatar pinned a\n // hardcoded #5faf7d \u2192 #3d8a5e gradient via the\n // `--sc-tile-icon-background` fallback, so when a workspace\n // overrode --sc-color-primary, every other element shifted to\n // the brand but the avatar stayed the default green \u2014 visibly\n // out of place against the surrounding chrome. Fallback colors\n // unchanged so velvet's default look is identical when no\n // workspace primary is set.\n background:\n 'var(--sc-tile-icon-background, linear-gradient(135deg, var(--sc-color-primary, #5faf7d) 0%, var(--sc-color-primary-hover, #3d8a5e) 100%))',\n color: '#fff',\n flexShrink: '0',\n fontSize: '14px',\n };\n const nameWrap: Record<string, string> = {\n display: 'flex',\n flexDirection: 'column',\n minWidth: '0',\n flex: '1 1 auto',\n };\n const name: Record<string, string> = {\n fontSize: '0.85rem',\n fontWeight: '600',\n color: 'var(--sc-content-text-color, inherit)',\n lineHeight: '1.2',\n };\n const status: Record<string, string> = {\n fontSize: '0.7rem',\n color: 'var(--sc-tile-title-color, #3d8275)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n lineHeight: '1.2',\n };\n const statusDot: Record<string, string> = {\n width: '6px',\n height: '6px',\n borderRadius: '9999px',\n background: 'var(--sc-tile-title-color, #3d8275)',\n display: 'inline-block',\n };\n return html`\n <div style=${styleMap(headerStyles)} data-chat-header>\n <span style=${styleMap(avatar)} aria-hidden=\"true\">\u2726</span>\n <div style=${styleMap(nameWrap)}>\n <span style=${styleMap(name)}>Assistant</span>\n <span style=${styleMap(status)}>\n <span style=${styleMap(statusDot)}></span>\n Online \u00B7 understands your session\n </span>\n </div>\n </div>\n `;\n}\n\nif (!customElements.get('adaptive-chat-bar')) {\n customElements.define('adaptive-chat-bar', AdaptiveChatBar);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'adaptive-chat-bar': AdaptiveChatBar;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/runtime.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
fetchMountedElements,
|
|
11
11
|
renderFallbackHtml
|
|
12
12
|
} from "./chunk-FHWJR5BX.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-QC5THSKS.js";
|
|
14
14
|
import "./chunk-JTZ36YJM.js";
|
|
15
15
|
import "./chunk-ONGGPQER.js";
|
|
16
16
|
import "./chunk-FVNSOP7B.js";
|
|
@@ -72,6 +72,17 @@ var ChatSession = class {
|
|
|
72
72
|
this._thinkingText += delta;
|
|
73
73
|
this.notify();
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Replace the active thinking narration outright (vs. appendThinkingDelta's
|
|
77
|
+
* streaming accumulation). Used to surface tool-call progress — e.g.
|
|
78
|
+
* "Searching…" while the agent works a tool — so a long tool phase shows
|
|
79
|
+
* what's happening instead of silent dots. No-op if unchanged.
|
|
80
|
+
*/
|
|
81
|
+
setThinkingText(text) {
|
|
82
|
+
if (this._thinkingText === text) return;
|
|
83
|
+
this._thinkingText = text;
|
|
84
|
+
this.notify();
|
|
85
|
+
}
|
|
75
86
|
/**
|
|
76
87
|
* End the active thinking turn — drop any narration so the trail
|
|
77
88
|
* stops showing it. Fires on real text-message-start and on
|
|
@@ -328,6 +339,17 @@ function debug(...args) {
|
|
|
328
339
|
console.debug("[chat-transport]", ...args);
|
|
329
340
|
}
|
|
330
341
|
}
|
|
342
|
+
function friendlyToolLabel(name) {
|
|
343
|
+
const n = (name || "").toLowerCase();
|
|
344
|
+
if (n.includes("search")) return "Searching\u2026";
|
|
345
|
+
if (n.includes("route") || n.includes("wiki")) return "Finding the right page\u2026";
|
|
346
|
+
if (n.includes("read") || n.includes("section")) return "Reading up on that\u2026";
|
|
347
|
+
if (n.includes("mount") || n.includes("unmount") || n.includes("element"))
|
|
348
|
+
return "Updating the page\u2026";
|
|
349
|
+
if (n.includes("response") || n.includes("primary") || n.includes("action"))
|
|
350
|
+
return "Putting that together\u2026";
|
|
351
|
+
return "Working on it\u2026";
|
|
352
|
+
}
|
|
331
353
|
function mergeForwardedProps(prev, next) {
|
|
332
354
|
if (next.forwardedProps !== void 0) return next;
|
|
333
355
|
if (!prev?.forwardedProps) return next;
|
|
@@ -742,6 +764,7 @@ var ChatTransport = class {
|
|
|
742
764
|
case "typing":
|
|
743
765
|
return;
|
|
744
766
|
case "message-append": {
|
|
767
|
+
chatSession.clearThinking();
|
|
745
768
|
this._currentAssistantMessageId = event.message.id;
|
|
746
769
|
chatSession.receiveStart(event.message.id);
|
|
747
770
|
if (event.message.content && event.message.content.length > 0) {
|
|
@@ -774,9 +797,12 @@ var ChatTransport = class {
|
|
|
774
797
|
return;
|
|
775
798
|
}
|
|
776
799
|
case "tool-call": {
|
|
800
|
+
const existing = this._findToolCallStatus(event.toolCall.id);
|
|
801
|
+
if (!existing) {
|
|
802
|
+
chatSession.setThinkingText(friendlyToolLabel(event.toolCall.name));
|
|
803
|
+
}
|
|
777
804
|
const targetMessageId = event.messageId ?? this._currentAssistantMessageId;
|
|
778
805
|
if (!targetMessageId) return;
|
|
779
|
-
const existing = this._findToolCallStatus(event.toolCall.id);
|
|
780
806
|
if (!existing) {
|
|
781
807
|
chatSession.addToolCall(targetMessageId, {
|
|
782
808
|
id: event.toolCall.id,
|
package/dist/runtime.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/ChatSession.ts", "../src/ChatTransport.ts", "../src/observer/allowlist.ts", "../src/observer/queue.ts", "../src/observer/transport.ts", "../src/observer/index.ts", "../src/AdaptiveChatBarMountable.ts", "../src/AdaptiveChipsStripMountable.ts", "../src/NavLinkMountable.ts", "../src/TextAnswerMountable.ts", "../src/runtime.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * ChatSession \u2014 singleton holder of the chat conversation state.\n *\n * The chat is conceptually one thing. Whether it's rendered in the\n * mini-canvas's lid, the drawer's lid, or as a tile inside any slot,\n * they're all VIEWS of the same conversation. This module owns that\n * shared state.\n *\n * Why a module-level singleton (not on `runtime`):\n * - Per-page scope is the right granularity for a chat (one user,\n * one conversation, however many canvas instances on the page).\n * - Avoids a new SmartCanvasRuntime API surface for now. Easy to\n * promote to `runtime.chat` later without breaking the widget API.\n * - Module identity is stable per page; multiple imports return the\n * same instance.\n *\n * Separation of concerns:\n * - `ChatSession` owns state: messages, inFlight.\n * - Views (AdaptiveChatBar via AdaptiveChatBarMountable) subscribe\n * to state changes and dispatch user actions back via send() /\n * interrupt().\n * - Transports (the LLM call, SSE pipeline, stub timers) listen\n * for \"send\" / \"interrupt\" events and eventually call receive()\n * with the assistant's reply. Transports are NOT owned by this\n * module \u2014 adapters live separately.\n *\n * No persistence in this slice. Future: snapshot to runtime.state\n * for cross-session continuity.\n */\n\nimport type { TrailMessage, TrailToolCall } from './AdaptiveChatTrail';\n\nexport interface ChatSessionState {\n readonly messages: readonly TrailMessage[];\n readonly inFlight: boolean;\n /**\n * Latest reasoning narration from the model, streamed via the\n * AG-UI `THINKING_TEXT_MESSAGE_CONTENT` channel. Empty string when\n * no thinking turn is active. Consumers render this in place of\n * the silent loading dots while the model decides what to do\n * between tool calls. Cleared the moment a real text or tool-call\n * event lands \u2014 at that point the model has switched to producing\n * visible output and the narration is over.\n */\n readonly thinkingText: string;\n}\n\nexport interface ToolResultEvent {\n toolCallId: string;\n result: unknown;\n approved: boolean;\n}\n\nexport type ChatSessionSubscriber = (state: ChatSessionState) => void;\nexport type SendListener = (event: { text: string; activeLidSlot?: string }) => void;\nexport type InterruptListener = () => void;\nexport type ToolResultListener = (event: ToolResultEvent) => void;\n\n/** Optional per-send envelope. */\nexport interface SendOptions {\n /**\n * The slot the calling chat-bar lives in (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Forwarded to transport listeners so the\n * outbound request can tag the correct ``X-Active-Lid-Slot`` regardless\n * of which bar most recently configured the singleton transport.\n * Without per-send threading, two coexisting chat-bars race over the\n * transport's cached ``activeLidSlot`` and the user-facing routing\n * silently follows whichever bar configured last.\n */\n activeLidSlot?: string;\n}\nexport type Unsubscribe = () => void;\n\nexport const CHAT_SESSION_STORAGE_KEY = 'syntro:chat:v1';\n\ninterface PersistedShape {\n messages: TrailMessage[];\n nextId: number;\n}\n\nfunction isValidMessage(value: unknown): value is TrailMessage {\n if (typeof value !== 'object' || value === null) return false;\n const m = value as Record<string, unknown>;\n return (\n (typeof m.id === 'number' || typeof m.id === 'string') &&\n (m.role === 'user' || m.role === 'assistant' || m.role === 'system') &&\n typeof m.text === 'string'\n );\n}\n\nfunction loadFromStorage(): PersistedShape | null {\n try {\n const raw = globalThis.localStorage?.getItem(CHAT_SESSION_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed || !Array.isArray(parsed.messages)) return null;\n const messages = parsed.messages.filter(isValidMessage);\n const nextId = typeof parsed.nextId === 'number' ? parsed.nextId : messages.length + 1;\n return { messages, nextId };\n } catch {\n return null;\n }\n}\n\nexport class ChatSession {\n private _messages: TrailMessage[] = [];\n private _inFlight = false;\n private _thinkingText = '';\n private _nextId = 1;\n\n private subscribers = new Set<ChatSessionSubscriber>();\n private sendListeners = new Set<SendListener>();\n private interruptListeners = new Set<InterruptListener>();\n private toolResultListeners = new Set<ToolResultListener>();\n\n constructor() {\n const restored = loadFromStorage();\n if (restored) {\n this._messages = restored.messages;\n this._nextId = restored.nextId;\n }\n }\n\n /** Snapshot the current state. Always returns a fresh immutable view. */\n getState(): ChatSessionState {\n return {\n messages: [...this._messages],\n inFlight: this._inFlight,\n thinkingText: this._thinkingText,\n };\n }\n\n /**\n * Append a delta to the active thinking turn's narration buffer.\n * Forwarded from the AG-UI THINKING_TEXT_MESSAGE_CONTENT event so\n * the chat trail can render the model's own reasoning instead of\n * silent loading dots between turns.\n */\n appendThinkingDelta(delta: string): void {\n if (!delta) return;\n this._thinkingText += delta;\n this.notify();\n }\n\n /**\n * End the active thinking turn \u2014 drop any narration so the trail\n * stops showing it. Fires on real text-message-start and on\n * tool-call-start, the moment the model switches from reasoning\n * to visible output.\n */\n clearThinking(): void {\n if (!this._thinkingText) return;\n this._thinkingText = '';\n this.notify();\n }\n\n /**\n * Subscribe to state changes. Called immediately with the current\n * state, then again on every change. Returns an unsubscribe function.\n */\n subscribe(cb: ChatSessionSubscriber): Unsubscribe {\n this.subscribers.add(cb);\n cb(this.getState());\n return () => {\n this.subscribers.delete(cb);\n };\n }\n\n /**\n * User submitted a message. Appends a user-role message, sets\n * inFlight=true, notifies state subscribers, and fires a \"send\"\n * event so transports can pick it up. Empty/whitespace text is a\n * no-op (matches the chat bar's local guard).\n */\n send(text: string, opts?: SendOptions): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n this._messages.push({ id: this._nextId++, role: 'user', text: trimmed });\n this._inFlight = true;\n this.notify();\n const event: { text: string; activeLidSlot?: string } = { text: trimmed };\n if (opts?.activeLidSlot) event.activeLidSlot = opts.activeLidSlot;\n for (const listener of this.sendListeners) listener(event);\n }\n\n /**\n * Single-shot assistant reply (no streaming). Equivalent to\n * receiveStart + receiveDelta + receiveEnd in one call. Useful for\n * stub transports and tests that don't model streaming.\n */\n receive(text: string): void {\n const id = `m-${this._nextId++}`;\n this._messages.push({ id, role: 'assistant', text, status: 'complete' });\n this._inFlight = false;\n this.notify();\n }\n\n /**\n * Begin a streaming assistant message. Appends an empty assistant\n * message with status='streaming'. Caller (transport adapter) feeds\n * deltas via receiveDelta(id, text) and signals completion via\n * receiveEnd(id). `inFlight` stays true through the stream.\n */\n receiveStart(id: string): void {\n this._messages.push({ id, role: 'assistant', text: '', status: 'streaming' });\n this._inFlight = true;\n this.notify();\n }\n\n /**\n * Append a delta to a streaming message. No-op when the id is\n * unknown (race between transport events and reset, etc.) \u2014 never\n * throws so transports can fire-and-forget.\n */\n receiveDelta(id: string, delta: string): void {\n const msg = this._messages.find((m) => m.id === id);\n if (!msg || msg.status !== 'streaming') return;\n msg.text += delta;\n this.notify();\n }\n\n /**\n * Mark a streaming message complete and clear inFlight. No-op when\n * the id is unknown (defensive against transport double-fires).\n */\n receiveEnd(id: string): void {\n const msg = this._messages.find((m) => m.id === id);\n if (msg && msg.status === 'streaming') {\n msg.status = 'complete';\n }\n this._inFlight = false;\n this.notify();\n }\n\n /**\n * Transport reports a fatal error. Marks any in-flight streaming\n * message as 'error' (so the trail can render a styled error chip\n * instead of pretending the partial text was a complete answer),\n * appends a system-role message with the error text for visibility,\n * and clears inFlight. Also drops any pending thinking narration\n * \u2014 leaving stale \"Let me check\u2026\" alongside an error chip reads\n * as if the assistant is still working when it isn't.\n */\n error(message: string): void {\n for (const m of this._messages) {\n if (m.status === 'streaming') m.status = 'error';\n }\n this._messages.push({\n id: `err-${this._nextId++}`,\n role: 'system',\n text: message,\n status: 'error',\n });\n this._inFlight = false;\n this._thinkingText = '';\n this.notify();\n }\n\n /**\n * User clicked the in-flight stop button. Clears inFlight and\n * fires an \"interrupt\" event so transports can cancel their\n * in-flight request. No-op if not in-flight (idempotent). Drops\n * any pending thinking narration for the same reason as error():\n * the visitor explicitly asked the assistant to stop, so it\n * shouldn't keep narrating in the trail.\n */\n interrupt(): void {\n if (!this._inFlight) return;\n this._inFlight = false;\n this._thinkingText = '';\n this.notify();\n for (const listener of this.interruptListeners) listener();\n }\n\n /**\n * Wipe state. Used by the canvas-close path (start a fresh\n * conversation next time) and by tests.\n */\n reset(): void {\n this._messages = [];\n this._inFlight = false;\n this._thinkingText = '';\n this._nextId = 1;\n this.notify();\n }\n\n /** Register a transport's send listener. Returns unsubscribe. */\n onSend(listener: SendListener): Unsubscribe {\n this.sendListeners.add(listener);\n return () => {\n this.sendListeners.delete(listener);\n };\n }\n\n /**\n * True when at least one transport has wired itself to the session's\n * send pipeline. Views can use this to surface \"no chat backend\n * connected\" affordances instead of hanging in `inFlight` after a\n * send fires into the void.\n */\n hasTransport(): boolean {\n return this.sendListeners.size > 0;\n }\n\n /** Register a transport's interrupt listener. Returns unsubscribe. */\n onInterrupt(listener: InterruptListener): Unsubscribe {\n this.interruptListeners.add(listener);\n return () => {\n this.interruptListeners.delete(listener);\n };\n }\n\n /**\n * Register a transport's tool-result listener. The transport\n * forwards `tool-result` actions back to the agent after the user\n * approves or rejects a client-tool call. Returns unsubscribe.\n */\n onToolResult(listener: ToolResultListener): Unsubscribe {\n this.toolResultListeners.add(listener);\n return () => {\n this.toolResultListeners.delete(listener);\n };\n }\n\n // -------------------------------------------------------------------------\n // Tool calls\n // -------------------------------------------------------------------------\n\n /**\n * Attach a tool call to a streaming assistant message. No-op when\n * the message id is unknown (race between transport events and\n * reset / late mount).\n */\n addToolCall(messageId: string | number, toolCall: TrailToolCall): void {\n const msg = this._messages.find((m) => m.id === messageId);\n if (!msg) return;\n msg.toolCalls = [...(msg.toolCalls ?? []), { ...toolCall }];\n this.notify();\n }\n\n /**\n * Partially update a tool call by id. Used by the transport to\n * advance status (args-streaming \u2192 running \u2192 done) as AG-UI events\n * arrive. No-op when the id is unknown.\n */\n updateToolCall(toolCallId: string, patch: Partial<TrailToolCall>): void {\n for (const msg of this._messages) {\n const tcs = msg.toolCalls;\n if (!tcs) continue;\n const idx = tcs.findIndex((tc) => tc.id === toolCallId);\n if (idx === -1) continue;\n const next = [...tcs];\n next[idx] = { ...next[idx], ...patch } as TrailToolCall;\n msg.toolCalls = next;\n this.notify();\n return;\n }\n }\n\n /**\n * Resolve a (client-) tool call. Marks the call done, persists, and\n * fires onToolResult so the transport can forward the result + the\n * user's approve/reject decision back to the agent. No-op when the\n * id is unknown.\n */\n resolveToolCall(toolCallId: string, result: unknown, approved: boolean): void {\n let found = false;\n for (const msg of this._messages) {\n const tcs = msg.toolCalls;\n if (!tcs) continue;\n const idx = tcs.findIndex((tc) => tc.id === toolCallId);\n if (idx === -1) continue;\n const next = [...tcs];\n next[idx] = { ...next[idx], status: 'done' } as TrailToolCall;\n msg.toolCalls = next;\n found = true;\n break;\n }\n if (!found) return;\n this.notify();\n for (const listener of this.toolResultListeners) {\n listener({ toolCallId, result, approved });\n }\n }\n\n private notify(): void {\n const state = this.getState();\n this.persist();\n for (const sub of this.subscribers) sub(state);\n }\n\n private persist(): void {\n try {\n if (this._messages.length === 0) {\n globalThis.localStorage?.removeItem(CHAT_SESSION_STORAGE_KEY);\n return;\n }\n const payload: PersistedShape = { messages: this._messages, nextId: this._nextId };\n globalThis.localStorage?.setItem(CHAT_SESSION_STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // private mode / quota / SSR \u2014 swallow; in-memory state is still valid\n }\n }\n}\n\n/**\n * The module-level singleton. Every `<adaptive-chat-bar>` (regardless\n * of which slot it lives in) reads from and writes to this instance.\n * Multiple imports of this module return the same object.\n *\n * Scope: per-page. Correct for the canonical case (one user, one\n * conversation, however many canvas views surface it). Multiple\n * `<smart-canvas>` instances on the same page will share state \u2014\n * tracked in project_future_work.md for per-runtime scoping.\n */\nexport const chatSession = new ChatSession();\n", "/**\n * ChatTransport \u2014 singleton transport adapter that bridges chatSession\n * (the view-side state holder) to the real backend chat pipeline\n * (AG-UI SSE at `/api/adaptive/stream`).\n *\n * This is the unification of two formerly separate paths:\n * - `ChatAssistantLit` (old) owns the transport plumbing \u2014\n * AgUiTransport, Cloudflare Turnstile, headers, A2UI passthrough,\n * telemetry, fallback card.\n * - `AdaptiveChatBar` + `chatSession` (new) owns the canvas-lid UX \u2014\n * glassmorphism bar, bubble-up trail, per-page persistence.\n *\n * This module ports every transport-side concern from ChatAssistantLit\n * into a session-shaped adapter so the new bar gets full backend\n * parity. The bar stays a pure view; the transport stays a pure pipe.\n *\n * Lifecycle:\n * - `configure({ backendUrl, runtime, ... })` \u2014 called once by the\n * SDK runtime at bootstrap from chat config. Idempotent; second\n * call with the same backendUrl is a no-op.\n * - Connection is LAZY. The transport doesn't acquire Turnstile or\n * open the SSE until the first chatSession.send() \u2014 saves cost\n * on pages where the user never opens chat.\n * - On chatSession.send \u2192 transport ensures connected (acquires\n * Turnstile token, builds AgUiTransport) then forwards\n * `{type:'user-message', text}` to the agent.\n * - On chatSession.onInterrupt \u2192 transport sends stop-generation.\n * - AgUi events stream into chatSession via receiveStart / Delta /\n * End / error.\n * - A2UI custom events forward to runtime.actions.applyBatch so the\n * agent can drive canvas updates.\n *\n * Telemetry parity with ChatAssistantLit:\n * - chatbot.transport_error (every error, with status/body/name)\n * - chatbot.a2ui_applied\n * - chatbot.fallback_rendered \u2014 emitted when the transport gives up\n * (Turnstile failed AND backend rejected) so existing PostHog\n * queries keep working.\n *\n * Threading model: single-flight per page. Multiple concurrent sends\n * are queued by AgUiTransport itself. Multiple bar mounts share this\n * one transport via chatSession.\n */\n\nimport type { ServerEvent } from '@syntrologie/chat';\n// AgUiTransport / Turnstile helpers live in the existing packages \u2014\n// we reuse them instead of re-implementing.\nimport { AgUiTransport } from '@syntrologie/chat/transport/agui';\n\nimport type { TrailToolCall } from './AdaptiveChatTrail';\nimport { chatSession } from './ChatSession';\nimport type { ElementMutation } from './elements';\nimport { decodeMutationEnvelope } from './elements';\nimport { acquireTokenWithChallenge } from './Turnstile';\nimport type { ChatbotWidgetRuntime } from './types';\n\n/**\n * Per-customer \"chat unavailable\" card config. Surfaced via onFallback\n * when the transport gives up after repeated failures. Mirrors\n * ChatbotFallback in types.ts so consumers can pass the same config.\n */\nexport interface ChatbotFallbackConfig {\n title?: string;\n message?: string;\n ctaLabel?: string;\n ctaHref?: string;\n}\n\nexport interface ChatTransportConfig {\n /** Backend host, e.g. \"https://demo-api.syntrologie.com\" or \"\" for same-origin. */\n backendUrl: string;\n /** Runtime hooks for A2UI apply + telemetry. */\n runtime: ChatbotWidgetRuntime;\n /** Optional thread id for conversation continuity across reloads. */\n threadId?: string;\n /**\n * Optional set of client-tool names the transport should treat as\n * \"needs user approval\" (surfaced via chatSession.toolCalls instead\n * of auto-executed server-side). Empty by default \u2014 all tool calls\n * are server-driven and the transport just emits the \"tool call\n * happened\" event.\n */\n clientTools?: Set<string>;\n /**\n * Per-customer \"chat unavailable\" card. Rendered by the host\n * (typically AdaptiveChatBarMountable) after repeated connect\n * failures wipe the chat surface \u2014 exactly the same UX\n * ChatAssistantLit's fallback path provides.\n */\n fallback?: ChatbotFallbackConfig;\n /**\n * Arbitrary JSON object attached to every AG-UI request as\n * `forwardedProps`. Used by the adaptive chat surface to ship the\n * LLM-authored UI element config (`uiTemplates`, `elementsEnabled`)\n * per request \u2014 the backend reads these to enable the\n * `mount_element` / `patch_element` / `unmount_element` tools.\n * Callable form is re-evaluated on every turn so a config edit can\n * land mid-conversation.\n */\n forwardedProps?: Record<string, unknown> | (() => Record<string, unknown> | undefined);\n /**\n * Optional callback for `syntro.element.mutation` AG-UI custom events.\n * The transport decodes the envelope on receipt; if it matches the\n * element-mutation schema, mutations are routed here instead of the\n * generic `runtime.actions.applyBatch` legacy path. Consumers are\n * expected to forward to `ElementInstanceStore.apply(mutations)` \u2014\n * we don't take a store reference directly so the transport stays\n * agnostic of which surface owns the store (the chat-bar widget\n * may own one; ChatAssistantLit owns its own; both share this\n * singleton transport).\n *\n * When unset, element-mutation envelopes fall back to applyBatch,\n * matching legacy behaviour (which would no-op since applyBatch\n * doesn't know about MutationEnvelope).\n */\n onElementMutation?: (mutations: ElementMutation[]) => void;\n /**\n * Slot the chat-bar widget is mounted into (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Forwarded as ``X-Active-Lid-Slot`` on every\n * ``/api/adaptive/stream`` request so the backend can route mounts to\n * the canvas next to whichever lid the visitor sent from. Optional \u2014\n * omitting it falls back to the template's static ``default_slot``\n * server-side, which is the pre-change behaviour.\n */\n activeLidSlot?: string;\n}\n\n/**\n * Debounce window for connect errors. Single transient errors\n * (cold-start 502, brief CORS preflight failure) should NOT swap the\n * chat to the fallback card; only sustained failure should. Matches\n * ChatAssistantLit's ERROR_DEBOUNCE_MS.\n */\nexport const FALLBACK_DEBOUNCE_MS = 1_500;\n\nexport interface FallbackPayload {\n reason: 'connect_failed' | 'connect_timeout';\n fallback: ChatbotFallbackConfig;\n transportId: string;\n transportAgeMs: number;\n messagesSucceeded: number;\n hadTurnstileToken: boolean | null;\n errorStatus: number | null;\n errorBody: string | null;\n errorMessage: string | null;\n errorName: string | null;\n}\n\nexport type FallbackListener = (payload: FallbackPayload) => void;\n\ntype ChatTransportStatus =\n | 'idle' // configure() not called yet\n | 'configured' // ready but not connected\n | 'acquiring' // Turnstile token acquisition in flight\n | 'connected' // AgUiTransport up and ready\n | 'error'; // last attempt failed; will retry on next send\n\ninterface SyntroGlobalConfig {\n token?: string;\n}\n\n/**\n * Read the workspace's syn_* token from runtime-config.js. The SDK\n * sets this global at bootstrap; for non-CDN test environments the\n * test page sets it directly. Returns undefined when the global is\n * missing \u2014 the connect will then fall through to the unauthenticated\n * path and the backend will 401 (caught by error handling below).\n */\nfunction readSyntroToken(): string | undefined {\n if (typeof window === 'undefined') return undefined;\n const cfg = (window as unknown as { __SYNTRO_CONFIG__?: SyntroGlobalConfig }).__SYNTRO_CONFIG__;\n const token = cfg?.token;\n return typeof token === 'string' && token.length > 0 ? token : undefined;\n}\n\n/**\n * Debug logger gated on `window.__SYNTRO_CHAT_DEBUG__`. Mirrors\n * ChatAssistantLit so flipping that flag in the customer's DevTools\n * enables verbose tracing across the whole chat pipeline (the bar\n * AND the legacy assistant) without rebuilding the SDK.\n */\nfunction debug(...args: unknown[]): void {\n if (typeof window === 'undefined') return;\n if ((window as unknown as { __SYNTRO_CHAT_DEBUG__?: boolean }).__SYNTRO_CHAT_DEBUG__) {\n console.debug('[chat-transport]', ...args);\n }\n}\n\n/**\n * Singleton-safe merge for forwardedProps. The transport is shared\n * across every chat surface in a canvas (chat-bar lid on the drawer,\n * inline chat-bar tile, hero anchor), and each surface calls\n * `configure()` on mount. If a surface that hasn't been wired with\n * `uiTemplates` configures *after* one that has, a naive shallow\n * merge clobbers the bag and the backend's `_inject_available_templates`\n * silently falls back to the empty list. Preserve any previously-set\n * bag unless the new config explicitly provides one \u2014 surfaces that\n * don't ship templates just opt out of mutating that field.\n */\nfunction mergeForwardedProps(\n prev: ChatTransportConfig | null,\n next: ChatTransportConfig\n): ChatTransportConfig {\n if (next.forwardedProps !== undefined) return next;\n if (!prev?.forwardedProps) return next;\n return { ...next, forwardedProps: prev.forwardedProps };\n}\n\nexport class ChatTransport {\n private _config: ChatTransportConfig | null = null;\n private _status: ChatTransportStatus = 'idle';\n private _agui: AgUiTransport | null = null;\n private _transportUnsub: (() => void) | null = null;\n private _sessionUnsubSend: (() => void) | null = null;\n private _sessionUnsubInterrupt: (() => void) | null = null;\n private _sessionUnsubToolResult: (() => void) | null = null;\n private _connectInFlight: Promise<boolean> | null = null;\n /** Bounded streaming-message id for the currently-being-typed assistant turn. */\n private _currentAssistantMessageId: string | null = null;\n /** Outcome bookkeeping for telemetry. */\n private _hadTurnstileToken: boolean | null = null;\n /** Count of successful round-trips for telemetry payloads. */\n private _messagesSucceeded = 0;\n /** True once a successful assistant message has landed \u2014 gates fallback. */\n private _hasSucceeded = false;\n /** True once fallback has fired (one-shot). */\n private _fallbackRendered = false;\n /**\n * Per-send override for ``X-Active-Lid-Slot``. Set in the\n * ``chatSession.onSend`` listener immediately before each\n * ``_forwardUserMessage`` and consumed by ``buildHeaders`` on the\n * outbound request. The singleton transport is shared by every\n * mounted chat-bar (drawer + inline) so cached ``_config.activeLidSlot``\n * follows whichever bar last reconfigured \u2014 using that for routing\n * silently misroutes tiles when both bars coexist. Per-send threading\n * pins the header to the bar that actually sent the message.\n */\n private _pendingLidSlot: string | null = null;\n /** Active debounce timer; null when no debounce pending. */\n private _errorDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n /** Most recent error payload, captured so debounced fallback can attach it. */\n private _lastErrorPayload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n } | null = null;\n private _fallbackListeners = new Set<FallbackListener>();\n /**\n * Per-configure-cycle id for correlating telemetry events from a\n * single transport lifetime. Mirrors ChatAssistantLit's mountId\n * but scoped to configure cycles since the transport is a\n * singleton across mounts.\n */\n private _transportId = `tx_${Math.random().toString(36).slice(2, 8)}`;\n private _configuredAt = 0;\n\n /**\n * Configure the transport. Idempotent \u2014 calling again with the same\n * backendUrl is a no-op; calling with a different backendUrl tears\n * the connection down and re-arms.\n */\n configure(config: ChatTransportConfig): void {\n const same =\n this._config &&\n this._config.backendUrl === config.backendUrl &&\n this._config.threadId === config.threadId;\n if (same) {\n // Allow runtime + clientTools to be replaced without reconnect \u2014\n // the bar may remount with a fresh runtime closure.\n this._config = { ...this._config, ...mergeForwardedProps(this._config, config) };\n return;\n }\n this._disconnect();\n this._config = config;\n this._status = 'configured';\n this._transportId = `tx_${Math.random().toString(36).slice(2, 8)}`;\n this._configuredAt = Date.now();\n this._wireSession();\n debug('configured', {\n transportId: this._transportId,\n backendUrl: config.backendUrl,\n threadId: config.threadId,\n });\n }\n\n /** ms since the most recent configure() call. 0 before any configure. */\n private _ageMs(): number {\n return this._configuredAt === 0 ? 0 : Date.now() - this._configuredAt;\n }\n\n /** True when configure() has been called and we're ready to lazy-connect on send. */\n get isConfigured(): boolean {\n return this._status !== 'idle';\n }\n\n /** True when AgUiTransport is up. */\n get isConnected(): boolean {\n return this._status === 'connected';\n }\n\n /**\n * Subscribe to fallback events \u2014 fires once per configure cycle\n * when the transport gives up after sustained failure. Hosts\n * (typically AdaptiveChatBarMountable) use this to swap the chat\n * bar for a static \"contact support\" card.\n */\n onFallback(listener: FallbackListener): () => void {\n this._fallbackListeners.add(listener);\n return () => {\n this._fallbackListeners.delete(listener);\n };\n }\n\n /**\n * Test seam \u2014 drive a synthetic error event through the transport's\n * error handling without standing up a real AgUi transport. Production\n * code path uses _onTransportEvent. Exported as a public method to\n * keep the test isolation simple; not part of the documented API.\n */\n simulateError(payload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n }): void {\n this._handleErrorEvent(payload);\n }\n\n /**\n * Test seam \u2014 register a synthetic successful message-complete so\n * the hasSucceeded gate flips without a real AgUi round-trip.\n */\n simulateSuccessfulMessage(): void {\n this._hasSucceeded = true;\n this._messagesSucceeded += 1;\n this._clearDebounceTimer();\n }\n\n /**\n * Test seam \u2014 return the lid slot that the next outbound request\n * WOULD tag ``X-Active-Lid-Slot`` with, given current state. Mirrors\n * the exact resolution buildHeaders uses (per-send slot wins over\n * cached config). Not part of the documented API.\n */\n getActiveLidSlotForTest(): string | null {\n return this._pendingLidSlot ?? this._config?.activeLidSlot ?? null;\n }\n\n /**\n * Tear connection-level state down. Used internally by configure()\n * to swap backends; preserves host-registered fallback listeners\n * because the host UI handler (e.g. AdaptiveChatBarMountable's\n * \"swap to fallback card\" callback) is configuration-independent.\n */\n private _disconnect(): void {\n if (this._transportUnsub) {\n this._transportUnsub();\n this._transportUnsub = null;\n }\n if (this._sessionUnsubSend) {\n this._sessionUnsubSend();\n this._sessionUnsubSend = null;\n }\n if (this._sessionUnsubInterrupt) {\n this._sessionUnsubInterrupt();\n this._sessionUnsubInterrupt = null;\n }\n if (this._sessionUnsubToolResult) {\n this._sessionUnsubToolResult();\n this._sessionUnsubToolResult = null;\n }\n if (this._agui) {\n this._agui.disconnect();\n this._agui = null;\n }\n this._clearDebounceTimer();\n this._config = null;\n this._status = 'idle';\n this._connectInFlight = null;\n this._currentAssistantMessageId = null;\n this._hadTurnstileToken = null;\n this._messagesSucceeded = 0;\n this._hasSucceeded = false;\n this._fallbackRendered = false;\n this._lastErrorPayload = null;\n this._pendingLidSlot = null;\n }\n\n /**\n * Tear everything down \u2014 connection state PLUS host listeners.\n * Use this in test teardown or when fully shutting the transport\n * (page unload, integration test reset). The mountable calls\n * _disconnect indirectly via reconfigure.\n */\n reset(): void {\n this._disconnect();\n this._fallbackListeners.clear();\n }\n\n private _clearDebounceTimer(): void {\n if (this._errorDebounceTimer) {\n clearTimeout(this._errorDebounceTimer);\n this._errorDebounceTimer = null;\n }\n }\n\n /**\n * Shared error-handling kernel \u2014 called by the AG-UI subscriber and\n * by the simulateError test seam. Publishes transport_error\n * telemetry, captures lastErrorPayload, and starts the debounce\n * timer that will fire fallback if no successful message arrives\n * before it expires. Gated by hasSucceeded (post-success errors\n * never fallback) and _fallbackRendered (one-shot).\n */\n private _handleErrorEvent(payload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n }): void {\n const status = payload.status ?? null;\n const body = payload.body ? String(payload.body).slice(0, 200) : null;\n this._lastErrorPayload = {\n message: payload.message,\n status,\n body,\n errorName: payload.errorName ?? null,\n };\n\n this._config?.runtime.events.publish('chatbot.transport_error', {\n source: 'chat-transport',\n transportId: this._transportId,\n transportAgeMs: this._ageMs(),\n messagesSucceeded: this._messagesSucceeded,\n hadTurnstileToken: this._hadTurnstileToken,\n hasSucceeded: this._hasSucceeded,\n errorMessage: payload.message ?? null,\n errorStatus: status,\n errorBody: body,\n errorName: payload.errorName ?? null,\n });\n\n if (this._hasSucceeded || this._fallbackRendered || this._errorDebounceTimer) return;\n this._errorDebounceTimer = setTimeout(() => {\n this._errorDebounceTimer = null;\n if (this._hasSucceeded || this._fallbackRendered) return;\n this._renderFallback('connect_failed');\n }, FALLBACK_DEBOUNCE_MS);\n }\n\n /**\n * Fire the fallback. One-shot per configure cycle. Notifies all\n * fallback listeners with the per-customer card config and the\n * diagnostic snapshot for telemetry/debug.\n */\n private _renderFallback(reason: FallbackPayload['reason']): void {\n if (this._fallbackRendered) return;\n this._fallbackRendered = true;\n debug('fallback', { reason, transportId: this._transportId, ageMs: this._ageMs() });\n const fallback = this._config?.fallback ?? {};\n const payload: FallbackPayload = {\n reason,\n fallback,\n transportId: this._transportId,\n transportAgeMs: this._ageMs(),\n messagesSucceeded: this._messagesSucceeded,\n hadTurnstileToken: this._hadTurnstileToken,\n errorStatus: this._lastErrorPayload?.status ?? null,\n errorBody: this._lastErrorPayload?.body ?? null,\n errorMessage: this._lastErrorPayload?.message ?? null,\n errorName: this._lastErrorPayload?.errorName ?? null,\n };\n this._config?.runtime.events.publish(\n 'chatbot.fallback_rendered',\n payload as unknown as Record<string, unknown>\n );\n for (const listener of this._fallbackListeners) listener(payload);\n }\n\n // -------------------------------------------------------------------------\n // Internal: chatSession wiring\n // -------------------------------------------------------------------------\n\n private _wireSession(): void {\n this._sessionUnsubSend = chatSession.onSend(({ text, activeLidSlot }) => {\n // Capture the sending bar's slot BEFORE awaiting the connect /\n // forward chain. `_pendingLidSlot` is consumed by buildHeaders on\n // the outbound request \u2014 see the field doc on `_pendingLidSlot`\n // for why we can't rely on `_config.activeLidSlot` here.\n this._pendingLidSlot =\n typeof activeLidSlot === 'string' && activeLidSlot.length > 0 ? activeLidSlot : null;\n void this._forwardUserMessage(text);\n });\n this._sessionUnsubInterrupt = chatSession.onInterrupt(() => {\n this._agui?.send({ type: 'stop-generation' });\n });\n this._sessionUnsubToolResult = chatSession.onToolResult(({ toolCallId, result, approved }) => {\n this._agui?.send({ type: 'tool-result', toolCallId, result, approved });\n });\n }\n\n private async _forwardUserMessage(text: string): Promise<void> {\n const ok = await this._ensureConnected();\n if (!ok || !this._agui) {\n // Connect failed; surface to the session so the bar shows an error\n // chip and clears inFlight (otherwise the user is stuck on the\n // \u23F9 stop button forever).\n chatSession.error(\"Couldn't connect to chat. Please try again.\");\n return;\n }\n this._agui.send({ type: 'user-message', text });\n }\n\n // -------------------------------------------------------------------------\n // Internal: connect (lazy, Turnstile-gated)\n // -------------------------------------------------------------------------\n\n /**\n * Ensure AgUiTransport is up. Idempotent \u2014 multiple concurrent calls\n * dedupe to a single Turnstile acquisition + transport setup.\n * Returns true on success, false on terminal failure.\n */\n private async _ensureConnected(): Promise<boolean> {\n if (this._status === 'connected' && this._agui) return true;\n if (!this._config) return false;\n if (this._connectInFlight) return this._connectInFlight;\n\n this._connectInFlight = (async () => {\n this._status = 'acquiring';\n const cft = await this._acquireTurnstileWithChallenge();\n this._hadTurnstileToken = cft !== null;\n\n if (this._config === null) return false; // raced with reset()\n\n const baseUrl = this._config.backendUrl.replace(/\\/$/, '');\n const streamUrl = `${baseUrl}/api/adaptive/stream`;\n const token = readSyntroToken();\n const buildHeaders = (): Record<string, string> => {\n const h: Record<string, string> = {};\n if (token) h.Authorization = `Bearer ${token}`;\n if (cft) h['CF-Turnstile-Token'] = cft;\n // Forward the slot the chat-bar that initiated this send lives\n // in so the backend can route mount_element results to the\n // canvas next to it. Prefer `_pendingLidSlot` (set on each\n // chatSession.onSend) over `_config.activeLidSlot` (last value\n // cached by configure): when drawer + inline bars coexist they\n // share this singleton transport, so the cached config follows\n // whichever bar reconfigured most recently \u2014 not the bar that\n // actually sent the current message. `_pendingLidSlot` pins the\n // header to the sender. Fall back to the cached config so older\n // call sites that haven't been migrated still get a value.\n const lidSlot = this._pendingLidSlot ?? this._config?.activeLidSlot;\n if (typeof lidSlot === 'string' && lidSlot.length > 0) {\n h['X-Active-Lid-Slot'] = lidSlot;\n }\n // Forward the runtime's visitor ids (the canonical, runtime-maintained\n // accessor \u2014 NOT window.posthog). distinct_id resolves historical\n // context (KNOWN ABOUT VISITOR block); session_id scopes the live\n // observation drain + seeds cross-session recall on the first turn.\n // Missing (consent denied / no runtime id) \u2192 header omitted \u2192 cold.\n try {\n const rt = this._config?.runtime as\n | {\n telemetry?: {\n getDistinctId?: () => string | null | undefined;\n getSessionId?: () => string | null | undefined;\n };\n }\n | undefined;\n const did = rt?.telemetry?.getDistinctId?.();\n if (typeof did === 'string' && did.length > 0) {\n h['X-Distinct-Id'] = did;\n }\n const sid = rt?.telemetry?.getSessionId?.();\n if (typeof sid === 'string' && sid.length > 0) {\n h['X-Syntro-Session'] = sid;\n }\n } catch {\n // A runtime telemetry throw is extremely rare but cheap to guard.\n }\n return h;\n };\n\n const runtime = this._config.runtime;\n // Resolve forwardedProps at run-time (each AG-UI request), not at\n // transport construction. The config can be updated via\n // `configure()` with the same backendUrl (no reconnect), so the\n // late-bound closure keeps the transport in sync with the most\n // recent uiTemplates / elementsEnabled declarations.\n const resolveForwardedProps = (): Record<string, unknown> | undefined => {\n const raw = this._config?.forwardedProps;\n return typeof raw === 'function' ? raw() : raw;\n };\n this._agui = new AgUiTransport({\n url: streamUrl,\n headers: buildHeaders,\n threadId: this._config.threadId,\n clientTools: this._config.clientTools,\n // Adaptive runtime SDK needs the `syntro_chat_session` cookie to\n // round-trip cross-origin so subsequent boot fetches can rehydrate\n // LLM-authored UI elements. Editor / action-plan chat surfaces\n // auth via `?token=` and intentionally leave this unset (see\n // AgUiTransportOptions.credentials docstring).\n credentials: 'include',\n forwardedProps: resolveForwardedProps,\n onA2UIEvent: (payload) => {\n // Discriminate `syntro.element.mutation` envelopes (LLM-\n // authored UI element mounts/patches/unmounts) from legacy\n // A2UI / raw ActionStep payloads. Mirrors ChatAssistantLit's\n // routing \u2014 the chat-bar lid surface needs the same wiring so\n // mount_element / patch_element / unmount_element results\n // actually land on the host page.\n const mutations = decodeMutationEnvelope(payload);\n if (mutations !== null) {\n const handler = this._config?.onElementMutation;\n if (handler) {\n try {\n handler(mutations);\n runtime.events.publish('chatbot.element_mutation_applied', {\n source: 'chat-transport',\n count: mutations.length,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[chat-transport] element mutation apply failed:', msg);\n }\n return;\n }\n // No handler registered \u2014 the surface using this transport\n // didn't opt into element mutations. Drop silently rather\n // than feeding a MutationEnvelope into applyBatch (which\n // would no-op or warn).\n return;\n }\n runtime.actions\n .applyBatch([payload as unknown as Record<string, unknown>])\n .then(() => {\n runtime.events.publish('chatbot.a2ui_applied', { source: 'chat-transport' });\n })\n .catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[chat-transport] A2UI apply failed:', msg);\n });\n },\n });\n this._agui.connect();\n this._transportUnsub = this._agui.subscribe((event) => this._onTransportEvent(event));\n this._status = 'connected';\n return true;\n })();\n\n try {\n return await this._connectInFlight;\n } finally {\n this._connectInFlight = null;\n }\n }\n\n /**\n * Acquire a Turnstile token via the managed-challenge flow.\n * Delegates to the shared Turnstile helper that owns the verify\n * panel lifecycle. Returns null when Turnstile is disabled at\n * build time or acquisition fails.\n */\n private async _acquireTurnstileWithChallenge(): Promise<string | null> {\n const { token } = await acquireTokenWithChallenge();\n return token;\n }\n\n // -------------------------------------------------------------------------\n // Internal: AgUi event \u2192 chatSession\n // -------------------------------------------------------------------------\n\n /**\n * Look up a tool call's current chatSession-side status by id.\n * Used to decide between addToolCall (first sighting) and\n * updateToolCall (subsequent updates) when AG-UI re-emits\n * `tool-call` events for client tools transitioning to 'pending'.\n */\n private _findToolCallStatus(toolCallId: string): TrailToolCall['status'] | null {\n const state = chatSession.getState();\n for (const msg of state.messages) {\n const tc = msg.toolCalls?.find((t) => t.id === toolCallId);\n if (tc) return tc.status;\n }\n return null;\n }\n\n /** Map AG-UI ToolCallStatus to TrailToolCall status. */\n private _mapToolCallStatus(status: string): TrailToolCall['status'] {\n switch (status) {\n case 'args-streaming':\n return 'args-streaming';\n case 'pending':\n return 'pending';\n case 'running':\n return 'running';\n case 'done':\n return 'done';\n case 'error':\n return 'error';\n default:\n return 'running';\n }\n }\n\n private _onTransportEvent(event: ServerEvent): void {\n switch (event.type) {\n case 'session-ready':\n case 'messages-snapshot':\n case 'typing':\n // Local-only events from AgUiTransport.connect() \u2014 no UI impact.\n return;\n\n case 'message-append': {\n // Start of a new streaming assistant message.\n this._currentAssistantMessageId = event.message.id;\n chatSession.receiveStart(event.message.id);\n if (event.message.content && event.message.content.length > 0) {\n chatSession.receiveDelta(event.message.id, event.message.content);\n }\n return;\n }\n\n case 'message-delta': {\n const id = event.messageId ?? this._currentAssistantMessageId;\n if (!id || !event.delta) return;\n chatSession.receiveDelta(id, event.delta);\n return;\n }\n\n case 'thinking-delta': {\n // Stream the model's reasoning narration into chat session state\n // so the trail can render it in place of silent loading dots\n // while the model decides what to do next.\n chatSession.appendThinkingDelta(event.delta);\n return;\n }\n\n case 'thinking-clear': {\n // Real output is about to start \u2014 drop the narration so the trail\n // can swap to the live text/tool-call chip in one frame.\n chatSession.clearThinking();\n return;\n }\n\n case 'message-complete': {\n const id = event.messageId ?? this._currentAssistantMessageId;\n if (!id) return;\n chatSession.receiveEnd(id);\n this._currentAssistantMessageId = null;\n this._messagesSucceeded += 1;\n // Flip the hasSucceeded gate: errors after this point will no\n // longer trigger a fallback swap (matches ChatAssistantLit).\n this._hasSucceeded = true;\n this._clearDebounceTimer();\n return;\n }\n\n case 'tool-call': {\n // tool-call arrives twice in the AG-UI flow: once at start\n // (status='args-streaming') and once at end for client tools\n // with status='pending' awaiting user approval. Add on the\n // first sighting, update on the second.\n const targetMessageId = event.messageId ?? this._currentAssistantMessageId;\n if (!targetMessageId) return;\n const existing = this._findToolCallStatus(event.toolCall.id);\n if (!existing) {\n chatSession.addToolCall(targetMessageId, {\n id: event.toolCall.id,\n name: event.toolCall.name,\n status: this._mapToolCallStatus(event.toolCall.status),\n });\n } else {\n chatSession.updateToolCall(event.toolCall.id, {\n name: event.toolCall.name,\n status: this._mapToolCallStatus(event.toolCall.status),\n });\n }\n return;\n }\n\n case 'tool-call-args-delta':\n // We don't currently surface streaming args in the trail chip\n // (too noisy for the compact UI), but a future expanded view\n // could subscribe and render them. Logged under debug.\n debug('tool-call-args-delta', event);\n return;\n\n case 'tool-call-done':\n // Server-side tool finished. Mark complete in the trail so the\n // chip transitions from \"running\" to \"done\". Client-tool\n // resolution goes through chatSession.resolveToolCall instead.\n chatSession.updateToolCall(event.toolCallId, { status: 'done' });\n return;\n\n case 'a2ui':\n // A2UI events also flow via onA2UIEvent in the transport\n // constructor \u2014 that path is what applies the batch. This\n // duplicate event is the public mirror; ignore here.\n return;\n\n case 'error': {\n const status = event.status ?? null;\n const body = event.body ? String(event.body).slice(0, 200) : null;\n console.warn(\n `[chat-transport] error status=${status ?? 'no-status'} succeeded=${this._messagesSucceeded}`,\n event\n );\n // Route through the shared error-handling kernel so the\n // debounce / hasSucceeded gate / fallback path apply uniformly\n // regardless of whether the error came from AG-UI or a test seam.\n this._handleErrorEvent({\n message: event.message,\n status,\n body,\n errorName: event.errorName ?? null,\n });\n // The chip-level error chip (shown immediately, no debounce)\n // gives the user feedback even when we're still waiting to see\n // if the failure is sustained enough to swap to the fallback.\n chatSession.error(event.message ?? 'Chat connection failed');\n this._currentAssistantMessageId = null;\n // Tear AgUiTransport down so the next send re-acquires Turnstile\n // and re-opens. Avoids reusing a broken HttpAgent under us.\n if (this._agui) {\n this._agui.disconnect();\n this._agui = null;\n }\n if (this._transportUnsub) {\n this._transportUnsub();\n this._transportUnsub = null;\n }\n this._status = 'error';\n return;\n }\n }\n }\n}\n\n/**\n * The module-level singleton. Imported by both the SDK runtime\n * bootstrap (to call configure) and any code that needs to read\n * transport state. Mirrors the chatSession singleton shape.\n */\nexport const chatTransport = new ChatTransport();\n", "/**\n * Pure mapping from raw PostHog events to ObservationEvents.\n *\n * One function: matchEvent(raw, opts) \u2192 ObservationEvent | null. Null means\n * \"drop, not significant.\" This module is the single source of truth for what\n * the chat agent sees on the in-session timeline; the SDK observer never\n * forwards anything matchEvent returns null for.\n *\n * Kept dependency-free (no DOM access, no PostHog SDK imports) so the\n * Vitest unit tests run without any browser shim.\n */\n\nexport type ObservationKind =\n | 'nav'\n | 'click'\n | 'form'\n | 'rage'\n | 'dead'\n | 'scroll'\n | 'view'\n | 'idle'\n | 'hover'\n | 'hesitation'\n | 'custom';\n\nexport interface ObservationEvent {\n ts: number;\n kind: ObservationKind;\n text: string;\n ref?: string;\n}\n\n/** Shape of a raw event reaching matchEvent. Loose by design \u2014 PostHog's\n * event shape evolves, and we want matchEvent to be resilient to extra\n * properties. */\nexport interface RawEvent {\n event: string;\n timestamp: number;\n properties: Record<string, unknown>;\n}\n\nexport interface MatchOptions {\n /** Workspace-configured custom event names to forward as kind=\"custom\". */\n observableEvents?: readonly string[];\n}\n\nconst MAX_TEXT_LEN = 200;\nconst SIGNIFICANT_CLICK_TAGS = new Set(['button', 'a']);\n\nfunction truncate(s: string): string {\n return s.length <= MAX_TEXT_LEN ? s : `${s.slice(0, MAX_TEXT_LEN - 1)}\u2026`;\n}\n\nfunction firstElement(props: Record<string, unknown>): Record<string, unknown> | null {\n const els = props.$elements;\n if (Array.isArray(els) && els.length > 0 && typeof els[0] === 'object' && els[0] !== null) {\n return els[0] as Record<string, unknown>;\n }\n return null;\n}\n\nfunction elementText(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return '';\n const t = el.text;\n return typeof t === 'string' ? t.trim() : '';\n}\n\nfunction elementTag(props: Record<string, unknown>): string {\n const explicit = props.$element_tag_name;\n if (typeof explicit === 'string') return explicit.toLowerCase();\n const el = firstElement(props);\n if (el && typeof el.tag_name === 'string') return (el.tag_name as string).toLowerCase();\n return '';\n}\n\nfunction elementRole(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return '';\n const role = el.attr__role;\n return typeof role === 'string' ? role.toLowerCase() : '';\n}\n\nfunction formName(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return 'unnamed';\n const name = el.attr__name;\n if (typeof name === 'string' && name) return name;\n const id = el.attr__id;\n if (typeof id === 'string' && id) return id;\n return 'unnamed';\n}\n\nfunction isSignificantClickTarget(props: Record<string, unknown>): boolean {\n const tag = elementTag(props);\n if (SIGNIFICANT_CLICK_TAGS.has(tag)) return true;\n if (elementRole(props) === 'button') return true;\n return false;\n}\n\nfunction pathname(props: Record<string, unknown>): string {\n const pn = props.$pathname;\n return typeof pn === 'string' ? pn : '/';\n}\n\nfunction renderCustomEvent(raw: RawEvent): string {\n // Stable summary: event name + up to two scalar props.\n const fields: string[] = [];\n for (const [k, v] of Object.entries(raw.properties)) {\n if (k.startsWith('$')) continue;\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n fields.push(`${k}=${v}`);\n if (fields.length >= 2) break;\n }\n }\n return fields.length > 0 ? `${raw.event} (${fields.join(', ')})` : raw.event;\n}\n\nexport function matchEvent(raw: RawEvent, opts: MatchOptions = {}): ObservationEvent | null {\n const props = raw.properties;\n\n switch (raw.event) {\n case '$pageview': {\n const path = pathname(props);\n return {\n ts: raw.timestamp,\n kind: 'nav',\n text: truncate(`navigated to ${path}`),\n ref: path,\n };\n }\n\n case '$autocapture': {\n const eventType = props.$event_type;\n\n if (eventType === 'click') {\n if (!isSignificantClickTarget(props)) return null;\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'click',\n text: truncate(`clicked '${text}'`),\n };\n }\n\n if (eventType === 'submit' && elementTag(props) === 'form') {\n return {\n ts: raw.timestamp,\n kind: 'form',\n text: truncate(`submitted form '${formName(props)}'`),\n };\n }\n\n return null;\n }\n\n case '$rageclick': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'rage',\n text: truncate(`rage-clicked '${text}'`),\n };\n }\n\n case '$dead_click': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'dead',\n text: truncate(`clicked '${text}' (no response)`),\n };\n }\n\n // \u2500\u2500 Canonical runtime-bus events (sources: `'canvas'` instrumentation\n // or the event-processor's rrweb detectors). These don't go through\n // PostHog; the chat-bar's bus translator forwards them as-is with\n // the canonical event name, and matchEvent picks the right slot\n // here. Keeps a single allowlist as the source of truth for what\n // the agent's observation tail can carry.\n case 'nav.section_viewed': {\n const section = typeof props.section === 'string' ? props.section : '';\n if (!section) return null;\n return {\n ts: raw.timestamp,\n kind: 'view',\n text: truncate(`viewed the '${section}' section`),\n ref: section,\n };\n }\n\n case 'nav.scroll_depth': {\n const pct = typeof props.percent === 'number' ? props.percent : null;\n if (pct === null) return null;\n return {\n ts: raw.timestamp,\n kind: 'scroll',\n text: truncate(`scrolled to ${pct}% of the page`),\n };\n }\n\n case 'ui.scroll_thrash': {\n return {\n ts: raw.timestamp,\n kind: 'scroll',\n text: 'scrolled up and down repeatedly (looking for something)',\n };\n }\n\n case 'ui.idle': {\n const ms = typeof props.durationMs === 'number' ? props.durationMs : null;\n const secs = ms !== null ? Math.round(ms / 1000) : null;\n return {\n ts: raw.timestamp,\n kind: 'idle',\n text: secs !== null ? `idle for ${secs}s` : 'idle',\n };\n }\n\n case 'ui.hover': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'hover',\n text: truncate(`hovered on '${text}'`),\n };\n }\n\n case 'ui.hesitation': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'hesitation',\n text: truncate(`hesitated near '${text}'`),\n };\n }\n\n case 'ui.focus_bounce': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'form',\n text: truncate(`focused '${text}' but didn't fill it`),\n };\n }\n\n default: {\n const allow = opts.observableEvents ?? [];\n if (allow.includes(raw.event)) {\n return {\n ts: raw.timestamp,\n kind: 'custom',\n text: truncate(renderCustomEvent(raw)),\n };\n }\n return null;\n }\n }\n}\n", "/**\n * In-memory batching queue for ObservationEvents.\n *\n * Holds events until either a size threshold or a time interval triggers\n * a flush. The flush function is injected so transport choice (fetch vs.\n * sendBeacon) and auth wiring stay out of this module.\n *\n * Backoff strategy: pure exponential, starting at 1s and capping at 30s\n * (1s \u2192 2s \u2192 4s \u2192 8s \u2192 16s \u2192 30s). Reset on first successful flush.\n * Jitter is intentionally omitted \u2014 the observer queue is per-client, so\n * thundering-herd at recovery is not a meaningful risk, and deterministic\n * timing keeps unit tests fast and stable. A \"permanent\" failure (4xx\n * marked by the caller) disables the queue entirely \u2014 no further flushes\n * are attempted; lastError is exposed via stats().\n */\n\nimport type { ObservationEvent } from './allowlist';\n\nexport interface FlushError extends Error {\n /** When true, the queue stops trying forever. Set by transport for 4xx. */\n permanent?: boolean;\n}\n\nexport interface ObserverQueueOptions {\n batchSize: number;\n flushIntervalMs: number;\n queueCap: number;\n flush: (batch: ObservationEvent[]) => Promise<void>;\n backoffStartMs?: number;\n backoffCapMs?: number;\n}\n\nexport interface ObserverStats {\n queued: number;\n sent: number;\n dropped: number;\n lastError: string | null;\n disabled: boolean;\n}\n\nexport class ObserverQueue {\n private readonly _opts: Required<ObserverQueueOptions>;\n private readonly _buffer: ObservationEvent[] = [];\n private _sent = 0;\n private _dropped = 0;\n private _lastError: string | null = null;\n private _disabled = false;\n private _intervalTimer: ReturnType<typeof setTimeout> | null = null;\n private _backoffTimer: ReturnType<typeof setTimeout> | null = null;\n private _currentBackoffMs = 0;\n private _inFlight = false;\n\n constructor(opts: ObserverQueueOptions) {\n this._opts = {\n backoffStartMs: 1000,\n backoffCapMs: 30_000,\n ...opts,\n };\n }\n\n push(event: ObservationEvent): void {\n if (this._disabled) return;\n if (this._buffer.length >= this._opts.queueCap) {\n this._buffer.shift();\n this._dropped += 1;\n }\n this._buffer.push(event);\n\n if (this._buffer.length >= this._opts.batchSize) {\n this._scheduleImmediate();\n } else {\n this._scheduleInterval();\n }\n }\n\n async flushNow(): Promise<void> {\n this._clearInterval();\n await this._flush();\n }\n\n stats(): ObserverStats {\n return {\n queued: this._buffer.length,\n sent: this._sent,\n dropped: this._dropped,\n lastError: this._lastError,\n disabled: this._disabled,\n };\n }\n\n private _scheduleImmediate(): void {\n queueMicrotask(() => {\n void this._flush();\n });\n }\n\n private _scheduleInterval(): void {\n if (this._intervalTimer != null) return;\n this._intervalTimer = setTimeout(() => {\n this._intervalTimer = null;\n void this._flush();\n }, this._opts.flushIntervalMs);\n }\n\n private _clearInterval(): void {\n if (this._intervalTimer != null) {\n clearTimeout(this._intervalTimer);\n this._intervalTimer = null;\n }\n }\n\n private async _flush(): Promise<void> {\n if (this._disabled || this._inFlight || this._buffer.length === 0) return;\n this._clearInterval();\n\n const batch = this._buffer.splice(0, this._opts.batchSize);\n this._inFlight = true;\n try {\n await this._opts.flush(batch);\n this._sent += batch.length;\n this._currentBackoffMs = 0;\n this._lastError = null;\n } catch (err) {\n this._buffer.unshift(...batch);\n const perm = (err as FlushError)?.permanent === true;\n this._lastError =\n err instanceof Error ? err.message : String((err as { message?: unknown })?.message ?? err);\n if (perm) {\n this._disabled = true;\n } else {\n this._scheduleBackoff();\n }\n } finally {\n this._inFlight = false;\n }\n }\n\n private _scheduleBackoff(): void {\n const next =\n this._currentBackoffMs === 0\n ? this._opts.backoffStartMs\n : Math.min(this._currentBackoffMs * 2, this._opts.backoffCapMs);\n this._currentBackoffMs = next;\n\n if (this._backoffTimer != null) clearTimeout(this._backoffTimer);\n this._backoffTimer = setTimeout(() => {\n this._backoffTimer = null;\n void this._flush();\n }, next);\n }\n}\n", "/**\n * HTTP transport for the observer queue.\n *\n * Two send paths:\n * - send(batch) \u2014 async fetch. Used for normal flushes. Throws on\n * non-2xx; sets the FlushError.permanent flag for 4xx so the queue\n * stops trying.\n * - sendBeacon(batch) \u2014 fire-and-forget via navigator.sendBeacon.\n * Used on `pagehide` so the last batch survives navigation. No\n * error path \u2014 beacon failure is invisible by design.\n *\n * Auth: same syn_ Bearer token mechanism as /stream. The token is read\n * via a getter so SDK tokens that rotate live get refreshed naturally.\n */\n\nimport type { ObservationEvent } from './allowlist';\n\nexport interface TransportOptions {\n url: string;\n token: () => string;\n getDistinctId: () => string | null;\n getSessionId: () => string | null;\n}\n\nexport interface Transport {\n send(batch: ObservationEvent[]): Promise<void>;\n sendBeacon(batch: ObservationEvent[]): boolean;\n}\n\ninterface RequestBody {\n distinct_id: string;\n session_id: string;\n batch: ObservationEvent[];\n}\n\n/**\n * Build the POST body, or null when PostHog can't give us BOTH a distinct_id\n * and a session_id. The backend keys the visitor buffer by distinct_id and\n * scopes the live drain by session_id, so without both there is nothing to\n * write \u2014 we drop the batch rather than POST a request the backend would 422\n * (which the queue treats as a permanent disable). No fallback ids by design:\n * consent-denied / hard-cookieless visitors simply get no personalization.\n */\nfunction buildBody(\n distinctId: string | null,\n sessionId: string | null,\n batch: ObservationEvent[]\n): string | null {\n if (!distinctId || !sessionId) return null;\n const body: RequestBody = { distinct_id: distinctId, session_id: sessionId, batch };\n return JSON.stringify(body);\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n return {\n async send(batch: ObservationEvent[]): Promise<void> {\n const body = buildBody(opts.getDistinctId(), opts.getSessionId(), batch);\n // No PostHog ids \u2192 nothing to buffer. Drop silently (not an error, not a\n // permanent disable): a later flush may have ids once PostHog resolves.\n if (body === null) return;\n const resp = await fetch(opts.url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${opts.token()}`,\n 'Content-Type': 'application/json',\n },\n body,\n keepalive: true,\n credentials: 'include',\n });\n if (!resp.ok) {\n const err = new Error(`observation POST ${resp.status}`) as Error & {\n permanent?: boolean;\n };\n // 4xx is permanent (bad token, malformed payload, etc.) EXCEPT 429:\n // the rate-limit middleware buckets /api/adaptive by workspace token,\n // so a busy site hitting 200/min should back off, not give up forever.\n if (resp.status >= 400 && resp.status < 500 && resp.status !== 429) {\n err.permanent = true;\n }\n throw err;\n }\n },\n\n sendBeacon(batch: ObservationEvent[]): boolean {\n const body = buildBody(opts.getDistinctId(), opts.getSessionId(), batch);\n if (body === null) return false;\n const blob = new Blob([body], { type: 'application/json' });\n const beacon = navigator?.sendBeacon;\n if (typeof beacon !== 'function') return false;\n return beacon.call(navigator, opts.url, blob);\n },\n };\n}\n", "/**\n * Observer entry point.\n *\n * startObserver wires the four pieces \u2014 allowlist filter + queue +\n * transport + PostHog subscription \u2014 into a single lifecycle controlled\n * via the returned handle. The handle is reference-counted: multiple\n * call sites (e.g. multiple chatbot widgets on the same page) share\n * one observer.\n *\n * Idempotent: calling startObserver twice with equivalent options\n * returns the same instance. Calling stop() decrements the ref count;\n * the observer tears down only when the count reaches zero.\n */\n\nimport { matchEvent, type RawEvent } from './allowlist';\nimport { ObserverQueue, type ObserverStats } from './queue';\nimport { createTransport, type Transport } from './transport';\n\nexport interface StartObserverOptions {\n url: string;\n token: () => string;\n getDistinctId: () => string | null;\n getSessionId: () => string | null;\n observableEvents?: readonly string[];\n /** Test seam: override fetch/timer behavior by injecting a custom transport. */\n transport?: Transport;\n}\n\nexport interface ObserverHandle {\n stop(): void;\n stats(): ObserverStats;\n /** Test seam: ingest a raw event directly without depending on PostHog being loaded. */\n ingest(raw: RawEvent): void;\n flushNow(): Promise<void>;\n}\n\ninterface ActiveObserver {\n refCount: number;\n queue: ObserverQueue;\n unsubscribe: () => void;\n options: StartObserverOptions;\n}\n\nlet _active: ActiveObserver | null = null;\n\nfunction _attachPostHog(\n ingest: (raw: RawEvent) => void,\n _observableEvents: readonly string[]\n): () => void {\n const ph = (globalThis as { posthog?: unknown }).posthog;\n if (!ph) return () => {};\n\n // PostHog's internal hook for \"an event was just captured\". The hook\n // fires for $pageview, $autocapture, $rageclick, $dead_click, and any\n // custom posthog.capture(name, props) call \u2014 exactly what the observer\n // wants. Used by the runtime SDK's bundled dist (smart-canvas.*.js).\n const addHook = (ph as { _addCaptureHook?: unknown })._addCaptureHook;\n if (typeof addHook !== 'function') return () => {};\n\n const handler = (eventName: string, properties: Record<string, unknown> | undefined) => {\n if (typeof eventName !== 'string') return;\n ingest({\n event: eventName,\n timestamp: Date.now(),\n properties: properties ?? {},\n });\n };\n\n // _addCaptureHook returns void in current PostHog SDK versions (no\n // unsubscribe). We accept that the listener leaks for the page lifetime \u2014\n // disabling it lives on the queue's `_disabled` flag instead.\n (addHook as (cb: typeof handler) => void).call(ph, handler);\n return () => {};\n}\n\nfunction _attachPageHide(_transport: Transport, queue: ObserverQueue): () => void {\n const handler = () => {\n const stats = queue.stats();\n if (stats.queued > 0) {\n void queue.flushNow();\n }\n };\n window.addEventListener('pagehide', handler, { capture: true });\n return () => window.removeEventListener('pagehide', handler, { capture: true });\n}\n\nexport function startObserver(opts: StartObserverOptions): ObserverHandle {\n if (_active) {\n _active.refCount += 1;\n return _makeHandle();\n }\n\n const transport = opts.transport ?? createTransport(opts);\n\n const queue = new ObserverQueue({\n batchSize: 10,\n flushIntervalMs: 2000,\n queueCap: 200,\n flush: (batch) => transport.send(batch),\n });\n\n const ingest = (raw: RawEvent) => {\n const ev = matchEvent(raw, { observableEvents: opts.observableEvents });\n if (ev !== null) {\n queue.push(ev);\n }\n };\n\n const unsubscribePh = _attachPostHog(ingest, opts.observableEvents ?? []);\n const unsubscribePageHide = _attachPageHide(transport, queue);\n\n _active = {\n refCount: 1,\n queue,\n unsubscribe: () => {\n unsubscribePh();\n unsubscribePageHide();\n },\n options: opts,\n };\n\n return _makeHandle();\n}\n\nfunction _makeHandle(): ObserverHandle {\n return {\n stop(): void {\n if (!_active) return;\n _active.refCount -= 1;\n if (_active.refCount <= 0) {\n _active.unsubscribe();\n _active = null;\n }\n },\n stats(): ObserverStats {\n return (\n _active?.queue.stats() ?? {\n queued: 0,\n sent: 0,\n dropped: 0,\n lastError: null,\n disabled: true,\n }\n );\n },\n ingest(raw: RawEvent): void {\n if (!_active) return;\n const ev = matchEvent(raw, {\n observableEvents: _active.options.observableEvents,\n });\n if (ev !== null) _active.queue.push(ev);\n },\n flushNow(): Promise<void> {\n return _active?.queue.flushNow() ?? Promise.resolve();\n },\n };\n}\n\n/** Test-only: reset module singleton state. */\nexport function _resetObserverForTests(): void {\n if (_active) {\n _active.unsubscribe();\n _active = null;\n }\n}\n", "/**\n * AdaptiveChatBarMountable \u2014 `MountableWidget` adapter that turns the\n * standalone `<adaptive-chat-bar>` Lit element into something the\n * runtime widget registry can mount.\n *\n * Registered as widget id `adaptive-chatbot:chat-bar`. Customers\n * reference it from canvas config \u2014 either as a slot's `lid` widget\n * (replaces the launcher when referenced from `slots.drawer.lid`) or\n * as a regular tile widget.\n *\n * The bar is a VIEW. State lives in the singleton `chatSession` \u2014\n * whether the bar mounts in the mini-canvas lid, the drawer lid, or\n * both, they're all views of the same conversation. The mountable:\n * - subscribes to chatSession.subscribe() and pushes state into\n * the bar's `messages` + `inFlight` props on every change\n * - routes the bar's `chat-message-sent` event \u2192 chatSession.send()\n * - routes the bar's `chat-interrupt` event \u2192 chatSession.interrupt()\n * - bubbles the bar's `canvas-close` event \u2192 optional onClose\n * callback (canvas-level concern, not session-level)\n *\n * Props (passed via mountConfig):\n * - `placeholder?: string` \u2014 input placeholder copy\n * - `onClose?: () => void` \u2014 fires on \u2715 click (canvas-level)\n *\n * Note: messages and inFlight are NOT props. They flow from chatSession.\n * A canvas-config author who wants to pre-seed messages should do so\n * via the session directly (e.g. via a startup action) \u2014 but typical\n * use is to let the conversation start empty.\n */\n\nimport './AdaptiveChatBar';\nimport type { AdaptiveChatBar } from './AdaptiveChatBar';\nimport { renderFallbackHtml } from './ChatAssistantLit';\nimport type { Unsubscribe } from './ChatSession';\nimport { chatSession } from './ChatSession';\nimport type { ChatTransportConfig } from './ChatTransport';\nimport { chatTransport } from './ChatTransport';\nimport {\n ActionHandler,\n ElementInstanceStore,\n type ElementMutation,\n fetchMountedElements,\n ItemHandler,\n TileHandler,\n} from './elements';\nimport { startObserver } from './observer';\nimport type { ChatbotFallback, ChatbotWidgetRuntime } from './types.js';\n\ninterface ChatBarMountConfig {\n placeholder?: string;\n /** Initial assistant greeting shown before any real conversation. */\n greeting?: string;\n /**\n * Pre-conversation tap-target rendered alongside the greeting when\n * the trail is empty. `label` is the button copy; `prompt` is what\n * gets sent through the normal chat-send path on tap.\n */\n introSuggestion?: { label: string; prompt: string };\n /** Forward to AdaptiveChatBar.forceExpanded (full-screen surfaces). */\n forceExpanded?: boolean;\n onClose?: () => void;\n /**\n * Backend host for the live chat transport. Same shape as\n * ChatbotConfig.backendUrl. When provided alongside `runtime`, the\n * bar configures the singleton ChatTransport on first mount so\n * sends hit the real `/api/adaptive/stream` SSE pipeline. Omitting\n * either disables the transport \u2014 the bar stays a pure view and\n * nothing replies. Useful for storybook / config-preview surfaces.\n */\n backendUrl?: string;\n /** Runtime injected by WidgetRegistry \u2014 required for backendUrl wiring. */\n runtime?: ChatbotWidgetRuntime;\n /** Optional thread id for conversation continuity across reloads. */\n threadId?: string;\n /**\n * Per-customer \"chat unavailable\" card. Rendered in place of the\n * chat bar when the transport gives up after sustained failure.\n * Mirrors ChatAssistantLit's fallback behaviour.\n */\n fallback?: ChatbotFallback;\n /**\n * Declarations for the LLM-authored UI element pipeline (Phase 5+).\n * When `elementsEnabled === true` AND `uiTemplates` is non-null, the\n * backend exposes `mount_element` / `patch_element` / `unmount_element`\n * tools to the chat agent, scoped to the templates declared here.\n *\n * Shape mirrors `UiTemplatesBlock` from `syntrologie_common.sdk.templates`\n * \u2014 typed loosely on the SDK side because the SDK never introspects\n * templates (it only receives mount/patch/unmount mutations); the\n * backend Pydantic models are the validation gate.\n *\n * Passed verbatim as `forwardedProps.uiTemplates` to the AG-UI\n * transport so the backend's `/api/adaptive/stream` reads them off\n * the inbound request body.\n */\n uiTemplates?: Record<string, unknown>;\n elementsEnabled?: boolean;\n /**\n * Slot name the runtime mounted this chat-bar into (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Injected by the host SDK slot components\n * (SyntroCanvasOverlay for the drawer, SyntroInlineSlot for inline\n * slots) so the chat-bar can forward it to the backend as\n * ``X-Active-Lid-Slot``. The backend uses it to mount tiles into the\n * canvas spatially nearest to the lid the visitor is engaging with.\n * Optional \u2014 older host bundles that don't inject this still work;\n * the backend falls back to the template's static default_slot.\n */\n _syntroSlotName?: string;\n}\n\ninterface MountState {\n bar: AdaptiveChatBar;\n cleanup: () => void;\n cfg: ChatBarMountConfig;\n}\n\nconst STATE_KEY = '__syntroChatBarMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyPlaceholder(bar: AdaptiveChatBar, cfg: ChatBarMountConfig): void {\n if (cfg.placeholder !== undefined) bar.placeholder = cfg.placeholder;\n if (cfg.greeting !== undefined) bar.greeting = cfg.greeting;\n bar.introSuggestion = cfg.introSuggestion;\n // Toggle independently \u2014 undefined means \"leave whatever the element\n // currently has\". Boolean cast keeps the default at false on first\n // mount when the field is absent.\n bar.forceExpanded = cfg.forceExpanded === true;\n}\n\n/**\n * Configure the singleton transport if the caller supplied a backend\n * URL + runtime. Idempotent \u2014 second mount with same args is a no-op.\n * Missing backendUrl OR runtime leaves the transport untouched (the\n * bar is then a pure local view; useful for previews / storybook).\n *\n * Spread (not cherry-pick) so the bar-only fields (placeholder,\n * onClose) flow through silently; ChatTransport ignores them. Cast\n * narrows after the guard.\n */\n/**\n * Lazily-constructed ElementInstanceStore singleton for the chat-bar\n * surface. Mounted on first configure with `elementsEnabled` so the\n * `runtime` closure is captured; subsequent reconfigures with the same\n * runtime reuse it. ChatAssistantLit owns its own store separately \u2014\n * each surface keeps independent state to avoid cross-surface\n * double-mounts on the same instance_id.\n */\nlet _elementStore: ElementInstanceStore | null = null;\n/**\n * Live ``template_id \u2192 widget`` map. Re-derived on each ``configure()``\n * from the chat-bar's ``uiTemplates`` prop (which mirrors what the admin\n * declared in canvas-config). Both the TileHandler (live mount path) and\n * the ElementInstanceStore (rehydrate replay path) read through this map\n * so the widget id stays consistent regardless of mount provenance.\n *\n * Without this, an LLM-authored mount with ``template_id: \"product-card\"``\n * emits ``widget: \"product-card\"`` to the runtime, which then renders the\n * tile chrome with a \"Widget not available: product-card\" body because\n * the actual widget is registered as ``adaptive-product:card``.\n */\nconst _templateWidgetMap = new Map<string, string>();\n\nfunction resolveTileWidget(templateId: string): string | undefined {\n return _templateWidgetMap.get(templateId);\n}\n\nfunction refreshTemplateWidgetMap(uiTemplates: Record<string, unknown> | undefined): void {\n _templateWidgetMap.clear();\n if (!uiTemplates) return;\n const tiles = (uiTemplates as { tiles?: Array<{ id?: unknown; widget?: unknown }> }).tiles;\n if (!Array.isArray(tiles)) return;\n for (const t of tiles) {\n const id = typeof t?.id === 'string' ? t.id : null;\n const widget = typeof t?.widget === 'string' ? t.widget : null;\n if (id && widget) _templateWidgetMap.set(id, widget);\n }\n}\n\nfunction getOrCreateElementStore(runtime: ChatbotWidgetRuntime): ElementInstanceStore {\n if (_elementStore) return _elementStore;\n _elementStore = new ElementInstanceStore({\n actions: runtime.actions,\n // Pass the runtime's event bus so ItemHandler can broadcast\n // `element.compositional_append` / `_patch` / `_remove` events\n // to container widgets (chips strip, FAQ accordion, nav tips).\n events: {\n publish: runtime.events.publish.bind(runtime.events),\n subscribe: runtime.events.subscribe?.bind(runtime.events),\n },\n handlers: [new TileHandler(resolveTileWidget), new ActionHandler(), new ItemHandler()],\n resolveTileWidget,\n });\n return _elementStore;\n}\n\n/**\n * Track whether we've already hydrated this store's snapshot. The store\n * itself is a singleton across mounts in the same page session, so we\n * want to hydrate exactly ONCE \u2014 repeated mounts (e.g. after an SPA\n * navigation that unmounts + remounts the chat-bar) reuse the warm\n * store without re-firing handler.mount() for every persisted item.\n *\n * The store's own version-dedup also prevents double-application, but\n * we still don't want to issue redundant HTTP requests on every mount.\n */\nlet _hydrationStarted = false;\n\nfunction hydrateOnce(runtime: ChatbotWidgetRuntime, backendUrl: string): void {\n if (_hydrationStarted) return;\n _hydrationStarted = true;\n const store = getOrCreateElementStore(runtime);\n // The fetcher reads `window.__SYNTRO_CONFIG__.token` by default; the\n // boot path already populated that. Empty/missing backendUrl falls\n // back to a same-origin relative endpoint so dev-server proxies\n // (Vite, Webpack) and host pages serving the SDK from their own\n // domain work without extra config. Same-origin is also the only\n // path that lets the `syntro_chat_session` cookie ride along \u2014 Lax\n // cookies don't follow cross-origin fetches.\n const trimmed = backendUrl.replace(/\\/$/, '');\n const endpoint = trimmed\n ? `${trimmed}/api/adaptive/mounted_elements`\n : '/api/adaptive/mounted_elements';\n fetchMountedElements({ endpoint }).then((response) => {\n if (!response) return; // 404 / network error / feature off \u2014 silent no-op\n // Hydrate replays each instance through its handler.mount(); for\n // ItemHandler that publishes `element.compositional_append` events,\n // which the chips strip subscribes to and re-inserts. Effects are\n // NOT replayed \u2014 they were never persisted in mounted_elements\n // (`_emit_effect_envelope` in the agent skips persistence).\n void store.hydrate(response.mounted_elements);\n });\n}\n\nfunction configureTransportIfPossible(cfg: ChatBarMountConfig): void {\n // Backend URL comes from `runtime.backendUrl` \u2014 the single source of\n // truth set once via `Syntro.init({backendUrl})` (or its SDK-internal\n // prod default if the customer doesn't pass one). The tile's\n // `props.backendUrl` is ignored: there is no per-widget override, the\n // customer integrator chooses the host ONCE at init time and every\n // adaptive uses it.\n if (!cfg.runtime) return;\n const backendUrl = (cfg.runtime as { backendUrl?: string }).backendUrl;\n if (!backendUrl) return;\n // Translate the element-instantiation declarations into the opaque\n // `forwardedProps` bag the transport ships on every AG-UI request.\n // Only attach when the feature is on AND templates are declared \u2014\n // otherwise the backend stays in its safe-default (feature_disabled)\n // path and the tools are never exposed.\n const elementsActive = cfg.elementsEnabled === true && cfg.uiTemplates != null;\n // Refresh the template\u2192widget map on every configure (and clear it\n // when elements are off) so live mounts and replays resolve the same\n // widget id. Done before getOrCreateElementStore below since the\n // store reads through ``resolveTileWidget`` at construction.\n refreshTemplateWidgetMap(elementsActive ? cfg.uiTemplates : undefined);\n const forwardedProps: Record<string, unknown> | undefined = elementsActive\n ? { elementsEnabled: true, uiTemplates: cfg.uiTemplates }\n : undefined;\n\n // Wire the `syntro.element.mutation` envelope route to a per-surface\n // ElementInstanceStore. The store applies mounts/patches/unmounts to\n // the host page via the runtime's ActionEngine. ChatAssistantLit has\n // its own equivalent wiring (it instantiates AgUiTransport directly,\n // not via this singleton); the lid surface needs the same routing\n // here so mount_element results actually land.\n const runtime = cfg.runtime;\n const onElementMutation = elementsActive\n ? (mutations: ElementMutation[]) => {\n void getOrCreateElementStore(runtime).apply(mutations);\n }\n : undefined;\n\n // Hydrate the element store from the backend session on first chat-bar\n // mount. Async \u2014 by the time the response arrives, container widgets\n // (chips strip, FAQ accordion) have already subscribed to the event\n // bus, so the replay events land in their subscribers. Items mounted\n // by the LLM in previous turns survive SPA navigation + page reload\n // for the lifetime of the AdaptiveSession (~24h default).\n if (elementsActive) {\n hydrateOnce(runtime, backendUrl);\n }\n\n chatTransport.configure({\n ...cfg,\n backendUrl,\n forwardedProps,\n onElementMutation,\n activeLidSlot: cfg._syntroSlotName,\n } as ChatTransportConfig);\n\n // Wire the visitor-activity observer once the transport is configured.\n // The observer subscribes to PostHog's capture hook and POSTs batched\n // `nav` / `click` / `form` / `rage` / `dead` events to\n // `/api/adaptive/observation` so the next ``/stream`` turn arrives\n // with `recent_observations` populated \u2014 that's what answers\n // \"what did the visitor just do?\" from the agent's perspective.\n // Without this the observer module is dead code: events sit in\n // PostHog with no path into the agent prompt.\n //\n // Idempotent + ref-counted in `startObserver`, so multiple chat-bar\n // mounts (drawer lid + page anchor) share one observer.\n startObserverIfPossible(cfg);\n}\n\nlet _observerStarted = false;\n\nfunction startObserverIfPossible(cfg: ChatBarMountConfig): void {\n if (_observerStarted) return;\n if (typeof window === 'undefined') return;\n const runtimeRef = cfg.runtime as\n | undefined\n | {\n events?: { subscribe?: (filter: unknown, cb: (e: unknown) => void) => () => void };\n backendUrl?: string;\n telemetry?: {\n getDistinctId?: () => string | undefined;\n getSessionId?: () => string | undefined;\n };\n };\n if (!runtimeRef?.events?.subscribe) return;\n // Read backendUrl from the runtime \u2014 same source of truth as the chat\n // transport, so the observer always hits the same backend instance.\n const trimmed = (runtimeRef.backendUrl ?? '').replace(/\\/$/, '');\n const url = trimmed ? `${trimmed}/api/adaptive/observation` : '/api/adaptive/observation';\n // distinct_id (visitor, cross-session) + session_id (this browsing session)\n // from the SYNTRO RUNTIME's telemetry (the canonical id accessor \u2014 not\n // window.posthog). The backend keys the observation buffer by distinct_id and\n // scopes the live drain by session_id. Both null when the runtime has no id\n // (consent denied / cookieless) \u2014 the transport then drops the batch (no\n // fallback ids, cold personalization by design).\n const runtimeId = (method: 'getDistinctId' | 'getSessionId'): string | null => {\n try {\n const v = runtimeRef.telemetry?.[method]?.();\n return typeof v === 'string' && v.length > 0 ? v : null;\n } catch {\n return null;\n }\n };\n const getDistinctId = (): string | null => runtimeId('getDistinctId');\n const getSessionId = (): string | null => runtimeId('getSessionId');\n const token = (): string => {\n const c = (window as { __SYNTRO_CONFIG__?: { token?: string } }).__SYNTRO_CONFIG__;\n return typeof c?.token === 'string' ? c.token : '';\n };\n // startObserver's PostHog auto-attach is a no-op in environments where\n // `window.posthog` isn't directly exposed (most production builds \u2014\n // PostHog is wrapped by the SDK telemetry layer and surfaced through\n // `SynOS.runtime.events`, not via the global). We always start it for\n // the queue + transport plumbing, then subscribe to the runtime event\n // bus and translate normalized events back into the `RawEvent` shape\n // the observer's allowlist expects.\n const handle = startObserver({ url, token, getDistinctId, getSessionId });\n // Expose queue stats on the window for in-page diagnostics. Lets a\n // tester verify events are queueing / flushing via the devtools\n // console without bouncing into source. Cheap; harmless in prod.\n (window as { __syntroObserverStats?: () => unknown }).__syntroObserverStats = () =>\n handle.stats();\n runtimeRef.events.subscribe({}, (evt: unknown) => {\n const e = evt as {\n ts?: number;\n name?: string;\n source?: string;\n props?: Record<string, unknown> & { originalEvent?: string };\n };\n if (!e?.name) return;\n const ts = typeof e.ts === 'number' ? e.ts : Date.now();\n // Two-path translation. The allowlist's `matchEvent` switches on\n // `event` name, so we just hand it the right name in either case:\n //\n // 1. PostHog-originated events arrive with `source: 'posthog'`\n // and `props.originalEvent` carrying the raw `$pageview` /\n // `$autocapture` name. Re-prefix `pathname`/`url` to their\n // `$`-prefixed forms so the PostHog matchers find them.\n // 2. Canonical runtime-bus events (`nav.section_viewed`,\n // `nav.scroll_depth`, `ui.scroll_thrash`, `ui.hover`, \u2026)\n // come straight from runtime-sdk instrumentation. Forward the\n // canonical name as-is \u2014 the allowlist has explicit cases for\n // each one.\n if (e.source === 'posthog') {\n const original = e.props?.originalEvent;\n if (typeof original !== 'string' || original.length === 0) return;\n const properties: Record<string, unknown> = { ...(e.props ?? {}) };\n if (typeof e.props?.pathname === 'string') properties.$pathname = e.props.pathname;\n if (typeof e.props?.url === 'string') properties.$current_url = e.props.url;\n handle.ingest({ event: original, timestamp: ts, properties });\n return;\n }\n // Forward canonical names directly. The allowlist drops any name\n // it doesn't know, so listing everything here is safe \u2014 match\n // decides what reaches the agent's observation tail.\n handle.ingest({\n event: e.name,\n timestamp: ts,\n properties: { ...(e.props ?? {}) },\n });\n });\n _observerStarted = true;\n}\n\nfunction wireListeners(bar: AdaptiveChatBar, state: MountState): Unsubscribe {\n const onMessageSent = (e: Event) => {\n const text = (e as CustomEvent<{ text: string }>).detail.text;\n // Read `_syntroSlotName` from `state.cfg` (the per-bar snapshot)\n // on EVERY send so the singleton transport tags the outbound\n // request with THIS bar's slot, regardless of which bar most\n // recently called `chatTransport.configure()`. Without this,\n // two coexisting bars (drawer + inline) race over the singleton's\n // cached `activeLidSlot` and tile-routing follows the wrong bar.\n chatSession.send(text, { activeLidSlot: state.cfg._syntroSlotName });\n // If no transport is listening for sends (no backendUrl in\n // mountConfig, the runtime injection didn't happen, or a test\n // didn't wire one up) the session would sit in `inFlight: true`\n // forever. Surface a clear, actionable error so the user sees\n // *something* rather than an indefinitely-spinning stop button.\n if (!chatSession.hasTransport()) {\n chatSession.error('Chat backend not configured \u2014 set backendUrl in the canvas config.');\n }\n };\n const onInterrupt = () => {\n chatSession.interrupt();\n };\n const onToolCallApproved = (e: Event) => {\n const detail = (e as CustomEvent<{ toolCallId: string; approved: boolean }>).detail;\n // Default to an empty-object result \u2014 the agent re-runs with the\n // approval signal. Hosts that want richer results (e.g. a form\n // result payload) can listen for `trail-toolcall-approved` higher\n // up and call chatSession.resolveToolCall themselves.\n chatSession.resolveToolCall(detail.toolCallId, {}, detail.approved);\n };\n // onClose reads state.cfg fresh on each invocation so update() can\n // swap the callback without re-wiring listeners.\n const onClose = () => {\n state.cfg.onClose?.();\n };\n bar.addEventListener('chat-message-sent', onMessageSent);\n bar.addEventListener('chat-interrupt', onInterrupt);\n bar.addEventListener('canvas-close', onClose);\n bar.addEventListener('trail-toolcall-approved', onToolCallApproved);\n return () => {\n bar.removeEventListener('chat-message-sent', onMessageSent);\n bar.removeEventListener('chat-interrupt', onInterrupt);\n bar.removeEventListener('canvas-close', onClose);\n bar.removeEventListener('trail-toolcall-approved', onToolCallApproved);\n };\n}\n\nexport const AdaptiveChatBarMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as ChatBarMountConfig;\n configureTransportIfPossible(cfg);\n const bar = document.createElement('adaptive-chat-bar') as AdaptiveChatBar;\n applyPlaceholder(bar, cfg);\n\n // Subscribe to the shared session. Fires immediately with the\n // current state so the bar reflects any pre-existing conversation.\n const unsubSession = chatSession.subscribe((s) => {\n bar.messages = [...s.messages];\n bar.inFlight = s.inFlight;\n bar.thinkingText = s.thinkingText;\n });\n\n // state holds the mutable cfg so update() can swap callbacks\n // without forcing a listener re-wire.\n const state = { bar, cleanup: () => {}, cfg };\n const unwireListeners = wireListeners(bar, state);\n\n container.appendChild(bar);\n\n // Subscribe to the transport's fallback signal. When the transport\n // gives up after sustained failure, replace the bar with the\n // per-customer \"chat unavailable\" card. One-shot \u2014 fallback fires\n // once per configure cycle, so we don't need to track re-mounts.\n const unsubFallback = chatTransport.onFallback(() => {\n bar.remove();\n container.innerHTML = renderFallbackHtml(state.cfg.fallback);\n });\n\n state.cleanup = () => {\n unsubSession();\n unsubFallback();\n unwireListeners();\n bar.remove();\n setState(container, null);\n };\n\n setState(container, state);\n return state.cleanup;\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as ChatBarMountConfig;\n configureTransportIfPossible(cfg);\n applyPlaceholder(state.bar, cfg);\n state.cfg = cfg;\n },\n};\n", "/**\n * AdaptiveChipsStripMountable \u2014 `MountableWidget` adapter for\n * `<adaptive-chips-strip>`. Registered as widget id\n * `adaptive-chatbot:chips-strip`.\n *\n * Mirrors `AdaptiveChatBarMountable`: creates the Lit element, forwards\n * props, bridges DOM events \u2192 prop callbacks, cleans up on unmount.\n *\n * Props (passed via mountConfig):\n * - `chips: SuggestionChip[]` \u2014 the strip's contents (required)\n * - `onChipRevealed?: ({id, payload}) => void` \u2014 fires when a chip\n * is opened\n * - `onChipDismissed?: ({id}) => void` \u2014 fires when \u00D7 is clicked\n *\n * The runtime registry injects `runtime` into mountConfig (see\n * `WidgetRegistry.mount`). We forward it as `runtimeRef` on the strip\n * so it can mount chip payload widgets through the same registry.\n */\n\nimport './AdaptiveChipsStrip';\nimport type { AdaptiveChipsStrip, SuggestionChip } from './AdaptiveChipsStrip';\n\ninterface ChipsStripMountConfig {\n chips?: SuggestionChip[];\n onChipRevealed?: (detail: { id: string; payload: SuggestionChip['config']['payload'] }) => void;\n onChipDismissed?: (detail: { id: string }) => void;\n // Injected by WidgetRegistry \u2014 see runtime-sdk/src/widgets/WidgetRegistry.ts.\n runtime?: unknown;\n // Injected by SyntroTileCard from the tile's resolved chromeless\n // state (which itself comes from `slot.theme.chromeless` with\n // `tile.chromeless` as the per-tile override).\n chromeless?: boolean;\n}\n\ninterface MountState {\n strip: AdaptiveChipsStrip;\n listeners: {\n revealed: (e: Event) => void;\n dismissed: (e: Event) => void;\n };\n}\n\nconst STATE_KEY = '__syntroChipsStripMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyProps(strip: AdaptiveChipsStrip, cfg: ChipsStripMountConfig): void {\n if (cfg.chips !== undefined) strip.chips = cfg.chips;\n // `runtime` arrives in every mountConfig from the WidgetRegistry \u2014\n // forward it so the strip can resolve + mount payload widgets.\n if (cfg.runtime !== undefined) {\n strip.runtimeRef = cfg.runtime as AdaptiveChipsStrip['runtimeRef'];\n }\n if (cfg.chromeless !== undefined) strip.chromeless = cfg.chromeless;\n}\n\nexport const AdaptiveChipsStripMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as ChipsStripMountConfig;\n const strip = document.createElement('adaptive-chips-strip') as AdaptiveChipsStrip;\n applyProps(strip, cfg);\n\n const state: MountState = {\n strip,\n listeners: {\n revealed: (e) => {\n const cb = cfg.onChipRevealed;\n if (cb) {\n cb(\n (e as CustomEvent<{ id: string; payload: SuggestionChip['config']['payload'] }>)\n .detail\n );\n }\n },\n dismissed: (e) => {\n const cb = cfg.onChipDismissed;\n if (cb) cb((e as CustomEvent<{ id: string }>).detail);\n },\n },\n };\n strip.addEventListener('chip-revealed', state.listeners.revealed);\n strip.addEventListener('chip-dismissed', state.listeners.dismissed);\n\n container.appendChild(strip);\n setState(container, state);\n\n return () => {\n strip.removeEventListener('chip-revealed', state.listeners.revealed);\n strip.removeEventListener('chip-dismissed', state.listeners.dismissed);\n strip.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as ChipsStripMountConfig;\n applyProps(state.strip, cfg);\n // Re-wire callback listeners so the new cfg's handlers fire.\n state.strip.removeEventListener('chip-revealed', state.listeners.revealed);\n state.strip.removeEventListener('chip-dismissed', state.listeners.dismissed);\n state.listeners.revealed = (e) => {\n const cb = cfg.onChipRevealed;\n if (cb) {\n cb((e as CustomEvent<{ id: string; payload: SuggestionChip['config']['payload'] }>).detail);\n }\n };\n state.listeners.dismissed = (e) => {\n const cb = cfg.onChipDismissed;\n if (cb) cb((e as CustomEvent<{ id: string }>).detail);\n };\n state.strip.addEventListener('chip-revealed', state.listeners.revealed);\n state.strip.addEventListener('chip-dismissed', state.listeners.dismissed);\n },\n};\n", "/**\n * NavLinkMountable \u2014 `MountableWidget` used as the payload of an\n * LLM-authored navigation chip.\n *\n * Flow:\n * LLM mounts `suggest-navigation` ItemTemplate with `{title, url}`\n * \u2192 backend builds chip with payload `{widget: 'adaptive-chatbot:nav-link', props: {url}}`\n * \u2192 user clicks the chip \u2192 chips-strip mounts THIS widget into the\n * chip's drawer\n * \u2192 user clicks the \"Go to <url>\" button this widget renders\n * \u2192 same-origin SPA navigation via pushState + popstate (matches\n * `adaptive-nav`'s `executeNavigate` path for SPA-router compatibility)\n *\n * Registered as widget id `adaptive-chatbot:nav-link`.\n *\n * Security note: only http(s), same-origin destinations are honored.\n * `javascript:`, `data:`, and cross-origin URLs are silently dropped at\n * URL construction. The ItemTemplate's EnumField allowlist is the\n * primary constraint; this is defense-in-depth.\n */\n\ninterface NavLinkProps {\n url?: string;\n /** Optional override for the button label. Defaults to \"Go to <url>\".\n * The chip's title already advertises the destination; this is just\n * the call-to-action verb. */\n label?: string;\n}\n\ninterface MountState {\n button: HTMLButtonElement;\n cfg: NavLinkProps;\n onClick: (e: Event) => void;\n}\n\nconst STATE_KEY = '__syntroNavLinkMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction navigateTo(rawUrl: string): void {\n if (!rawUrl) return;\n let resolved: URL;\n try {\n resolved = new URL(rawUrl, window.location.origin);\n } catch {\n return;\n }\n if (resolved.origin !== window.location.origin) return;\n if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return;\n window.history.pushState(null, '', resolved.toString());\n window.dispatchEvent(new PopStateEvent('popstate'));\n}\n\nfunction buildButton(cfg: NavLinkProps): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.dataset.syntroNavLink = '';\n button.style.display = 'inline-flex';\n button.style.alignItems = 'center';\n button.style.gap = '6px';\n button.style.padding = '6px 12px';\n button.style.borderRadius = '8px';\n button.style.fontFamily = \"var(--sc-font-family, 'system-ui')\";\n button.style.fontSize = '12px';\n button.style.fontWeight = '600';\n button.style.cursor = 'pointer';\n button.style.color = 'var(--sc-accent-foreground, currentColor)';\n button.style.background = 'hsl(var(--sc-accent-color) / 0.85)';\n button.style.border = '1px solid hsl(var(--sc-accent-color) / 0.30)';\n applyLabel(button, cfg);\n return button;\n}\n\nfunction applyLabel(button: HTMLButtonElement, cfg: NavLinkProps): void {\n const url = String(cfg.url ?? '');\n const label = cfg.label ?? (url ? `Go to ${url}` : 'Go');\n // textContent (not innerHTML) \u2014 LLM-authored URLs are an enum on the\n // backend so injection isn't realistic, but defense-in-depth is cheap.\n button.textContent = label;\n}\n\nexport const NavLinkMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as NavLinkProps;\n const button = buildButton(cfg);\n const onClick = (_e: Event): void => {\n const current = getState(container);\n const url = current?.cfg.url ?? cfg.url;\n navigateTo(String(url ?? ''));\n };\n button.addEventListener('click', onClick);\n container.appendChild(button);\n setState(container, { button, cfg, onClick });\n return () => {\n button.removeEventListener('click', onClick);\n button.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as NavLinkProps;\n applyLabel(state.button, cfg);\n state.cfg = cfg;\n },\n};\n", "/**\n * TextAnswerMountable \u2014 `MountableWidget` for the simplest chip payload\n * kind: a single paragraph of body text.\n *\n * Registered as widget id `adaptive-chatbot:text-answer`. Used by\n * `AdaptiveChipsStrip` when a chip's payload references it.\n *\n * Replaces the old hand-rolled resolver path. Customers wanting richer\n * payloads (markdown, mini-product cards, embedded charts, etc.) ship\n * their own mountable through the same registry \u2014 no special\n * resolver-map seam.\n */\n\ninterface TextAnswerProps {\n text?: string;\n}\n\ninterface MountState {\n paragraph: HTMLParagraphElement;\n cfg: TextAnswerProps;\n}\n\nconst STATE_KEY = '__syntroTextAnswerMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyText(p: HTMLParagraphElement, text: string): void {\n p.textContent = text;\n}\n\nexport const TextAnswerMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as TextAnswerProps;\n const paragraph = document.createElement('p');\n paragraph.dataset.syntroTextAnswer = '';\n // Keep the styling minimal \u2014 paragraph inherits the slot's\n // `--sc-tile-text-color` (set by the chips strip's drawer chrome)\n // so the text reads consistently against the host's surface.\n paragraph.style.margin = '0';\n paragraph.style.fontSize = '12px';\n paragraph.style.lineHeight = '1.55';\n paragraph.style.color = 'var(--sc-tile-text-color, currentColor)';\n applyText(paragraph, String(cfg.text ?? ''));\n container.appendChild(paragraph);\n\n setState(container, { paragraph, cfg });\n return () => {\n paragraph.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as TextAnswerProps;\n applyText(state.paragraph, String(cfg.text ?? ''));\n state.cfg = cfg;\n },\n};\n", "/**\n * Adaptive Chatbot - Runtime Module\n *\n * Runtime manifest for the AI chat assistant adaptive.\n * Uses @syntrologie/chat for the UI \u2014 no React dependency.\n *\n * Chat surfaces are config-driven: customers reference the chat-bar\n * widget id (`adaptive-chatbot:chat-bar`) from `slots.drawer.lid` (to\n * replace the launcher FAB) or any other slot's `lid` / tile slot. The\n * adaptive no longer auto-registers a canvas lid renderer.\n */\n\n// Side-effect imports so the custom elements register with the global\n// registry as soon as the adaptive is loaded.\nimport './AdaptiveChatBar';\nimport './AdaptiveChatTrail';\nimport { AdaptiveChatBarMountable } from './AdaptiveChatBarMountable';\nimport { AdaptiveChipsStripMountable } from './AdaptiveChipsStripMountable';\nimport { ChatAssistantLitMountable } from './ChatAssistantLit';\nimport { NavLinkMountable } from './NavLinkMountable';\nimport { TextAnswerMountable } from './TextAnswerMountable';\n\nexport const runtime = {\n id: 'adaptive-chatbot',\n version: '2.0.0',\n name: 'Chat Assistant',\n description: 'AI chat assistant powered by @syntrologie/chat with SSE transport',\n\n executors: [],\n\n widgets: [\n {\n id: 'adaptive-chatbot:assistant',\n component: ChatAssistantLitMountable,\n metadata: {\n name: 'Chat Assistant',\n description: 'AI-powered chat assistant with SSE streaming and A2UI support',\n icon: '\uD83D\uDCAC',\n },\n },\n // PRD \u00A73 chat lid: the standalone chat bar UI shell. Used as a slot\n // `lid` widget (where it replaces the launcher) or as a regular\n // tile widget (renders inside the drawer). Headless of any chat\n // transport \u2014 emits chat-message-sent / chat-interrupt / canvas-close\n // for the parent to wire to whatever pipeline it owns.\n {\n id: 'adaptive-chatbot:chat-bar',\n component: AdaptiveChatBarMountable,\n metadata: {\n name: 'Chat Bar',\n description:\n 'Always-visible chat input row with bubble-up trail. Headless \u2014 wire to your own transport.',\n icon: '\u2726',\n },\n },\n // PRD \u00A74.5 suggested-chips tile: horizontally-wrapping chip strip\n // with click-to-reveal payload drawer. Each chip is a\n // `suggestions:chip` action.\n {\n id: 'adaptive-chatbot:chips-strip',\n component: AdaptiveChipsStripMountable,\n metadata: {\n name: 'Suggested Chips',\n description: 'Wrapping chip strip with click-to-reveal payloads.',\n icon: '\u2728',\n },\n },\n // Built-in chip payload \u2014 a single paragraph of body text. Chip\n // payloads are widget references (same {widget,props} shape as\n // tile/lid configs); this is the simplest one shipped out of the\n // box so the chip pattern works without requiring a downstream\n // adaptive for a \"just answer with text\" case.\n {\n id: 'adaptive-chatbot:text-answer',\n component: TextAnswerMountable,\n metadata: {\n name: 'Text Answer',\n description: 'Single paragraph payload \u2014 the default chip-drawer content.',\n icon: '\u00B6',\n },\n },\n // Chip payload for LLM-authored navigation suggestions. Backed by\n // the `suggest-navigation` ItemTemplate: the backend wraps a curated\n // URL into props.url, the chip's payload-drawer mounts this widget,\n // user clicks \"Go to <url>\" \u2192 same-origin SPA navigation. Kept here\n // (not in adaptive-nav) so chip payloads ship with the chatbot\n // bundle that already provides chips-strip + text-answer.\n {\n id: 'adaptive-chatbot:nav-link',\n component: NavLinkMountable,\n metadata: {\n name: 'Nav Link',\n description:\n 'Same-origin navigation button \u2014 used as a chip payload for LLM-authored nav suggestions.',\n icon: '\u2192',\n },\n },\n ],\n};\n\nexport default runtime;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * ChatSession \u2014 singleton holder of the chat conversation state.\n *\n * The chat is conceptually one thing. Whether it's rendered in the\n * mini-canvas's lid, the drawer's lid, or as a tile inside any slot,\n * they're all VIEWS of the same conversation. This module owns that\n * shared state.\n *\n * Why a module-level singleton (not on `runtime`):\n * - Per-page scope is the right granularity for a chat (one user,\n * one conversation, however many canvas instances on the page).\n * - Avoids a new SmartCanvasRuntime API surface for now. Easy to\n * promote to `runtime.chat` later without breaking the widget API.\n * - Module identity is stable per page; multiple imports return the\n * same instance.\n *\n * Separation of concerns:\n * - `ChatSession` owns state: messages, inFlight.\n * - Views (AdaptiveChatBar via AdaptiveChatBarMountable) subscribe\n * to state changes and dispatch user actions back via send() /\n * interrupt().\n * - Transports (the LLM call, SSE pipeline, stub timers) listen\n * for \"send\" / \"interrupt\" events and eventually call receive()\n * with the assistant's reply. Transports are NOT owned by this\n * module \u2014 adapters live separately.\n *\n * No persistence in this slice. Future: snapshot to runtime.state\n * for cross-session continuity.\n */\n\nimport type { TrailMessage, TrailToolCall } from './AdaptiveChatTrail';\n\nexport interface ChatSessionState {\n readonly messages: readonly TrailMessage[];\n readonly inFlight: boolean;\n /**\n * Latest reasoning narration from the model, streamed via the\n * AG-UI `THINKING_TEXT_MESSAGE_CONTENT` channel. Empty string when\n * no thinking turn is active. Consumers render this in place of\n * the silent loading dots while the model decides what to do\n * between tool calls. Cleared the moment a real text or tool-call\n * event lands \u2014 at that point the model has switched to producing\n * visible output and the narration is over.\n */\n readonly thinkingText: string;\n}\n\nexport interface ToolResultEvent {\n toolCallId: string;\n result: unknown;\n approved: boolean;\n}\n\nexport type ChatSessionSubscriber = (state: ChatSessionState) => void;\nexport type SendListener = (event: { text: string; activeLidSlot?: string }) => void;\nexport type InterruptListener = () => void;\nexport type ToolResultListener = (event: ToolResultEvent) => void;\n\n/** Optional per-send envelope. */\nexport interface SendOptions {\n /**\n * The slot the calling chat-bar lives in (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Forwarded to transport listeners so the\n * outbound request can tag the correct ``X-Active-Lid-Slot`` regardless\n * of which bar most recently configured the singleton transport.\n * Without per-send threading, two coexisting chat-bars race over the\n * transport's cached ``activeLidSlot`` and the user-facing routing\n * silently follows whichever bar configured last.\n */\n activeLidSlot?: string;\n}\nexport type Unsubscribe = () => void;\n\nexport const CHAT_SESSION_STORAGE_KEY = 'syntro:chat:v1';\n\ninterface PersistedShape {\n messages: TrailMessage[];\n nextId: number;\n}\n\nfunction isValidMessage(value: unknown): value is TrailMessage {\n if (typeof value !== 'object' || value === null) return false;\n const m = value as Record<string, unknown>;\n return (\n (typeof m.id === 'number' || typeof m.id === 'string') &&\n (m.role === 'user' || m.role === 'assistant' || m.role === 'system') &&\n typeof m.text === 'string'\n );\n}\n\nfunction loadFromStorage(): PersistedShape | null {\n try {\n const raw = globalThis.localStorage?.getItem(CHAT_SESSION_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed || !Array.isArray(parsed.messages)) return null;\n const messages = parsed.messages.filter(isValidMessage);\n const nextId = typeof parsed.nextId === 'number' ? parsed.nextId : messages.length + 1;\n return { messages, nextId };\n } catch {\n return null;\n }\n}\n\nexport class ChatSession {\n private _messages: TrailMessage[] = [];\n private _inFlight = false;\n private _thinkingText = '';\n private _nextId = 1;\n\n private subscribers = new Set<ChatSessionSubscriber>();\n private sendListeners = new Set<SendListener>();\n private interruptListeners = new Set<InterruptListener>();\n private toolResultListeners = new Set<ToolResultListener>();\n\n constructor() {\n const restored = loadFromStorage();\n if (restored) {\n this._messages = restored.messages;\n this._nextId = restored.nextId;\n }\n }\n\n /** Snapshot the current state. Always returns a fresh immutable view. */\n getState(): ChatSessionState {\n return {\n messages: [...this._messages],\n inFlight: this._inFlight,\n thinkingText: this._thinkingText,\n };\n }\n\n /**\n * Append a delta to the active thinking turn's narration buffer.\n * Forwarded from the AG-UI THINKING_TEXT_MESSAGE_CONTENT event so\n * the chat trail can render the model's own reasoning instead of\n * silent loading dots between turns.\n */\n appendThinkingDelta(delta: string): void {\n if (!delta) return;\n this._thinkingText += delta;\n this.notify();\n }\n\n /**\n * Replace the active thinking narration outright (vs. appendThinkingDelta's\n * streaming accumulation). Used to surface tool-call progress \u2014 e.g.\n * \"Searching\u2026\" while the agent works a tool \u2014 so a long tool phase shows\n * what's happening instead of silent dots. No-op if unchanged.\n */\n setThinkingText(text: string): void {\n if (this._thinkingText === text) return;\n this._thinkingText = text;\n this.notify();\n }\n\n /**\n * End the active thinking turn \u2014 drop any narration so the trail\n * stops showing it. Fires on real text-message-start and on\n * tool-call-start, the moment the model switches from reasoning\n * to visible output.\n */\n clearThinking(): void {\n if (!this._thinkingText) return;\n this._thinkingText = '';\n this.notify();\n }\n\n /**\n * Subscribe to state changes. Called immediately with the current\n * state, then again on every change. Returns an unsubscribe function.\n */\n subscribe(cb: ChatSessionSubscriber): Unsubscribe {\n this.subscribers.add(cb);\n cb(this.getState());\n return () => {\n this.subscribers.delete(cb);\n };\n }\n\n /**\n * User submitted a message. Appends a user-role message, sets\n * inFlight=true, notifies state subscribers, and fires a \"send\"\n * event so transports can pick it up. Empty/whitespace text is a\n * no-op (matches the chat bar's local guard).\n */\n send(text: string, opts?: SendOptions): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n this._messages.push({ id: this._nextId++, role: 'user', text: trimmed });\n this._inFlight = true;\n this.notify();\n const event: { text: string; activeLidSlot?: string } = { text: trimmed };\n if (opts?.activeLidSlot) event.activeLidSlot = opts.activeLidSlot;\n for (const listener of this.sendListeners) listener(event);\n }\n\n /**\n * Single-shot assistant reply (no streaming). Equivalent to\n * receiveStart + receiveDelta + receiveEnd in one call. Useful for\n * stub transports and tests that don't model streaming.\n */\n receive(text: string): void {\n const id = `m-${this._nextId++}`;\n this._messages.push({ id, role: 'assistant', text, status: 'complete' });\n this._inFlight = false;\n this.notify();\n }\n\n /**\n * Begin a streaming assistant message. Appends an empty assistant\n * message with status='streaming'. Caller (transport adapter) feeds\n * deltas via receiveDelta(id, text) and signals completion via\n * receiveEnd(id). `inFlight` stays true through the stream.\n */\n receiveStart(id: string): void {\n this._messages.push({ id, role: 'assistant', text: '', status: 'streaming' });\n this._inFlight = true;\n this.notify();\n }\n\n /**\n * Append a delta to a streaming message. No-op when the id is\n * unknown (race between transport events and reset, etc.) \u2014 never\n * throws so transports can fire-and-forget.\n */\n receiveDelta(id: string, delta: string): void {\n const msg = this._messages.find((m) => m.id === id);\n if (!msg || msg.status !== 'streaming') return;\n msg.text += delta;\n this.notify();\n }\n\n /**\n * Mark a streaming message complete and clear inFlight. No-op when\n * the id is unknown (defensive against transport double-fires).\n */\n receiveEnd(id: string): void {\n const msg = this._messages.find((m) => m.id === id);\n if (msg && msg.status === 'streaming') {\n msg.status = 'complete';\n }\n this._inFlight = false;\n this.notify();\n }\n\n /**\n * Transport reports a fatal error. Marks any in-flight streaming\n * message as 'error' (so the trail can render a styled error chip\n * instead of pretending the partial text was a complete answer),\n * appends a system-role message with the error text for visibility,\n * and clears inFlight. Also drops any pending thinking narration\n * \u2014 leaving stale \"Let me check\u2026\" alongside an error chip reads\n * as if the assistant is still working when it isn't.\n */\n error(message: string): void {\n for (const m of this._messages) {\n if (m.status === 'streaming') m.status = 'error';\n }\n this._messages.push({\n id: `err-${this._nextId++}`,\n role: 'system',\n text: message,\n status: 'error',\n });\n this._inFlight = false;\n this._thinkingText = '';\n this.notify();\n }\n\n /**\n * User clicked the in-flight stop button. Clears inFlight and\n * fires an \"interrupt\" event so transports can cancel their\n * in-flight request. No-op if not in-flight (idempotent). Drops\n * any pending thinking narration for the same reason as error():\n * the visitor explicitly asked the assistant to stop, so it\n * shouldn't keep narrating in the trail.\n */\n interrupt(): void {\n if (!this._inFlight) return;\n this._inFlight = false;\n this._thinkingText = '';\n this.notify();\n for (const listener of this.interruptListeners) listener();\n }\n\n /**\n * Wipe state. Used by the canvas-close path (start a fresh\n * conversation next time) and by tests.\n */\n reset(): void {\n this._messages = [];\n this._inFlight = false;\n this._thinkingText = '';\n this._nextId = 1;\n this.notify();\n }\n\n /** Register a transport's send listener. Returns unsubscribe. */\n onSend(listener: SendListener): Unsubscribe {\n this.sendListeners.add(listener);\n return () => {\n this.sendListeners.delete(listener);\n };\n }\n\n /**\n * True when at least one transport has wired itself to the session's\n * send pipeline. Views can use this to surface \"no chat backend\n * connected\" affordances instead of hanging in `inFlight` after a\n * send fires into the void.\n */\n hasTransport(): boolean {\n return this.sendListeners.size > 0;\n }\n\n /** Register a transport's interrupt listener. Returns unsubscribe. */\n onInterrupt(listener: InterruptListener): Unsubscribe {\n this.interruptListeners.add(listener);\n return () => {\n this.interruptListeners.delete(listener);\n };\n }\n\n /**\n * Register a transport's tool-result listener. The transport\n * forwards `tool-result` actions back to the agent after the user\n * approves or rejects a client-tool call. Returns unsubscribe.\n */\n onToolResult(listener: ToolResultListener): Unsubscribe {\n this.toolResultListeners.add(listener);\n return () => {\n this.toolResultListeners.delete(listener);\n };\n }\n\n // -------------------------------------------------------------------------\n // Tool calls\n // -------------------------------------------------------------------------\n\n /**\n * Attach a tool call to a streaming assistant message. No-op when\n * the message id is unknown (race between transport events and\n * reset / late mount).\n */\n addToolCall(messageId: string | number, toolCall: TrailToolCall): void {\n const msg = this._messages.find((m) => m.id === messageId);\n if (!msg) return;\n msg.toolCalls = [...(msg.toolCalls ?? []), { ...toolCall }];\n this.notify();\n }\n\n /**\n * Partially update a tool call by id. Used by the transport to\n * advance status (args-streaming \u2192 running \u2192 done) as AG-UI events\n * arrive. No-op when the id is unknown.\n */\n updateToolCall(toolCallId: string, patch: Partial<TrailToolCall>): void {\n for (const msg of this._messages) {\n const tcs = msg.toolCalls;\n if (!tcs) continue;\n const idx = tcs.findIndex((tc) => tc.id === toolCallId);\n if (idx === -1) continue;\n const next = [...tcs];\n next[idx] = { ...next[idx], ...patch } as TrailToolCall;\n msg.toolCalls = next;\n this.notify();\n return;\n }\n }\n\n /**\n * Resolve a (client-) tool call. Marks the call done, persists, and\n * fires onToolResult so the transport can forward the result + the\n * user's approve/reject decision back to the agent. No-op when the\n * id is unknown.\n */\n resolveToolCall(toolCallId: string, result: unknown, approved: boolean): void {\n let found = false;\n for (const msg of this._messages) {\n const tcs = msg.toolCalls;\n if (!tcs) continue;\n const idx = tcs.findIndex((tc) => tc.id === toolCallId);\n if (idx === -1) continue;\n const next = [...tcs];\n next[idx] = { ...next[idx], status: 'done' } as TrailToolCall;\n msg.toolCalls = next;\n found = true;\n break;\n }\n if (!found) return;\n this.notify();\n for (const listener of this.toolResultListeners) {\n listener({ toolCallId, result, approved });\n }\n }\n\n private notify(): void {\n const state = this.getState();\n this.persist();\n for (const sub of this.subscribers) sub(state);\n }\n\n private persist(): void {\n try {\n if (this._messages.length === 0) {\n globalThis.localStorage?.removeItem(CHAT_SESSION_STORAGE_KEY);\n return;\n }\n const payload: PersistedShape = { messages: this._messages, nextId: this._nextId };\n globalThis.localStorage?.setItem(CHAT_SESSION_STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // private mode / quota / SSR \u2014 swallow; in-memory state is still valid\n }\n }\n}\n\n/**\n * The module-level singleton. Every `<adaptive-chat-bar>` (regardless\n * of which slot it lives in) reads from and writes to this instance.\n * Multiple imports of this module return the same object.\n *\n * Scope: per-page. Correct for the canonical case (one user, one\n * conversation, however many canvas views surface it). Multiple\n * `<smart-canvas>` instances on the same page will share state \u2014\n * tracked in project_future_work.md for per-runtime scoping.\n */\nexport const chatSession = new ChatSession();\n", "/**\n * ChatTransport \u2014 singleton transport adapter that bridges chatSession\n * (the view-side state holder) to the real backend chat pipeline\n * (AG-UI SSE at `/api/adaptive/stream`).\n *\n * This is the unification of two formerly separate paths:\n * - `ChatAssistantLit` (old) owns the transport plumbing \u2014\n * AgUiTransport, Cloudflare Turnstile, headers, A2UI passthrough,\n * telemetry, fallback card.\n * - `AdaptiveChatBar` + `chatSession` (new) owns the canvas-lid UX \u2014\n * glassmorphism bar, bubble-up trail, per-page persistence.\n *\n * This module ports every transport-side concern from ChatAssistantLit\n * into a session-shaped adapter so the new bar gets full backend\n * parity. The bar stays a pure view; the transport stays a pure pipe.\n *\n * Lifecycle:\n * - `configure({ backendUrl, runtime, ... })` \u2014 called once by the\n * SDK runtime at bootstrap from chat config. Idempotent; second\n * call with the same backendUrl is a no-op.\n * - Connection is LAZY. The transport doesn't acquire Turnstile or\n * open the SSE until the first chatSession.send() \u2014 saves cost\n * on pages where the user never opens chat.\n * - On chatSession.send \u2192 transport ensures connected (acquires\n * Turnstile token, builds AgUiTransport) then forwards\n * `{type:'user-message', text}` to the agent.\n * - On chatSession.onInterrupt \u2192 transport sends stop-generation.\n * - AgUi events stream into chatSession via receiveStart / Delta /\n * End / error.\n * - A2UI custom events forward to runtime.actions.applyBatch so the\n * agent can drive canvas updates.\n *\n * Telemetry parity with ChatAssistantLit:\n * - chatbot.transport_error (every error, with status/body/name)\n * - chatbot.a2ui_applied\n * - chatbot.fallback_rendered \u2014 emitted when the transport gives up\n * (Turnstile failed AND backend rejected) so existing PostHog\n * queries keep working.\n *\n * Threading model: single-flight per page. Multiple concurrent sends\n * are queued by AgUiTransport itself. Multiple bar mounts share this\n * one transport via chatSession.\n */\n\nimport type { ServerEvent } from '@syntrologie/chat';\n// AgUiTransport / Turnstile helpers live in the existing packages \u2014\n// we reuse them instead of re-implementing.\nimport { AgUiTransport } from '@syntrologie/chat/transport/agui';\n\nimport type { TrailToolCall } from './AdaptiveChatTrail';\nimport { chatSession } from './ChatSession';\nimport type { ElementMutation } from './elements';\nimport { decodeMutationEnvelope } from './elements';\nimport { acquireTokenWithChallenge } from './Turnstile';\nimport type { ChatbotWidgetRuntime } from './types';\n\n/**\n * Per-customer \"chat unavailable\" card config. Surfaced via onFallback\n * when the transport gives up after repeated failures. Mirrors\n * ChatbotFallback in types.ts so consumers can pass the same config.\n */\nexport interface ChatbotFallbackConfig {\n title?: string;\n message?: string;\n ctaLabel?: string;\n ctaHref?: string;\n}\n\nexport interface ChatTransportConfig {\n /** Backend host, e.g. \"https://demo-api.syntrologie.com\" or \"\" for same-origin. */\n backendUrl: string;\n /** Runtime hooks for A2UI apply + telemetry. */\n runtime: ChatbotWidgetRuntime;\n /** Optional thread id for conversation continuity across reloads. */\n threadId?: string;\n /**\n * Optional set of client-tool names the transport should treat as\n * \"needs user approval\" (surfaced via chatSession.toolCalls instead\n * of auto-executed server-side). Empty by default \u2014 all tool calls\n * are server-driven and the transport just emits the \"tool call\n * happened\" event.\n */\n clientTools?: Set<string>;\n /**\n * Per-customer \"chat unavailable\" card. Rendered by the host\n * (typically AdaptiveChatBarMountable) after repeated connect\n * failures wipe the chat surface \u2014 exactly the same UX\n * ChatAssistantLit's fallback path provides.\n */\n fallback?: ChatbotFallbackConfig;\n /**\n * Arbitrary JSON object attached to every AG-UI request as\n * `forwardedProps`. Used by the adaptive chat surface to ship the\n * LLM-authored UI element config (`uiTemplates`, `elementsEnabled`)\n * per request \u2014 the backend reads these to enable the\n * `mount_element` / `patch_element` / `unmount_element` tools.\n * Callable form is re-evaluated on every turn so a config edit can\n * land mid-conversation.\n */\n forwardedProps?: Record<string, unknown> | (() => Record<string, unknown> | undefined);\n /**\n * Optional callback for `syntro.element.mutation` AG-UI custom events.\n * The transport decodes the envelope on receipt; if it matches the\n * element-mutation schema, mutations are routed here instead of the\n * generic `runtime.actions.applyBatch` legacy path. Consumers are\n * expected to forward to `ElementInstanceStore.apply(mutations)` \u2014\n * we don't take a store reference directly so the transport stays\n * agnostic of which surface owns the store (the chat-bar widget\n * may own one; ChatAssistantLit owns its own; both share this\n * singleton transport).\n *\n * When unset, element-mutation envelopes fall back to applyBatch,\n * matching legacy behaviour (which would no-op since applyBatch\n * doesn't know about MutationEnvelope).\n */\n onElementMutation?: (mutations: ElementMutation[]) => void;\n /**\n * Slot the chat-bar widget is mounted into (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Forwarded as ``X-Active-Lid-Slot`` on every\n * ``/api/adaptive/stream`` request so the backend can route mounts to\n * the canvas next to whichever lid the visitor sent from. Optional \u2014\n * omitting it falls back to the template's static ``default_slot``\n * server-side, which is the pre-change behaviour.\n */\n activeLidSlot?: string;\n}\n\n/**\n * Debounce window for connect errors. Single transient errors\n * (cold-start 502, brief CORS preflight failure) should NOT swap the\n * chat to the fallback card; only sustained failure should. Matches\n * ChatAssistantLit's ERROR_DEBOUNCE_MS.\n */\nexport const FALLBACK_DEBOUNCE_MS = 1_500;\n\nexport interface FallbackPayload {\n reason: 'connect_failed' | 'connect_timeout';\n fallback: ChatbotFallbackConfig;\n transportId: string;\n transportAgeMs: number;\n messagesSucceeded: number;\n hadTurnstileToken: boolean | null;\n errorStatus: number | null;\n errorBody: string | null;\n errorMessage: string | null;\n errorName: string | null;\n}\n\nexport type FallbackListener = (payload: FallbackPayload) => void;\n\ntype ChatTransportStatus =\n | 'idle' // configure() not called yet\n | 'configured' // ready but not connected\n | 'acquiring' // Turnstile token acquisition in flight\n | 'connected' // AgUiTransport up and ready\n | 'error'; // last attempt failed; will retry on next send\n\ninterface SyntroGlobalConfig {\n token?: string;\n}\n\n/**\n * Read the workspace's syn_* token from runtime-config.js. The SDK\n * sets this global at bootstrap; for non-CDN test environments the\n * test page sets it directly. Returns undefined when the global is\n * missing \u2014 the connect will then fall through to the unauthenticated\n * path and the backend will 401 (caught by error handling below).\n */\nfunction readSyntroToken(): string | undefined {\n if (typeof window === 'undefined') return undefined;\n const cfg = (window as unknown as { __SYNTRO_CONFIG__?: SyntroGlobalConfig }).__SYNTRO_CONFIG__;\n const token = cfg?.token;\n return typeof token === 'string' && token.length > 0 ? token : undefined;\n}\n\n/**\n * Debug logger gated on `window.__SYNTRO_CHAT_DEBUG__`. Mirrors\n * ChatAssistantLit so flipping that flag in the customer's DevTools\n * enables verbose tracing across the whole chat pipeline (the bar\n * AND the legacy assistant) without rebuilding the SDK.\n */\nfunction debug(...args: unknown[]): void {\n if (typeof window === 'undefined') return;\n if ((window as unknown as { __SYNTRO_CHAT_DEBUG__?: boolean }).__SYNTRO_CHAT_DEBUG__) {\n console.debug('[chat-transport]', ...args);\n }\n}\n\n/**\n * Visitor-facing progress copy for a tool call, shown in the thinking chip\n * while the agent works. Keyed on substrings of the (technical) tool name so\n * it survives renames; falls back to a generic \"Working on it\u2026\". Never shows\n * the raw tool name to a visitor.\n */\nfunction friendlyToolLabel(name: string): string {\n const n = (name || '').toLowerCase();\n if (n.includes('search')) return 'Searching\u2026';\n if (n.includes('route') || n.includes('wiki')) return 'Finding the right page\u2026';\n if (n.includes('read') || n.includes('section')) return 'Reading up on that\u2026';\n if (n.includes('mount') || n.includes('unmount') || n.includes('element'))\n return 'Updating the page\u2026';\n if (n.includes('response') || n.includes('primary') || n.includes('action'))\n return 'Putting that together\u2026';\n return 'Working on it\u2026';\n}\n\n/**\n * Singleton-safe merge for forwardedProps. The transport is shared\n * across every chat surface in a canvas (chat-bar lid on the drawer,\n * inline chat-bar tile, hero anchor), and each surface calls\n * `configure()` on mount. If a surface that hasn't been wired with\n * `uiTemplates` configures *after* one that has, a naive shallow\n * merge clobbers the bag and the backend's `_inject_available_templates`\n * silently falls back to the empty list. Preserve any previously-set\n * bag unless the new config explicitly provides one \u2014 surfaces that\n * don't ship templates just opt out of mutating that field.\n */\nfunction mergeForwardedProps(\n prev: ChatTransportConfig | null,\n next: ChatTransportConfig\n): ChatTransportConfig {\n if (next.forwardedProps !== undefined) return next;\n if (!prev?.forwardedProps) return next;\n return { ...next, forwardedProps: prev.forwardedProps };\n}\n\nexport class ChatTransport {\n private _config: ChatTransportConfig | null = null;\n private _status: ChatTransportStatus = 'idle';\n private _agui: AgUiTransport | null = null;\n private _transportUnsub: (() => void) | null = null;\n private _sessionUnsubSend: (() => void) | null = null;\n private _sessionUnsubInterrupt: (() => void) | null = null;\n private _sessionUnsubToolResult: (() => void) | null = null;\n private _connectInFlight: Promise<boolean> | null = null;\n /** Bounded streaming-message id for the currently-being-typed assistant turn. */\n private _currentAssistantMessageId: string | null = null;\n /** Outcome bookkeeping for telemetry. */\n private _hadTurnstileToken: boolean | null = null;\n /** Count of successful round-trips for telemetry payloads. */\n private _messagesSucceeded = 0;\n /** True once a successful assistant message has landed \u2014 gates fallback. */\n private _hasSucceeded = false;\n /** True once fallback has fired (one-shot). */\n private _fallbackRendered = false;\n /**\n * Per-send override for ``X-Active-Lid-Slot``. Set in the\n * ``chatSession.onSend`` listener immediately before each\n * ``_forwardUserMessage`` and consumed by ``buildHeaders`` on the\n * outbound request. The singleton transport is shared by every\n * mounted chat-bar (drawer + inline) so cached ``_config.activeLidSlot``\n * follows whichever bar last reconfigured \u2014 using that for routing\n * silently misroutes tiles when both bars coexist. Per-send threading\n * pins the header to the bar that actually sent the message.\n */\n private _pendingLidSlot: string | null = null;\n /** Active debounce timer; null when no debounce pending. */\n private _errorDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n /** Most recent error payload, captured so debounced fallback can attach it. */\n private _lastErrorPayload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n } | null = null;\n private _fallbackListeners = new Set<FallbackListener>();\n /**\n * Per-configure-cycle id for correlating telemetry events from a\n * single transport lifetime. Mirrors ChatAssistantLit's mountId\n * but scoped to configure cycles since the transport is a\n * singleton across mounts.\n */\n private _transportId = `tx_${Math.random().toString(36).slice(2, 8)}`;\n private _configuredAt = 0;\n\n /**\n * Configure the transport. Idempotent \u2014 calling again with the same\n * backendUrl is a no-op; calling with a different backendUrl tears\n * the connection down and re-arms.\n */\n configure(config: ChatTransportConfig): void {\n const same =\n this._config &&\n this._config.backendUrl === config.backendUrl &&\n this._config.threadId === config.threadId;\n if (same) {\n // Allow runtime + clientTools to be replaced without reconnect \u2014\n // the bar may remount with a fresh runtime closure.\n this._config = { ...this._config, ...mergeForwardedProps(this._config, config) };\n return;\n }\n this._disconnect();\n this._config = config;\n this._status = 'configured';\n this._transportId = `tx_${Math.random().toString(36).slice(2, 8)}`;\n this._configuredAt = Date.now();\n this._wireSession();\n debug('configured', {\n transportId: this._transportId,\n backendUrl: config.backendUrl,\n threadId: config.threadId,\n });\n }\n\n /** ms since the most recent configure() call. 0 before any configure. */\n private _ageMs(): number {\n return this._configuredAt === 0 ? 0 : Date.now() - this._configuredAt;\n }\n\n /** True when configure() has been called and we're ready to lazy-connect on send. */\n get isConfigured(): boolean {\n return this._status !== 'idle';\n }\n\n /** True when AgUiTransport is up. */\n get isConnected(): boolean {\n return this._status === 'connected';\n }\n\n /**\n * Subscribe to fallback events \u2014 fires once per configure cycle\n * when the transport gives up after sustained failure. Hosts\n * (typically AdaptiveChatBarMountable) use this to swap the chat\n * bar for a static \"contact support\" card.\n */\n onFallback(listener: FallbackListener): () => void {\n this._fallbackListeners.add(listener);\n return () => {\n this._fallbackListeners.delete(listener);\n };\n }\n\n /**\n * Test seam \u2014 drive a synthetic error event through the transport's\n * error handling without standing up a real AgUi transport. Production\n * code path uses _onTransportEvent. Exported as a public method to\n * keep the test isolation simple; not part of the documented API.\n */\n simulateError(payload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n }): void {\n this._handleErrorEvent(payload);\n }\n\n /**\n * Test seam \u2014 register a synthetic successful message-complete so\n * the hasSucceeded gate flips without a real AgUi round-trip.\n */\n simulateSuccessfulMessage(): void {\n this._hasSucceeded = true;\n this._messagesSucceeded += 1;\n this._clearDebounceTimer();\n }\n\n /**\n * Test seam \u2014 return the lid slot that the next outbound request\n * WOULD tag ``X-Active-Lid-Slot`` with, given current state. Mirrors\n * the exact resolution buildHeaders uses (per-send slot wins over\n * cached config). Not part of the documented API.\n */\n getActiveLidSlotForTest(): string | null {\n return this._pendingLidSlot ?? this._config?.activeLidSlot ?? null;\n }\n\n /**\n * Tear connection-level state down. Used internally by configure()\n * to swap backends; preserves host-registered fallback listeners\n * because the host UI handler (e.g. AdaptiveChatBarMountable's\n * \"swap to fallback card\" callback) is configuration-independent.\n */\n private _disconnect(): void {\n if (this._transportUnsub) {\n this._transportUnsub();\n this._transportUnsub = null;\n }\n if (this._sessionUnsubSend) {\n this._sessionUnsubSend();\n this._sessionUnsubSend = null;\n }\n if (this._sessionUnsubInterrupt) {\n this._sessionUnsubInterrupt();\n this._sessionUnsubInterrupt = null;\n }\n if (this._sessionUnsubToolResult) {\n this._sessionUnsubToolResult();\n this._sessionUnsubToolResult = null;\n }\n if (this._agui) {\n this._agui.disconnect();\n this._agui = null;\n }\n this._clearDebounceTimer();\n this._config = null;\n this._status = 'idle';\n this._connectInFlight = null;\n this._currentAssistantMessageId = null;\n this._hadTurnstileToken = null;\n this._messagesSucceeded = 0;\n this._hasSucceeded = false;\n this._fallbackRendered = false;\n this._lastErrorPayload = null;\n this._pendingLidSlot = null;\n }\n\n /**\n * Tear everything down \u2014 connection state PLUS host listeners.\n * Use this in test teardown or when fully shutting the transport\n * (page unload, integration test reset). The mountable calls\n * _disconnect indirectly via reconfigure.\n */\n reset(): void {\n this._disconnect();\n this._fallbackListeners.clear();\n }\n\n private _clearDebounceTimer(): void {\n if (this._errorDebounceTimer) {\n clearTimeout(this._errorDebounceTimer);\n this._errorDebounceTimer = null;\n }\n }\n\n /**\n * Shared error-handling kernel \u2014 called by the AG-UI subscriber and\n * by the simulateError test seam. Publishes transport_error\n * telemetry, captures lastErrorPayload, and starts the debounce\n * timer that will fire fallback if no successful message arrives\n * before it expires. Gated by hasSucceeded (post-success errors\n * never fallback) and _fallbackRendered (one-shot).\n */\n private _handleErrorEvent(payload: {\n message?: string;\n status?: number | null;\n body?: string | null;\n errorName?: string | null;\n }): void {\n const status = payload.status ?? null;\n const body = payload.body ? String(payload.body).slice(0, 200) : null;\n this._lastErrorPayload = {\n message: payload.message,\n status,\n body,\n errorName: payload.errorName ?? null,\n };\n\n this._config?.runtime.events.publish('chatbot.transport_error', {\n source: 'chat-transport',\n transportId: this._transportId,\n transportAgeMs: this._ageMs(),\n messagesSucceeded: this._messagesSucceeded,\n hadTurnstileToken: this._hadTurnstileToken,\n hasSucceeded: this._hasSucceeded,\n errorMessage: payload.message ?? null,\n errorStatus: status,\n errorBody: body,\n errorName: payload.errorName ?? null,\n });\n\n if (this._hasSucceeded || this._fallbackRendered || this._errorDebounceTimer) return;\n this._errorDebounceTimer = setTimeout(() => {\n this._errorDebounceTimer = null;\n if (this._hasSucceeded || this._fallbackRendered) return;\n this._renderFallback('connect_failed');\n }, FALLBACK_DEBOUNCE_MS);\n }\n\n /**\n * Fire the fallback. One-shot per configure cycle. Notifies all\n * fallback listeners with the per-customer card config and the\n * diagnostic snapshot for telemetry/debug.\n */\n private _renderFallback(reason: FallbackPayload['reason']): void {\n if (this._fallbackRendered) return;\n this._fallbackRendered = true;\n debug('fallback', { reason, transportId: this._transportId, ageMs: this._ageMs() });\n const fallback = this._config?.fallback ?? {};\n const payload: FallbackPayload = {\n reason,\n fallback,\n transportId: this._transportId,\n transportAgeMs: this._ageMs(),\n messagesSucceeded: this._messagesSucceeded,\n hadTurnstileToken: this._hadTurnstileToken,\n errorStatus: this._lastErrorPayload?.status ?? null,\n errorBody: this._lastErrorPayload?.body ?? null,\n errorMessage: this._lastErrorPayload?.message ?? null,\n errorName: this._lastErrorPayload?.errorName ?? null,\n };\n this._config?.runtime.events.publish(\n 'chatbot.fallback_rendered',\n payload as unknown as Record<string, unknown>\n );\n for (const listener of this._fallbackListeners) listener(payload);\n }\n\n // -------------------------------------------------------------------------\n // Internal: chatSession wiring\n // -------------------------------------------------------------------------\n\n private _wireSession(): void {\n this._sessionUnsubSend = chatSession.onSend(({ text, activeLidSlot }) => {\n // Capture the sending bar's slot BEFORE awaiting the connect /\n // forward chain. `_pendingLidSlot` is consumed by buildHeaders on\n // the outbound request \u2014 see the field doc on `_pendingLidSlot`\n // for why we can't rely on `_config.activeLidSlot` here.\n this._pendingLidSlot =\n typeof activeLidSlot === 'string' && activeLidSlot.length > 0 ? activeLidSlot : null;\n void this._forwardUserMessage(text);\n });\n this._sessionUnsubInterrupt = chatSession.onInterrupt(() => {\n this._agui?.send({ type: 'stop-generation' });\n });\n this._sessionUnsubToolResult = chatSession.onToolResult(({ toolCallId, result, approved }) => {\n this._agui?.send({ type: 'tool-result', toolCallId, result, approved });\n });\n }\n\n private async _forwardUserMessage(text: string): Promise<void> {\n const ok = await this._ensureConnected();\n if (!ok || !this._agui) {\n // Connect failed; surface to the session so the bar shows an error\n // chip and clears inFlight (otherwise the user is stuck on the\n // \u23F9 stop button forever).\n chatSession.error(\"Couldn't connect to chat. Please try again.\");\n return;\n }\n this._agui.send({ type: 'user-message', text });\n }\n\n // -------------------------------------------------------------------------\n // Internal: connect (lazy, Turnstile-gated)\n // -------------------------------------------------------------------------\n\n /**\n * Ensure AgUiTransport is up. Idempotent \u2014 multiple concurrent calls\n * dedupe to a single Turnstile acquisition + transport setup.\n * Returns true on success, false on terminal failure.\n */\n private async _ensureConnected(): Promise<boolean> {\n if (this._status === 'connected' && this._agui) return true;\n if (!this._config) return false;\n if (this._connectInFlight) return this._connectInFlight;\n\n this._connectInFlight = (async () => {\n this._status = 'acquiring';\n const cft = await this._acquireTurnstileWithChallenge();\n this._hadTurnstileToken = cft !== null;\n\n if (this._config === null) return false; // raced with reset()\n\n const baseUrl = this._config.backendUrl.replace(/\\/$/, '');\n const streamUrl = `${baseUrl}/api/adaptive/stream`;\n const token = readSyntroToken();\n const buildHeaders = (): Record<string, string> => {\n const h: Record<string, string> = {};\n if (token) h.Authorization = `Bearer ${token}`;\n if (cft) h['CF-Turnstile-Token'] = cft;\n // Forward the slot the chat-bar that initiated this send lives\n // in so the backend can route mount_element results to the\n // canvas next to it. Prefer `_pendingLidSlot` (set on each\n // chatSession.onSend) over `_config.activeLidSlot` (last value\n // cached by configure): when drawer + inline bars coexist they\n // share this singleton transport, so the cached config follows\n // whichever bar reconfigured most recently \u2014 not the bar that\n // actually sent the current message. `_pendingLidSlot` pins the\n // header to the sender. Fall back to the cached config so older\n // call sites that haven't been migrated still get a value.\n const lidSlot = this._pendingLidSlot ?? this._config?.activeLidSlot;\n if (typeof lidSlot === 'string' && lidSlot.length > 0) {\n h['X-Active-Lid-Slot'] = lidSlot;\n }\n // Forward the runtime's visitor ids (the canonical, runtime-maintained\n // accessor \u2014 NOT window.posthog). distinct_id resolves historical\n // context (KNOWN ABOUT VISITOR block); session_id scopes the live\n // observation drain + seeds cross-session recall on the first turn.\n // Missing (consent denied / no runtime id) \u2192 header omitted \u2192 cold.\n try {\n const rt = this._config?.runtime as\n | {\n telemetry?: {\n getDistinctId?: () => string | null | undefined;\n getSessionId?: () => string | null | undefined;\n };\n }\n | undefined;\n const did = rt?.telemetry?.getDistinctId?.();\n if (typeof did === 'string' && did.length > 0) {\n h['X-Distinct-Id'] = did;\n }\n const sid = rt?.telemetry?.getSessionId?.();\n if (typeof sid === 'string' && sid.length > 0) {\n h['X-Syntro-Session'] = sid;\n }\n } catch {\n // A runtime telemetry throw is extremely rare but cheap to guard.\n }\n return h;\n };\n\n const runtime = this._config.runtime;\n // Resolve forwardedProps at run-time (each AG-UI request), not at\n // transport construction. The config can be updated via\n // `configure()` with the same backendUrl (no reconnect), so the\n // late-bound closure keeps the transport in sync with the most\n // recent uiTemplates / elementsEnabled declarations.\n const resolveForwardedProps = (): Record<string, unknown> | undefined => {\n const raw = this._config?.forwardedProps;\n return typeof raw === 'function' ? raw() : raw;\n };\n this._agui = new AgUiTransport({\n url: streamUrl,\n headers: buildHeaders,\n threadId: this._config.threadId,\n clientTools: this._config.clientTools,\n // Adaptive runtime SDK needs the `syntro_chat_session` cookie to\n // round-trip cross-origin so subsequent boot fetches can rehydrate\n // LLM-authored UI elements. Editor / action-plan chat surfaces\n // auth via `?token=` and intentionally leave this unset (see\n // AgUiTransportOptions.credentials docstring).\n credentials: 'include',\n forwardedProps: resolveForwardedProps,\n onA2UIEvent: (payload) => {\n // Discriminate `syntro.element.mutation` envelopes (LLM-\n // authored UI element mounts/patches/unmounts) from legacy\n // A2UI / raw ActionStep payloads. Mirrors ChatAssistantLit's\n // routing \u2014 the chat-bar lid surface needs the same wiring so\n // mount_element / patch_element / unmount_element results\n // actually land on the host page.\n const mutations = decodeMutationEnvelope(payload);\n if (mutations !== null) {\n const handler = this._config?.onElementMutation;\n if (handler) {\n try {\n handler(mutations);\n runtime.events.publish('chatbot.element_mutation_applied', {\n source: 'chat-transport',\n count: mutations.length,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[chat-transport] element mutation apply failed:', msg);\n }\n return;\n }\n // No handler registered \u2014 the surface using this transport\n // didn't opt into element mutations. Drop silently rather\n // than feeding a MutationEnvelope into applyBatch (which\n // would no-op or warn).\n return;\n }\n runtime.actions\n .applyBatch([payload as unknown as Record<string, unknown>])\n .then(() => {\n runtime.events.publish('chatbot.a2ui_applied', { source: 'chat-transport' });\n })\n .catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('[chat-transport] A2UI apply failed:', msg);\n });\n },\n });\n this._agui.connect();\n this._transportUnsub = this._agui.subscribe((event) => this._onTransportEvent(event));\n this._status = 'connected';\n return true;\n })();\n\n try {\n return await this._connectInFlight;\n } finally {\n this._connectInFlight = null;\n }\n }\n\n /**\n * Acquire a Turnstile token via the managed-challenge flow.\n * Delegates to the shared Turnstile helper that owns the verify\n * panel lifecycle. Returns null when Turnstile is disabled at\n * build time or acquisition fails.\n */\n private async _acquireTurnstileWithChallenge(): Promise<string | null> {\n const { token } = await acquireTokenWithChallenge();\n return token;\n }\n\n // -------------------------------------------------------------------------\n // Internal: AgUi event \u2192 chatSession\n // -------------------------------------------------------------------------\n\n /**\n * Look up a tool call's current chatSession-side status by id.\n * Used to decide between addToolCall (first sighting) and\n * updateToolCall (subsequent updates) when AG-UI re-emits\n * `tool-call` events for client tools transitioning to 'pending'.\n */\n private _findToolCallStatus(toolCallId: string): TrailToolCall['status'] | null {\n const state = chatSession.getState();\n for (const msg of state.messages) {\n const tc = msg.toolCalls?.find((t) => t.id === toolCallId);\n if (tc) return tc.status;\n }\n return null;\n }\n\n /** Map AG-UI ToolCallStatus to TrailToolCall status. */\n private _mapToolCallStatus(status: string): TrailToolCall['status'] {\n switch (status) {\n case 'args-streaming':\n return 'args-streaming';\n case 'pending':\n return 'pending';\n case 'running':\n return 'running';\n case 'done':\n return 'done';\n case 'error':\n return 'error';\n default:\n return 'running';\n }\n }\n\n private _onTransportEvent(event: ServerEvent): void {\n switch (event.type) {\n case 'session-ready':\n case 'messages-snapshot':\n case 'typing':\n // Local-only events from AgUiTransport.connect() \u2014 no UI impact.\n return;\n\n case 'message-append': {\n // Start of a new streaming assistant message \u2014 drop any tool-call\n // narration so the chip hands off cleanly to the streaming text.\n chatSession.clearThinking();\n this._currentAssistantMessageId = event.message.id;\n chatSession.receiveStart(event.message.id);\n if (event.message.content && event.message.content.length > 0) {\n chatSession.receiveDelta(event.message.id, event.message.content);\n }\n return;\n }\n\n case 'message-delta': {\n const id = event.messageId ?? this._currentAssistantMessageId;\n if (!id || !event.delta) return;\n chatSession.receiveDelta(id, event.delta);\n return;\n }\n\n case 'thinking-delta': {\n // Stream the model's reasoning narration into chat session state\n // so the trail can render it in place of silent loading dots\n // while the model decides what to do next.\n chatSession.appendThinkingDelta(event.delta);\n return;\n }\n\n case 'thinking-clear': {\n // Real output is about to start \u2014 drop the narration so the trail\n // can swap to the live text/tool-call chip in one frame.\n chatSession.clearThinking();\n return;\n }\n\n case 'message-complete': {\n const id = event.messageId ?? this._currentAssistantMessageId;\n if (!id) return;\n chatSession.receiveEnd(id);\n this._currentAssistantMessageId = null;\n this._messagesSucceeded += 1;\n // Flip the hasSucceeded gate: errors after this point will no\n // longer trigger a fallback swap (matches ChatAssistantLit).\n this._hasSucceeded = true;\n this._clearDebounceTimer();\n return;\n }\n\n case 'tool-call': {\n // tool-call arrives twice in the AG-UI flow: once at start\n // (status='args-streaming') and once at end for client tools\n // with status='pending' awaiting user approval. Add on the\n // first sighting, update on the second.\n const existing = this._findToolCallStatus(event.toolCall.id);\n // Narrate the tool on first sighting so a long tool phase shows\n // progress in the thinking chip (\"Searching\u2026\") instead of silent\n // dots. Crucially this runs BEFORE the targetMessageId guard below \u2014\n // the agent fires its first tool calls before any assistant message\n // exists, and those would otherwise be invisible (chip dropped).\n if (!existing) {\n chatSession.setThinkingText(friendlyToolLabel(event.toolCall.name));\n }\n const targetMessageId = event.messageId ?? this._currentAssistantMessageId;\n if (!targetMessageId) return;\n if (!existing) {\n chatSession.addToolCall(targetMessageId, {\n id: event.toolCall.id,\n name: event.toolCall.name,\n status: this._mapToolCallStatus(event.toolCall.status),\n });\n } else {\n chatSession.updateToolCall(event.toolCall.id, {\n name: event.toolCall.name,\n status: this._mapToolCallStatus(event.toolCall.status),\n });\n }\n return;\n }\n\n case 'tool-call-args-delta':\n // We don't currently surface streaming args in the trail chip\n // (too noisy for the compact UI), but a future expanded view\n // could subscribe and render them. Logged under debug.\n debug('tool-call-args-delta', event);\n return;\n\n case 'tool-call-done':\n // Server-side tool finished. Mark complete in the trail so the\n // chip transitions from \"running\" to \"done\". Client-tool\n // resolution goes through chatSession.resolveToolCall instead.\n chatSession.updateToolCall(event.toolCallId, { status: 'done' });\n return;\n\n case 'a2ui':\n // A2UI events also flow via onA2UIEvent in the transport\n // constructor \u2014 that path is what applies the batch. This\n // duplicate event is the public mirror; ignore here.\n return;\n\n case 'error': {\n const status = event.status ?? null;\n const body = event.body ? String(event.body).slice(0, 200) : null;\n console.warn(\n `[chat-transport] error status=${status ?? 'no-status'} succeeded=${this._messagesSucceeded}`,\n event\n );\n // Route through the shared error-handling kernel so the\n // debounce / hasSucceeded gate / fallback path apply uniformly\n // regardless of whether the error came from AG-UI or a test seam.\n this._handleErrorEvent({\n message: event.message,\n status,\n body,\n errorName: event.errorName ?? null,\n });\n // The chip-level error chip (shown immediately, no debounce)\n // gives the user feedback even when we're still waiting to see\n // if the failure is sustained enough to swap to the fallback.\n chatSession.error(event.message ?? 'Chat connection failed');\n this._currentAssistantMessageId = null;\n // Tear AgUiTransport down so the next send re-acquires Turnstile\n // and re-opens. Avoids reusing a broken HttpAgent under us.\n if (this._agui) {\n this._agui.disconnect();\n this._agui = null;\n }\n if (this._transportUnsub) {\n this._transportUnsub();\n this._transportUnsub = null;\n }\n this._status = 'error';\n return;\n }\n }\n }\n}\n\n/**\n * The module-level singleton. Imported by both the SDK runtime\n * bootstrap (to call configure) and any code that needs to read\n * transport state. Mirrors the chatSession singleton shape.\n */\nexport const chatTransport = new ChatTransport();\n", "/**\n * Pure mapping from raw PostHog events to ObservationEvents.\n *\n * One function: matchEvent(raw, opts) \u2192 ObservationEvent | null. Null means\n * \"drop, not significant.\" This module is the single source of truth for what\n * the chat agent sees on the in-session timeline; the SDK observer never\n * forwards anything matchEvent returns null for.\n *\n * Kept dependency-free (no DOM access, no PostHog SDK imports) so the\n * Vitest unit tests run without any browser shim.\n */\n\nexport type ObservationKind =\n | 'nav'\n | 'click'\n | 'form'\n | 'rage'\n | 'dead'\n | 'scroll'\n | 'view'\n | 'idle'\n | 'hover'\n | 'hesitation'\n | 'custom';\n\nexport interface ObservationEvent {\n ts: number;\n kind: ObservationKind;\n text: string;\n ref?: string;\n}\n\n/** Shape of a raw event reaching matchEvent. Loose by design \u2014 PostHog's\n * event shape evolves, and we want matchEvent to be resilient to extra\n * properties. */\nexport interface RawEvent {\n event: string;\n timestamp: number;\n properties: Record<string, unknown>;\n}\n\nexport interface MatchOptions {\n /** Workspace-configured custom event names to forward as kind=\"custom\". */\n observableEvents?: readonly string[];\n}\n\nconst MAX_TEXT_LEN = 200;\nconst SIGNIFICANT_CLICK_TAGS = new Set(['button', 'a']);\n\nfunction truncate(s: string): string {\n return s.length <= MAX_TEXT_LEN ? s : `${s.slice(0, MAX_TEXT_LEN - 1)}\u2026`;\n}\n\nfunction firstElement(props: Record<string, unknown>): Record<string, unknown> | null {\n const els = props.$elements;\n if (Array.isArray(els) && els.length > 0 && typeof els[0] === 'object' && els[0] !== null) {\n return els[0] as Record<string, unknown>;\n }\n return null;\n}\n\nfunction elementText(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return '';\n const t = el.text;\n return typeof t === 'string' ? t.trim() : '';\n}\n\nfunction elementTag(props: Record<string, unknown>): string {\n const explicit = props.$element_tag_name;\n if (typeof explicit === 'string') return explicit.toLowerCase();\n const el = firstElement(props);\n if (el && typeof el.tag_name === 'string') return (el.tag_name as string).toLowerCase();\n return '';\n}\n\nfunction elementRole(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return '';\n const role = el.attr__role;\n return typeof role === 'string' ? role.toLowerCase() : '';\n}\n\nfunction formName(props: Record<string, unknown>): string {\n const el = firstElement(props);\n if (!el) return 'unnamed';\n const name = el.attr__name;\n if (typeof name === 'string' && name) return name;\n const id = el.attr__id;\n if (typeof id === 'string' && id) return id;\n return 'unnamed';\n}\n\nfunction isSignificantClickTarget(props: Record<string, unknown>): boolean {\n const tag = elementTag(props);\n if (SIGNIFICANT_CLICK_TAGS.has(tag)) return true;\n if (elementRole(props) === 'button') return true;\n return false;\n}\n\nfunction pathname(props: Record<string, unknown>): string {\n const pn = props.$pathname;\n return typeof pn === 'string' ? pn : '/';\n}\n\nfunction renderCustomEvent(raw: RawEvent): string {\n // Stable summary: event name + up to two scalar props.\n const fields: string[] = [];\n for (const [k, v] of Object.entries(raw.properties)) {\n if (k.startsWith('$')) continue;\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n fields.push(`${k}=${v}`);\n if (fields.length >= 2) break;\n }\n }\n return fields.length > 0 ? `${raw.event} (${fields.join(', ')})` : raw.event;\n}\n\nexport function matchEvent(raw: RawEvent, opts: MatchOptions = {}): ObservationEvent | null {\n const props = raw.properties;\n\n switch (raw.event) {\n case '$pageview': {\n const path = pathname(props);\n return {\n ts: raw.timestamp,\n kind: 'nav',\n text: truncate(`navigated to ${path}`),\n ref: path,\n };\n }\n\n case '$autocapture': {\n const eventType = props.$event_type;\n\n if (eventType === 'click') {\n if (!isSignificantClickTarget(props)) return null;\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'click',\n text: truncate(`clicked '${text}'`),\n };\n }\n\n if (eventType === 'submit' && elementTag(props) === 'form') {\n return {\n ts: raw.timestamp,\n kind: 'form',\n text: truncate(`submitted form '${formName(props)}'`),\n };\n }\n\n return null;\n }\n\n case '$rageclick': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'rage',\n text: truncate(`rage-clicked '${text}'`),\n };\n }\n\n case '$dead_click': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'dead',\n text: truncate(`clicked '${text}' (no response)`),\n };\n }\n\n // \u2500\u2500 Canonical runtime-bus events (sources: `'canvas'` instrumentation\n // or the event-processor's rrweb detectors). These don't go through\n // PostHog; the chat-bar's bus translator forwards them as-is with\n // the canonical event name, and matchEvent picks the right slot\n // here. Keeps a single allowlist as the source of truth for what\n // the agent's observation tail can carry.\n case 'nav.section_viewed': {\n const section = typeof props.section === 'string' ? props.section : '';\n if (!section) return null;\n return {\n ts: raw.timestamp,\n kind: 'view',\n text: truncate(`viewed the '${section}' section`),\n ref: section,\n };\n }\n\n case 'nav.scroll_depth': {\n const pct = typeof props.percent === 'number' ? props.percent : null;\n if (pct === null) return null;\n return {\n ts: raw.timestamp,\n kind: 'scroll',\n text: truncate(`scrolled to ${pct}% of the page`),\n };\n }\n\n case 'ui.scroll_thrash': {\n return {\n ts: raw.timestamp,\n kind: 'scroll',\n text: 'scrolled up and down repeatedly (looking for something)',\n };\n }\n\n case 'ui.idle': {\n const ms = typeof props.durationMs === 'number' ? props.durationMs : null;\n const secs = ms !== null ? Math.round(ms / 1000) : null;\n return {\n ts: raw.timestamp,\n kind: 'idle',\n text: secs !== null ? `idle for ${secs}s` : 'idle',\n };\n }\n\n case 'ui.hover': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'hover',\n text: truncate(`hovered on '${text}'`),\n };\n }\n\n case 'ui.hesitation': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'hesitation',\n text: truncate(`hesitated near '${text}'`),\n };\n }\n\n case 'ui.focus_bounce': {\n const text = elementText(props) || elementTag(props);\n return {\n ts: raw.timestamp,\n kind: 'form',\n text: truncate(`focused '${text}' but didn't fill it`),\n };\n }\n\n default: {\n const allow = opts.observableEvents ?? [];\n if (allow.includes(raw.event)) {\n return {\n ts: raw.timestamp,\n kind: 'custom',\n text: truncate(renderCustomEvent(raw)),\n };\n }\n return null;\n }\n }\n}\n", "/**\n * In-memory batching queue for ObservationEvents.\n *\n * Holds events until either a size threshold or a time interval triggers\n * a flush. The flush function is injected so transport choice (fetch vs.\n * sendBeacon) and auth wiring stay out of this module.\n *\n * Backoff strategy: pure exponential, starting at 1s and capping at 30s\n * (1s \u2192 2s \u2192 4s \u2192 8s \u2192 16s \u2192 30s). Reset on first successful flush.\n * Jitter is intentionally omitted \u2014 the observer queue is per-client, so\n * thundering-herd at recovery is not a meaningful risk, and deterministic\n * timing keeps unit tests fast and stable. A \"permanent\" failure (4xx\n * marked by the caller) disables the queue entirely \u2014 no further flushes\n * are attempted; lastError is exposed via stats().\n */\n\nimport type { ObservationEvent } from './allowlist';\n\nexport interface FlushError extends Error {\n /** When true, the queue stops trying forever. Set by transport for 4xx. */\n permanent?: boolean;\n}\n\nexport interface ObserverQueueOptions {\n batchSize: number;\n flushIntervalMs: number;\n queueCap: number;\n flush: (batch: ObservationEvent[]) => Promise<void>;\n backoffStartMs?: number;\n backoffCapMs?: number;\n}\n\nexport interface ObserverStats {\n queued: number;\n sent: number;\n dropped: number;\n lastError: string | null;\n disabled: boolean;\n}\n\nexport class ObserverQueue {\n private readonly _opts: Required<ObserverQueueOptions>;\n private readonly _buffer: ObservationEvent[] = [];\n private _sent = 0;\n private _dropped = 0;\n private _lastError: string | null = null;\n private _disabled = false;\n private _intervalTimer: ReturnType<typeof setTimeout> | null = null;\n private _backoffTimer: ReturnType<typeof setTimeout> | null = null;\n private _currentBackoffMs = 0;\n private _inFlight = false;\n\n constructor(opts: ObserverQueueOptions) {\n this._opts = {\n backoffStartMs: 1000,\n backoffCapMs: 30_000,\n ...opts,\n };\n }\n\n push(event: ObservationEvent): void {\n if (this._disabled) return;\n if (this._buffer.length >= this._opts.queueCap) {\n this._buffer.shift();\n this._dropped += 1;\n }\n this._buffer.push(event);\n\n if (this._buffer.length >= this._opts.batchSize) {\n this._scheduleImmediate();\n } else {\n this._scheduleInterval();\n }\n }\n\n async flushNow(): Promise<void> {\n this._clearInterval();\n await this._flush();\n }\n\n stats(): ObserverStats {\n return {\n queued: this._buffer.length,\n sent: this._sent,\n dropped: this._dropped,\n lastError: this._lastError,\n disabled: this._disabled,\n };\n }\n\n private _scheduleImmediate(): void {\n queueMicrotask(() => {\n void this._flush();\n });\n }\n\n private _scheduleInterval(): void {\n if (this._intervalTimer != null) return;\n this._intervalTimer = setTimeout(() => {\n this._intervalTimer = null;\n void this._flush();\n }, this._opts.flushIntervalMs);\n }\n\n private _clearInterval(): void {\n if (this._intervalTimer != null) {\n clearTimeout(this._intervalTimer);\n this._intervalTimer = null;\n }\n }\n\n private async _flush(): Promise<void> {\n if (this._disabled || this._inFlight || this._buffer.length === 0) return;\n this._clearInterval();\n\n const batch = this._buffer.splice(0, this._opts.batchSize);\n this._inFlight = true;\n try {\n await this._opts.flush(batch);\n this._sent += batch.length;\n this._currentBackoffMs = 0;\n this._lastError = null;\n } catch (err) {\n this._buffer.unshift(...batch);\n const perm = (err as FlushError)?.permanent === true;\n this._lastError =\n err instanceof Error ? err.message : String((err as { message?: unknown })?.message ?? err);\n if (perm) {\n this._disabled = true;\n } else {\n this._scheduleBackoff();\n }\n } finally {\n this._inFlight = false;\n }\n }\n\n private _scheduleBackoff(): void {\n const next =\n this._currentBackoffMs === 0\n ? this._opts.backoffStartMs\n : Math.min(this._currentBackoffMs * 2, this._opts.backoffCapMs);\n this._currentBackoffMs = next;\n\n if (this._backoffTimer != null) clearTimeout(this._backoffTimer);\n this._backoffTimer = setTimeout(() => {\n this._backoffTimer = null;\n void this._flush();\n }, next);\n }\n}\n", "/**\n * HTTP transport for the observer queue.\n *\n * Two send paths:\n * - send(batch) \u2014 async fetch. Used for normal flushes. Throws on\n * non-2xx; sets the FlushError.permanent flag for 4xx so the queue\n * stops trying.\n * - sendBeacon(batch) \u2014 fire-and-forget via navigator.sendBeacon.\n * Used on `pagehide` so the last batch survives navigation. No\n * error path \u2014 beacon failure is invisible by design.\n *\n * Auth: same syn_ Bearer token mechanism as /stream. The token is read\n * via a getter so SDK tokens that rotate live get refreshed naturally.\n */\n\nimport type { ObservationEvent } from './allowlist';\n\nexport interface TransportOptions {\n url: string;\n token: () => string;\n getDistinctId: () => string | null;\n getSessionId: () => string | null;\n}\n\nexport interface Transport {\n send(batch: ObservationEvent[]): Promise<void>;\n sendBeacon(batch: ObservationEvent[]): boolean;\n}\n\ninterface RequestBody {\n distinct_id: string;\n session_id: string;\n batch: ObservationEvent[];\n}\n\n/**\n * Build the POST body, or null when PostHog can't give us BOTH a distinct_id\n * and a session_id. The backend keys the visitor buffer by distinct_id and\n * scopes the live drain by session_id, so without both there is nothing to\n * write \u2014 we drop the batch rather than POST a request the backend would 422\n * (which the queue treats as a permanent disable). No fallback ids by design:\n * consent-denied / hard-cookieless visitors simply get no personalization.\n */\nfunction buildBody(\n distinctId: string | null,\n sessionId: string | null,\n batch: ObservationEvent[]\n): string | null {\n if (!distinctId || !sessionId) return null;\n const body: RequestBody = { distinct_id: distinctId, session_id: sessionId, batch };\n return JSON.stringify(body);\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n return {\n async send(batch: ObservationEvent[]): Promise<void> {\n const body = buildBody(opts.getDistinctId(), opts.getSessionId(), batch);\n // No PostHog ids \u2192 nothing to buffer. Drop silently (not an error, not a\n // permanent disable): a later flush may have ids once PostHog resolves.\n if (body === null) return;\n const resp = await fetch(opts.url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${opts.token()}`,\n 'Content-Type': 'application/json',\n },\n body,\n keepalive: true,\n credentials: 'include',\n });\n if (!resp.ok) {\n const err = new Error(`observation POST ${resp.status}`) as Error & {\n permanent?: boolean;\n };\n // 4xx is permanent (bad token, malformed payload, etc.) EXCEPT 429:\n // the rate-limit middleware buckets /api/adaptive by workspace token,\n // so a busy site hitting 200/min should back off, not give up forever.\n if (resp.status >= 400 && resp.status < 500 && resp.status !== 429) {\n err.permanent = true;\n }\n throw err;\n }\n },\n\n sendBeacon(batch: ObservationEvent[]): boolean {\n const body = buildBody(opts.getDistinctId(), opts.getSessionId(), batch);\n if (body === null) return false;\n const blob = new Blob([body], { type: 'application/json' });\n const beacon = navigator?.sendBeacon;\n if (typeof beacon !== 'function') return false;\n return beacon.call(navigator, opts.url, blob);\n },\n };\n}\n", "/**\n * Observer entry point.\n *\n * startObserver wires the four pieces \u2014 allowlist filter + queue +\n * transport + PostHog subscription \u2014 into a single lifecycle controlled\n * via the returned handle. The handle is reference-counted: multiple\n * call sites (e.g. multiple chatbot widgets on the same page) share\n * one observer.\n *\n * Idempotent: calling startObserver twice with equivalent options\n * returns the same instance. Calling stop() decrements the ref count;\n * the observer tears down only when the count reaches zero.\n */\n\nimport { matchEvent, type RawEvent } from './allowlist';\nimport { ObserverQueue, type ObserverStats } from './queue';\nimport { createTransport, type Transport } from './transport';\n\nexport interface StartObserverOptions {\n url: string;\n token: () => string;\n getDistinctId: () => string | null;\n getSessionId: () => string | null;\n observableEvents?: readonly string[];\n /** Test seam: override fetch/timer behavior by injecting a custom transport. */\n transport?: Transport;\n}\n\nexport interface ObserverHandle {\n stop(): void;\n stats(): ObserverStats;\n /** Test seam: ingest a raw event directly without depending on PostHog being loaded. */\n ingest(raw: RawEvent): void;\n flushNow(): Promise<void>;\n}\n\ninterface ActiveObserver {\n refCount: number;\n queue: ObserverQueue;\n unsubscribe: () => void;\n options: StartObserverOptions;\n}\n\nlet _active: ActiveObserver | null = null;\n\nfunction _attachPostHog(\n ingest: (raw: RawEvent) => void,\n _observableEvents: readonly string[]\n): () => void {\n const ph = (globalThis as { posthog?: unknown }).posthog;\n if (!ph) return () => {};\n\n // PostHog's internal hook for \"an event was just captured\". The hook\n // fires for $pageview, $autocapture, $rageclick, $dead_click, and any\n // custom posthog.capture(name, props) call \u2014 exactly what the observer\n // wants. Used by the runtime SDK's bundled dist (smart-canvas.*.js).\n const addHook = (ph as { _addCaptureHook?: unknown })._addCaptureHook;\n if (typeof addHook !== 'function') return () => {};\n\n const handler = (eventName: string, properties: Record<string, unknown> | undefined) => {\n if (typeof eventName !== 'string') return;\n ingest({\n event: eventName,\n timestamp: Date.now(),\n properties: properties ?? {},\n });\n };\n\n // _addCaptureHook returns void in current PostHog SDK versions (no\n // unsubscribe). We accept that the listener leaks for the page lifetime \u2014\n // disabling it lives on the queue's `_disabled` flag instead.\n (addHook as (cb: typeof handler) => void).call(ph, handler);\n return () => {};\n}\n\nfunction _attachPageHide(_transport: Transport, queue: ObserverQueue): () => void {\n const handler = () => {\n const stats = queue.stats();\n if (stats.queued > 0) {\n void queue.flushNow();\n }\n };\n window.addEventListener('pagehide', handler, { capture: true });\n return () => window.removeEventListener('pagehide', handler, { capture: true });\n}\n\nexport function startObserver(opts: StartObserverOptions): ObserverHandle {\n if (_active) {\n _active.refCount += 1;\n return _makeHandle();\n }\n\n const transport = opts.transport ?? createTransport(opts);\n\n const queue = new ObserverQueue({\n batchSize: 10,\n flushIntervalMs: 2000,\n queueCap: 200,\n flush: (batch) => transport.send(batch),\n });\n\n const ingest = (raw: RawEvent) => {\n const ev = matchEvent(raw, { observableEvents: opts.observableEvents });\n if (ev !== null) {\n queue.push(ev);\n }\n };\n\n const unsubscribePh = _attachPostHog(ingest, opts.observableEvents ?? []);\n const unsubscribePageHide = _attachPageHide(transport, queue);\n\n _active = {\n refCount: 1,\n queue,\n unsubscribe: () => {\n unsubscribePh();\n unsubscribePageHide();\n },\n options: opts,\n };\n\n return _makeHandle();\n}\n\nfunction _makeHandle(): ObserverHandle {\n return {\n stop(): void {\n if (!_active) return;\n _active.refCount -= 1;\n if (_active.refCount <= 0) {\n _active.unsubscribe();\n _active = null;\n }\n },\n stats(): ObserverStats {\n return (\n _active?.queue.stats() ?? {\n queued: 0,\n sent: 0,\n dropped: 0,\n lastError: null,\n disabled: true,\n }\n );\n },\n ingest(raw: RawEvent): void {\n if (!_active) return;\n const ev = matchEvent(raw, {\n observableEvents: _active.options.observableEvents,\n });\n if (ev !== null) _active.queue.push(ev);\n },\n flushNow(): Promise<void> {\n return _active?.queue.flushNow() ?? Promise.resolve();\n },\n };\n}\n\n/** Test-only: reset module singleton state. */\nexport function _resetObserverForTests(): void {\n if (_active) {\n _active.unsubscribe();\n _active = null;\n }\n}\n", "/**\n * AdaptiveChatBarMountable \u2014 `MountableWidget` adapter that turns the\n * standalone `<adaptive-chat-bar>` Lit element into something the\n * runtime widget registry can mount.\n *\n * Registered as widget id `adaptive-chatbot:chat-bar`. Customers\n * reference it from canvas config \u2014 either as a slot's `lid` widget\n * (replaces the launcher when referenced from `slots.drawer.lid`) or\n * as a regular tile widget.\n *\n * The bar is a VIEW. State lives in the singleton `chatSession` \u2014\n * whether the bar mounts in the mini-canvas lid, the drawer lid, or\n * both, they're all views of the same conversation. The mountable:\n * - subscribes to chatSession.subscribe() and pushes state into\n * the bar's `messages` + `inFlight` props on every change\n * - routes the bar's `chat-message-sent` event \u2192 chatSession.send()\n * - routes the bar's `chat-interrupt` event \u2192 chatSession.interrupt()\n * - bubbles the bar's `canvas-close` event \u2192 optional onClose\n * callback (canvas-level concern, not session-level)\n *\n * Props (passed via mountConfig):\n * - `placeholder?: string` \u2014 input placeholder copy\n * - `onClose?: () => void` \u2014 fires on \u2715 click (canvas-level)\n *\n * Note: messages and inFlight are NOT props. They flow from chatSession.\n * A canvas-config author who wants to pre-seed messages should do so\n * via the session directly (e.g. via a startup action) \u2014 but typical\n * use is to let the conversation start empty.\n */\n\nimport './AdaptiveChatBar';\nimport type { AdaptiveChatBar } from './AdaptiveChatBar';\nimport { renderFallbackHtml } from './ChatAssistantLit';\nimport type { Unsubscribe } from './ChatSession';\nimport { chatSession } from './ChatSession';\nimport type { ChatTransportConfig } from './ChatTransport';\nimport { chatTransport } from './ChatTransport';\nimport {\n ActionHandler,\n ElementInstanceStore,\n type ElementMutation,\n fetchMountedElements,\n ItemHandler,\n TileHandler,\n} from './elements';\nimport { startObserver } from './observer';\nimport type { ChatbotFallback, ChatbotWidgetRuntime } from './types.js';\n\ninterface ChatBarMountConfig {\n placeholder?: string;\n /** Initial assistant greeting shown before any real conversation. */\n greeting?: string;\n /**\n * Pre-conversation tap-target rendered alongside the greeting when\n * the trail is empty. `label` is the button copy; `prompt` is what\n * gets sent through the normal chat-send path on tap.\n */\n introSuggestion?: { label: string; prompt: string };\n /** Forward to AdaptiveChatBar.forceExpanded (full-screen surfaces). */\n forceExpanded?: boolean;\n onClose?: () => void;\n /**\n * Backend host for the live chat transport. Same shape as\n * ChatbotConfig.backendUrl. When provided alongside `runtime`, the\n * bar configures the singleton ChatTransport on first mount so\n * sends hit the real `/api/adaptive/stream` SSE pipeline. Omitting\n * either disables the transport \u2014 the bar stays a pure view and\n * nothing replies. Useful for storybook / config-preview surfaces.\n */\n backendUrl?: string;\n /** Runtime injected by WidgetRegistry \u2014 required for backendUrl wiring. */\n runtime?: ChatbotWidgetRuntime;\n /** Optional thread id for conversation continuity across reloads. */\n threadId?: string;\n /**\n * Per-customer \"chat unavailable\" card. Rendered in place of the\n * chat bar when the transport gives up after sustained failure.\n * Mirrors ChatAssistantLit's fallback behaviour.\n */\n fallback?: ChatbotFallback;\n /**\n * Declarations for the LLM-authored UI element pipeline (Phase 5+).\n * When `elementsEnabled === true` AND `uiTemplates` is non-null, the\n * backend exposes `mount_element` / `patch_element` / `unmount_element`\n * tools to the chat agent, scoped to the templates declared here.\n *\n * Shape mirrors `UiTemplatesBlock` from `syntrologie_common.sdk.templates`\n * \u2014 typed loosely on the SDK side because the SDK never introspects\n * templates (it only receives mount/patch/unmount mutations); the\n * backend Pydantic models are the validation gate.\n *\n * Passed verbatim as `forwardedProps.uiTemplates` to the AG-UI\n * transport so the backend's `/api/adaptive/stream` reads them off\n * the inbound request body.\n */\n uiTemplates?: Record<string, unknown>;\n elementsEnabled?: boolean;\n /**\n * Slot name the runtime mounted this chat-bar into (e.g. ``\"drawer\"``,\n * ``\"adaptive-chat\"``). Injected by the host SDK slot components\n * (SyntroCanvasOverlay for the drawer, SyntroInlineSlot for inline\n * slots) so the chat-bar can forward it to the backend as\n * ``X-Active-Lid-Slot``. The backend uses it to mount tiles into the\n * canvas spatially nearest to the lid the visitor is engaging with.\n * Optional \u2014 older host bundles that don't inject this still work;\n * the backend falls back to the template's static default_slot.\n */\n _syntroSlotName?: string;\n}\n\ninterface MountState {\n bar: AdaptiveChatBar;\n cleanup: () => void;\n cfg: ChatBarMountConfig;\n}\n\nconst STATE_KEY = '__syntroChatBarMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyPlaceholder(bar: AdaptiveChatBar, cfg: ChatBarMountConfig): void {\n if (cfg.placeholder !== undefined) bar.placeholder = cfg.placeholder;\n if (cfg.greeting !== undefined) bar.greeting = cfg.greeting;\n bar.introSuggestion = cfg.introSuggestion;\n // Toggle independently \u2014 undefined means \"leave whatever the element\n // currently has\". Boolean cast keeps the default at false on first\n // mount when the field is absent.\n bar.forceExpanded = cfg.forceExpanded === true;\n}\n\n/**\n * Configure the singleton transport if the caller supplied a backend\n * URL + runtime. Idempotent \u2014 second mount with same args is a no-op.\n * Missing backendUrl OR runtime leaves the transport untouched (the\n * bar is then a pure local view; useful for previews / storybook).\n *\n * Spread (not cherry-pick) so the bar-only fields (placeholder,\n * onClose) flow through silently; ChatTransport ignores them. Cast\n * narrows after the guard.\n */\n/**\n * Lazily-constructed ElementInstanceStore singleton for the chat-bar\n * surface. Mounted on first configure with `elementsEnabled` so the\n * `runtime` closure is captured; subsequent reconfigures with the same\n * runtime reuse it. ChatAssistantLit owns its own store separately \u2014\n * each surface keeps independent state to avoid cross-surface\n * double-mounts on the same instance_id.\n */\nlet _elementStore: ElementInstanceStore | null = null;\n/**\n * Live ``template_id \u2192 widget`` map. Re-derived on each ``configure()``\n * from the chat-bar's ``uiTemplates`` prop (which mirrors what the admin\n * declared in canvas-config). Both the TileHandler (live mount path) and\n * the ElementInstanceStore (rehydrate replay path) read through this map\n * so the widget id stays consistent regardless of mount provenance.\n *\n * Without this, an LLM-authored mount with ``template_id: \"product-card\"``\n * emits ``widget: \"product-card\"`` to the runtime, which then renders the\n * tile chrome with a \"Widget not available: product-card\" body because\n * the actual widget is registered as ``adaptive-product:card``.\n */\nconst _templateWidgetMap = new Map<string, string>();\n\nfunction resolveTileWidget(templateId: string): string | undefined {\n return _templateWidgetMap.get(templateId);\n}\n\nfunction refreshTemplateWidgetMap(uiTemplates: Record<string, unknown> | undefined): void {\n _templateWidgetMap.clear();\n if (!uiTemplates) return;\n const tiles = (uiTemplates as { tiles?: Array<{ id?: unknown; widget?: unknown }> }).tiles;\n if (!Array.isArray(tiles)) return;\n for (const t of tiles) {\n const id = typeof t?.id === 'string' ? t.id : null;\n const widget = typeof t?.widget === 'string' ? t.widget : null;\n if (id && widget) _templateWidgetMap.set(id, widget);\n }\n}\n\nfunction getOrCreateElementStore(runtime: ChatbotWidgetRuntime): ElementInstanceStore {\n if (_elementStore) return _elementStore;\n _elementStore = new ElementInstanceStore({\n actions: runtime.actions,\n // Pass the runtime's event bus so ItemHandler can broadcast\n // `element.compositional_append` / `_patch` / `_remove` events\n // to container widgets (chips strip, FAQ accordion, nav tips).\n events: {\n publish: runtime.events.publish.bind(runtime.events),\n subscribe: runtime.events.subscribe?.bind(runtime.events),\n },\n handlers: [new TileHandler(resolveTileWidget), new ActionHandler(), new ItemHandler()],\n resolveTileWidget,\n });\n return _elementStore;\n}\n\n/**\n * Track whether we've already hydrated this store's snapshot. The store\n * itself is a singleton across mounts in the same page session, so we\n * want to hydrate exactly ONCE \u2014 repeated mounts (e.g. after an SPA\n * navigation that unmounts + remounts the chat-bar) reuse the warm\n * store without re-firing handler.mount() for every persisted item.\n *\n * The store's own version-dedup also prevents double-application, but\n * we still don't want to issue redundant HTTP requests on every mount.\n */\nlet _hydrationStarted = false;\n\nfunction hydrateOnce(runtime: ChatbotWidgetRuntime, backendUrl: string): void {\n if (_hydrationStarted) return;\n _hydrationStarted = true;\n const store = getOrCreateElementStore(runtime);\n // The fetcher reads `window.__SYNTRO_CONFIG__.token` by default; the\n // boot path already populated that. Empty/missing backendUrl falls\n // back to a same-origin relative endpoint so dev-server proxies\n // (Vite, Webpack) and host pages serving the SDK from their own\n // domain work without extra config. Same-origin is also the only\n // path that lets the `syntro_chat_session` cookie ride along \u2014 Lax\n // cookies don't follow cross-origin fetches.\n const trimmed = backendUrl.replace(/\\/$/, '');\n const endpoint = trimmed\n ? `${trimmed}/api/adaptive/mounted_elements`\n : '/api/adaptive/mounted_elements';\n fetchMountedElements({ endpoint }).then((response) => {\n if (!response) return; // 404 / network error / feature off \u2014 silent no-op\n // Hydrate replays each instance through its handler.mount(); for\n // ItemHandler that publishes `element.compositional_append` events,\n // which the chips strip subscribes to and re-inserts. Effects are\n // NOT replayed \u2014 they were never persisted in mounted_elements\n // (`_emit_effect_envelope` in the agent skips persistence).\n void store.hydrate(response.mounted_elements);\n });\n}\n\nfunction configureTransportIfPossible(cfg: ChatBarMountConfig): void {\n // Backend URL comes from `runtime.backendUrl` \u2014 the single source of\n // truth set once via `Syntro.init({backendUrl})` (or its SDK-internal\n // prod default if the customer doesn't pass one). The tile's\n // `props.backendUrl` is ignored: there is no per-widget override, the\n // customer integrator chooses the host ONCE at init time and every\n // adaptive uses it.\n if (!cfg.runtime) return;\n const backendUrl = (cfg.runtime as { backendUrl?: string }).backendUrl;\n if (!backendUrl) return;\n // Translate the element-instantiation declarations into the opaque\n // `forwardedProps` bag the transport ships on every AG-UI request.\n // Only attach when the feature is on AND templates are declared \u2014\n // otherwise the backend stays in its safe-default (feature_disabled)\n // path and the tools are never exposed.\n const elementsActive = cfg.elementsEnabled === true && cfg.uiTemplates != null;\n // Refresh the template\u2192widget map on every configure (and clear it\n // when elements are off) so live mounts and replays resolve the same\n // widget id. Done before getOrCreateElementStore below since the\n // store reads through ``resolveTileWidget`` at construction.\n refreshTemplateWidgetMap(elementsActive ? cfg.uiTemplates : undefined);\n const forwardedProps: Record<string, unknown> | undefined = elementsActive\n ? { elementsEnabled: true, uiTemplates: cfg.uiTemplates }\n : undefined;\n\n // Wire the `syntro.element.mutation` envelope route to a per-surface\n // ElementInstanceStore. The store applies mounts/patches/unmounts to\n // the host page via the runtime's ActionEngine. ChatAssistantLit has\n // its own equivalent wiring (it instantiates AgUiTransport directly,\n // not via this singleton); the lid surface needs the same routing\n // here so mount_element results actually land.\n const runtime = cfg.runtime;\n const onElementMutation = elementsActive\n ? (mutations: ElementMutation[]) => {\n void getOrCreateElementStore(runtime).apply(mutations);\n }\n : undefined;\n\n // Hydrate the element store from the backend session on first chat-bar\n // mount. Async \u2014 by the time the response arrives, container widgets\n // (chips strip, FAQ accordion) have already subscribed to the event\n // bus, so the replay events land in their subscribers. Items mounted\n // by the LLM in previous turns survive SPA navigation + page reload\n // for the lifetime of the AdaptiveSession (~24h default).\n if (elementsActive) {\n hydrateOnce(runtime, backendUrl);\n }\n\n chatTransport.configure({\n ...cfg,\n backendUrl,\n forwardedProps,\n onElementMutation,\n activeLidSlot: cfg._syntroSlotName,\n } as ChatTransportConfig);\n\n // Wire the visitor-activity observer once the transport is configured.\n // The observer subscribes to PostHog's capture hook and POSTs batched\n // `nav` / `click` / `form` / `rage` / `dead` events to\n // `/api/adaptive/observation` so the next ``/stream`` turn arrives\n // with `recent_observations` populated \u2014 that's what answers\n // \"what did the visitor just do?\" from the agent's perspective.\n // Without this the observer module is dead code: events sit in\n // PostHog with no path into the agent prompt.\n //\n // Idempotent + ref-counted in `startObserver`, so multiple chat-bar\n // mounts (drawer lid + page anchor) share one observer.\n startObserverIfPossible(cfg);\n}\n\nlet _observerStarted = false;\n\nfunction startObserverIfPossible(cfg: ChatBarMountConfig): void {\n if (_observerStarted) return;\n if (typeof window === 'undefined') return;\n const runtimeRef = cfg.runtime as\n | undefined\n | {\n events?: { subscribe?: (filter: unknown, cb: (e: unknown) => void) => () => void };\n backendUrl?: string;\n telemetry?: {\n getDistinctId?: () => string | undefined;\n getSessionId?: () => string | undefined;\n };\n };\n if (!runtimeRef?.events?.subscribe) return;\n // Read backendUrl from the runtime \u2014 same source of truth as the chat\n // transport, so the observer always hits the same backend instance.\n const trimmed = (runtimeRef.backendUrl ?? '').replace(/\\/$/, '');\n const url = trimmed ? `${trimmed}/api/adaptive/observation` : '/api/adaptive/observation';\n // distinct_id (visitor, cross-session) + session_id (this browsing session)\n // from the SYNTRO RUNTIME's telemetry (the canonical id accessor \u2014 not\n // window.posthog). The backend keys the observation buffer by distinct_id and\n // scopes the live drain by session_id. Both null when the runtime has no id\n // (consent denied / cookieless) \u2014 the transport then drops the batch (no\n // fallback ids, cold personalization by design).\n const runtimeId = (method: 'getDistinctId' | 'getSessionId'): string | null => {\n try {\n const v = runtimeRef.telemetry?.[method]?.();\n return typeof v === 'string' && v.length > 0 ? v : null;\n } catch {\n return null;\n }\n };\n const getDistinctId = (): string | null => runtimeId('getDistinctId');\n const getSessionId = (): string | null => runtimeId('getSessionId');\n const token = (): string => {\n const c = (window as { __SYNTRO_CONFIG__?: { token?: string } }).__SYNTRO_CONFIG__;\n return typeof c?.token === 'string' ? c.token : '';\n };\n // startObserver's PostHog auto-attach is a no-op in environments where\n // `window.posthog` isn't directly exposed (most production builds \u2014\n // PostHog is wrapped by the SDK telemetry layer and surfaced through\n // `SynOS.runtime.events`, not via the global). We always start it for\n // the queue + transport plumbing, then subscribe to the runtime event\n // bus and translate normalized events back into the `RawEvent` shape\n // the observer's allowlist expects.\n const handle = startObserver({ url, token, getDistinctId, getSessionId });\n // Expose queue stats on the window for in-page diagnostics. Lets a\n // tester verify events are queueing / flushing via the devtools\n // console without bouncing into source. Cheap; harmless in prod.\n (window as { __syntroObserverStats?: () => unknown }).__syntroObserverStats = () =>\n handle.stats();\n runtimeRef.events.subscribe({}, (evt: unknown) => {\n const e = evt as {\n ts?: number;\n name?: string;\n source?: string;\n props?: Record<string, unknown> & { originalEvent?: string };\n };\n if (!e?.name) return;\n const ts = typeof e.ts === 'number' ? e.ts : Date.now();\n // Two-path translation. The allowlist's `matchEvent` switches on\n // `event` name, so we just hand it the right name in either case:\n //\n // 1. PostHog-originated events arrive with `source: 'posthog'`\n // and `props.originalEvent` carrying the raw `$pageview` /\n // `$autocapture` name. Re-prefix `pathname`/`url` to their\n // `$`-prefixed forms so the PostHog matchers find them.\n // 2. Canonical runtime-bus events (`nav.section_viewed`,\n // `nav.scroll_depth`, `ui.scroll_thrash`, `ui.hover`, \u2026)\n // come straight from runtime-sdk instrumentation. Forward the\n // canonical name as-is \u2014 the allowlist has explicit cases for\n // each one.\n if (e.source === 'posthog') {\n const original = e.props?.originalEvent;\n if (typeof original !== 'string' || original.length === 0) return;\n const properties: Record<string, unknown> = { ...(e.props ?? {}) };\n if (typeof e.props?.pathname === 'string') properties.$pathname = e.props.pathname;\n if (typeof e.props?.url === 'string') properties.$current_url = e.props.url;\n handle.ingest({ event: original, timestamp: ts, properties });\n return;\n }\n // Forward canonical names directly. The allowlist drops any name\n // it doesn't know, so listing everything here is safe \u2014 match\n // decides what reaches the agent's observation tail.\n handle.ingest({\n event: e.name,\n timestamp: ts,\n properties: { ...(e.props ?? {}) },\n });\n });\n _observerStarted = true;\n}\n\nfunction wireListeners(bar: AdaptiveChatBar, state: MountState): Unsubscribe {\n const onMessageSent = (e: Event) => {\n const text = (e as CustomEvent<{ text: string }>).detail.text;\n // Read `_syntroSlotName` from `state.cfg` (the per-bar snapshot)\n // on EVERY send so the singleton transport tags the outbound\n // request with THIS bar's slot, regardless of which bar most\n // recently called `chatTransport.configure()`. Without this,\n // two coexisting bars (drawer + inline) race over the singleton's\n // cached `activeLidSlot` and tile-routing follows the wrong bar.\n chatSession.send(text, { activeLidSlot: state.cfg._syntroSlotName });\n // If no transport is listening for sends (no backendUrl in\n // mountConfig, the runtime injection didn't happen, or a test\n // didn't wire one up) the session would sit in `inFlight: true`\n // forever. Surface a clear, actionable error so the user sees\n // *something* rather than an indefinitely-spinning stop button.\n if (!chatSession.hasTransport()) {\n chatSession.error('Chat backend not configured \u2014 set backendUrl in the canvas config.');\n }\n };\n const onInterrupt = () => {\n chatSession.interrupt();\n };\n const onToolCallApproved = (e: Event) => {\n const detail = (e as CustomEvent<{ toolCallId: string; approved: boolean }>).detail;\n // Default to an empty-object result \u2014 the agent re-runs with the\n // approval signal. Hosts that want richer results (e.g. a form\n // result payload) can listen for `trail-toolcall-approved` higher\n // up and call chatSession.resolveToolCall themselves.\n chatSession.resolveToolCall(detail.toolCallId, {}, detail.approved);\n };\n // onClose reads state.cfg fresh on each invocation so update() can\n // swap the callback without re-wiring listeners.\n const onClose = () => {\n state.cfg.onClose?.();\n };\n bar.addEventListener('chat-message-sent', onMessageSent);\n bar.addEventListener('chat-interrupt', onInterrupt);\n bar.addEventListener('canvas-close', onClose);\n bar.addEventListener('trail-toolcall-approved', onToolCallApproved);\n return () => {\n bar.removeEventListener('chat-message-sent', onMessageSent);\n bar.removeEventListener('chat-interrupt', onInterrupt);\n bar.removeEventListener('canvas-close', onClose);\n bar.removeEventListener('trail-toolcall-approved', onToolCallApproved);\n };\n}\n\nexport const AdaptiveChatBarMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as ChatBarMountConfig;\n configureTransportIfPossible(cfg);\n const bar = document.createElement('adaptive-chat-bar') as AdaptiveChatBar;\n applyPlaceholder(bar, cfg);\n\n // Subscribe to the shared session. Fires immediately with the\n // current state so the bar reflects any pre-existing conversation.\n const unsubSession = chatSession.subscribe((s) => {\n bar.messages = [...s.messages];\n bar.inFlight = s.inFlight;\n bar.thinkingText = s.thinkingText;\n });\n\n // state holds the mutable cfg so update() can swap callbacks\n // without forcing a listener re-wire.\n const state = { bar, cleanup: () => {}, cfg };\n const unwireListeners = wireListeners(bar, state);\n\n container.appendChild(bar);\n\n // Subscribe to the transport's fallback signal. When the transport\n // gives up after sustained failure, replace the bar with the\n // per-customer \"chat unavailable\" card. One-shot \u2014 fallback fires\n // once per configure cycle, so we don't need to track re-mounts.\n const unsubFallback = chatTransport.onFallback(() => {\n bar.remove();\n container.innerHTML = renderFallbackHtml(state.cfg.fallback);\n });\n\n state.cleanup = () => {\n unsubSession();\n unsubFallback();\n unwireListeners();\n bar.remove();\n setState(container, null);\n };\n\n setState(container, state);\n return state.cleanup;\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as ChatBarMountConfig;\n configureTransportIfPossible(cfg);\n applyPlaceholder(state.bar, cfg);\n state.cfg = cfg;\n },\n};\n", "/**\n * AdaptiveChipsStripMountable \u2014 `MountableWidget` adapter for\n * `<adaptive-chips-strip>`. Registered as widget id\n * `adaptive-chatbot:chips-strip`.\n *\n * Mirrors `AdaptiveChatBarMountable`: creates the Lit element, forwards\n * props, bridges DOM events \u2192 prop callbacks, cleans up on unmount.\n *\n * Props (passed via mountConfig):\n * - `chips: SuggestionChip[]` \u2014 the strip's contents (required)\n * - `onChipRevealed?: ({id, payload}) => void` \u2014 fires when a chip\n * is opened\n * - `onChipDismissed?: ({id}) => void` \u2014 fires when \u00D7 is clicked\n *\n * The runtime registry injects `runtime` into mountConfig (see\n * `WidgetRegistry.mount`). We forward it as `runtimeRef` on the strip\n * so it can mount chip payload widgets through the same registry.\n */\n\nimport './AdaptiveChipsStrip';\nimport type { AdaptiveChipsStrip, SuggestionChip } from './AdaptiveChipsStrip';\n\ninterface ChipsStripMountConfig {\n chips?: SuggestionChip[];\n onChipRevealed?: (detail: { id: string; payload: SuggestionChip['config']['payload'] }) => void;\n onChipDismissed?: (detail: { id: string }) => void;\n // Injected by WidgetRegistry \u2014 see runtime-sdk/src/widgets/WidgetRegistry.ts.\n runtime?: unknown;\n // Injected by SyntroTileCard from the tile's resolved chromeless\n // state (which itself comes from `slot.theme.chromeless` with\n // `tile.chromeless` as the per-tile override).\n chromeless?: boolean;\n}\n\ninterface MountState {\n strip: AdaptiveChipsStrip;\n listeners: {\n revealed: (e: Event) => void;\n dismissed: (e: Event) => void;\n };\n}\n\nconst STATE_KEY = '__syntroChipsStripMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyProps(strip: AdaptiveChipsStrip, cfg: ChipsStripMountConfig): void {\n if (cfg.chips !== undefined) strip.chips = cfg.chips;\n // `runtime` arrives in every mountConfig from the WidgetRegistry \u2014\n // forward it so the strip can resolve + mount payload widgets.\n if (cfg.runtime !== undefined) {\n strip.runtimeRef = cfg.runtime as AdaptiveChipsStrip['runtimeRef'];\n }\n if (cfg.chromeless !== undefined) strip.chromeless = cfg.chromeless;\n}\n\nexport const AdaptiveChipsStripMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as ChipsStripMountConfig;\n const strip = document.createElement('adaptive-chips-strip') as AdaptiveChipsStrip;\n applyProps(strip, cfg);\n\n const state: MountState = {\n strip,\n listeners: {\n revealed: (e) => {\n const cb = cfg.onChipRevealed;\n if (cb) {\n cb(\n (e as CustomEvent<{ id: string; payload: SuggestionChip['config']['payload'] }>)\n .detail\n );\n }\n },\n dismissed: (e) => {\n const cb = cfg.onChipDismissed;\n if (cb) cb((e as CustomEvent<{ id: string }>).detail);\n },\n },\n };\n strip.addEventListener('chip-revealed', state.listeners.revealed);\n strip.addEventListener('chip-dismissed', state.listeners.dismissed);\n\n container.appendChild(strip);\n setState(container, state);\n\n return () => {\n strip.removeEventListener('chip-revealed', state.listeners.revealed);\n strip.removeEventListener('chip-dismissed', state.listeners.dismissed);\n strip.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as ChipsStripMountConfig;\n applyProps(state.strip, cfg);\n // Re-wire callback listeners so the new cfg's handlers fire.\n state.strip.removeEventListener('chip-revealed', state.listeners.revealed);\n state.strip.removeEventListener('chip-dismissed', state.listeners.dismissed);\n state.listeners.revealed = (e) => {\n const cb = cfg.onChipRevealed;\n if (cb) {\n cb((e as CustomEvent<{ id: string; payload: SuggestionChip['config']['payload'] }>).detail);\n }\n };\n state.listeners.dismissed = (e) => {\n const cb = cfg.onChipDismissed;\n if (cb) cb((e as CustomEvent<{ id: string }>).detail);\n };\n state.strip.addEventListener('chip-revealed', state.listeners.revealed);\n state.strip.addEventListener('chip-dismissed', state.listeners.dismissed);\n },\n};\n", "/**\n * NavLinkMountable \u2014 `MountableWidget` used as the payload of an\n * LLM-authored navigation chip.\n *\n * Flow:\n * LLM mounts `suggest-navigation` ItemTemplate with `{title, url}`\n * \u2192 backend builds chip with payload `{widget: 'adaptive-chatbot:nav-link', props: {url}}`\n * \u2192 user clicks the chip \u2192 chips-strip mounts THIS widget into the\n * chip's drawer\n * \u2192 user clicks the \"Go to <url>\" button this widget renders\n * \u2192 same-origin SPA navigation via pushState + popstate (matches\n * `adaptive-nav`'s `executeNavigate` path for SPA-router compatibility)\n *\n * Registered as widget id `adaptive-chatbot:nav-link`.\n *\n * Security note: only http(s), same-origin destinations are honored.\n * `javascript:`, `data:`, and cross-origin URLs are silently dropped at\n * URL construction. The ItemTemplate's EnumField allowlist is the\n * primary constraint; this is defense-in-depth.\n */\n\ninterface NavLinkProps {\n url?: string;\n /** Optional override for the button label. Defaults to \"Go to <url>\".\n * The chip's title already advertises the destination; this is just\n * the call-to-action verb. */\n label?: string;\n}\n\ninterface MountState {\n button: HTMLButtonElement;\n cfg: NavLinkProps;\n onClick: (e: Event) => void;\n}\n\nconst STATE_KEY = '__syntroNavLinkMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction navigateTo(rawUrl: string): void {\n if (!rawUrl) return;\n let resolved: URL;\n try {\n resolved = new URL(rawUrl, window.location.origin);\n } catch {\n return;\n }\n if (resolved.origin !== window.location.origin) return;\n if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return;\n window.history.pushState(null, '', resolved.toString());\n window.dispatchEvent(new PopStateEvent('popstate'));\n}\n\nfunction buildButton(cfg: NavLinkProps): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.dataset.syntroNavLink = '';\n button.style.display = 'inline-flex';\n button.style.alignItems = 'center';\n button.style.gap = '6px';\n button.style.padding = '6px 12px';\n button.style.borderRadius = '8px';\n button.style.fontFamily = \"var(--sc-font-family, 'system-ui')\";\n button.style.fontSize = '12px';\n button.style.fontWeight = '600';\n button.style.cursor = 'pointer';\n button.style.color = 'var(--sc-accent-foreground, currentColor)';\n button.style.background = 'hsl(var(--sc-accent-color) / 0.85)';\n button.style.border = '1px solid hsl(var(--sc-accent-color) / 0.30)';\n applyLabel(button, cfg);\n return button;\n}\n\nfunction applyLabel(button: HTMLButtonElement, cfg: NavLinkProps): void {\n const url = String(cfg.url ?? '');\n const label = cfg.label ?? (url ? `Go to ${url}` : 'Go');\n // textContent (not innerHTML) \u2014 LLM-authored URLs are an enum on the\n // backend so injection isn't realistic, but defense-in-depth is cheap.\n button.textContent = label;\n}\n\nexport const NavLinkMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as NavLinkProps;\n const button = buildButton(cfg);\n const onClick = (_e: Event): void => {\n const current = getState(container);\n const url = current?.cfg.url ?? cfg.url;\n navigateTo(String(url ?? ''));\n };\n button.addEventListener('click', onClick);\n container.appendChild(button);\n setState(container, { button, cfg, onClick });\n return () => {\n button.removeEventListener('click', onClick);\n button.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as NavLinkProps;\n applyLabel(state.button, cfg);\n state.cfg = cfg;\n },\n};\n", "/**\n * TextAnswerMountable \u2014 `MountableWidget` for the simplest chip payload\n * kind: a single paragraph of body text.\n *\n * Registered as widget id `adaptive-chatbot:text-answer`. Used by\n * `AdaptiveChipsStrip` when a chip's payload references it.\n *\n * Replaces the old hand-rolled resolver path. Customers wanting richer\n * payloads (markdown, mini-product cards, embedded charts, etc.) ship\n * their own mountable through the same registry \u2014 no special\n * resolver-map seam.\n */\n\ninterface TextAnswerProps {\n text?: string;\n}\n\ninterface MountState {\n paragraph: HTMLParagraphElement;\n cfg: TextAnswerProps;\n}\n\nconst STATE_KEY = '__syntroTextAnswerMount';\n\nfunction getState(container: HTMLElement): MountState | null {\n return (container as unknown as Record<string, MountState | undefined>)[STATE_KEY] ?? null;\n}\nfunction setState(container: HTMLElement, state: MountState | null): void {\n (container as unknown as Record<string, MountState | null>)[STATE_KEY] = state;\n}\n\nfunction applyText(p: HTMLParagraphElement, text: string): void {\n p.textContent = text;\n}\n\nexport const TextAnswerMountable = {\n mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void {\n const cfg = (mountConfig ?? {}) as TextAnswerProps;\n const paragraph = document.createElement('p');\n paragraph.dataset.syntroTextAnswer = '';\n // Keep the styling minimal \u2014 paragraph inherits the slot's\n // `--sc-tile-text-color` (set by the chips strip's drawer chrome)\n // so the text reads consistently against the host's surface.\n paragraph.style.margin = '0';\n paragraph.style.fontSize = '12px';\n paragraph.style.lineHeight = '1.55';\n paragraph.style.color = 'var(--sc-tile-text-color, currentColor)';\n applyText(paragraph, String(cfg.text ?? ''));\n container.appendChild(paragraph);\n\n setState(container, { paragraph, cfg });\n return () => {\n paragraph.remove();\n setState(container, null);\n };\n },\n\n update(container: HTMLElement, mountConfig?: Record<string, unknown>): void {\n const state = getState(container);\n if (!state) return;\n const cfg = (mountConfig ?? {}) as TextAnswerProps;\n applyText(state.paragraph, String(cfg.text ?? ''));\n state.cfg = cfg;\n },\n};\n", "/**\n * Adaptive Chatbot - Runtime Module\n *\n * Runtime manifest for the AI chat assistant adaptive.\n * Uses @syntrologie/chat for the UI \u2014 no React dependency.\n *\n * Chat surfaces are config-driven: customers reference the chat-bar\n * widget id (`adaptive-chatbot:chat-bar`) from `slots.drawer.lid` (to\n * replace the launcher FAB) or any other slot's `lid` / tile slot. The\n * adaptive no longer auto-registers a canvas lid renderer.\n */\n\n// Side-effect imports so the custom elements register with the global\n// registry as soon as the adaptive is loaded.\nimport './AdaptiveChatBar';\nimport './AdaptiveChatTrail';\nimport { AdaptiveChatBarMountable } from './AdaptiveChatBarMountable';\nimport { AdaptiveChipsStripMountable } from './AdaptiveChipsStripMountable';\nimport { ChatAssistantLitMountable } from './ChatAssistantLit';\nimport { NavLinkMountable } from './NavLinkMountable';\nimport { TextAnswerMountable } from './TextAnswerMountable';\n\nexport const runtime = {\n id: 'adaptive-chatbot',\n version: '2.0.0',\n name: 'Chat Assistant',\n description: 'AI chat assistant powered by @syntrologie/chat with SSE transport',\n\n executors: [],\n\n widgets: [\n {\n id: 'adaptive-chatbot:assistant',\n component: ChatAssistantLitMountable,\n metadata: {\n name: 'Chat Assistant',\n description: 'AI-powered chat assistant with SSE streaming and A2UI support',\n icon: '\uD83D\uDCAC',\n },\n },\n // PRD \u00A73 chat lid: the standalone chat bar UI shell. Used as a slot\n // `lid` widget (where it replaces the launcher) or as a regular\n // tile widget (renders inside the drawer). Headless of any chat\n // transport \u2014 emits chat-message-sent / chat-interrupt / canvas-close\n // for the parent to wire to whatever pipeline it owns.\n {\n id: 'adaptive-chatbot:chat-bar',\n component: AdaptiveChatBarMountable,\n metadata: {\n name: 'Chat Bar',\n description:\n 'Always-visible chat input row with bubble-up trail. Headless \u2014 wire to your own transport.',\n icon: '\u2726',\n },\n },\n // PRD \u00A74.5 suggested-chips tile: horizontally-wrapping chip strip\n // with click-to-reveal payload drawer. Each chip is a\n // `suggestions:chip` action.\n {\n id: 'adaptive-chatbot:chips-strip',\n component: AdaptiveChipsStripMountable,\n metadata: {\n name: 'Suggested Chips',\n description: 'Wrapping chip strip with click-to-reveal payloads.',\n icon: '\u2728',\n },\n },\n // Built-in chip payload \u2014 a single paragraph of body text. Chip\n // payloads are widget references (same {widget,props} shape as\n // tile/lid configs); this is the simplest one shipped out of the\n // box so the chip pattern works without requiring a downstream\n // adaptive for a \"just answer with text\" case.\n {\n id: 'adaptive-chatbot:text-answer',\n component: TextAnswerMountable,\n metadata: {\n name: 'Text Answer',\n description: 'Single paragraph payload \u2014 the default chip-drawer content.',\n icon: '\u00B6',\n },\n },\n // Chip payload for LLM-authored navigation suggestions. Backed by\n // the `suggest-navigation` ItemTemplate: the backend wraps a curated\n // URL into props.url, the chip's payload-drawer mounts this widget,\n // user clicks \"Go to <url>\" \u2192 same-origin SPA navigation. Kept here\n // (not in adaptive-nav) so chip payloads ship with the chatbot\n // bundle that already provides chips-strip + text-answer.\n {\n id: 'adaptive-chatbot:nav-link',\n component: NavLinkMountable,\n metadata: {\n name: 'Nav Link',\n description:\n 'Same-origin navigation button \u2014 used as a chip payload for LLM-authored nav suggestions.',\n icon: '\u2192',\n },\n },\n ],\n};\n\nexport default runtime;\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAyEO,IAAM,2BAA2B;AAOxC,SAAS,eAAe,OAAuC;AAC7D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,UACG,OAAO,EAAE,OAAO,YAAY,OAAO,EAAE,OAAO,cAC5C,EAAE,SAAS,UAAU,EAAE,SAAS,eAAe,EAAE,SAAS,aAC3D,OAAO,EAAE,SAAS;AAEtB;AAEA,SAAS,kBAAyC;AAChD,MAAI;AACF,UAAM,MAAM,WAAW,cAAc,QAAQ,wBAAwB;AACrE,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,CAAC,UAAU,CAAC,MAAM,QAAQ,OAAO,QAAQ,EAAG,QAAO;AACvD,UAAM,WAAW,OAAO,SAAS,OAAO,cAAc;AACtD,UAAM,SAAS,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS,SAAS,SAAS;AACrF,WAAO,EAAE,UAAU,OAAO;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,cAAN,MAAkB;AAAA,EAWvB,cAAc;AAVd,SAAQ,YAA4B,CAAC;AACrC,SAAQ,YAAY;AACpB,SAAQ,gBAAgB;AACxB,SAAQ,UAAU;AAElB,SAAQ,cAAc,oBAAI,IAA2B;AACrD,SAAQ,gBAAgB,oBAAI,IAAkB;AAC9C,SAAQ,qBAAqB,oBAAI,IAAuB;AACxD,SAAQ,sBAAsB,oBAAI,IAAwB;AAGxD,UAAM,WAAW,gBAAgB;AACjC,QAAI,UAAU;AACZ,WAAK,YAAY,SAAS;AAC1B,WAAK,UAAU,SAAS;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAGA,WAA6B;AAC3B,WAAO;AAAA,MACL,UAAU,CAAC,GAAG,KAAK,SAAS;AAAA,MAC5B,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,OAAqB;AACvC,QAAI,CAAC,MAAO;AACZ,SAAK,iBAAiB;AACtB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,MAAoB;AAClC,QAAI,KAAK,kBAAkB,KAAM;AACjC,SAAK,gBAAgB;AACrB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAsB;AACpB,QAAI,CAAC,KAAK,cAAe;AACzB,SAAK,gBAAgB;AACrB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,IAAwC;AAChD,SAAK,YAAY,IAAI,EAAE;AACvB,OAAG,KAAK,SAAS,CAAC;AAClB,WAAO,MAAM;AACX,WAAK,YAAY,OAAO,EAAE;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,MAAc,MAA0B;AAC3C,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AACd,SAAK,UAAU,KAAK,EAAE,IAAI,KAAK,WAAW,MAAM,QAAQ,MAAM,QAAQ,CAAC;AACvE,SAAK,YAAY;AACjB,SAAK,OAAO;AACZ,UAAM,QAAkD,EAAE,MAAM,QAAQ;AACxE,QAAI,MAAM,cAAe,OAAM,gBAAgB,KAAK;AACpD,eAAW,YAAY,KAAK,cAAe,UAAS,KAAK;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAAoB;AAC1B,UAAM,KAAK,KAAK,KAAK,SAAS;AAC9B,SAAK,UAAU,KAAK,EAAE,IAAI,MAAM,aAAa,MAAM,QAAQ,WAAW,CAAC;AACvE,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,IAAkB;AAC7B,SAAK,UAAU,KAAK,EAAE,IAAI,MAAM,aAAa,MAAM,IAAI,QAAQ,YAAY,CAAC;AAC5E,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,IAAY,OAAqB;AAC5C,UAAM,MAAM,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,QAAI,CAAC,OAAO,IAAI,WAAW,YAAa;AACxC,QAAI,QAAQ;AACZ,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,IAAkB;AAC3B,UAAM,MAAM,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,QAAI,OAAO,IAAI,WAAW,aAAa;AACrC,UAAI,SAAS;AAAA,IACf;AACA,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SAAuB;AAC3B,eAAW,KAAK,KAAK,WAAW;AAC9B,UAAI,EAAE,WAAW,YAAa,GAAE,SAAS;AAAA,IAC3C;AACA,SAAK,UAAU,KAAK;AAAA,MAClB,IAAI,OAAO,KAAK,SAAS;AAAA,MACzB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,IACV,CAAC;AACD,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,YAAkB;AAChB,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,OAAO;AACZ,eAAW,YAAY,KAAK,mBAAoB,UAAS;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACZ,SAAK,YAAY,CAAC;AAClB,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,UAAU;AACf,SAAK,OAAO;AAAA,EACd;AAAA;AAAA,EAGA,OAAO,UAAqC;AAC1C,SAAK,cAAc,IAAI,QAAQ;AAC/B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,QAAQ;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAwB;AACtB,WAAO,KAAK,cAAc,OAAO;AAAA,EACnC;AAAA;AAAA,EAGA,YAAY,UAA0C;AACpD,SAAK,mBAAmB,IAAI,QAAQ;AACpC,WAAO,MAAM;AACX,WAAK,mBAAmB,OAAO,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,UAA2C;AACtD,SAAK,oBAAoB,IAAI,QAAQ;AACrC,WAAO,MAAM;AACX,WAAK,oBAAoB,OAAO,QAAQ;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY,WAA4B,UAA+B;AACrE,UAAM,MAAM,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AACzD,QAAI,CAAC,IAAK;AACV,QAAI,YAAY,CAAC,GAAI,IAAI,aAAa,CAAC,GAAI,EAAE,GAAG,SAAS,CAAC;AAC1D,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,YAAoB,OAAqC;AACtE,eAAW,OAAO,KAAK,WAAW;AAChC,YAAM,MAAM,IAAI;AAChB,UAAI,CAAC,IAAK;AACV,YAAM,MAAM,IAAI,UAAU,CAAC,OAAO,GAAG,OAAO,UAAU;AACtD,UAAI,QAAQ,GAAI;AAChB,YAAM,OAAO,CAAC,GAAG,GAAG;AACpB,WAAK,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,MAAM;AACrC,UAAI,YAAY;AAChB,WAAK,OAAO;AACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,YAAoB,QAAiB,UAAyB;AAC5E,QAAI,QAAQ;AACZ,eAAW,OAAO,KAAK,WAAW;AAChC,YAAM,MAAM,IAAI;AAChB,UAAI,CAAC,IAAK;AACV,YAAM,MAAM,IAAI,UAAU,CAAC,OAAO,GAAG,OAAO,UAAU;AACtD,UAAI,QAAQ,GAAI;AAChB,YAAM,OAAO,CAAC,GAAG,GAAG;AACpB,WAAK,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,QAAQ,OAAO;AAC3C,UAAI,YAAY;AAChB,cAAQ;AACR;AAAA,IACF;AACA,QAAI,CAAC,MAAO;AACZ,SAAK,OAAO;AACZ,eAAW,YAAY,KAAK,qBAAqB;AAC/C,eAAS,EAAE,YAAY,QAAQ,SAAS,CAAC;AAAA,IAC3C;AAAA,EACF;AAAA,EAEQ,SAAe;AACrB,UAAM,QAAQ,KAAK,SAAS;AAC5B,SAAK,QAAQ;AACb,eAAW,OAAO,KAAK,YAAa,KAAI,KAAK;AAAA,EAC/C;AAAA,EAEQ,UAAgB;AACtB,QAAI;AACF,UAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,mBAAW,cAAc,WAAW,wBAAwB;AAC5D;AAAA,MACF;AACA,YAAM,UAA0B,EAAE,UAAU,KAAK,WAAW,QAAQ,KAAK,QAAQ;AACjF,iBAAW,cAAc,QAAQ,0BAA0B,KAAK,UAAU,OAAO,CAAC;AAAA,IACpF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAYO,IAAM,cAAc,IAAI,YAAY;;;ACtSpC,IAAM,uBAAuB;AAmCpC,SAAS,kBAAsC;AAC7C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,MAAO,OAAiE;AAC9E,QAAM,QAAQ,KAAK;AACnB,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAQA,SAAS,SAAS,MAAuB;AACvC,MAAI,OAAO,WAAW,YAAa;AACnC,MAAK,OAA0D,uBAAuB;AACpF,YAAQ,MAAM,oBAAoB,GAAG,IAAI;AAAA,EAC3C;AACF;AAQA,SAAS,kBAAkB,MAAsB;AAC/C,QAAM,KAAK,QAAQ,IAAI,YAAY;AACnC,MAAI,EAAE,SAAS,QAAQ,EAAG,QAAO;AACjC,MAAI,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,MAAM,EAAG,QAAO;AACtD,MAAI,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,SAAS,EAAG,QAAO;AACxD,MAAI,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,SAAS,KAAK,EAAE,SAAS,SAAS;AACtE,WAAO;AACT,MAAI,EAAE,SAAS,UAAU,KAAK,EAAE,SAAS,SAAS,KAAK,EAAE,SAAS,QAAQ;AACxE,WAAO;AACT,SAAO;AACT;AAaA,SAAS,oBACP,MACA,MACqB;AACrB,MAAI,KAAK,mBAAmB,OAAW,QAAO;AAC9C,MAAI,CAAC,MAAM,eAAgB,QAAO;AAClC,SAAO,EAAE,GAAG,MAAM,gBAAgB,KAAK,eAAe;AACxD;AAEO,IAAM,gBAAN,MAAoB;AAAA,EAApB;AACL,SAAQ,UAAsC;AAC9C,SAAQ,UAA+B;AACvC,SAAQ,QAA8B;AACtC,SAAQ,kBAAuC;AAC/C,SAAQ,oBAAyC;AACjD,SAAQ,yBAA8C;AACtD,SAAQ,0BAA+C;AACvD,SAAQ,mBAA4C;AAEpD;AAAA,SAAQ,6BAA4C;AAEpD;AAAA,SAAQ,qBAAqC;AAE7C;AAAA,SAAQ,qBAAqB;AAE7B;AAAA,SAAQ,gBAAgB;AAExB;AAAA,SAAQ,oBAAoB;AAW5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,kBAAiC;AAEzC;AAAA,SAAQ,sBAA4D;AAEpE;AAAA,SAAQ,oBAKG;AACX,SAAQ,qBAAqB,oBAAI,IAAsB;AAOvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,eAAe,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACnE,SAAQ,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxB,UAAU,QAAmC;AAC3C,UAAM,OACJ,KAAK,WACL,KAAK,QAAQ,eAAe,OAAO,cACnC,KAAK,QAAQ,aAAa,OAAO;AACnC,QAAI,MAAM;AAGR,WAAK,UAAU,EAAE,GAAG,KAAK,SAAS,GAAG,oBAAoB,KAAK,SAAS,MAAM,EAAE;AAC/E;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,eAAe,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAChE,SAAK,gBAAgB,KAAK,IAAI;AAC9B,SAAK,aAAa;AAClB,UAAM,cAAc;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,SAAiB;AACvB,WAAO,KAAK,kBAAkB,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,EAC1D;AAAA;AAAA,EAGA,IAAI,eAAwB;AAC1B,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,UAAwC;AACjD,SAAK,mBAAmB,IAAI,QAAQ;AACpC,WAAO,MAAM;AACX,WAAK,mBAAmB,OAAO,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,SAKL;AACP,SAAK,kBAAkB,OAAO;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,4BAAkC;AAChC,SAAK,gBAAgB;AACrB,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,0BAAyC;AACvC,WAAO,KAAK,mBAAmB,KAAK,SAAS,iBAAiB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cAAoB;AAC1B,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AACrB,WAAK,kBAAkB;AAAA,IACzB;AACA,QAAI,KAAK,mBAAmB;AAC1B,WAAK,kBAAkB;AACvB,WAAK,oBAAoB;AAAA,IAC3B;AACA,QAAI,KAAK,wBAAwB;AAC/B,WAAK,uBAAuB;AAC5B,WAAK,yBAAyB;AAAA,IAChC;AACA,QAAI,KAAK,yBAAyB;AAChC,WAAK,wBAAwB;AAC7B,WAAK,0BAA0B;AAAA,IACjC;AACA,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,WAAW;AACtB,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,oBAAoB;AACzB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,mBAAmB;AACxB,SAAK,6BAA6B;AAClC,SAAK,qBAAqB;AAC1B,SAAK,qBAAqB;AAC1B,SAAK,gBAAgB;AACrB,SAAK,oBAAoB;AACzB,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAc;AACZ,SAAK,YAAY;AACjB,SAAK,mBAAmB,MAAM;AAAA,EAChC;AAAA,EAEQ,sBAA4B;AAClC,QAAI,KAAK,qBAAqB;AAC5B,mBAAa,KAAK,mBAAmB;AACrC,WAAK,sBAAsB;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,kBAAkB,SAKjB;AACP,UAAM,SAAS,QAAQ,UAAU;AACjC,UAAM,OAAO,QAAQ,OAAO,OAAO,QAAQ,IAAI,EAAE,MAAM,GAAG,GAAG,IAAI;AACjE,SAAK,oBAAoB;AAAA,MACvB,SAAS,QAAQ;AAAA,MACjB;AAAA,MACA;AAAA,MACA,WAAW,QAAQ,aAAa;AAAA,IAClC;AAEA,SAAK,SAAS,QAAQ,OAAO,QAAQ,2BAA2B;AAAA,MAC9D,QAAQ;AAAA,MACR,aAAa,KAAK;AAAA,MAClB,gBAAgB,KAAK,OAAO;AAAA,MAC5B,mBAAmB,KAAK;AAAA,MACxB,mBAAmB,KAAK;AAAA,MACxB,cAAc,KAAK;AAAA,MACnB,cAAc,QAAQ,WAAW;AAAA,MACjC,aAAa;AAAA,MACb,WAAW;AAAA,MACX,WAAW,QAAQ,aAAa;AAAA,IAClC,CAAC;AAED,QAAI,KAAK,iBAAiB,KAAK,qBAAqB,KAAK,oBAAqB;AAC9E,SAAK,sBAAsB,WAAW,MAAM;AAC1C,WAAK,sBAAsB;AAC3B,UAAI,KAAK,iBAAiB,KAAK,kBAAmB;AAClD,WAAK,gBAAgB,gBAAgB;AAAA,IACvC,GAAG,oBAAoB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,QAAyC;AAC/D,QAAI,KAAK,kBAAmB;AAC5B,SAAK,oBAAoB;AACzB,UAAM,YAAY,EAAE,QAAQ,aAAa,KAAK,cAAc,OAAO,KAAK,OAAO,EAAE,CAAC;AAClF,UAAM,WAAW,KAAK,SAAS,YAAY,CAAC;AAC5C,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,gBAAgB,KAAK,OAAO;AAAA,MAC5B,mBAAmB,KAAK;AAAA,MACxB,mBAAmB,KAAK;AAAA,MACxB,aAAa,KAAK,mBAAmB,UAAU;AAAA,MAC/C,WAAW,KAAK,mBAAmB,QAAQ;AAAA,MAC3C,cAAc,KAAK,mBAAmB,WAAW;AAAA,MACjD,WAAW,KAAK,mBAAmB,aAAa;AAAA,IAClD;AACA,SAAK,SAAS,QAAQ,OAAO;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AACA,eAAW,YAAY,KAAK,mBAAoB,UAAS,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAqB;AAC3B,SAAK,oBAAoB,YAAY,OAAO,CAAC,EAAE,MAAM,cAAc,MAAM;AAKvE,WAAK,kBACH,OAAO,kBAAkB,YAAY,cAAc,SAAS,IAAI,gBAAgB;AAClF,WAAK,KAAK,oBAAoB,IAAI;AAAA,IACpC,CAAC;AACD,SAAK,yBAAyB,YAAY,YAAY,MAAM;AAC1D,WAAK,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAAA,IAC9C,CAAC;AACD,SAAK,0BAA0B,YAAY,aAAa,CAAC,EAAE,YAAY,QAAQ,SAAS,MAAM;AAC5F,WAAK,OAAO,KAAK,EAAE,MAAM,eAAe,YAAY,QAAQ,SAAS,CAAC;AAAA,IACxE,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,oBAAoB,MAA6B;AAC7D,UAAM,KAAK,MAAM,KAAK,iBAAiB;AACvC,QAAI,CAAC,MAAM,CAAC,KAAK,OAAO;AAItB,kBAAY,MAAM,6CAA6C;AAC/D;AAAA,IACF;AACA,SAAK,MAAM,KAAK,EAAE,MAAM,gBAAgB,KAAK,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,mBAAqC;AACjD,QAAI,KAAK,YAAY,eAAe,KAAK,MAAO,QAAO;AACvD,QAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,QAAI,KAAK,iBAAkB,QAAO,KAAK;AAEvC,SAAK,oBAAoB,YAAY;AACnC,WAAK,UAAU;AACf,YAAM,MAAM,MAAM,KAAK,+BAA+B;AACtD,WAAK,qBAAqB,QAAQ;AAElC,UAAI,KAAK,YAAY,KAAM,QAAO;AAElC,YAAM,UAAU,KAAK,QAAQ,WAAW,QAAQ,OAAO,EAAE;AACzD,YAAM,YAAY,GAAG,OAAO;AAC5B,YAAM,QAAQ,gBAAgB;AAC9B,YAAM,eAAe,MAA8B;AACjD,cAAM,IAA4B,CAAC;AACnC,YAAI,MAAO,GAAE,gBAAgB,UAAU,KAAK;AAC5C,YAAI,IAAK,GAAE,oBAAoB,IAAI;AAWnC,cAAM,UAAU,KAAK,mBAAmB,KAAK,SAAS;AACtD,YAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,GAAG;AACrD,YAAE,mBAAmB,IAAI;AAAA,QAC3B;AAMA,YAAI;AACF,gBAAM,KAAK,KAAK,SAAS;AAQzB,gBAAM,MAAM,IAAI,WAAW,gBAAgB;AAC3C,cAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAC7C,cAAE,eAAe,IAAI;AAAA,UACvB;AACA,gBAAM,MAAM,IAAI,WAAW,eAAe;AAC1C,cAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAC7C,cAAE,kBAAkB,IAAI;AAAA,UAC1B;AAAA,QACF,QAAQ;AAAA,QAER;AACA,eAAO;AAAA,MACT;AAEA,YAAMA,WAAU,KAAK,QAAQ;AAM7B,YAAM,wBAAwB,MAA2C;AACvE,cAAM,MAAM,KAAK,SAAS;AAC1B,eAAO,OAAO,QAAQ,aAAa,IAAI,IAAI;AAAA,MAC7C;AACA,WAAK,QAAQ,IAAI,cAAc;AAAA,QAC7B,KAAK;AAAA,QACL,SAAS;AAAA,QACT,UAAU,KAAK,QAAQ;AAAA,QACvB,aAAa,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAM1B,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,aAAa,CAAC,YAAY;AAOxB,gBAAM,YAAY,uBAAuB,OAAO;AAChD,cAAI,cAAc,MAAM;AACtB,kBAAM,UAAU,KAAK,SAAS;AAC9B,gBAAI,SAAS;AACX,kBAAI;AACF,wBAAQ,SAAS;AACjB,gBAAAA,SAAQ,OAAO,QAAQ,oCAAoC;AAAA,kBACzD,QAAQ;AAAA,kBACR,OAAO,UAAU;AAAA,gBACnB,CAAC;AAAA,cACH,SAAS,KAAK;AACZ,sBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,wBAAQ,MAAM,mDAAmD,GAAG;AAAA,cACtE;AACA;AAAA,YACF;AAKA;AAAA,UACF;AACA,UAAAA,SAAQ,QACL,WAAW,CAAC,OAA6C,CAAC,EAC1D,KAAK,MAAM;AACV,YAAAA,SAAQ,OAAO,QAAQ,wBAAwB,EAAE,QAAQ,iBAAiB,CAAC;AAAA,UAC7E,CAAC,EACA,MAAM,CAAC,QAAiB;AACvB,kBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,oBAAQ,MAAM,uCAAuC,GAAG;AAAA,UAC1D,CAAC;AAAA,QACL;AAAA,MACF,CAAC;AACD,WAAK,MAAM,QAAQ;AACnB,WAAK,kBAAkB,KAAK,MAAM,UAAU,CAAC,UAAU,KAAK,kBAAkB,KAAK,CAAC;AACpF,WAAK,UAAU;AACf,aAAO;AAAA,IACT,GAAG;AAEH,QAAI;AACF,aAAO,MAAM,KAAK;AAAA,IACpB,UAAE;AACA,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,iCAAyD;AACrE,UAAM,EAAE,MAAM,IAAI,MAAM,0BAA0B;AAClD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,oBAAoB,YAAoD;AAC9E,UAAM,QAAQ,YAAY,SAAS;AACnC,eAAW,OAAO,MAAM,UAAU;AAChC,YAAM,KAAK,IAAI,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,UAAU;AACzD,UAAI,GAAI,QAAO,GAAG;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,mBAAmB,QAAyC;AAClE,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAA0B;AAClD,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAEH;AAAA,MAEF,KAAK,kBAAkB;AAGrB,oBAAY,cAAc;AAC1B,aAAK,6BAA6B,MAAM,QAAQ;AAChD,oBAAY,aAAa,MAAM,QAAQ,EAAE;AACzC,YAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,QAAQ,SAAS,GAAG;AAC7D,sBAAY,aAAa,MAAM,QAAQ,IAAI,MAAM,QAAQ,OAAO;AAAA,QAClE;AACA;AAAA,MACF;AAAA,MAEA,KAAK,iBAAiB;AACpB,cAAM,KAAK,MAAM,aAAa,KAAK;AACnC,YAAI,CAAC,MAAM,CAAC,MAAM,MAAO;AACzB,oBAAY,aAAa,IAAI,MAAM,KAAK;AACxC;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AAIrB,oBAAY,oBAAoB,MAAM,KAAK;AAC3C;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AAGrB,oBAAY,cAAc;AAC1B;AAAA,MACF;AAAA,MAEA,KAAK,oBAAoB;AACvB,cAAM,KAAK,MAAM,aAAa,KAAK;AACnC,YAAI,CAAC,GAAI;AACT,oBAAY,WAAW,EAAE;AACzB,aAAK,6BAA6B;AAClC,aAAK,sBAAsB;AAG3B,aAAK,gBAAgB;AACrB,aAAK,oBAAoB;AACzB;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAKhB,cAAM,WAAW,KAAK,oBAAoB,MAAM,SAAS,EAAE;AAM3D,YAAI,CAAC,UAAU;AACb,sBAAY,gBAAgB,kBAAkB,MAAM,SAAS,IAAI,CAAC;AAAA,QACpE;AACA,cAAM,kBAAkB,MAAM,aAAa,KAAK;AAChD,YAAI,CAAC,gBAAiB;AACtB,YAAI,CAAC,UAAU;AACb,sBAAY,YAAY,iBAAiB;AAAA,YACvC,IAAI,MAAM,SAAS;AAAA,YACnB,MAAM,MAAM,SAAS;AAAA,YACrB,QAAQ,KAAK,mBAAmB,MAAM,SAAS,MAAM;AAAA,UACvD,CAAC;AAAA,QACH,OAAO;AACL,sBAAY,eAAe,MAAM,SAAS,IAAI;AAAA,YAC5C,MAAM,MAAM,SAAS;AAAA,YACrB,QAAQ,KAAK,mBAAmB,MAAM,SAAS,MAAM;AAAA,UACvD,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AAIH,cAAM,wBAAwB,KAAK;AACnC;AAAA,MAEF,KAAK;AAIH,oBAAY,eAAe,MAAM,YAAY,EAAE,QAAQ,OAAO,CAAC;AAC/D;AAAA,MAEF,KAAK;AAIH;AAAA,MAEF,KAAK,SAAS;AACZ,cAAM,SAAS,MAAM,UAAU;AAC/B,cAAM,OAAO,MAAM,OAAO,OAAO,MAAM,IAAI,EAAE,MAAM,GAAG,GAAG,IAAI;AAC7D,gBAAQ;AAAA,UACN,iCAAiC,UAAU,WAAW,cAAc,KAAK,kBAAkB;AAAA,UAC3F;AAAA,QACF;AAIA,aAAK,kBAAkB;AAAA,UACrB,SAAS,MAAM;AAAA,UACf;AAAA,UACA;AAAA,UACA,WAAW,MAAM,aAAa;AAAA,QAChC,CAAC;AAID,oBAAY,MAAM,MAAM,WAAW,wBAAwB;AAC3D,aAAK,6BAA6B;AAGlC,YAAI,KAAK,OAAO;AACd,eAAK,MAAM,WAAW;AACtB,eAAK,QAAQ;AAAA,QACf;AACA,YAAI,KAAK,iBAAiB;AACxB,eAAK,gBAAgB;AACrB,eAAK,kBAAkB;AAAA,QACzB;AACA,aAAK,UAAU;AACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAOO,IAAM,gBAAgB,IAAI,cAAc;;;AC5zB/C,IAAM,eAAe;AACrB,IAAM,yBAAyB,oBAAI,IAAI,CAAC,UAAU,GAAG,CAAC;AAEtD,SAAS,SAAS,GAAmB;AACnC,SAAO,EAAE,UAAU,eAAe,IAAI,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC;AACvE;AAEA,SAAS,aAAa,OAAgE;AACpF,QAAM,MAAM,MAAM;AAClB,MAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,MAAM,YAAY,IAAI,CAAC,MAAM,MAAM;AACzF,WAAO,IAAI,CAAC;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAwC;AAC3D,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,IAAI,GAAG;AACb,SAAO,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI;AAC5C;AAEA,SAAS,WAAW,OAAwC;AAC1D,QAAM,WAAW,MAAM;AACvB,MAAI,OAAO,aAAa,SAAU,QAAO,SAAS,YAAY;AAC9D,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,MAAM,OAAO,GAAG,aAAa,SAAU,QAAQ,GAAG,SAAoB,YAAY;AACtF,SAAO;AACT;AAEA,SAAS,YAAY,OAAwC;AAC3D,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,OAAO,GAAG;AAChB,SAAO,OAAO,SAAS,WAAW,KAAK,YAAY,IAAI;AACzD;AAEA,SAAS,SAAS,OAAwC;AACxD,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,OAAO,GAAG;AAChB,MAAI,OAAO,SAAS,YAAY,KAAM,QAAO;AAC7C,QAAM,KAAK,GAAG;AACd,MAAI,OAAO,OAAO,YAAY,GAAI,QAAO;AACzC,SAAO;AACT;AAEA,SAAS,yBAAyB,OAAyC;AACzE,QAAM,MAAM,WAAW,KAAK;AAC5B,MAAI,uBAAuB,IAAI,GAAG,EAAG,QAAO;AAC5C,MAAI,YAAY,KAAK,MAAM,SAAU,QAAO;AAC5C,SAAO;AACT;AAEA,SAAS,SAAS,OAAwC;AACxD,QAAM,KAAK,MAAM;AACjB,SAAO,OAAO,OAAO,WAAW,KAAK;AACvC;AAEA,SAAS,kBAAkB,KAAuB;AAEhD,QAAM,SAAmB,CAAC;AAC1B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AACnD,QAAI,EAAE,WAAW,GAAG,EAAG;AACvB,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,OAAO,MAAM,WAAW;AAC5E,aAAO,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE;AACvB,UAAI,OAAO,UAAU,EAAG;AAAA,IAC1B;AAAA,EACF;AACA,SAAO,OAAO,SAAS,IAAI,GAAG,IAAI,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI;AACzE;AAEO,SAAS,WAAW,KAAe,OAAqB,CAAC,GAA4B;AAC1F,QAAM,QAAQ,IAAI;AAElB,UAAQ,IAAI,OAAO;AAAA,IACjB,KAAK,aAAa;AAChB,YAAM,OAAO,SAAS,KAAK;AAC3B,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,gBAAgB,IAAI,EAAE;AAAA,QACrC,KAAK;AAAA,MACP;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,YAAY,MAAM;AAExB,UAAI,cAAc,SAAS;AACzB,YAAI,CAAC,yBAAyB,KAAK,EAAG,QAAO;AAC7C,cAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,eAAO;AAAA,UACL,IAAI,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM,SAAS,YAAY,IAAI,GAAG;AAAA,QACpC;AAAA,MACF;AAEA,UAAI,cAAc,YAAY,WAAW,KAAK,MAAM,QAAQ;AAC1D,eAAO;AAAA,UACL,IAAI,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM,SAAS,mBAAmB,SAAS,KAAK,CAAC,GAAG;AAAA,QACtD;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,cAAc;AACjB,YAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,iBAAiB,IAAI,GAAG;AAAA,MACzC;AAAA,IACF;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,YAAY,IAAI,iBAAiB;AAAA,MAClD;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,KAAK,sBAAsB;AACzB,YAAM,UAAU,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;AACpE,UAAI,CAAC,QAAS,QAAO;AACrB,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,eAAe,OAAO,WAAW;AAAA,QAChD,KAAK;AAAA,MACP;AAAA,IACF;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,MAAM,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;AAChE,UAAI,QAAQ,KAAM,QAAO;AACzB,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,eAAe,GAAG,eAAe;AAAA,MAClD;AAAA,IACF;AAAA,IAEA,KAAK,oBAAoB;AACvB,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IAEA,KAAK,WAAW;AACd,YAAM,KAAK,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AACrE,YAAM,OAAO,OAAO,OAAO,KAAK,MAAM,KAAK,GAAI,IAAI;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,OAAO,YAAY,IAAI,MAAM;AAAA,MAC9C;AAAA,IACF;AAAA,IAEA,KAAK,YAAY;AACf,YAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,eAAe,IAAI,GAAG;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,mBAAmB,IAAI,GAAG;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,KAAK,mBAAmB;AACtB,YAAM,OAAO,YAAY,KAAK,KAAK,WAAW,KAAK;AACnD,aAAO;AAAA,QACL,IAAI,IAAI;AAAA,QACR,MAAM;AAAA,QACN,MAAM,SAAS,YAAY,IAAI,sBAAsB;AAAA,MACvD;AAAA,IACF;AAAA,IAEA,SAAS;AACP,YAAM,QAAQ,KAAK,oBAAoB,CAAC;AACxC,UAAI,MAAM,SAAS,IAAI,KAAK,GAAG;AAC7B,eAAO;AAAA,UACL,IAAI,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM,SAAS,kBAAkB,GAAG,CAAC;AAAA,QACvC;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC1NO,IAAM,gBAAN,MAAoB;AAAA,EAYzB,YAAY,MAA4B;AAVxC,SAAiB,UAA8B,CAAC;AAChD,SAAQ,QAAQ;AAChB,SAAQ,WAAW;AACnB,SAAQ,aAA4B;AACpC,SAAQ,YAAY;AACpB,SAAQ,iBAAuD;AAC/D,SAAQ,gBAAsD;AAC9D,SAAQ,oBAAoB;AAC5B,SAAQ,YAAY;AAGlB,SAAK,QAAQ;AAAA,MACX,gBAAgB;AAAA,MAChB,cAAc;AAAA,MACd,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,KAAK,OAA+B;AAClC,QAAI,KAAK,UAAW;AACpB,QAAI,KAAK,QAAQ,UAAU,KAAK,MAAM,UAAU;AAC9C,WAAK,QAAQ,MAAM;AACnB,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,QAAQ,KAAK,KAAK;AAEvB,QAAI,KAAK,QAAQ,UAAU,KAAK,MAAM,WAAW;AAC/C,WAAK,mBAAmB;AAAA,IAC1B,OAAO;AACL,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,eAAe;AACpB,UAAM,KAAK,OAAO;AAAA,EACpB;AAAA,EAEA,QAAuB;AACrB,WAAO;AAAA,MACL,QAAQ,KAAK,QAAQ;AAAA,MACrB,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,qBAA2B;AACjC,mBAAe,MAAM;AACnB,WAAK,KAAK,OAAO;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEQ,oBAA0B;AAChC,QAAI,KAAK,kBAAkB,KAAM;AACjC,SAAK,iBAAiB,WAAW,MAAM;AACrC,WAAK,iBAAiB;AACtB,WAAK,KAAK,OAAO;AAAA,IACnB,GAAG,KAAK,MAAM,eAAe;AAAA,EAC/B;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,kBAAkB,MAAM;AAC/B,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,SAAwB;AACpC,QAAI,KAAK,aAAa,KAAK,aAAa,KAAK,QAAQ,WAAW,EAAG;AACnE,SAAK,eAAe;AAEpB,UAAM,QAAQ,KAAK,QAAQ,OAAO,GAAG,KAAK,MAAM,SAAS;AACzD,SAAK,YAAY;AACjB,QAAI;AACF,YAAM,KAAK,MAAM,MAAM,KAAK;AAC5B,WAAK,SAAS,MAAM;AACpB,WAAK,oBAAoB;AACzB,WAAK,aAAa;AAAA,IACpB,SAAS,KAAK;AACZ,WAAK,QAAQ,QAAQ,GAAG,KAAK;AAC7B,YAAM,OAAQ,KAAoB,cAAc;AAChD,WAAK,aACH,eAAe,QAAQ,IAAI,UAAU,OAAQ,KAA+B,WAAW,GAAG;AAC5F,UAAI,MAAM;AACR,aAAK,YAAY;AAAA,MACnB,OAAO;AACL,aAAK,iBAAiB;AAAA,MACxB;AAAA,IACF,UAAE;AACA,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,UAAM,OACJ,KAAK,sBAAsB,IACvB,KAAK,MAAM,iBACX,KAAK,IAAI,KAAK,oBAAoB,GAAG,KAAK,MAAM,YAAY;AAClE,SAAK,oBAAoB;AAEzB,QAAI,KAAK,iBAAiB,KAAM,cAAa,KAAK,aAAa;AAC/D,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,gBAAgB;AACrB,WAAK,KAAK,OAAO;AAAA,IACnB,GAAG,IAAI;AAAA,EACT;AACF;;;AC3GA,SAAS,UACP,YACA,WACA,OACe;AACf,MAAI,CAAC,cAAc,CAAC,UAAW,QAAO;AACtC,QAAM,OAAoB,EAAE,aAAa,YAAY,YAAY,WAAW,MAAM;AAClF,SAAO,KAAK,UAAU,IAAI;AAC5B;AAEO,SAAS,gBAAgB,MAAmC;AACjE,SAAO;AAAA,IACL,MAAM,KAAK,OAA0C;AACnD,YAAM,OAAO,UAAU,KAAK,cAAc,GAAG,KAAK,aAAa,GAAG,KAAK;AAGvE,UAAI,SAAS,KAAM;AACnB,YAAM,OAAO,MAAM,MAAM,KAAK,KAAK;AAAA,QACjC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,MAAM,CAAC;AAAA,UACrC,gBAAgB;AAAA,QAClB;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,aAAa;AAAA,MACf,CAAC;AACD,UAAI,CAAC,KAAK,IAAI;AACZ,cAAM,MAAM,IAAI,MAAM,oBAAoB,KAAK,MAAM,EAAE;AAMvD,YAAI,KAAK,UAAU,OAAO,KAAK,SAAS,OAAO,KAAK,WAAW,KAAK;AAClE,cAAI,YAAY;AAAA,QAClB;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IAEA,WAAW,OAAoC;AAC7C,YAAM,OAAO,UAAU,KAAK,cAAc,GAAG,KAAK,aAAa,GAAG,KAAK;AACvE,UAAI,SAAS,KAAM,QAAO;AAC1B,YAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAM,SAAS,WAAW;AAC1B,UAAI,OAAO,WAAW,WAAY,QAAO;AACzC,aAAO,OAAO,KAAK,WAAW,KAAK,KAAK,IAAI;AAAA,IAC9C;AAAA,EACF;AACF;;;AClDA,IAAI,UAAiC;AAErC,SAAS,eACP,QACA,mBACY;AACZ,QAAM,KAAM,WAAqC;AACjD,MAAI,CAAC,GAAI,QAAO,MAAM;AAAA,EAAC;AAMvB,QAAM,UAAW,GAAqC;AACtD,MAAI,OAAO,YAAY,WAAY,QAAO,MAAM;AAAA,EAAC;AAEjD,QAAM,UAAU,CAAC,WAAmB,eAAoD;AACtF,QAAI,OAAO,cAAc,SAAU;AACnC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,WAAW,KAAK,IAAI;AAAA,MACpB,YAAY,cAAc,CAAC;AAAA,IAC7B,CAAC;AAAA,EACH;AAKA,EAAC,QAAyC,KAAK,IAAI,OAAO;AAC1D,SAAO,MAAM;AAAA,EAAC;AAChB;AAEA,SAAS,gBAAgB,YAAuB,OAAkC;AAChF,QAAM,UAAU,MAAM;AACpB,UAAM,QAAQ,MAAM,MAAM;AAC1B,QAAI,MAAM,SAAS,GAAG;AACpB,WAAK,MAAM,SAAS;AAAA,IACtB;AAAA,EACF;AACA,SAAO,iBAAiB,YAAY,SAAS,EAAE,SAAS,KAAK,CAAC;AAC9D,SAAO,MAAM,OAAO,oBAAoB,YAAY,SAAS,EAAE,SAAS,KAAK,CAAC;AAChF;AAEO,SAAS,cAAc,MAA4C;AACxE,MAAI,SAAS;AACX,YAAQ,YAAY;AACpB,WAAO,YAAY;AAAA,EACrB;AAEA,QAAM,YAAY,KAAK,aAAa,gBAAgB,IAAI;AAExD,QAAM,QAAQ,IAAI,cAAc;AAAA,IAC9B,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,OAAO,CAAC,UAAU,UAAU,KAAK,KAAK;AAAA,EACxC,CAAC;AAED,QAAM,SAAS,CAAC,QAAkB;AAChC,UAAM,KAAK,WAAW,KAAK,EAAE,kBAAkB,KAAK,iBAAiB,CAAC;AACtE,QAAI,OAAO,MAAM;AACf,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,QAAM,gBAAgB,eAAe,QAAQ,KAAK,oBAAoB,CAAC,CAAC;AACxE,QAAM,sBAAsB,gBAAgB,WAAW,KAAK;AAE5D,YAAU;AAAA,IACR,UAAU;AAAA,IACV;AAAA,IACA,aAAa,MAAM;AACjB,oBAAc;AACd,0BAAoB;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,EACX;AAEA,SAAO,YAAY;AACrB;AAEA,SAAS,cAA8B;AACrC,SAAO;AAAA,IACL,OAAa;AACX,UAAI,CAAC,QAAS;AACd,cAAQ,YAAY;AACpB,UAAI,QAAQ,YAAY,GAAG;AACzB,gBAAQ,YAAY;AACpB,kBAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,QAAuB;AACrB,aACE,SAAS,MAAM,MAAM,KAAK;AAAA,QACxB,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,QACX,UAAU;AAAA,MACZ;AAAA,IAEJ;AAAA,IACA,OAAO,KAAqB;AAC1B,UAAI,CAAC,QAAS;AACd,YAAM,KAAK,WAAW,KAAK;AAAA,QACzB,kBAAkB,QAAQ,QAAQ;AAAA,MACpC,CAAC;AACD,UAAI,OAAO,KAAM,SAAQ,MAAM,KAAK,EAAE;AAAA,IACxC;AAAA,IACA,WAA0B;AACxB,aAAO,SAAS,MAAM,SAAS,KAAK,QAAQ,QAAQ;AAAA,IACtD;AAAA,EACF;AACF;;;ACxCA,IAAM,YAAY;AAElB,SAAS,SAAS,WAA2C;AAC3D,SAAQ,UAAgE,SAAS,KAAK;AACxF;AACA,SAAS,SAAS,WAAwB,OAAgC;AACxE,EAAC,UAA2D,SAAS,IAAI;AAC3E;AAEA,SAAS,iBAAiB,KAAsB,KAA+B;AAC7E,MAAI,IAAI,gBAAgB,OAAW,KAAI,cAAc,IAAI;AACzD,MAAI,IAAI,aAAa,OAAW,KAAI,WAAW,IAAI;AACnD,MAAI,kBAAkB,IAAI;AAI1B,MAAI,gBAAgB,IAAI,kBAAkB;AAC5C;AAoBA,IAAI,gBAA6C;AAajD,IAAM,qBAAqB,oBAAI,IAAoB;AAEnD,SAAS,kBAAkB,YAAwC;AACjE,SAAO,mBAAmB,IAAI,UAAU;AAC1C;AAEA,SAAS,yBAAyB,aAAwD;AACxF,qBAAmB,MAAM;AACzB,MAAI,CAAC,YAAa;AAClB,QAAM,QAAS,YAAsE;AACrF,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG;AAC3B,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,OAAO,GAAG,OAAO,WAAW,EAAE,KAAK;AAC9C,UAAM,SAAS,OAAO,GAAG,WAAW,WAAW,EAAE,SAAS;AAC1D,QAAI,MAAM,OAAQ,oBAAmB,IAAI,IAAI,MAAM;AAAA,EACrD;AACF;AAEA,SAAS,wBAAwBC,UAAqD;AACpF,MAAI,cAAe,QAAO;AAC1B,kBAAgB,IAAI,qBAAqB;AAAA,IACvC,SAASA,SAAQ;AAAA;AAAA;AAAA;AAAA,IAIjB,QAAQ;AAAA,MACN,SAASA,SAAQ,OAAO,QAAQ,KAAKA,SAAQ,MAAM;AAAA,MACnD,WAAWA,SAAQ,OAAO,WAAW,KAAKA,SAAQ,MAAM;AAAA,IAC1D;AAAA,IACA,UAAU,CAAC,IAAI,YAAY,iBAAiB,GAAG,IAAI,cAAc,GAAG,IAAI,YAAY,CAAC;AAAA,IACrF;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAYA,IAAI,oBAAoB;AAExB,SAAS,YAAYA,UAA+B,YAA0B;AAC5E,MAAI,kBAAmB;AACvB,sBAAoB;AACpB,QAAM,QAAQ,wBAAwBA,QAAO;AAQ7C,QAAM,UAAU,WAAW,QAAQ,OAAO,EAAE;AAC5C,QAAM,WAAW,UACb,GAAG,OAAO,mCACV;AACJ,uBAAqB,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa;AACpD,QAAI,CAAC,SAAU;AAMf,SAAK,MAAM,QAAQ,SAAS,gBAAgB;AAAA,EAC9C,CAAC;AACH;AAEA,SAAS,6BAA6B,KAA+B;AAOnE,MAAI,CAAC,IAAI,QAAS;AAClB,QAAM,aAAc,IAAI,QAAoC;AAC5D,MAAI,CAAC,WAAY;AAMjB,QAAM,iBAAiB,IAAI,oBAAoB,QAAQ,IAAI,eAAe;AAK1E,2BAAyB,iBAAiB,IAAI,cAAc,MAAS;AACrE,QAAM,iBAAsD,iBACxD,EAAE,iBAAiB,MAAM,aAAa,IAAI,YAAY,IACtD;AAQJ,QAAMA,WAAU,IAAI;AACpB,QAAM,oBAAoB,iBACtB,CAAC,cAAiC;AAChC,SAAK,wBAAwBA,QAAO,EAAE,MAAM,SAAS;AAAA,EACvD,IACA;AAQJ,MAAI,gBAAgB;AAClB,gBAAYA,UAAS,UAAU;AAAA,EACjC;AAEA,gBAAc,UAAU;AAAA,IACtB,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,IAAI;AAAA,EACrB,CAAwB;AAaxB,0BAAwB,GAAG;AAC7B;AAEA,IAAI,mBAAmB;AAEvB,SAAS,wBAAwB,KAA+B;AAC9D,MAAI,iBAAkB;AACtB,MAAI,OAAO,WAAW,YAAa;AACnC,QAAM,aAAa,IAAI;AAUvB,MAAI,CAAC,YAAY,QAAQ,UAAW;AAGpC,QAAM,WAAW,WAAW,cAAc,IAAI,QAAQ,OAAO,EAAE;AAC/D,QAAM,MAAM,UAAU,GAAG,OAAO,8BAA8B;AAO9D,QAAM,YAAY,CAAC,WAA4D;AAC7E,QAAI;AACF,YAAM,IAAI,WAAW,YAAY,MAAM,IAAI;AAC3C,aAAO,OAAO,MAAM,YAAY,EAAE,SAAS,IAAI,IAAI;AAAA,IACrD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,gBAAgB,MAAqB,UAAU,eAAe;AACpE,QAAM,eAAe,MAAqB,UAAU,cAAc;AAClE,QAAM,QAAQ,MAAc;AAC1B,UAAM,IAAK,OAAsD;AACjE,WAAO,OAAO,GAAG,UAAU,WAAW,EAAE,QAAQ;AAAA,EAClD;AAQA,QAAM,SAAS,cAAc,EAAE,KAAK,OAAO,eAAe,aAAa,CAAC;AAIxE,EAAC,OAAqD,wBAAwB,MAC5E,OAAO,MAAM;AACf,aAAW,OAAO,UAAU,CAAC,GAAG,CAAC,QAAiB;AAChD,UAAM,IAAI;AAMV,QAAI,CAAC,GAAG,KAAM;AACd,UAAM,KAAK,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK,KAAK,IAAI;AAatD,QAAI,EAAE,WAAW,WAAW;AAC1B,YAAM,WAAW,EAAE,OAAO;AAC1B,UAAI,OAAO,aAAa,YAAY,SAAS,WAAW,EAAG;AAC3D,YAAM,aAAsC,EAAE,GAAI,EAAE,SAAS,CAAC,EAAG;AACjE,UAAI,OAAO,EAAE,OAAO,aAAa,SAAU,YAAW,YAAY,EAAE,MAAM;AAC1E,UAAI,OAAO,EAAE,OAAO,QAAQ,SAAU,YAAW,eAAe,EAAE,MAAM;AACxE,aAAO,OAAO,EAAE,OAAO,UAAU,WAAW,IAAI,WAAW,CAAC;AAC5D;AAAA,IACF;AAIA,WAAO,OAAO;AAAA,MACZ,OAAO,EAAE;AAAA,MACT,WAAW;AAAA,MACX,YAAY,EAAE,GAAI,EAAE,SAAS,CAAC,EAAG;AAAA,IACnC,CAAC;AAAA,EACH,CAAC;AACD,qBAAmB;AACrB;AAEA,SAAS,cAAc,KAAsB,OAAgC;AAC3E,QAAM,gBAAgB,CAAC,MAAa;AAClC,UAAM,OAAQ,EAAoC,OAAO;AAOzD,gBAAY,KAAK,MAAM,EAAE,eAAe,MAAM,IAAI,gBAAgB,CAAC;AAMnE,QAAI,CAAC,YAAY,aAAa,GAAG;AAC/B,kBAAY,MAAM,yEAAoE;AAAA,IACxF;AAAA,EACF;AACA,QAAM,cAAc,MAAM;AACxB,gBAAY,UAAU;AAAA,EACxB;AACA,QAAM,qBAAqB,CAAC,MAAa;AACvC,UAAM,SAAU,EAA6D;AAK7E,gBAAY,gBAAgB,OAAO,YAAY,CAAC,GAAG,OAAO,QAAQ;AAAA,EACpE;AAGA,QAAM,UAAU,MAAM;AACpB,UAAM,IAAI,UAAU;AAAA,EACtB;AACA,MAAI,iBAAiB,qBAAqB,aAAa;AACvD,MAAI,iBAAiB,kBAAkB,WAAW;AAClD,MAAI,iBAAiB,gBAAgB,OAAO;AAC5C,MAAI,iBAAiB,2BAA2B,kBAAkB;AAClE,SAAO,MAAM;AACX,QAAI,oBAAoB,qBAAqB,aAAa;AAC1D,QAAI,oBAAoB,kBAAkB,WAAW;AACrD,QAAI,oBAAoB,gBAAgB,OAAO;AAC/C,QAAI,oBAAoB,2BAA2B,kBAAkB;AAAA,EACvE;AACF;AAEO,IAAM,2BAA2B;AAAA,EACtC,MAAM,WAAwB,aAAmD;AAC/E,UAAM,MAAO,eAAe,CAAC;AAC7B,iCAA6B,GAAG;AAChC,UAAM,MAAM,SAAS,cAAc,mBAAmB;AACtD,qBAAiB,KAAK,GAAG;AAIzB,UAAM,eAAe,YAAY,UAAU,CAAC,MAAM;AAChD,UAAI,WAAW,CAAC,GAAG,EAAE,QAAQ;AAC7B,UAAI,WAAW,EAAE;AACjB,UAAI,eAAe,EAAE;AAAA,IACvB,CAAC;AAID,UAAM,QAAQ,EAAE,KAAK,SAAS,MAAM;AAAA,IAAC,GAAG,IAAI;AAC5C,UAAM,kBAAkB,cAAc,KAAK,KAAK;AAEhD,cAAU,YAAY,GAAG;AAMzB,UAAM,gBAAgB,cAAc,WAAW,MAAM;AACnD,UAAI,OAAO;AACX,gBAAU,YAAY,mBAAmB,MAAM,IAAI,QAAQ;AAAA,IAC7D,CAAC;AAED,UAAM,UAAU,MAAM;AACpB,mBAAa;AACb,oBAAc;AACd,sBAAgB;AAChB,UAAI,OAAO;AACX,eAAS,WAAW,IAAI;AAAA,IAC1B;AAEA,aAAS,WAAW,KAAK;AACzB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,OAAO,WAAwB,aAA6C;AAC1E,UAAM,QAAQ,SAAS,SAAS;AAChC,QAAI,CAAC,MAAO;AACZ,UAAM,MAAO,eAAe,CAAC;AAC7B,iCAA6B,GAAG;AAChC,qBAAiB,MAAM,KAAK,GAAG;AAC/B,UAAM,MAAM;AAAA,EACd;AACF;;;AC5cA,IAAMC,aAAY;AAElB,SAASC,UAAS,WAA2C;AAC3D,SAAQ,UAAgED,UAAS,KAAK;AACxF;AACA,SAASE,UAAS,WAAwB,OAAgC;AACxE,EAAC,UAA2DF,UAAS,IAAI;AAC3E;AAEA,SAAS,WAAW,OAA2B,KAAkC;AAC/E,MAAI,IAAI,UAAU,OAAW,OAAM,QAAQ,IAAI;AAG/C,MAAI,IAAI,YAAY,QAAW;AAC7B,UAAM,aAAa,IAAI;AAAA,EACzB;AACA,MAAI,IAAI,eAAe,OAAW,OAAM,aAAa,IAAI;AAC3D;AAEO,IAAM,8BAA8B;AAAA,EACzC,MAAM,WAAwB,aAAmD;AAC/E,UAAM,MAAO,eAAe,CAAC;AAC7B,UAAM,QAAQ,SAAS,cAAc,sBAAsB;AAC3D,eAAW,OAAO,GAAG;AAErB,UAAM,QAAoB;AAAA,MACxB;AAAA,MACA,WAAW;AAAA,QACT,UAAU,CAAC,MAAM;AACf,gBAAM,KAAK,IAAI;AACf,cAAI,IAAI;AACN;AAAA,cACG,EACE;AAAA,YACL;AAAA,UACF;AAAA,QACF;AAAA,QACA,WAAW,CAAC,MAAM;AAChB,gBAAM,KAAK,IAAI;AACf,cAAI,GAAI,IAAI,EAAkC,MAAM;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AACA,UAAM,iBAAiB,iBAAiB,MAAM,UAAU,QAAQ;AAChE,UAAM,iBAAiB,kBAAkB,MAAM,UAAU,SAAS;AAElE,cAAU,YAAY,KAAK;AAC3B,IAAAE,UAAS,WAAW,KAAK;AAEzB,WAAO,MAAM;AACX,YAAM,oBAAoB,iBAAiB,MAAM,UAAU,QAAQ;AACnE,YAAM,oBAAoB,kBAAkB,MAAM,UAAU,SAAS;AACrE,YAAM,OAAO;AACb,MAAAA,UAAS,WAAW,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,OAAO,WAAwB,aAA6C;AAC1E,UAAM,QAAQD,UAAS,SAAS;AAChC,QAAI,CAAC,MAAO;AACZ,UAAM,MAAO,eAAe,CAAC;AAC7B,eAAW,MAAM,OAAO,GAAG;AAE3B,UAAM,MAAM,oBAAoB,iBAAiB,MAAM,UAAU,QAAQ;AACzE,UAAM,MAAM,oBAAoB,kBAAkB,MAAM,UAAU,SAAS;AAC3E,UAAM,UAAU,WAAW,CAAC,MAAM;AAChC,YAAM,KAAK,IAAI;AACf,UAAI,IAAI;AACN,WAAI,EAAgF,MAAM;AAAA,MAC5F;AAAA,IACF;AACA,UAAM,UAAU,YAAY,CAAC,MAAM;AACjC,YAAM,KAAK,IAAI;AACf,UAAI,GAAI,IAAI,EAAkC,MAAM;AAAA,IACtD;AACA,UAAM,MAAM,iBAAiB,iBAAiB,MAAM,UAAU,QAAQ;AACtE,UAAM,MAAM,iBAAiB,kBAAkB,MAAM,UAAU,SAAS;AAAA,EAC1E;AACF;;;ACrFA,IAAME,aAAY;AAElB,SAASC,UAAS,WAA2C;AAC3D,SAAQ,UAAgED,UAAS,KAAK;AACxF;AACA,SAASE,UAAS,WAAwB,OAAgC;AACxE,EAAC,UAA2DF,UAAS,IAAI;AAC3E;AAEA,SAAS,WAAW,QAAsB;AACxC,MAAI,CAAC,OAAQ;AACb,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,IAAI,QAAQ,OAAO,SAAS,MAAM;AAAA,EACnD,QAAQ;AACN;AAAA,EACF;AACA,MAAI,SAAS,WAAW,OAAO,SAAS,OAAQ;AAChD,MAAI,SAAS,aAAa,WAAW,SAAS,aAAa,SAAU;AACrE,SAAO,QAAQ,UAAU,MAAM,IAAI,SAAS,SAAS,CAAC;AACtD,SAAO,cAAc,IAAI,cAAc,UAAU,CAAC;AACpD;AAEA,SAAS,YAAY,KAAsC;AACzD,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,OAAO;AACd,SAAO,QAAQ,gBAAgB;AAC/B,SAAO,MAAM,UAAU;AACvB,SAAO,MAAM,aAAa;AAC1B,SAAO,MAAM,MAAM;AACnB,SAAO,MAAM,UAAU;AACvB,SAAO,MAAM,eAAe;AAC5B,SAAO,MAAM,aAAa;AAC1B,SAAO,MAAM,WAAW;AACxB,SAAO,MAAM,aAAa;AAC1B,SAAO,MAAM,SAAS;AACtB,SAAO,MAAM,QAAQ;AACrB,SAAO,MAAM,aAAa;AAC1B,SAAO,MAAM,SAAS;AACtB,aAAW,QAAQ,GAAG;AACtB,SAAO;AACT;AAEA,SAAS,WAAW,QAA2B,KAAyB;AACtE,QAAM,MAAM,OAAO,IAAI,OAAO,EAAE;AAChC,QAAM,QAAQ,IAAI,UAAU,MAAM,SAAS,GAAG,KAAK;AAGnD,SAAO,cAAc;AACvB;AAEO,IAAM,mBAAmB;AAAA,EAC9B,MAAM,WAAwB,aAAmD;AAC/E,UAAM,MAAO,eAAe,CAAC;AAC7B,UAAM,SAAS,YAAY,GAAG;AAC9B,UAAM,UAAU,CAAC,OAAoB;AACnC,YAAM,UAAUC,UAAS,SAAS;AAClC,YAAM,MAAM,SAAS,IAAI,OAAO,IAAI;AACpC,iBAAW,OAAO,OAAO,EAAE,CAAC;AAAA,IAC9B;AACA,WAAO,iBAAiB,SAAS,OAAO;AACxC,cAAU,YAAY,MAAM;AAC5B,IAAAC,UAAS,WAAW,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAC5C,WAAO,MAAM;AACX,aAAO,oBAAoB,SAAS,OAAO;AAC3C,aAAO,OAAO;AACd,MAAAA,UAAS,WAAW,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,OAAO,WAAwB,aAA6C;AAC1E,UAAM,QAAQD,UAAS,SAAS;AAChC,QAAI,CAAC,MAAO;AACZ,UAAM,MAAO,eAAe,CAAC;AAC7B,eAAW,MAAM,QAAQ,GAAG;AAC5B,UAAM,MAAM;AAAA,EACd;AACF;;;AC1FA,IAAME,aAAY;AAElB,SAASC,UAAS,WAA2C;AAC3D,SAAQ,UAAgED,UAAS,KAAK;AACxF;AACA,SAASE,UAAS,WAAwB,OAAgC;AACxE,EAAC,UAA2DF,UAAS,IAAI;AAC3E;AAEA,SAAS,UAAU,GAAyB,MAAoB;AAC9D,IAAE,cAAc;AAClB;AAEO,IAAM,sBAAsB;AAAA,EACjC,MAAM,WAAwB,aAAmD;AAC/E,UAAM,MAAO,eAAe,CAAC;AAC7B,UAAM,YAAY,SAAS,cAAc,GAAG;AAC5C,cAAU,QAAQ,mBAAmB;AAIrC,cAAU,MAAM,SAAS;AACzB,cAAU,MAAM,WAAW;AAC3B,cAAU,MAAM,aAAa;AAC7B,cAAU,MAAM,QAAQ;AACxB,cAAU,WAAW,OAAO,IAAI,QAAQ,EAAE,CAAC;AAC3C,cAAU,YAAY,SAAS;AAE/B,IAAAE,UAAS,WAAW,EAAE,WAAW,IAAI,CAAC;AACtC,WAAO,MAAM;AACX,gBAAU,OAAO;AACjB,MAAAA,UAAS,WAAW,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,OAAO,WAAwB,aAA6C;AAC1E,UAAM,QAAQD,UAAS,SAAS;AAChC,QAAI,CAAC,MAAO;AACZ,UAAM,MAAO,eAAe,CAAC;AAC7B,cAAU,MAAM,WAAW,OAAO,IAAI,QAAQ,EAAE,CAAC;AACjD,UAAM,MAAM;AAAA,EACd;AACF;;;AC1CO,IAAM,UAAU;AAAA,EACrB,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,WAAW,CAAC;AAAA,EAEZ,SAAS;AAAA,IACP;AAAA,MACE,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA;AAAA,MACE,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aACE;AAAA,QACF,MAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,MACE,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA;AAAA,MACE,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA;AAAA,MACE,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aACE;AAAA,QACF,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,kBAAQ;",
|
|
6
6
|
"names": ["runtime", "runtime", "STATE_KEY", "getState", "setState", "STATE_KEY", "getState", "setState", "STATE_KEY", "getState", "setState"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/AdaptiveChatBar.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * AdaptiveChatBar \u2014 the canvas lid composition for the chat-canvas\n * experience. Renders the bubble-up trail on top and an always-visible\n * input row below.\n *\n * Wiring contract (events out):\n * - `chat-message-sent` ({ text }): the user submitted text via Enter\n * or the send button. The owning code is responsible for pushing\n * this into the conversation history and producing a reply.\n * - `canvas-close`: the user clicked the close \u2715 button. Propagated\n * to the canvas overlay so the underlying drawer is dismissed.\n *\n * Wiring contract (props in):\n * - `messages`: the conversation trail, passed straight through to\n * `<adaptive-chat-trail>`.\n * - `placeholder`: input placeholder copy. Defaults to a generic\n * \"Ask, find, or navigate\u2026\" \u2014 the host (typically the slot's lid\n * widget mount) can override to a context-specific string.\n *\n * Light DOM. Glassmorphism is applied at the input-row level so the\n * trail above floats over the host page without chrome. See PRD \u00A74.4.\n */\n\nimport { html, LitElement, nothing } from 'lit';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport './AdaptiveChatTrail.js';\nimport type { TrailMessage } from './AdaptiveChatTrail.js';\n\nconst DEFAULT_PLACEHOLDER = 'Ask, find, or navigate\u2026';\n\nexport class AdaptiveChatBar extends LitElement {\n static override properties = {\n messages: { attribute: false },\n placeholder: { type: String },\n greeting: { type: String },\n inFlight: { type: Boolean, reflect: true },\n thinkingText: { attribute: false },\n introSuggestion: { attribute: false },\n forceExpanded: { type: Boolean, reflect: true },\n _input: { state: true },\n };\n\n messages: TrailMessage[] = [];\n\n /**\n * Live reasoning narration from the model \u2014 streamed in via\n * AG-UI THINKING_TEXT_MESSAGE_CONTENT events and forwarded by\n * the ChatSession subscription on the host (mountable).\n * Forwarded verbatim to the trail, which renders it in place of\n * the silent loading dots between turns. Empty string when no\n * thinking turn is active.\n */\n thinkingText = '';\n /**\n * Pre-conversation suggestion button \u2014 forwarded to the trail's\n * empty-state pane. When the visitor clicks it the trail emits\n * `trail-intro-suggestion`; we catch that here and submit the\n * configured prompt through the normal send path.\n */\n introSuggestion: { label: string; prompt: string } | undefined = undefined;\n\n /** Pass-through to {@link AdaptiveChatTrail}'s ``forceExpanded`` prop.\n * Hosts that mount the chat-bar in a full-screen surface (mobile\n * panel, agent app, etc.) set this to skip the collapse affordance\n * \u2014 there is no smaller state to fall back to. */\n forceExpanded = false;\n placeholder = DEFAULT_PLACEHOLDER;\n /**\n * Initial assistant message shown before any real conversation\n * starts. Renders inside the trail as a phantom assistant chip\n * when messages.length === 0; auto-disappears as soon as the\n * first user message lands. Mirrors ChatAssistantLit's greeting.\n */\n greeting: string | undefined = undefined;\n /**\n * Whether a chat round-trip is in flight (request sent, awaiting\n * reply). The single send/stop button morphs accordingly: \u2191 when\n * ready, \u23F9 when in-flight. Parent owns this state \u2014 set true after\n * `chat-message-sent` fires, false when the reply lands or the\n * request is aborted. Enter is inert while in-flight.\n */\n inFlight = false;\n _input = '';\n\n override createRenderRoot(): HTMLElement {\n return this;\n }\n\n // Host-level styling (display, width, height, flex, etc.) is owned\n // by the container \u2014 SDK shadow root provides default rules, panel\n // overrides via design tokens (--sc-chat-bar-host-*). This adaptive\n // never sets inline styles on itself. See SmartCanvasElementLit's\n // static styles for the rule.\n\n private _onInput = (e: Event): void => {\n this._input = (e.target as HTMLInputElement).value;\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n // Enter is the send affordance \u2014 while in-flight there's nothing\n // to send, so it's a no-op. Interrupt requires the explicit\n // \u23F9 click to avoid surprise-aborting on a stray keystroke.\n if (this.inFlight) return;\n this._send();\n }\n };\n\n // Single button. Click delegates to send-or-interrupt based on\n // current state. Same DOM node, different behavior \u2014 discoverability\n // wins from the user not having to scan for which control is active.\n private _onSendOrInterrupt = (): void => {\n if (this.inFlight) {\n this.dispatchEvent(new CustomEvent('chat-interrupt', { bubbles: true, composed: true }));\n return;\n }\n this._send();\n };\n\n private _onClose = (): void => {\n this.dispatchEvent(new CustomEvent('canvas-close', { bubbles: true, composed: true }));\n };\n\n private _send(): void {\n const text = this._input.trim();\n if (!text) return;\n this.dispatchEvent(\n new CustomEvent<{ text: string }>('chat-message-sent', {\n detail: { text },\n bubbles: true,\n composed: true,\n })\n );\n this._input = '';\n // Drop the input value too \u2014 the input's bound value is `this._input`\n // via the render, but jsdom's two-way binding via property only takes\n // effect after the next render, so set it imperatively for the test\n // and for browser symmetry (most browsers do the right thing here\n // anyway because Lit re-renders on the state change).\n const input = this.querySelector<HTMLInputElement>('input[data-chat-input]');\n if (input) input.value = '';\n }\n\n /**\n * Visitor tapped the intro suggestion button in the empty-state\n * trail. Submit the configured prompt through the same channel as\n * a typed message so listeners (mountable \u2192 chatSession.send) see\n * a uniform shape \u2014 no need for a parallel \"suggestion-sent\" path.\n * The trail's intro pane auto-disappears the moment the first\n * message lands, so this also closes the empty state in one go.\n */\n private _onIntroSuggestion = (e: Event): void => {\n const detail = (e as CustomEvent<{ prompt: string }>).detail;\n if (!detail?.prompt) return;\n e.stopPropagation();\n if (this.inFlight) return;\n this.dispatchEvent(\n new CustomEvent<{ text: string }>('chat-message-sent', {\n detail: { text: detail.prompt },\n bubbles: true,\n composed: true,\n })\n );\n };\n\n override render() {\n return html`\n <div style=${styleMap(rootStyles(this.forceExpanded))}>\n ${this.forceExpanded ? renderHeader() : nothing}\n <adaptive-chat-trail\n .messages=${this.messages}\n .greeting=${this.greeting}\n .forceExpanded=${this.forceExpanded}\n .inFlight=${this.inFlight}\n .thinkingText=${this.thinkingText}\n .introSuggestion=${this.introSuggestion}\n @trail-intro-suggestion=${this._onIntroSuggestion}\n ></adaptive-chat-trail>\n <div style=${styleMap(rowStyles(this.forceExpanded))} data-chat-row>\n <span style=${styleMap(avatarStyles())} aria-hidden=\"true\">\u2726</span>\n <input\n data-chat-input\n type=\"text\"\n placeholder=${this.placeholder}\n .value=${this._input}\n @input=${this._onInput}\n @keydown=${this._onKeyDown}\n style=${styleMap(inputStyles())}\n aria-label=\"Chat input\"\n />\n <button\n type=\"button\"\n data-chat-send\n data-state=${this.inFlight ? 'in-flight' : 'ready'}\n @click=${this._onSendOrInterrupt}\n aria-label=${this.inFlight ? 'Stop' : 'Send message'}\n title=${this.inFlight ? 'Interrupt' : 'Send'}\n style=${styleMap(sendStyles(this.inFlight))}\n >${this.inFlight ? '\u25A0' : '\u2191'}</button>\n <button\n type=\"button\"\n data-chat-close\n @click=${this._onClose}\n aria-label=\"Hide chat\"\n style=${styleMap(closeStyles())}\n >\u2715</button>\n </div>\n </div>\n `;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Styles \u2014 kept inline (Lit styleMap) so they participate in light-DOM\n// rendering and pick up host CSS variables (e.g. --sc-tile-background).\n// ---------------------------------------------------------------------------\n\nfunction rootStyles(forceExpanded: boolean): Record<string, string> {\n // When the host expects the chat to fill its container (full-screen\n // panel, agent app), we grow vertically AND wrap the whole widget in\n // its own chrome card \u2014 trail + input read as one cohesive surface\n // instead of a naked trail above a chrome'd input. Floating mounts\n // (bottom-right pinned, etc.) stay chrome-less here because their\n // chrome is owned by the host's positioned wrapper.\n if (!forceExpanded) {\n return {\n display: 'flex',\n flexDirection: 'column',\n gap: '6px',\n width: '100%',\n pointerEvents: 'auto',\n };\n }\n // Input is ABSOLUTELY positioned at the bottom of this chrome card\n // (see rowStyles forceExpanded mode). That guarantees the input is\n // always visible \u2014 even when the lid region is tighter than the\n // chat-bar would naturally want. The flex column above holds\n // header + trail; padding-bottom reserves the input's footprint so\n // trail content can never overlap.\n //\n // Priority of \"what disappears when space is tight\":\n // Trail (shrinks to 0 first via flex: 1 1 0)\n // Header (can shrink via default flex: 0 1 auto)\n // Input (NEVER \u2014 it's positioned absolute, always at the bottom)\n return {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n flex: '1 1 auto',\n minHeight: '0',\n overflow: 'hidden',\n pointerEvents: 'auto',\n background: 'var(--sc-tile-background, rgba(255, 255, 255, 0.92))',\n border: 'var(--sc-tile-border, 1px solid rgba(0, 0, 0, 0.06))',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n boxShadow: 'var(--sc-tile-shadow, 0 12px 32px -16px rgba(0, 0, 0, 0.18))',\n // Reserves room for the absolute-positioned input pill (36px high\n // + 12px from bottom) plus a 16px visual gap above the input.\n padding: '0.75rem 0.75rem calc(36px + 1.75rem)',\n color: 'var(--sc-tile-title-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n // Override the trail's host-layout tokens so the trail (a flex item\n // of this column) shrinks to 0 first when space is tight \u2014 letting\n // the header and absolute-positioned input pill stay pinned. The\n // SDK-level rule in SmartCanvasElementLit consumes these tokens on\n // adaptive-chat-trail's host element. Containers OWN host styling\n // via tokens; the adaptive never sets inline styles on its host.\n ['--sc-chat-trail-host-display']: 'flex',\n ['--sc-chat-trail-host-flex-direction']: 'column',\n ['--sc-chat-trail-host-flex']: '1 1 0',\n ['--sc-chat-trail-host-min-height']: '0',\n ['--sc-chat-trail-host-overflow']: 'hidden',\n };\n}\n\nfunction rowStyles(forceExpanded: boolean): Record<string, string> {\n // forceExpanded \u2014 root container already carries the chrome; row\n // becomes a flat input-pill inside that chrome (subtle border + soft\n // background, no shadow/blur).\n if (forceExpanded) {\n // Absolute-pinned to the chrome card's bottom edge so it never\n // disappears under any container size. The chrome reserves\n // padding-bottom equal to this row's footprint so flex content\n // above (header + trail) can't overlap.\n return {\n position: 'absolute',\n left: '0.75rem',\n right: '0.75rem',\n bottom: '0.75rem',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 14px',\n borderRadius: '9999px',\n background: 'rgba(0, 0, 0, 0.04)',\n border: '1px solid rgba(0, 0, 0, 0.10)',\n color: 'var(--sc-content-text-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n minHeight: '36px',\n };\n }\n // Floating mount \u2014 keeps the original tile-chrome look.\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '10px 12px',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n background: 'var(--sc-tile-background, rgba(15, 19, 24, 0.6))',\n backdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n WebkitBackdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n border: 'var(--sc-tile-border, 1px solid rgba(255, 255, 255, 0.08))',\n boxShadow: 'var(--sc-tile-shadow, 0 2px 12px rgba(0, 0, 0, 0.3))',\n color: 'var(--sc-tile-title-color, #fafafa)',\n fontFamily: 'var(--sc-font-family, inherit)',\n };\n}\n\nfunction avatarStyles(): Record<string, string> {\n return {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n borderRadius: '9999px',\n background: 'hsl(var(--sc-accent-color) / 0.15)',\n border: '1px solid hsl(var(--sc-accent-color) / 0.30)',\n color: 'hsl(var(--sc-accent-color) / 0.95)',\n flexShrink: '0',\n fontSize: '11px',\n };\n}\n\nfunction inputStyles(): Record<string, string> {\n return {\n flex: '1',\n minWidth: '0',\n background: 'transparent',\n border: 'none',\n outline: 'none',\n color: 'inherit',\n fontSize: '13px',\n };\n}\n\nfunction sendStyles(inFlight: boolean): Record<string, string> {\n return {\n width: '28px',\n height: '28px',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '9999px',\n // Ready: filled accent (send is the affordance). In-flight: hollow\n // ring + accent ring (stop is a one-of-a-kind disruptive action,\n // styled differently so the user reads \"this isn't just send\").\n background: inFlight ? 'transparent' : 'hsl(var(--sc-accent-color) / 0.85)',\n color: inFlight ? 'hsl(var(--sc-accent-color) / 0.95)' : 'var(--sc-accent-foreground, #fff)',\n border: inFlight ? '1px solid hsl(var(--sc-accent-color) / 0.55)' : 'none',\n cursor: 'pointer',\n flexShrink: '0',\n transition: 'background 150ms ease, color 150ms ease, border-color 150ms ease',\n };\n}\n\nfunction closeStyles(): Record<string, string> {\n return {\n width: '28px',\n height: '28px',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '9999px',\n background: 'transparent',\n color: 'inherit',\n border: 'var(--sc-content-bubble-border, 1px solid rgba(255, 255, 255, 0.18))',\n cursor: 'pointer',\n flexShrink: '0',\n opacity: '0.7',\n };\n}\n\nfunction renderHeader() {\n const headerStyles: Record<string, string> = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '4px 4px 12px',\n borderBottom: '1px solid var(--sc-content-divider-color, rgba(0, 0, 0, 0.08))',\n flex: '0 0 auto',\n };\n const avatar: Record<string, string> = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n borderRadius: '9999px',\n // Track the workspace brand primary so the avatar matches every\n // other green in the canvas (velvet's chip gradient, the status\n // dot below, the send button). Previously the avatar pinned a\n // hardcoded #5faf7d \u2192 #3d8a5e gradient via the\n // `--sc-tile-icon-background` fallback, so when a workspace\n // overrode --sc-color-primary, every other element shifted to\n // the brand but the avatar stayed the default green \u2014 visibly\n // out of place against the surrounding chrome. Fallback colors\n // unchanged so velvet's default look is identical when no\n // workspace primary is set.\n background:\n 'var(--sc-tile-icon-background, linear-gradient(135deg, var(--sc-color-primary, #5faf7d) 0%, var(--sc-color-primary-hover, #3d8a5e) 100%))',\n color: '#fff',\n flexShrink: '0',\n fontSize: '14px',\n };\n const nameWrap: Record<string, string> = {\n display: 'flex',\n flexDirection: 'column',\n minWidth: '0',\n flex: '1 1 auto',\n };\n const name: Record<string, string> = {\n fontSize: '0.85rem',\n fontWeight: '600',\n color: 'var(--sc-content-text-color, inherit)',\n lineHeight: '1.2',\n };\n const status: Record<string, string> = {\n fontSize: '0.7rem',\n color: 'var(--sc-tile-title-color, #3d8275)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n lineHeight: '1.2',\n };\n const statusDot: Record<string, string> = {\n width: '6px',\n height: '6px',\n borderRadius: '9999px',\n background: 'var(--sc-tile-title-color, #3d8275)',\n display: 'inline-block',\n };\n return html`\n <div style=${styleMap(headerStyles)} data-chat-header>\n <span style=${styleMap(avatar)} aria-hidden=\"true\">\u2726</span>\n <div style=${styleMap(nameWrap)}>\n <span style=${styleMap(name)}>Assistant</span>\n <span style=${styleMap(status)}>\n <span style=${styleMap(statusDot)}></span>\n Online \u00B7 understands your session\n </span>\n </div>\n </div>\n `;\n}\n\nif (!customElements.get('adaptive-chat-bar')) {\n customElements.define('adaptive-chat-bar', AdaptiveChatBar);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'adaptive-chat-bar': AdaptiveChatBar;\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAuBA,SAAS,MAAM,YAAY,eAAe;AAC1C,SAAS,gBAAgB;AAKzB,IAAM,sBAAsB;AAErB,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAAzC;AAAA;AAYL,oBAA2B,CAAC;AAU5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAe;AAOf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAiE;AAMjE;AAAA;AAAA;AAAA;AAAA,yBAAgB;AAChB,uBAAc;AAOd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA+B;AAQ/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAW;AACX,kBAAS;AAYT;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,WAAW,CAAC,MAAmB;AACrC,WAAK,SAAU,EAAE,OAA4B;AAAA,IAC/C;AAEA,SAAQ,aAAa,CAAC,MAA2B;AAC/C,UAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,UAAE,eAAe;AAIjB,YAAI,KAAK,SAAU;AACnB,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAKA;AAAA;AAAA;AAAA,SAAQ,qBAAqB,MAAY;AACvC,UAAI,KAAK,UAAU;AACjB,aAAK,cAAc,IAAI,YAAY,kBAAkB,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AACvF;AAAA,MACF;AACA,WAAK,MAAM;AAAA,IACb;AAEA,SAAQ,WAAW,MAAY;AAC7B,WAAK,cAAc,IAAI,YAAY,gBAAgB,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,IACvF;AA8BA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,qBAAqB,CAAC,MAAmB;AAC/C,YAAM,SAAU,EAAsC;AACtD,UAAI,CAAC,QAAQ,OAAQ;AACrB,QAAE,gBAAgB;AAClB,UAAI,KAAK,SAAU;AACnB,WAAK;AAAA,QACH,IAAI,YAA8B,qBAAqB;AAAA,UACrD,QAAQ,EAAE,MAAM,OAAO,OAAO;AAAA,UAC9B,SAAS;AAAA,UACT,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA,EAhFS,mBAAgC;AACvC,WAAO;AAAA,EACT;AAAA,EAsCQ,QAAc;AACpB,UAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,QAAI,CAAC,KAAM;AACX,SAAK;AAAA,MACH,IAAI,YAA8B,qBAAqB;AAAA,QACrD,QAAQ,EAAE,KAAK;AAAA,QACf,SAAS;AAAA,QACT,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AACA,SAAK,SAAS;AAMd,UAAM,QAAQ,KAAK,cAAgC,wBAAwB;AAC3E,QAAI,MAAO,OAAM,QAAQ;AAAA,EAC3B;AAAA,EAwBS,SAAS;AAChB,WAAO;AAAA,mBACQ,SAAS,WAAW,KAAK,aAAa,CAAC,CAAC;AAAA,UACjD,KAAK,gBAAgB,aAAa,IAAI,OAAO;AAAA;AAAA,sBAEjC,KAAK,QAAQ;AAAA,sBACb,KAAK,QAAQ;AAAA,2BACR,KAAK,aAAa;AAAA,sBACvB,KAAK,QAAQ;AAAA,0BACT,KAAK,YAAY;AAAA,6BACd,KAAK,eAAe;AAAA,oCACb,KAAK,kBAAkB;AAAA;AAAA,qBAEtC,SAAS,UAAU,KAAK,aAAa,CAAC,CAAC;AAAA,wBACpC,SAAS,aAAa,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,0BAItB,KAAK,WAAW;AAAA,qBACrB,KAAK,MAAM;AAAA,qBACX,KAAK,QAAQ;AAAA,uBACX,KAAK,UAAU;AAAA,oBAClB,SAAS,YAAY,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMlB,KAAK,WAAW,cAAc,OAAO;AAAA,qBACzC,KAAK,kBAAkB;AAAA,yBACnB,KAAK,WAAW,SAAS,cAAc;AAAA,oBAC5C,KAAK,WAAW,cAAc,MAAM;AAAA,oBACpC,SAAS,WAAW,KAAK,QAAQ,CAAC,CAAC;AAAA,aAC1C,KAAK,WAAW,WAAM,QAAG;AAAA;AAAA;AAAA;AAAA,qBAIjB,KAAK,QAAQ;AAAA;AAAA,oBAEd,SAAS,YAAY,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKzC;AACF;AArLa,gBACK,aAAa;AAAA,EAC3B,UAAU,EAAE,WAAW,MAAM;AAAA,EAC7B,aAAa,EAAE,MAAM,OAAO;AAAA,EAC5B,UAAU,EAAE,MAAM,OAAO;AAAA,EACzB,UAAU,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EACzC,cAAc,EAAE,WAAW,MAAM;AAAA,EACjC,iBAAiB,EAAE,WAAW,MAAM;AAAA,EACpC,eAAe,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EAC9C,QAAQ,EAAE,OAAO,KAAK;AACxB;AAkLF,SAAS,WAAW,eAAgD;AAOlE,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,KAAK;AAAA,MACL,OAAO;AAAA,MACP,eAAe;AAAA,IACjB;AAAA,EACF;AAYA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,WAAW;AAAA,IACX,UAAU;AAAA,IACV,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA;AAAA;AAAA,IAGX,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOZ,CAAC,8BAA8B,GAAG;AAAA,IAClC,CAAC,qCAAqC,GAAG;AAAA,IACzC,CAAC,2BAA2B,GAAG;AAAA,IAC/B,CAAC,iCAAiC,GAAG;AAAA,IACrC,CAAC,+BAA+B,GAAG;AAAA,EACrC;AACF;AAEA,SAAS,UAAU,eAAgD;AAIjE,MAAI,eAAe;AAKjB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,SAAS;AAAA,MACT,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,SAAS;AAAA,IACT,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AACF;AAEA,SAAS,eAAuC;AAC9C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,cAAsC;AAC7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,WAAW,UAA2C;AAC7D,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,cAAc;AAAA;AAAA;AAAA;AAAA,IAId,YAAY,WAAW,gBAAgB;AAAA,IACvC,OAAO,WAAW,uCAAuC;AAAA,IACzD,QAAQ,WAAW,iDAAiD;AAAA,IACpE,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAEA,SAAS,cAAsC;AAC7C,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,EACX;AACF;AAEA,SAAS,eAAe;AACtB,QAAM,eAAuC;AAAA,IAC3C,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,SAAS;AAAA,IACT,cAAc;AAAA,IACd,MAAM;AAAA,EACR;AACA,QAAM,SAAiC;AAAA,IACrC,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWd,YACE;AAAA,IACF,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACA,QAAM,WAAmC;AAAA,IACvC,SAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACA,QAAM,OAA+B;AAAA,IACnC,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AACA,QAAM,SAAiC;AAAA,IACrC,UAAU;AAAA,IACV,OAAO;AAAA,IACP,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,YAAY;AAAA,EACd;AACA,QAAM,YAAoC;AAAA,IACxC,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,SAAS;AAAA,EACX;AACA,SAAO;AAAA,iBACQ,SAAS,YAAY,CAAC;AAAA,oBACnB,SAAS,MAAM,CAAC;AAAA,mBACjB,SAAS,QAAQ,CAAC;AAAA,sBACf,SAAS,IAAI,CAAC;AAAA,sBACd,SAAS,MAAM,CAAC;AAAA,wBACd,SAAS,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAM3C;AAEA,IAAI,CAAC,eAAe,IAAI,mBAAmB,GAAG;AAC5C,iBAAe,OAAO,qBAAqB,eAAe;AAC5D;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|