@helpai/elements 0.12.3 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configurator.mjs +171 -87
- package/elements-web-component.esm.js +27 -27
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +27 -27
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +27 -27
- package/elements.esm.js.map +4 -4
- package/elements.js +28 -28
- package/elements.js.map +4 -4
- package/index.d.ts +143 -2
- package/index.mjs +1470 -502
- package/package.json +1 -1
- package/schema.d.ts +127 -2
- package/schema.json +476 -3
- package/schema.mjs +178 -89
- package/style.css +1 -1
- package/web-component.mjs +1487 -523
package/index.mjs
CHANGED
|
@@ -6,8 +6,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6
6
|
import { h, render } from "preact";
|
|
7
7
|
|
|
8
8
|
// src/ui/app.tsx
|
|
9
|
-
import { useCallback as useCallback6, useEffect as useEffect17, useMemo as useMemo3, useRef as useRef8, useState as
|
|
10
|
-
import { useSignal } from "@preact/signals";
|
|
9
|
+
import { useCallback as useCallback6, useEffect as useEffect17, useMemo as useMemo3, useRef as useRef8, useState as useState13 } from "preact/hooks";
|
|
10
|
+
import { useSignal as useSignal2 } from "@preact/signals";
|
|
11
11
|
|
|
12
12
|
// src/core/brand.ts
|
|
13
13
|
var BRAND = {
|
|
@@ -105,15 +105,154 @@ var STRINGS_EN = {
|
|
|
105
105
|
newsEmpty: "No news yet",
|
|
106
106
|
newsLoading: "Loading news\u2026",
|
|
107
107
|
newsBack: "Back to news",
|
|
108
|
-
newsPublishedAt: "Published {date}"
|
|
108
|
+
newsPublishedAt: "Published {date}",
|
|
109
|
+
// ── Forms + human-in-the-loop (intake / ask-input / approval) ───
|
|
110
|
+
intakeSubmit: "Start chat",
|
|
111
|
+
intakeSkip: "Skip for now",
|
|
112
|
+
formRequired: "This field is required",
|
|
113
|
+
formInvalidEmail: "Enter a valid email address",
|
|
114
|
+
formInvalidTel: "Enter a valid phone number",
|
|
115
|
+
formInvalidUrl: "Enter a valid URL",
|
|
116
|
+
formInvalidNumber: "Enter a valid number",
|
|
117
|
+
formTooShort: "Too short (min {min} characters)",
|
|
118
|
+
formTooLong: "Too long (max {max} characters)",
|
|
119
|
+
formNumberTooSmall: "Must be at least {min}",
|
|
120
|
+
formNumberTooLarge: "Must be at most {max}",
|
|
121
|
+
formPatternMismatch: "Please match the requested format",
|
|
122
|
+
formChooseAtLeast: "Choose at least {min}",
|
|
123
|
+
formChooseAtMost: "Choose at most {max}",
|
|
124
|
+
formOther: "Other",
|
|
125
|
+
formOtherPlaceholder: "Type your answer\u2026",
|
|
126
|
+
inputRequired: "Input required",
|
|
127
|
+
inputSubmit: "Submit",
|
|
128
|
+
inputSkip: "Skip",
|
|
129
|
+
inputSubmitted: "Answer submitted",
|
|
130
|
+
approvalRequired: "Approval required",
|
|
131
|
+
approve: "Approve",
|
|
132
|
+
reject: "Reject",
|
|
133
|
+
approved: "Approved",
|
|
134
|
+
rejected: "Rejected",
|
|
135
|
+
approvalReason: "Add a reason (optional)",
|
|
136
|
+
stepNoLongerActive: "This request is no longer active."
|
|
137
|
+
};
|
|
138
|
+
var STRINGS_FR = {
|
|
139
|
+
attach: "Joindre des fichiers",
|
|
140
|
+
attachmentMimeRejected: "Type de fichier non pris en charge",
|
|
141
|
+
attachmentTooLarge: "Le fichier est trop volumineux",
|
|
142
|
+
attachmentTooMany: "Limite de pi\xE8ces jointes atteinte",
|
|
143
|
+
chatClosed: "Cette conversation est ferm\xE9e",
|
|
144
|
+
close: "Fermer",
|
|
145
|
+
collapse: "R\xE9duire",
|
|
146
|
+
collapseSidebar: "R\xE9duire la barre lat\xE9rale",
|
|
147
|
+
composerPlaceholder: "\xC9crivez un message\u2026",
|
|
148
|
+
dateLastWeek: "7 derniers jours",
|
|
149
|
+
dateOlder: "Plus ancien",
|
|
150
|
+
dateToday: "Aujourd'hui",
|
|
151
|
+
dateYesterday: "Hier",
|
|
152
|
+
dropZone: "D\xE9posez les fichiers \xE0 joindre",
|
|
153
|
+
errorGeneric: "Une erreur s'est produite",
|
|
154
|
+
errorRateLimited: "Trop de requ\xEAtes \u2014 veuillez r\xE9essayer dans un instant.",
|
|
155
|
+
errorRetry: "R\xE9essayer",
|
|
156
|
+
expand: "Agrandir",
|
|
157
|
+
expandSidebar: "D\xE9velopper la barre lat\xE9rale",
|
|
158
|
+
exitFullscreen: "Quitter le plein \xE9cran",
|
|
159
|
+
fullscreen: "Plein \xE9cran",
|
|
160
|
+
history: "Historique",
|
|
161
|
+
historyBack: "Retour au chat",
|
|
162
|
+
historyEmpty: "Aucune conversation pour le moment",
|
|
163
|
+
historyLoading: "Chargement de vos conversations\u2026",
|
|
164
|
+
historyNewChat: "Nouvelle conversation",
|
|
165
|
+
historyTitle: "Historique des conversations",
|
|
166
|
+
language: "Langue",
|
|
167
|
+
launcherOpen: "Ouvrir le chat",
|
|
168
|
+
messagesLoading: "Chargement de la conversation\u2026",
|
|
169
|
+
micStart: "D\xE9marrer la saisie vocale",
|
|
170
|
+
micStop: "Arr\xEAter la saisie vocale",
|
|
171
|
+
micUnsupported: "La saisie vocale n'est pas prise en charge par ce navigateur",
|
|
172
|
+
moreActions: "Plus d'actions",
|
|
173
|
+
newConversation: "Nouvelle conversation",
|
|
174
|
+
panelTitle: "Chat",
|
|
175
|
+
popOut: "Ouvrir dans un nouvel onglet",
|
|
176
|
+
resizeHandle: "Glisser pour redimensionner",
|
|
177
|
+
scrollToBottom: "Aller au plus r\xE9cent",
|
|
178
|
+
send: "Envoyer",
|
|
179
|
+
soundOff: "Son d\xE9sactiv\xE9",
|
|
180
|
+
soundOn: "Son activ\xE9",
|
|
181
|
+
startNewConversation: "D\xE9marrer une nouvelle conversation",
|
|
182
|
+
stop: "Arr\xEAter",
|
|
183
|
+
theme: "Th\xE8me",
|
|
184
|
+
themeAuto: "Auto (syst\xE8me)",
|
|
185
|
+
themeDark: "Sombre",
|
|
186
|
+
themeLight: "Clair",
|
|
187
|
+
loading: "Chargement\u2026",
|
|
188
|
+
thinking: "R\xE9flexion\u2026",
|
|
189
|
+
thoughts: "R\xE9flexions",
|
|
190
|
+
usedTool: "Outil utilis\xE9",
|
|
191
|
+
// ── Messenger modules ──────────────────────────────────────────
|
|
192
|
+
tabHome: "Accueil",
|
|
193
|
+
tabMessages: "Messages",
|
|
194
|
+
tabHelp: "Aide",
|
|
195
|
+
tabNews: "Actualit\xE9s",
|
|
196
|
+
modulesEmpty: "Rien pour le moment",
|
|
197
|
+
moduleBack: "Retour",
|
|
198
|
+
contentLoading: "Chargement\u2026",
|
|
199
|
+
homeGreeting: "Comment pouvons-nous vous aider ?",
|
|
200
|
+
homeGreetingNamed: "Bonjour {name} \u{1F44B}",
|
|
201
|
+
homeGreetingLead: "Comment pouvons-nous vous aider ?",
|
|
202
|
+
homeSearchPlaceholder: "Rechercher de l'aide",
|
|
203
|
+
homeContentTitle: "Articles populaires",
|
|
204
|
+
helpTitle: "Aide",
|
|
205
|
+
helpSearchPlaceholder: "Rechercher de l'aide",
|
|
206
|
+
helpEmpty: "Aucun article d'aide pour le moment",
|
|
207
|
+
helpLoading: "Chargement de l'aide\u2026",
|
|
208
|
+
helpSearchEmpty: "Aucun r\xE9sultat trouv\xE9",
|
|
209
|
+
newsTitle: "Actualit\xE9s",
|
|
210
|
+
newsEmpty: "Aucune actualit\xE9 pour le moment",
|
|
211
|
+
newsLoading: "Chargement des actualit\xE9s\u2026",
|
|
212
|
+
newsBack: "Retour aux actualit\xE9s",
|
|
213
|
+
newsPublishedAt: "Publi\xE9 le {date}",
|
|
214
|
+
// ── Forms + human-in-the-loop (intake / ask-input / approval) ───
|
|
215
|
+
intakeSubmit: "D\xE9marrer le chat",
|
|
216
|
+
intakeSkip: "Ignorer pour l'instant",
|
|
217
|
+
formRequired: "Ce champ est obligatoire",
|
|
218
|
+
formInvalidEmail: "Saisissez une adresse e-mail valide",
|
|
219
|
+
formInvalidTel: "Saisissez un num\xE9ro de t\xE9l\xE9phone valide",
|
|
220
|
+
formInvalidUrl: "Saisissez une URL valide",
|
|
221
|
+
formInvalidNumber: "Saisissez un nombre valide",
|
|
222
|
+
formTooShort: "Trop court (min. {min} caract\xE8res)",
|
|
223
|
+
formTooLong: "Trop long (max. {max} caract\xE8res)",
|
|
224
|
+
formNumberTooSmall: "Doit \xEAtre au moins {min}",
|
|
225
|
+
formNumberTooLarge: "Doit \xEAtre au plus {max}",
|
|
226
|
+
formPatternMismatch: "Veuillez respecter le format demand\xE9",
|
|
227
|
+
formChooseAtLeast: "Choisissez au moins {min}",
|
|
228
|
+
formChooseAtMost: "Choisissez au plus {max}",
|
|
229
|
+
formOther: "Autre",
|
|
230
|
+
formOtherPlaceholder: "Saisissez votre r\xE9ponse\u2026",
|
|
231
|
+
inputRequired: "Saisie requise",
|
|
232
|
+
inputSubmit: "Envoyer",
|
|
233
|
+
inputSkip: "Ignorer",
|
|
234
|
+
inputSubmitted: "R\xE9ponse envoy\xE9e",
|
|
235
|
+
approvalRequired: "Approbation requise",
|
|
236
|
+
approve: "Approuver",
|
|
237
|
+
reject: "Refuser",
|
|
238
|
+
approved: "Approuv\xE9",
|
|
239
|
+
rejected: "Refus\xE9",
|
|
240
|
+
approvalReason: "Ajouter une raison (facultatif)",
|
|
241
|
+
stepNoLongerActive: "Cette demande n'est plus active."
|
|
242
|
+
};
|
|
243
|
+
var BUILTIN_STRINGS = {
|
|
244
|
+
en: STRINGS_EN,
|
|
245
|
+
fr: STRINGS_FR
|
|
109
246
|
};
|
|
110
247
|
function resolveStrings(locale, override) {
|
|
111
248
|
const tag = primaryTag(locale);
|
|
112
249
|
const isNested = isNestedShape(override);
|
|
250
|
+
const builtinLocale = tag === "en" ? {} : BUILTIN_STRINGS[tag] ?? {};
|
|
113
251
|
const localeOverride = isNested ? override[tag] ?? {} : override ?? {};
|
|
114
252
|
const enOverride = isNested ? override.en ?? {} : {};
|
|
115
253
|
return {
|
|
116
254
|
...STRINGS_EN,
|
|
255
|
+
...builtinLocale,
|
|
117
256
|
...enOverride,
|
|
118
257
|
...localeOverride
|
|
119
258
|
};
|
|
@@ -308,11 +447,14 @@ var DEFAULT_ATTACHMENTS = {
|
|
|
308
447
|
var DEFAULT_WELCOME = { animation: "typewriter", speed: 60 };
|
|
309
448
|
var DEFAULT_FEATURES = {
|
|
310
449
|
files: true,
|
|
311
|
-
voice: "local"
|
|
450
|
+
voice: "local",
|
|
451
|
+
humanInLoop: true
|
|
312
452
|
};
|
|
453
|
+
var DEFAULT_INTAKE = { enabled: false, fields: [], skippable: false };
|
|
313
454
|
var DEFAULT_ENDPOINTS = {
|
|
314
455
|
upload: "/ai/agent/upload-file",
|
|
315
|
-
transcribe: "/ai/agent/transcribe-audio"
|
|
456
|
+
transcribe: "/ai/agent/transcribe-audio",
|
|
457
|
+
intake: "/ai/agent/intake"
|
|
316
458
|
};
|
|
317
459
|
var DEFAULT_LAUNCHER = {
|
|
318
460
|
variant: "circle",
|
|
@@ -374,11 +516,14 @@ function resolveOptions(rawOpts) {
|
|
|
374
516
|
features: {
|
|
375
517
|
files: opts.features?.files ?? DEFAULT_FEATURES.files,
|
|
376
518
|
voice: opts.features?.voice ?? DEFAULT_FEATURES.voice,
|
|
519
|
+
humanInLoop: opts.features?.humanInLoop ?? DEFAULT_FEATURES.humanInLoop,
|
|
377
520
|
tools: opts.features?.tools
|
|
378
521
|
},
|
|
522
|
+
intake: resolveIntake(opts.intake),
|
|
379
523
|
endpoints: {
|
|
380
524
|
upload: opts.endpoints?.upload ?? DEFAULT_ENDPOINTS.upload,
|
|
381
|
-
transcribe: opts.endpoints?.transcribe ?? DEFAULT_ENDPOINTS.transcribe
|
|
525
|
+
transcribe: opts.endpoints?.transcribe ?? DEFAULT_ENDPOINTS.transcribe,
|
|
526
|
+
intake: opts.endpoints?.intake ?? DEFAULT_ENDPOINTS.intake
|
|
382
527
|
},
|
|
383
528
|
attachments: {
|
|
384
529
|
accept: opts.composer?.attachments?.accept ?? DEFAULT_ATTACHMENTS.accept,
|
|
@@ -477,6 +622,18 @@ function resolveModules(overrides) {
|
|
|
477
622
|
const byId = Object.fromEntries(list.map((m) => [m.id, m]));
|
|
478
623
|
return { list, byId };
|
|
479
624
|
}
|
|
625
|
+
function resolveIntake(overrides) {
|
|
626
|
+
const fields = (overrides?.fields ?? []).filter((f) => Boolean(f && f.name && f.label && f.type));
|
|
627
|
+
if (fields.length === 0) return DEFAULT_INTAKE;
|
|
628
|
+
return {
|
|
629
|
+
enabled: overrides?.enabled ?? false,
|
|
630
|
+
title: overrides?.title,
|
|
631
|
+
description: overrides?.description,
|
|
632
|
+
fields,
|
|
633
|
+
submitLabel: overrides?.submitLabel,
|
|
634
|
+
skippable: overrides?.skippable ?? false
|
|
635
|
+
};
|
|
636
|
+
}
|
|
480
637
|
function resolveLauncher(overrides) {
|
|
481
638
|
const callout = overrides?.callout?.text ? {
|
|
482
639
|
shape: "pill",
|
|
@@ -522,6 +679,7 @@ var SECTION_KEYS = [
|
|
|
522
679
|
"i18n",
|
|
523
680
|
"footer",
|
|
524
681
|
"features",
|
|
682
|
+
"intake",
|
|
525
683
|
"endpoints"
|
|
526
684
|
];
|
|
527
685
|
function mergeServerConfig(user, server) {
|
|
@@ -712,7 +870,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
712
870
|
var reset_default = '*,*:before,*:after{box-sizing:border-box;margin:0;padding:0;border:0}button{font:inherit;color:inherit;background:none;cursor:pointer;-webkit-appearance:none;appearance:none;line-height:1}button:focus-visible,[tabindex]:focus-visible,textarea:focus-visible,input:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}textarea,input{font:inherit;color:inherit;background:none;border:0;outline:0;resize:none}a{color:var(--__P__-accent);text-decoration:underline;text-underline-offset:2px}img,svg{display:block;max-width:100%}ul,ol{list-style:none}.__P__-app{display:block;width:100%;height:100%;font-family:var(--__P__-font);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"cv11","ss01","ss03"}.__P__-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n';
|
|
713
871
|
|
|
714
872
|
// src/styles/panel.css
|
|
715
|
-
var panel_default = '.__P__-anchor{right:16px;bottom:16px}:host([data-position="bottom-left"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{right:auto;left:16px}:host([data-position="top-right"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{bottom:auto;top:16px}.__P__-anchor{position:fixed;display:flex;flex-direction:column;align-items:flex-end;gap:var(--__P__-space-3);pointer-events:none}.__P__-anchor{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=sm]{--__P__-fab-size: 44px}.__P__-anchor[data-launcher-size=md]{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=lg]{--__P__-fab-size: 68px}.__P__-anchor>*{pointer-events:auto}.__P__-fab[data-size=sm]{--__P__-fab-size: 44px;font-size:var(--__P__-text-sm)}.__P__-fab[data-size=md]{--__P__-fab-size: 56px;font-size:14px}.__P__-fab[data-size=lg]{--__P__-fab-size: 68px;font-size:var(--__P__-text-base)}.__P__-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);color:var(--__P__-accent-text);background:var(--__P__-accent);box-shadow:var(--__P__-shadow-fab);font-weight:600;line-height:1;transform-origin:bottom right;animation:__P__-fab-in var(--__P__-dur-base) var(--__P__-ease) both;transition:transform var(--__P__-dur-base) var(--__P__-ease),opacity var(--__P__-dur-base) var(--__P__-ease),box-shadow var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab:hover{transform:translateY(-2px)}.__P__-fab:active{transform:translateY(0)}.__P__-fab:focus-visible{outline:2px solid var(--__P__-on-accent);outline-offset:3px}.__P__-fab svg{width:24px;height:24px;flex-shrink:0}@keyframes __P__-fab-in{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}.__P__-fab[data-leaving]{position:absolute;right:0;bottom:0;animation:__P__-fab-out var(--__P__-dur-quick) var(--__P__-ease) forwards;pointer-events:none}:host([data-position^="top-"]) .__P__-fab[data-leaving]{bottom:auto;top:0}:host([data-position$="-left"]) .__P__-fab[data-leaving]{right:auto;left:0}@keyframes __P__-fab-out{0%{opacity:1;transform:none}to{opacity:0;transform:scale(.85)}}.__P__-fab[data-variant=circle]{width:var(--__P__-fab-size);height:var(--__P__-fab-size);border-radius:999px}.__P__-fab[data-variant=circle] .__P__-fab-label{display:none}.__P__-fab[data-variant=pill]{height:var(--__P__-fab-size);padding:0 18px 0 16px;border-radius:999px}.__P__-fab[data-variant=bar]{height:var(--__P__-fab-size);padding:0 22px;border-radius:var(--__P__-radius)}.__P__-fab[data-variant=minimal]{height:var(--__P__-fab-size);padding:0 var(--__P__-space-4);border-radius:999px;background:transparent;color:var(--__P__-accent);box-shadow:none;border:1px solid currentColor}.__P__-fab[data-variant=minimal]:hover{background:color-mix(in srgb,var(--__P__-accent) 12%,transparent)}.__P__-callout{--__P__-callout-fab-h: var(--__P__-fab-size, 56px);--__P__-callout-gap: clamp(12px, calc(var(--__P__-callout-fab-h) * .25), 22px);--__P__-callout-nudge-direction: -1;position:absolute;display:inline-flex;align-items:center;gap:var(--__P__-space-2);padding:10px 14px;background:var(--__P__-fg);color:var(--__P__-bg);border-radius:999px;font-size:var(--__P__-text-sm);font-weight:600;line-height:1.2;box-shadow:0 10px 30px -8px #00000059;pointer-events:auto;animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease);z-index:1;max-width:240px;white-space:nowrap}.__P__-callout[data-position=left]{right:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%)}.__P__-callout[data-position=right]{left:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%);--__P__-callout-nudge-direction: 1}.__P__-callout[data-position=top]{bottom:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-position=bottom]{top:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}:host([data-position$="-left"]) .__P__-callout[data-position=top],:host([data-position$="-left"]) .__P__-callout[data-position=bottom]{right:auto;left:0}.__P__-callout[data-shape=bubble]{border-radius:var(--__P__-radius-md);white-space:normal;width:max-content;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-shape=callout]{padding:12px 18px;font-size:14px;background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-callout:after{content:"";position:absolute;width:12px;height:12px;background:inherit;border-radius:2px;transform:rotate(45deg)}.__P__-callout[data-position=left]:after{right:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=right]:after{left:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=top]:after{bottom:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-position=bottom]:after{top:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}:host([data-position$="-left"]) .__P__-callout[data-position=top]:after,:host([data-position$="-left"]) .__P__-callout[data-position=bottom]:after{right:auto;left:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-animated]{animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease),__P__-callout-nudge 1.6s var(--__P__-ease-in-out) var(--__P__-dur-slow) infinite}@keyframes __P__-callout-in{0%{opacity:0}to{opacity:1}}@keyframes __P__-callout-nudge{0%,to{margin-left:0;margin-right:0}50%{margin-left:calc(6px * var(--__P__-callout-nudge-direction));margin-right:calc(-6px * var(--__P__-callout-nudge-direction))}}@media(prefers-reduced-motion:reduce){.__P__-callout[data-animated]{animation:__P__-callout-in 1ms var(--__P__-ease)}.__P__-icon-btn[data-recording=true],.__P__-typing span{animation:none}}.__P__-callout-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:inherit;opacity:.7;cursor:pointer}.__P__-callout-close:hover{opacity:1;background:#ffffff26}.__P__-callout-close svg{width:12px;height:12px}.__P__-panel{width:var(--__P__-panel-w);height:var(--__P__-panel-h);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);background:var(--__P__-bg);color:var(--__P__-fg);border-radius:var(--__P__-radius-lg);box-shadow:var(--__P__-shadow-panel);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;animation:__P__-panel-in var(--__P__-dur-slow) var(--__P__-ease);border:1px solid var(--__P__-border)}:host([data-mode="open"]) .__P__-panel{width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));min-width:var(--__P__-resize-min-w, auto);min-height:var(--__P__-resize-min-h, auto);max-width:var(--__P__-resize-max-w, calc(100vw - 32px) );max-height:var(--__P__-resize-max-h, calc(100dvh - 32px) )}@keyframes __P__-panel-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}:host([data-mode="expanded"]) .__P__-panel{width:var(--__P__-expanded-w, 640px);height:var(--__P__-expanded-h, 820px);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px)}:host([data-mode="fullscreen"]){z-index:var(--__P__-z-panel)!important}:host([data-mode="fullscreen"]) .__P__-anchor{inset:0;align-items:stretch;padding:0}:host([data-mode="fullscreen"]) .__P__-panel{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}:host([data-mode="fullscreen"]) .__P__-fab{display:none}:host([data-mode="inline"]) .__P__-anchor,:host([data-mode="standalone"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-height:0}:host([data-mode="inline"]) .__P__-panel,:host([data-mode="standalone"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;animation:none}:host([data-mode="inline"]) .__P__-fab,:host([data-mode="standalone"]) .__P__-fab{display:none}:host([data-mode="inline"]){min-height:320px}:host([data-mode="inline"]) .__P__-panel{border-radius:var(--__P__-radius)}:host([data-mode="standalone"]) .__P__-panel{border-radius:0;border:0;box-shadow:none}:host([data-mode="modal"]){position:fixed!important;inset:0!important;z-index:var(--__P__-z-panel)!important;display:block!important;width:100vw;height:100dvh;background:var(--__P__-modal-backdrop, var(--__P__-backdrop));animation:__P__-backdrop-in var(--__P__-dur-base) var(--__P__-ease) both;--__P__-panel-w: min(960px, 92vw);--__P__-panel-h: min(720px, 88dvh)}:host([data-mode="modal"]) .__P__-anchor{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:var(--__P__-space-6);pointer-events:none}:host([data-mode="modal"]) .__P__-panel{pointer-events:auto;width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));max-width:calc(100vw - 48px);max-height:calc(100dvh - 48px);min-width:0;min-height:0;border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-panel);animation:__P__-modal-in var(--__P__-dur-base) var(--__P__-ease);translate:var(--__P__-modal-dx, 0px) var(--__P__-modal-dy, 0px)}:host([data-mode="modal"]) .__P__-header,:host([data-mode="modal"]) .__P__-back-header,:host([data-mode="modal"]) .__P__-home-hero{cursor:grab;touch-action:none}:host([data-mode="modal"]) .__P__-panel[data-dragging]{cursor:grabbing;user-select:none}:host([data-mode="modal"]) .__P__-panel[data-dragging] *{cursor:grabbing}:host([data-mode="modal"]) .__P__-fab{display:none}@keyframes __P__-backdrop-in{0%{background:#0000}to{background:var(--__P__-modal-backdrop, var(--__P__-backdrop))}}@keyframes __P__-modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}:host([data-mode="drawer"]){--__P__-panel-w: min(440px, calc(100vw - 32px) );--__P__-panel-h: 100dvh}:host([data-mode="drawer"]) .__P__-anchor{position:fixed;--__P__-inset-x: var(--__P__-panel-inset, 12px);--__P__-inset-y: var(--__P__-panel-inset, 3dvh);top:var(--__P__-inset-y);bottom:auto;right:var(--__P__-inset-x);left:auto;width:min(var(--__P__-widget-w, var(--__P__-panel-w)),calc(100vw - var(--__P__-inset-x) * 2));height:min(var(--__P__-widget-h, var(--__P__-panel-h)),calc(100dvh - var(--__P__-inset-y) * 2));padding:0;display:block;pointer-events:auto}:host([data-mode="drawer"][data-position$="-left"]) .__P__-anchor{right:auto;left:var(--__P__-inset-x)}:host([data-mode="drawer"][data-position^="bottom-"]) .__P__-anchor{top:auto;bottom:var(--__P__-inset-y)}:host([data-mode="drawer"]) .__P__-panel{width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border-radius:var(--__P__-radius, 12px);border:1px solid var(--__P__-border);box-shadow:-8px 16px 32px -12px #00000038;animation:__P__-drawer-in var(--__P__-dur-base) var(--__P__-ease)}:host([data-mode="drawer"][data-position$="-left"]) .__P__-panel{box-shadow:8px 16px 32px -12px #00000038;animation:__P__-drawer-in-left var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab[data-edge-tab]{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-2);position:fixed;top:50%;height:140px;width:auto;min-width:0;padding:10px 8px;writing-mode:vertical-rl;text-orientation:mixed;transform:translateY(-50%);transform-origin:center;animation:__P__-edge-tab-in var(--__P__-dur-base) var(--__P__-ease) both}.__P__-fab[data-edge-tab] svg{writing-mode:horizontal-tb}.__P__-fab[data-edge-tab]:hover{transform:translateY(-50%) scale(1.03)}.__P__-fab[data-edge-tab]:active{transform:translateY(-50%) scale(.97)}:host([data-position$="-right"]) .__P__-fab[data-edge-tab]{right:0;left:auto;border-radius:12px 0 0 12px;box-shadow:-6px 0 18px -8px #0000004d}:host([data-position$="-left"]) .__P__-fab[data-edge-tab]{left:0;right:auto;border-radius:0 12px 12px 0;box-shadow:6px 0 18px -8px #0000004d}.__P__-fab[data-edge-tab][data-leaving]{position:fixed;top:50%;bottom:auto;animation:__P__-edge-tab-out var(--__P__-dur-quick) var(--__P__-ease) forwards}@keyframes __P__-edge-tab-in{0%{opacity:0;transform:translateY(-50%) scale(.9)}to{opacity:1;transform:translateY(-50%) scale(1)}}@keyframes __P__-edge-tab-out{0%{opacity:1;transform:translateY(-50%) scale(1)}to{opacity:0;transform:translateY(-50%) scale(.85)}}@keyframes __P__-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes __P__-drawer-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@media(prefers-reduced-motion:reduce){:host([data-mode="drawer"]) .__P__-panel,.__P__-fab[data-edge-tab]{animation:none}}.__P__-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);background:var(--__P__-bg)}.__P__-header h1{font-size:14px;font-weight:600;flex:1;letter-spacing:-.01em}.__P__-header-actions{margin-left:auto;display:flex;align-items:center;gap:var(--__P__-space-1);flex-shrink:0}.__P__-agent{flex:1;display:inline-flex;align-items:center;gap:10px;min-width:0}.__P__-agent-avatar{position:relative;width:32px;height:32px;border-radius:999px;background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--__P__-text-xs);overflow:hidden;flex-shrink:0}.__P__-agent-avatar img{width:100%;height:100%;object-fit:cover}.__P__-agent-avatar:after{content:"";position:absolute;right:-1px;bottom:-1px;width:10px;height:10px;border-radius:999px;border:2px solid var(--__P__-bg);background:var(--__P__-neutral)}.__P__-agent-avatar[data-status=online]:after{background:var(--__P__-success)}.__P__-agent-avatar[data-status=away]:after{background:var(--__P__-warning)}.__P__-agent-avatar[data-status=offline]:after{background:var(--__P__-neutral)}.__P__-agent-meta{display:flex;flex-direction:column;line-height:1.15;min-width:0}.__P__-agent-meta strong{font-size:14px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-agent-meta span{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-suggestions{display:flex;flex-wrap:nowrap;gap:var(--__P__-space-2);padding:6px 14px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;-ms-overflow-style:none;min-width:0}.__P__-suggestions::-webkit-scrollbar{display:none}.__P__-suggestions:before,.__P__-suggestions:after{content:"";flex:1 1 0;min-width:0}.__P__-suggestion{flex:0 0 auto;scroll-snap-align:center;padding:7px 14px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg);font-size:var(--__P__-text-sm);font-weight:500;white-space:nowrap;transition:background var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-suggestion:hover{border-color:var(--__P__-accent);color:var(--__P__-accent);transform:translateY(-1px)}.__P__-suggestion:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px;border-color:var(--__P__-accent)}.__P__-suggestion:active{transform:translateY(0)}.__P__-icon-btn{width:32px;height:32px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);transition:background var(--__P__-dur-quick) var(--__P__-ease),color var(--__P__-dur-quick) var(--__P__-ease)}.__P__-icon-btn:hover{background:var(--__P__-bg-elevated);color:var(--__P__-fg)}.__P__-icon-btn:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-icon-btn:active{background:var(--__P__-border)}.__P__-icon-btn:disabled{opacity:.45;cursor:not-allowed}.__P__-icon-btn:before{content:"";position:absolute;inset:-6px}.__P__-icon-btn{position:relative}.__P__-icon-btn svg{width:18px;height:18px}.__P__-icon-btn[data-recording=true]{color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);animation:__P__-pulse 1.2s var(--__P__-ease) infinite}@keyframes __P__-pulse{0%,to{box-shadow:0 0 color-mix(in srgb,var(--__P__-accent) 40%,transparent)}50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--__P__-accent) 0%,transparent)}}.__P__-list-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}.__P__-jump{position:absolute;right:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:999px;border:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);color:var(--__P__-fg);box-shadow:var(--__P__-shadow-panel);cursor:pointer;opacity:.85;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease);animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-jump:hover{opacity:1}.__P__-jump:active{transform:translateY(1px)}.__P__-jump svg{width:18px;height:18px}.__P__-list{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-4);padding-bottom:var(--__P__-space-8);display:flex;flex-direction:column;gap:14px;scrollbar-width:thin;scrollbar-color:var(--__P__-border-strong) transparent;scrollbar-gutter:stable}.__P__-list::-webkit-scrollbar{width:8px}.__P__-list::-webkit-scrollbar-thumb{background:var(--__P__-border-strong);border-radius:8px}.__P__-date-divider{position:sticky;top:var(--__P__-space-2);z-index:2;display:flex;justify-content:center;margin:var(--__P__-space-1) 0;pointer-events:none}.__P__-date-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--__P__-fg-muted);background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);box-shadow:var(--__P__-shadow-card);opacity:0;pointer-events:none;transition:opacity var(--__P__-dur-base) var(--__P__-ease)}.__P__-list[data-scrolling=true] .__P__-date-pill{opacity:1;pointer-events:auto}@media(prefers-reduced-motion:reduce){.__P__-date-pill{transition:none}}.__P__-bubble-row{display:flex}.__P__-bubble-row[data-role=user]{justify-content:flex-end}.__P__-bubble-row[data-role=assistant]{justify-content:flex-start}.__P__-bubble{max-width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);line-height:1.6;font-size:14px;word-wrap:break-word;overflow-wrap:anywhere;box-shadow:0 1px 2px #0000000a,0 1px 8px -4px #0000000f;animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-bubble ::selection{background:color-mix(in srgb,var(--__P__-accent) 30%,transparent)}.__P__-bubble-row[data-role=user] .__P__-bubble ::selection{background:#fff6;color:var(--__P__-bubble-user-text)}@keyframes __P__-bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.__P__-bubble-row[data-role=user] .__P__-bubble{background:var(--__P__-bubble-user);color:var(--__P__-bubble-user-text);border-bottom-right-radius:5px}.__P__-bubble-row[data-role=assistant] .__P__-bubble{background:var(--__P__-bubble-assistant);color:var(--__P__-bubble-assistant-text);border-bottom-left-radius:5px}.__P__-bubble-col{display:flex;flex-direction:column;max-width:85%;min-width:0}.__P__-bubble-row[data-role=user] .__P__-bubble-col{align-items:flex-end}.__P__-bubble-row[data-role=assistant] .__P__-bubble-col{align-items:flex-start}.__P__-bubble-time{margin-top:3px;padding:0 4px;font-size:11px;line-height:1;color:var(--__P__-fg-muted);user-select:none}.__P__-md>*:first-child{margin-top:0}.__P__-md>*:last-child{margin-bottom:0}.__P__-md p{margin:10px 0}.__P__-md h1,.__P__-md h2,.__P__-md h3,.__P__-md h4,.__P__-md h5,.__P__-md h6{margin:18px 0 8px;line-height:1.3;letter-spacing:-.01em;font-weight:700}.__P__-md h1{font-size:1.4em}.__P__-md h2{font-size:1.22em}.__P__-md h3{font-size:1.08em}.__P__-md h4,.__P__-md h5,.__P__-md h6{font-size:1em}.__P__-md>h1:first-child,.__P__-md>h2:first-child,.__P__-md>h3:first-child,.__P__-md>h4:first-child,.__P__-md>h5:first-child,.__P__-md>h6:first-child{margin-top:0}.__P__-md ul,.__P__-md ol{padding-left:1.5em;margin:10px 0}.__P__-md ul{list-style:disc}.__P__-md ol{list-style:decimal}.__P__-md li{margin:6px 0;padding-left:2px}.__P__-md li::marker{color:var(--__P__-fg-muted)}.__P__-md li>p{margin:6px 0}.__P__-md li>ul,.__P__-md li>ol{margin:6px 0}.__P__-md strong,.__P__-md b{font-weight:650;letter-spacing:-.005em}.__P__-md em,.__P__-md i{font-style:italic}.__P__-md code{font-family:var(--__P__-font-mono);font-size:.86em;padding:1px 6px;border-radius:5px;background:color-mix(in srgb,var(--__P__-accent) 10%,transparent);color:var(--__P__-fg);border:1px solid color-mix(in srgb,var(--__P__-accent) 16%,transparent)}.__P__-md pre{font-family:var(--__P__-font-mono);font-size:12.5px;padding:12px 14px;border-radius:var(--__P__-radius-sm);background:#7f7f7f1f;overflow-x:auto;margin:var(--__P__-space-3) 0;line-height:1.5}.__P__-md pre code{padding:0;background:none}.__P__-md a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}.__P__-md a:hover{text-decoration-thickness:2px}.__P__-md blockquote{margin:14px 0;padding:6px 14px;border-left:3px solid color-mix(in srgb,var(--__P__-accent) 50%,transparent);background:color-mix(in srgb,var(--__P__-accent) 5%,transparent);border-radius:0 var(--__P__-radius-sm) var(--__P__-radius-sm) 0;color:var(--__P__-fg-muted)}.__P__-md blockquote>:first-child{margin-top:0}.__P__-md blockquote>:last-child{margin-bottom:0}.__P__-md hr{border:0;height:1px;background:color-mix(in srgb,currentColor 18%,transparent);margin:var(--__P__-space-4) 0}.__P__-md table{border-collapse:collapse;margin:var(--__P__-space-3) 0;font-size:.95em;display:block;overflow-x:auto;max-width:100%;font-variant-numeric:tabular-nums}.__P__-md th,.__P__-md td{padding:6px 10px;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);text-align:left}.__P__-md th{font-weight:700;background:color-mix(in srgb,currentColor 6%,transparent)}.__P__-md h1+ul,.__P__-md h1+ol,.__P__-md h2+ul,.__P__-md h2+ol,.__P__-md h3+ul,.__P__-md h3+ol,.__P__-md h4+ul,.__P__-md h4+ol{margin-top:var(--__P__-space-1)}.__P__-loading{display:inline-flex;align-items:center;gap:var(--__P__-space-2);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-loading-spinner{width:14px;height:14px;border-radius:999px;border:2px solid currentColor;border-top-color:transparent;animation:__P__-spin .8s linear infinite}@keyframes __P__-spin{to{transform:rotate(1turn)}}.__P__-typing{display:inline-flex;gap:var(--__P__-space-1);padding:var(--__P__-space-1) 0}.__P__-typing span{width:5px;height:5px;border-radius:999px;background:currentColor;opacity:.4;animation:__P__-blink 1.2s var(--__P__-ease) infinite}.__P__-typing span:nth-child(2){animation-delay:.2s}.__P__-typing span:nth-child(3){animation-delay:.4s}@keyframes __P__-blink{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.__P__-reasoning{margin:var(--__P__-space-1) 0 var(--__P__-space-2);padding-left:var(--__P__-space-3);border-left:2px solid var(--__P__-border-strong)}.__P__-reasoning-summary{display:inline-flex;align-items:center;gap:var(--__P__-space-1);cursor:pointer;list-style:none;user-select:none;color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-reasoning-summary::-webkit-details-marker{display:none}.__P__-reasoning-summary:before{content:"";width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);opacity:.7;transition:transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-reasoning[open] .__P__-reasoning-summary:before{transform:rotate(45deg)}.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:__P__-reasoning-pulse 1.4s var(--__P__-ease) infinite}@keyframes __P__-reasoning-pulse{0%,to{opacity:.5}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:none}}.__P__-reasoning-body{margin-top:var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-reasoning-body>:first-child{margin-top:0}.__P__-reasoning-body>:last-child{margin-bottom:0}.__P__-tool-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2);margin-top:6px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs)}.__P__-composer{border-top:1px solid var(--__P__-border);padding:10px 12px;background:var(--__P__-bg);display:flex;flex-direction:column;gap:var(--__P__-space-2)}.__P__-composer-row{display:flex;align-items:flex-end;gap:6px}.__P__-textarea{flex:1;height:40px;max-height:160px;padding:10px 12px;border-radius:var(--__P__-radius);background:var(--__P__-bg-elevated);border:1px solid transparent;font-size:14px;line-height:1.4;transition:height var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),box-shadow var(--__P__-dur-quick) var(--__P__-ease)}.__P__-textarea:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:1px;border-color:var(--__P__-focus)}@media(pointer:coarse){.__P__-textarea,.__P__-home-search-input{font-size:16px}.__P__-textarea{height:44px}}.__P__-send{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease),background var(--__P__-dur-quick) var(--__P__-ease)}.__P__-send[data-shape=circle]{border-radius:999px}.__P__-send[data-shape=square]{border-radius:var(--__P__-radius-sm)}.__P__-send[data-shape=pill]{width:auto;padding:0 18px;border-radius:999px}.__P__-send[data-variant=filled]{background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-send[data-variant=outline]{background:transparent;color:var(--__P__-accent);border-color:var(--__P__-accent)}.__P__-send[data-variant=outline]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 10%,transparent)}.__P__-send[data-variant=ghost]{background:transparent;color:var(--__P__-accent)}.__P__-send[data-variant=ghost]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 8%,transparent)}.__P__-send:disabled{opacity:.4;cursor:not-allowed}.__P__-send:not(:disabled):hover{transform:translateY(-1px)}.__P__-send:not(:disabled):active{transform:translateY(0)}.__P__-send:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-send svg{width:18px;height:18px}.__P__-composer-actions{display:flex;gap:var(--__P__-space-1);flex-wrap:wrap}.__P__-attachments{display:flex;flex-wrap:wrap;gap:6px}.__P__-attachment-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-1);border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);font-size:var(--__P__-text-xs);max-width:200px}.__P__-attachment-thumb{width:24px;height:24px;border-radius:999px;object-fit:cover;background:var(--__P__-border)}.__P__-attachment-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-attachment-remove{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted)}.__P__-attachment-remove:hover{background:var(--__P__-border);color:var(--__P__-fg)}.__P__-dropzone{position:absolute;inset:8px;border:2px dashed var(--__P__-accent);border-radius:var(--__P__-radius);background:color-mix(in srgb,var(--__P__-accent) 8%,transparent);display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--__P__-accent);pointer-events:none;z-index:10;animation:__P__-fade-in var(--__P__-dur-quick) var(--__P__-ease)}@keyframes __P__-fade-in{0%{opacity:0}to{opacity:1}}.__P__-error{margin-top:var(--__P__-space-1);padding:8px 10px;border-radius:var(--__P__-radius-sm);background:var(--__P__-danger-bg);color:var(--__P__-danger-text);font-size:var(--__P__-text-sm);display:flex;align-items:center;gap:var(--__P__-space-2)}.__P__-error button{color:inherit;text-decoration:underline;font-size:var(--__P__-text-sm)}.__P__-history{flex:1;overflow-y:auto;padding:var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-3)}.__P__-history-footer{flex:none;padding:var(--__P__-space-2) var(--__P__-space-3) var(--__P__-space-3);border-top:1px solid var(--__P__-border);background:var(--__P__-surface)}.__P__-history-new{width:100%;display:flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);padding:var(--__P__-space-2) var(--__P__-space-3);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-on-accent);cursor:pointer;font-size:var(--__P__-text-sm);font-weight:600;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-history-new svg{width:16px;height:16px}.__P__-history-new:hover{filter:brightness(1.08)}.__P__-history-new:active{transform:translateY(1px)}.__P__-history-new:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-history-empty{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 16px;color:var(--__P__-fg-muted);font-size:14px;text-align:center}.__P__-history-group{display:flex;flex-direction:column;padding:0 var(--__P__-space-2)}.__P__-history-heading{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-fg-muted);padding:12px 8px 6px;text-transform:uppercase;letter-spacing:.04em}.__P__-history-item{all:unset;display:flex;flex-direction:column;gap:3px;padding:10px 12px;border-radius:var(--__P__-radius-md);cursor:pointer;transition:background var(--__P__-dur-base) var(--__P__-ease)}.__P__-history-item:hover{background:var(--__P__-bg-elevated)}.__P__-history-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-history-title{font-size:14px;font-weight:500;color:var(--__P__-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-preview{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-item[data-closed=true] .__P__-history-title:after{content:"\\2022";margin-left:var(--__P__-space-2);opacity:.5}.__P__-list-loading{margin:auto;padding:var(--__P__-space-6) var(--__P__-space-4);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);text-align:center}.__P__-readonly-banner{display:flex;flex-direction:column;align-items:center;gap:10px;padding:14px 12px;margin:0 var(--__P__-space-3) var(--__P__-space-3);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);text-align:center;font-size:var(--__P__-text-sm)}.__P__-readonly-label{line-height:1.4}.__P__-readonly-cta{appearance:none;border:0;cursor:pointer;padding:var(--__P__-space-2) var(--__P__-space-4);border-radius:999px;background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-readonly-cta:hover,.__P__-readonly-cta:focus-visible{filter:brightness(1.1)}.__P__-readonly-cta:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}.__P__-composer-footer{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:10px 16px;margin:0 var(--__P__-space-3);border-top:1px solid var(--__P__-border);text-align:center;font-size:11px;line-height:1.4;color:var(--__P__-fg-muted)}.__P__-disclaimer{max-width:320px;margin:0 auto;opacity:.9;letter-spacing:.01em}.__P__-poweredby{display:inline-flex;align-items:center;justify-content:center;gap:6px;color:inherit;text-decoration:none;opacity:.7;transition:opacity var(--__P__-dur-base) var(--__P__-ease);font-size:11px;letter-spacing:.02em}.__P__-poweredby:hover{opacity:1}.__P__-poweredby-logo{height:12px;width:auto;display:inline-block;vertical-align:middle}.__P__-poweredby-bar{flex:none;display:flex;align-items:center;justify-content:center;padding:6px 16px;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated)}.__P__-menu-wrap{position:relative;display:inline-flex}.__P__-menu{position:absolute;top:100%;right:0;margin-top:6px;min-width:200px;padding:6px;background:var(--__P__-bg);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);box-shadow:var(--__P__-shadow-panel);z-index:10;display:flex;flex-direction:column;gap:2px;animation:__P__-menu-in var(--__P__-dur-base) var(--__P__-ease)}@media(prefers-reduced-motion:reduce){.__P__-menu{animation:none}}@keyframes __P__-menu-in{0%{opacity:0;transform:translateY(-4px) scale(.98);transform-origin:top right}to{opacity:1;transform:none}}.__P__-menu-item{all:unset;display:flex;align-items:center;gap:10px;padding:8px 10px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);border-radius:var(--__P__-radius-sm);cursor:pointer;user-select:none}.__P__-menu-item:hover{background:var(--__P__-bg-elevated)}.__P__-menu-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-menu-item[disabled]{opacity:.45;cursor:not-allowed}.__P__-menu-icon{display:inline-flex;width:16px;height:16px;color:var(--__P__-fg-muted)}.__P__-menu-icon svg{width:16px;height:16px}.__P__-menu-label{flex:1}.__P__-menu-check{display:inline-flex;color:var(--__P__-accent)}.__P__-menu-check svg{width:14px;height:14px}.__P__-resize-grip{position:absolute;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);opacity:.45;transition:opacity var(--__P__-dur-base) var(--__P__-ease);z-index:2;touch-action:none;user-select:none}.__P__-resize-grip:hover,.__P__-resize-grip:focus-visible{opacity:1}.__P__-resize-grip svg{width:10px;height:10px}.__P__-resize-grip--bottom-left{bottom:2px;left:2px;cursor:nesw-resize;transform:scaleX(-1)}.__P__-resize-grip--bottom-right{bottom:2px;right:2px;cursor:nwse-resize}.__P__-resize-grip--top-left{top:2px;left:2px;cursor:nwse-resize;transform:rotate(180deg)}.__P__-resize-grip--top-right{top:2px;right:2px;cursor:nesw-resize;transform:scaleY(-1)}:host(:not([data-mode="open"])) .__P__-resize-grip{display:none}.__P__-messenger{display:flex;flex-direction:column;overflow:hidden}.__P__-messenger-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}.__P__-module{display:flex;flex-direction:column;height:100%;min-height:0}.__P__-module-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-3);display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-home{background:radial-gradient(125% 65% at 88% 0%,color-mix(in srgb,#fff 16%,transparent),transparent 55%),linear-gradient(180deg,var(--__P__-accent) 0%,var(--__P__-accent) 22%,color-mix(in srgb,var(--__P__-accent) 28%,var(--__P__-surface)) 44%,var(--__P__-surface) 70%);border-radius:var(--__P__-radius-lg) var(--__P__-radius-lg) 0 0}.__P__-home-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;background:transparent}.__P__-home-cards{display:flex;flex-direction:column;gap:var(--__P__-space-3);padding:4px 14px 16px}.__P__-module-pad{padding:var(--__P__-space-3) var(--__P__-space-3) 0}.__P__-module-empty{display:flex;flex-direction:column;align-items:center;gap:var(--__P__-space-3);padding:var(--__P__-space-8) var(--__P__-space-4);text-align:center;color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-module-retry{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border-strong);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);font-weight:600;cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-module-retry:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}.__P__-module-retry:active{background:var(--__P__-border)}.__P__-module-retry:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-help-list{flex:1;min-height:0;overflow-y:auto;padding-bottom:var(--__P__-space-3)}.__P__-help-group{display:flex;flex-direction:column}.__P__-help-section-title{position:sticky;top:0;z-index:1;margin:0;padding:var(--__P__-space-3) var(--__P__-space-5) var(--__P__-space-2);font-size:var(--__P__-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--__P__-fg-muted);background:var(--__P__-bg)}.__P__-help-card{margin:0 var(--__P__-space-3) var(--__P__-space-3);background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden}.__P__-help-card .__P__-list-row{border-bottom:0;border-radius:0}.__P__-help-card .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-help-card .__P__-list-row:hover{background:var(--__P__-hover)}.__P__-module-cta{padding:var(--__P__-space-3);border-top:1px solid var(--__P__-border)}.__P__-tabbar{display:flex;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);flex-shrink:0}.__P__-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-1);min-height:48px;padding:var(--__P__-space-2) var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600;transition:color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-tab:hover{color:var(--__P__-fg)}.__P__-tab[aria-selected=true]{color:var(--__P__-accent)}.__P__-tab:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-tab:active{background:var(--__P__-hover)}.__P__-tab-icon{position:relative;display:inline-flex}.__P__-tab-icon svg{width:22px;height:22px}.__P__-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--__P__-accent);color:var(--__P__-on-accent);font-size:10px;font-weight:600;line-height:1}.__P__-home-hero{flex-shrink:0;padding:var(--__P__-space-5) var(--__P__-space-5) var(--__P__-space-3);color:var(--__P__-on-accent);--__P__-focus: var(--__P__-on-accent)}.__P__-home-hero-top{display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-3);min-height:32px}.__P__-home-brand{font-size:14px;font-weight:600;letter-spacing:.01em;color:color-mix(in srgb,#fff 82%,transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.__P__-home-brand-spacer{flex:1}.__P__-home-hero-actions{display:flex;align-items:center;gap:var(--__P__-space-2);flex-shrink:0}.__P__-home-hero-actions .__P__-icon-btn{color:#fff}.__P__-home-greeting{margin:28px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;overflow-wrap:anywhere}.__P__-home-lead{margin:2px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;color:color-mix(in srgb,var(--__P__-on-accent) 88%,transparent);overflow-wrap:anywhere}.__P__-home-avatars{display:flex}.__P__-home-avatar{width:30px;height:30px;border-radius:999px;overflow:hidden;margin-left:-10px;border:2px solid color-mix(in srgb,#fff 92%,transparent);box-shadow:0 1px 3px #0000002e;background:var(--__P__-surface);display:inline-flex;align-items:center;justify-content:center;font-size:var(--__P__-text-xs);font-weight:700;color:var(--__P__-fg)}.__P__-home-avatar:first-child{margin-left:0}.__P__-home-avatar img{width:100%;height:100%;object-fit:cover}.__P__-home-content{background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-card);overflow:hidden}.__P__-home-content-title{padding:var(--__P__-space-4) var(--__P__-space-4) var(--__P__-space-3);font-size:var(--__P__-text-sm);font-weight:700}.__P__-home-content-list{display:flex;flex-direction:column;padding:0 var(--__P__-space-2) var(--__P__-space-2)}.__P__-home-content-list .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-home-card{display:block;width:100%;text-align:left;background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);padding:var(--__P__-space-4);box-shadow:var(--__P__-shadow-card)}.__P__-home-card[data-interactive=true]{cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-home-card[data-interactive=true]:hover{background:var(--__P__-bg-elevated)}.__P__-home-card[data-interactive=true]:active{transform:translateY(1px)}.__P__-home-card[data-interactive=true]:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-recent-row{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-recent-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;flex-shrink:0;border-radius:999px;background:color-mix(in oklch,var(--__P__-accent) 14%,transparent);color:var(--__P__-accent)}.__P__-home-recent-avatar svg{width:20px;height:20px}.__P__-home-recent-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.__P__-home-recent-title{font-weight:600;font-size:14px}.__P__-home-recent-preview{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-home-recent-at{color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);flex-shrink:0}.__P__-home-recent-dot{width:8px;height:8px;border-radius:999px;background:var(--__P__-accent);flex-shrink:0}.__P__-home-recent-row[data-unread=true] .__P__-home-recent-title{font-weight:700}.__P__-home-status{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-status-icon svg{width:22px;height:22px;color:var(--__P__-success)}.__P__-home-status[data-level=degraded] .__P__-home-status-icon svg{color:var(--__P__-warning)}.__P__-home-status[data-level=down] .__P__-home-status-icon svg{color:var(--__P__-danger)}.__P__-home-status-text{font-weight:600;font-size:14px}.__P__-home-search{display:flex;align-items:center;gap:var(--__P__-space-2);width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);border:1px solid var(--__P__-border);background:var(--__P__-surface);text-align:left}.__P__-home-search[data-input=true]{background:var(--__P__-bg-elevated)}.__P__-home-search:hover{border-color:var(--__P__-border-strong)}.__P__-home-search:focus-visible,.__P__-home-search:focus-within{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-search-text{flex:1;color:var(--__P__-fg-muted);font-size:14px}.__P__-home-search-input{flex:1;border:0;background:transparent;font-size:14px;color:var(--__P__-fg);outline:none}.__P__-home-search-icon svg{width:18px;height:18px;color:var(--__P__-accent)}.__P__-list-row{display:flex;align-items:center;gap:var(--__P__-space-3);width:100%;min-height:44px;text-align:left;padding:var(--__P__-space-3) var(--__P__-space-2);border-radius:var(--__P__-radius-sm)}.__P__-list-row:hover{background:var(--__P__-bg-elevated)}.__P__-list-row:active{background:var(--__P__-border)}.__P__-list-row:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-list-row-body{display:flex;flex-direction:column;min-width:0;flex:1}.__P__-list-row-title{font-weight:600;font-size:var(--__P__-text-md);line-height:1.35}.__P__-list-row-sub{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);margin-top:var(--__P__-space-1);line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-list-row-chevron svg{width:18px;height:18px;color:var(--__P__-accent);flex-shrink:0}.__P__-back-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);flex-shrink:0}.__P__-back-title{flex:1;text-align:center;font-size:var(--__P__-text-md);font-weight:700;margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-back-spacer{width:32px;height:1px}.__P__-content{display:flex;flex-direction:column;gap:14px;width:100%;max-width:68ch;margin:0 auto}.__P__-content-hero{width:100%;border-radius:var(--__P__-radius)}.__P__-content-subtitle{color:var(--__P__-fg-muted);margin:0}.__P__-content-frame{flex:1;min-height:0;width:100%;border:0;background:#fff}.__P__-news-list{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-news-card{display:block;width:100%;text-align:left;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden;background:var(--__P__-surface)}.__P__-news-card{transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-news-card:hover{background:var(--__P__-bg-elevated)}.__P__-news-card:active{transform:translateY(1px)}.__P__-news-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-news-hero{width:100%;display:block}.__P__-news-body{display:flex;flex-direction:column;gap:6px;padding:14px 16px}.__P__-news-tags{display:flex;gap:6px;flex-wrap:wrap}.__P__-news-tag{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);padding:2px 8px;border-radius:999px}.__P__-news-title{font-weight:700;font-size:var(--__P__-text-md)}.__P__-news-summary{color:var(--__P__-fg-muted);font-size:14px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-modules-empty{display:flex;align-items:center;justify-content:center;position:relative}.__P__-modules-empty-close{position:absolute;top:12px;right:12px}.__P__-modules-empty-text{color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}\n';
|
|
873
|
+
var panel_default = '.__P__-anchor{right:16px;bottom:16px}:host([data-position="bottom-left"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{right:auto;left:16px}:host([data-position="top-right"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{bottom:auto;top:16px}.__P__-anchor{position:fixed;display:flex;flex-direction:column;align-items:flex-end;gap:var(--__P__-space-3);pointer-events:none}.__P__-anchor{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=sm]{--__P__-fab-size: 44px}.__P__-anchor[data-launcher-size=md]{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=lg]{--__P__-fab-size: 68px}.__P__-anchor>*{pointer-events:auto}.__P__-fab[data-size=sm]{--__P__-fab-size: 44px;font-size:var(--__P__-text-sm)}.__P__-fab[data-size=md]{--__P__-fab-size: 56px;font-size:14px}.__P__-fab[data-size=lg]{--__P__-fab-size: 68px;font-size:var(--__P__-text-base)}.__P__-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);color:var(--__P__-accent-text);background:var(--__P__-accent);box-shadow:var(--__P__-shadow-fab);font-weight:600;line-height:1;transform-origin:bottom right;animation:__P__-fab-in var(--__P__-dur-base) var(--__P__-ease) both;transition:transform var(--__P__-dur-base) var(--__P__-ease),opacity var(--__P__-dur-base) var(--__P__-ease),box-shadow var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab:hover{transform:translateY(-2px)}.__P__-fab:active{transform:translateY(0)}.__P__-fab:focus-visible{outline:2px solid var(--__P__-on-accent);outline-offset:3px}.__P__-fab svg{width:24px;height:24px;flex-shrink:0}@keyframes __P__-fab-in{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}.__P__-fab[data-leaving]{position:absolute;right:0;bottom:0;animation:__P__-fab-out var(--__P__-dur-quick) var(--__P__-ease) forwards;pointer-events:none}:host([data-position^="top-"]) .__P__-fab[data-leaving]{bottom:auto;top:0}:host([data-position$="-left"]) .__P__-fab[data-leaving]{right:auto;left:0}@keyframes __P__-fab-out{0%{opacity:1;transform:none}to{opacity:0;transform:scale(.85)}}.__P__-fab[data-variant=circle]{width:var(--__P__-fab-size);height:var(--__P__-fab-size);border-radius:999px}.__P__-fab[data-variant=circle] .__P__-fab-label{display:none}.__P__-fab[data-variant=pill]{height:var(--__P__-fab-size);padding:0 18px 0 16px;border-radius:999px}.__P__-fab[data-variant=bar]{height:var(--__P__-fab-size);padding:0 22px;border-radius:var(--__P__-radius)}.__P__-fab[data-variant=minimal]{height:var(--__P__-fab-size);padding:0 var(--__P__-space-4);border-radius:999px;background:transparent;color:var(--__P__-accent);box-shadow:none;border:1px solid currentColor}.__P__-fab[data-variant=minimal]:hover{background:color-mix(in srgb,var(--__P__-accent) 12%,transparent)}.__P__-callout{--__P__-callout-fab-h: var(--__P__-fab-size, 56px);--__P__-callout-gap: clamp(12px, calc(var(--__P__-callout-fab-h) * .25), 22px);--__P__-callout-nudge-direction: -1;position:absolute;display:inline-flex;align-items:center;gap:var(--__P__-space-2);padding:10px 14px;background:var(--__P__-fg);color:var(--__P__-bg);border-radius:999px;font-size:var(--__P__-text-sm);font-weight:600;line-height:1.2;box-shadow:0 10px 30px -8px #00000059;pointer-events:auto;animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease);z-index:1;max-width:240px;white-space:nowrap}.__P__-callout[data-position=left]{right:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%)}.__P__-callout[data-position=right]{left:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%);--__P__-callout-nudge-direction: 1}.__P__-callout[data-position=top]{bottom:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-position=bottom]{top:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}:host([data-position$="-left"]) .__P__-callout[data-position=top],:host([data-position$="-left"]) .__P__-callout[data-position=bottom]{right:auto;left:0}.__P__-callout[data-shape=bubble]{border-radius:var(--__P__-radius-md);white-space:normal;width:max-content;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-shape=callout]{padding:12px 18px;font-size:14px;background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-callout:after{content:"";position:absolute;width:12px;height:12px;background:inherit;border-radius:2px;transform:rotate(45deg)}.__P__-callout[data-position=left]:after{right:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=right]:after{left:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=top]:after{bottom:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-position=bottom]:after{top:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}:host([data-position$="-left"]) .__P__-callout[data-position=top]:after,:host([data-position$="-left"]) .__P__-callout[data-position=bottom]:after{right:auto;left:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-animated]{animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease),__P__-callout-nudge 1.6s var(--__P__-ease-in-out) var(--__P__-dur-slow) infinite}@keyframes __P__-callout-in{0%{opacity:0}to{opacity:1}}@keyframes __P__-callout-nudge{0%,to{margin-left:0;margin-right:0}50%{margin-left:calc(6px * var(--__P__-callout-nudge-direction));margin-right:calc(-6px * var(--__P__-callout-nudge-direction))}}@media(prefers-reduced-motion:reduce){.__P__-callout[data-animated]{animation:__P__-callout-in 1ms var(--__P__-ease)}.__P__-icon-btn[data-recording=true],.__P__-typing span{animation:none}}.__P__-callout-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:inherit;opacity:.7;cursor:pointer}.__P__-callout-close:hover{opacity:1;background:#ffffff26}.__P__-callout-close svg{width:12px;height:12px}.__P__-panel{width:var(--__P__-panel-w);height:var(--__P__-panel-h);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);background:var(--__P__-bg);color:var(--__P__-fg);border-radius:var(--__P__-radius-lg);box-shadow:var(--__P__-shadow-panel);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;animation:__P__-panel-in var(--__P__-dur-slow) var(--__P__-ease);border:1px solid var(--__P__-border)}:host([data-mode="open"]) .__P__-panel{width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));min-width:var(--__P__-resize-min-w, auto);min-height:var(--__P__-resize-min-h, auto);max-width:var(--__P__-resize-max-w, calc(100vw - 32px) );max-height:var(--__P__-resize-max-h, calc(100dvh - 32px) )}@keyframes __P__-panel-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}:host([data-mode="expanded"]) .__P__-panel{width:var(--__P__-expanded-w, 640px);height:var(--__P__-expanded-h, 820px);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px)}:host([data-mode="fullscreen"]){z-index:var(--__P__-z-panel)!important}:host([data-mode="fullscreen"]) .__P__-anchor{inset:0;align-items:stretch;padding:0}:host([data-mode="fullscreen"]) .__P__-panel{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}:host([data-mode="fullscreen"]) .__P__-fab{display:none}:host([data-mode="inline"]) .__P__-anchor,:host([data-mode="standalone"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-height:0}:host([data-mode="inline"]) .__P__-panel,:host([data-mode="standalone"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;animation:none}:host([data-mode="inline"]) .__P__-fab,:host([data-mode="standalone"]) .__P__-fab{display:none}:host([data-mode="inline"]){min-height:320px}:host([data-mode="inline"]) .__P__-panel{border-radius:var(--__P__-radius)}:host([data-mode="standalone"]) .__P__-panel{border-radius:0;border:0;box-shadow:none}:host([data-mode="modal"]){position:fixed!important;inset:0!important;z-index:var(--__P__-z-panel)!important;display:block!important;width:100vw;height:100dvh;background:var(--__P__-modal-backdrop, var(--__P__-backdrop));animation:__P__-backdrop-in var(--__P__-dur-base) var(--__P__-ease) both;--__P__-panel-w: min(960px, 92vw);--__P__-panel-h: min(720px, 88dvh)}:host([data-mode="modal"]) .__P__-anchor{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:var(--__P__-space-6);pointer-events:none}:host([data-mode="modal"]) .__P__-panel{pointer-events:auto;width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));max-width:calc(100vw - 48px);max-height:calc(100dvh - 48px);min-width:0;min-height:0;border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-panel);animation:__P__-modal-in var(--__P__-dur-base) var(--__P__-ease);translate:var(--__P__-modal-dx, 0px) var(--__P__-modal-dy, 0px)}:host([data-mode="modal"]) .__P__-header,:host([data-mode="modal"]) .__P__-back-header,:host([data-mode="modal"]) .__P__-home-hero{cursor:grab;touch-action:none}:host([data-mode="modal"]) .__P__-panel[data-dragging]{cursor:grabbing;user-select:none}:host([data-mode="modal"]) .__P__-panel[data-dragging] *{cursor:grabbing}:host([data-mode="modal"]) .__P__-fab{display:none}@keyframes __P__-backdrop-in{0%{background:#0000}to{background:var(--__P__-modal-backdrop, var(--__P__-backdrop))}}@keyframes __P__-modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}:host([data-mode="drawer"]){--__P__-panel-w: min(440px, calc(100vw - 32px) );--__P__-panel-h: 100dvh}:host([data-mode="drawer"]) .__P__-anchor{position:fixed;--__P__-inset-x: var(--__P__-panel-inset, 12px);--__P__-inset-y: var(--__P__-panel-inset, 3dvh);top:var(--__P__-inset-y);bottom:auto;right:var(--__P__-inset-x);left:auto;width:min(var(--__P__-widget-w, var(--__P__-panel-w)),calc(100vw - var(--__P__-inset-x) * 2));height:min(var(--__P__-widget-h, var(--__P__-panel-h)),calc(100dvh - var(--__P__-inset-y) * 2));padding:0;display:block;pointer-events:auto}:host([data-mode="drawer"][data-position$="-left"]) .__P__-anchor{right:auto;left:var(--__P__-inset-x)}:host([data-mode="drawer"][data-position^="bottom-"]) .__P__-anchor{top:auto;bottom:var(--__P__-inset-y)}:host([data-mode="drawer"]) .__P__-panel{width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border-radius:var(--__P__-radius, 12px);border:1px solid var(--__P__-border);box-shadow:-8px 16px 32px -12px #00000038;animation:__P__-drawer-in var(--__P__-dur-base) var(--__P__-ease)}:host([data-mode="drawer"][data-position$="-left"]) .__P__-panel{box-shadow:8px 16px 32px -12px #00000038;animation:__P__-drawer-in-left var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab[data-edge-tab]{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-2);position:fixed;top:50%;height:140px;width:auto;min-width:0;padding:10px 8px;writing-mode:vertical-rl;text-orientation:mixed;transform:translateY(-50%);transform-origin:center;animation:__P__-edge-tab-in var(--__P__-dur-base) var(--__P__-ease) both}.__P__-fab[data-edge-tab] svg{writing-mode:horizontal-tb}.__P__-fab[data-edge-tab]:hover{transform:translateY(-50%) scale(1.03)}.__P__-fab[data-edge-tab]:active{transform:translateY(-50%) scale(.97)}:host([data-position$="-right"]) .__P__-fab[data-edge-tab]{right:0;left:auto;border-radius:12px 0 0 12px;box-shadow:-6px 0 18px -8px #0000004d}:host([data-position$="-left"]) .__P__-fab[data-edge-tab]{left:0;right:auto;border-radius:0 12px 12px 0;box-shadow:6px 0 18px -8px #0000004d}.__P__-fab[data-edge-tab][data-leaving]{position:fixed;top:50%;bottom:auto;animation:__P__-edge-tab-out var(--__P__-dur-quick) var(--__P__-ease) forwards}@keyframes __P__-edge-tab-in{0%{opacity:0;transform:translateY(-50%) scale(.9)}to{opacity:1;transform:translateY(-50%) scale(1)}}@keyframes __P__-edge-tab-out{0%{opacity:1;transform:translateY(-50%) scale(1)}to{opacity:0;transform:translateY(-50%) scale(.85)}}@keyframes __P__-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes __P__-drawer-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@media(prefers-reduced-motion:reduce){:host([data-mode="drawer"]) .__P__-panel,.__P__-fab[data-edge-tab]{animation:none}}.__P__-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);background:var(--__P__-bg)}.__P__-header h1{font-size:14px;font-weight:600;flex:1;letter-spacing:-.01em}.__P__-header-actions{margin-left:auto;display:flex;align-items:center;gap:var(--__P__-space-1);flex-shrink:0}.__P__-agent{flex:1;display:inline-flex;align-items:center;gap:10px;min-width:0}.__P__-agent-avatar{position:relative;width:32px;height:32px;border-radius:999px;background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--__P__-text-xs);overflow:hidden;flex-shrink:0}.__P__-agent-avatar img{width:100%;height:100%;object-fit:cover}.__P__-agent-avatar:after{content:"";position:absolute;right:-1px;bottom:-1px;width:10px;height:10px;border-radius:999px;border:2px solid var(--__P__-bg);background:var(--__P__-neutral)}.__P__-agent-avatar[data-status=online]:after{background:var(--__P__-success)}.__P__-agent-avatar[data-status=away]:after{background:var(--__P__-warning)}.__P__-agent-avatar[data-status=offline]:after{background:var(--__P__-neutral)}.__P__-agent-meta{display:flex;flex-direction:column;line-height:1.15;min-width:0}.__P__-agent-meta strong{font-size:14px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-agent-meta span{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-suggestions{display:flex;flex-wrap:nowrap;gap:var(--__P__-space-2);padding:6px 14px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;-ms-overflow-style:none;min-width:0}.__P__-suggestions::-webkit-scrollbar{display:none}.__P__-suggestions:before,.__P__-suggestions:after{content:"";flex:1 1 0;min-width:0}.__P__-suggestion{flex:0 0 auto;scroll-snap-align:center;padding:7px 14px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg);font-size:var(--__P__-text-sm);font-weight:500;white-space:nowrap;transition:background var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-suggestion:hover{border-color:var(--__P__-accent);color:var(--__P__-accent);transform:translateY(-1px)}.__P__-suggestion:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px;border-color:var(--__P__-accent)}.__P__-suggestion:active{transform:translateY(0)}.__P__-icon-btn{width:32px;height:32px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);transition:background var(--__P__-dur-quick) var(--__P__-ease),color var(--__P__-dur-quick) var(--__P__-ease)}.__P__-icon-btn:hover{background:var(--__P__-bg-elevated);color:var(--__P__-fg)}.__P__-icon-btn:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-icon-btn:active{background:var(--__P__-border)}.__P__-icon-btn:disabled{opacity:.45;cursor:not-allowed}.__P__-icon-btn:before{content:"";position:absolute;inset:-6px}.__P__-icon-btn{position:relative}.__P__-icon-btn svg{width:18px;height:18px}.__P__-icon-btn[data-recording=true]{color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);animation:__P__-pulse 1.2s var(--__P__-ease) infinite}@keyframes __P__-pulse{0%,to{box-shadow:0 0 color-mix(in srgb,var(--__P__-accent) 40%,transparent)}50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--__P__-accent) 0%,transparent)}}.__P__-list-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}.__P__-jump{position:absolute;right:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:999px;border:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);color:var(--__P__-fg);box-shadow:var(--__P__-shadow-panel);cursor:pointer;opacity:.85;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease);animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-jump:hover{opacity:1}.__P__-jump:active{transform:translateY(1px)}.__P__-jump svg{width:18px;height:18px}.__P__-list{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-4);padding-bottom:var(--__P__-space-8);display:flex;flex-direction:column;gap:14px;scrollbar-width:thin;scrollbar-color:var(--__P__-border-strong) transparent;scrollbar-gutter:stable}.__P__-list::-webkit-scrollbar{width:8px}.__P__-list::-webkit-scrollbar-thumb{background:var(--__P__-border-strong);border-radius:8px}.__P__-date-divider{position:sticky;top:var(--__P__-space-2);z-index:2;display:flex;justify-content:center;margin:var(--__P__-space-1) 0;pointer-events:none}.__P__-date-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--__P__-fg-muted);background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);box-shadow:var(--__P__-shadow-card);opacity:0;pointer-events:none;transition:opacity var(--__P__-dur-base) var(--__P__-ease)}.__P__-list[data-scrolling=true] .__P__-date-pill{opacity:1;pointer-events:auto}@media(prefers-reduced-motion:reduce){.__P__-date-pill{transition:none}}.__P__-bubble-row{display:flex}.__P__-bubble-row[data-role=user]{justify-content:flex-end}.__P__-bubble-row[data-role=assistant]{justify-content:flex-start}.__P__-bubble{max-width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);line-height:1.6;font-size:14px;word-wrap:break-word;overflow-wrap:anywhere;box-shadow:0 1px 2px #0000000a,0 1px 8px -4px #0000000f;animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-bubble ::selection{background:color-mix(in srgb,var(--__P__-accent) 30%,transparent)}.__P__-bubble-row[data-role=user] .__P__-bubble ::selection{background:#fff6;color:var(--__P__-bubble-user-text)}@keyframes __P__-bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.__P__-bubble-row[data-role=user] .__P__-bubble{background:var(--__P__-bubble-user);color:var(--__P__-bubble-user-text);border-bottom-right-radius:5px}.__P__-bubble-row[data-role=assistant] .__P__-bubble{background:var(--__P__-bubble-assistant);color:var(--__P__-bubble-assistant-text);border-bottom-left-radius:5px}.__P__-bubble-col{display:flex;flex-direction:column;max-width:85%;min-width:0}.__P__-bubble-row[data-role=user] .__P__-bubble-col{align-items:flex-end}.__P__-bubble-row[data-role=assistant] .__P__-bubble-col{align-items:flex-start}.__P__-bubble-time{margin-top:3px;padding:0 4px;font-size:11px;line-height:1;color:var(--__P__-fg-muted);user-select:none}.__P__-md>*:first-child{margin-top:0}.__P__-md>*:last-child{margin-bottom:0}.__P__-md p{margin:10px 0}.__P__-md h1,.__P__-md h2,.__P__-md h3,.__P__-md h4,.__P__-md h5,.__P__-md h6{margin:18px 0 8px;line-height:1.3;letter-spacing:-.01em;font-weight:700}.__P__-md h1{font-size:1.4em}.__P__-md h2{font-size:1.22em}.__P__-md h3{font-size:1.08em}.__P__-md h4,.__P__-md h5,.__P__-md h6{font-size:1em}.__P__-md>h1:first-child,.__P__-md>h2:first-child,.__P__-md>h3:first-child,.__P__-md>h4:first-child,.__P__-md>h5:first-child,.__P__-md>h6:first-child{margin-top:0}.__P__-md ul,.__P__-md ol{padding-left:1.5em;margin:10px 0}.__P__-md ul{list-style:disc}.__P__-md ol{list-style:decimal}.__P__-md li{margin:6px 0;padding-left:2px}.__P__-md li::marker{color:var(--__P__-fg-muted)}.__P__-md li>p{margin:6px 0}.__P__-md li>ul,.__P__-md li>ol{margin:6px 0}.__P__-md strong,.__P__-md b{font-weight:650;letter-spacing:-.005em}.__P__-md em,.__P__-md i{font-style:italic}.__P__-md code{font-family:var(--__P__-font-mono);font-size:.86em;padding:1px 6px;border-radius:5px;background:color-mix(in srgb,var(--__P__-accent) 10%,transparent);color:var(--__P__-fg);border:1px solid color-mix(in srgb,var(--__P__-accent) 16%,transparent)}.__P__-md pre{font-family:var(--__P__-font-mono);font-size:12.5px;padding:12px 14px;border-radius:var(--__P__-radius-sm);background:#7f7f7f1f;overflow-x:auto;margin:var(--__P__-space-3) 0;line-height:1.5}.__P__-md pre code{padding:0;background:none}.__P__-md a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}.__P__-md a:hover{text-decoration-thickness:2px}.__P__-md blockquote{margin:14px 0;padding:6px 14px;border-left:3px solid color-mix(in srgb,var(--__P__-accent) 50%,transparent);background:color-mix(in srgb,var(--__P__-accent) 5%,transparent);border-radius:0 var(--__P__-radius-sm) var(--__P__-radius-sm) 0;color:var(--__P__-fg-muted)}.__P__-md blockquote>:first-child{margin-top:0}.__P__-md blockquote>:last-child{margin-bottom:0}.__P__-md hr{border:0;height:1px;background:color-mix(in srgb,currentColor 18%,transparent);margin:var(--__P__-space-4) 0}.__P__-md table{border-collapse:collapse;margin:var(--__P__-space-3) 0;font-size:.95em;display:block;overflow-x:auto;max-width:100%;font-variant-numeric:tabular-nums}.__P__-md th,.__P__-md td{padding:6px 10px;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);text-align:left}.__P__-md th{font-weight:700;background:color-mix(in srgb,currentColor 6%,transparent)}.__P__-md h1+ul,.__P__-md h1+ol,.__P__-md h2+ul,.__P__-md h2+ol,.__P__-md h3+ul,.__P__-md h3+ol,.__P__-md h4+ul,.__P__-md h4+ol{margin-top:var(--__P__-space-1)}.__P__-loading{display:inline-flex;align-items:center;gap:var(--__P__-space-2);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-loading-spinner{width:14px;height:14px;border-radius:999px;border:2px solid currentColor;border-top-color:transparent;animation:__P__-spin .8s linear infinite}@keyframes __P__-spin{to{transform:rotate(1turn)}}.__P__-typing{display:inline-flex;gap:var(--__P__-space-1);padding:var(--__P__-space-1) 0}.__P__-typing span{width:5px;height:5px;border-radius:999px;background:currentColor;opacity:.4;animation:__P__-blink 1.2s var(--__P__-ease) infinite}.__P__-typing span:nth-child(2){animation-delay:.2s}.__P__-typing span:nth-child(3){animation-delay:.4s}@keyframes __P__-blink{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.__P__-reasoning{margin:var(--__P__-space-1) 0 var(--__P__-space-2);padding-left:var(--__P__-space-3);border-left:2px solid var(--__P__-border-strong)}.__P__-reasoning-summary{display:inline-flex;align-items:center;gap:var(--__P__-space-1);cursor:pointer;list-style:none;user-select:none;color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-reasoning-summary::-webkit-details-marker{display:none}.__P__-reasoning-summary:before{content:"";width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);opacity:.7;transition:transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-reasoning[open] .__P__-reasoning-summary:before{transform:rotate(45deg)}.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:__P__-reasoning-pulse 1.4s var(--__P__-ease) infinite}@keyframes __P__-reasoning-pulse{0%,to{opacity:.5}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:none}}.__P__-reasoning-body{margin-top:var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-reasoning-body>:first-child{margin-top:0}.__P__-reasoning-body>:last-child{margin-bottom:0}.__P__-tool-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2);margin-top:6px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs)}.__P__-composer{border-top:1px solid var(--__P__-border);padding:10px 12px;background:var(--__P__-bg);display:flex;flex-direction:column;gap:var(--__P__-space-2)}.__P__-composer-row{display:flex;align-items:flex-end;gap:6px}.__P__-textarea{flex:1;height:40px;max-height:160px;padding:10px 12px;border-radius:var(--__P__-radius);background:var(--__P__-bg-elevated);border:1px solid transparent;font-size:14px;line-height:1.4;transition:height var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),box-shadow var(--__P__-dur-quick) var(--__P__-ease)}.__P__-textarea:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:1px;border-color:var(--__P__-focus)}@media(pointer:coarse){.__P__-textarea,.__P__-home-search-input{font-size:16px}.__P__-textarea{height:44px}}.__P__-send{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease),background var(--__P__-dur-quick) var(--__P__-ease)}.__P__-send[data-shape=circle]{border-radius:999px}.__P__-send[data-shape=square]{border-radius:var(--__P__-radius-sm)}.__P__-send[data-shape=pill]{width:auto;padding:0 18px;border-radius:999px}.__P__-send[data-variant=filled]{background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-send[data-variant=outline]{background:transparent;color:var(--__P__-accent);border-color:var(--__P__-accent)}.__P__-send[data-variant=outline]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 10%,transparent)}.__P__-send[data-variant=ghost]{background:transparent;color:var(--__P__-accent)}.__P__-send[data-variant=ghost]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 8%,transparent)}.__P__-send:disabled{opacity:.4;cursor:not-allowed}.__P__-send:not(:disabled):hover{transform:translateY(-1px)}.__P__-send:not(:disabled):active{transform:translateY(0)}.__P__-send:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-send svg{width:18px;height:18px}.__P__-composer-actions{display:flex;gap:var(--__P__-space-1);flex-wrap:wrap}.__P__-attachments{display:flex;flex-wrap:wrap;gap:6px}.__P__-attachment-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-1);border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);font-size:var(--__P__-text-xs);max-width:200px}.__P__-attachment-thumb{width:24px;height:24px;border-radius:999px;object-fit:cover;background:var(--__P__-border)}.__P__-attachment-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-attachment-remove{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted)}.__P__-attachment-remove:hover{background:var(--__P__-border);color:var(--__P__-fg)}.__P__-dropzone{position:absolute;inset:8px;border:2px dashed var(--__P__-accent);border-radius:var(--__P__-radius);background:color-mix(in srgb,var(--__P__-accent) 8%,transparent);display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--__P__-accent);pointer-events:none;z-index:10;animation:__P__-fade-in var(--__P__-dur-quick) var(--__P__-ease)}@keyframes __P__-fade-in{0%{opacity:0}to{opacity:1}}.__P__-error{margin-top:var(--__P__-space-1);padding:8px 10px;border-radius:var(--__P__-radius-sm);background:var(--__P__-danger-bg);color:var(--__P__-danger-text);font-size:var(--__P__-text-sm);display:flex;align-items:center;gap:var(--__P__-space-2)}.__P__-error button{color:inherit;text-decoration:underline;font-size:var(--__P__-text-sm)}.__P__-history{flex:1;overflow-y:auto;padding:var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-3)}.__P__-history-footer{flex:none;padding:var(--__P__-space-2) var(--__P__-space-3) var(--__P__-space-3);border-top:1px solid var(--__P__-border);background:var(--__P__-surface)}.__P__-history-new{width:100%;display:flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);padding:var(--__P__-space-2) var(--__P__-space-3);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-on-accent);cursor:pointer;font-size:var(--__P__-text-sm);font-weight:600;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-history-new svg{width:16px;height:16px}.__P__-history-new:hover{filter:brightness(1.08)}.__P__-history-new:active{transform:translateY(1px)}.__P__-history-new:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-history-empty{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 16px;color:var(--__P__-fg-muted);font-size:14px;text-align:center}.__P__-history-group{display:flex;flex-direction:column;padding:0 var(--__P__-space-2)}.__P__-history-heading{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-fg-muted);padding:12px 8px 6px;text-transform:uppercase;letter-spacing:.04em}.__P__-history-item{all:unset;display:flex;flex-direction:column;gap:3px;padding:10px 12px;border-radius:var(--__P__-radius-md);cursor:pointer;transition:background var(--__P__-dur-base) var(--__P__-ease)}.__P__-history-item:hover{background:var(--__P__-bg-elevated)}.__P__-history-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-history-title{font-size:14px;font-weight:500;color:var(--__P__-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-preview{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-item[data-closed=true] .__P__-history-title:after{content:"\\2022";margin-left:var(--__P__-space-2);opacity:.5}.__P__-list-loading{margin:auto;padding:var(--__P__-space-6) var(--__P__-space-4);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);text-align:center}.__P__-readonly-banner{display:flex;flex-direction:column;align-items:center;gap:10px;padding:14px 12px;margin:0 var(--__P__-space-3) var(--__P__-space-3);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);text-align:center;font-size:var(--__P__-text-sm)}.__P__-readonly-label{line-height:1.4}.__P__-readonly-cta{appearance:none;border:0;cursor:pointer;padding:var(--__P__-space-2) var(--__P__-space-4);border-radius:999px;background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-readonly-cta:hover,.__P__-readonly-cta:focus-visible{filter:brightness(1.1)}.__P__-readonly-cta:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}.__P__-composer-footer{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:10px 16px;margin:0 var(--__P__-space-3);border-top:1px solid var(--__P__-border);text-align:center;font-size:11px;line-height:1.4;color:var(--__P__-fg-muted)}.__P__-disclaimer{max-width:320px;margin:0 auto;opacity:.9;letter-spacing:.01em}.__P__-poweredby{display:inline-flex;align-items:center;justify-content:center;gap:6px;color:inherit;text-decoration:none;opacity:.7;transition:opacity var(--__P__-dur-base) var(--__P__-ease);font-size:11px;letter-spacing:.02em}.__P__-poweredby:hover{opacity:1}.__P__-poweredby-logo{height:12px;width:auto;display:inline-block;vertical-align:middle}.__P__-poweredby-bar{flex:none;display:flex;align-items:center;justify-content:center;padding:6px 16px;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated)}.__P__-menu-wrap{position:relative;display:inline-flex}.__P__-menu{position:absolute;top:100%;right:0;margin-top:6px;min-width:200px;padding:6px;background:var(--__P__-bg);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);box-shadow:var(--__P__-shadow-panel);z-index:10;display:flex;flex-direction:column;gap:2px;animation:__P__-menu-in var(--__P__-dur-base) var(--__P__-ease)}@media(prefers-reduced-motion:reduce){.__P__-menu{animation:none}}@keyframes __P__-menu-in{0%{opacity:0;transform:translateY(-4px) scale(.98);transform-origin:top right}to{opacity:1;transform:none}}.__P__-menu-item{all:unset;display:flex;align-items:center;gap:10px;padding:8px 10px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);border-radius:var(--__P__-radius-sm);cursor:pointer;user-select:none}.__P__-menu-item:hover{background:var(--__P__-bg-elevated)}.__P__-menu-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-menu-item[disabled]{opacity:.45;cursor:not-allowed}.__P__-menu-icon{display:inline-flex;width:16px;height:16px;color:var(--__P__-fg-muted)}.__P__-menu-icon svg{width:16px;height:16px}.__P__-menu-label{flex:1}.__P__-menu-check{display:inline-flex;color:var(--__P__-accent)}.__P__-menu-check svg{width:14px;height:14px}.__P__-resize-grip{position:absolute;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);opacity:.45;transition:opacity var(--__P__-dur-base) var(--__P__-ease);z-index:2;touch-action:none;user-select:none}.__P__-resize-grip:hover,.__P__-resize-grip:focus-visible{opacity:1}.__P__-resize-grip svg{width:10px;height:10px}.__P__-resize-grip--bottom-left{bottom:2px;left:2px;cursor:nesw-resize;transform:scaleX(-1)}.__P__-resize-grip--bottom-right{bottom:2px;right:2px;cursor:nwse-resize}.__P__-resize-grip--top-left{top:2px;left:2px;cursor:nwse-resize;transform:rotate(180deg)}.__P__-resize-grip--top-right{top:2px;right:2px;cursor:nesw-resize;transform:scaleY(-1)}:host(:not([data-mode="open"])) .__P__-resize-grip{display:none}.__P__-messenger{display:flex;flex-direction:column;overflow:hidden}.__P__-messenger-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}.__P__-module{display:flex;flex-direction:column;height:100%;min-height:0}.__P__-module-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-3);display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-home{background:radial-gradient(125% 65% at 88% 0%,color-mix(in srgb,#fff 16%,transparent),transparent 55%),linear-gradient(180deg,var(--__P__-accent) 0%,var(--__P__-accent) 22%,color-mix(in srgb,var(--__P__-accent) 28%,var(--__P__-surface)) 44%,var(--__P__-surface) 70%);border-radius:var(--__P__-radius-lg) var(--__P__-radius-lg) 0 0}.__P__-home-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;background:transparent}.__P__-home-cards{display:flex;flex-direction:column;gap:var(--__P__-space-3);padding:4px 14px 16px}.__P__-module-pad{padding:var(--__P__-space-3) var(--__P__-space-3) 0}.__P__-module-empty{display:flex;flex-direction:column;align-items:center;gap:var(--__P__-space-3);padding:var(--__P__-space-8) var(--__P__-space-4);text-align:center;color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-module-retry{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border-strong);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);font-weight:600;cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-module-retry:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}.__P__-module-retry:active{background:var(--__P__-border)}.__P__-module-retry:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-help-list{flex:1;min-height:0;overflow-y:auto;padding-bottom:var(--__P__-space-3)}.__P__-help-group{display:flex;flex-direction:column}.__P__-help-section-title{position:sticky;top:0;z-index:1;margin:0;padding:var(--__P__-space-3) var(--__P__-space-5) var(--__P__-space-2);font-size:var(--__P__-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--__P__-fg-muted);background:var(--__P__-bg)}.__P__-help-card{margin:0 var(--__P__-space-3) var(--__P__-space-3);background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden}.__P__-help-card .__P__-list-row{border-bottom:0;border-radius:0}.__P__-help-card .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-help-card .__P__-list-row:hover{background:var(--__P__-hover)}.__P__-module-cta{padding:var(--__P__-space-3);border-top:1px solid var(--__P__-border)}.__P__-tabbar{display:flex;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);flex-shrink:0}.__P__-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-1);min-height:48px;padding:var(--__P__-space-2) var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600;transition:color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-tab:hover{color:var(--__P__-fg)}.__P__-tab[aria-selected=true]{color:var(--__P__-accent)}.__P__-tab:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-tab:active{background:var(--__P__-hover)}.__P__-tab-icon{position:relative;display:inline-flex}.__P__-tab-icon svg{width:22px;height:22px}.__P__-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--__P__-accent);color:var(--__P__-on-accent);font-size:10px;font-weight:600;line-height:1}.__P__-home-hero{flex-shrink:0;padding:var(--__P__-space-5) var(--__P__-space-5) var(--__P__-space-3);color:var(--__P__-on-accent);--__P__-focus: var(--__P__-on-accent)}.__P__-home-hero-top{display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-3);min-height:32px}.__P__-home-brand{font-size:14px;font-weight:600;letter-spacing:.01em;color:color-mix(in srgb,#fff 82%,transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.__P__-home-brand-spacer{flex:1}.__P__-home-hero-actions{display:flex;align-items:center;gap:var(--__P__-space-2);flex-shrink:0}.__P__-home-hero-actions .__P__-icon-btn{color:#fff}.__P__-home-greeting{margin:28px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;overflow-wrap:anywhere}.__P__-home-lead{margin:2px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;color:color-mix(in srgb,var(--__P__-on-accent) 88%,transparent);overflow-wrap:anywhere}.__P__-home-avatars{display:flex}.__P__-home-avatar{width:30px;height:30px;border-radius:999px;overflow:hidden;margin-left:-10px;border:2px solid color-mix(in srgb,#fff 92%,transparent);box-shadow:0 1px 3px #0000002e;background:var(--__P__-surface);display:inline-flex;align-items:center;justify-content:center;font-size:var(--__P__-text-xs);font-weight:700;color:var(--__P__-fg)}.__P__-home-avatar:first-child{margin-left:0}.__P__-home-avatar img{width:100%;height:100%;object-fit:cover}.__P__-home-content{background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-card);overflow:hidden}.__P__-home-content-title{padding:var(--__P__-space-4) var(--__P__-space-4) var(--__P__-space-3);font-size:var(--__P__-text-sm);font-weight:700}.__P__-home-content-list{display:flex;flex-direction:column;padding:0 var(--__P__-space-2) var(--__P__-space-2)}.__P__-home-content-list .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-home-card{display:block;width:100%;text-align:left;background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);padding:var(--__P__-space-4);box-shadow:var(--__P__-shadow-card)}.__P__-home-card[data-interactive=true]{cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-home-card[data-interactive=true]:hover{background:var(--__P__-bg-elevated)}.__P__-home-card[data-interactive=true]:active{transform:translateY(1px)}.__P__-home-card[data-interactive=true]:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-recent-row{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-recent-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;flex-shrink:0;border-radius:999px;background:color-mix(in oklch,var(--__P__-accent) 14%,transparent);color:var(--__P__-accent)}.__P__-home-recent-avatar svg{width:20px;height:20px}.__P__-home-recent-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.__P__-home-recent-title{font-weight:600;font-size:14px}.__P__-home-recent-preview{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-home-recent-at{color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);flex-shrink:0}.__P__-home-recent-dot{width:8px;height:8px;border-radius:999px;background:var(--__P__-accent);flex-shrink:0}.__P__-home-recent-row[data-unread=true] .__P__-home-recent-title{font-weight:700}.__P__-home-status{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-status-icon svg{width:22px;height:22px;color:var(--__P__-success)}.__P__-home-status[data-level=degraded] .__P__-home-status-icon svg{color:var(--__P__-warning)}.__P__-home-status[data-level=down] .__P__-home-status-icon svg{color:var(--__P__-danger)}.__P__-home-status-text{font-weight:600;font-size:14px}.__P__-home-search{display:flex;align-items:center;gap:var(--__P__-space-2);width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);border:1px solid var(--__P__-border);background:var(--__P__-surface);text-align:left}.__P__-home-search[data-input=true]{background:var(--__P__-bg-elevated)}.__P__-home-search:hover{border-color:var(--__P__-border-strong)}.__P__-home-search:focus-visible,.__P__-home-search:focus-within{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-search-text{flex:1;color:var(--__P__-fg-muted);font-size:14px}.__P__-home-search-input{flex:1;border:0;background:transparent;font-size:14px;color:var(--__P__-fg);outline:none}.__P__-home-search-icon svg{width:18px;height:18px;color:var(--__P__-accent)}.__P__-list-row{display:flex;align-items:center;gap:var(--__P__-space-3);width:100%;min-height:44px;text-align:left;padding:var(--__P__-space-3) var(--__P__-space-2);border-radius:var(--__P__-radius-sm)}.__P__-list-row:hover{background:var(--__P__-bg-elevated)}.__P__-list-row:active{background:var(--__P__-border)}.__P__-list-row:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-list-row-body{display:flex;flex-direction:column;min-width:0;flex:1}.__P__-list-row-title{font-weight:600;font-size:var(--__P__-text-md);line-height:1.35}.__P__-list-row-sub{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);margin-top:var(--__P__-space-1);line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-list-row-chevron svg{width:18px;height:18px;color:var(--__P__-accent);flex-shrink:0}.__P__-back-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);flex-shrink:0}.__P__-back-title{flex:1;text-align:center;font-size:var(--__P__-text-md);font-weight:700;margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-back-spacer{width:32px;height:1px}.__P__-content{display:flex;flex-direction:column;gap:14px;width:100%;max-width:68ch;margin:0 auto}.__P__-content-hero{width:100%;border-radius:var(--__P__-radius)}.__P__-content-subtitle{color:var(--__P__-fg-muted);margin:0}.__P__-content-frame{flex:1;min-height:0;width:100%;border:0;background:#fff}.__P__-news-list{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-news-card{display:block;width:100%;text-align:left;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden;background:var(--__P__-surface)}.__P__-news-card{transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-news-card:hover{background:var(--__P__-bg-elevated)}.__P__-news-card:active{transform:translateY(1px)}.__P__-news-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-news-hero{width:100%;display:block}.__P__-news-body{display:flex;flex-direction:column;gap:6px;padding:14px 16px}.__P__-news-tags{display:flex;gap:6px;flex-wrap:wrap}.__P__-news-tag{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);padding:2px 8px;border-radius:999px}.__P__-news-title{font-weight:700;font-size:var(--__P__-text-md)}.__P__-news-summary{color:var(--__P__-fg-muted);font-size:14px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-modules-empty{display:flex;align-items:center;justify-content:center;position:relative}.__P__-modules-empty-close{position:absolute;top:12px;right:12px}.__P__-modules-empty-text{color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-form{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-field{display:flex;flex-direction:column;gap:4px}.__P__-field-label{font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-field-req{color:var(--__P__-danger)}.__P__-field-input{width:100%;box-sizing:border-box;padding:var(--__P__-space-2) var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg);color:var(--__P__-fg);font:inherit;font-size:var(--__P__-text-sm);resize:vertical;transition:border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-field-input:focus-visible{outline:none;border-color:var(--__P__-accent)}.__P__-field[data-invalid=true] .__P__-field-input{border-color:var(--__P__-danger)}.__P__-field-hint{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-field-error{font-size:var(--__P__-text-xs);color:var(--__P__-danger)}.__P__-field-choices{display:flex;flex-direction:column;gap:6px}.__P__-choice{display:flex;align-items:flex-start;gap:8px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);cursor:pointer}.__P__-choice input{margin-top:2px;accent-color:var(--__P__-accent)}.__P__-form-actions{display:flex;justify-content:flex-end;gap:var(--__P__-space-2);margin-top:2px}.__P__-form-submit,.__P__-tool-approve{padding:var(--__P__-space-2) var(--__P__-space-4);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);cursor:pointer;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-submit:hover:not(:disabled),.__P__-tool-approve:hover:not(:disabled){filter:brightness(1.06)}.__P__-form-submit:disabled{opacity:.6;cursor:default}.__P__-form-skip,.__P__-tool-reject{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:transparent;color:var(--__P__-fg-muted);font:inherit;font-size:var(--__P__-text-sm);cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-skip:hover:not(:disabled),.__P__-tool-reject:hover:not(:disabled){background:var(--__P__-bg-elevated)}.__P__-intake{display:flex;flex-direction:column;gap:var(--__P__-space-2);padding:var(--__P__-space-3) var(--__P__-space-4) var(--__P__-space-4);border-top:1px solid var(--__P__-border);overflow-y:auto}.__P__-intake-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-intake-desc{margin:0 0 var(--__P__-space-1);font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-ask-input,.__P__-tool-approval{display:flex;flex-direction:column;gap:var(--__P__-space-2);margin-top:6px;padding:var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated)}.__P__-tool-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-badge{padding:2px 8px;border-radius:999px;background:var(--__P__-warning, #f59e0b);color:#1a1206;font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-title{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}.__P__-tool-question{margin:0;font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-tool-desc{margin:0;font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-args{margin:0;padding:var(--__P__-space-2);max-height:160px;overflow:auto;border-radius:var(--__P__-radius-sm);background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);white-space:pre-wrap;word-break:break-word}.__P__-tool-stale-note{margin:0;font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-tool-decided{flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-decided-label{padding:2px 8px;border-radius:999px;background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-decided-label[data-approved=true]{color:var(--__P__-success, #16a34a);border-color:var(--__P__-success, #16a34a)}.__P__-tool-decided-label[data-approved=false]{color:var(--__P__-danger);border-color:var(--__P__-danger)}.__P__-tool-decided-value{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}\n';
|
|
716
874
|
|
|
717
875
|
// src/styles/standalone.css
|
|
718
876
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -800,22 +958,22 @@ function attachAdoptedSheet(shadow, doc) {
|
|
|
800
958
|
}
|
|
801
959
|
}
|
|
802
960
|
function applyThemeOverrides(host, overrides) {
|
|
803
|
-
const
|
|
804
|
-
if (overrides.accent) host.style.setProperty(`--${
|
|
805
|
-
if (overrides.accentText) host.style.setProperty(`--${
|
|
806
|
-
if (overrides.radius) host.style.setProperty(`--${
|
|
807
|
-
if (overrides.fontFamily) host.style.setProperty(`--${
|
|
961
|
+
const p33 = BRAND.cssPrefix;
|
|
962
|
+
if (overrides.accent) host.style.setProperty(`--${p33}-accent`, overrides.accent);
|
|
963
|
+
if (overrides.accentText) host.style.setProperty(`--${p33}-accent-text`, overrides.accentText);
|
|
964
|
+
if (overrides.radius) host.style.setProperty(`--${p33}-radius`, overrides.radius);
|
|
965
|
+
if (overrides.fontFamily) host.style.setProperty(`--${p33}-font`, overrides.fontFamily);
|
|
808
966
|
}
|
|
809
967
|
function applyThemeMode(host, mode) {
|
|
810
968
|
host.dataset.theme = mode;
|
|
811
969
|
}
|
|
812
970
|
function applySize(host, size) {
|
|
813
|
-
const
|
|
814
|
-
if (size.width !== void 0) host.style.setProperty(`--${
|
|
815
|
-
if (size.height !== void 0) host.style.setProperty(`--${
|
|
816
|
-
if (size.expanded?.width !== void 0) host.style.setProperty(`--${
|
|
817
|
-
if (size.expanded?.height !== void 0) host.style.setProperty(`--${
|
|
818
|
-
if (size.inset !== void 0) host.style.setProperty(`--${
|
|
971
|
+
const p33 = BRAND.cssPrefix;
|
|
972
|
+
if (size.width !== void 0) host.style.setProperty(`--${p33}-panel-w`, size.width);
|
|
973
|
+
if (size.height !== void 0) host.style.setProperty(`--${p33}-panel-h`, size.height);
|
|
974
|
+
if (size.expanded?.width !== void 0) host.style.setProperty(`--${p33}-expanded-w`, size.expanded.width);
|
|
975
|
+
if (size.expanded?.height !== void 0) host.style.setProperty(`--${p33}-expanded-h`, size.expanded.height);
|
|
976
|
+
if (size.inset !== void 0) host.style.setProperty(`--${p33}-panel-inset`, size.inset);
|
|
819
977
|
}
|
|
820
978
|
function applyPosition(host, pos) {
|
|
821
979
|
host.dataset.position = pos;
|
|
@@ -986,11 +1144,11 @@ function toBase64Url(json) {
|
|
|
986
1144
|
var nonEmpty = (ctx) => ctx && Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
987
1145
|
function encodeContext(user, page) {
|
|
988
1146
|
const u = nonEmpty(user);
|
|
989
|
-
const
|
|
990
|
-
if (!u && !
|
|
1147
|
+
const p33 = nonEmpty(page);
|
|
1148
|
+
if (!u && !p33) return void 0;
|
|
991
1149
|
const envelope = {};
|
|
992
1150
|
if (u) envelope.user = u;
|
|
993
|
-
if (
|
|
1151
|
+
if (p33) envelope.page = p33;
|
|
994
1152
|
return toBase64Url(JSON.stringify(envelope));
|
|
995
1153
|
}
|
|
996
1154
|
|
|
@@ -1029,7 +1187,15 @@ var DEFAULT_PATHS = {
|
|
|
1029
1187
|
markRead: "/ai/agent/mark-read",
|
|
1030
1188
|
// ── CMS content (unified — Home / Help / News / docs) ─────────────
|
|
1031
1189
|
/** All widget content via one filtered endpoint. `GET /ai/agent/content?tags=…`. */
|
|
1032
|
-
content: "/ai/agent/content"
|
|
1190
|
+
content: "/ai/agent/content",
|
|
1191
|
+
/**
|
|
1192
|
+
* Optional pre-chat intake submission. POST `{ visitorId, sessionId, values,
|
|
1193
|
+
* skipped? }` → record the lead immediately (before/independent of the first
|
|
1194
|
+
* message), keyed by the same visitor + session as the conversation.
|
|
1195
|
+
* Overridable via `endpoints.intake`. Fire-and-forget; 404 on older backends
|
|
1196
|
+
* is ignored.
|
|
1197
|
+
*/
|
|
1198
|
+
intake: "/ai/agent/intake"
|
|
1033
1199
|
};
|
|
1034
1200
|
var CONTEXT_PARAM = "context";
|
|
1035
1201
|
function buildSendMessageRequest(params) {
|
|
@@ -1053,18 +1219,34 @@ function buildSendMessageRequest(params) {
|
|
|
1053
1219
|
if (Object.keys(data).length > 0) body.data = data;
|
|
1054
1220
|
return body;
|
|
1055
1221
|
}
|
|
1222
|
+
function isResolvedToolPart(p33) {
|
|
1223
|
+
return p33.state === "output" || p33.state === "error" || p33.approval?.approved !== void 0;
|
|
1224
|
+
}
|
|
1056
1225
|
function normalizeToolRef(ref) {
|
|
1057
1226
|
if (typeof ref === "string") return ref ? { code: ref } : null;
|
|
1058
1227
|
return ref?.code ? ref : null;
|
|
1059
1228
|
}
|
|
1060
1229
|
function messageToWireParts(m) {
|
|
1061
1230
|
const out = [];
|
|
1062
|
-
for (const
|
|
1063
|
-
if (
|
|
1064
|
-
out.push({ text:
|
|
1231
|
+
for (const p33 of m.parts) {
|
|
1232
|
+
if (p33.kind === "text" && p33.text) {
|
|
1233
|
+
out.push({ text: p33.text, type: "text" });
|
|
1065
1234
|
}
|
|
1066
|
-
if (
|
|
1067
|
-
out.push({ mediaType:
|
|
1235
|
+
if (p33.kind === "file" && p33.url) {
|
|
1236
|
+
out.push({ mediaType: p33.mediaType, type: "file", url: p33.url });
|
|
1237
|
+
}
|
|
1238
|
+
if (p33.kind === "tool" && isResolvedToolPart(p33)) {
|
|
1239
|
+
const part = {
|
|
1240
|
+
type: "tool",
|
|
1241
|
+
toolCallId: p33.toolCallId,
|
|
1242
|
+
toolName: p33.toolName,
|
|
1243
|
+
state: p33.state
|
|
1244
|
+
};
|
|
1245
|
+
if (p33.input !== void 0) part.input = p33.input;
|
|
1246
|
+
if (p33.output !== void 0) part.output = p33.output;
|
|
1247
|
+
if (p33.error !== void 0) part.errorText = p33.error;
|
|
1248
|
+
if (p33.approval && p33.approval.approved !== void 0) part.approval = p33.approval;
|
|
1249
|
+
out.push(part);
|
|
1068
1250
|
}
|
|
1069
1251
|
}
|
|
1070
1252
|
for (const a of m.attachments ?? []) {
|
|
@@ -1311,6 +1493,25 @@ var AgentTransport = class {
|
|
|
1311
1493
|
get transcribePath() {
|
|
1312
1494
|
return this.opts.endpoints?.transcribe ?? "/ai/agent/transcribe-audio";
|
|
1313
1495
|
}
|
|
1496
|
+
get intakePath() {
|
|
1497
|
+
return this.opts.endpoints?.intake ?? DEFAULT_PATHS.intake;
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Record a completed pre-chat intake form. Fire-and-forget — the lead is
|
|
1501
|
+
* captured even if the visitor never sends a message. `sessionId` is explicit
|
|
1502
|
+
* so the record ties to the conversation that follows; `visitorId` + context
|
|
1503
|
+
* ride the envelope. A failure (e.g. 404 on a backend that doesn't implement
|
|
1504
|
+
* the endpoint) is non-fatal — the values still reach the agent as
|
|
1505
|
+
* `userContext` on the next message, so callers don't await this.
|
|
1506
|
+
*/
|
|
1507
|
+
async submitIntake(sessionId, values, skipped = false) {
|
|
1508
|
+
log4.debug("submitIntake \u2192", { sessionId, fields: Object.keys(values).length, skipped });
|
|
1509
|
+
try {
|
|
1510
|
+
await this.postJson(this.intakePath, { sessionId, values, skipped }, "submitIntake");
|
|
1511
|
+
} catch (err) {
|
|
1512
|
+
log4.debug("submitIntake failed (non-fatal)", { err });
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1314
1515
|
sendMessage(body) {
|
|
1315
1516
|
log4.debug("message \u2192", {
|
|
1316
1517
|
sessionId: body.sessionId,
|
|
@@ -1624,8 +1825,21 @@ function fromWireMessage(w) {
|
|
|
1624
1825
|
if (part.type === "file") {
|
|
1625
1826
|
return { kind: "file", url: part.url, mediaType: part.mediaType };
|
|
1626
1827
|
}
|
|
1828
|
+
if (part.type === "tool") {
|
|
1829
|
+
return {
|
|
1830
|
+
kind: "tool",
|
|
1831
|
+
toolCallId: part.toolCallId,
|
|
1832
|
+
toolName: part.toolName,
|
|
1833
|
+
inputPartialSig: signal(""),
|
|
1834
|
+
inputSig: signal(part.input),
|
|
1835
|
+
outputSig: signal(part.output),
|
|
1836
|
+
errorSig: signal(part.errorText),
|
|
1837
|
+
stateSig: signal(part.state),
|
|
1838
|
+
approvalSig: signal(part.approval)
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1627
1841
|
return null;
|
|
1628
|
-
}).filter((
|
|
1842
|
+
}).filter((p33) => p33 !== null);
|
|
1629
1843
|
return {
|
|
1630
1844
|
id: w.id,
|
|
1631
1845
|
role: w.role,
|
|
@@ -1655,45 +1869,62 @@ function assistantText(m) {
|
|
|
1655
1869
|
}
|
|
1656
1870
|
return out;
|
|
1657
1871
|
}
|
|
1658
|
-
function partToReactive(
|
|
1659
|
-
if (
|
|
1660
|
-
return { kind:
|
|
1872
|
+
function partToReactive(p33) {
|
|
1873
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1874
|
+
return { kind: p33.kind, id: p33.id, textSig: signal(p33.text), doneSig: signal(p33.done) };
|
|
1661
1875
|
}
|
|
1662
|
-
if (
|
|
1876
|
+
if (p33.kind === "tool") {
|
|
1663
1877
|
return {
|
|
1664
1878
|
kind: "tool",
|
|
1665
|
-
toolCallId:
|
|
1666
|
-
toolName:
|
|
1667
|
-
inputPartialSig: signal(
|
|
1668
|
-
inputSig: signal(
|
|
1669
|
-
outputSig: signal(
|
|
1670
|
-
errorSig: signal(
|
|
1671
|
-
stateSig: signal(
|
|
1879
|
+
toolCallId: p33.toolCallId,
|
|
1880
|
+
toolName: p33.toolName,
|
|
1881
|
+
inputPartialSig: signal(p33.inputPartial),
|
|
1882
|
+
inputSig: signal(p33.input),
|
|
1883
|
+
outputSig: signal(p33.output),
|
|
1884
|
+
errorSig: signal(p33.error),
|
|
1885
|
+
stateSig: signal(p33.state),
|
|
1886
|
+
approvalSig: signal(p33.approval)
|
|
1672
1887
|
};
|
|
1673
1888
|
}
|
|
1674
|
-
return
|
|
1889
|
+
return p33;
|
|
1675
1890
|
}
|
|
1676
|
-
function partFromReactive(
|
|
1677
|
-
if (
|
|
1678
|
-
return { kind:
|
|
1891
|
+
function partFromReactive(p33) {
|
|
1892
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1893
|
+
return { kind: p33.kind, id: p33.id, text: p33.textSig.value, done: p33.doneSig.value };
|
|
1679
1894
|
}
|
|
1680
|
-
if (
|
|
1895
|
+
if (p33.kind === "tool") {
|
|
1681
1896
|
return {
|
|
1682
1897
|
kind: "tool",
|
|
1683
|
-
toolCallId:
|
|
1684
|
-
toolName:
|
|
1685
|
-
inputPartial:
|
|
1686
|
-
input:
|
|
1687
|
-
output:
|
|
1688
|
-
error:
|
|
1689
|
-
state:
|
|
1898
|
+
toolCallId: p33.toolCallId,
|
|
1899
|
+
toolName: p33.toolName,
|
|
1900
|
+
inputPartial: p33.inputPartialSig.value,
|
|
1901
|
+
input: p33.inputSig.value,
|
|
1902
|
+
output: p33.outputSig.value,
|
|
1903
|
+
error: p33.errorSig.value,
|
|
1904
|
+
state: p33.stateSig.value,
|
|
1905
|
+
approval: p33.approvalSig.value
|
|
1690
1906
|
};
|
|
1691
1907
|
}
|
|
1692
|
-
return
|
|
1908
|
+
return p33;
|
|
1693
1909
|
}
|
|
1694
1910
|
|
|
1695
1911
|
// src/stream/reducer.ts
|
|
1696
1912
|
import { signal as signal2 } from "@preact/signals";
|
|
1913
|
+
|
|
1914
|
+
// src/stream/constants.ts
|
|
1915
|
+
var ASK_USER_INPUT_TOOL = "tool:ask-user-input";
|
|
1916
|
+
function isAskUserInputTool(toolName) {
|
|
1917
|
+
if (!toolName) return false;
|
|
1918
|
+
const t = toolName.toLowerCase();
|
|
1919
|
+
return t === ASK_USER_INPUT_TOOL || t === "ask-user-input" || t === "ask_user_input";
|
|
1920
|
+
}
|
|
1921
|
+
var TRIGGER = {
|
|
1922
|
+
submitMessage: "submit-message",
|
|
1923
|
+
toolResult: "tool-result",
|
|
1924
|
+
toolApproval: "tool-approval"
|
|
1925
|
+
};
|
|
1926
|
+
|
|
1927
|
+
// src/stream/reducer.ts
|
|
1697
1928
|
var log5 = logger.scope("reducer");
|
|
1698
1929
|
var StreamReducer = class {
|
|
1699
1930
|
constructor(messagesSig) {
|
|
@@ -1731,8 +1962,8 @@ var StreamReducer = class {
|
|
|
1731
1962
|
ensureTextPart(m, "text", chunk.id);
|
|
1732
1963
|
return;
|
|
1733
1964
|
case "text-delta": {
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1965
|
+
const p33 = ensureTextPart(m, "text", chunk.id);
|
|
1966
|
+
p33.textSig.value += chunk.delta;
|
|
1736
1967
|
return;
|
|
1737
1968
|
}
|
|
1738
1969
|
case "text-end":
|
|
@@ -1742,8 +1973,8 @@ var StreamReducer = class {
|
|
|
1742
1973
|
ensureTextPart(m, "reasoning", chunk.id).doneSig.value = false;
|
|
1743
1974
|
return;
|
|
1744
1975
|
case "reasoning-delta": {
|
|
1745
|
-
const
|
|
1746
|
-
|
|
1976
|
+
const p33 = ensureTextPart(m, "reasoning", chunk.id);
|
|
1977
|
+
p33.textSig.value += chunk.delta;
|
|
1747
1978
|
return;
|
|
1748
1979
|
}
|
|
1749
1980
|
case "reasoning-end":
|
|
@@ -1754,6 +1985,7 @@ var StreamReducer = class {
|
|
|
1754
1985
|
case "tool-input-available":
|
|
1755
1986
|
case "tool-output-available":
|
|
1756
1987
|
case "tool-output-error":
|
|
1988
|
+
case "tool-approval-request":
|
|
1757
1989
|
applyTool(m, chunk);
|
|
1758
1990
|
return;
|
|
1759
1991
|
case "file":
|
|
@@ -1761,7 +1993,7 @@ var StreamReducer = class {
|
|
|
1761
1993
|
return;
|
|
1762
1994
|
case "source-url": {
|
|
1763
1995
|
const parts = m.partsSig.value;
|
|
1764
|
-
if (parts.some((
|
|
1996
|
+
if (parts.some((p33) => p33.kind === "source" && p33.sourceId === chunk.sourceId)) return;
|
|
1765
1997
|
appendPart(m, { kind: "source", sourceId: chunk.sourceId, url: chunk.url, title: chunk.title });
|
|
1766
1998
|
return;
|
|
1767
1999
|
}
|
|
@@ -1785,14 +2017,14 @@ var StreamReducer = class {
|
|
|
1785
2017
|
}
|
|
1786
2018
|
};
|
|
1787
2019
|
function ensureTextPart(m, kind, id) {
|
|
1788
|
-
const existing = m.partsSig.value.find((
|
|
2020
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === kind && p33.id === id);
|
|
1789
2021
|
if (existing) return existing;
|
|
1790
2022
|
const part = { kind, id, textSig: signal2(""), doneSig: signal2(false) };
|
|
1791
2023
|
appendPart(m, part);
|
|
1792
2024
|
return part;
|
|
1793
2025
|
}
|
|
1794
2026
|
function ensureToolPart(m, toolCallId, toolName) {
|
|
1795
|
-
const existing = m.partsSig.value.find((
|
|
2027
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === "tool" && p33.toolCallId === toolCallId);
|
|
1796
2028
|
if (existing) return existing;
|
|
1797
2029
|
const part = {
|
|
1798
2030
|
kind: "tool",
|
|
@@ -1802,7 +2034,8 @@ function ensureToolPart(m, toolCallId, toolName) {
|
|
|
1802
2034
|
inputSig: signal2(void 0),
|
|
1803
2035
|
outputSig: signal2(void 0),
|
|
1804
2036
|
errorSig: signal2(void 0),
|
|
1805
|
-
stateSig: signal2("input")
|
|
2037
|
+
stateSig: signal2("input"),
|
|
2038
|
+
approvalSig: signal2(void 0)
|
|
1806
2039
|
};
|
|
1807
2040
|
appendPart(m, part);
|
|
1808
2041
|
return part;
|
|
@@ -1816,26 +2049,32 @@ function applyTool(m, chunk) {
|
|
|
1816
2049
|
ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
1817
2050
|
return;
|
|
1818
2051
|
case "tool-input-delta": {
|
|
1819
|
-
const
|
|
1820
|
-
|
|
2052
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2053
|
+
p33.inputPartialSig.value += chunk.delta;
|
|
1821
2054
|
return;
|
|
1822
2055
|
}
|
|
1823
2056
|
case "tool-input-available": {
|
|
1824
|
-
const
|
|
1825
|
-
|
|
1826
|
-
|
|
2057
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2058
|
+
p33.inputSig.value = chunk.input;
|
|
2059
|
+
p33.stateSig.value = isAskUserInputTool(p33.toolName) ? "awaiting-input" : "awaiting";
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
case "tool-approval-request": {
|
|
2063
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2064
|
+
p33.approvalSig.value = { id: chunk.approvalId };
|
|
2065
|
+
p33.stateSig.value = "awaiting-approval";
|
|
1827
2066
|
return;
|
|
1828
2067
|
}
|
|
1829
2068
|
case "tool-output-available": {
|
|
1830
|
-
const
|
|
1831
|
-
|
|
1832
|
-
|
|
2069
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2070
|
+
p33.outputSig.value = chunk.output;
|
|
2071
|
+
p33.stateSig.value = "output";
|
|
1833
2072
|
return;
|
|
1834
2073
|
}
|
|
1835
2074
|
case "tool-output-error": {
|
|
1836
|
-
const
|
|
1837
|
-
|
|
1838
|
-
|
|
2075
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2076
|
+
p33.errorSig.value = chunk.errorText;
|
|
2077
|
+
p33.stateSig.value = "error";
|
|
1839
2078
|
return;
|
|
1840
2079
|
}
|
|
1841
2080
|
default:
|
|
@@ -1855,6 +2094,7 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
1855
2094
|
const KEY_CALLOUT_DISMISSED = `${prefix}.calloutDismissed`;
|
|
1856
2095
|
const KEY_SIDEBAR_COLLAPSED = `${prefix}.sidebarCollapsed`;
|
|
1857
2096
|
const KEY_ACTIVE_MODULE = `${prefix}.activeModule`;
|
|
2097
|
+
const KEY_INTAKE = `${prefix}.intake`;
|
|
1858
2098
|
const persistence = {
|
|
1859
2099
|
getVisitorId() {
|
|
1860
2100
|
const existing = storage.get(KEY_VISITOR);
|
|
@@ -1937,6 +2177,24 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
1937
2177
|
saveActiveModule(id) {
|
|
1938
2178
|
storage.set(KEY_ACTIVE_MODULE, id);
|
|
1939
2179
|
},
|
|
2180
|
+
loadIntake() {
|
|
2181
|
+
const raw = storage.get(KEY_INTAKE);
|
|
2182
|
+
if (!raw) return null;
|
|
2183
|
+
try {
|
|
2184
|
+
const parsed = JSON.parse(raw);
|
|
2185
|
+
return isPlainObject2(parsed) ? parsed : null;
|
|
2186
|
+
} catch (error) {
|
|
2187
|
+
log6.warn("loadIntake parse failed", { error });
|
|
2188
|
+
return null;
|
|
2189
|
+
}
|
|
2190
|
+
},
|
|
2191
|
+
saveIntake(values) {
|
|
2192
|
+
try {
|
|
2193
|
+
storage.set(KEY_INTAKE, JSON.stringify(values));
|
|
2194
|
+
} catch (error) {
|
|
2195
|
+
log6.warn("saveIntake serialise failed", { error });
|
|
2196
|
+
}
|
|
2197
|
+
},
|
|
1940
2198
|
clearSession() {
|
|
1941
2199
|
storage.remove(KEY_CHAT);
|
|
1942
2200
|
}
|
|
@@ -2478,7 +2736,30 @@ var TID = {
|
|
|
2478
2736
|
/** Help article row — suffix `-{id}`. */
|
|
2479
2737
|
helpArticle: `${p2}-help-article`,
|
|
2480
2738
|
/** News list item — suffix `-{id}`. */
|
|
2481
|
-
newsItem: `${p2}-news-item
|
|
2739
|
+
newsItem: `${p2}-news-item`,
|
|
2740
|
+
// ── Forms + human-in-the-loop (intake / ask-input / approval) ────
|
|
2741
|
+
/** Pre-chat intake form root (blocking gate). */
|
|
2742
|
+
intakeForm: `${p2}-intake-form`,
|
|
2743
|
+
/** Intake submit button. */
|
|
2744
|
+
intakeSubmit: `${p2}-intake-submit`,
|
|
2745
|
+
/** Intake skip button (only when `skippable`). */
|
|
2746
|
+
intakeSkip: `${p2}-intake-skip`,
|
|
2747
|
+
/** A single form field control — suffix `-{name}` at the JSX site. */
|
|
2748
|
+
formField: `${p2}-form-field`,
|
|
2749
|
+
/** Ask-input tool root (inline form in a message bubble). */
|
|
2750
|
+
toolAskInput: `${p2}-tool-ask-input`,
|
|
2751
|
+
/** Ask-input submit button. */
|
|
2752
|
+
toolInputSubmit: `${p2}-tool-input-submit`,
|
|
2753
|
+
/** Ask-input skip button. */
|
|
2754
|
+
toolInputSkip: `${p2}-tool-input-skip`,
|
|
2755
|
+
/** Tool-approval root (approve/reject prompt). */
|
|
2756
|
+
toolApproval: `${p2}-tool-approval`,
|
|
2757
|
+
/** Tool-approval approve button. */
|
|
2758
|
+
toolApprove: `${p2}-tool-approve`,
|
|
2759
|
+
/** Tool-approval reject button. */
|
|
2760
|
+
toolReject: `${p2}-tool-reject`,
|
|
2761
|
+
/** Recorded tool decision summary (after approve/reject/submit). */
|
|
2762
|
+
toolDecision: `${p2}-tool-decision`
|
|
2482
2763
|
};
|
|
2483
2764
|
function tid(base, suffix) {
|
|
2484
2765
|
return `${base}-${suffix}`;
|
|
@@ -2589,24 +2870,24 @@ import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef
|
|
|
2589
2870
|
import { useEffect as useEffect2, useRef } from "preact/hooks";
|
|
2590
2871
|
import { jsx as jsx3 } from "preact/jsx-runtime";
|
|
2591
2872
|
function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, strings }) {
|
|
2592
|
-
const
|
|
2873
|
+
const p33 = BRAND.cssPrefix;
|
|
2593
2874
|
const dragRef = useRef(null);
|
|
2594
2875
|
useEffect2(() => {
|
|
2595
2876
|
if (!panelEl) return;
|
|
2596
2877
|
const style = panelEl.style;
|
|
2597
|
-
if (resize.minWidth) style.setProperty(`--${
|
|
2598
|
-
if (resize.maxWidth) style.setProperty(`--${
|
|
2599
|
-
if (resize.minHeight) style.setProperty(`--${
|
|
2600
|
-
if (resize.maxHeight) style.setProperty(`--${
|
|
2878
|
+
if (resize.minWidth) style.setProperty(`--${p33}-resize-min-w`, resize.minWidth);
|
|
2879
|
+
if (resize.maxWidth) style.setProperty(`--${p33}-resize-max-w`, resize.maxWidth);
|
|
2880
|
+
if (resize.minHeight) style.setProperty(`--${p33}-resize-min-h`, resize.minHeight);
|
|
2881
|
+
if (resize.maxHeight) style.setProperty(`--${p33}-resize-max-h`, resize.maxHeight);
|
|
2601
2882
|
if (initialSize) {
|
|
2602
|
-
style.setProperty(`--${
|
|
2603
|
-
style.setProperty(`--${
|
|
2883
|
+
style.setProperty(`--${p33}-widget-w`, `${initialSize.width}px`);
|
|
2884
|
+
style.setProperty(`--${p33}-widget-h`, `${initialSize.height}px`);
|
|
2604
2885
|
}
|
|
2605
|
-
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight,
|
|
2886
|
+
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight, p33, initialSize]);
|
|
2606
2887
|
if (!panelEl) return null;
|
|
2607
2888
|
const isTop = position.startsWith("top-");
|
|
2608
2889
|
const isRight = position.endsWith("-right");
|
|
2609
|
-
const cornerClass = `${
|
|
2890
|
+
const cornerClass = `${p33}-resize-grip ${p33}-resize-grip--${isTop ? "bottom" : "top"}-${isRight ? "left" : "right"}`;
|
|
2610
2891
|
const onPointerDown = (e) => {
|
|
2611
2892
|
if (!panelEl) return;
|
|
2612
2893
|
const target = e.currentTarget;
|
|
@@ -2630,8 +2911,8 @@ function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, stri
|
|
|
2630
2911
|
if (!d || e.pointerId !== d.pointerId || !panelEl) return;
|
|
2631
2912
|
const dx = (e.clientX - d.startX) * d.dirX;
|
|
2632
2913
|
const dy = (e.clientY - d.startY) * d.dirY;
|
|
2633
|
-
panelEl.style.setProperty(`--${
|
|
2634
|
-
panelEl.style.setProperty(`--${
|
|
2914
|
+
panelEl.style.setProperty(`--${p33}-widget-w`, `${d.startW + dx}px`);
|
|
2915
|
+
panelEl.style.setProperty(`--${p33}-widget-h`, `${d.startH + dy}px`);
|
|
2635
2916
|
};
|
|
2636
2917
|
const onPointerUp = (e) => {
|
|
2637
2918
|
const d = dragRef.current;
|
|
@@ -2668,7 +2949,7 @@ var KEEP_VISIBLE = 56;
|
|
|
2668
2949
|
function useDragMove(panelEl, enabled) {
|
|
2669
2950
|
useEffect3(() => {
|
|
2670
2951
|
if (!enabled || !panelEl) return;
|
|
2671
|
-
const
|
|
2952
|
+
const num2 = (v) => Number.parseFloat(v) || 0;
|
|
2672
2953
|
const clamp = (v, max) => Math.min(max, Math.max(-max, v));
|
|
2673
2954
|
let drag = null;
|
|
2674
2955
|
const onDown = (e) => {
|
|
@@ -2679,8 +2960,8 @@ function useDragMove(panelEl, enabled) {
|
|
|
2679
2960
|
id: e.pointerId,
|
|
2680
2961
|
x: e.clientX,
|
|
2681
2962
|
y: e.clientY,
|
|
2682
|
-
dx:
|
|
2683
|
-
dy:
|
|
2963
|
+
dx: num2(panelEl.style.getPropertyValue(`--${p4}-modal-dx`)),
|
|
2964
|
+
dy: num2(panelEl.style.getPropertyValue(`--${p4}-modal-dy`)),
|
|
2684
2965
|
// Centred origin: |offset| ≤ (viewport + panel)/2 − keepVisible keeps a
|
|
2685
2966
|
// strip of the dialog reachable so it can never be lost off-screen.
|
|
2686
2967
|
maxX: (window.innerWidth + rect.width) / 2 - KEEP_VISIBLE,
|
|
@@ -3366,20 +3647,20 @@ function usePopoverMenu({ itemCount, initialFocusIndex }) {
|
|
|
3366
3647
|
// src/ui/overflow-menu.tsx
|
|
3367
3648
|
import { jsx as jsx8, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
3368
3649
|
function OverflowMenu({ items, triggerLabel }) {
|
|
3369
|
-
const
|
|
3650
|
+
const p33 = BRAND.cssPrefix;
|
|
3370
3651
|
const menu = usePopoverMenu({ itemCount: items.length });
|
|
3371
3652
|
const handleSelect = (item) => {
|
|
3372
3653
|
if (item.disabled) return;
|
|
3373
3654
|
item.onSelect();
|
|
3374
3655
|
if (!item.keepOpen) menu.close();
|
|
3375
3656
|
};
|
|
3376
|
-
return /* @__PURE__ */ jsxs6("div", { class: `${
|
|
3657
|
+
return /* @__PURE__ */ jsxs6("div", { class: `${p33}-menu-wrap`, children: [
|
|
3377
3658
|
/* @__PURE__ */ jsx8(
|
|
3378
3659
|
"button",
|
|
3379
3660
|
{
|
|
3380
3661
|
ref: menu.triggerRef,
|
|
3381
3662
|
type: "button",
|
|
3382
|
-
class: `${
|
|
3663
|
+
class: `${p33}-icon-btn`,
|
|
3383
3664
|
"aria-label": triggerLabel,
|
|
3384
3665
|
"aria-haspopup": "menu",
|
|
3385
3666
|
"aria-expanded": menu.open,
|
|
@@ -3393,7 +3674,7 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3393
3674
|
"div",
|
|
3394
3675
|
{
|
|
3395
3676
|
ref: menu.menuRef,
|
|
3396
|
-
class: `${
|
|
3677
|
+
class: `${p33}-menu`,
|
|
3397
3678
|
role: "menu",
|
|
3398
3679
|
"aria-label": triggerLabel,
|
|
3399
3680
|
onKeyDown: menu.onMenuKey,
|
|
@@ -3403,15 +3684,15 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3403
3684
|
{
|
|
3404
3685
|
type: "button",
|
|
3405
3686
|
role: "menuitem",
|
|
3406
|
-
class: `${
|
|
3687
|
+
class: `${p33}-menu-item`,
|
|
3407
3688
|
"aria-pressed": item.type === "switch" ? item.on : void 0,
|
|
3408
3689
|
disabled: item.disabled,
|
|
3409
3690
|
lang: item.lang,
|
|
3410
3691
|
onClick: () => handleSelect(item),
|
|
3411
3692
|
children: [
|
|
3412
|
-
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3413
|
-
/* @__PURE__ */ jsx8("span", { class: `${
|
|
3414
|
-
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3693
|
+
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-icon`, children: item.icon }) : null,
|
|
3694
|
+
/* @__PURE__ */ jsx8("span", { class: `${p33}-menu-label`, children: item.label }),
|
|
3695
|
+
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-check`, "aria-hidden": "true", children: /* @__PURE__ */ jsx8(CheckIcon, {}) }) : null
|
|
3415
3696
|
]
|
|
3416
3697
|
},
|
|
3417
3698
|
item.id
|
|
@@ -3533,18 +3814,360 @@ function HeaderActions({ panelProps, variant }) {
|
|
|
3533
3814
|
] });
|
|
3534
3815
|
}
|
|
3535
3816
|
|
|
3817
|
+
// src/ui/form/dynamic-form.tsx
|
|
3818
|
+
import { useState as useState5 } from "preact/hooks";
|
|
3819
|
+
|
|
3820
|
+
// src/ui/form/validate.ts
|
|
3821
|
+
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3822
|
+
var URL_RE = /^https?:\/\/[^\s.]+\.[^\s]+$/i;
|
|
3823
|
+
var TEL_RE = /^[+]?[\d\s().-]{6,}$/;
|
|
3824
|
+
function fmt(template, vars) {
|
|
3825
|
+
return template.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? `{${k}}`));
|
|
3826
|
+
}
|
|
3827
|
+
function selectionCount(value) {
|
|
3828
|
+
if (Array.isArray(value)) return value.length;
|
|
3829
|
+
return value && value.trim() ? 1 : 0;
|
|
3830
|
+
}
|
|
3831
|
+
function validateField(field, value, strings) {
|
|
3832
|
+
const required = field.required ?? true;
|
|
3833
|
+
const v = field.validation;
|
|
3834
|
+
if (field.type === "multiselect") {
|
|
3835
|
+
const count = selectionCount(value);
|
|
3836
|
+
if (required && count === 0) return strings.formRequired;
|
|
3837
|
+
if (count === 0) return void 0;
|
|
3838
|
+
if (v?.minSelections != null && count < v.minSelections) {
|
|
3839
|
+
return fmt(strings.formChooseAtLeast, { min: v.minSelections });
|
|
3840
|
+
}
|
|
3841
|
+
if (v?.maxSelections != null && count > v.maxSelections) {
|
|
3842
|
+
return fmt(strings.formChooseAtMost, { max: v.maxSelections });
|
|
3843
|
+
}
|
|
3844
|
+
return void 0;
|
|
3845
|
+
}
|
|
3846
|
+
const text = typeof value === "string" ? value.trim() : "";
|
|
3847
|
+
if (!text) return required ? strings.formRequired : void 0;
|
|
3848
|
+
switch (field.type) {
|
|
3849
|
+
case "email":
|
|
3850
|
+
if (!EMAIL_RE2.test(text)) return strings.formInvalidEmail;
|
|
3851
|
+
break;
|
|
3852
|
+
case "url":
|
|
3853
|
+
if (!URL_RE.test(text)) return strings.formInvalidUrl;
|
|
3854
|
+
break;
|
|
3855
|
+
case "tel":
|
|
3856
|
+
if (!TEL_RE.test(text)) return strings.formInvalidTel;
|
|
3857
|
+
break;
|
|
3858
|
+
case "number": {
|
|
3859
|
+
const n = Number(text);
|
|
3860
|
+
if (!Number.isFinite(n)) return strings.formInvalidNumber;
|
|
3861
|
+
if (v?.min != null && n < v.min) return fmt(strings.formNumberTooSmall, { min: v.min });
|
|
3862
|
+
if (v?.max != null && n > v.max) return fmt(strings.formNumberTooLarge, { max: v.max });
|
|
3863
|
+
break;
|
|
3864
|
+
}
|
|
3865
|
+
default:
|
|
3866
|
+
break;
|
|
3867
|
+
}
|
|
3868
|
+
if (v?.minLength != null && text.length < v.minLength) return fmt(strings.formTooShort, { min: v.minLength });
|
|
3869
|
+
if (v?.maxLength != null && text.length > v.maxLength) return fmt(strings.formTooLong, { max: v.maxLength });
|
|
3870
|
+
if (v?.pattern) {
|
|
3871
|
+
try {
|
|
3872
|
+
if (!new RegExp(v.pattern).test(text)) return strings.formPatternMismatch;
|
|
3873
|
+
} catch {
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
return void 0;
|
|
3877
|
+
}
|
|
3878
|
+
function validateForm(fields, values, strings) {
|
|
3879
|
+
const errors = {};
|
|
3880
|
+
for (const field of fields) {
|
|
3881
|
+
const err = validateField(field, values[field.name], strings);
|
|
3882
|
+
if (err) errors[field.name] = err;
|
|
3883
|
+
}
|
|
3884
|
+
return errors;
|
|
3885
|
+
}
|
|
3886
|
+
function flattenValues(values) {
|
|
3887
|
+
const out = {};
|
|
3888
|
+
for (const [k, v] of Object.entries(values)) {
|
|
3889
|
+
const flat = Array.isArray(v) ? v.join(", ") : v;
|
|
3890
|
+
if (flat && flat.trim()) out[k] = flat.trim();
|
|
3891
|
+
}
|
|
3892
|
+
return out;
|
|
3893
|
+
}
|
|
3894
|
+
|
|
3895
|
+
// src/ui/form/dynamic-form.tsx
|
|
3896
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
3897
|
+
var p10 = BRAND.cssPrefix;
|
|
3898
|
+
var OTHER = "__other__";
|
|
3899
|
+
function DynamicForm({
|
|
3900
|
+
fields,
|
|
3901
|
+
strings,
|
|
3902
|
+
submitLabel,
|
|
3903
|
+
onSubmit,
|
|
3904
|
+
skipLabel,
|
|
3905
|
+
onSkip,
|
|
3906
|
+
disabled,
|
|
3907
|
+
rootTestId,
|
|
3908
|
+
submitTestId,
|
|
3909
|
+
skipTestId
|
|
3910
|
+
}) {
|
|
3911
|
+
const [values, setValues] = useState5(() => seedValues(fields));
|
|
3912
|
+
const [other, setOther] = useState5({});
|
|
3913
|
+
const [errors, setErrors] = useState5({});
|
|
3914
|
+
const clearError = (name) => {
|
|
3915
|
+
if (errors[name]) setErrors((prev) => ({ ...prev, [name]: "" }));
|
|
3916
|
+
};
|
|
3917
|
+
const setValue = (name, v) => {
|
|
3918
|
+
setValues((prev) => ({ ...prev, [name]: v }));
|
|
3919
|
+
clearError(name);
|
|
3920
|
+
};
|
|
3921
|
+
const setOtherText = (name, t) => {
|
|
3922
|
+
setOther((prev) => ({ ...prev, [name]: t }));
|
|
3923
|
+
clearError(name);
|
|
3924
|
+
};
|
|
3925
|
+
const submit = (e) => {
|
|
3926
|
+
e.preventDefault();
|
|
3927
|
+
if (disabled) return;
|
|
3928
|
+
const resolved = resolveValues(fields, values, other);
|
|
3929
|
+
const errs = validateForm(fields, resolved, strings);
|
|
3930
|
+
if (Object.keys(errs).length > 0) {
|
|
3931
|
+
setErrors(errs);
|
|
3932
|
+
return;
|
|
3933
|
+
}
|
|
3934
|
+
onSubmit(flattenValues(resolved));
|
|
3935
|
+
};
|
|
3936
|
+
return /* @__PURE__ */ jsxs8("form", { class: `${p10}-form`, onSubmit: submit, "data-testid": rootTestId, noValidate: true, children: [
|
|
3937
|
+
fields.map((field) => /* @__PURE__ */ jsx10(
|
|
3938
|
+
Field,
|
|
3939
|
+
{
|
|
3940
|
+
field,
|
|
3941
|
+
value: values[field.name],
|
|
3942
|
+
otherText: other[field.name] ?? "",
|
|
3943
|
+
error: errors[field.name],
|
|
3944
|
+
disabled,
|
|
3945
|
+
strings,
|
|
3946
|
+
onChange: (v) => setValue(field.name, v),
|
|
3947
|
+
onOtherChange: (t) => setOtherText(field.name, t)
|
|
3948
|
+
},
|
|
3949
|
+
field.name
|
|
3950
|
+
)),
|
|
3951
|
+
/* @__PURE__ */ jsxs8("div", { class: `${p10}-form-actions`, children: [
|
|
3952
|
+
skipLabel && onSkip ? /* @__PURE__ */ jsx10("button", { type: "button", class: `${p10}-form-skip`, onClick: onSkip, disabled, "data-testid": skipTestId, children: skipLabel }) : null,
|
|
3953
|
+
/* @__PURE__ */ jsx10("button", { type: "submit", class: `${p10}-form-submit`, disabled, "data-testid": submitTestId, children: submitLabel })
|
|
3954
|
+
] })
|
|
3955
|
+
] });
|
|
3956
|
+
}
|
|
3957
|
+
function Field({
|
|
3958
|
+
field,
|
|
3959
|
+
value,
|
|
3960
|
+
otherText,
|
|
3961
|
+
error,
|
|
3962
|
+
disabled,
|
|
3963
|
+
strings,
|
|
3964
|
+
onChange,
|
|
3965
|
+
onOtherChange
|
|
3966
|
+
}) {
|
|
3967
|
+
const fieldTid = tid(TID.formField, field.name);
|
|
3968
|
+
const control = renderControl({ field, value, otherText, disabled, strings, onChange, onOtherChange, fieldTid });
|
|
3969
|
+
return /* @__PURE__ */ jsxs8("label", { class: `${p10}-field`, "data-field": field.name, "data-invalid": error ? "true" : void 0, children: [
|
|
3970
|
+
/* @__PURE__ */ jsxs8("span", { class: `${p10}-field-label`, children: [
|
|
3971
|
+
field.label,
|
|
3972
|
+
field.required ?? true ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-req`, "aria-hidden": "true", children: " *" }) : null
|
|
3973
|
+
] }),
|
|
3974
|
+
control,
|
|
3975
|
+
field.validationHint && !error ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-hint`, children: field.validationHint }) : null,
|
|
3976
|
+
error ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-error`, role: "alert", children: error }) : null
|
|
3977
|
+
] });
|
|
3978
|
+
}
|
|
3979
|
+
function renderControl(args) {
|
|
3980
|
+
const { field, value, otherText, disabled, strings, onChange, onOtherChange, fieldTid } = args;
|
|
3981
|
+
const str2 = typeof value === "string" ? value : "";
|
|
3982
|
+
switch (field.type) {
|
|
3983
|
+
case "textarea":
|
|
3984
|
+
return /* @__PURE__ */ jsx10(
|
|
3985
|
+
"textarea",
|
|
3986
|
+
{
|
|
3987
|
+
class: `${p10}-field-input`,
|
|
3988
|
+
rows: 3,
|
|
3989
|
+
value: str2,
|
|
3990
|
+
placeholder: field.placeholder,
|
|
3991
|
+
disabled,
|
|
3992
|
+
onInput: (e) => onChange(e.target.value),
|
|
3993
|
+
"data-testid": fieldTid
|
|
3994
|
+
}
|
|
3995
|
+
);
|
|
3996
|
+
case "select":
|
|
3997
|
+
return /* @__PURE__ */ jsxs8(
|
|
3998
|
+
"select",
|
|
3999
|
+
{
|
|
4000
|
+
class: `${p10}-field-input`,
|
|
4001
|
+
value: str2,
|
|
4002
|
+
disabled,
|
|
4003
|
+
onChange: (e) => onChange(e.target.value),
|
|
4004
|
+
"data-testid": fieldTid,
|
|
4005
|
+
children: [
|
|
4006
|
+
/* @__PURE__ */ jsx10("option", { value: "", children: field.placeholder ?? "\u2014" }),
|
|
4007
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsx10("option", { value: o.value, children: o.label ?? o.value }, o.value))
|
|
4008
|
+
]
|
|
4009
|
+
}
|
|
4010
|
+
);
|
|
4011
|
+
case "radio": {
|
|
4012
|
+
const isOther = field.allowOther && str2 === OTHER;
|
|
4013
|
+
return /* @__PURE__ */ jsxs8("div", { class: `${p10}-field-choices`, role: "radiogroup", "data-testid": fieldTid, children: [
|
|
4014
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4015
|
+
/* @__PURE__ */ jsx10(
|
|
4016
|
+
"input",
|
|
4017
|
+
{
|
|
4018
|
+
type: "radio",
|
|
4019
|
+
name: `${p10}-${field.name}`,
|
|
4020
|
+
checked: str2 === o.value,
|
|
4021
|
+
disabled,
|
|
4022
|
+
onChange: () => onChange(o.value)
|
|
4023
|
+
}
|
|
4024
|
+
),
|
|
4025
|
+
/* @__PURE__ */ jsx10("span", { children: o.label ?? o.value })
|
|
4026
|
+
] }, o.value)),
|
|
4027
|
+
field.allowOther ? /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4028
|
+
/* @__PURE__ */ jsx10(
|
|
4029
|
+
"input",
|
|
4030
|
+
{
|
|
4031
|
+
type: "radio",
|
|
4032
|
+
name: `${p10}-${field.name}`,
|
|
4033
|
+
checked: str2 === OTHER,
|
|
4034
|
+
disabled,
|
|
4035
|
+
onChange: () => onChange(OTHER)
|
|
4036
|
+
}
|
|
4037
|
+
),
|
|
4038
|
+
/* @__PURE__ */ jsx10("span", { children: strings.formOther })
|
|
4039
|
+
] }) : null,
|
|
4040
|
+
isOther ? /* @__PURE__ */ jsx10(
|
|
4041
|
+
"input",
|
|
4042
|
+
{
|
|
4043
|
+
class: `${p10}-field-input`,
|
|
4044
|
+
value: otherText,
|
|
4045
|
+
placeholder: field.placeholder ?? strings.formOtherPlaceholder,
|
|
4046
|
+
disabled,
|
|
4047
|
+
onInput: (e) => onOtherChange(e.target.value)
|
|
4048
|
+
}
|
|
4049
|
+
) : null
|
|
4050
|
+
] });
|
|
4051
|
+
}
|
|
4052
|
+
case "checkbox":
|
|
4053
|
+
return /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4054
|
+
/* @__PURE__ */ jsx10(
|
|
4055
|
+
"input",
|
|
4056
|
+
{
|
|
4057
|
+
type: "checkbox",
|
|
4058
|
+
checked: str2 === "true",
|
|
4059
|
+
disabled,
|
|
4060
|
+
onChange: (e) => onChange(e.target.checked ? "true" : ""),
|
|
4061
|
+
"data-testid": fieldTid
|
|
4062
|
+
}
|
|
4063
|
+
),
|
|
4064
|
+
/* @__PURE__ */ jsx10("span", { children: field.placeholder ?? field.label })
|
|
4065
|
+
] });
|
|
4066
|
+
case "multiselect": {
|
|
4067
|
+
const selected = Array.isArray(value) ? value : [];
|
|
4068
|
+
const toggle = (v, on) => onChange(on ? [...selected, v] : selected.filter((x) => x !== v));
|
|
4069
|
+
return /* @__PURE__ */ jsxs8("div", { class: `${p10}-field-choices`, "data-testid": fieldTid, children: [
|
|
4070
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4071
|
+
/* @__PURE__ */ jsx10(
|
|
4072
|
+
"input",
|
|
4073
|
+
{
|
|
4074
|
+
type: "checkbox",
|
|
4075
|
+
checked: selected.includes(o.value),
|
|
4076
|
+
disabled,
|
|
4077
|
+
onChange: (e) => toggle(o.value, e.target.checked)
|
|
4078
|
+
}
|
|
4079
|
+
),
|
|
4080
|
+
/* @__PURE__ */ jsx10("span", { children: o.label ?? o.value })
|
|
4081
|
+
] }, o.value)),
|
|
4082
|
+
field.allowOther || (field.options ?? []).length === 0 ? /* @__PURE__ */ jsx10(
|
|
4083
|
+
"textarea",
|
|
4084
|
+
{
|
|
4085
|
+
class: `${p10}-field-input`,
|
|
4086
|
+
rows: 2,
|
|
4087
|
+
value: otherText,
|
|
4088
|
+
placeholder: field.placeholder ?? strings.formOtherPlaceholder,
|
|
4089
|
+
disabled,
|
|
4090
|
+
onInput: (e) => onOtherChange(e.target.value)
|
|
4091
|
+
}
|
|
4092
|
+
) : null
|
|
4093
|
+
] });
|
|
4094
|
+
}
|
|
4095
|
+
default:
|
|
4096
|
+
return /* @__PURE__ */ jsx10(
|
|
4097
|
+
"input",
|
|
4098
|
+
{
|
|
4099
|
+
class: `${p10}-field-input`,
|
|
4100
|
+
type: inputType(field.type),
|
|
4101
|
+
value: str2,
|
|
4102
|
+
placeholder: field.placeholder,
|
|
4103
|
+
disabled,
|
|
4104
|
+
onInput: (e) => onChange(e.target.value),
|
|
4105
|
+
"data-testid": fieldTid
|
|
4106
|
+
}
|
|
4107
|
+
);
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
function inputType(type) {
|
|
4111
|
+
return type === "number" || type === "email" || type === "tel" || type === "url" ? type : "text";
|
|
4112
|
+
}
|
|
4113
|
+
function seedValues(fields) {
|
|
4114
|
+
const out = {};
|
|
4115
|
+
for (const f of fields) {
|
|
4116
|
+
if (f.defaultValue == null) continue;
|
|
4117
|
+
out[f.name] = f.type === "multiselect" ? f.defaultValue.split(",").map((s) => s.trim()).filter(Boolean) : f.defaultValue;
|
|
4118
|
+
}
|
|
4119
|
+
return out;
|
|
4120
|
+
}
|
|
4121
|
+
function resolveValues(fields, values, other) {
|
|
4122
|
+
const out = { ...values };
|
|
4123
|
+
for (const f of fields) {
|
|
4124
|
+
const otherText = other[f.name]?.trim();
|
|
4125
|
+
if (f.type === "radio" && f.allowOther && values[f.name] === OTHER) {
|
|
4126
|
+
out[f.name] = otherText ?? "";
|
|
4127
|
+
} else if (f.type === "multiselect" && otherText) {
|
|
4128
|
+
const tokens = otherText.split(/[,\n;]+/).map((t) => t.trim()).filter(Boolean);
|
|
4129
|
+
const base = Array.isArray(values[f.name]) ? values[f.name] : [];
|
|
4130
|
+
out[f.name] = [...base, ...tokens];
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
return out;
|
|
4134
|
+
}
|
|
4135
|
+
|
|
4136
|
+
// src/ui/intake-gate.tsx
|
|
4137
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
4138
|
+
var p11 = BRAND.cssPrefix;
|
|
4139
|
+
function IntakeGate({ intake, strings, onComplete }) {
|
|
4140
|
+
return /* @__PURE__ */ jsxs9("div", { class: `${p11}-intake`, "data-testid": TID.intakeForm, children: [
|
|
4141
|
+
intake.title ? /* @__PURE__ */ jsx11("h3", { class: `${p11}-intake-title`, children: intake.title }) : null,
|
|
4142
|
+
intake.description ? /* @__PURE__ */ jsx11("p", { class: `${p11}-intake-desc`, children: intake.description }) : null,
|
|
4143
|
+
/* @__PURE__ */ jsx11(
|
|
4144
|
+
DynamicForm,
|
|
4145
|
+
{
|
|
4146
|
+
fields: intake.fields,
|
|
4147
|
+
strings,
|
|
4148
|
+
submitLabel: intake.submitLabel ?? strings.intakeSubmit,
|
|
4149
|
+
onSubmit: onComplete,
|
|
4150
|
+
skipLabel: intake.skippable ? strings.intakeSkip : void 0,
|
|
4151
|
+
onSkip: intake.skippable ? () => onComplete({}) : void 0,
|
|
4152
|
+
submitTestId: TID.intakeSubmit,
|
|
4153
|
+
skipTestId: TID.intakeSkip
|
|
4154
|
+
}
|
|
4155
|
+
)
|
|
4156
|
+
] });
|
|
4157
|
+
}
|
|
4158
|
+
|
|
3536
4159
|
// src/ui/message-list.tsx
|
|
3537
|
-
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as
|
|
3538
|
-
import { useComputed as
|
|
4160
|
+
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as useState6 } from "preact/hooks";
|
|
4161
|
+
import { useComputed as useComputed5 } from "@preact/signals";
|
|
3539
4162
|
|
|
3540
4163
|
// src/ui/message-bubble.tsx
|
|
3541
|
-
import { useComputed as
|
|
4164
|
+
import { useComputed as useComputed4 } from "@preact/signals";
|
|
3542
4165
|
|
|
3543
4166
|
// src/ui/markdown.tsx
|
|
3544
4167
|
import { useEffect as useEffect7, useMemo, useRef as useRef4 } from "preact/hooks";
|
|
3545
4168
|
import { effect, signal as signal4 } from "@preact/signals";
|
|
3546
4169
|
import * as smd from "streaming-markdown";
|
|
3547
|
-
import { jsx as
|
|
4170
|
+
import { jsx as jsx12 } from "preact/jsx-runtime";
|
|
3548
4171
|
function MarkdownView({ textSig, doneSig }) {
|
|
3549
4172
|
const ref = useRef4(null);
|
|
3550
4173
|
useEffect7(() => {
|
|
@@ -3594,12 +4217,12 @@ function MarkdownView({ textSig, doneSig }) {
|
|
|
3594
4217
|
el.removeEventListener("click", onClick);
|
|
3595
4218
|
};
|
|
3596
4219
|
}, [textSig, doneSig]);
|
|
3597
|
-
return /* @__PURE__ */
|
|
4220
|
+
return /* @__PURE__ */ jsx12("div", { ref });
|
|
3598
4221
|
}
|
|
3599
4222
|
function StaticMarkdown({ text }) {
|
|
3600
4223
|
const textSig = useMemo(() => signal4(text), [text]);
|
|
3601
4224
|
const doneSig = useMemo(() => signal4(true), []);
|
|
3602
|
-
return /* @__PURE__ */
|
|
4225
|
+
return /* @__PURE__ */ jsx12(MarkdownView, { textSig, doneSig });
|
|
3603
4226
|
}
|
|
3604
4227
|
function hardenLink(a) {
|
|
3605
4228
|
const href = a.getAttribute("href") ?? "";
|
|
@@ -3611,29 +4234,247 @@ function hardenLink(a) {
|
|
|
3611
4234
|
a.rel = [...tokens].join(" ");
|
|
3612
4235
|
}
|
|
3613
4236
|
|
|
4237
|
+
// src/ui/tool-approval.tsx
|
|
4238
|
+
import { useComputed as useComputed2, useSignal } from "@preact/signals";
|
|
4239
|
+
import { Fragment, jsx as jsx13, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4240
|
+
var p12 = BRAND.cssPrefix;
|
|
4241
|
+
function ToolApproval({ part, strings, active, onDecision }) {
|
|
4242
|
+
const approval = useComputed2(() => part.approvalSig.value);
|
|
4243
|
+
const input = useComputed2(() => part.inputSig.value);
|
|
4244
|
+
const reason = useSignal("");
|
|
4245
|
+
const decided = approval.value?.approved !== void 0;
|
|
4246
|
+
if (decided) {
|
|
4247
|
+
const ap = approval.value;
|
|
4248
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval ${p12}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4249
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-label`, "data-approved": ap?.approved ? "true" : "false", children: ap?.approved ? strings.approved : strings.rejected }),
|
|
4250
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName }),
|
|
4251
|
+
ap?.reason ? /* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-value`, children: ap.reason }) : null
|
|
4252
|
+
] });
|
|
4253
|
+
}
|
|
4254
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval`, "data-testid": TID.toolApproval, children: [
|
|
4255
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-head`, children: [
|
|
4256
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-badge`, children: strings.approvalRequired }),
|
|
4257
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName })
|
|
4258
|
+
] }),
|
|
4259
|
+
summarizeInput(input.value) ? /* @__PURE__ */ jsx13("pre", { class: `${p12}-tool-args`, children: summarizeInput(input.value) }) : null,
|
|
4260
|
+
active ? /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
4261
|
+
/* @__PURE__ */ jsx13(
|
|
4262
|
+
"input",
|
|
4263
|
+
{
|
|
4264
|
+
class: `${p12}-field-input`,
|
|
4265
|
+
value: reason.value,
|
|
4266
|
+
placeholder: strings.approvalReason,
|
|
4267
|
+
onInput: (e) => {
|
|
4268
|
+
reason.value = e.target.value;
|
|
4269
|
+
}
|
|
4270
|
+
}
|
|
4271
|
+
),
|
|
4272
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-actions`, children: [
|
|
4273
|
+
/* @__PURE__ */ jsx13(
|
|
4274
|
+
"button",
|
|
4275
|
+
{
|
|
4276
|
+
type: "button",
|
|
4277
|
+
class: `${p12}-tool-reject`,
|
|
4278
|
+
onClick: () => onDecision(part.toolCallId, false, reason.value.trim() || void 0),
|
|
4279
|
+
"data-testid": TID.toolReject,
|
|
4280
|
+
children: strings.reject
|
|
4281
|
+
}
|
|
4282
|
+
),
|
|
4283
|
+
/* @__PURE__ */ jsx13(
|
|
4284
|
+
"button",
|
|
4285
|
+
{
|
|
4286
|
+
type: "button",
|
|
4287
|
+
class: `${p12}-tool-approve`,
|
|
4288
|
+
onClick: () => onDecision(part.toolCallId, true, reason.value.trim() || void 0),
|
|
4289
|
+
"data-testid": TID.toolApprove,
|
|
4290
|
+
children: strings.approve
|
|
4291
|
+
}
|
|
4292
|
+
)
|
|
4293
|
+
] })
|
|
4294
|
+
] }) : /* @__PURE__ */ jsx13("p", { class: `${p12}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4295
|
+
] });
|
|
4296
|
+
}
|
|
4297
|
+
function summarizeInput(input) {
|
|
4298
|
+
if (input == null) return "";
|
|
4299
|
+
try {
|
|
4300
|
+
const json = typeof input === "string" ? input : JSON.stringify(input, null, 2);
|
|
4301
|
+
return json.length > 600 ? `${json.slice(0, 600)}\u2026` : json;
|
|
4302
|
+
} catch {
|
|
4303
|
+
return "";
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
// src/ui/tool-ask-input.tsx
|
|
4308
|
+
import { useComputed as useComputed3 } from "@preact/signals";
|
|
4309
|
+
|
|
4310
|
+
// src/ui/form/field.ts
|
|
4311
|
+
function parseAskUserInput(input) {
|
|
4312
|
+
const raw = input && typeof input === "object" ? input : {};
|
|
4313
|
+
const responseType = raw.responseType;
|
|
4314
|
+
return {
|
|
4315
|
+
title: str(raw.title),
|
|
4316
|
+
question: str(raw.question) ?? "Please provide the missing information.",
|
|
4317
|
+
description: str(raw.description),
|
|
4318
|
+
placeholder: str(raw.placeholder),
|
|
4319
|
+
responseType: responseType === "single-choice" || responseType === "multi-choice" || responseType === "confirmation" || responseType === "free-text" ? responseType : "free-text",
|
|
4320
|
+
choices: Array.isArray(raw.choices) ? raw.choices : void 0,
|
|
4321
|
+
allowOther: typeof raw.allowOther === "boolean" ? raw.allowOther : void 0,
|
|
4322
|
+
required: typeof raw.required === "boolean" ? raw.required : true,
|
|
4323
|
+
defaultValues: Array.isArray(raw.defaultValues) ? raw.defaultValues.filter((v) => typeof v === "string") : void 0,
|
|
4324
|
+
minSelections: num(raw.minSelections),
|
|
4325
|
+
maxSelections: num(raw.maxSelections),
|
|
4326
|
+
validationHint: str(raw.validationHint)
|
|
4327
|
+
};
|
|
4328
|
+
}
|
|
4329
|
+
function askInputToFields(req) {
|
|
4330
|
+
if (req.responseType === "confirmation") return [];
|
|
4331
|
+
const options = (req.choices ?? []).map(normalizeChoice).filter((c) => c !== null);
|
|
4332
|
+
let type = "textarea";
|
|
4333
|
+
if (req.responseType === "single-choice" && options.length > 0) type = "radio";
|
|
4334
|
+
else if (req.responseType === "multi-choice") type = "multiselect";
|
|
4335
|
+
const defaultValue = type === "multiselect" ? req.defaultValues?.join(", ") : req.defaultValues?.[0];
|
|
4336
|
+
return [
|
|
4337
|
+
{
|
|
4338
|
+
name: "answer",
|
|
4339
|
+
label: req.question,
|
|
4340
|
+
type,
|
|
4341
|
+
placeholder: req.placeholder,
|
|
4342
|
+
required: req.required ?? true,
|
|
4343
|
+
defaultValue,
|
|
4344
|
+
options: options.length > 0 ? options : void 0,
|
|
4345
|
+
allowOther: req.allowOther,
|
|
4346
|
+
validationHint: req.validationHint,
|
|
4347
|
+
validation: type === "multiselect" ? { minSelections: req.minSelections, maxSelections: req.maxSelections } : void 0
|
|
4348
|
+
}
|
|
4349
|
+
];
|
|
4350
|
+
}
|
|
4351
|
+
function normalizeChoice(c) {
|
|
4352
|
+
if (typeof c === "string") return c ? { value: c, label: c } : null;
|
|
4353
|
+
if (c && typeof c.value === "string" && c.value)
|
|
4354
|
+
return { value: c.value, label: c.label ?? c.value, description: c.description };
|
|
4355
|
+
return null;
|
|
4356
|
+
}
|
|
4357
|
+
function str(v) {
|
|
4358
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
4359
|
+
}
|
|
4360
|
+
function num(v) {
|
|
4361
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
// src/ui/tool-ask-input.tsx
|
|
4365
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
4366
|
+
var p13 = BRAND.cssPrefix;
|
|
4367
|
+
function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
4368
|
+
const state = useComputed3(() => part.stateSig.value);
|
|
4369
|
+
const request = useComputed3(() => parseAskUserInput(part.inputSig.value));
|
|
4370
|
+
const decided = state.value === "output" || state.value === "error";
|
|
4371
|
+
if (decided) {
|
|
4372
|
+
return /* @__PURE__ */ jsx14(DecidedSummary, { part, strings });
|
|
4373
|
+
}
|
|
4374
|
+
if (!active) {
|
|
4375
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-stale`, "data-testid": TID.toolAskInput, children: [
|
|
4376
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: request.value.title ?? request.value.question }),
|
|
4377
|
+
/* @__PURE__ */ jsx14("p", { class: `${p13}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4378
|
+
] });
|
|
4379
|
+
}
|
|
4380
|
+
const req = request.value;
|
|
4381
|
+
const fields = askInputToFields(req);
|
|
4382
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input`, "data-testid": TID.toolAskInput, children: [
|
|
4383
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: req.title }),
|
|
4384
|
+
req.description ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-desc`, children: req.description }) : null,
|
|
4385
|
+
req.responseType === "confirmation" ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-question`, children: req.question }) : null,
|
|
4386
|
+
req.responseType === "confirmation" ? /* @__PURE__ */ jsxs11("div", { class: `${p13}-form-actions`, children: [
|
|
4387
|
+
/* @__PURE__ */ jsx14(
|
|
4388
|
+
"button",
|
|
4389
|
+
{
|
|
4390
|
+
type: "button",
|
|
4391
|
+
class: `${p13}-form-skip`,
|
|
4392
|
+
onClick: () => onSubmit(part.toolCallId, { confirmed: false }),
|
|
4393
|
+
"data-testid": TID.toolInputSkip,
|
|
4394
|
+
children: strings.reject
|
|
4395
|
+
}
|
|
4396
|
+
),
|
|
4397
|
+
/* @__PURE__ */ jsx14(
|
|
4398
|
+
"button",
|
|
4399
|
+
{
|
|
4400
|
+
type: "button",
|
|
4401
|
+
class: `${p13}-form-submit`,
|
|
4402
|
+
onClick: () => onSubmit(part.toolCallId, { confirmed: true }),
|
|
4403
|
+
"data-testid": TID.toolInputSubmit,
|
|
4404
|
+
children: strings.approve
|
|
4405
|
+
}
|
|
4406
|
+
)
|
|
4407
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
4408
|
+
DynamicForm,
|
|
4409
|
+
{
|
|
4410
|
+
fields,
|
|
4411
|
+
strings,
|
|
4412
|
+
submitLabel: strings.inputSubmit,
|
|
4413
|
+
onSubmit: (values) => onSubmit(part.toolCallId, values),
|
|
4414
|
+
skipLabel: req.required === false ? strings.inputSkip : void 0,
|
|
4415
|
+
onSkip: req.required === false ? () => onSubmit(part.toolCallId, {}) : void 0,
|
|
4416
|
+
submitTestId: TID.toolInputSubmit,
|
|
4417
|
+
skipTestId: TID.toolInputSkip
|
|
4418
|
+
}
|
|
4419
|
+
)
|
|
4420
|
+
] });
|
|
4421
|
+
}
|
|
4422
|
+
function Header({ strings, title }) {
|
|
4423
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-head`, children: [
|
|
4424
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-badge`, children: strings.inputRequired }),
|
|
4425
|
+
title ? /* @__PURE__ */ jsx14("strong", { class: `${p13}-tool-title`, children: title }) : null
|
|
4426
|
+
] });
|
|
4427
|
+
}
|
|
4428
|
+
function DecidedSummary({ part, strings }) {
|
|
4429
|
+
const output = useComputed3(() => part.outputSig.value);
|
|
4430
|
+
const text = summarizeOutput(output.value) || strings.inputSubmitted;
|
|
4431
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4432
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-label`, children: strings.inputSubmitted }),
|
|
4433
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-value`, children: text })
|
|
4434
|
+
] });
|
|
4435
|
+
}
|
|
4436
|
+
function summarizeOutput(output) {
|
|
4437
|
+
if (output == null) return "";
|
|
4438
|
+
if (typeof output === "string") return output;
|
|
4439
|
+
if (typeof output === "object") {
|
|
4440
|
+
const rec = output;
|
|
4441
|
+
if ("confirmed" in rec) return rec.confirmed ? "Yes" : "No";
|
|
4442
|
+
return Object.values(rec).filter((v) => typeof v === "string" || typeof v === "number").join(", ");
|
|
4443
|
+
}
|
|
4444
|
+
return String(output);
|
|
4445
|
+
}
|
|
4446
|
+
|
|
3614
4447
|
// src/ui/tool-chip.tsx
|
|
3615
|
-
import { jsx as
|
|
4448
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
3616
4449
|
function ToolChip({ part, strings }) {
|
|
3617
|
-
const
|
|
3618
|
-
return /* @__PURE__ */
|
|
3619
|
-
/* @__PURE__ */
|
|
4450
|
+
const p33 = BRAND.cssPrefix;
|
|
4451
|
+
return /* @__PURE__ */ jsxs12("span", { class: `${p33}-tool-chip`, role: "status", children: [
|
|
4452
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
3620
4453
|
strings.usedTool,
|
|
3621
4454
|
":"
|
|
3622
4455
|
] }),
|
|
3623
|
-
/* @__PURE__ */
|
|
4456
|
+
/* @__PURE__ */ jsx15("strong", { children: part.toolName })
|
|
3624
4457
|
] });
|
|
3625
4458
|
}
|
|
3626
4459
|
|
|
3627
4460
|
// src/ui/message-bubble.tsx
|
|
3628
|
-
import { jsx as
|
|
3629
|
-
var
|
|
3630
|
-
function MessageBubble({
|
|
3631
|
-
|
|
4461
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
|
|
4462
|
+
var p14 = BRAND.cssPrefix;
|
|
4463
|
+
function MessageBubble({
|
|
4464
|
+
message,
|
|
4465
|
+
strings,
|
|
4466
|
+
responseMode,
|
|
4467
|
+
showReasoning,
|
|
4468
|
+
showToolCalls,
|
|
4469
|
+
interactive = false,
|
|
4470
|
+
tool
|
|
4471
|
+
}) {
|
|
4472
|
+
const parts = useComputed4(() => message.partsSig.value);
|
|
3632
4473
|
const partList = parts.value;
|
|
3633
|
-
const hasAnswerText =
|
|
4474
|
+
const hasAnswerText = useComputed4(
|
|
3634
4475
|
() => message.partsSig.value.some((part) => part.kind === "text" && part.textSig.value.length > 0)
|
|
3635
4476
|
);
|
|
3636
|
-
const reasoningVisible =
|
|
4477
|
+
const reasoningVisible = useComputed4(
|
|
3637
4478
|
() => showReasoning && message.partsSig.value.some((part) => part.kind === "reasoning")
|
|
3638
4479
|
);
|
|
3639
4480
|
const streaming = message.role === "assistant" && message.status === "streaming";
|
|
@@ -3641,23 +4482,25 @@ function MessageBubble({ message, strings, responseMode, showReasoning, showTool
|
|
|
3641
4482
|
const working = streaming && !hasAnswerText.value;
|
|
3642
4483
|
const showStreamDots = streaming && !bufferedHold && !(reasoningVisible.value && working);
|
|
3643
4484
|
const stamp = formatStamp(message.createdAt);
|
|
3644
|
-
return /* @__PURE__ */
|
|
3645
|
-
/* @__PURE__ */
|
|
3646
|
-
bufferedHold ? /* @__PURE__ */
|
|
4485
|
+
return /* @__PURE__ */ jsx16("div", { class: `${p14}-bubble-row`, "data-role": message.role, "data-testid": tid(TID.messageBubble, message.id), children: /* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble-col`, children: [
|
|
4486
|
+
/* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble`, children: [
|
|
4487
|
+
bufferedHold ? /* @__PURE__ */ jsx16(LoadingSpinner, { label: strings.loading }) : partList.map((part) => /* @__PURE__ */ jsx16(
|
|
3647
4488
|
PartView,
|
|
3648
4489
|
{
|
|
3649
4490
|
part,
|
|
3650
4491
|
active: working,
|
|
3651
4492
|
strings,
|
|
3652
4493
|
showReasoning,
|
|
3653
|
-
showToolCalls
|
|
4494
|
+
showToolCalls,
|
|
4495
|
+
interactive,
|
|
4496
|
+
tool
|
|
3654
4497
|
},
|
|
3655
4498
|
partKey(part)
|
|
3656
4499
|
)),
|
|
3657
|
-
showStreamDots && /* @__PURE__ */
|
|
3658
|
-
message.status === "error" && message.errorText ? /* @__PURE__ */
|
|
4500
|
+
showStreamDots && /* @__PURE__ */ jsx16(TypingDots, {}),
|
|
4501
|
+
message.status === "error" && message.errorText ? /* @__PURE__ */ jsx16("div", { class: `${p14}-error`, role: "alert", children: /* @__PURE__ */ jsx16("span", { children: message.errorText }) }) : null
|
|
3659
4502
|
] }),
|
|
3660
|
-
stamp ? /* @__PURE__ */
|
|
4503
|
+
stamp ? /* @__PURE__ */ jsx16("time", { class: `${p14}-bubble-time`, dateTime: stamp.iso, title: stamp.full, children: stamp.short }) : null
|
|
3661
4504
|
] }) });
|
|
3662
4505
|
}
|
|
3663
4506
|
function formatStamp(createdAt) {
|
|
@@ -3678,32 +4521,62 @@ function PartView({
|
|
|
3678
4521
|
active,
|
|
3679
4522
|
strings,
|
|
3680
4523
|
showReasoning,
|
|
3681
|
-
showToolCalls
|
|
4524
|
+
showToolCalls,
|
|
4525
|
+
interactive,
|
|
4526
|
+
tool
|
|
3682
4527
|
}) {
|
|
3683
4528
|
switch (part.kind) {
|
|
3684
4529
|
case "text":
|
|
3685
|
-
return /* @__PURE__ */
|
|
4530
|
+
return /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig });
|
|
3686
4531
|
case "reasoning":
|
|
3687
|
-
return showReasoning ? /* @__PURE__ */
|
|
4532
|
+
return showReasoning ? /* @__PURE__ */ jsx16(ReasoningView, { part, active, strings }) : null;
|
|
3688
4533
|
case "tool":
|
|
3689
|
-
return
|
|
4534
|
+
return /* @__PURE__ */ jsx16(
|
|
4535
|
+
ToolPartView,
|
|
4536
|
+
{
|
|
4537
|
+
part,
|
|
4538
|
+
strings,
|
|
4539
|
+
showToolCalls,
|
|
4540
|
+
interactive,
|
|
4541
|
+
tool
|
|
4542
|
+
}
|
|
4543
|
+
);
|
|
3690
4544
|
case "file":
|
|
3691
4545
|
if (part.mediaType.startsWith("image/")) {
|
|
3692
|
-
return /* @__PURE__ */
|
|
4546
|
+
return /* @__PURE__ */ jsx16("img", { src: part.url, alt: "", loading: "lazy" });
|
|
3693
4547
|
}
|
|
3694
|
-
return /* @__PURE__ */
|
|
4548
|
+
return /* @__PURE__ */ jsx16("a", { href: part.url, target: "_blank", rel: "noreferrer noopener", children: part.url });
|
|
3695
4549
|
case "source":
|
|
3696
4550
|
return null;
|
|
3697
4551
|
}
|
|
3698
4552
|
}
|
|
4553
|
+
function ToolPartView({
|
|
4554
|
+
part,
|
|
4555
|
+
strings,
|
|
4556
|
+
showToolCalls,
|
|
4557
|
+
interactive,
|
|
4558
|
+
tool
|
|
4559
|
+
}) {
|
|
4560
|
+
const state = useComputed4(() => part.stateSig.value);
|
|
4561
|
+
const hasApproval = useComputed4(() => part.approvalSig.value !== void 0);
|
|
4562
|
+
if (tool?.humanInLoop) {
|
|
4563
|
+
if (hasApproval.value || state.value === "awaiting-approval") {
|
|
4564
|
+
return /* @__PURE__ */ jsx16(ToolApproval, { part, strings, active: interactive, onDecision: tool.onDecision });
|
|
4565
|
+
}
|
|
4566
|
+
if (isAskUserInputTool(part.toolName) || state.value === "awaiting-input") {
|
|
4567
|
+
return /* @__PURE__ */ jsx16(ToolAskInput, { part, strings, active: interactive, onSubmit: tool.onResult });
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
return showToolCalls ? /* @__PURE__ */ jsx16(ToolChip, { part, strings }) : null;
|
|
4571
|
+
}
|
|
3699
4572
|
function ReasoningView({
|
|
3700
4573
|
part,
|
|
3701
4574
|
active,
|
|
3702
4575
|
strings
|
|
3703
4576
|
}) {
|
|
3704
|
-
return /* @__PURE__ */
|
|
3705
|
-
/* @__PURE__ */
|
|
3706
|
-
/* @__PURE__ */
|
|
4577
|
+
return /* @__PURE__ */ jsxs13("details", { class: `${p14}-reasoning`, open: active, "data-active": active ? "true" : void 0, children: [
|
|
4578
|
+
/* @__PURE__ */ jsx16("summary", { class: `${p14}-reasoning-summary`, children: /* @__PURE__ */ jsx16("span", { class: `${p14}-reasoning-label`, children: active ? strings.thinking : strings.thoughts }) }),
|
|
4579
|
+
/* @__PURE__ */ jsx16("div", { class: `${p14}-reasoning-body`, children: /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig }) })
|
|
3707
4580
|
] });
|
|
3708
4581
|
}
|
|
3709
4582
|
function partKey(part) {
|
|
@@ -3720,29 +4593,38 @@ function partKey(part) {
|
|
|
3720
4593
|
}
|
|
3721
4594
|
}
|
|
3722
4595
|
function TypingDots() {
|
|
3723
|
-
return /* @__PURE__ */
|
|
3724
|
-
/* @__PURE__ */
|
|
3725
|
-
/* @__PURE__ */
|
|
3726
|
-
/* @__PURE__ */
|
|
4596
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-typing`, "aria-hidden": "true", children: [
|
|
4597
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4598
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4599
|
+
/* @__PURE__ */ jsx16("span", {})
|
|
3727
4600
|
] });
|
|
3728
4601
|
}
|
|
3729
4602
|
function LoadingSpinner({ label }) {
|
|
3730
|
-
return /* @__PURE__ */
|
|
3731
|
-
/* @__PURE__ */
|
|
3732
|
-
/* @__PURE__ */
|
|
4603
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-loading`, role: "status", children: [
|
|
4604
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-spinner`, "aria-hidden": "true" }),
|
|
4605
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-label`, children: label })
|
|
3733
4606
|
] });
|
|
3734
4607
|
}
|
|
3735
4608
|
|
|
3736
4609
|
// src/ui/message-list.tsx
|
|
3737
|
-
import { jsx as
|
|
3738
|
-
var
|
|
4610
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
4611
|
+
var p15 = BRAND.cssPrefix;
|
|
3739
4612
|
var STICK_THRESHOLD = 120;
|
|
3740
4613
|
var DIVIDER_IDLE_MS = 1200;
|
|
3741
|
-
function MessageList({
|
|
4614
|
+
function MessageList({
|
|
4615
|
+
messagesSig,
|
|
4616
|
+
strings,
|
|
4617
|
+
responseMode,
|
|
4618
|
+
showReasoning,
|
|
4619
|
+
showToolCalls,
|
|
4620
|
+
loading,
|
|
4621
|
+
idle,
|
|
4622
|
+
tool
|
|
4623
|
+
}) {
|
|
3742
4624
|
const ref = useRef5(null);
|
|
3743
|
-
const messages =
|
|
3744
|
-
const [showJump, setShowJump] =
|
|
3745
|
-
const [scrolling, setScrolling] =
|
|
4625
|
+
const messages = useComputed5(() => messagesSig.value);
|
|
4626
|
+
const [showJump, setShowJump] = useState6(false);
|
|
4627
|
+
const [scrolling, setScrolling] = useState6(false);
|
|
3746
4628
|
const hasHydratedRef = useRef5(false);
|
|
3747
4629
|
const firstMessageId = messages.value[0]?.id;
|
|
3748
4630
|
useLayoutEffect(() => {
|
|
@@ -3797,18 +4679,18 @@ function MessageList({ messagesSig, strings, responseMode, showReasoning, showTo
|
|
|
3797
4679
|
const el = ref.current;
|
|
3798
4680
|
if (!el) return;
|
|
3799
4681
|
const syncJump = () => setShowJump(el.scrollHeight - el.scrollTop - el.clientHeight > STICK_THRESHOLD * 2);
|
|
3800
|
-
let
|
|
4682
|
+
let idleTimer;
|
|
3801
4683
|
const onScroll = () => {
|
|
3802
4684
|
syncJump();
|
|
3803
4685
|
setScrolling(true);
|
|
3804
|
-
clearTimeout(
|
|
3805
|
-
|
|
4686
|
+
clearTimeout(idleTimer);
|
|
4687
|
+
idleTimer = setTimeout(() => setScrolling(false), DIVIDER_IDLE_MS);
|
|
3806
4688
|
};
|
|
3807
4689
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
3808
4690
|
syncJump();
|
|
3809
4691
|
return () => {
|
|
3810
4692
|
el.removeEventListener("scroll", onScroll);
|
|
3811
|
-
clearTimeout(
|
|
4693
|
+
clearTimeout(idleTimer);
|
|
3812
4694
|
};
|
|
3813
4695
|
}, []);
|
|
3814
4696
|
const jumpToBottom = () => {
|
|
@@ -3817,54 +4699,57 @@ function MessageList({ messagesSig, strings, responseMode, showReasoning, showTo
|
|
|
3817
4699
|
};
|
|
3818
4700
|
const rows = [];
|
|
3819
4701
|
let prevDay = "";
|
|
4702
|
+
const lastId = messages.value.at(-1)?.id;
|
|
3820
4703
|
for (const m of messages.value) {
|
|
3821
4704
|
const day = dayKey(m.createdAt);
|
|
3822
4705
|
if (day && day !== prevDay) {
|
|
3823
4706
|
rows.push(
|
|
3824
|
-
/* @__PURE__ */
|
|
4707
|
+
/* @__PURE__ */ jsx17("div", { class: `${p15}-date-divider`, children: /* @__PURE__ */ jsx17("span", { class: `${p15}-date-pill`, title: fullDate(m.createdAt), children: dayLabel(m.createdAt, strings) }) }, `day:${day}`)
|
|
3825
4708
|
);
|
|
3826
4709
|
prevDay = day;
|
|
3827
4710
|
}
|
|
3828
4711
|
rows.push(
|
|
3829
|
-
/* @__PURE__ */
|
|
4712
|
+
/* @__PURE__ */ jsx17(
|
|
3830
4713
|
MessageBubble,
|
|
3831
4714
|
{
|
|
3832
4715
|
message: m,
|
|
3833
4716
|
strings,
|
|
3834
4717
|
responseMode,
|
|
3835
4718
|
showReasoning,
|
|
3836
|
-
showToolCalls
|
|
4719
|
+
showToolCalls,
|
|
4720
|
+
interactive: Boolean(idle) && m.id === lastId,
|
|
4721
|
+
tool
|
|
3837
4722
|
},
|
|
3838
4723
|
m.id
|
|
3839
4724
|
)
|
|
3840
4725
|
);
|
|
3841
4726
|
}
|
|
3842
|
-
return /* @__PURE__ */
|
|
3843
|
-
/* @__PURE__ */
|
|
4727
|
+
return /* @__PURE__ */ jsxs14("div", { class: `${p15}-list-wrap`, children: [
|
|
4728
|
+
/* @__PURE__ */ jsxs14(
|
|
3844
4729
|
"div",
|
|
3845
4730
|
{
|
|
3846
4731
|
ref,
|
|
3847
|
-
class: `${
|
|
4732
|
+
class: `${p15}-list`,
|
|
3848
4733
|
role: "log",
|
|
3849
4734
|
"aria-live": "polite",
|
|
3850
4735
|
"aria-relevant": "additions text",
|
|
3851
4736
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
3852
4737
|
children: [
|
|
3853
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */
|
|
4738
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.messagesLoading }) : null,
|
|
3854
4739
|
rows
|
|
3855
4740
|
]
|
|
3856
4741
|
}
|
|
3857
4742
|
),
|
|
3858
|
-
showJump ? /* @__PURE__ */
|
|
4743
|
+
showJump ? /* @__PURE__ */ jsx17(
|
|
3859
4744
|
"button",
|
|
3860
4745
|
{
|
|
3861
4746
|
type: "button",
|
|
3862
|
-
class: `${
|
|
4747
|
+
class: `${p15}-jump`,
|
|
3863
4748
|
onClick: jumpToBottom,
|
|
3864
4749
|
"aria-label": strings.scrollToBottom,
|
|
3865
4750
|
title: strings.scrollToBottom,
|
|
3866
4751
|
"data-testid": TID.scrollToBottom,
|
|
3867
|
-
children: /* @__PURE__ */
|
|
4752
|
+
children: /* @__PURE__ */ jsx17(ChevronDownIcon, {})
|
|
3868
4753
|
}
|
|
3869
4754
|
) : null
|
|
3870
4755
|
] });
|
|
@@ -3893,7 +4778,7 @@ function dayLabel(createdAt, strings) {
|
|
|
3893
4778
|
}
|
|
3894
4779
|
|
|
3895
4780
|
// src/ui/conversation-list.tsx
|
|
3896
|
-
import { useEffect as useEffect9, useState as
|
|
4781
|
+
import { useEffect as useEffect9, useState as useState7 } from "preact/hooks";
|
|
3897
4782
|
|
|
3898
4783
|
// src/ui/history-groups.ts
|
|
3899
4784
|
var HISTORY_BUCKETS = ["today", "yesterday", "lastWeek", "older"];
|
|
@@ -3923,7 +4808,7 @@ function startOfDay(ms) {
|
|
|
3923
4808
|
}
|
|
3924
4809
|
|
|
3925
4810
|
// src/ui/conversation-list.tsx
|
|
3926
|
-
import { Fragment, jsx as
|
|
4811
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
3927
4812
|
var log11 = logger.scope("history");
|
|
3928
4813
|
var BUCKET_TO_STRING = {
|
|
3929
4814
|
today: "dateToday",
|
|
@@ -3932,9 +4817,9 @@ var BUCKET_TO_STRING = {
|
|
|
3932
4817
|
older: "dateOlder"
|
|
3933
4818
|
};
|
|
3934
4819
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
3935
|
-
const
|
|
3936
|
-
const [state, setState] =
|
|
3937
|
-
const [sessions, setChats] =
|
|
4820
|
+
const p33 = BRAND.cssPrefix;
|
|
4821
|
+
const [state, setState] = useState7("loading");
|
|
4822
|
+
const [sessions, setChats] = useState7([]);
|
|
3938
4823
|
useEffect9(() => {
|
|
3939
4824
|
let cancelled = false;
|
|
3940
4825
|
transport.listSessions({ visitorId }).then((res) => {
|
|
@@ -3950,38 +4835,38 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
3950
4835
|
cancelled = true;
|
|
3951
4836
|
};
|
|
3952
4837
|
}, [transport, visitorId]);
|
|
3953
|
-
const newChatButton = onNewChat ? /* @__PURE__ */
|
|
3954
|
-
/* @__PURE__ */
|
|
4838
|
+
const newChatButton = onNewChat ? /* @__PURE__ */ jsx18("div", { class: `${p33}-history-footer`, children: /* @__PURE__ */ jsxs15("button", { type: "button", class: `${p33}-history-new`, onClick: onNewChat, "data-testid": TID.sidebarNewChat, children: [
|
|
4839
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
3955
4840
|
strings.historyNewChat
|
|
3956
4841
|
] }) }) : null;
|
|
3957
4842
|
if (state === "loading") {
|
|
3958
|
-
return /* @__PURE__ */
|
|
3959
|
-
/* @__PURE__ */
|
|
4843
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4844
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
3960
4845
|
newChatButton
|
|
3961
4846
|
] });
|
|
3962
4847
|
}
|
|
3963
4848
|
if (state === "error" || sessions.length === 0) {
|
|
3964
|
-
return /* @__PURE__ */
|
|
3965
|
-
/* @__PURE__ */
|
|
4849
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4850
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
3966
4851
|
newChatButton
|
|
3967
4852
|
] });
|
|
3968
4853
|
}
|
|
3969
4854
|
const groups = groupByBucket(Date.now(), sessions);
|
|
3970
|
-
return /* @__PURE__ */
|
|
3971
|
-
/* @__PURE__ */
|
|
3972
|
-
/* @__PURE__ */
|
|
3973
|
-
group.sessions.map((chat) => /* @__PURE__ */
|
|
4855
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4856
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4857
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4858
|
+
group.sessions.map((chat) => /* @__PURE__ */ jsxs15(
|
|
3974
4859
|
"button",
|
|
3975
4860
|
{
|
|
3976
4861
|
type: "button",
|
|
3977
4862
|
role: "listitem",
|
|
3978
|
-
class: `${
|
|
4863
|
+
class: `${p33}-history-item`,
|
|
3979
4864
|
onClick: () => onSelect(chat),
|
|
3980
4865
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
3981
4866
|
"data-testid": tid(TID.historyItem, chat.sessionId),
|
|
3982
4867
|
children: [
|
|
3983
|
-
/* @__PURE__ */
|
|
3984
|
-
chat.preview ? /* @__PURE__ */
|
|
4868
|
+
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4869
|
+
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
3985
4870
|
]
|
|
3986
4871
|
},
|
|
3987
4872
|
chat.sessionId
|
|
@@ -3992,21 +4877,21 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
3992
4877
|
}
|
|
3993
4878
|
|
|
3994
4879
|
// src/ui/chat-history-pane.tsx
|
|
3995
|
-
import { jsx as
|
|
4880
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
3996
4881
|
function ChatHistoryPane(props2) {
|
|
3997
|
-
return /* @__PURE__ */
|
|
4882
|
+
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
3998
4883
|
}
|
|
3999
4884
|
|
|
4000
4885
|
// src/ui/suggestions.tsx
|
|
4001
|
-
import { jsx as
|
|
4002
|
-
var
|
|
4886
|
+
import { jsx as jsx20 } from "preact/jsx-runtime";
|
|
4887
|
+
var p16 = BRAND.cssPrefix;
|
|
4003
4888
|
function Suggestions({ suggestions, onPick }) {
|
|
4004
4889
|
if (suggestions.length === 0) return null;
|
|
4005
|
-
return /* @__PURE__ */
|
|
4890
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx20(
|
|
4006
4891
|
"button",
|
|
4007
4892
|
{
|
|
4008
4893
|
type: "button",
|
|
4009
|
-
class: `${
|
|
4894
|
+
class: `${p16}-suggestion`,
|
|
4010
4895
|
onClick: () => onPick(s),
|
|
4011
4896
|
"data-testid": tid(TID.suggestion, i),
|
|
4012
4897
|
children: s.label
|
|
@@ -4016,8 +4901,8 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
4016
4901
|
}
|
|
4017
4902
|
|
|
4018
4903
|
// src/ui/panel.tsx
|
|
4019
|
-
import { Fragment as
|
|
4020
|
-
var
|
|
4904
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
4905
|
+
var p17 = BRAND.cssPrefix;
|
|
4021
4906
|
function Panel(props2) {
|
|
4022
4907
|
const { options, onClose } = props2;
|
|
4023
4908
|
const s = options.strings;
|
|
@@ -4041,18 +4926,18 @@ function Panel(props2) {
|
|
|
4041
4926
|
}, []);
|
|
4042
4927
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
4043
4928
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
4044
|
-
return /* @__PURE__ */
|
|
4929
|
+
return /* @__PURE__ */ jsxs16(
|
|
4045
4930
|
"div",
|
|
4046
4931
|
{
|
|
4047
4932
|
ref: containerRef,
|
|
4048
|
-
class: `${
|
|
4933
|
+
class: `${p17}-panel`,
|
|
4049
4934
|
role: "dialog",
|
|
4050
4935
|
"aria-modal": "false",
|
|
4051
4936
|
"aria-label": s.panelTitle,
|
|
4052
4937
|
style: { position: "relative" },
|
|
4053
4938
|
"data-testid": TID.panel,
|
|
4054
4939
|
children: [
|
|
4055
|
-
/* @__PURE__ */
|
|
4940
|
+
/* @__PURE__ */ jsx21(
|
|
4056
4941
|
PanelContent,
|
|
4057
4942
|
{
|
|
4058
4943
|
...props2,
|
|
@@ -4061,7 +4946,7 @@ function Panel(props2) {
|
|
|
4061
4946
|
composerAttachApiRef
|
|
4062
4947
|
}
|
|
4063
4948
|
),
|
|
4064
|
-
/* @__PURE__ */
|
|
4949
|
+
/* @__PURE__ */ jsx21(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
4065
4950
|
]
|
|
4066
4951
|
}
|
|
4067
4952
|
);
|
|
@@ -4092,13 +4977,39 @@ function PanelContent(props2) {
|
|
|
4092
4977
|
onSend,
|
|
4093
4978
|
onStop,
|
|
4094
4979
|
onSuggestion,
|
|
4980
|
+
intakePending,
|
|
4981
|
+
onIntakeComplete,
|
|
4982
|
+
tool,
|
|
4095
4983
|
containerEl,
|
|
4096
4984
|
dragOver,
|
|
4097
4985
|
composerAttachApiRef
|
|
4098
4986
|
} = props2;
|
|
4099
4987
|
const s = options.strings;
|
|
4100
|
-
|
|
4101
|
-
|
|
4988
|
+
let composerArea;
|
|
4989
|
+
if (intakePending) {
|
|
4990
|
+
composerArea = /* @__PURE__ */ jsx21(IntakeGate, { intake: options.intake, strings: s, onComplete: onIntakeComplete });
|
|
4991
|
+
} else if (canSend) {
|
|
4992
|
+
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
4993
|
+
/* @__PURE__ */ jsx21(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
4994
|
+
/* @__PURE__ */ jsx21(
|
|
4995
|
+
Composer,
|
|
4996
|
+
{
|
|
4997
|
+
options,
|
|
4998
|
+
transport,
|
|
4999
|
+
feedback,
|
|
5000
|
+
bus,
|
|
5001
|
+
isStreaming,
|
|
5002
|
+
onSend,
|
|
5003
|
+
onStop,
|
|
5004
|
+
attachApiRef: composerAttachApiRef
|
|
5005
|
+
}
|
|
5006
|
+
)
|
|
5007
|
+
] });
|
|
5008
|
+
} else {
|
|
5009
|
+
composerArea = /* @__PURE__ */ jsx21(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear });
|
|
5010
|
+
}
|
|
5011
|
+
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5012
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
4102
5013
|
HistoryHeader,
|
|
4103
5014
|
{
|
|
4104
5015
|
strings: s,
|
|
@@ -4106,22 +5017,22 @@ function PanelContent(props2) {
|
|
|
4106
5017
|
onClose,
|
|
4107
5018
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
4108
5019
|
}
|
|
4109
|
-
) : /* @__PURE__ */
|
|
4110
|
-
onBack ? /* @__PURE__ */
|
|
5020
|
+
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5021
|
+
onBack ? /* @__PURE__ */ jsx21(
|
|
4111
5022
|
"button",
|
|
4112
5023
|
{
|
|
4113
5024
|
type: "button",
|
|
4114
|
-
class: `${
|
|
5025
|
+
class: `${p17}-icon-btn`,
|
|
4115
5026
|
onClick: onBack,
|
|
4116
5027
|
"aria-label": s.moduleBack,
|
|
4117
5028
|
title: s.moduleBack,
|
|
4118
|
-
children: /* @__PURE__ */
|
|
5029
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
4119
5030
|
}
|
|
4120
5031
|
) : null,
|
|
4121
|
-
agent ? /* @__PURE__ */
|
|
4122
|
-
/* @__PURE__ */
|
|
5032
|
+
agent ? /* @__PURE__ */ jsx21(AgentBadge, { agent }) : /* @__PURE__ */ jsx21("h1", { children: s.panelTitle }),
|
|
5033
|
+
/* @__PURE__ */ jsx21(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
4123
5034
|
] }),
|
|
4124
|
-
view === "history" ? /* @__PURE__ */
|
|
5035
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
4125
5036
|
ChatHistoryPane,
|
|
4126
5037
|
{
|
|
4127
5038
|
transport,
|
|
@@ -4130,9 +5041,9 @@ function PanelContent(props2) {
|
|
|
4130
5041
|
onSelect: (chat) => onSelectHistoryChat(chat.sessionId),
|
|
4131
5042
|
onNewChat
|
|
4132
5043
|
}
|
|
4133
|
-
) : /* @__PURE__ */
|
|
4134
|
-
/* @__PURE__ */
|
|
4135
|
-
/* @__PURE__ */
|
|
5044
|
+
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5045
|
+
/* @__PURE__ */ jsx21(DropZone, { visible: dragOver, strings: s }),
|
|
5046
|
+
/* @__PURE__ */ jsx21(
|
|
4136
5047
|
MessageList,
|
|
4137
5048
|
{
|
|
4138
5049
|
messagesSig,
|
|
@@ -4140,28 +5051,15 @@ function PanelContent(props2) {
|
|
|
4140
5051
|
responseMode: options.responseMode,
|
|
4141
5052
|
showReasoning: options.showReasoning,
|
|
4142
5053
|
showToolCalls: options.showToolCalls,
|
|
4143
|
-
loading: loadingMessages
|
|
5054
|
+
loading: loadingMessages,
|
|
5055
|
+
idle: !isStreaming,
|
|
5056
|
+
tool
|
|
4144
5057
|
}
|
|
4145
5058
|
),
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
/* @__PURE__ */ jsx17(
|
|
4149
|
-
Composer,
|
|
4150
|
-
{
|
|
4151
|
-
options,
|
|
4152
|
-
transport,
|
|
4153
|
-
feedback,
|
|
4154
|
-
bus,
|
|
4155
|
-
isStreaming,
|
|
4156
|
-
onSend,
|
|
4157
|
-
onStop,
|
|
4158
|
-
attachApiRef: composerAttachApiRef
|
|
4159
|
-
}
|
|
4160
|
-
)
|
|
4161
|
-
] }) : /* @__PURE__ */ jsx17(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear }),
|
|
4162
|
-
/* @__PURE__ */ jsx17(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5059
|
+
composerArea,
|
|
5060
|
+
/* @__PURE__ */ jsx21(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
4163
5061
|
] }),
|
|
4164
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5062
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx21(
|
|
4165
5063
|
ResizeGrip,
|
|
4166
5064
|
{
|
|
4167
5065
|
panelEl: containerEl,
|
|
@@ -4180,86 +5078,86 @@ function HistoryHeader({
|
|
|
4180
5078
|
onClose,
|
|
4181
5079
|
showClose
|
|
4182
5080
|
}) {
|
|
4183
|
-
return /* @__PURE__ */
|
|
4184
|
-
/* @__PURE__ */
|
|
5081
|
+
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5082
|
+
/* @__PURE__ */ jsx21(
|
|
4185
5083
|
"button",
|
|
4186
5084
|
{
|
|
4187
5085
|
type: "button",
|
|
4188
|
-
class: `${
|
|
5086
|
+
class: `${p17}-icon-btn`,
|
|
4189
5087
|
onClick: onBack,
|
|
4190
5088
|
"aria-label": strings.historyBack,
|
|
4191
5089
|
title: strings.historyBack,
|
|
4192
|
-
children: /* @__PURE__ */
|
|
5090
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
4193
5091
|
}
|
|
4194
5092
|
),
|
|
4195
|
-
/* @__PURE__ */
|
|
4196
|
-
showClose ? /* @__PURE__ */
|
|
5093
|
+
/* @__PURE__ */ jsx21("h1", { children: strings.historyTitle }),
|
|
5094
|
+
showClose ? /* @__PURE__ */ jsx21(
|
|
4197
5095
|
"button",
|
|
4198
5096
|
{
|
|
4199
5097
|
type: "button",
|
|
4200
|
-
class: `${
|
|
5098
|
+
class: `${p17}-icon-btn`,
|
|
4201
5099
|
onClick: onClose,
|
|
4202
5100
|
"aria-label": strings.close,
|
|
4203
5101
|
title: strings.close,
|
|
4204
|
-
children: /* @__PURE__ */
|
|
5102
|
+
children: /* @__PURE__ */ jsx21(CloseIcon, {})
|
|
4205
5103
|
}
|
|
4206
5104
|
) : null
|
|
4207
5105
|
] });
|
|
4208
5106
|
}
|
|
4209
5107
|
function ReadOnlyBanner({ label, ctaLabel, onNewChat }) {
|
|
4210
|
-
return /* @__PURE__ */
|
|
4211
|
-
/* @__PURE__ */
|
|
4212
|
-
/* @__PURE__ */
|
|
5108
|
+
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5109
|
+
/* @__PURE__ */ jsx21("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5110
|
+
/* @__PURE__ */ jsx21("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewChat, children: ctaLabel })
|
|
4213
5111
|
] });
|
|
4214
5112
|
}
|
|
4215
5113
|
function ComposerFooter({ disclaimer }) {
|
|
4216
5114
|
if (!disclaimer) return null;
|
|
4217
|
-
return /* @__PURE__ */
|
|
5115
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx21("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
4218
5116
|
}
|
|
4219
5117
|
function PoweredByBar({ poweredBy }) {
|
|
4220
5118
|
if (!poweredBy) return null;
|
|
4221
|
-
return /* @__PURE__ */
|
|
5119
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx21(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
4222
5120
|
}
|
|
4223
5121
|
function PoweredBy({ logoUrl, text, href }) {
|
|
4224
|
-
const inner = /* @__PURE__ */
|
|
4225
|
-
logoUrl ? /* @__PURE__ */
|
|
4226
|
-
text ? /* @__PURE__ */
|
|
5122
|
+
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5123
|
+
logoUrl ? /* @__PURE__ */ jsx21("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5124
|
+
text ? /* @__PURE__ */ jsx21("span", { children: text }) : null
|
|
4227
5125
|
] });
|
|
4228
5126
|
if (href) {
|
|
4229
|
-
return /* @__PURE__ */
|
|
5127
|
+
return /* @__PURE__ */ jsx21("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
4230
5128
|
}
|
|
4231
|
-
return /* @__PURE__ */
|
|
5129
|
+
return /* @__PURE__ */ jsx21("span", { class: `${p17}-poweredby`, children: inner });
|
|
4232
5130
|
}
|
|
4233
5131
|
|
|
4234
5132
|
// src/ui/sidebar.tsx
|
|
4235
|
-
import { Fragment as
|
|
5133
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
4236
5134
|
function Sidebar(props2) {
|
|
4237
|
-
const
|
|
5135
|
+
const p33 = BRAND.cssPrefix;
|
|
4238
5136
|
const { site, blocks, strings, collapsed } = props2;
|
|
4239
5137
|
const navigation = blocks?.navigation ?? [];
|
|
4240
5138
|
const linkCards = blocks?.linkCards ?? [];
|
|
4241
5139
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
4242
|
-
return /* @__PURE__ */
|
|
4243
|
-
/* @__PURE__ */
|
|
4244
|
-
/* @__PURE__ */
|
|
4245
|
-
/* @__PURE__ */
|
|
5140
|
+
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5141
|
+
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5142
|
+
/* @__PURE__ */ jsx22(SidebarBrand, { site }),
|
|
5143
|
+
/* @__PURE__ */ jsx22(
|
|
4246
5144
|
"button",
|
|
4247
5145
|
{
|
|
4248
5146
|
type: "button",
|
|
4249
|
-
class: `${
|
|
5147
|
+
class: `${p33}-sidebar-toggle`,
|
|
4250
5148
|
"aria-label": toggleLabel,
|
|
4251
5149
|
"aria-expanded": collapsed ? "false" : "true",
|
|
4252
5150
|
title: toggleLabel,
|
|
4253
5151
|
onClick: props2.onToggleCollapsed,
|
|
4254
5152
|
"data-testid": TID.sidebarToggle,
|
|
4255
|
-
children: /* @__PURE__ */
|
|
5153
|
+
children: /* @__PURE__ */ jsx22(SidebarToggleIcon, { collapsed })
|
|
4256
5154
|
}
|
|
4257
5155
|
)
|
|
4258
5156
|
] }),
|
|
4259
|
-
collapsed ? null : /* @__PURE__ */
|
|
4260
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
4261
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
4262
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5157
|
+
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5158
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx22("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx22(SidebarNav, { items: navigation }) }) : null,
|
|
5159
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx22(SidebarCards, { items: linkCards }) }) : null,
|
|
5160
|
+
props2.showConversations ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx22(
|
|
4263
5161
|
ConversationList,
|
|
4264
5162
|
{
|
|
4265
5163
|
transport: props2.transport,
|
|
@@ -4273,18 +5171,18 @@ function Sidebar(props2) {
|
|
|
4273
5171
|
] });
|
|
4274
5172
|
}
|
|
4275
5173
|
function SidebarBrand({ site }) {
|
|
4276
|
-
const
|
|
5174
|
+
const p33 = BRAND.cssPrefix;
|
|
4277
5175
|
if (site?.logo?.url) {
|
|
4278
5176
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
4279
|
-
return /* @__PURE__ */
|
|
4280
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
4281
|
-
/* @__PURE__ */
|
|
5177
|
+
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5178
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx22("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5179
|
+
/* @__PURE__ */ jsx22("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
4282
5180
|
] });
|
|
4283
5181
|
}
|
|
4284
|
-
return /* @__PURE__ */
|
|
5182
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
4285
5183
|
}
|
|
4286
5184
|
function SidebarToggleIcon({ collapsed }) {
|
|
4287
|
-
return /* @__PURE__ */
|
|
5185
|
+
return /* @__PURE__ */ jsx22(
|
|
4288
5186
|
"svg",
|
|
4289
5187
|
{
|
|
4290
5188
|
width: "16",
|
|
@@ -4294,38 +5192,38 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
4294
5192
|
stroke: "currentColor",
|
|
4295
5193
|
"stroke-width": "2",
|
|
4296
5194
|
"aria-hidden": "true",
|
|
4297
|
-
children: collapsed ? /* @__PURE__ */
|
|
5195
|
+
children: collapsed ? /* @__PURE__ */ jsx22("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx22("polyline", { points: "15 6 9 12 15 18" })
|
|
4298
5196
|
}
|
|
4299
5197
|
);
|
|
4300
5198
|
}
|
|
4301
5199
|
function SidebarNav({ items }) {
|
|
4302
|
-
const
|
|
4303
|
-
return /* @__PURE__ */
|
|
5200
|
+
const p33 = BRAND.cssPrefix;
|
|
5201
|
+
return /* @__PURE__ */ jsx22("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsxs17(
|
|
4304
5202
|
"a",
|
|
4305
5203
|
{
|
|
4306
|
-
class: `${
|
|
5204
|
+
class: `${p33}-sidebar-nav-item`,
|
|
4307
5205
|
href: item.href,
|
|
4308
5206
|
target: item.href ? "_blank" : void 0,
|
|
4309
5207
|
rel: item.href ? "noreferrer" : void 0,
|
|
4310
5208
|
children: [
|
|
4311
|
-
item.icon ? /* @__PURE__ */
|
|
4312
|
-
/* @__PURE__ */
|
|
5209
|
+
item.icon ? /* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5210
|
+
/* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
4313
5211
|
]
|
|
4314
5212
|
}
|
|
4315
5213
|
) }, item.id ?? item.label)) });
|
|
4316
5214
|
}
|
|
4317
5215
|
function SidebarCards({ items }) {
|
|
4318
|
-
const
|
|
4319
|
-
return /* @__PURE__ */
|
|
5216
|
+
const p33 = BRAND.cssPrefix;
|
|
5217
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
4320
5218
|
"a",
|
|
4321
5219
|
{
|
|
4322
|
-
class: `${
|
|
5220
|
+
class: `${p33}-sidebar-card`,
|
|
4323
5221
|
href: item.href,
|
|
4324
5222
|
target: item.href ? "_blank" : void 0,
|
|
4325
5223
|
rel: item.href ? "noreferrer" : void 0,
|
|
4326
5224
|
children: [
|
|
4327
|
-
/* @__PURE__ */
|
|
4328
|
-
item.description ? /* @__PURE__ */
|
|
5225
|
+
/* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5226
|
+
item.description ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
4329
5227
|
]
|
|
4330
5228
|
},
|
|
4331
5229
|
item.id ?? item.label
|
|
@@ -4333,11 +5231,11 @@ function SidebarCards({ items }) {
|
|
|
4333
5231
|
}
|
|
4334
5232
|
|
|
4335
5233
|
// src/ui/page-shell.tsx
|
|
4336
|
-
import { jsx as
|
|
4337
|
-
var
|
|
5234
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5235
|
+
var p18 = BRAND.cssPrefix;
|
|
4338
5236
|
function PageShell(props2) {
|
|
4339
|
-
return /* @__PURE__ */
|
|
4340
|
-
/* @__PURE__ */
|
|
5237
|
+
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5238
|
+
/* @__PURE__ */ jsx23(
|
|
4341
5239
|
Sidebar,
|
|
4342
5240
|
{
|
|
4343
5241
|
site: props2.site,
|
|
@@ -4352,7 +5250,7 @@ function PageShell(props2) {
|
|
|
4352
5250
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
4353
5251
|
}
|
|
4354
5252
|
),
|
|
4355
|
-
/* @__PURE__ */
|
|
5253
|
+
/* @__PURE__ */ jsx23("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
4356
5254
|
] });
|
|
4357
5255
|
}
|
|
4358
5256
|
|
|
@@ -4390,7 +5288,7 @@ var atTabRoot = (s) => activeStack(s).length === 0;
|
|
|
4390
5288
|
|
|
4391
5289
|
// src/ui/messenger-home.tsx
|
|
4392
5290
|
import { useCallback as useCallback4, useEffect as useEffect15, useRef as useRef7 } from "preact/hooks";
|
|
4393
|
-
import { useComputed as
|
|
5291
|
+
import { useComputed as useComputed6 } from "@preact/signals";
|
|
4394
5292
|
|
|
4395
5293
|
// src/ui/modules/messages.tsx
|
|
4396
5294
|
var chatLayout = {
|
|
@@ -4399,83 +5297,83 @@ var chatLayout = {
|
|
|
4399
5297
|
};
|
|
4400
5298
|
|
|
4401
5299
|
// src/ui/modules/help.tsx
|
|
4402
|
-
import { useEffect as useEffect11, useMemo as useMemo2, useState as
|
|
5300
|
+
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
4403
5301
|
|
|
4404
5302
|
// src/ui/back-header.tsx
|
|
4405
|
-
import { jsx as
|
|
4406
|
-
var
|
|
5303
|
+
import { jsx as jsx24, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5304
|
+
var p19 = BRAND.cssPrefix;
|
|
4407
5305
|
function TitleBar({ title, actions }) {
|
|
4408
|
-
return /* @__PURE__ */
|
|
4409
|
-
/* @__PURE__ */
|
|
4410
|
-
/* @__PURE__ */
|
|
4411
|
-
actions ?? /* @__PURE__ */
|
|
5306
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5307
|
+
/* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5308
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5309
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
4412
5310
|
] });
|
|
4413
5311
|
}
|
|
4414
5312
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
4415
|
-
return /* @__PURE__ */
|
|
4416
|
-
/* @__PURE__ */
|
|
4417
|
-
/* @__PURE__ */
|
|
4418
|
-
actions ?? /* @__PURE__ */
|
|
5313
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5314
|
+
/* @__PURE__ */ jsx24("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx24(BackIcon, {}) }),
|
|
5315
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5316
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
4419
5317
|
] });
|
|
4420
5318
|
}
|
|
4421
5319
|
|
|
4422
5320
|
// src/ui/home-search.tsx
|
|
4423
|
-
import { jsx as
|
|
4424
|
-
var
|
|
5321
|
+
import { jsx as jsx25, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5322
|
+
var p20 = BRAND.cssPrefix;
|
|
4425
5323
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
4426
|
-
return /* @__PURE__ */
|
|
4427
|
-
/* @__PURE__ */
|
|
4428
|
-
/* @__PURE__ */
|
|
5324
|
+
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5325
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5326
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
4429
5327
|
] });
|
|
4430
5328
|
}
|
|
4431
5329
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
4432
|
-
return /* @__PURE__ */
|
|
4433
|
-
/* @__PURE__ */
|
|
5330
|
+
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5331
|
+
/* @__PURE__ */ jsx25(
|
|
4434
5332
|
"input",
|
|
4435
5333
|
{
|
|
4436
5334
|
type: "search",
|
|
4437
|
-
class: `${
|
|
5335
|
+
class: `${p20}-home-search-input`,
|
|
4438
5336
|
placeholder,
|
|
4439
5337
|
value,
|
|
4440
5338
|
onInput: (e) => onInput(e.currentTarget.value),
|
|
4441
5339
|
"data-testid": TID.helpSearch
|
|
4442
5340
|
}
|
|
4443
5341
|
),
|
|
4444
|
-
/* @__PURE__ */
|
|
5342
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
4445
5343
|
] });
|
|
4446
5344
|
}
|
|
4447
5345
|
|
|
4448
5346
|
// src/ui/list-row.tsx
|
|
4449
|
-
import { jsx as
|
|
4450
|
-
var
|
|
5347
|
+
import { jsx as jsx26, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5348
|
+
var p21 = BRAND.cssPrefix;
|
|
4451
5349
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
4452
|
-
return /* @__PURE__ */
|
|
4453
|
-
/* @__PURE__ */
|
|
4454
|
-
/* @__PURE__ */
|
|
4455
|
-
subtitle ? /* @__PURE__ */
|
|
5350
|
+
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5351
|
+
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5352
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5353
|
+
subtitle ? /* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
4456
5354
|
] }),
|
|
4457
|
-
/* @__PURE__ */
|
|
5355
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx26(ChevronRightIcon, {}) })
|
|
4458
5356
|
] });
|
|
4459
5357
|
}
|
|
4460
5358
|
|
|
4461
5359
|
// src/ui/module-state.tsx
|
|
4462
|
-
import { jsx as
|
|
4463
|
-
var
|
|
5360
|
+
import { jsx as jsx27, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5361
|
+
var p22 = BRAND.cssPrefix;
|
|
4464
5362
|
function ModuleState({
|
|
4465
5363
|
tone = "info",
|
|
4466
5364
|
message,
|
|
4467
5365
|
onRetry,
|
|
4468
5366
|
strings
|
|
4469
5367
|
}) {
|
|
4470
|
-
return /* @__PURE__ */
|
|
4471
|
-
/* @__PURE__ */
|
|
4472
|
-
onRetry ? /* @__PURE__ */
|
|
5368
|
+
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5369
|
+
/* @__PURE__ */ jsx27("span", { children: message }),
|
|
5370
|
+
onRetry ? /* @__PURE__ */ jsx27("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
4473
5371
|
] });
|
|
4474
5372
|
}
|
|
4475
5373
|
|
|
4476
5374
|
// src/ui/modules/help.tsx
|
|
4477
|
-
import { jsx as
|
|
4478
|
-
var
|
|
5375
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5376
|
+
var p23 = BRAND.cssPrefix;
|
|
4479
5377
|
var log12 = logger.scope("help");
|
|
4480
5378
|
var openArticle = (nav, a) => a.url ? nav.push({ kind: "iframe", url: a.url, title: a.title }) : nav.push({ kind: "content", id: a.id, title: a.title });
|
|
4481
5379
|
function groupByCategory(items) {
|
|
@@ -4504,7 +5402,7 @@ function fuzzySearch(items, query) {
|
|
|
4504
5402
|
return items.map((item) => ({ item, score: Math.max(fuzzyScore(q, item.title) * 2, fuzzyScore(q, item.description ?? "")) })).filter((r) => r.score > 0).toSorted((a, b) => b.score - a.score).map((r) => r.item);
|
|
4505
5403
|
}
|
|
4506
5404
|
function ArticleRow({ article, nav }) {
|
|
4507
|
-
return /* @__PURE__ */
|
|
5405
|
+
return /* @__PURE__ */ jsx28(
|
|
4508
5406
|
ListRow,
|
|
4509
5407
|
{
|
|
4510
5408
|
title: article.title,
|
|
@@ -4516,11 +5414,11 @@ function ArticleRow({ article, nav }) {
|
|
|
4516
5414
|
}
|
|
4517
5415
|
function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
4518
5416
|
const tags = config.contentTags;
|
|
4519
|
-
const [state, setState] =
|
|
4520
|
-
const [errorMsg, setErrorMsg] =
|
|
4521
|
-
const [items, setItems] =
|
|
4522
|
-
const [query, setQuery] =
|
|
4523
|
-
const [reloadKey, setReloadKey] =
|
|
5417
|
+
const [state, setState] = useState8("loading");
|
|
5418
|
+
const [errorMsg, setErrorMsg] = useState8(strings.errorGeneric);
|
|
5419
|
+
const [items, setItems] = useState8([]);
|
|
5420
|
+
const [query, setQuery] = useState8("");
|
|
5421
|
+
const [reloadKey, setReloadKey] = useState8(0);
|
|
4524
5422
|
useEffect11(() => {
|
|
4525
5423
|
let cancelled = false;
|
|
4526
5424
|
setState("loading");
|
|
@@ -4541,46 +5439,46 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
4541
5439
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
4542
5440
|
function renderBody() {
|
|
4543
5441
|
if (query.trim().length > 0) {
|
|
4544
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
4545
|
-
return /* @__PURE__ */
|
|
5442
|
+
if (results.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5443
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) });
|
|
4546
5444
|
}
|
|
4547
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5445
|
+
if (state === "loading") return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpLoading, strings });
|
|
4548
5446
|
if (state === "error") {
|
|
4549
|
-
return /* @__PURE__ */
|
|
5447
|
+
return /* @__PURE__ */ jsx28(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
4550
5448
|
}
|
|
4551
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
4552
|
-
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */
|
|
4553
|
-
category ? /* @__PURE__ */
|
|
4554
|
-
/* @__PURE__ */
|
|
5449
|
+
if (items.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpEmpty, strings });
|
|
5450
|
+
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5451
|
+
category ? /* @__PURE__ */ jsx28("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5452
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) })
|
|
4555
5453
|
] }, category));
|
|
4556
5454
|
}
|
|
4557
|
-
return /* @__PURE__ */
|
|
4558
|
-
/* @__PURE__ */
|
|
4559
|
-
/* @__PURE__ */
|
|
4560
|
-
/* @__PURE__ */
|
|
5455
|
+
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5456
|
+
/* @__PURE__ */ jsx28(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx28(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5457
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx28(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5458
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
4561
5459
|
] });
|
|
4562
5460
|
}
|
|
4563
5461
|
var helpLayout = {
|
|
4564
5462
|
Icon: HelpIcon,
|
|
4565
|
-
Root: (props2) => /* @__PURE__ */
|
|
5463
|
+
Root: (props2) => /* @__PURE__ */ jsx28(HelpRoot, { ...props2 })
|
|
4566
5464
|
};
|
|
4567
5465
|
|
|
4568
5466
|
// src/ui/modules/home.tsx
|
|
4569
|
-
import { useEffect as useEffect12, useState as
|
|
5467
|
+
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
4570
5468
|
|
|
4571
5469
|
// src/ui/home-card.tsx
|
|
4572
|
-
import { jsx as
|
|
4573
|
-
var
|
|
5470
|
+
import { jsx as jsx29 } from "preact/jsx-runtime";
|
|
5471
|
+
var p24 = BRAND.cssPrefix;
|
|
4574
5472
|
function HomeCard({ onClick, children, testid }) {
|
|
4575
5473
|
if (onClick) {
|
|
4576
|
-
return /* @__PURE__ */
|
|
5474
|
+
return /* @__PURE__ */ jsx29("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
4577
5475
|
}
|
|
4578
|
-
return /* @__PURE__ */
|
|
5476
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
4579
5477
|
}
|
|
4580
5478
|
|
|
4581
5479
|
// src/ui/modules/home.tsx
|
|
4582
|
-
import { Fragment as
|
|
4583
|
-
var
|
|
5480
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5481
|
+
var p25 = BRAND.cssPrefix;
|
|
4584
5482
|
var log13 = logger.scope("home");
|
|
4585
5483
|
function resolveGreeting(props2) {
|
|
4586
5484
|
const name = props2.options.userContext?.name;
|
|
@@ -4594,8 +5492,8 @@ function resolveGreeting(props2) {
|
|
|
4594
5492
|
var openContent = (nav, item) => item.url ? nav.push({ kind: "iframe", url: item.url, title: item.title }) : nav.push({ kind: "content", id: item.id, title: item.title });
|
|
4595
5493
|
function HomeRoot(props2) {
|
|
4596
5494
|
const { transport, strings, config, nav, panelProps } = props2;
|
|
4597
|
-
const [recent, setRecent] =
|
|
4598
|
-
const [content, setContent] =
|
|
5495
|
+
const [recent, setRecent] = useState9(null);
|
|
5496
|
+
const [content, setContent] = useState9([]);
|
|
4599
5497
|
const tagsKey = config.contentTags?.join(",");
|
|
4600
5498
|
useEffect12(() => {
|
|
4601
5499
|
if (!config.showRecentMessages) return;
|
|
@@ -4617,49 +5515,49 @@ function HomeRoot(props2) {
|
|
|
4617
5515
|
const avatars = config.userAvatars ?? [];
|
|
4618
5516
|
const status = config.status;
|
|
4619
5517
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
4620
|
-
return /* @__PURE__ */
|
|
4621
|
-
/* @__PURE__ */
|
|
4622
|
-
/* @__PURE__ */
|
|
4623
|
-
config.brandName ? /* @__PURE__ */
|
|
4624
|
-
/* @__PURE__ */
|
|
4625
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
4626
|
-
/* @__PURE__ */
|
|
5518
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5519
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5520
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5521
|
+
config.brandName ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-brand`, "data-testid": TID.homeBrand, children: config.brandName }) : /* @__PURE__ */ jsx30("span", { class: `${p25}-home-brand-spacer`, "aria-hidden": "true" }),
|
|
5522
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5523
|
+
avatars.length > 0 ? /* @__PURE__ */ jsx30("div", { class: `${p25}-home-avatars`, children: avatars.map((a) => /* @__PURE__ */ jsx30("span", { class: `${p25}-home-avatar`, title: a.role ? `${a.name} \xB7 ${a.role}` : a.name, children: a.avatar ? /* @__PURE__ */ jsx30("img", { src: a.avatar, alt: "", loading: "lazy" }) : /* @__PURE__ */ jsx30("span", { children: initials(a.name) }) }, a.name)) }) : null,
|
|
5524
|
+
/* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" })
|
|
4627
5525
|
] })
|
|
4628
5526
|
] }),
|
|
4629
|
-
config.showGreeting !== false ? /* @__PURE__ */
|
|
4630
|
-
/* @__PURE__ */
|
|
4631
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5527
|
+
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5528
|
+
/* @__PURE__ */ jsx30("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5529
|
+
greeting.subtitle ? /* @__PURE__ */ jsx30("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
4632
5530
|
] }) : null
|
|
4633
5531
|
] }),
|
|
4634
|
-
/* @__PURE__ */
|
|
4635
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5532
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5533
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx30(
|
|
4636
5534
|
HomeSearchButton,
|
|
4637
5535
|
{
|
|
4638
5536
|
placeholder: strings.homeSearchPlaceholder,
|
|
4639
5537
|
onActivate: () => nav.switchToLayout("help")
|
|
4640
5538
|
}
|
|
4641
5539
|
) : null,
|
|
4642
|
-
recent ? /* @__PURE__ */
|
|
4643
|
-
/* @__PURE__ */
|
|
4644
|
-
/* @__PURE__ */
|
|
4645
|
-
/* @__PURE__ */
|
|
4646
|
-
recent.preview ? /* @__PURE__ */
|
|
5540
|
+
recent ? /* @__PURE__ */ jsx30(HomeCard, { onClick: () => nav.selectSession(recent.sessionId), testid: TID.homeRecent, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-recent-row`, "data-unread": (recent.unreadCount ?? 0) > 0 ? "true" : void 0, children: [
|
|
5541
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5542
|
+
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5543
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5544
|
+
recent.preview ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
4647
5545
|
] }),
|
|
4648
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5546
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
4649
5547
|
] }) }) : null,
|
|
4650
|
-
status ? /* @__PURE__ */
|
|
5548
|
+
status ? /* @__PURE__ */ jsx30(
|
|
4651
5549
|
HomeCard,
|
|
4652
5550
|
{
|
|
4653
5551
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
4654
|
-
children: /* @__PURE__ */
|
|
4655
|
-
/* @__PURE__ */
|
|
4656
|
-
/* @__PURE__ */
|
|
5552
|
+
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5553
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(StatusOkIcon, {}) }),
|
|
5554
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
4657
5555
|
] })
|
|
4658
5556
|
}
|
|
4659
5557
|
) : null,
|
|
4660
|
-
content.length > 0 ? /* @__PURE__ */
|
|
4661
|
-
/* @__PURE__ */
|
|
4662
|
-
/* @__PURE__ */
|
|
5558
|
+
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5559
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5560
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx30(
|
|
4663
5561
|
ListRow,
|
|
4664
5562
|
{
|
|
4665
5563
|
title: item.title,
|
|
@@ -4675,20 +5573,20 @@ function HomeRoot(props2) {
|
|
|
4675
5573
|
}
|
|
4676
5574
|
var homeLayout = {
|
|
4677
5575
|
Icon: HomeIcon,
|
|
4678
|
-
Root: (props2) => /* @__PURE__ */
|
|
5576
|
+
Root: (props2) => /* @__PURE__ */ jsx30(HomeRoot, { ...props2 })
|
|
4679
5577
|
};
|
|
4680
5578
|
|
|
4681
5579
|
// src/ui/modules/news.tsx
|
|
4682
|
-
import { useEffect as useEffect13, useState as
|
|
4683
|
-
import { jsx as
|
|
4684
|
-
var
|
|
5580
|
+
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5581
|
+
import { jsx as jsx31, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5582
|
+
var p26 = BRAND.cssPrefix;
|
|
4685
5583
|
var log14 = logger.scope("news");
|
|
4686
5584
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
4687
5585
|
const tags = config.contentTags;
|
|
4688
|
-
const [state, setState] =
|
|
4689
|
-
const [errorMsg, setErrorMsg] =
|
|
4690
|
-
const [items, setItems] =
|
|
4691
|
-
const [reloadKey, setReloadKey] =
|
|
5586
|
+
const [state, setState] = useState10("loading");
|
|
5587
|
+
const [errorMsg, setErrorMsg] = useState10(strings.errorGeneric);
|
|
5588
|
+
const [items, setItems] = useState10([]);
|
|
5589
|
+
const [reloadKey, setReloadKey] = useState10(0);
|
|
4692
5590
|
useEffect13(() => {
|
|
4693
5591
|
let cancelled = false;
|
|
4694
5592
|
setState("loading");
|
|
@@ -4707,38 +5605,38 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
4707
5605
|
};
|
|
4708
5606
|
}, [transport, tags, reloadKey]);
|
|
4709
5607
|
function renderBody() {
|
|
4710
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5608
|
+
if (state === "loading") return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsLoading, strings });
|
|
4711
5609
|
if (state === "error") {
|
|
4712
|
-
return /* @__PURE__ */
|
|
5610
|
+
return /* @__PURE__ */ jsx31(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
4713
5611
|
}
|
|
4714
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
4715
|
-
return /* @__PURE__ */
|
|
5612
|
+
if (items.length === 0) return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsEmpty, strings });
|
|
5613
|
+
return /* @__PURE__ */ jsx31("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
4716
5614
|
"button",
|
|
4717
5615
|
{
|
|
4718
5616
|
type: "button",
|
|
4719
|
-
class: `${
|
|
5617
|
+
class: `${p26}-news-card`,
|
|
4720
5618
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
4721
5619
|
"data-testid": tid(TID.newsItem, item.id),
|
|
4722
5620
|
children: [
|
|
4723
|
-
item.image ? /* @__PURE__ */
|
|
4724
|
-
/* @__PURE__ */
|
|
4725
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
4726
|
-
/* @__PURE__ */
|
|
4727
|
-
item.description ? /* @__PURE__ */
|
|
5621
|
+
item.image ? /* @__PURE__ */ jsx31("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5622
|
+
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5623
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx31("span", { class: `${p26}-news-tag`, children: t }, t)) }) : null,
|
|
5624
|
+
/* @__PURE__ */ jsx31("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5625
|
+
item.description ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
4728
5626
|
] })
|
|
4729
5627
|
]
|
|
4730
5628
|
},
|
|
4731
5629
|
item.id
|
|
4732
5630
|
)) });
|
|
4733
5631
|
}
|
|
4734
|
-
return /* @__PURE__ */
|
|
4735
|
-
/* @__PURE__ */
|
|
4736
|
-
/* @__PURE__ */
|
|
5632
|
+
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5633
|
+
/* @__PURE__ */ jsx31(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx31(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5634
|
+
/* @__PURE__ */ jsx31("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
4737
5635
|
] });
|
|
4738
5636
|
}
|
|
4739
5637
|
var newsLayout = {
|
|
4740
5638
|
Icon: NewsIcon,
|
|
4741
|
-
Root: (props2) => /* @__PURE__ */
|
|
5639
|
+
Root: (props2) => /* @__PURE__ */ jsx31(NewsRoot, { ...props2 })
|
|
4742
5640
|
};
|
|
4743
5641
|
|
|
4744
5642
|
// src/ui/modules/registry.ts
|
|
@@ -4750,28 +5648,28 @@ var LAYOUTS = {
|
|
|
4750
5648
|
};
|
|
4751
5649
|
|
|
4752
5650
|
// src/ui/home-tab-bar.tsx
|
|
4753
|
-
import { jsx as
|
|
4754
|
-
var
|
|
5651
|
+
import { jsx as jsx32, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5652
|
+
var p27 = BRAND.cssPrefix;
|
|
4755
5653
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
4756
|
-
return /* @__PURE__ */
|
|
5654
|
+
return /* @__PURE__ */ jsx32("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
4757
5655
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
4758
5656
|
const selected = m.id === activeTab;
|
|
4759
5657
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
4760
|
-
return /* @__PURE__ */
|
|
5658
|
+
return /* @__PURE__ */ jsxs26(
|
|
4761
5659
|
"button",
|
|
4762
5660
|
{
|
|
4763
5661
|
type: "button",
|
|
4764
5662
|
role: "tab",
|
|
4765
5663
|
"aria-selected": selected,
|
|
4766
|
-
class: `${
|
|
5664
|
+
class: `${p27}-tab`,
|
|
4767
5665
|
onClick: () => onSelect(m.id),
|
|
4768
5666
|
"data-testid": tid(TID.tab, m.id),
|
|
4769
5667
|
children: [
|
|
4770
|
-
/* @__PURE__ */
|
|
4771
|
-
/* @__PURE__ */
|
|
4772
|
-
badge ? /* @__PURE__ */
|
|
5668
|
+
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5669
|
+
/* @__PURE__ */ jsx32(Icon, {}),
|
|
5670
|
+
badge ? /* @__PURE__ */ jsx32("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
4773
5671
|
] }),
|
|
4774
|
-
/* @__PURE__ */
|
|
5672
|
+
/* @__PURE__ */ jsx32("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
4775
5673
|
]
|
|
4776
5674
|
},
|
|
4777
5675
|
m.id
|
|
@@ -4780,12 +5678,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
4780
5678
|
}
|
|
4781
5679
|
|
|
4782
5680
|
// src/ui/iframe-view.tsx
|
|
4783
|
-
import { jsx as
|
|
4784
|
-
var
|
|
5681
|
+
import { jsx as jsx33, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5682
|
+
var p28 = BRAND.cssPrefix;
|
|
4785
5683
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
4786
5684
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
4787
|
-
return /* @__PURE__ */
|
|
4788
|
-
/* @__PURE__ */
|
|
5685
|
+
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5686
|
+
/* @__PURE__ */ jsx33(
|
|
4789
5687
|
BackHeader,
|
|
4790
5688
|
{
|
|
4791
5689
|
title: title || strings.moduleBack,
|
|
@@ -4794,10 +5692,10 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
4794
5692
|
actions
|
|
4795
5693
|
}
|
|
4796
5694
|
),
|
|
4797
|
-
/* @__PURE__ */
|
|
5695
|
+
/* @__PURE__ */ jsx33(
|
|
4798
5696
|
"iframe",
|
|
4799
5697
|
{
|
|
4800
|
-
class: `${
|
|
5698
|
+
class: `${p28}-content-frame`,
|
|
4801
5699
|
src: url,
|
|
4802
5700
|
title: title || "content",
|
|
4803
5701
|
sandbox: SANDBOX,
|
|
@@ -4810,14 +5708,14 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
4810
5708
|
}
|
|
4811
5709
|
|
|
4812
5710
|
// src/ui/content-view.tsx
|
|
4813
|
-
import { useCallback as useCallback3, useEffect as useEffect14, useState as
|
|
4814
|
-
import { jsx as
|
|
4815
|
-
var
|
|
5711
|
+
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5712
|
+
import { jsx as jsx34, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5713
|
+
var p29 = BRAND.cssPrefix;
|
|
4816
5714
|
var log15 = logger.scope("content");
|
|
4817
5715
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
4818
|
-
const [item, setItem] =
|
|
4819
|
-
const [failed, setFailed] =
|
|
4820
|
-
const [reloadKey, setReloadKey] =
|
|
5716
|
+
const [item, setItem] = useState11(null);
|
|
5717
|
+
const [failed, setFailed] = useState11(false);
|
|
5718
|
+
const [reloadKey, setReloadKey] = useState11(0);
|
|
4821
5719
|
const retry = useCallback3(() => {
|
|
4822
5720
|
setFailed(false);
|
|
4823
5721
|
setItem(null);
|
|
@@ -4840,17 +5738,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
4840
5738
|
};
|
|
4841
5739
|
}, [transport, id, reloadKey]);
|
|
4842
5740
|
function renderBody() {
|
|
4843
|
-
if (failed) return /* @__PURE__ */
|
|
4844
|
-
if (item === null) return /* @__PURE__ */
|
|
4845
|
-
return /* @__PURE__ */
|
|
4846
|
-
item.image ? /* @__PURE__ */
|
|
4847
|
-
item.description ? /* @__PURE__ */
|
|
4848
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
4849
|
-
/* @__PURE__ */
|
|
5741
|
+
if (failed) return /* @__PURE__ */ jsx34(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5742
|
+
if (item === null) return /* @__PURE__ */ jsx34(ModuleState, { message: strings.contentLoading, strings });
|
|
5743
|
+
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5744
|
+
item.image ? /* @__PURE__ */ jsx34("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5745
|
+
item.description ? /* @__PURE__ */ jsx34("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5746
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx34("span", { class: `${p29}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx34("span", { class: `${p29}-news-tag`, children: t }, t)) }) : null,
|
|
5747
|
+
/* @__PURE__ */ jsx34(StaticMarkdown, { text: item.content ?? "" })
|
|
4850
5748
|
] });
|
|
4851
5749
|
}
|
|
4852
|
-
return /* @__PURE__ */
|
|
4853
|
-
/* @__PURE__ */
|
|
5750
|
+
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5751
|
+
/* @__PURE__ */ jsx34(
|
|
4854
5752
|
BackHeader,
|
|
4855
5753
|
{
|
|
4856
5754
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -4860,13 +5758,13 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
4860
5758
|
testid: TID.backHeader
|
|
4861
5759
|
}
|
|
4862
5760
|
),
|
|
4863
|
-
/* @__PURE__ */
|
|
5761
|
+
/* @__PURE__ */ jsx34("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
4864
5762
|
] });
|
|
4865
5763
|
}
|
|
4866
5764
|
|
|
4867
5765
|
// src/ui/messenger-home.tsx
|
|
4868
|
-
import { jsx as
|
|
4869
|
-
var
|
|
5766
|
+
import { jsx as jsx35, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5767
|
+
var p30 = BRAND.cssPrefix;
|
|
4870
5768
|
function MessengerHome({
|
|
4871
5769
|
panelProps,
|
|
4872
5770
|
enabledModules,
|
|
@@ -4898,7 +5796,7 @@ function MessengerHome({
|
|
|
4898
5796
|
}, []);
|
|
4899
5797
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
4900
5798
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
4901
|
-
const navState =
|
|
5799
|
+
const navState = useComputed6(() => nav.sig.value).value;
|
|
4902
5800
|
const top = topScreen(navState);
|
|
4903
5801
|
const activeModule = options.modules.byId[navState.activeTab];
|
|
4904
5802
|
const isReader = top?.kind === "iframe" || top?.kind === "content";
|
|
@@ -4934,12 +5832,12 @@ function MessengerHome({
|
|
|
4934
5832
|
nav: moduleNav,
|
|
4935
5833
|
panelProps
|
|
4936
5834
|
});
|
|
4937
|
-
const plainActions = /* @__PURE__ */
|
|
5835
|
+
const plainActions = /* @__PURE__ */ jsx35(HeaderActions, { panelProps, variant: "plain" });
|
|
4938
5836
|
let body;
|
|
4939
5837
|
if (top?.kind === "iframe") {
|
|
4940
|
-
body = /* @__PURE__ */
|
|
5838
|
+
body = /* @__PURE__ */ jsx35(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
4941
5839
|
} else if (top?.kind === "content") {
|
|
4942
|
-
body = /* @__PURE__ */
|
|
5840
|
+
body = /* @__PURE__ */ jsx35(
|
|
4943
5841
|
ContentView,
|
|
4944
5842
|
{
|
|
4945
5843
|
id: top.id,
|
|
@@ -4951,7 +5849,7 @@ function MessengerHome({
|
|
|
4951
5849
|
}
|
|
4952
5850
|
);
|
|
4953
5851
|
} else if (activeModule?.layout === "chat") {
|
|
4954
|
-
body = /* @__PURE__ */
|
|
5852
|
+
body = /* @__PURE__ */ jsx35(
|
|
4955
5853
|
PanelContent,
|
|
4956
5854
|
{
|
|
4957
5855
|
...panelProps,
|
|
@@ -4962,23 +5860,23 @@ function MessengerHome({
|
|
|
4962
5860
|
);
|
|
4963
5861
|
} else if (activeModule) {
|
|
4964
5862
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
4965
|
-
body = Root ? /* @__PURE__ */
|
|
5863
|
+
body = Root ? /* @__PURE__ */ jsx35(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
4966
5864
|
} else {
|
|
4967
5865
|
body = null;
|
|
4968
5866
|
}
|
|
4969
|
-
return /* @__PURE__ */
|
|
5867
|
+
return /* @__PURE__ */ jsxs29(
|
|
4970
5868
|
"div",
|
|
4971
5869
|
{
|
|
4972
5870
|
ref: containerRef,
|
|
4973
|
-
class: `${
|
|
5871
|
+
class: `${p30}-panel ${p30}-messenger`,
|
|
4974
5872
|
role: "dialog",
|
|
4975
5873
|
"aria-modal": "false",
|
|
4976
5874
|
"aria-label": strings.panelTitle,
|
|
4977
5875
|
style: { position: "relative" },
|
|
4978
5876
|
"data-testid": TID.messengerHome,
|
|
4979
5877
|
children: [
|
|
4980
|
-
/* @__PURE__ */
|
|
4981
|
-
showTabBar ? /* @__PURE__ */
|
|
5878
|
+
/* @__PURE__ */ jsx35("div", { class: `${p30}-messenger-body`, children: body }),
|
|
5879
|
+
showTabBar ? /* @__PURE__ */ jsx35(
|
|
4982
5880
|
HomeTabBar,
|
|
4983
5881
|
{
|
|
4984
5882
|
modules: enabledModules,
|
|
@@ -4988,8 +5886,8 @@ function MessengerHome({
|
|
|
4988
5886
|
onSelect: nav.switchTab
|
|
4989
5887
|
}
|
|
4990
5888
|
) : null,
|
|
4991
|
-
/* @__PURE__ */
|
|
4992
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
5889
|
+
/* @__PURE__ */ jsx35(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
5890
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx35(
|
|
4993
5891
|
ResizeGrip,
|
|
4994
5892
|
{
|
|
4995
5893
|
panelEl: containerRef.current,
|
|
@@ -5006,29 +5904,29 @@ function MessengerHome({
|
|
|
5006
5904
|
}
|
|
5007
5905
|
|
|
5008
5906
|
// src/ui/modules-empty.tsx
|
|
5009
|
-
import { jsx as
|
|
5010
|
-
var
|
|
5907
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
5908
|
+
var p31 = BRAND.cssPrefix;
|
|
5011
5909
|
function ModulesEmpty({ strings, onClose }) {
|
|
5012
|
-
return /* @__PURE__ */
|
|
5910
|
+
return /* @__PURE__ */ jsxs30(
|
|
5013
5911
|
"div",
|
|
5014
5912
|
{
|
|
5015
|
-
class: `${
|
|
5913
|
+
class: `${p31}-panel ${p31}-modules-empty`,
|
|
5016
5914
|
role: "dialog",
|
|
5017
5915
|
"aria-label": strings.panelTitle,
|
|
5018
5916
|
"data-testid": TID.modulesEmpty,
|
|
5019
5917
|
children: [
|
|
5020
|
-
onClose ? /* @__PURE__ */
|
|
5918
|
+
onClose ? /* @__PURE__ */ jsx36(
|
|
5021
5919
|
"button",
|
|
5022
5920
|
{
|
|
5023
5921
|
type: "button",
|
|
5024
|
-
class: `${
|
|
5922
|
+
class: `${p31}-icon-btn ${p31}-modules-empty-close`,
|
|
5025
5923
|
onClick: onClose,
|
|
5026
5924
|
"aria-label": strings.close,
|
|
5027
5925
|
title: strings.close,
|
|
5028
|
-
children: /* @__PURE__ */
|
|
5926
|
+
children: /* @__PURE__ */ jsx36(CloseIcon, {})
|
|
5029
5927
|
}
|
|
5030
5928
|
) : null,
|
|
5031
|
-
/* @__PURE__ */
|
|
5929
|
+
/* @__PURE__ */ jsx36("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
5032
5930
|
]
|
|
5033
5931
|
}
|
|
5034
5932
|
);
|
|
@@ -5083,11 +5981,11 @@ function animateTypewriter(msg, text, charsPerSecond, abort) {
|
|
|
5083
5981
|
}
|
|
5084
5982
|
|
|
5085
5983
|
// src/ui/use-launcher-callout.ts
|
|
5086
|
-
import { useCallback as useCallback5, useEffect as useEffect16, useState as
|
|
5984
|
+
import { useCallback as useCallback5, useEffect as useEffect16, useState as useState12 } from "preact/hooks";
|
|
5087
5985
|
function useLauncherCallout({ callout, persistence }) {
|
|
5088
5986
|
const textKey = callout?.text ?? "";
|
|
5089
5987
|
const persistent = callout?.persistent ?? true;
|
|
5090
|
-
const [dismissed, setDismissed] =
|
|
5988
|
+
const [dismissed, setDismissed] = useState12(() => persistent ? false : persistence.loadCalloutDismissed(textKey));
|
|
5091
5989
|
useEffect16(() => {
|
|
5092
5990
|
setDismissed(persistent ? false : persistence.loadCalloutDismissed(textKey));
|
|
5093
5991
|
}, [textKey, persistent, persistence]);
|
|
@@ -5099,21 +5997,21 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
5099
5997
|
}
|
|
5100
5998
|
|
|
5101
5999
|
// src/ui/app.tsx
|
|
5102
|
-
import { jsx as
|
|
6000
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
5103
6001
|
var log16 = logger.scope("app");
|
|
5104
|
-
var
|
|
6002
|
+
var p32 = BRAND.cssPrefix;
|
|
5105
6003
|
function App({ options, hostElement, bus }) {
|
|
5106
|
-
const [persistence] =
|
|
5107
|
-
const [visitorId, setVisitorId] =
|
|
6004
|
+
const [persistence] = useState13(() => createPersistence(options.widgetId, options.storage));
|
|
6005
|
+
const [visitorId, setVisitorId] = useState13(() => persistence.getVisitorId());
|
|
5108
6006
|
const initialSettings = persistence.loadUserPrefs();
|
|
5109
|
-
const [activeLocale, setActiveLocale] =
|
|
5110
|
-
const [activeThemeMode, setActiveThemeMode] =
|
|
6007
|
+
const [activeLocale, setActiveLocale] = useState13(() => initialSettings.locale ?? options.locale);
|
|
6008
|
+
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
5111
6009
|
() => initialSettings.themeMode ?? options.themeMode
|
|
5112
6010
|
);
|
|
5113
|
-
const sessionIdSig =
|
|
5114
|
-
const messagesSig =
|
|
5115
|
-
const unreadCountSig =
|
|
5116
|
-
const [loadingMessages, setLoadingMessages] =
|
|
6011
|
+
const sessionIdSig = useSignal2(persistence.loadSessionId());
|
|
6012
|
+
const messagesSig = useSignal2([]);
|
|
6013
|
+
const unreadCountSig = useSignal2(0);
|
|
6014
|
+
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
5117
6015
|
function landingTab() {
|
|
5118
6016
|
const list = options.modules.list;
|
|
5119
6017
|
const ids = new Set(list.map((m) => m.id));
|
|
@@ -5132,14 +6030,14 @@ function App({ options, hostElement, bus }) {
|
|
|
5132
6030
|
const homeNav = homeNavRef.current;
|
|
5133
6031
|
const chatTabIdRef = useRef8(void 0);
|
|
5134
6032
|
chatTabIdRef.current = chatTabId();
|
|
5135
|
-
const [sessionReady, setSessionReady] =
|
|
6033
|
+
const [sessionReady, setSessionReady] = useState13(false);
|
|
5136
6034
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
5137
6035
|
const initialPanelRef = useRef8(
|
|
5138
6036
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
5139
6037
|
);
|
|
5140
|
-
const [isOpen, setIsOpen] =
|
|
6038
|
+
const [isOpen, setIsOpen] = useState13(initialPanelRef.current.panelOpen);
|
|
5141
6039
|
const initialPanelApplied = useRef8(false);
|
|
5142
|
-
const [launcherLeaving, setLauncherLeaving] =
|
|
6040
|
+
const [launcherLeaving, setLauncherLeaving] = useState13(false);
|
|
5143
6041
|
const { dismissed: calloutDismissed, dismissCallout: dismissCalloutRaw } = useLauncherCallout({
|
|
5144
6042
|
callout: options.launcher.callout,
|
|
5145
6043
|
persistence
|
|
@@ -5150,19 +6048,20 @@ function App({ options, hostElement, bus }) {
|
|
|
5150
6048
|
bus.emit("calloutDismiss", void 0);
|
|
5151
6049
|
dismissCalloutRaw();
|
|
5152
6050
|
}, [bus, dismissCalloutRaw]);
|
|
5153
|
-
const [panelSize, setPanelSize] =
|
|
6051
|
+
const [panelSize, setPanelSize] = useState13(initialPanelRef.current.panelSize);
|
|
5154
6052
|
const initialSizeApplied = useRef8(false);
|
|
5155
|
-
const [view, setView] =
|
|
5156
|
-
const [canSend, setCanSend] =
|
|
5157
|
-
const [streaming, setStreaming] =
|
|
5158
|
-
const [agent, setAgent] =
|
|
5159
|
-
const [suggestions, setSuggestions] =
|
|
5160
|
-
const [activeCancel, setActiveCancel] =
|
|
6053
|
+
const [view, setView] = useState13("chat");
|
|
6054
|
+
const [canSend, setCanSend] = useState13(true);
|
|
6055
|
+
const [streaming, setStreaming] = useState13(false);
|
|
6056
|
+
const [agent, setAgent] = useState13(null);
|
|
6057
|
+
const [suggestions, setSuggestions] = useState13([]);
|
|
6058
|
+
const [activeCancel, setActiveCancel] = useState13(null);
|
|
5161
6059
|
const welcomeAbortRef = useRef8(null);
|
|
5162
|
-
const [parsedSite, setParsedSite] =
|
|
5163
|
-
const [parsedBlocks, setParsedBlocks] =
|
|
5164
|
-
const [sidebarCollapsed, setSidebarCollapsed] =
|
|
5165
|
-
const [
|
|
6060
|
+
const [parsedSite, setParsedSite] = useState13(void 0);
|
|
6061
|
+
const [parsedBlocks, setParsedBlocks] = useState13(void 0);
|
|
6062
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState13(() => persistence.loadSidebarCollapsed() ?? false);
|
|
6063
|
+
const [intakeValues, setIntakeValues] = useState13(() => persistence.loadIntake());
|
|
6064
|
+
const [transport] = useState13(
|
|
5166
6065
|
() => new AgentTransport({
|
|
5167
6066
|
baseUrl: options.baseUrl,
|
|
5168
6067
|
auth: createAuth({
|
|
@@ -5173,8 +6072,8 @@ function App({ options, hostElement, bus }) {
|
|
|
5173
6072
|
endpoints: options.endpoints
|
|
5174
6073
|
})
|
|
5175
6074
|
);
|
|
5176
|
-
const [reducer] =
|
|
5177
|
-
const [feedback] =
|
|
6075
|
+
const [reducer] = useState13(() => new StreamReducer(messagesSig));
|
|
6076
|
+
const [feedback] = useState13(() => new FeedbackBus(options.sound, options.haptics));
|
|
5178
6077
|
const patchAndSync = useCallback6(
|
|
5179
6078
|
(patch) => {
|
|
5180
6079
|
persistence.patchUserPrefs(patch);
|
|
@@ -5344,9 +6243,11 @@ function App({ options, hostElement, bus }) {
|
|
|
5344
6243
|
);
|
|
5345
6244
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
5346
6245
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
6246
|
+
const intakeSig = JSON.stringify(intakeValues ?? null);
|
|
5347
6247
|
useEffect17(() => {
|
|
5348
|
-
|
|
5349
|
-
|
|
6248
|
+
const merged = intakeValues ? { ...intakeValues, ...options.userContext } : options.userContext;
|
|
6249
|
+
transport.setContext(merged, toWirePageContext(options.pageContext));
|
|
6250
|
+
}, [transport, userSig, pageSig, intakeSig]);
|
|
5350
6251
|
const runResume = useCallback6(
|
|
5351
6252
|
async (handle) => {
|
|
5352
6253
|
let bubble = null;
|
|
@@ -5434,24 +6335,8 @@ function App({ options, hostElement, bus }) {
|
|
|
5434
6335
|
document.addEventListener("keydown", onKey);
|
|
5435
6336
|
return () => document.removeEventListener("keydown", onKey);
|
|
5436
6337
|
}, [isOpen, options.mode]);
|
|
5437
|
-
const
|
|
5438
|
-
async (
|
|
5439
|
-
log16.info("send", { textLen: text.length, attachments: attachments.length, streaming });
|
|
5440
|
-
if (streaming) return;
|
|
5441
|
-
bus.emit("send", { text, attachmentCount: attachments.length });
|
|
5442
|
-
if (suggestions.length > 0) setSuggestions([]);
|
|
5443
|
-
const uploaded = await uploadAttachments(transport, attachments, (err) => {
|
|
5444
|
-
log16.warn("upload failed", { err });
|
|
5445
|
-
bus.emit("error", err);
|
|
5446
|
-
options.onError?.(err);
|
|
5447
|
-
});
|
|
5448
|
-
feedback.unlock();
|
|
5449
|
-
feedback.play("messageSent");
|
|
5450
|
-
const userMsg = makeUserMessage(text, uploaded);
|
|
5451
|
-
const assistantMsg = makeAssistantMessage();
|
|
5452
|
-
messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
|
|
5453
|
-
reducer.attach(assistantMsg);
|
|
5454
|
-
emitMessage(bus, options, "user", text);
|
|
6338
|
+
const streamAssistant = useCallback6(
|
|
6339
|
+
async (assistantMsg, trigger) => {
|
|
5455
6340
|
const activeSessionId = sessionIdSig.value ?? uuid7();
|
|
5456
6341
|
if (!sessionIdSig.value) {
|
|
5457
6342
|
sessionIdSig.value = activeSessionId;
|
|
@@ -5460,10 +6345,10 @@ function App({ options, hostElement, bus }) {
|
|
|
5460
6345
|
const body = buildSendMessageRequest({
|
|
5461
6346
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
5462
6347
|
sessionId: activeSessionId,
|
|
5463
|
-
// textModel + imageModel are backend-only — selected per
|
|
5464
|
-
// deployment in the dashboard, never passed up by the widget.
|
|
6348
|
+
// textModel + imageModel are backend-only — selected per deployment.
|
|
5465
6349
|
tools: options.features.tools,
|
|
5466
6350
|
responseMode: options.responseMode,
|
|
6351
|
+
trigger,
|
|
5467
6352
|
// Identity + preferences ride on every message — server may need
|
|
5468
6353
|
// them to route, persist, or reconcile in-flight.
|
|
5469
6354
|
visitorId,
|
|
@@ -5495,19 +6380,95 @@ function App({ options, hostElement, bus }) {
|
|
|
5495
6380
|
messagesSig.value = [...messagesSig.value];
|
|
5496
6381
|
}
|
|
5497
6382
|
},
|
|
5498
|
-
[
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
6383
|
+
[transport, reducer, messagesSig, sessionIdSig, options, bus, feedback, persistence, visitorId]
|
|
6384
|
+
);
|
|
6385
|
+
const resolveTool = useCallback6(
|
|
6386
|
+
(toolCallId, trigger, mutate) => {
|
|
6387
|
+
if (streaming) return;
|
|
6388
|
+
const last = messagesSig.value.at(-1);
|
|
6389
|
+
const part = last?.partsSig.value.find(
|
|
6390
|
+
(pt) => pt.kind === "tool" && pt.toolCallId === toolCallId
|
|
6391
|
+
);
|
|
6392
|
+
if (!part) {
|
|
6393
|
+
log16.warn("resolveTool: tool part not found", { toolCallId });
|
|
6394
|
+
return;
|
|
6395
|
+
}
|
|
6396
|
+
mutate(part);
|
|
6397
|
+
if (last) last.partsSig.value = [...last.partsSig.value];
|
|
6398
|
+
const assistantMsg = makeAssistantMessage();
|
|
6399
|
+
messagesSig.value = [...messagesSig.value, assistantMsg];
|
|
6400
|
+
reducer.attach(assistantMsg);
|
|
6401
|
+
void streamAssistant(assistantMsg, trigger);
|
|
6402
|
+
},
|
|
6403
|
+
[streaming, messagesSig, reducer, streamAssistant]
|
|
6404
|
+
);
|
|
6405
|
+
const handleToolResult = useCallback6(
|
|
6406
|
+
(toolCallId, output) => {
|
|
6407
|
+
log16.info("toolResult", { toolCallId });
|
|
6408
|
+
bus.emit("toolResult", { toolCallId });
|
|
6409
|
+
resolveTool(toolCallId, TRIGGER.toolResult, (part) => {
|
|
6410
|
+
part.outputSig.value = output;
|
|
6411
|
+
part.stateSig.value = "output";
|
|
6412
|
+
});
|
|
6413
|
+
},
|
|
6414
|
+
[bus, resolveTool]
|
|
6415
|
+
);
|
|
6416
|
+
const handleToolDecision = useCallback6(
|
|
6417
|
+
(toolCallId, approved, reason) => {
|
|
6418
|
+
log16.info("toolDecision", { toolCallId, approved });
|
|
6419
|
+
bus.emit("toolDecision", { toolCallId, approved });
|
|
6420
|
+
resolveTool(toolCallId, TRIGGER.toolApproval, (part) => {
|
|
6421
|
+
const id = part.approvalSig.value?.id ?? toolCallId;
|
|
6422
|
+
part.approvalSig.value = { id, approved, reason };
|
|
6423
|
+
part.stateSig.value = "output";
|
|
6424
|
+
});
|
|
6425
|
+
},
|
|
6426
|
+
[bus, resolveTool]
|
|
6427
|
+
);
|
|
6428
|
+
const toolInteraction = useMemo3(
|
|
6429
|
+
() => ({ humanInLoop: options.features.humanInLoop, onResult: handleToolResult, onDecision: handleToolDecision }),
|
|
6430
|
+
[options.features.humanInLoop, handleToolResult, handleToolDecision]
|
|
6431
|
+
);
|
|
6432
|
+
const intakePending = options.intake.enabled && intakeValues === null;
|
|
6433
|
+
const handleIntakeComplete = useCallback6(
|
|
6434
|
+
(values) => {
|
|
6435
|
+
const hasValues = Object.keys(values).length > 0;
|
|
6436
|
+
log16.info("intakeComplete", { fields: Object.keys(values).length, skipped: !hasValues });
|
|
6437
|
+
persistence.saveIntake(values);
|
|
6438
|
+
setIntakeValues(values);
|
|
6439
|
+
bus.emit("intakeSubmit", values);
|
|
6440
|
+
if (!hasValues) return;
|
|
6441
|
+
const activeSessionId = sessionIdSig.value ?? uuid7();
|
|
6442
|
+
if (!sessionIdSig.value) {
|
|
6443
|
+
sessionIdSig.value = activeSessionId;
|
|
6444
|
+
persistence.saveSessionId(activeSessionId);
|
|
6445
|
+
transport.primeIdentity(void 0, activeSessionId);
|
|
6446
|
+
}
|
|
6447
|
+
void transport.submitIntake(activeSessionId, values);
|
|
6448
|
+
},
|
|
6449
|
+
[persistence, bus, sessionIdSig, transport]
|
|
6450
|
+
);
|
|
6451
|
+
const handleSend = useCallback6(
|
|
6452
|
+
async (text, attachments) => {
|
|
6453
|
+
log16.info("send", { textLen: text.length, attachments: attachments.length, streaming });
|
|
6454
|
+
if (streaming) return;
|
|
6455
|
+
bus.emit("send", { text, attachmentCount: attachments.length });
|
|
6456
|
+
if (suggestions.length > 0) setSuggestions([]);
|
|
6457
|
+
const uploaded = await uploadAttachments(transport, attachments, (err) => {
|
|
6458
|
+
log16.warn("upload failed", { err });
|
|
6459
|
+
bus.emit("error", err);
|
|
6460
|
+
options.onError?.(err);
|
|
6461
|
+
});
|
|
6462
|
+
feedback.unlock();
|
|
6463
|
+
feedback.play("messageSent");
|
|
6464
|
+
const userMsg = makeUserMessage(text, uploaded);
|
|
6465
|
+
const assistantMsg = makeAssistantMessage();
|
|
6466
|
+
messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
|
|
6467
|
+
reducer.attach(assistantMsg);
|
|
6468
|
+
emitMessage(bus, options, "user", text);
|
|
6469
|
+
await streamAssistant(assistantMsg, TRIGGER.submitMessage);
|
|
6470
|
+
},
|
|
6471
|
+
[streaming, transport, bus, options, suggestions.length, messagesSig, reducer, streamAssistant]
|
|
5511
6472
|
);
|
|
5512
6473
|
const handleStop = useCallback6(() => {
|
|
5513
6474
|
log16.info("stop");
|
|
@@ -5711,7 +6672,10 @@ function App({ options, hostElement, bus }) {
|
|
|
5711
6672
|
log16.info("suggestion", { text });
|
|
5712
6673
|
bus.emit("suggestion", { text });
|
|
5713
6674
|
void handleSend(text, []);
|
|
5714
|
-
}
|
|
6675
|
+
},
|
|
6676
|
+
intakePending,
|
|
6677
|
+
onIntakeComplete: handleIntakeComplete,
|
|
6678
|
+
tool: toolInteraction
|
|
5715
6679
|
};
|
|
5716
6680
|
const onSelectSession = (sessionId) => {
|
|
5717
6681
|
void handleSelectHistoryChat(sessionId);
|
|
@@ -5723,12 +6687,12 @@ function App({ options, hostElement, bus }) {
|
|
|
5723
6687
|
const renderSurface = (size) => {
|
|
5724
6688
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
5725
6689
|
if (enabledModules.length === 0) {
|
|
5726
|
-
return /* @__PURE__ */
|
|
6690
|
+
return /* @__PURE__ */ jsx37(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
5727
6691
|
}
|
|
5728
6692
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
5729
|
-
return /* @__PURE__ */
|
|
6693
|
+
return /* @__PURE__ */ jsx37(Panel, { ...panelProps, panelSize: size });
|
|
5730
6694
|
}
|
|
5731
|
-
return /* @__PURE__ */
|
|
6695
|
+
return /* @__PURE__ */ jsx37(
|
|
5732
6696
|
MessengerHome,
|
|
5733
6697
|
{
|
|
5734
6698
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
@@ -5746,7 +6710,7 @@ function App({ options, hostElement, bus }) {
|
|
|
5746
6710
|
void handleSelectHistoryChat(chat.sessionId);
|
|
5747
6711
|
};
|
|
5748
6712
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
5749
|
-
return /* @__PURE__ */
|
|
6713
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
5750
6714
|
PageShell,
|
|
5751
6715
|
{
|
|
5752
6716
|
site: parsedSite,
|
|
@@ -5765,15 +6729,15 @@ function App({ options, hostElement, bus }) {
|
|
|
5765
6729
|
}
|
|
5766
6730
|
if (isInlineLike) {
|
|
5767
6731
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
5768
|
-
return /* @__PURE__ */
|
|
6732
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
5769
6733
|
}
|
|
5770
6734
|
const drawerEdgeTab = options.mode === "drawer";
|
|
5771
6735
|
const triggerOwnedByPage = options.mode === "modal";
|
|
5772
6736
|
const launcherVisible = !triggerOwnedByPage && !options.launcher.hidden && (!isOpen || launcherLeaving);
|
|
5773
6737
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
5774
|
-
return /* @__PURE__ */
|
|
6738
|
+
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
5775
6739
|
isOpen ? renderSurface(panelSize) : null,
|
|
5776
|
-
launcherVisible ? /* @__PURE__ */
|
|
6740
|
+
launcherVisible ? /* @__PURE__ */ jsx37(
|
|
5777
6741
|
Launcher,
|
|
5778
6742
|
{
|
|
5779
6743
|
onToggle: handleOpen,
|
|
@@ -5783,7 +6747,7 @@ function App({ options, hostElement, bus }) {
|
|
|
5783
6747
|
edgeTab: drawerEdgeTab
|
|
5784
6748
|
}
|
|
5785
6749
|
) : null,
|
|
5786
|
-
calloutToRender ? /* @__PURE__ */
|
|
6750
|
+
calloutToRender ? /* @__PURE__ */ jsx37(
|
|
5787
6751
|
LauncherCallout,
|
|
5788
6752
|
{
|
|
5789
6753
|
callout: calloutToRender,
|
|
@@ -5982,6 +6946,10 @@ var EVENT_NAMES = [
|
|
|
5982
6946
|
"selectChat",
|
|
5983
6947
|
"suggestion",
|
|
5984
6948
|
"toggleHistory",
|
|
6949
|
+
// Forms + human-in-the-loop
|
|
6950
|
+
"intakeSubmit",
|
|
6951
|
+
"toolResult",
|
|
6952
|
+
"toolDecision",
|
|
5985
6953
|
// Composer / attachments / voice
|
|
5986
6954
|
"attach",
|
|
5987
6955
|
"removeAttachment",
|