@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/web-component.mjs
CHANGED
|
@@ -6,8 +6,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
6
6
|
import { h as h2, render as render2 } 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
|
};
|
|
@@ -293,11 +432,14 @@ var DEFAULT_ATTACHMENTS = {
|
|
|
293
432
|
var DEFAULT_WELCOME = { animation: "typewriter", speed: 60 };
|
|
294
433
|
var DEFAULT_FEATURES = {
|
|
295
434
|
files: true,
|
|
296
|
-
voice: "local"
|
|
435
|
+
voice: "local",
|
|
436
|
+
humanInLoop: true
|
|
297
437
|
};
|
|
438
|
+
var DEFAULT_INTAKE = { enabled: false, fields: [], skippable: false };
|
|
298
439
|
var DEFAULT_ENDPOINTS = {
|
|
299
440
|
upload: "/ai/agent/upload-file",
|
|
300
|
-
transcribe: "/ai/agent/transcribe-audio"
|
|
441
|
+
transcribe: "/ai/agent/transcribe-audio",
|
|
442
|
+
intake: "/ai/agent/intake"
|
|
301
443
|
};
|
|
302
444
|
var DEFAULT_LAUNCHER = {
|
|
303
445
|
variant: "circle",
|
|
@@ -359,11 +501,14 @@ function resolveOptions(rawOpts) {
|
|
|
359
501
|
features: {
|
|
360
502
|
files: opts.features?.files ?? DEFAULT_FEATURES.files,
|
|
361
503
|
voice: opts.features?.voice ?? DEFAULT_FEATURES.voice,
|
|
504
|
+
humanInLoop: opts.features?.humanInLoop ?? DEFAULT_FEATURES.humanInLoop,
|
|
362
505
|
tools: opts.features?.tools
|
|
363
506
|
},
|
|
507
|
+
intake: resolveIntake(opts.intake),
|
|
364
508
|
endpoints: {
|
|
365
509
|
upload: opts.endpoints?.upload ?? DEFAULT_ENDPOINTS.upload,
|
|
366
|
-
transcribe: opts.endpoints?.transcribe ?? DEFAULT_ENDPOINTS.transcribe
|
|
510
|
+
transcribe: opts.endpoints?.transcribe ?? DEFAULT_ENDPOINTS.transcribe,
|
|
511
|
+
intake: opts.endpoints?.intake ?? DEFAULT_ENDPOINTS.intake
|
|
367
512
|
},
|
|
368
513
|
attachments: {
|
|
369
514
|
accept: opts.composer?.attachments?.accept ?? DEFAULT_ATTACHMENTS.accept,
|
|
@@ -462,6 +607,18 @@ function resolveModules(overrides) {
|
|
|
462
607
|
const byId = Object.fromEntries(list.map((m) => [m.id, m]));
|
|
463
608
|
return { list, byId };
|
|
464
609
|
}
|
|
610
|
+
function resolveIntake(overrides) {
|
|
611
|
+
const fields = (overrides?.fields ?? []).filter((f) => Boolean(f && f.name && f.label && f.type));
|
|
612
|
+
if (fields.length === 0) return DEFAULT_INTAKE;
|
|
613
|
+
return {
|
|
614
|
+
enabled: overrides?.enabled ?? false,
|
|
615
|
+
title: overrides?.title,
|
|
616
|
+
description: overrides?.description,
|
|
617
|
+
fields,
|
|
618
|
+
submitLabel: overrides?.submitLabel,
|
|
619
|
+
skippable: overrides?.skippable ?? false
|
|
620
|
+
};
|
|
621
|
+
}
|
|
465
622
|
function resolveLauncher(overrides) {
|
|
466
623
|
const callout = overrides?.callout?.text ? {
|
|
467
624
|
shape: "pill",
|
|
@@ -507,6 +664,7 @@ var SECTION_KEYS = [
|
|
|
507
664
|
"i18n",
|
|
508
665
|
"footer",
|
|
509
666
|
"features",
|
|
667
|
+
"intake",
|
|
510
668
|
"endpoints"
|
|
511
669
|
];
|
|
512
670
|
function mergeServerConfig(user, server) {
|
|
@@ -658,55 +816,55 @@ var REACTIVE_ATTRS = [
|
|
|
658
816
|
];
|
|
659
817
|
function parseAttributes(get) {
|
|
660
818
|
const opts = {};
|
|
661
|
-
const
|
|
819
|
+
const str2 = (name) => {
|
|
662
820
|
const v = get(name);
|
|
663
821
|
return v === null || v === "" ? void 0 : v;
|
|
664
822
|
};
|
|
665
823
|
for (const [attr, key, cast] of EMBED_SCALAR_ATTRS) {
|
|
666
|
-
const raw =
|
|
824
|
+
const raw = str2(attr);
|
|
667
825
|
if (raw === void 0) continue;
|
|
668
826
|
opts[key] = cast ? cast(raw) : raw;
|
|
669
827
|
}
|
|
670
|
-
const presentationFlat = collectSubset(
|
|
671
|
-
const size = collectSubset(
|
|
828
|
+
const presentationFlat = collectSubset(str2, PRESENTATION_ATTRS);
|
|
829
|
+
const size = collectSubset(str2, PRESENTATION_SIZE_ATTRS);
|
|
672
830
|
if (presentationFlat || size) {
|
|
673
831
|
opts.presentation = { ...presentationFlat, ...size ? { size } : {} };
|
|
674
832
|
}
|
|
675
|
-
const behavior = collectSubset(
|
|
833
|
+
const behavior = collectSubset(str2, BEHAVIOR_ATTRS);
|
|
676
834
|
if (behavior) opts.behavior = behavior;
|
|
677
|
-
const i18n = collectSubset(
|
|
835
|
+
const i18n = collectSubset(str2, I18N_ATTRS);
|
|
678
836
|
if (i18n) opts.i18n = i18n;
|
|
679
|
-
const launcher = parseLauncher(get,
|
|
837
|
+
const launcher = parseLauncher(get, str2);
|
|
680
838
|
if (launcher) opts.launcher = launcher;
|
|
681
|
-
const features = collectSubset(
|
|
839
|
+
const features = collectSubset(str2, FEATURE_ATTRS);
|
|
682
840
|
if (features) opts.features = features;
|
|
683
|
-
const endpoints = collectSubset(
|
|
841
|
+
const endpoints = collectSubset(str2, ENDPOINT_ATTRS);
|
|
684
842
|
if (endpoints) opts.endpoints = endpoints;
|
|
685
|
-
const userContext = collectContext(
|
|
843
|
+
const userContext = collectContext(str2, USER_CONTEXT_ATTRS, "user-context");
|
|
686
844
|
if (userContext) opts.userContext = userContext;
|
|
687
|
-
const pageContext = collectContext(
|
|
845
|
+
const pageContext = collectContext(str2, PAGE_CONTEXT_ATTRS, "page-context");
|
|
688
846
|
if (pageContext) opts.pageContext = pageContext;
|
|
689
|
-
const actionsRaw =
|
|
847
|
+
const actionsRaw = str2("actions");
|
|
690
848
|
if (actionsRaw !== void 0) opts.header = { actions: onlyValidActions(actionsRaw) };
|
|
691
849
|
return opts;
|
|
692
850
|
}
|
|
693
|
-
function collectSubset(
|
|
851
|
+
function collectSubset(str2, table) {
|
|
694
852
|
const out = {};
|
|
695
853
|
for (const [attr, key, cast] of table) {
|
|
696
|
-
const raw =
|
|
854
|
+
const raw = str2(attr);
|
|
697
855
|
if (raw === void 0) continue;
|
|
698
856
|
out[key] = cast ? cast(raw) : raw;
|
|
699
857
|
}
|
|
700
858
|
return Object.keys(out).length > 0 ? out : null;
|
|
701
859
|
}
|
|
702
|
-
function collectContext(
|
|
860
|
+
function collectContext(str2, table, jsonAttr) {
|
|
703
861
|
const scalars = {};
|
|
704
862
|
for (const [attr, key] of table) {
|
|
705
|
-
const raw =
|
|
863
|
+
const raw = str2(attr);
|
|
706
864
|
if (raw !== void 0) scalars[key] = raw;
|
|
707
865
|
}
|
|
708
866
|
let fromJson = {};
|
|
709
|
-
const jsonRaw =
|
|
867
|
+
const jsonRaw = str2(jsonAttr);
|
|
710
868
|
if (jsonRaw) {
|
|
711
869
|
try {
|
|
712
870
|
const parsed = JSON.parse(jsonRaw);
|
|
@@ -717,13 +875,13 @@ function collectContext(str, table, jsonAttr) {
|
|
|
717
875
|
const out = { ...fromJson, ...scalars };
|
|
718
876
|
return Object.keys(out).length > 0 ? out : null;
|
|
719
877
|
}
|
|
720
|
-
function parseLauncher(get,
|
|
721
|
-
const base = collectSubset(
|
|
878
|
+
function parseLauncher(get, str2) {
|
|
879
|
+
const base = collectSubset(str2, LAUNCHER_ATTRS) ?? {};
|
|
722
880
|
const label = get("launcher-label");
|
|
723
881
|
if (label !== null) base.label = label;
|
|
724
|
-
const text =
|
|
882
|
+
const text = str2("callout-text");
|
|
725
883
|
if (text) {
|
|
726
|
-
const delay = Number.parseInt(
|
|
884
|
+
const delay = Number.parseInt(str2("callout-delay") ?? "", 10);
|
|
727
885
|
base.callout = { text, ...Number.isFinite(delay) ? { delayMs: delay } : {} };
|
|
728
886
|
}
|
|
729
887
|
return Object.keys(base).length > 0 ? base : null;
|
|
@@ -767,7 +925,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
767
925
|
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';
|
|
768
926
|
|
|
769
927
|
// src/styles/panel.css
|
|
770
|
-
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';
|
|
928
|
+
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';
|
|
771
929
|
|
|
772
930
|
// src/styles/standalone.css
|
|
773
931
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -855,22 +1013,22 @@ function attachAdoptedSheet(shadow, doc) {
|
|
|
855
1013
|
}
|
|
856
1014
|
}
|
|
857
1015
|
function applyThemeOverrides(host, overrides) {
|
|
858
|
-
const
|
|
859
|
-
if (overrides.accent) host.style.setProperty(`--${
|
|
860
|
-
if (overrides.accentText) host.style.setProperty(`--${
|
|
861
|
-
if (overrides.radius) host.style.setProperty(`--${
|
|
862
|
-
if (overrides.fontFamily) host.style.setProperty(`--${
|
|
1016
|
+
const p33 = BRAND.cssPrefix;
|
|
1017
|
+
if (overrides.accent) host.style.setProperty(`--${p33}-accent`, overrides.accent);
|
|
1018
|
+
if (overrides.accentText) host.style.setProperty(`--${p33}-accent-text`, overrides.accentText);
|
|
1019
|
+
if (overrides.radius) host.style.setProperty(`--${p33}-radius`, overrides.radius);
|
|
1020
|
+
if (overrides.fontFamily) host.style.setProperty(`--${p33}-font`, overrides.fontFamily);
|
|
863
1021
|
}
|
|
864
1022
|
function applyThemeMode(host, mode) {
|
|
865
1023
|
host.dataset.theme = mode;
|
|
866
1024
|
}
|
|
867
1025
|
function applySize(host, size) {
|
|
868
|
-
const
|
|
869
|
-
if (size.width !== void 0) host.style.setProperty(`--${
|
|
870
|
-
if (size.height !== void 0) host.style.setProperty(`--${
|
|
871
|
-
if (size.expanded?.width !== void 0) host.style.setProperty(`--${
|
|
872
|
-
if (size.expanded?.height !== void 0) host.style.setProperty(`--${
|
|
873
|
-
if (size.inset !== void 0) host.style.setProperty(`--${
|
|
1026
|
+
const p33 = BRAND.cssPrefix;
|
|
1027
|
+
if (size.width !== void 0) host.style.setProperty(`--${p33}-panel-w`, size.width);
|
|
1028
|
+
if (size.height !== void 0) host.style.setProperty(`--${p33}-panel-h`, size.height);
|
|
1029
|
+
if (size.expanded?.width !== void 0) host.style.setProperty(`--${p33}-expanded-w`, size.expanded.width);
|
|
1030
|
+
if (size.expanded?.height !== void 0) host.style.setProperty(`--${p33}-expanded-h`, size.expanded.height);
|
|
1031
|
+
if (size.inset !== void 0) host.style.setProperty(`--${p33}-panel-inset`, size.inset);
|
|
874
1032
|
}
|
|
875
1033
|
function applyPosition(host, pos) {
|
|
876
1034
|
host.dataset.position = pos;
|
|
@@ -1041,11 +1199,11 @@ function toBase64Url(json) {
|
|
|
1041
1199
|
var nonEmpty = (ctx) => ctx && Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
1042
1200
|
function encodeContext(user, page) {
|
|
1043
1201
|
const u = nonEmpty(user);
|
|
1044
|
-
const
|
|
1045
|
-
if (!u && !
|
|
1202
|
+
const p33 = nonEmpty(page);
|
|
1203
|
+
if (!u && !p33) return void 0;
|
|
1046
1204
|
const envelope = {};
|
|
1047
1205
|
if (u) envelope.user = u;
|
|
1048
|
-
if (
|
|
1206
|
+
if (p33) envelope.page = p33;
|
|
1049
1207
|
return toBase64Url(JSON.stringify(envelope));
|
|
1050
1208
|
}
|
|
1051
1209
|
|
|
@@ -1084,7 +1242,15 @@ var DEFAULT_PATHS = {
|
|
|
1084
1242
|
markRead: "/ai/agent/mark-read",
|
|
1085
1243
|
// ── CMS content (unified — Home / Help / News / docs) ─────────────
|
|
1086
1244
|
/** All widget content via one filtered endpoint. `GET /ai/agent/content?tags=…`. */
|
|
1087
|
-
content: "/ai/agent/content"
|
|
1245
|
+
content: "/ai/agent/content",
|
|
1246
|
+
/**
|
|
1247
|
+
* Optional pre-chat intake submission. POST `{ visitorId, sessionId, values,
|
|
1248
|
+
* skipped? }` → record the lead immediately (before/independent of the first
|
|
1249
|
+
* message), keyed by the same visitor + session as the conversation.
|
|
1250
|
+
* Overridable via `endpoints.intake`. Fire-and-forget; 404 on older backends
|
|
1251
|
+
* is ignored.
|
|
1252
|
+
*/
|
|
1253
|
+
intake: "/ai/agent/intake"
|
|
1088
1254
|
};
|
|
1089
1255
|
var CONTEXT_PARAM = "context";
|
|
1090
1256
|
function buildSendMessageRequest(params) {
|
|
@@ -1108,18 +1274,34 @@ function buildSendMessageRequest(params) {
|
|
|
1108
1274
|
if (Object.keys(data).length > 0) body.data = data;
|
|
1109
1275
|
return body;
|
|
1110
1276
|
}
|
|
1277
|
+
function isResolvedToolPart(p33) {
|
|
1278
|
+
return p33.state === "output" || p33.state === "error" || p33.approval?.approved !== void 0;
|
|
1279
|
+
}
|
|
1111
1280
|
function normalizeToolRef(ref) {
|
|
1112
1281
|
if (typeof ref === "string") return ref ? { code: ref } : null;
|
|
1113
1282
|
return ref?.code ? ref : null;
|
|
1114
1283
|
}
|
|
1115
1284
|
function messageToWireParts(m) {
|
|
1116
1285
|
const out = [];
|
|
1117
|
-
for (const
|
|
1118
|
-
if (
|
|
1119
|
-
out.push({ text:
|
|
1286
|
+
for (const p33 of m.parts) {
|
|
1287
|
+
if (p33.kind === "text" && p33.text) {
|
|
1288
|
+
out.push({ text: p33.text, type: "text" });
|
|
1120
1289
|
}
|
|
1121
|
-
if (
|
|
1122
|
-
out.push({ mediaType:
|
|
1290
|
+
if (p33.kind === "file" && p33.url) {
|
|
1291
|
+
out.push({ mediaType: p33.mediaType, type: "file", url: p33.url });
|
|
1292
|
+
}
|
|
1293
|
+
if (p33.kind === "tool" && isResolvedToolPart(p33)) {
|
|
1294
|
+
const part = {
|
|
1295
|
+
type: "tool",
|
|
1296
|
+
toolCallId: p33.toolCallId,
|
|
1297
|
+
toolName: p33.toolName,
|
|
1298
|
+
state: p33.state
|
|
1299
|
+
};
|
|
1300
|
+
if (p33.input !== void 0) part.input = p33.input;
|
|
1301
|
+
if (p33.output !== void 0) part.output = p33.output;
|
|
1302
|
+
if (p33.error !== void 0) part.errorText = p33.error;
|
|
1303
|
+
if (p33.approval && p33.approval.approved !== void 0) part.approval = p33.approval;
|
|
1304
|
+
out.push(part);
|
|
1123
1305
|
}
|
|
1124
1306
|
}
|
|
1125
1307
|
for (const a of m.attachments ?? []) {
|
|
@@ -1366,6 +1548,25 @@ var AgentTransport = class {
|
|
|
1366
1548
|
get transcribePath() {
|
|
1367
1549
|
return this.opts.endpoints?.transcribe ?? "/ai/agent/transcribe-audio";
|
|
1368
1550
|
}
|
|
1551
|
+
get intakePath() {
|
|
1552
|
+
return this.opts.endpoints?.intake ?? DEFAULT_PATHS.intake;
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Record a completed pre-chat intake form. Fire-and-forget — the lead is
|
|
1556
|
+
* captured even if the visitor never sends a message. `sessionId` is explicit
|
|
1557
|
+
* so the record ties to the conversation that follows; `visitorId` + context
|
|
1558
|
+
* ride the envelope. A failure (e.g. 404 on a backend that doesn't implement
|
|
1559
|
+
* the endpoint) is non-fatal — the values still reach the agent as
|
|
1560
|
+
* `userContext` on the next message, so callers don't await this.
|
|
1561
|
+
*/
|
|
1562
|
+
async submitIntake(sessionId, values, skipped = false) {
|
|
1563
|
+
log4.debug("submitIntake \u2192", { sessionId, fields: Object.keys(values).length, skipped });
|
|
1564
|
+
try {
|
|
1565
|
+
await this.postJson(this.intakePath, { sessionId, values, skipped }, "submitIntake");
|
|
1566
|
+
} catch (err) {
|
|
1567
|
+
log4.debug("submitIntake failed (non-fatal)", { err });
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1369
1570
|
sendMessage(body) {
|
|
1370
1571
|
log4.debug("message \u2192", {
|
|
1371
1572
|
sessionId: body.sessionId,
|
|
@@ -1679,8 +1880,21 @@ function fromWireMessage(w) {
|
|
|
1679
1880
|
if (part.type === "file") {
|
|
1680
1881
|
return { kind: "file", url: part.url, mediaType: part.mediaType };
|
|
1681
1882
|
}
|
|
1883
|
+
if (part.type === "tool") {
|
|
1884
|
+
return {
|
|
1885
|
+
kind: "tool",
|
|
1886
|
+
toolCallId: part.toolCallId,
|
|
1887
|
+
toolName: part.toolName,
|
|
1888
|
+
inputPartialSig: signal(""),
|
|
1889
|
+
inputSig: signal(part.input),
|
|
1890
|
+
outputSig: signal(part.output),
|
|
1891
|
+
errorSig: signal(part.errorText),
|
|
1892
|
+
stateSig: signal(part.state),
|
|
1893
|
+
approvalSig: signal(part.approval)
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1682
1896
|
return null;
|
|
1683
|
-
}).filter((
|
|
1897
|
+
}).filter((p33) => p33 !== null);
|
|
1684
1898
|
return {
|
|
1685
1899
|
id: w.id,
|
|
1686
1900
|
role: w.role,
|
|
@@ -1710,45 +1924,62 @@ function assistantText(m) {
|
|
|
1710
1924
|
}
|
|
1711
1925
|
return out;
|
|
1712
1926
|
}
|
|
1713
|
-
function partToReactive(
|
|
1714
|
-
if (
|
|
1715
|
-
return { kind:
|
|
1927
|
+
function partToReactive(p33) {
|
|
1928
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1929
|
+
return { kind: p33.kind, id: p33.id, textSig: signal(p33.text), doneSig: signal(p33.done) };
|
|
1716
1930
|
}
|
|
1717
|
-
if (
|
|
1931
|
+
if (p33.kind === "tool") {
|
|
1718
1932
|
return {
|
|
1719
1933
|
kind: "tool",
|
|
1720
|
-
toolCallId:
|
|
1721
|
-
toolName:
|
|
1722
|
-
inputPartialSig: signal(
|
|
1723
|
-
inputSig: signal(
|
|
1724
|
-
outputSig: signal(
|
|
1725
|
-
errorSig: signal(
|
|
1726
|
-
stateSig: signal(
|
|
1934
|
+
toolCallId: p33.toolCallId,
|
|
1935
|
+
toolName: p33.toolName,
|
|
1936
|
+
inputPartialSig: signal(p33.inputPartial),
|
|
1937
|
+
inputSig: signal(p33.input),
|
|
1938
|
+
outputSig: signal(p33.output),
|
|
1939
|
+
errorSig: signal(p33.error),
|
|
1940
|
+
stateSig: signal(p33.state),
|
|
1941
|
+
approvalSig: signal(p33.approval)
|
|
1727
1942
|
};
|
|
1728
1943
|
}
|
|
1729
|
-
return
|
|
1944
|
+
return p33;
|
|
1730
1945
|
}
|
|
1731
|
-
function partFromReactive(
|
|
1732
|
-
if (
|
|
1733
|
-
return { kind:
|
|
1946
|
+
function partFromReactive(p33) {
|
|
1947
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1948
|
+
return { kind: p33.kind, id: p33.id, text: p33.textSig.value, done: p33.doneSig.value };
|
|
1734
1949
|
}
|
|
1735
|
-
if (
|
|
1950
|
+
if (p33.kind === "tool") {
|
|
1736
1951
|
return {
|
|
1737
1952
|
kind: "tool",
|
|
1738
|
-
toolCallId:
|
|
1739
|
-
toolName:
|
|
1740
|
-
inputPartial:
|
|
1741
|
-
input:
|
|
1742
|
-
output:
|
|
1743
|
-
error:
|
|
1744
|
-
state:
|
|
1953
|
+
toolCallId: p33.toolCallId,
|
|
1954
|
+
toolName: p33.toolName,
|
|
1955
|
+
inputPartial: p33.inputPartialSig.value,
|
|
1956
|
+
input: p33.inputSig.value,
|
|
1957
|
+
output: p33.outputSig.value,
|
|
1958
|
+
error: p33.errorSig.value,
|
|
1959
|
+
state: p33.stateSig.value,
|
|
1960
|
+
approval: p33.approvalSig.value
|
|
1745
1961
|
};
|
|
1746
1962
|
}
|
|
1747
|
-
return
|
|
1963
|
+
return p33;
|
|
1748
1964
|
}
|
|
1749
1965
|
|
|
1750
1966
|
// src/stream/reducer.ts
|
|
1751
1967
|
import { signal as signal2 } from "@preact/signals";
|
|
1968
|
+
|
|
1969
|
+
// src/stream/constants.ts
|
|
1970
|
+
var ASK_USER_INPUT_TOOL = "tool:ask-user-input";
|
|
1971
|
+
function isAskUserInputTool(toolName) {
|
|
1972
|
+
if (!toolName) return false;
|
|
1973
|
+
const t = toolName.toLowerCase();
|
|
1974
|
+
return t === ASK_USER_INPUT_TOOL || t === "ask-user-input" || t === "ask_user_input";
|
|
1975
|
+
}
|
|
1976
|
+
var TRIGGER = {
|
|
1977
|
+
submitMessage: "submit-message",
|
|
1978
|
+
toolResult: "tool-result",
|
|
1979
|
+
toolApproval: "tool-approval"
|
|
1980
|
+
};
|
|
1981
|
+
|
|
1982
|
+
// src/stream/reducer.ts
|
|
1752
1983
|
var log5 = logger.scope("reducer");
|
|
1753
1984
|
var StreamReducer = class {
|
|
1754
1985
|
constructor(messagesSig) {
|
|
@@ -1786,8 +2017,8 @@ var StreamReducer = class {
|
|
|
1786
2017
|
ensureTextPart(m, "text", chunk.id);
|
|
1787
2018
|
return;
|
|
1788
2019
|
case "text-delta": {
|
|
1789
|
-
const
|
|
1790
|
-
|
|
2020
|
+
const p33 = ensureTextPart(m, "text", chunk.id);
|
|
2021
|
+
p33.textSig.value += chunk.delta;
|
|
1791
2022
|
return;
|
|
1792
2023
|
}
|
|
1793
2024
|
case "text-end":
|
|
@@ -1797,8 +2028,8 @@ var StreamReducer = class {
|
|
|
1797
2028
|
ensureTextPart(m, "reasoning", chunk.id).doneSig.value = false;
|
|
1798
2029
|
return;
|
|
1799
2030
|
case "reasoning-delta": {
|
|
1800
|
-
const
|
|
1801
|
-
|
|
2031
|
+
const p33 = ensureTextPart(m, "reasoning", chunk.id);
|
|
2032
|
+
p33.textSig.value += chunk.delta;
|
|
1802
2033
|
return;
|
|
1803
2034
|
}
|
|
1804
2035
|
case "reasoning-end":
|
|
@@ -1809,6 +2040,7 @@ var StreamReducer = class {
|
|
|
1809
2040
|
case "tool-input-available":
|
|
1810
2041
|
case "tool-output-available":
|
|
1811
2042
|
case "tool-output-error":
|
|
2043
|
+
case "tool-approval-request":
|
|
1812
2044
|
applyTool(m, chunk);
|
|
1813
2045
|
return;
|
|
1814
2046
|
case "file":
|
|
@@ -1816,7 +2048,7 @@ var StreamReducer = class {
|
|
|
1816
2048
|
return;
|
|
1817
2049
|
case "source-url": {
|
|
1818
2050
|
const parts = m.partsSig.value;
|
|
1819
|
-
if (parts.some((
|
|
2051
|
+
if (parts.some((p33) => p33.kind === "source" && p33.sourceId === chunk.sourceId)) return;
|
|
1820
2052
|
appendPart(m, { kind: "source", sourceId: chunk.sourceId, url: chunk.url, title: chunk.title });
|
|
1821
2053
|
return;
|
|
1822
2054
|
}
|
|
@@ -1840,14 +2072,14 @@ var StreamReducer = class {
|
|
|
1840
2072
|
}
|
|
1841
2073
|
};
|
|
1842
2074
|
function ensureTextPart(m, kind, id) {
|
|
1843
|
-
const existing = m.partsSig.value.find((
|
|
2075
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === kind && p33.id === id);
|
|
1844
2076
|
if (existing) return existing;
|
|
1845
2077
|
const part = { kind, id, textSig: signal2(""), doneSig: signal2(false) };
|
|
1846
2078
|
appendPart(m, part);
|
|
1847
2079
|
return part;
|
|
1848
2080
|
}
|
|
1849
2081
|
function ensureToolPart(m, toolCallId, toolName) {
|
|
1850
|
-
const existing = m.partsSig.value.find((
|
|
2082
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === "tool" && p33.toolCallId === toolCallId);
|
|
1851
2083
|
if (existing) return existing;
|
|
1852
2084
|
const part = {
|
|
1853
2085
|
kind: "tool",
|
|
@@ -1857,7 +2089,8 @@ function ensureToolPart(m, toolCallId, toolName) {
|
|
|
1857
2089
|
inputSig: signal2(void 0),
|
|
1858
2090
|
outputSig: signal2(void 0),
|
|
1859
2091
|
errorSig: signal2(void 0),
|
|
1860
|
-
stateSig: signal2("input")
|
|
2092
|
+
stateSig: signal2("input"),
|
|
2093
|
+
approvalSig: signal2(void 0)
|
|
1861
2094
|
};
|
|
1862
2095
|
appendPart(m, part);
|
|
1863
2096
|
return part;
|
|
@@ -1871,26 +2104,32 @@ function applyTool(m, chunk) {
|
|
|
1871
2104
|
ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
1872
2105
|
return;
|
|
1873
2106
|
case "tool-input-delta": {
|
|
1874
|
-
const
|
|
1875
|
-
|
|
2107
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2108
|
+
p33.inputPartialSig.value += chunk.delta;
|
|
1876
2109
|
return;
|
|
1877
2110
|
}
|
|
1878
2111
|
case "tool-input-available": {
|
|
1879
|
-
const
|
|
1880
|
-
|
|
1881
|
-
|
|
2112
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2113
|
+
p33.inputSig.value = chunk.input;
|
|
2114
|
+
p33.stateSig.value = isAskUserInputTool(p33.toolName) ? "awaiting-input" : "awaiting";
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
case "tool-approval-request": {
|
|
2118
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2119
|
+
p33.approvalSig.value = { id: chunk.approvalId };
|
|
2120
|
+
p33.stateSig.value = "awaiting-approval";
|
|
1882
2121
|
return;
|
|
1883
2122
|
}
|
|
1884
2123
|
case "tool-output-available": {
|
|
1885
|
-
const
|
|
1886
|
-
|
|
1887
|
-
|
|
2124
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2125
|
+
p33.outputSig.value = chunk.output;
|
|
2126
|
+
p33.stateSig.value = "output";
|
|
1888
2127
|
return;
|
|
1889
2128
|
}
|
|
1890
2129
|
case "tool-output-error": {
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
2130
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2131
|
+
p33.errorSig.value = chunk.errorText;
|
|
2132
|
+
p33.stateSig.value = "error";
|
|
1894
2133
|
return;
|
|
1895
2134
|
}
|
|
1896
2135
|
default:
|
|
@@ -1910,6 +2149,7 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
1910
2149
|
const KEY_CALLOUT_DISMISSED = `${prefix}.calloutDismissed`;
|
|
1911
2150
|
const KEY_SIDEBAR_COLLAPSED = `${prefix}.sidebarCollapsed`;
|
|
1912
2151
|
const KEY_ACTIVE_MODULE = `${prefix}.activeModule`;
|
|
2152
|
+
const KEY_INTAKE = `${prefix}.intake`;
|
|
1913
2153
|
const persistence = {
|
|
1914
2154
|
getVisitorId() {
|
|
1915
2155
|
const existing = storage.get(KEY_VISITOR);
|
|
@@ -1992,6 +2232,24 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
1992
2232
|
saveActiveModule(id) {
|
|
1993
2233
|
storage.set(KEY_ACTIVE_MODULE, id);
|
|
1994
2234
|
},
|
|
2235
|
+
loadIntake() {
|
|
2236
|
+
const raw = storage.get(KEY_INTAKE);
|
|
2237
|
+
if (!raw) return null;
|
|
2238
|
+
try {
|
|
2239
|
+
const parsed = JSON.parse(raw);
|
|
2240
|
+
return isPlainObject2(parsed) ? parsed : null;
|
|
2241
|
+
} catch (error) {
|
|
2242
|
+
log6.warn("loadIntake parse failed", { error });
|
|
2243
|
+
return null;
|
|
2244
|
+
}
|
|
2245
|
+
},
|
|
2246
|
+
saveIntake(values) {
|
|
2247
|
+
try {
|
|
2248
|
+
storage.set(KEY_INTAKE, JSON.stringify(values));
|
|
2249
|
+
} catch (error) {
|
|
2250
|
+
log6.warn("saveIntake serialise failed", { error });
|
|
2251
|
+
}
|
|
2252
|
+
},
|
|
1995
2253
|
clearSession() {
|
|
1996
2254
|
storage.remove(KEY_CHAT);
|
|
1997
2255
|
}
|
|
@@ -2533,7 +2791,30 @@ var TID = {
|
|
|
2533
2791
|
/** Help article row — suffix `-{id}`. */
|
|
2534
2792
|
helpArticle: `${p2}-help-article`,
|
|
2535
2793
|
/** News list item — suffix `-{id}`. */
|
|
2536
|
-
newsItem: `${p2}-news-item
|
|
2794
|
+
newsItem: `${p2}-news-item`,
|
|
2795
|
+
// ── Forms + human-in-the-loop (intake / ask-input / approval) ────
|
|
2796
|
+
/** Pre-chat intake form root (blocking gate). */
|
|
2797
|
+
intakeForm: `${p2}-intake-form`,
|
|
2798
|
+
/** Intake submit button. */
|
|
2799
|
+
intakeSubmit: `${p2}-intake-submit`,
|
|
2800
|
+
/** Intake skip button (only when `skippable`). */
|
|
2801
|
+
intakeSkip: `${p2}-intake-skip`,
|
|
2802
|
+
/** A single form field control — suffix `-{name}` at the JSX site. */
|
|
2803
|
+
formField: `${p2}-form-field`,
|
|
2804
|
+
/** Ask-input tool root (inline form in a message bubble). */
|
|
2805
|
+
toolAskInput: `${p2}-tool-ask-input`,
|
|
2806
|
+
/** Ask-input submit button. */
|
|
2807
|
+
toolInputSubmit: `${p2}-tool-input-submit`,
|
|
2808
|
+
/** Ask-input skip button. */
|
|
2809
|
+
toolInputSkip: `${p2}-tool-input-skip`,
|
|
2810
|
+
/** Tool-approval root (approve/reject prompt). */
|
|
2811
|
+
toolApproval: `${p2}-tool-approval`,
|
|
2812
|
+
/** Tool-approval approve button. */
|
|
2813
|
+
toolApprove: `${p2}-tool-approve`,
|
|
2814
|
+
/** Tool-approval reject button. */
|
|
2815
|
+
toolReject: `${p2}-tool-reject`,
|
|
2816
|
+
/** Recorded tool decision summary (after approve/reject/submit). */
|
|
2817
|
+
toolDecision: `${p2}-tool-decision`
|
|
2537
2818
|
};
|
|
2538
2819
|
function tid(base, suffix) {
|
|
2539
2820
|
return `${base}-${suffix}`;
|
|
@@ -2644,24 +2925,24 @@ import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef
|
|
|
2644
2925
|
import { useEffect as useEffect2, useRef } from "preact/hooks";
|
|
2645
2926
|
import { jsx as jsx3 } from "preact/jsx-runtime";
|
|
2646
2927
|
function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, strings }) {
|
|
2647
|
-
const
|
|
2928
|
+
const p33 = BRAND.cssPrefix;
|
|
2648
2929
|
const dragRef = useRef(null);
|
|
2649
2930
|
useEffect2(() => {
|
|
2650
2931
|
if (!panelEl) return;
|
|
2651
2932
|
const style = panelEl.style;
|
|
2652
|
-
if (resize.minWidth) style.setProperty(`--${
|
|
2653
|
-
if (resize.maxWidth) style.setProperty(`--${
|
|
2654
|
-
if (resize.minHeight) style.setProperty(`--${
|
|
2655
|
-
if (resize.maxHeight) style.setProperty(`--${
|
|
2933
|
+
if (resize.minWidth) style.setProperty(`--${p33}-resize-min-w`, resize.minWidth);
|
|
2934
|
+
if (resize.maxWidth) style.setProperty(`--${p33}-resize-max-w`, resize.maxWidth);
|
|
2935
|
+
if (resize.minHeight) style.setProperty(`--${p33}-resize-min-h`, resize.minHeight);
|
|
2936
|
+
if (resize.maxHeight) style.setProperty(`--${p33}-resize-max-h`, resize.maxHeight);
|
|
2656
2937
|
if (initialSize) {
|
|
2657
|
-
style.setProperty(`--${
|
|
2658
|
-
style.setProperty(`--${
|
|
2938
|
+
style.setProperty(`--${p33}-widget-w`, `${initialSize.width}px`);
|
|
2939
|
+
style.setProperty(`--${p33}-widget-h`, `${initialSize.height}px`);
|
|
2659
2940
|
}
|
|
2660
|
-
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight,
|
|
2941
|
+
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight, p33, initialSize]);
|
|
2661
2942
|
if (!panelEl) return null;
|
|
2662
2943
|
const isTop = position.startsWith("top-");
|
|
2663
2944
|
const isRight = position.endsWith("-right");
|
|
2664
|
-
const cornerClass = `${
|
|
2945
|
+
const cornerClass = `${p33}-resize-grip ${p33}-resize-grip--${isTop ? "bottom" : "top"}-${isRight ? "left" : "right"}`;
|
|
2665
2946
|
const onPointerDown = (e) => {
|
|
2666
2947
|
if (!panelEl) return;
|
|
2667
2948
|
const target = e.currentTarget;
|
|
@@ -2685,8 +2966,8 @@ function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, stri
|
|
|
2685
2966
|
if (!d || e.pointerId !== d.pointerId || !panelEl) return;
|
|
2686
2967
|
const dx = (e.clientX - d.startX) * d.dirX;
|
|
2687
2968
|
const dy = (e.clientY - d.startY) * d.dirY;
|
|
2688
|
-
panelEl.style.setProperty(`--${
|
|
2689
|
-
panelEl.style.setProperty(`--${
|
|
2969
|
+
panelEl.style.setProperty(`--${p33}-widget-w`, `${d.startW + dx}px`);
|
|
2970
|
+
panelEl.style.setProperty(`--${p33}-widget-h`, `${d.startH + dy}px`);
|
|
2690
2971
|
};
|
|
2691
2972
|
const onPointerUp = (e) => {
|
|
2692
2973
|
const d = dragRef.current;
|
|
@@ -2723,7 +3004,7 @@ var KEEP_VISIBLE = 56;
|
|
|
2723
3004
|
function useDragMove(panelEl, enabled) {
|
|
2724
3005
|
useEffect3(() => {
|
|
2725
3006
|
if (!enabled || !panelEl) return;
|
|
2726
|
-
const
|
|
3007
|
+
const num2 = (v) => Number.parseFloat(v) || 0;
|
|
2727
3008
|
const clamp = (v, max) => Math.min(max, Math.max(-max, v));
|
|
2728
3009
|
let drag = null;
|
|
2729
3010
|
const onDown = (e) => {
|
|
@@ -2734,8 +3015,8 @@ function useDragMove(panelEl, enabled) {
|
|
|
2734
3015
|
id: e.pointerId,
|
|
2735
3016
|
x: e.clientX,
|
|
2736
3017
|
y: e.clientY,
|
|
2737
|
-
dx:
|
|
2738
|
-
dy:
|
|
3018
|
+
dx: num2(panelEl.style.getPropertyValue(`--${p4}-modal-dx`)),
|
|
3019
|
+
dy: num2(panelEl.style.getPropertyValue(`--${p4}-modal-dy`)),
|
|
2739
3020
|
// Centred origin: |offset| ≤ (viewport + panel)/2 − keepVisible keeps a
|
|
2740
3021
|
// strip of the dialog reachable so it can never be lost off-screen.
|
|
2741
3022
|
maxX: (window.innerWidth + rect.width) / 2 - KEEP_VISIBLE,
|
|
@@ -3421,20 +3702,20 @@ function usePopoverMenu({ itemCount, initialFocusIndex }) {
|
|
|
3421
3702
|
// src/ui/overflow-menu.tsx
|
|
3422
3703
|
import { jsx as jsx8, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
3423
3704
|
function OverflowMenu({ items, triggerLabel }) {
|
|
3424
|
-
const
|
|
3705
|
+
const p33 = BRAND.cssPrefix;
|
|
3425
3706
|
const menu = usePopoverMenu({ itemCount: items.length });
|
|
3426
3707
|
const handleSelect = (item) => {
|
|
3427
3708
|
if (item.disabled) return;
|
|
3428
3709
|
item.onSelect();
|
|
3429
3710
|
if (!item.keepOpen) menu.close();
|
|
3430
3711
|
};
|
|
3431
|
-
return /* @__PURE__ */ jsxs6("div", { class: `${
|
|
3712
|
+
return /* @__PURE__ */ jsxs6("div", { class: `${p33}-menu-wrap`, children: [
|
|
3432
3713
|
/* @__PURE__ */ jsx8(
|
|
3433
3714
|
"button",
|
|
3434
3715
|
{
|
|
3435
3716
|
ref: menu.triggerRef,
|
|
3436
3717
|
type: "button",
|
|
3437
|
-
class: `${
|
|
3718
|
+
class: `${p33}-icon-btn`,
|
|
3438
3719
|
"aria-label": triggerLabel,
|
|
3439
3720
|
"aria-haspopup": "menu",
|
|
3440
3721
|
"aria-expanded": menu.open,
|
|
@@ -3448,7 +3729,7 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3448
3729
|
"div",
|
|
3449
3730
|
{
|
|
3450
3731
|
ref: menu.menuRef,
|
|
3451
|
-
class: `${
|
|
3732
|
+
class: `${p33}-menu`,
|
|
3452
3733
|
role: "menu",
|
|
3453
3734
|
"aria-label": triggerLabel,
|
|
3454
3735
|
onKeyDown: menu.onMenuKey,
|
|
@@ -3458,15 +3739,15 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3458
3739
|
{
|
|
3459
3740
|
type: "button",
|
|
3460
3741
|
role: "menuitem",
|
|
3461
|
-
class: `${
|
|
3742
|
+
class: `${p33}-menu-item`,
|
|
3462
3743
|
"aria-pressed": item.type === "switch" ? item.on : void 0,
|
|
3463
3744
|
disabled: item.disabled,
|
|
3464
3745
|
lang: item.lang,
|
|
3465
3746
|
onClick: () => handleSelect(item),
|
|
3466
3747
|
children: [
|
|
3467
|
-
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3468
|
-
/* @__PURE__ */ jsx8("span", { class: `${
|
|
3469
|
-
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3748
|
+
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-icon`, children: item.icon }) : null,
|
|
3749
|
+
/* @__PURE__ */ jsx8("span", { class: `${p33}-menu-label`, children: item.label }),
|
|
3750
|
+
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-check`, "aria-hidden": "true", children: /* @__PURE__ */ jsx8(CheckIcon, {}) }) : null
|
|
3470
3751
|
]
|
|
3471
3752
|
},
|
|
3472
3753
|
item.id
|
|
@@ -3588,18 +3869,360 @@ function HeaderActions({ panelProps, variant }) {
|
|
|
3588
3869
|
] });
|
|
3589
3870
|
}
|
|
3590
3871
|
|
|
3872
|
+
// src/ui/form/dynamic-form.tsx
|
|
3873
|
+
import { useState as useState5 } from "preact/hooks";
|
|
3874
|
+
|
|
3875
|
+
// src/ui/form/validate.ts
|
|
3876
|
+
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3877
|
+
var URL_RE = /^https?:\/\/[^\s.]+\.[^\s]+$/i;
|
|
3878
|
+
var TEL_RE = /^[+]?[\d\s().-]{6,}$/;
|
|
3879
|
+
function fmt(template, vars) {
|
|
3880
|
+
return template.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? `{${k}}`));
|
|
3881
|
+
}
|
|
3882
|
+
function selectionCount(value) {
|
|
3883
|
+
if (Array.isArray(value)) return value.length;
|
|
3884
|
+
return value && value.trim() ? 1 : 0;
|
|
3885
|
+
}
|
|
3886
|
+
function validateField(field, value, strings) {
|
|
3887
|
+
const required = field.required ?? true;
|
|
3888
|
+
const v = field.validation;
|
|
3889
|
+
if (field.type === "multiselect") {
|
|
3890
|
+
const count = selectionCount(value);
|
|
3891
|
+
if (required && count === 0) return strings.formRequired;
|
|
3892
|
+
if (count === 0) return void 0;
|
|
3893
|
+
if (v?.minSelections != null && count < v.minSelections) {
|
|
3894
|
+
return fmt(strings.formChooseAtLeast, { min: v.minSelections });
|
|
3895
|
+
}
|
|
3896
|
+
if (v?.maxSelections != null && count > v.maxSelections) {
|
|
3897
|
+
return fmt(strings.formChooseAtMost, { max: v.maxSelections });
|
|
3898
|
+
}
|
|
3899
|
+
return void 0;
|
|
3900
|
+
}
|
|
3901
|
+
const text = typeof value === "string" ? value.trim() : "";
|
|
3902
|
+
if (!text) return required ? strings.formRequired : void 0;
|
|
3903
|
+
switch (field.type) {
|
|
3904
|
+
case "email":
|
|
3905
|
+
if (!EMAIL_RE2.test(text)) return strings.formInvalidEmail;
|
|
3906
|
+
break;
|
|
3907
|
+
case "url":
|
|
3908
|
+
if (!URL_RE.test(text)) return strings.formInvalidUrl;
|
|
3909
|
+
break;
|
|
3910
|
+
case "tel":
|
|
3911
|
+
if (!TEL_RE.test(text)) return strings.formInvalidTel;
|
|
3912
|
+
break;
|
|
3913
|
+
case "number": {
|
|
3914
|
+
const n = Number(text);
|
|
3915
|
+
if (!Number.isFinite(n)) return strings.formInvalidNumber;
|
|
3916
|
+
if (v?.min != null && n < v.min) return fmt(strings.formNumberTooSmall, { min: v.min });
|
|
3917
|
+
if (v?.max != null && n > v.max) return fmt(strings.formNumberTooLarge, { max: v.max });
|
|
3918
|
+
break;
|
|
3919
|
+
}
|
|
3920
|
+
default:
|
|
3921
|
+
break;
|
|
3922
|
+
}
|
|
3923
|
+
if (v?.minLength != null && text.length < v.minLength) return fmt(strings.formTooShort, { min: v.minLength });
|
|
3924
|
+
if (v?.maxLength != null && text.length > v.maxLength) return fmt(strings.formTooLong, { max: v.maxLength });
|
|
3925
|
+
if (v?.pattern) {
|
|
3926
|
+
try {
|
|
3927
|
+
if (!new RegExp(v.pattern).test(text)) return strings.formPatternMismatch;
|
|
3928
|
+
} catch {
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
return void 0;
|
|
3932
|
+
}
|
|
3933
|
+
function validateForm(fields, values, strings) {
|
|
3934
|
+
const errors = {};
|
|
3935
|
+
for (const field of fields) {
|
|
3936
|
+
const err = validateField(field, values[field.name], strings);
|
|
3937
|
+
if (err) errors[field.name] = err;
|
|
3938
|
+
}
|
|
3939
|
+
return errors;
|
|
3940
|
+
}
|
|
3941
|
+
function flattenValues(values) {
|
|
3942
|
+
const out = {};
|
|
3943
|
+
for (const [k, v] of Object.entries(values)) {
|
|
3944
|
+
const flat = Array.isArray(v) ? v.join(", ") : v;
|
|
3945
|
+
if (flat && flat.trim()) out[k] = flat.trim();
|
|
3946
|
+
}
|
|
3947
|
+
return out;
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3950
|
+
// src/ui/form/dynamic-form.tsx
|
|
3951
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
3952
|
+
var p10 = BRAND.cssPrefix;
|
|
3953
|
+
var OTHER = "__other__";
|
|
3954
|
+
function DynamicForm({
|
|
3955
|
+
fields,
|
|
3956
|
+
strings,
|
|
3957
|
+
submitLabel,
|
|
3958
|
+
onSubmit,
|
|
3959
|
+
skipLabel,
|
|
3960
|
+
onSkip,
|
|
3961
|
+
disabled,
|
|
3962
|
+
rootTestId,
|
|
3963
|
+
submitTestId,
|
|
3964
|
+
skipTestId
|
|
3965
|
+
}) {
|
|
3966
|
+
const [values, setValues] = useState5(() => seedValues(fields));
|
|
3967
|
+
const [other, setOther] = useState5({});
|
|
3968
|
+
const [errors, setErrors] = useState5({});
|
|
3969
|
+
const clearError = (name) => {
|
|
3970
|
+
if (errors[name]) setErrors((prev) => ({ ...prev, [name]: "" }));
|
|
3971
|
+
};
|
|
3972
|
+
const setValue = (name, v) => {
|
|
3973
|
+
setValues((prev) => ({ ...prev, [name]: v }));
|
|
3974
|
+
clearError(name);
|
|
3975
|
+
};
|
|
3976
|
+
const setOtherText = (name, t) => {
|
|
3977
|
+
setOther((prev) => ({ ...prev, [name]: t }));
|
|
3978
|
+
clearError(name);
|
|
3979
|
+
};
|
|
3980
|
+
const submit = (e) => {
|
|
3981
|
+
e.preventDefault();
|
|
3982
|
+
if (disabled) return;
|
|
3983
|
+
const resolved = resolveValues(fields, values, other);
|
|
3984
|
+
const errs = validateForm(fields, resolved, strings);
|
|
3985
|
+
if (Object.keys(errs).length > 0) {
|
|
3986
|
+
setErrors(errs);
|
|
3987
|
+
return;
|
|
3988
|
+
}
|
|
3989
|
+
onSubmit(flattenValues(resolved));
|
|
3990
|
+
};
|
|
3991
|
+
return /* @__PURE__ */ jsxs8("form", { class: `${p10}-form`, onSubmit: submit, "data-testid": rootTestId, noValidate: true, children: [
|
|
3992
|
+
fields.map((field) => /* @__PURE__ */ jsx10(
|
|
3993
|
+
Field,
|
|
3994
|
+
{
|
|
3995
|
+
field,
|
|
3996
|
+
value: values[field.name],
|
|
3997
|
+
otherText: other[field.name] ?? "",
|
|
3998
|
+
error: errors[field.name],
|
|
3999
|
+
disabled,
|
|
4000
|
+
strings,
|
|
4001
|
+
onChange: (v) => setValue(field.name, v),
|
|
4002
|
+
onOtherChange: (t) => setOtherText(field.name, t)
|
|
4003
|
+
},
|
|
4004
|
+
field.name
|
|
4005
|
+
)),
|
|
4006
|
+
/* @__PURE__ */ jsxs8("div", { class: `${p10}-form-actions`, children: [
|
|
4007
|
+
skipLabel && onSkip ? /* @__PURE__ */ jsx10("button", { type: "button", class: `${p10}-form-skip`, onClick: onSkip, disabled, "data-testid": skipTestId, children: skipLabel }) : null,
|
|
4008
|
+
/* @__PURE__ */ jsx10("button", { type: "submit", class: `${p10}-form-submit`, disabled, "data-testid": submitTestId, children: submitLabel })
|
|
4009
|
+
] })
|
|
4010
|
+
] });
|
|
4011
|
+
}
|
|
4012
|
+
function Field({
|
|
4013
|
+
field,
|
|
4014
|
+
value,
|
|
4015
|
+
otherText,
|
|
4016
|
+
error,
|
|
4017
|
+
disabled,
|
|
4018
|
+
strings,
|
|
4019
|
+
onChange,
|
|
4020
|
+
onOtherChange
|
|
4021
|
+
}) {
|
|
4022
|
+
const fieldTid = tid(TID.formField, field.name);
|
|
4023
|
+
const control = renderControl({ field, value, otherText, disabled, strings, onChange, onOtherChange, fieldTid });
|
|
4024
|
+
return /* @__PURE__ */ jsxs8("label", { class: `${p10}-field`, "data-field": field.name, "data-invalid": error ? "true" : void 0, children: [
|
|
4025
|
+
/* @__PURE__ */ jsxs8("span", { class: `${p10}-field-label`, children: [
|
|
4026
|
+
field.label,
|
|
4027
|
+
field.required ?? true ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-req`, "aria-hidden": "true", children: " *" }) : null
|
|
4028
|
+
] }),
|
|
4029
|
+
control,
|
|
4030
|
+
field.validationHint && !error ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-hint`, children: field.validationHint }) : null,
|
|
4031
|
+
error ? /* @__PURE__ */ jsx10("span", { class: `${p10}-field-error`, role: "alert", children: error }) : null
|
|
4032
|
+
] });
|
|
4033
|
+
}
|
|
4034
|
+
function renderControl(args) {
|
|
4035
|
+
const { field, value, otherText, disabled, strings, onChange, onOtherChange, fieldTid } = args;
|
|
4036
|
+
const str2 = typeof value === "string" ? value : "";
|
|
4037
|
+
switch (field.type) {
|
|
4038
|
+
case "textarea":
|
|
4039
|
+
return /* @__PURE__ */ jsx10(
|
|
4040
|
+
"textarea",
|
|
4041
|
+
{
|
|
4042
|
+
class: `${p10}-field-input`,
|
|
4043
|
+
rows: 3,
|
|
4044
|
+
value: str2,
|
|
4045
|
+
placeholder: field.placeholder,
|
|
4046
|
+
disabled,
|
|
4047
|
+
onInput: (e) => onChange(e.target.value),
|
|
4048
|
+
"data-testid": fieldTid
|
|
4049
|
+
}
|
|
4050
|
+
);
|
|
4051
|
+
case "select":
|
|
4052
|
+
return /* @__PURE__ */ jsxs8(
|
|
4053
|
+
"select",
|
|
4054
|
+
{
|
|
4055
|
+
class: `${p10}-field-input`,
|
|
4056
|
+
value: str2,
|
|
4057
|
+
disabled,
|
|
4058
|
+
onChange: (e) => onChange(e.target.value),
|
|
4059
|
+
"data-testid": fieldTid,
|
|
4060
|
+
children: [
|
|
4061
|
+
/* @__PURE__ */ jsx10("option", { value: "", children: field.placeholder ?? "\u2014" }),
|
|
4062
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsx10("option", { value: o.value, children: o.label ?? o.value }, o.value))
|
|
4063
|
+
]
|
|
4064
|
+
}
|
|
4065
|
+
);
|
|
4066
|
+
case "radio": {
|
|
4067
|
+
const isOther = field.allowOther && str2 === OTHER;
|
|
4068
|
+
return /* @__PURE__ */ jsxs8("div", { class: `${p10}-field-choices`, role: "radiogroup", "data-testid": fieldTid, children: [
|
|
4069
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4070
|
+
/* @__PURE__ */ jsx10(
|
|
4071
|
+
"input",
|
|
4072
|
+
{
|
|
4073
|
+
type: "radio",
|
|
4074
|
+
name: `${p10}-${field.name}`,
|
|
4075
|
+
checked: str2 === o.value,
|
|
4076
|
+
disabled,
|
|
4077
|
+
onChange: () => onChange(o.value)
|
|
4078
|
+
}
|
|
4079
|
+
),
|
|
4080
|
+
/* @__PURE__ */ jsx10("span", { children: o.label ?? o.value })
|
|
4081
|
+
] }, o.value)),
|
|
4082
|
+
field.allowOther ? /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4083
|
+
/* @__PURE__ */ jsx10(
|
|
4084
|
+
"input",
|
|
4085
|
+
{
|
|
4086
|
+
type: "radio",
|
|
4087
|
+
name: `${p10}-${field.name}`,
|
|
4088
|
+
checked: str2 === OTHER,
|
|
4089
|
+
disabled,
|
|
4090
|
+
onChange: () => onChange(OTHER)
|
|
4091
|
+
}
|
|
4092
|
+
),
|
|
4093
|
+
/* @__PURE__ */ jsx10("span", { children: strings.formOther })
|
|
4094
|
+
] }) : null,
|
|
4095
|
+
isOther ? /* @__PURE__ */ jsx10(
|
|
4096
|
+
"input",
|
|
4097
|
+
{
|
|
4098
|
+
class: `${p10}-field-input`,
|
|
4099
|
+
value: otherText,
|
|
4100
|
+
placeholder: field.placeholder ?? strings.formOtherPlaceholder,
|
|
4101
|
+
disabled,
|
|
4102
|
+
onInput: (e) => onOtherChange(e.target.value)
|
|
4103
|
+
}
|
|
4104
|
+
) : null
|
|
4105
|
+
] });
|
|
4106
|
+
}
|
|
4107
|
+
case "checkbox":
|
|
4108
|
+
return /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4109
|
+
/* @__PURE__ */ jsx10(
|
|
4110
|
+
"input",
|
|
4111
|
+
{
|
|
4112
|
+
type: "checkbox",
|
|
4113
|
+
checked: str2 === "true",
|
|
4114
|
+
disabled,
|
|
4115
|
+
onChange: (e) => onChange(e.target.checked ? "true" : ""),
|
|
4116
|
+
"data-testid": fieldTid
|
|
4117
|
+
}
|
|
4118
|
+
),
|
|
4119
|
+
/* @__PURE__ */ jsx10("span", { children: field.placeholder ?? field.label })
|
|
4120
|
+
] });
|
|
4121
|
+
case "multiselect": {
|
|
4122
|
+
const selected = Array.isArray(value) ? value : [];
|
|
4123
|
+
const toggle = (v, on) => onChange(on ? [...selected, v] : selected.filter((x) => x !== v));
|
|
4124
|
+
return /* @__PURE__ */ jsxs8("div", { class: `${p10}-field-choices`, "data-testid": fieldTid, children: [
|
|
4125
|
+
(field.options ?? []).map((o) => /* @__PURE__ */ jsxs8("label", { class: `${p10}-choice`, children: [
|
|
4126
|
+
/* @__PURE__ */ jsx10(
|
|
4127
|
+
"input",
|
|
4128
|
+
{
|
|
4129
|
+
type: "checkbox",
|
|
4130
|
+
checked: selected.includes(o.value),
|
|
4131
|
+
disabled,
|
|
4132
|
+
onChange: (e) => toggle(o.value, e.target.checked)
|
|
4133
|
+
}
|
|
4134
|
+
),
|
|
4135
|
+
/* @__PURE__ */ jsx10("span", { children: o.label ?? o.value })
|
|
4136
|
+
] }, o.value)),
|
|
4137
|
+
field.allowOther || (field.options ?? []).length === 0 ? /* @__PURE__ */ jsx10(
|
|
4138
|
+
"textarea",
|
|
4139
|
+
{
|
|
4140
|
+
class: `${p10}-field-input`,
|
|
4141
|
+
rows: 2,
|
|
4142
|
+
value: otherText,
|
|
4143
|
+
placeholder: field.placeholder ?? strings.formOtherPlaceholder,
|
|
4144
|
+
disabled,
|
|
4145
|
+
onInput: (e) => onOtherChange(e.target.value)
|
|
4146
|
+
}
|
|
4147
|
+
) : null
|
|
4148
|
+
] });
|
|
4149
|
+
}
|
|
4150
|
+
default:
|
|
4151
|
+
return /* @__PURE__ */ jsx10(
|
|
4152
|
+
"input",
|
|
4153
|
+
{
|
|
4154
|
+
class: `${p10}-field-input`,
|
|
4155
|
+
type: inputType(field.type),
|
|
4156
|
+
value: str2,
|
|
4157
|
+
placeholder: field.placeholder,
|
|
4158
|
+
disabled,
|
|
4159
|
+
onInput: (e) => onChange(e.target.value),
|
|
4160
|
+
"data-testid": fieldTid
|
|
4161
|
+
}
|
|
4162
|
+
);
|
|
4163
|
+
}
|
|
4164
|
+
}
|
|
4165
|
+
function inputType(type) {
|
|
4166
|
+
return type === "number" || type === "email" || type === "tel" || type === "url" ? type : "text";
|
|
4167
|
+
}
|
|
4168
|
+
function seedValues(fields) {
|
|
4169
|
+
const out = {};
|
|
4170
|
+
for (const f of fields) {
|
|
4171
|
+
if (f.defaultValue == null) continue;
|
|
4172
|
+
out[f.name] = f.type === "multiselect" ? f.defaultValue.split(",").map((s) => s.trim()).filter(Boolean) : f.defaultValue;
|
|
4173
|
+
}
|
|
4174
|
+
return out;
|
|
4175
|
+
}
|
|
4176
|
+
function resolveValues(fields, values, other) {
|
|
4177
|
+
const out = { ...values };
|
|
4178
|
+
for (const f of fields) {
|
|
4179
|
+
const otherText = other[f.name]?.trim();
|
|
4180
|
+
if (f.type === "radio" && f.allowOther && values[f.name] === OTHER) {
|
|
4181
|
+
out[f.name] = otherText ?? "";
|
|
4182
|
+
} else if (f.type === "multiselect" && otherText) {
|
|
4183
|
+
const tokens = otherText.split(/[,\n;]+/).map((t) => t.trim()).filter(Boolean);
|
|
4184
|
+
const base = Array.isArray(values[f.name]) ? values[f.name] : [];
|
|
4185
|
+
out[f.name] = [...base, ...tokens];
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
return out;
|
|
4189
|
+
}
|
|
4190
|
+
|
|
4191
|
+
// src/ui/intake-gate.tsx
|
|
4192
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
4193
|
+
var p11 = BRAND.cssPrefix;
|
|
4194
|
+
function IntakeGate({ intake, strings, onComplete }) {
|
|
4195
|
+
return /* @__PURE__ */ jsxs9("div", { class: `${p11}-intake`, "data-testid": TID.intakeForm, children: [
|
|
4196
|
+
intake.title ? /* @__PURE__ */ jsx11("h3", { class: `${p11}-intake-title`, children: intake.title }) : null,
|
|
4197
|
+
intake.description ? /* @__PURE__ */ jsx11("p", { class: `${p11}-intake-desc`, children: intake.description }) : null,
|
|
4198
|
+
/* @__PURE__ */ jsx11(
|
|
4199
|
+
DynamicForm,
|
|
4200
|
+
{
|
|
4201
|
+
fields: intake.fields,
|
|
4202
|
+
strings,
|
|
4203
|
+
submitLabel: intake.submitLabel ?? strings.intakeSubmit,
|
|
4204
|
+
onSubmit: onComplete,
|
|
4205
|
+
skipLabel: intake.skippable ? strings.intakeSkip : void 0,
|
|
4206
|
+
onSkip: intake.skippable ? () => onComplete({}) : void 0,
|
|
4207
|
+
submitTestId: TID.intakeSubmit,
|
|
4208
|
+
skipTestId: TID.intakeSkip
|
|
4209
|
+
}
|
|
4210
|
+
)
|
|
4211
|
+
] });
|
|
4212
|
+
}
|
|
4213
|
+
|
|
3591
4214
|
// src/ui/message-list.tsx
|
|
3592
|
-
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as
|
|
3593
|
-
import { useComputed as
|
|
4215
|
+
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as useState6 } from "preact/hooks";
|
|
4216
|
+
import { useComputed as useComputed5 } from "@preact/signals";
|
|
3594
4217
|
|
|
3595
4218
|
// src/ui/message-bubble.tsx
|
|
3596
|
-
import { useComputed as
|
|
4219
|
+
import { useComputed as useComputed4 } from "@preact/signals";
|
|
3597
4220
|
|
|
3598
4221
|
// src/ui/markdown.tsx
|
|
3599
4222
|
import { useEffect as useEffect7, useMemo, useRef as useRef4 } from "preact/hooks";
|
|
3600
4223
|
import { effect, signal as signal4 } from "@preact/signals";
|
|
3601
4224
|
import * as smd from "streaming-markdown";
|
|
3602
|
-
import { jsx as
|
|
4225
|
+
import { jsx as jsx12 } from "preact/jsx-runtime";
|
|
3603
4226
|
function MarkdownView({ textSig, doneSig }) {
|
|
3604
4227
|
const ref = useRef4(null);
|
|
3605
4228
|
useEffect7(() => {
|
|
@@ -3649,12 +4272,12 @@ function MarkdownView({ textSig, doneSig }) {
|
|
|
3649
4272
|
el.removeEventListener("click", onClick);
|
|
3650
4273
|
};
|
|
3651
4274
|
}, [textSig, doneSig]);
|
|
3652
|
-
return /* @__PURE__ */
|
|
4275
|
+
return /* @__PURE__ */ jsx12("div", { ref });
|
|
3653
4276
|
}
|
|
3654
4277
|
function StaticMarkdown({ text }) {
|
|
3655
4278
|
const textSig = useMemo(() => signal4(text), [text]);
|
|
3656
4279
|
const doneSig = useMemo(() => signal4(true), []);
|
|
3657
|
-
return /* @__PURE__ */
|
|
4280
|
+
return /* @__PURE__ */ jsx12(MarkdownView, { textSig, doneSig });
|
|
3658
4281
|
}
|
|
3659
4282
|
function hardenLink(a) {
|
|
3660
4283
|
const href = a.getAttribute("href") ?? "";
|
|
@@ -3666,29 +4289,247 @@ function hardenLink(a) {
|
|
|
3666
4289
|
a.rel = [...tokens].join(" ");
|
|
3667
4290
|
}
|
|
3668
4291
|
|
|
4292
|
+
// src/ui/tool-approval.tsx
|
|
4293
|
+
import { useComputed as useComputed2, useSignal } from "@preact/signals";
|
|
4294
|
+
import { Fragment, jsx as jsx13, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4295
|
+
var p12 = BRAND.cssPrefix;
|
|
4296
|
+
function ToolApproval({ part, strings, active, onDecision }) {
|
|
4297
|
+
const approval = useComputed2(() => part.approvalSig.value);
|
|
4298
|
+
const input = useComputed2(() => part.inputSig.value);
|
|
4299
|
+
const reason = useSignal("");
|
|
4300
|
+
const decided = approval.value?.approved !== void 0;
|
|
4301
|
+
if (decided) {
|
|
4302
|
+
const ap = approval.value;
|
|
4303
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval ${p12}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4304
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-label`, "data-approved": ap?.approved ? "true" : "false", children: ap?.approved ? strings.approved : strings.rejected }),
|
|
4305
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName }),
|
|
4306
|
+
ap?.reason ? /* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-value`, children: ap.reason }) : null
|
|
4307
|
+
] });
|
|
4308
|
+
}
|
|
4309
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval`, "data-testid": TID.toolApproval, children: [
|
|
4310
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-head`, children: [
|
|
4311
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-badge`, children: strings.approvalRequired }),
|
|
4312
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName })
|
|
4313
|
+
] }),
|
|
4314
|
+
summarizeInput(input.value) ? /* @__PURE__ */ jsx13("pre", { class: `${p12}-tool-args`, children: summarizeInput(input.value) }) : null,
|
|
4315
|
+
active ? /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
4316
|
+
/* @__PURE__ */ jsx13(
|
|
4317
|
+
"input",
|
|
4318
|
+
{
|
|
4319
|
+
class: `${p12}-field-input`,
|
|
4320
|
+
value: reason.value,
|
|
4321
|
+
placeholder: strings.approvalReason,
|
|
4322
|
+
onInput: (e) => {
|
|
4323
|
+
reason.value = e.target.value;
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
),
|
|
4327
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-actions`, children: [
|
|
4328
|
+
/* @__PURE__ */ jsx13(
|
|
4329
|
+
"button",
|
|
4330
|
+
{
|
|
4331
|
+
type: "button",
|
|
4332
|
+
class: `${p12}-tool-reject`,
|
|
4333
|
+
onClick: () => onDecision(part.toolCallId, false, reason.value.trim() || void 0),
|
|
4334
|
+
"data-testid": TID.toolReject,
|
|
4335
|
+
children: strings.reject
|
|
4336
|
+
}
|
|
4337
|
+
),
|
|
4338
|
+
/* @__PURE__ */ jsx13(
|
|
4339
|
+
"button",
|
|
4340
|
+
{
|
|
4341
|
+
type: "button",
|
|
4342
|
+
class: `${p12}-tool-approve`,
|
|
4343
|
+
onClick: () => onDecision(part.toolCallId, true, reason.value.trim() || void 0),
|
|
4344
|
+
"data-testid": TID.toolApprove,
|
|
4345
|
+
children: strings.approve
|
|
4346
|
+
}
|
|
4347
|
+
)
|
|
4348
|
+
] })
|
|
4349
|
+
] }) : /* @__PURE__ */ jsx13("p", { class: `${p12}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4350
|
+
] });
|
|
4351
|
+
}
|
|
4352
|
+
function summarizeInput(input) {
|
|
4353
|
+
if (input == null) return "";
|
|
4354
|
+
try {
|
|
4355
|
+
const json = typeof input === "string" ? input : JSON.stringify(input, null, 2);
|
|
4356
|
+
return json.length > 600 ? `${json.slice(0, 600)}\u2026` : json;
|
|
4357
|
+
} catch {
|
|
4358
|
+
return "";
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
// src/ui/tool-ask-input.tsx
|
|
4363
|
+
import { useComputed as useComputed3 } from "@preact/signals";
|
|
4364
|
+
|
|
4365
|
+
// src/ui/form/field.ts
|
|
4366
|
+
function parseAskUserInput(input) {
|
|
4367
|
+
const raw = input && typeof input === "object" ? input : {};
|
|
4368
|
+
const responseType = raw.responseType;
|
|
4369
|
+
return {
|
|
4370
|
+
title: str(raw.title),
|
|
4371
|
+
question: str(raw.question) ?? "Please provide the missing information.",
|
|
4372
|
+
description: str(raw.description),
|
|
4373
|
+
placeholder: str(raw.placeholder),
|
|
4374
|
+
responseType: responseType === "single-choice" || responseType === "multi-choice" || responseType === "confirmation" || responseType === "free-text" ? responseType : "free-text",
|
|
4375
|
+
choices: Array.isArray(raw.choices) ? raw.choices : void 0,
|
|
4376
|
+
allowOther: typeof raw.allowOther === "boolean" ? raw.allowOther : void 0,
|
|
4377
|
+
required: typeof raw.required === "boolean" ? raw.required : true,
|
|
4378
|
+
defaultValues: Array.isArray(raw.defaultValues) ? raw.defaultValues.filter((v) => typeof v === "string") : void 0,
|
|
4379
|
+
minSelections: num(raw.minSelections),
|
|
4380
|
+
maxSelections: num(raw.maxSelections),
|
|
4381
|
+
validationHint: str(raw.validationHint)
|
|
4382
|
+
};
|
|
4383
|
+
}
|
|
4384
|
+
function askInputToFields(req) {
|
|
4385
|
+
if (req.responseType === "confirmation") return [];
|
|
4386
|
+
const options = (req.choices ?? []).map(normalizeChoice).filter((c) => c !== null);
|
|
4387
|
+
let type = "textarea";
|
|
4388
|
+
if (req.responseType === "single-choice" && options.length > 0) type = "radio";
|
|
4389
|
+
else if (req.responseType === "multi-choice") type = "multiselect";
|
|
4390
|
+
const defaultValue = type === "multiselect" ? req.defaultValues?.join(", ") : req.defaultValues?.[0];
|
|
4391
|
+
return [
|
|
4392
|
+
{
|
|
4393
|
+
name: "answer",
|
|
4394
|
+
label: req.question,
|
|
4395
|
+
type,
|
|
4396
|
+
placeholder: req.placeholder,
|
|
4397
|
+
required: req.required ?? true,
|
|
4398
|
+
defaultValue,
|
|
4399
|
+
options: options.length > 0 ? options : void 0,
|
|
4400
|
+
allowOther: req.allowOther,
|
|
4401
|
+
validationHint: req.validationHint,
|
|
4402
|
+
validation: type === "multiselect" ? { minSelections: req.minSelections, maxSelections: req.maxSelections } : void 0
|
|
4403
|
+
}
|
|
4404
|
+
];
|
|
4405
|
+
}
|
|
4406
|
+
function normalizeChoice(c) {
|
|
4407
|
+
if (typeof c === "string") return c ? { value: c, label: c } : null;
|
|
4408
|
+
if (c && typeof c.value === "string" && c.value)
|
|
4409
|
+
return { value: c.value, label: c.label ?? c.value, description: c.description };
|
|
4410
|
+
return null;
|
|
4411
|
+
}
|
|
4412
|
+
function str(v) {
|
|
4413
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
4414
|
+
}
|
|
4415
|
+
function num(v) {
|
|
4416
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4419
|
+
// src/ui/tool-ask-input.tsx
|
|
4420
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
4421
|
+
var p13 = BRAND.cssPrefix;
|
|
4422
|
+
function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
4423
|
+
const state = useComputed3(() => part.stateSig.value);
|
|
4424
|
+
const request = useComputed3(() => parseAskUserInput(part.inputSig.value));
|
|
4425
|
+
const decided = state.value === "output" || state.value === "error";
|
|
4426
|
+
if (decided) {
|
|
4427
|
+
return /* @__PURE__ */ jsx14(DecidedSummary, { part, strings });
|
|
4428
|
+
}
|
|
4429
|
+
if (!active) {
|
|
4430
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-stale`, "data-testid": TID.toolAskInput, children: [
|
|
4431
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: request.value.title ?? request.value.question }),
|
|
4432
|
+
/* @__PURE__ */ jsx14("p", { class: `${p13}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4433
|
+
] });
|
|
4434
|
+
}
|
|
4435
|
+
const req = request.value;
|
|
4436
|
+
const fields = askInputToFields(req);
|
|
4437
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input`, "data-testid": TID.toolAskInput, children: [
|
|
4438
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: req.title }),
|
|
4439
|
+
req.description ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-desc`, children: req.description }) : null,
|
|
4440
|
+
req.responseType === "confirmation" ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-question`, children: req.question }) : null,
|
|
4441
|
+
req.responseType === "confirmation" ? /* @__PURE__ */ jsxs11("div", { class: `${p13}-form-actions`, children: [
|
|
4442
|
+
/* @__PURE__ */ jsx14(
|
|
4443
|
+
"button",
|
|
4444
|
+
{
|
|
4445
|
+
type: "button",
|
|
4446
|
+
class: `${p13}-form-skip`,
|
|
4447
|
+
onClick: () => onSubmit(part.toolCallId, { confirmed: false }),
|
|
4448
|
+
"data-testid": TID.toolInputSkip,
|
|
4449
|
+
children: strings.reject
|
|
4450
|
+
}
|
|
4451
|
+
),
|
|
4452
|
+
/* @__PURE__ */ jsx14(
|
|
4453
|
+
"button",
|
|
4454
|
+
{
|
|
4455
|
+
type: "button",
|
|
4456
|
+
class: `${p13}-form-submit`,
|
|
4457
|
+
onClick: () => onSubmit(part.toolCallId, { confirmed: true }),
|
|
4458
|
+
"data-testid": TID.toolInputSubmit,
|
|
4459
|
+
children: strings.approve
|
|
4460
|
+
}
|
|
4461
|
+
)
|
|
4462
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
4463
|
+
DynamicForm,
|
|
4464
|
+
{
|
|
4465
|
+
fields,
|
|
4466
|
+
strings,
|
|
4467
|
+
submitLabel: strings.inputSubmit,
|
|
4468
|
+
onSubmit: (values) => onSubmit(part.toolCallId, values),
|
|
4469
|
+
skipLabel: req.required === false ? strings.inputSkip : void 0,
|
|
4470
|
+
onSkip: req.required === false ? () => onSubmit(part.toolCallId, {}) : void 0,
|
|
4471
|
+
submitTestId: TID.toolInputSubmit,
|
|
4472
|
+
skipTestId: TID.toolInputSkip
|
|
4473
|
+
}
|
|
4474
|
+
)
|
|
4475
|
+
] });
|
|
4476
|
+
}
|
|
4477
|
+
function Header({ strings, title }) {
|
|
4478
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-head`, children: [
|
|
4479
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-badge`, children: strings.inputRequired }),
|
|
4480
|
+
title ? /* @__PURE__ */ jsx14("strong", { class: `${p13}-tool-title`, children: title }) : null
|
|
4481
|
+
] });
|
|
4482
|
+
}
|
|
4483
|
+
function DecidedSummary({ part, strings }) {
|
|
4484
|
+
const output = useComputed3(() => part.outputSig.value);
|
|
4485
|
+
const text = summarizeOutput(output.value) || strings.inputSubmitted;
|
|
4486
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4487
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-label`, children: strings.inputSubmitted }),
|
|
4488
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-value`, children: text })
|
|
4489
|
+
] });
|
|
4490
|
+
}
|
|
4491
|
+
function summarizeOutput(output) {
|
|
4492
|
+
if (output == null) return "";
|
|
4493
|
+
if (typeof output === "string") return output;
|
|
4494
|
+
if (typeof output === "object") {
|
|
4495
|
+
const rec = output;
|
|
4496
|
+
if ("confirmed" in rec) return rec.confirmed ? "Yes" : "No";
|
|
4497
|
+
return Object.values(rec).filter((v) => typeof v === "string" || typeof v === "number").join(", ");
|
|
4498
|
+
}
|
|
4499
|
+
return String(output);
|
|
4500
|
+
}
|
|
4501
|
+
|
|
3669
4502
|
// src/ui/tool-chip.tsx
|
|
3670
|
-
import { jsx as
|
|
4503
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
3671
4504
|
function ToolChip({ part, strings }) {
|
|
3672
|
-
const
|
|
3673
|
-
return /* @__PURE__ */
|
|
3674
|
-
/* @__PURE__ */
|
|
4505
|
+
const p33 = BRAND.cssPrefix;
|
|
4506
|
+
return /* @__PURE__ */ jsxs12("span", { class: `${p33}-tool-chip`, role: "status", children: [
|
|
4507
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
3675
4508
|
strings.usedTool,
|
|
3676
4509
|
":"
|
|
3677
4510
|
] }),
|
|
3678
|
-
/* @__PURE__ */
|
|
4511
|
+
/* @__PURE__ */ jsx15("strong", { children: part.toolName })
|
|
3679
4512
|
] });
|
|
3680
4513
|
}
|
|
3681
4514
|
|
|
3682
4515
|
// src/ui/message-bubble.tsx
|
|
3683
|
-
import { jsx as
|
|
3684
|
-
var
|
|
3685
|
-
function MessageBubble({
|
|
3686
|
-
|
|
4516
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
|
|
4517
|
+
var p14 = BRAND.cssPrefix;
|
|
4518
|
+
function MessageBubble({
|
|
4519
|
+
message,
|
|
4520
|
+
strings,
|
|
4521
|
+
responseMode,
|
|
4522
|
+
showReasoning,
|
|
4523
|
+
showToolCalls,
|
|
4524
|
+
interactive = false,
|
|
4525
|
+
tool
|
|
4526
|
+
}) {
|
|
4527
|
+
const parts = useComputed4(() => message.partsSig.value);
|
|
3687
4528
|
const partList = parts.value;
|
|
3688
|
-
const hasAnswerText =
|
|
4529
|
+
const hasAnswerText = useComputed4(
|
|
3689
4530
|
() => message.partsSig.value.some((part) => part.kind === "text" && part.textSig.value.length > 0)
|
|
3690
4531
|
);
|
|
3691
|
-
const reasoningVisible =
|
|
4532
|
+
const reasoningVisible = useComputed4(
|
|
3692
4533
|
() => showReasoning && message.partsSig.value.some((part) => part.kind === "reasoning")
|
|
3693
4534
|
);
|
|
3694
4535
|
const streaming = message.role === "assistant" && message.status === "streaming";
|
|
@@ -3696,23 +4537,25 @@ function MessageBubble({ message, strings, responseMode, showReasoning, showTool
|
|
|
3696
4537
|
const working = streaming && !hasAnswerText.value;
|
|
3697
4538
|
const showStreamDots = streaming && !bufferedHold && !(reasoningVisible.value && working);
|
|
3698
4539
|
const stamp = formatStamp(message.createdAt);
|
|
3699
|
-
return /* @__PURE__ */
|
|
3700
|
-
/* @__PURE__ */
|
|
3701
|
-
bufferedHold ? /* @__PURE__ */
|
|
4540
|
+
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: [
|
|
4541
|
+
/* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble`, children: [
|
|
4542
|
+
bufferedHold ? /* @__PURE__ */ jsx16(LoadingSpinner, { label: strings.loading }) : partList.map((part) => /* @__PURE__ */ jsx16(
|
|
3702
4543
|
PartView,
|
|
3703
4544
|
{
|
|
3704
4545
|
part,
|
|
3705
4546
|
active: working,
|
|
3706
4547
|
strings,
|
|
3707
4548
|
showReasoning,
|
|
3708
|
-
showToolCalls
|
|
4549
|
+
showToolCalls,
|
|
4550
|
+
interactive,
|
|
4551
|
+
tool
|
|
3709
4552
|
},
|
|
3710
4553
|
partKey(part)
|
|
3711
4554
|
)),
|
|
3712
|
-
showStreamDots && /* @__PURE__ */
|
|
3713
|
-
message.status === "error" && message.errorText ? /* @__PURE__ */
|
|
4555
|
+
showStreamDots && /* @__PURE__ */ jsx16(TypingDots, {}),
|
|
4556
|
+
message.status === "error" && message.errorText ? /* @__PURE__ */ jsx16("div", { class: `${p14}-error`, role: "alert", children: /* @__PURE__ */ jsx16("span", { children: message.errorText }) }) : null
|
|
3714
4557
|
] }),
|
|
3715
|
-
stamp ? /* @__PURE__ */
|
|
4558
|
+
stamp ? /* @__PURE__ */ jsx16("time", { class: `${p14}-bubble-time`, dateTime: stamp.iso, title: stamp.full, children: stamp.short }) : null
|
|
3716
4559
|
] }) });
|
|
3717
4560
|
}
|
|
3718
4561
|
function formatStamp(createdAt) {
|
|
@@ -3733,32 +4576,62 @@ function PartView({
|
|
|
3733
4576
|
active,
|
|
3734
4577
|
strings,
|
|
3735
4578
|
showReasoning,
|
|
3736
|
-
showToolCalls
|
|
4579
|
+
showToolCalls,
|
|
4580
|
+
interactive,
|
|
4581
|
+
tool
|
|
3737
4582
|
}) {
|
|
3738
4583
|
switch (part.kind) {
|
|
3739
4584
|
case "text":
|
|
3740
|
-
return /* @__PURE__ */
|
|
4585
|
+
return /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig });
|
|
3741
4586
|
case "reasoning":
|
|
3742
|
-
return showReasoning ? /* @__PURE__ */
|
|
4587
|
+
return showReasoning ? /* @__PURE__ */ jsx16(ReasoningView, { part, active, strings }) : null;
|
|
3743
4588
|
case "tool":
|
|
3744
|
-
return
|
|
4589
|
+
return /* @__PURE__ */ jsx16(
|
|
4590
|
+
ToolPartView,
|
|
4591
|
+
{
|
|
4592
|
+
part,
|
|
4593
|
+
strings,
|
|
4594
|
+
showToolCalls,
|
|
4595
|
+
interactive,
|
|
4596
|
+
tool
|
|
4597
|
+
}
|
|
4598
|
+
);
|
|
3745
4599
|
case "file":
|
|
3746
4600
|
if (part.mediaType.startsWith("image/")) {
|
|
3747
|
-
return /* @__PURE__ */
|
|
4601
|
+
return /* @__PURE__ */ jsx16("img", { src: part.url, alt: "", loading: "lazy" });
|
|
3748
4602
|
}
|
|
3749
|
-
return /* @__PURE__ */
|
|
4603
|
+
return /* @__PURE__ */ jsx16("a", { href: part.url, target: "_blank", rel: "noreferrer noopener", children: part.url });
|
|
3750
4604
|
case "source":
|
|
3751
4605
|
return null;
|
|
3752
4606
|
}
|
|
3753
4607
|
}
|
|
4608
|
+
function ToolPartView({
|
|
4609
|
+
part,
|
|
4610
|
+
strings,
|
|
4611
|
+
showToolCalls,
|
|
4612
|
+
interactive,
|
|
4613
|
+
tool
|
|
4614
|
+
}) {
|
|
4615
|
+
const state = useComputed4(() => part.stateSig.value);
|
|
4616
|
+
const hasApproval = useComputed4(() => part.approvalSig.value !== void 0);
|
|
4617
|
+
if (tool?.humanInLoop) {
|
|
4618
|
+
if (hasApproval.value || state.value === "awaiting-approval") {
|
|
4619
|
+
return /* @__PURE__ */ jsx16(ToolApproval, { part, strings, active: interactive, onDecision: tool.onDecision });
|
|
4620
|
+
}
|
|
4621
|
+
if (isAskUserInputTool(part.toolName) || state.value === "awaiting-input") {
|
|
4622
|
+
return /* @__PURE__ */ jsx16(ToolAskInput, { part, strings, active: interactive, onSubmit: tool.onResult });
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
return showToolCalls ? /* @__PURE__ */ jsx16(ToolChip, { part, strings }) : null;
|
|
4626
|
+
}
|
|
3754
4627
|
function ReasoningView({
|
|
3755
4628
|
part,
|
|
3756
4629
|
active,
|
|
3757
4630
|
strings
|
|
3758
4631
|
}) {
|
|
3759
|
-
return /* @__PURE__ */
|
|
3760
|
-
/* @__PURE__ */
|
|
3761
|
-
/* @__PURE__ */
|
|
4632
|
+
return /* @__PURE__ */ jsxs13("details", { class: `${p14}-reasoning`, open: active, "data-active": active ? "true" : void 0, children: [
|
|
4633
|
+
/* @__PURE__ */ jsx16("summary", { class: `${p14}-reasoning-summary`, children: /* @__PURE__ */ jsx16("span", { class: `${p14}-reasoning-label`, children: active ? strings.thinking : strings.thoughts }) }),
|
|
4634
|
+
/* @__PURE__ */ jsx16("div", { class: `${p14}-reasoning-body`, children: /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig }) })
|
|
3762
4635
|
] });
|
|
3763
4636
|
}
|
|
3764
4637
|
function partKey(part) {
|
|
@@ -3775,29 +4648,38 @@ function partKey(part) {
|
|
|
3775
4648
|
}
|
|
3776
4649
|
}
|
|
3777
4650
|
function TypingDots() {
|
|
3778
|
-
return /* @__PURE__ */
|
|
3779
|
-
/* @__PURE__ */
|
|
3780
|
-
/* @__PURE__ */
|
|
3781
|
-
/* @__PURE__ */
|
|
4651
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-typing`, "aria-hidden": "true", children: [
|
|
4652
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4653
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4654
|
+
/* @__PURE__ */ jsx16("span", {})
|
|
3782
4655
|
] });
|
|
3783
4656
|
}
|
|
3784
4657
|
function LoadingSpinner({ label }) {
|
|
3785
|
-
return /* @__PURE__ */
|
|
3786
|
-
/* @__PURE__ */
|
|
3787
|
-
/* @__PURE__ */
|
|
4658
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-loading`, role: "status", children: [
|
|
4659
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-spinner`, "aria-hidden": "true" }),
|
|
4660
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-label`, children: label })
|
|
3788
4661
|
] });
|
|
3789
4662
|
}
|
|
3790
4663
|
|
|
3791
4664
|
// src/ui/message-list.tsx
|
|
3792
|
-
import { jsx as
|
|
3793
|
-
var
|
|
4665
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
4666
|
+
var p15 = BRAND.cssPrefix;
|
|
3794
4667
|
var STICK_THRESHOLD = 120;
|
|
3795
4668
|
var DIVIDER_IDLE_MS = 1200;
|
|
3796
|
-
function MessageList({
|
|
4669
|
+
function MessageList({
|
|
4670
|
+
messagesSig,
|
|
4671
|
+
strings,
|
|
4672
|
+
responseMode,
|
|
4673
|
+
showReasoning,
|
|
4674
|
+
showToolCalls,
|
|
4675
|
+
loading,
|
|
4676
|
+
idle,
|
|
4677
|
+
tool
|
|
4678
|
+
}) {
|
|
3797
4679
|
const ref = useRef5(null);
|
|
3798
|
-
const messages =
|
|
3799
|
-
const [showJump, setShowJump] =
|
|
3800
|
-
const [scrolling, setScrolling] =
|
|
4680
|
+
const messages = useComputed5(() => messagesSig.value);
|
|
4681
|
+
const [showJump, setShowJump] = useState6(false);
|
|
4682
|
+
const [scrolling, setScrolling] = useState6(false);
|
|
3801
4683
|
const hasHydratedRef = useRef5(false);
|
|
3802
4684
|
const firstMessageId = messages.value[0]?.id;
|
|
3803
4685
|
useLayoutEffect(() => {
|
|
@@ -3852,18 +4734,18 @@ function MessageList({ messagesSig, strings, responseMode, showReasoning, showTo
|
|
|
3852
4734
|
const el = ref.current;
|
|
3853
4735
|
if (!el) return;
|
|
3854
4736
|
const syncJump = () => setShowJump(el.scrollHeight - el.scrollTop - el.clientHeight > STICK_THRESHOLD * 2);
|
|
3855
|
-
let
|
|
4737
|
+
let idleTimer;
|
|
3856
4738
|
const onScroll = () => {
|
|
3857
4739
|
syncJump();
|
|
3858
4740
|
setScrolling(true);
|
|
3859
|
-
clearTimeout(
|
|
3860
|
-
|
|
4741
|
+
clearTimeout(idleTimer);
|
|
4742
|
+
idleTimer = setTimeout(() => setScrolling(false), DIVIDER_IDLE_MS);
|
|
3861
4743
|
};
|
|
3862
4744
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
3863
4745
|
syncJump();
|
|
3864
4746
|
return () => {
|
|
3865
4747
|
el.removeEventListener("scroll", onScroll);
|
|
3866
|
-
clearTimeout(
|
|
4748
|
+
clearTimeout(idleTimer);
|
|
3867
4749
|
};
|
|
3868
4750
|
}, []);
|
|
3869
4751
|
const jumpToBottom = () => {
|
|
@@ -3872,54 +4754,57 @@ function MessageList({ messagesSig, strings, responseMode, showReasoning, showTo
|
|
|
3872
4754
|
};
|
|
3873
4755
|
const rows = [];
|
|
3874
4756
|
let prevDay = "";
|
|
4757
|
+
const lastId = messages.value.at(-1)?.id;
|
|
3875
4758
|
for (const m of messages.value) {
|
|
3876
4759
|
const day = dayKey(m.createdAt);
|
|
3877
4760
|
if (day && day !== prevDay) {
|
|
3878
4761
|
rows.push(
|
|
3879
|
-
/* @__PURE__ */
|
|
4762
|
+
/* @__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}`)
|
|
3880
4763
|
);
|
|
3881
4764
|
prevDay = day;
|
|
3882
4765
|
}
|
|
3883
4766
|
rows.push(
|
|
3884
|
-
/* @__PURE__ */
|
|
4767
|
+
/* @__PURE__ */ jsx17(
|
|
3885
4768
|
MessageBubble,
|
|
3886
4769
|
{
|
|
3887
4770
|
message: m,
|
|
3888
4771
|
strings,
|
|
3889
4772
|
responseMode,
|
|
3890
4773
|
showReasoning,
|
|
3891
|
-
showToolCalls
|
|
4774
|
+
showToolCalls,
|
|
4775
|
+
interactive: Boolean(idle) && m.id === lastId,
|
|
4776
|
+
tool
|
|
3892
4777
|
},
|
|
3893
4778
|
m.id
|
|
3894
4779
|
)
|
|
3895
4780
|
);
|
|
3896
4781
|
}
|
|
3897
|
-
return /* @__PURE__ */
|
|
3898
|
-
/* @__PURE__ */
|
|
4782
|
+
return /* @__PURE__ */ jsxs14("div", { class: `${p15}-list-wrap`, children: [
|
|
4783
|
+
/* @__PURE__ */ jsxs14(
|
|
3899
4784
|
"div",
|
|
3900
4785
|
{
|
|
3901
4786
|
ref,
|
|
3902
|
-
class: `${
|
|
4787
|
+
class: `${p15}-list`,
|
|
3903
4788
|
role: "log",
|
|
3904
4789
|
"aria-live": "polite",
|
|
3905
4790
|
"aria-relevant": "additions text",
|
|
3906
4791
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
3907
4792
|
children: [
|
|
3908
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */
|
|
4793
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.messagesLoading }) : null,
|
|
3909
4794
|
rows
|
|
3910
4795
|
]
|
|
3911
4796
|
}
|
|
3912
4797
|
),
|
|
3913
|
-
showJump ? /* @__PURE__ */
|
|
4798
|
+
showJump ? /* @__PURE__ */ jsx17(
|
|
3914
4799
|
"button",
|
|
3915
4800
|
{
|
|
3916
4801
|
type: "button",
|
|
3917
|
-
class: `${
|
|
4802
|
+
class: `${p15}-jump`,
|
|
3918
4803
|
onClick: jumpToBottom,
|
|
3919
4804
|
"aria-label": strings.scrollToBottom,
|
|
3920
4805
|
title: strings.scrollToBottom,
|
|
3921
4806
|
"data-testid": TID.scrollToBottom,
|
|
3922
|
-
children: /* @__PURE__ */
|
|
4807
|
+
children: /* @__PURE__ */ jsx17(ChevronDownIcon, {})
|
|
3923
4808
|
}
|
|
3924
4809
|
) : null
|
|
3925
4810
|
] });
|
|
@@ -3948,7 +4833,7 @@ function dayLabel(createdAt, strings) {
|
|
|
3948
4833
|
}
|
|
3949
4834
|
|
|
3950
4835
|
// src/ui/conversation-list.tsx
|
|
3951
|
-
import { useEffect as useEffect9, useState as
|
|
4836
|
+
import { useEffect as useEffect9, useState as useState7 } from "preact/hooks";
|
|
3952
4837
|
|
|
3953
4838
|
// src/ui/history-groups.ts
|
|
3954
4839
|
var HISTORY_BUCKETS = ["today", "yesterday", "lastWeek", "older"];
|
|
@@ -3978,7 +4863,7 @@ function startOfDay(ms) {
|
|
|
3978
4863
|
}
|
|
3979
4864
|
|
|
3980
4865
|
// src/ui/conversation-list.tsx
|
|
3981
|
-
import { Fragment, jsx as
|
|
4866
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
3982
4867
|
var log11 = logger.scope("history");
|
|
3983
4868
|
var BUCKET_TO_STRING = {
|
|
3984
4869
|
today: "dateToday",
|
|
@@ -3987,9 +4872,9 @@ var BUCKET_TO_STRING = {
|
|
|
3987
4872
|
older: "dateOlder"
|
|
3988
4873
|
};
|
|
3989
4874
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
3990
|
-
const
|
|
3991
|
-
const [state, setState] =
|
|
3992
|
-
const [sessions, setChats] =
|
|
4875
|
+
const p33 = BRAND.cssPrefix;
|
|
4876
|
+
const [state, setState] = useState7("loading");
|
|
4877
|
+
const [sessions, setChats] = useState7([]);
|
|
3993
4878
|
useEffect9(() => {
|
|
3994
4879
|
let cancelled = false;
|
|
3995
4880
|
transport.listSessions({ visitorId }).then((res) => {
|
|
@@ -4005,38 +4890,38 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4005
4890
|
cancelled = true;
|
|
4006
4891
|
};
|
|
4007
4892
|
}, [transport, visitorId]);
|
|
4008
|
-
const newChatButton = onNewChat ? /* @__PURE__ */
|
|
4009
|
-
/* @__PURE__ */
|
|
4893
|
+
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: [
|
|
4894
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
4010
4895
|
strings.historyNewChat
|
|
4011
4896
|
] }) }) : null;
|
|
4012
4897
|
if (state === "loading") {
|
|
4013
|
-
return /* @__PURE__ */
|
|
4014
|
-
/* @__PURE__ */
|
|
4898
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4899
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
4015
4900
|
newChatButton
|
|
4016
4901
|
] });
|
|
4017
4902
|
}
|
|
4018
4903
|
if (state === "error" || sessions.length === 0) {
|
|
4019
|
-
return /* @__PURE__ */
|
|
4020
|
-
/* @__PURE__ */
|
|
4904
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4905
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4021
4906
|
newChatButton
|
|
4022
4907
|
] });
|
|
4023
4908
|
}
|
|
4024
4909
|
const groups = groupByBucket(Date.now(), sessions);
|
|
4025
|
-
return /* @__PURE__ */
|
|
4026
|
-
/* @__PURE__ */
|
|
4027
|
-
/* @__PURE__ */
|
|
4028
|
-
group.sessions.map((chat) => /* @__PURE__ */
|
|
4910
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4911
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4912
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4913
|
+
group.sessions.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4029
4914
|
"button",
|
|
4030
4915
|
{
|
|
4031
4916
|
type: "button",
|
|
4032
4917
|
role: "listitem",
|
|
4033
|
-
class: `${
|
|
4918
|
+
class: `${p33}-history-item`,
|
|
4034
4919
|
onClick: () => onSelect(chat),
|
|
4035
4920
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4036
4921
|
"data-testid": tid(TID.historyItem, chat.sessionId),
|
|
4037
4922
|
children: [
|
|
4038
|
-
/* @__PURE__ */
|
|
4039
|
-
chat.preview ? /* @__PURE__ */
|
|
4923
|
+
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4924
|
+
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4040
4925
|
]
|
|
4041
4926
|
},
|
|
4042
4927
|
chat.sessionId
|
|
@@ -4047,21 +4932,21 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4047
4932
|
}
|
|
4048
4933
|
|
|
4049
4934
|
// src/ui/chat-history-pane.tsx
|
|
4050
|
-
import { jsx as
|
|
4935
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4051
4936
|
function ChatHistoryPane(props2) {
|
|
4052
|
-
return /* @__PURE__ */
|
|
4937
|
+
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
4053
4938
|
}
|
|
4054
4939
|
|
|
4055
4940
|
// src/ui/suggestions.tsx
|
|
4056
|
-
import { jsx as
|
|
4057
|
-
var
|
|
4941
|
+
import { jsx as jsx20 } from "preact/jsx-runtime";
|
|
4942
|
+
var p16 = BRAND.cssPrefix;
|
|
4058
4943
|
function Suggestions({ suggestions, onPick }) {
|
|
4059
4944
|
if (suggestions.length === 0) return null;
|
|
4060
|
-
return /* @__PURE__ */
|
|
4945
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx20(
|
|
4061
4946
|
"button",
|
|
4062
4947
|
{
|
|
4063
4948
|
type: "button",
|
|
4064
|
-
class: `${
|
|
4949
|
+
class: `${p16}-suggestion`,
|
|
4065
4950
|
onClick: () => onPick(s),
|
|
4066
4951
|
"data-testid": tid(TID.suggestion, i),
|
|
4067
4952
|
children: s.label
|
|
@@ -4071,8 +4956,8 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
4071
4956
|
}
|
|
4072
4957
|
|
|
4073
4958
|
// src/ui/panel.tsx
|
|
4074
|
-
import { Fragment as
|
|
4075
|
-
var
|
|
4959
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
4960
|
+
var p17 = BRAND.cssPrefix;
|
|
4076
4961
|
function Panel(props2) {
|
|
4077
4962
|
const { options, onClose } = props2;
|
|
4078
4963
|
const s = options.strings;
|
|
@@ -4096,18 +4981,18 @@ function Panel(props2) {
|
|
|
4096
4981
|
}, []);
|
|
4097
4982
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
4098
4983
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
4099
|
-
return /* @__PURE__ */
|
|
4984
|
+
return /* @__PURE__ */ jsxs16(
|
|
4100
4985
|
"div",
|
|
4101
4986
|
{
|
|
4102
4987
|
ref: containerRef,
|
|
4103
|
-
class: `${
|
|
4988
|
+
class: `${p17}-panel`,
|
|
4104
4989
|
role: "dialog",
|
|
4105
4990
|
"aria-modal": "false",
|
|
4106
4991
|
"aria-label": s.panelTitle,
|
|
4107
4992
|
style: { position: "relative" },
|
|
4108
4993
|
"data-testid": TID.panel,
|
|
4109
4994
|
children: [
|
|
4110
|
-
/* @__PURE__ */
|
|
4995
|
+
/* @__PURE__ */ jsx21(
|
|
4111
4996
|
PanelContent,
|
|
4112
4997
|
{
|
|
4113
4998
|
...props2,
|
|
@@ -4116,7 +5001,7 @@ function Panel(props2) {
|
|
|
4116
5001
|
composerAttachApiRef
|
|
4117
5002
|
}
|
|
4118
5003
|
),
|
|
4119
|
-
/* @__PURE__ */
|
|
5004
|
+
/* @__PURE__ */ jsx21(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
4120
5005
|
]
|
|
4121
5006
|
}
|
|
4122
5007
|
);
|
|
@@ -4147,13 +5032,39 @@ function PanelContent(props2) {
|
|
|
4147
5032
|
onSend,
|
|
4148
5033
|
onStop,
|
|
4149
5034
|
onSuggestion,
|
|
5035
|
+
intakePending,
|
|
5036
|
+
onIntakeComplete,
|
|
5037
|
+
tool,
|
|
4150
5038
|
containerEl,
|
|
4151
5039
|
dragOver,
|
|
4152
5040
|
composerAttachApiRef
|
|
4153
5041
|
} = props2;
|
|
4154
5042
|
const s = options.strings;
|
|
4155
|
-
|
|
4156
|
-
|
|
5043
|
+
let composerArea;
|
|
5044
|
+
if (intakePending) {
|
|
5045
|
+
composerArea = /* @__PURE__ */ jsx21(IntakeGate, { intake: options.intake, strings: s, onComplete: onIntakeComplete });
|
|
5046
|
+
} else if (canSend) {
|
|
5047
|
+
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5048
|
+
/* @__PURE__ */ jsx21(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
5049
|
+
/* @__PURE__ */ jsx21(
|
|
5050
|
+
Composer,
|
|
5051
|
+
{
|
|
5052
|
+
options,
|
|
5053
|
+
transport,
|
|
5054
|
+
feedback,
|
|
5055
|
+
bus,
|
|
5056
|
+
isStreaming,
|
|
5057
|
+
onSend,
|
|
5058
|
+
onStop,
|
|
5059
|
+
attachApiRef: composerAttachApiRef
|
|
5060
|
+
}
|
|
5061
|
+
)
|
|
5062
|
+
] });
|
|
5063
|
+
} else {
|
|
5064
|
+
composerArea = /* @__PURE__ */ jsx21(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear });
|
|
5065
|
+
}
|
|
5066
|
+
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5067
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
4157
5068
|
HistoryHeader,
|
|
4158
5069
|
{
|
|
4159
5070
|
strings: s,
|
|
@@ -4161,22 +5072,22 @@ function PanelContent(props2) {
|
|
|
4161
5072
|
onClose,
|
|
4162
5073
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
4163
5074
|
}
|
|
4164
|
-
) : /* @__PURE__ */
|
|
4165
|
-
onBack ? /* @__PURE__ */
|
|
5075
|
+
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5076
|
+
onBack ? /* @__PURE__ */ jsx21(
|
|
4166
5077
|
"button",
|
|
4167
5078
|
{
|
|
4168
5079
|
type: "button",
|
|
4169
|
-
class: `${
|
|
5080
|
+
class: `${p17}-icon-btn`,
|
|
4170
5081
|
onClick: onBack,
|
|
4171
5082
|
"aria-label": s.moduleBack,
|
|
4172
5083
|
title: s.moduleBack,
|
|
4173
|
-
children: /* @__PURE__ */
|
|
5084
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
4174
5085
|
}
|
|
4175
5086
|
) : null,
|
|
4176
|
-
agent ? /* @__PURE__ */
|
|
4177
|
-
/* @__PURE__ */
|
|
5087
|
+
agent ? /* @__PURE__ */ jsx21(AgentBadge, { agent }) : /* @__PURE__ */ jsx21("h1", { children: s.panelTitle }),
|
|
5088
|
+
/* @__PURE__ */ jsx21(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
4178
5089
|
] }),
|
|
4179
|
-
view === "history" ? /* @__PURE__ */
|
|
5090
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
4180
5091
|
ChatHistoryPane,
|
|
4181
5092
|
{
|
|
4182
5093
|
transport,
|
|
@@ -4185,9 +5096,9 @@ function PanelContent(props2) {
|
|
|
4185
5096
|
onSelect: (chat) => onSelectHistoryChat(chat.sessionId),
|
|
4186
5097
|
onNewChat
|
|
4187
5098
|
}
|
|
4188
|
-
) : /* @__PURE__ */
|
|
4189
|
-
/* @__PURE__ */
|
|
4190
|
-
/* @__PURE__ */
|
|
5099
|
+
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5100
|
+
/* @__PURE__ */ jsx21(DropZone, { visible: dragOver, strings: s }),
|
|
5101
|
+
/* @__PURE__ */ jsx21(
|
|
4191
5102
|
MessageList,
|
|
4192
5103
|
{
|
|
4193
5104
|
messagesSig,
|
|
@@ -4195,28 +5106,15 @@ function PanelContent(props2) {
|
|
|
4195
5106
|
responseMode: options.responseMode,
|
|
4196
5107
|
showReasoning: options.showReasoning,
|
|
4197
5108
|
showToolCalls: options.showToolCalls,
|
|
4198
|
-
loading: loadingMessages
|
|
5109
|
+
loading: loadingMessages,
|
|
5110
|
+
idle: !isStreaming,
|
|
5111
|
+
tool
|
|
4199
5112
|
}
|
|
4200
5113
|
),
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
/* @__PURE__ */ jsx17(
|
|
4204
|
-
Composer,
|
|
4205
|
-
{
|
|
4206
|
-
options,
|
|
4207
|
-
transport,
|
|
4208
|
-
feedback,
|
|
4209
|
-
bus,
|
|
4210
|
-
isStreaming,
|
|
4211
|
-
onSend,
|
|
4212
|
-
onStop,
|
|
4213
|
-
attachApiRef: composerAttachApiRef
|
|
4214
|
-
}
|
|
4215
|
-
)
|
|
4216
|
-
] }) : /* @__PURE__ */ jsx17(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear }),
|
|
4217
|
-
/* @__PURE__ */ jsx17(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5114
|
+
composerArea,
|
|
5115
|
+
/* @__PURE__ */ jsx21(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
4218
5116
|
] }),
|
|
4219
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5117
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx21(
|
|
4220
5118
|
ResizeGrip,
|
|
4221
5119
|
{
|
|
4222
5120
|
panelEl: containerEl,
|
|
@@ -4235,86 +5133,86 @@ function HistoryHeader({
|
|
|
4235
5133
|
onClose,
|
|
4236
5134
|
showClose
|
|
4237
5135
|
}) {
|
|
4238
|
-
return /* @__PURE__ */
|
|
4239
|
-
/* @__PURE__ */
|
|
5136
|
+
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5137
|
+
/* @__PURE__ */ jsx21(
|
|
4240
5138
|
"button",
|
|
4241
5139
|
{
|
|
4242
5140
|
type: "button",
|
|
4243
|
-
class: `${
|
|
5141
|
+
class: `${p17}-icon-btn`,
|
|
4244
5142
|
onClick: onBack,
|
|
4245
5143
|
"aria-label": strings.historyBack,
|
|
4246
5144
|
title: strings.historyBack,
|
|
4247
|
-
children: /* @__PURE__ */
|
|
5145
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
4248
5146
|
}
|
|
4249
5147
|
),
|
|
4250
|
-
/* @__PURE__ */
|
|
4251
|
-
showClose ? /* @__PURE__ */
|
|
5148
|
+
/* @__PURE__ */ jsx21("h1", { children: strings.historyTitle }),
|
|
5149
|
+
showClose ? /* @__PURE__ */ jsx21(
|
|
4252
5150
|
"button",
|
|
4253
5151
|
{
|
|
4254
5152
|
type: "button",
|
|
4255
|
-
class: `${
|
|
5153
|
+
class: `${p17}-icon-btn`,
|
|
4256
5154
|
onClick: onClose,
|
|
4257
5155
|
"aria-label": strings.close,
|
|
4258
5156
|
title: strings.close,
|
|
4259
|
-
children: /* @__PURE__ */
|
|
5157
|
+
children: /* @__PURE__ */ jsx21(CloseIcon, {})
|
|
4260
5158
|
}
|
|
4261
5159
|
) : null
|
|
4262
5160
|
] });
|
|
4263
5161
|
}
|
|
4264
5162
|
function ReadOnlyBanner({ label, ctaLabel, onNewChat }) {
|
|
4265
|
-
return /* @__PURE__ */
|
|
4266
|
-
/* @__PURE__ */
|
|
4267
|
-
/* @__PURE__ */
|
|
5163
|
+
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5164
|
+
/* @__PURE__ */ jsx21("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5165
|
+
/* @__PURE__ */ jsx21("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewChat, children: ctaLabel })
|
|
4268
5166
|
] });
|
|
4269
5167
|
}
|
|
4270
5168
|
function ComposerFooter({ disclaimer }) {
|
|
4271
5169
|
if (!disclaimer) return null;
|
|
4272
|
-
return /* @__PURE__ */
|
|
5170
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx21("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
4273
5171
|
}
|
|
4274
5172
|
function PoweredByBar({ poweredBy }) {
|
|
4275
5173
|
if (!poweredBy) return null;
|
|
4276
|
-
return /* @__PURE__ */
|
|
5174
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx21(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
4277
5175
|
}
|
|
4278
5176
|
function PoweredBy({ logoUrl, text, href }) {
|
|
4279
|
-
const inner = /* @__PURE__ */
|
|
4280
|
-
logoUrl ? /* @__PURE__ */
|
|
4281
|
-
text ? /* @__PURE__ */
|
|
5177
|
+
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5178
|
+
logoUrl ? /* @__PURE__ */ jsx21("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5179
|
+
text ? /* @__PURE__ */ jsx21("span", { children: text }) : null
|
|
4282
5180
|
] });
|
|
4283
5181
|
if (href) {
|
|
4284
|
-
return /* @__PURE__ */
|
|
5182
|
+
return /* @__PURE__ */ jsx21("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
4285
5183
|
}
|
|
4286
|
-
return /* @__PURE__ */
|
|
5184
|
+
return /* @__PURE__ */ jsx21("span", { class: `${p17}-poweredby`, children: inner });
|
|
4287
5185
|
}
|
|
4288
5186
|
|
|
4289
5187
|
// src/ui/sidebar.tsx
|
|
4290
|
-
import { Fragment as
|
|
5188
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
4291
5189
|
function Sidebar(props2) {
|
|
4292
|
-
const
|
|
5190
|
+
const p33 = BRAND.cssPrefix;
|
|
4293
5191
|
const { site, blocks, strings, collapsed } = props2;
|
|
4294
5192
|
const navigation = blocks?.navigation ?? [];
|
|
4295
5193
|
const linkCards = blocks?.linkCards ?? [];
|
|
4296
5194
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
4297
|
-
return /* @__PURE__ */
|
|
4298
|
-
/* @__PURE__ */
|
|
4299
|
-
/* @__PURE__ */
|
|
4300
|
-
/* @__PURE__ */
|
|
5195
|
+
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5196
|
+
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5197
|
+
/* @__PURE__ */ jsx22(SidebarBrand, { site }),
|
|
5198
|
+
/* @__PURE__ */ jsx22(
|
|
4301
5199
|
"button",
|
|
4302
5200
|
{
|
|
4303
5201
|
type: "button",
|
|
4304
|
-
class: `${
|
|
5202
|
+
class: `${p33}-sidebar-toggle`,
|
|
4305
5203
|
"aria-label": toggleLabel,
|
|
4306
5204
|
"aria-expanded": collapsed ? "false" : "true",
|
|
4307
5205
|
title: toggleLabel,
|
|
4308
5206
|
onClick: props2.onToggleCollapsed,
|
|
4309
5207
|
"data-testid": TID.sidebarToggle,
|
|
4310
|
-
children: /* @__PURE__ */
|
|
5208
|
+
children: /* @__PURE__ */ jsx22(SidebarToggleIcon, { collapsed })
|
|
4311
5209
|
}
|
|
4312
5210
|
)
|
|
4313
5211
|
] }),
|
|
4314
|
-
collapsed ? null : /* @__PURE__ */
|
|
4315
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
4316
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
4317
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5212
|
+
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5213
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx22("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx22(SidebarNav, { items: navigation }) }) : null,
|
|
5214
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx22(SidebarCards, { items: linkCards }) }) : null,
|
|
5215
|
+
props2.showConversations ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx22(
|
|
4318
5216
|
ConversationList,
|
|
4319
5217
|
{
|
|
4320
5218
|
transport: props2.transport,
|
|
@@ -4328,18 +5226,18 @@ function Sidebar(props2) {
|
|
|
4328
5226
|
] });
|
|
4329
5227
|
}
|
|
4330
5228
|
function SidebarBrand({ site }) {
|
|
4331
|
-
const
|
|
5229
|
+
const p33 = BRAND.cssPrefix;
|
|
4332
5230
|
if (site?.logo?.url) {
|
|
4333
5231
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
4334
|
-
return /* @__PURE__ */
|
|
4335
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
4336
|
-
/* @__PURE__ */
|
|
5232
|
+
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5233
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx22("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5234
|
+
/* @__PURE__ */ jsx22("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
4337
5235
|
] });
|
|
4338
5236
|
}
|
|
4339
|
-
return /* @__PURE__ */
|
|
5237
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
4340
5238
|
}
|
|
4341
5239
|
function SidebarToggleIcon({ collapsed }) {
|
|
4342
|
-
return /* @__PURE__ */
|
|
5240
|
+
return /* @__PURE__ */ jsx22(
|
|
4343
5241
|
"svg",
|
|
4344
5242
|
{
|
|
4345
5243
|
width: "16",
|
|
@@ -4349,38 +5247,38 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
4349
5247
|
stroke: "currentColor",
|
|
4350
5248
|
"stroke-width": "2",
|
|
4351
5249
|
"aria-hidden": "true",
|
|
4352
|
-
children: collapsed ? /* @__PURE__ */
|
|
5250
|
+
children: collapsed ? /* @__PURE__ */ jsx22("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx22("polyline", { points: "15 6 9 12 15 18" })
|
|
4353
5251
|
}
|
|
4354
5252
|
);
|
|
4355
5253
|
}
|
|
4356
5254
|
function SidebarNav({ items }) {
|
|
4357
|
-
const
|
|
4358
|
-
return /* @__PURE__ */
|
|
5255
|
+
const p33 = BRAND.cssPrefix;
|
|
5256
|
+
return /* @__PURE__ */ jsx22("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsxs17(
|
|
4359
5257
|
"a",
|
|
4360
5258
|
{
|
|
4361
|
-
class: `${
|
|
5259
|
+
class: `${p33}-sidebar-nav-item`,
|
|
4362
5260
|
href: item.href,
|
|
4363
5261
|
target: item.href ? "_blank" : void 0,
|
|
4364
5262
|
rel: item.href ? "noreferrer" : void 0,
|
|
4365
5263
|
children: [
|
|
4366
|
-
item.icon ? /* @__PURE__ */
|
|
4367
|
-
/* @__PURE__ */
|
|
5264
|
+
item.icon ? /* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5265
|
+
/* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
4368
5266
|
]
|
|
4369
5267
|
}
|
|
4370
5268
|
) }, item.id ?? item.label)) });
|
|
4371
5269
|
}
|
|
4372
5270
|
function SidebarCards({ items }) {
|
|
4373
|
-
const
|
|
4374
|
-
return /* @__PURE__ */
|
|
5271
|
+
const p33 = BRAND.cssPrefix;
|
|
5272
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
4375
5273
|
"a",
|
|
4376
5274
|
{
|
|
4377
|
-
class: `${
|
|
5275
|
+
class: `${p33}-sidebar-card`,
|
|
4378
5276
|
href: item.href,
|
|
4379
5277
|
target: item.href ? "_blank" : void 0,
|
|
4380
5278
|
rel: item.href ? "noreferrer" : void 0,
|
|
4381
5279
|
children: [
|
|
4382
|
-
/* @__PURE__ */
|
|
4383
|
-
item.description ? /* @__PURE__ */
|
|
5280
|
+
/* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5281
|
+
item.description ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
4384
5282
|
]
|
|
4385
5283
|
},
|
|
4386
5284
|
item.id ?? item.label
|
|
@@ -4388,11 +5286,11 @@ function SidebarCards({ items }) {
|
|
|
4388
5286
|
}
|
|
4389
5287
|
|
|
4390
5288
|
// src/ui/page-shell.tsx
|
|
4391
|
-
import { jsx as
|
|
4392
|
-
var
|
|
5289
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5290
|
+
var p18 = BRAND.cssPrefix;
|
|
4393
5291
|
function PageShell(props2) {
|
|
4394
|
-
return /* @__PURE__ */
|
|
4395
|
-
/* @__PURE__ */
|
|
5292
|
+
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5293
|
+
/* @__PURE__ */ jsx23(
|
|
4396
5294
|
Sidebar,
|
|
4397
5295
|
{
|
|
4398
5296
|
site: props2.site,
|
|
@@ -4407,7 +5305,7 @@ function PageShell(props2) {
|
|
|
4407
5305
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
4408
5306
|
}
|
|
4409
5307
|
),
|
|
4410
|
-
/* @__PURE__ */
|
|
5308
|
+
/* @__PURE__ */ jsx23("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
4411
5309
|
] });
|
|
4412
5310
|
}
|
|
4413
5311
|
|
|
@@ -4445,7 +5343,7 @@ var atTabRoot = (s) => activeStack(s).length === 0;
|
|
|
4445
5343
|
|
|
4446
5344
|
// src/ui/messenger-home.tsx
|
|
4447
5345
|
import { useCallback as useCallback4, useEffect as useEffect15, useRef as useRef7 } from "preact/hooks";
|
|
4448
|
-
import { useComputed as
|
|
5346
|
+
import { useComputed as useComputed6 } from "@preact/signals";
|
|
4449
5347
|
|
|
4450
5348
|
// src/ui/modules/messages.tsx
|
|
4451
5349
|
var chatLayout = {
|
|
@@ -4454,83 +5352,83 @@ var chatLayout = {
|
|
|
4454
5352
|
};
|
|
4455
5353
|
|
|
4456
5354
|
// src/ui/modules/help.tsx
|
|
4457
|
-
import { useEffect as useEffect11, useMemo as useMemo2, useState as
|
|
5355
|
+
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
4458
5356
|
|
|
4459
5357
|
// src/ui/back-header.tsx
|
|
4460
|
-
import { jsx as
|
|
4461
|
-
var
|
|
5358
|
+
import { jsx as jsx24, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5359
|
+
var p19 = BRAND.cssPrefix;
|
|
4462
5360
|
function TitleBar({ title, actions }) {
|
|
4463
|
-
return /* @__PURE__ */
|
|
4464
|
-
/* @__PURE__ */
|
|
4465
|
-
/* @__PURE__ */
|
|
4466
|
-
actions ?? /* @__PURE__ */
|
|
5361
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5362
|
+
/* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5363
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5364
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
4467
5365
|
] });
|
|
4468
5366
|
}
|
|
4469
5367
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
4470
|
-
return /* @__PURE__ */
|
|
4471
|
-
/* @__PURE__ */
|
|
4472
|
-
/* @__PURE__ */
|
|
4473
|
-
actions ?? /* @__PURE__ */
|
|
5368
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5369
|
+
/* @__PURE__ */ jsx24("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx24(BackIcon, {}) }),
|
|
5370
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5371
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
4474
5372
|
] });
|
|
4475
5373
|
}
|
|
4476
5374
|
|
|
4477
5375
|
// src/ui/home-search.tsx
|
|
4478
|
-
import { jsx as
|
|
4479
|
-
var
|
|
5376
|
+
import { jsx as jsx25, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5377
|
+
var p20 = BRAND.cssPrefix;
|
|
4480
5378
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
4481
|
-
return /* @__PURE__ */
|
|
4482
|
-
/* @__PURE__ */
|
|
4483
|
-
/* @__PURE__ */
|
|
5379
|
+
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5380
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5381
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
4484
5382
|
] });
|
|
4485
5383
|
}
|
|
4486
5384
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
4487
|
-
return /* @__PURE__ */
|
|
4488
|
-
/* @__PURE__ */
|
|
5385
|
+
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5386
|
+
/* @__PURE__ */ jsx25(
|
|
4489
5387
|
"input",
|
|
4490
5388
|
{
|
|
4491
5389
|
type: "search",
|
|
4492
|
-
class: `${
|
|
5390
|
+
class: `${p20}-home-search-input`,
|
|
4493
5391
|
placeholder,
|
|
4494
5392
|
value,
|
|
4495
5393
|
onInput: (e) => onInput(e.currentTarget.value),
|
|
4496
5394
|
"data-testid": TID.helpSearch
|
|
4497
5395
|
}
|
|
4498
5396
|
),
|
|
4499
|
-
/* @__PURE__ */
|
|
5397
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
4500
5398
|
] });
|
|
4501
5399
|
}
|
|
4502
5400
|
|
|
4503
5401
|
// src/ui/list-row.tsx
|
|
4504
|
-
import { jsx as
|
|
4505
|
-
var
|
|
5402
|
+
import { jsx as jsx26, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5403
|
+
var p21 = BRAND.cssPrefix;
|
|
4506
5404
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
4507
|
-
return /* @__PURE__ */
|
|
4508
|
-
/* @__PURE__ */
|
|
4509
|
-
/* @__PURE__ */
|
|
4510
|
-
subtitle ? /* @__PURE__ */
|
|
5405
|
+
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5406
|
+
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5407
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5408
|
+
subtitle ? /* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
4511
5409
|
] }),
|
|
4512
|
-
/* @__PURE__ */
|
|
5410
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx26(ChevronRightIcon, {}) })
|
|
4513
5411
|
] });
|
|
4514
5412
|
}
|
|
4515
5413
|
|
|
4516
5414
|
// src/ui/module-state.tsx
|
|
4517
|
-
import { jsx as
|
|
4518
|
-
var
|
|
5415
|
+
import { jsx as jsx27, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5416
|
+
var p22 = BRAND.cssPrefix;
|
|
4519
5417
|
function ModuleState({
|
|
4520
5418
|
tone = "info",
|
|
4521
5419
|
message,
|
|
4522
5420
|
onRetry,
|
|
4523
5421
|
strings
|
|
4524
5422
|
}) {
|
|
4525
|
-
return /* @__PURE__ */
|
|
4526
|
-
/* @__PURE__ */
|
|
4527
|
-
onRetry ? /* @__PURE__ */
|
|
5423
|
+
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5424
|
+
/* @__PURE__ */ jsx27("span", { children: message }),
|
|
5425
|
+
onRetry ? /* @__PURE__ */ jsx27("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
4528
5426
|
] });
|
|
4529
5427
|
}
|
|
4530
5428
|
|
|
4531
5429
|
// src/ui/modules/help.tsx
|
|
4532
|
-
import { jsx as
|
|
4533
|
-
var
|
|
5430
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5431
|
+
var p23 = BRAND.cssPrefix;
|
|
4534
5432
|
var log12 = logger.scope("help");
|
|
4535
5433
|
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 });
|
|
4536
5434
|
function groupByCategory(items) {
|
|
@@ -4559,7 +5457,7 @@ function fuzzySearch(items, query) {
|
|
|
4559
5457
|
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);
|
|
4560
5458
|
}
|
|
4561
5459
|
function ArticleRow({ article, nav }) {
|
|
4562
|
-
return /* @__PURE__ */
|
|
5460
|
+
return /* @__PURE__ */ jsx28(
|
|
4563
5461
|
ListRow,
|
|
4564
5462
|
{
|
|
4565
5463
|
title: article.title,
|
|
@@ -4571,11 +5469,11 @@ function ArticleRow({ article, nav }) {
|
|
|
4571
5469
|
}
|
|
4572
5470
|
function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
4573
5471
|
const tags = config.contentTags;
|
|
4574
|
-
const [state, setState] =
|
|
4575
|
-
const [errorMsg, setErrorMsg] =
|
|
4576
|
-
const [items, setItems] =
|
|
4577
|
-
const [query, setQuery] =
|
|
4578
|
-
const [reloadKey, setReloadKey] =
|
|
5472
|
+
const [state, setState] = useState8("loading");
|
|
5473
|
+
const [errorMsg, setErrorMsg] = useState8(strings.errorGeneric);
|
|
5474
|
+
const [items, setItems] = useState8([]);
|
|
5475
|
+
const [query, setQuery] = useState8("");
|
|
5476
|
+
const [reloadKey, setReloadKey] = useState8(0);
|
|
4579
5477
|
useEffect11(() => {
|
|
4580
5478
|
let cancelled = false;
|
|
4581
5479
|
setState("loading");
|
|
@@ -4596,46 +5494,46 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
4596
5494
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
4597
5495
|
function renderBody() {
|
|
4598
5496
|
if (query.trim().length > 0) {
|
|
4599
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
4600
|
-
return /* @__PURE__ */
|
|
5497
|
+
if (results.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5498
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) });
|
|
4601
5499
|
}
|
|
4602
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5500
|
+
if (state === "loading") return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpLoading, strings });
|
|
4603
5501
|
if (state === "error") {
|
|
4604
|
-
return /* @__PURE__ */
|
|
5502
|
+
return /* @__PURE__ */ jsx28(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
4605
5503
|
}
|
|
4606
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
4607
|
-
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */
|
|
4608
|
-
category ? /* @__PURE__ */
|
|
4609
|
-
/* @__PURE__ */
|
|
5504
|
+
if (items.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpEmpty, strings });
|
|
5505
|
+
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5506
|
+
category ? /* @__PURE__ */ jsx28("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5507
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) })
|
|
4610
5508
|
] }, category));
|
|
4611
5509
|
}
|
|
4612
|
-
return /* @__PURE__ */
|
|
4613
|
-
/* @__PURE__ */
|
|
4614
|
-
/* @__PURE__ */
|
|
4615
|
-
/* @__PURE__ */
|
|
5510
|
+
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5511
|
+
/* @__PURE__ */ jsx28(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx28(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5512
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx28(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5513
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
4616
5514
|
] });
|
|
4617
5515
|
}
|
|
4618
5516
|
var helpLayout = {
|
|
4619
5517
|
Icon: HelpIcon,
|
|
4620
|
-
Root: (props2) => /* @__PURE__ */
|
|
5518
|
+
Root: (props2) => /* @__PURE__ */ jsx28(HelpRoot, { ...props2 })
|
|
4621
5519
|
};
|
|
4622
5520
|
|
|
4623
5521
|
// src/ui/modules/home.tsx
|
|
4624
|
-
import { useEffect as useEffect12, useState as
|
|
5522
|
+
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
4625
5523
|
|
|
4626
5524
|
// src/ui/home-card.tsx
|
|
4627
|
-
import { jsx as
|
|
4628
|
-
var
|
|
5525
|
+
import { jsx as jsx29 } from "preact/jsx-runtime";
|
|
5526
|
+
var p24 = BRAND.cssPrefix;
|
|
4629
5527
|
function HomeCard({ onClick, children, testid }) {
|
|
4630
5528
|
if (onClick) {
|
|
4631
|
-
return /* @__PURE__ */
|
|
5529
|
+
return /* @__PURE__ */ jsx29("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
4632
5530
|
}
|
|
4633
|
-
return /* @__PURE__ */
|
|
5531
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
4634
5532
|
}
|
|
4635
5533
|
|
|
4636
5534
|
// src/ui/modules/home.tsx
|
|
4637
|
-
import { Fragment as
|
|
4638
|
-
var
|
|
5535
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5536
|
+
var p25 = BRAND.cssPrefix;
|
|
4639
5537
|
var log13 = logger.scope("home");
|
|
4640
5538
|
function resolveGreeting(props2) {
|
|
4641
5539
|
const name = props2.options.userContext?.name;
|
|
@@ -4649,8 +5547,8 @@ function resolveGreeting(props2) {
|
|
|
4649
5547
|
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 });
|
|
4650
5548
|
function HomeRoot(props2) {
|
|
4651
5549
|
const { transport, strings, config, nav, panelProps } = props2;
|
|
4652
|
-
const [recent, setRecent] =
|
|
4653
|
-
const [content, setContent] =
|
|
5550
|
+
const [recent, setRecent] = useState9(null);
|
|
5551
|
+
const [content, setContent] = useState9([]);
|
|
4654
5552
|
const tagsKey = config.contentTags?.join(",");
|
|
4655
5553
|
useEffect12(() => {
|
|
4656
5554
|
if (!config.showRecentMessages) return;
|
|
@@ -4672,49 +5570,49 @@ function HomeRoot(props2) {
|
|
|
4672
5570
|
const avatars = config.userAvatars ?? [];
|
|
4673
5571
|
const status = config.status;
|
|
4674
5572
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
4675
|
-
return /* @__PURE__ */
|
|
4676
|
-
/* @__PURE__ */
|
|
4677
|
-
/* @__PURE__ */
|
|
4678
|
-
config.brandName ? /* @__PURE__ */
|
|
4679
|
-
/* @__PURE__ */
|
|
4680
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
4681
|
-
/* @__PURE__ */
|
|
5573
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5574
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5575
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5576
|
+
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" }),
|
|
5577
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5578
|
+
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,
|
|
5579
|
+
/* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" })
|
|
4682
5580
|
] })
|
|
4683
5581
|
] }),
|
|
4684
|
-
config.showGreeting !== false ? /* @__PURE__ */
|
|
4685
|
-
/* @__PURE__ */
|
|
4686
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5582
|
+
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5583
|
+
/* @__PURE__ */ jsx30("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5584
|
+
greeting.subtitle ? /* @__PURE__ */ jsx30("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
4687
5585
|
] }) : null
|
|
4688
5586
|
] }),
|
|
4689
|
-
/* @__PURE__ */
|
|
4690
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5587
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5588
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx30(
|
|
4691
5589
|
HomeSearchButton,
|
|
4692
5590
|
{
|
|
4693
5591
|
placeholder: strings.homeSearchPlaceholder,
|
|
4694
5592
|
onActivate: () => nav.switchToLayout("help")
|
|
4695
5593
|
}
|
|
4696
5594
|
) : null,
|
|
4697
|
-
recent ? /* @__PURE__ */
|
|
4698
|
-
/* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
recent.preview ? /* @__PURE__ */
|
|
5595
|
+
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: [
|
|
5596
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5597
|
+
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5598
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5599
|
+
recent.preview ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
4702
5600
|
] }),
|
|
4703
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5601
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
4704
5602
|
] }) }) : null,
|
|
4705
|
-
status ? /* @__PURE__ */
|
|
5603
|
+
status ? /* @__PURE__ */ jsx30(
|
|
4706
5604
|
HomeCard,
|
|
4707
5605
|
{
|
|
4708
5606
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
4709
|
-
children: /* @__PURE__ */
|
|
4710
|
-
/* @__PURE__ */
|
|
4711
|
-
/* @__PURE__ */
|
|
5607
|
+
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5608
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(StatusOkIcon, {}) }),
|
|
5609
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
4712
5610
|
] })
|
|
4713
5611
|
}
|
|
4714
5612
|
) : null,
|
|
4715
|
-
content.length > 0 ? /* @__PURE__ */
|
|
4716
|
-
/* @__PURE__ */
|
|
4717
|
-
/* @__PURE__ */
|
|
5613
|
+
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5614
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5615
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx30(
|
|
4718
5616
|
ListRow,
|
|
4719
5617
|
{
|
|
4720
5618
|
title: item.title,
|
|
@@ -4730,20 +5628,20 @@ function HomeRoot(props2) {
|
|
|
4730
5628
|
}
|
|
4731
5629
|
var homeLayout = {
|
|
4732
5630
|
Icon: HomeIcon,
|
|
4733
|
-
Root: (props2) => /* @__PURE__ */
|
|
5631
|
+
Root: (props2) => /* @__PURE__ */ jsx30(HomeRoot, { ...props2 })
|
|
4734
5632
|
};
|
|
4735
5633
|
|
|
4736
5634
|
// src/ui/modules/news.tsx
|
|
4737
|
-
import { useEffect as useEffect13, useState as
|
|
4738
|
-
import { jsx as
|
|
4739
|
-
var
|
|
5635
|
+
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5636
|
+
import { jsx as jsx31, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5637
|
+
var p26 = BRAND.cssPrefix;
|
|
4740
5638
|
var log14 = logger.scope("news");
|
|
4741
5639
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
4742
5640
|
const tags = config.contentTags;
|
|
4743
|
-
const [state, setState] =
|
|
4744
|
-
const [errorMsg, setErrorMsg] =
|
|
4745
|
-
const [items, setItems] =
|
|
4746
|
-
const [reloadKey, setReloadKey] =
|
|
5641
|
+
const [state, setState] = useState10("loading");
|
|
5642
|
+
const [errorMsg, setErrorMsg] = useState10(strings.errorGeneric);
|
|
5643
|
+
const [items, setItems] = useState10([]);
|
|
5644
|
+
const [reloadKey, setReloadKey] = useState10(0);
|
|
4747
5645
|
useEffect13(() => {
|
|
4748
5646
|
let cancelled = false;
|
|
4749
5647
|
setState("loading");
|
|
@@ -4762,38 +5660,38 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
4762
5660
|
};
|
|
4763
5661
|
}, [transport, tags, reloadKey]);
|
|
4764
5662
|
function renderBody() {
|
|
4765
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5663
|
+
if (state === "loading") return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsLoading, strings });
|
|
4766
5664
|
if (state === "error") {
|
|
4767
|
-
return /* @__PURE__ */
|
|
5665
|
+
return /* @__PURE__ */ jsx31(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
4768
5666
|
}
|
|
4769
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
4770
|
-
return /* @__PURE__ */
|
|
5667
|
+
if (items.length === 0) return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsEmpty, strings });
|
|
5668
|
+
return /* @__PURE__ */ jsx31("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
4771
5669
|
"button",
|
|
4772
5670
|
{
|
|
4773
5671
|
type: "button",
|
|
4774
|
-
class: `${
|
|
5672
|
+
class: `${p26}-news-card`,
|
|
4775
5673
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
4776
5674
|
"data-testid": tid(TID.newsItem, item.id),
|
|
4777
5675
|
children: [
|
|
4778
|
-
item.image ? /* @__PURE__ */
|
|
4779
|
-
/* @__PURE__ */
|
|
4780
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
4781
|
-
/* @__PURE__ */
|
|
4782
|
-
item.description ? /* @__PURE__ */
|
|
5676
|
+
item.image ? /* @__PURE__ */ jsx31("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5677
|
+
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5678
|
+
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,
|
|
5679
|
+
/* @__PURE__ */ jsx31("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5680
|
+
item.description ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
4783
5681
|
] })
|
|
4784
5682
|
]
|
|
4785
5683
|
},
|
|
4786
5684
|
item.id
|
|
4787
5685
|
)) });
|
|
4788
5686
|
}
|
|
4789
|
-
return /* @__PURE__ */
|
|
4790
|
-
/* @__PURE__ */
|
|
4791
|
-
/* @__PURE__ */
|
|
5687
|
+
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5688
|
+
/* @__PURE__ */ jsx31(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx31(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5689
|
+
/* @__PURE__ */ jsx31("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
4792
5690
|
] });
|
|
4793
5691
|
}
|
|
4794
5692
|
var newsLayout = {
|
|
4795
5693
|
Icon: NewsIcon,
|
|
4796
|
-
Root: (props2) => /* @__PURE__ */
|
|
5694
|
+
Root: (props2) => /* @__PURE__ */ jsx31(NewsRoot, { ...props2 })
|
|
4797
5695
|
};
|
|
4798
5696
|
|
|
4799
5697
|
// src/ui/modules/registry.ts
|
|
@@ -4805,28 +5703,28 @@ var LAYOUTS = {
|
|
|
4805
5703
|
};
|
|
4806
5704
|
|
|
4807
5705
|
// src/ui/home-tab-bar.tsx
|
|
4808
|
-
import { jsx as
|
|
4809
|
-
var
|
|
5706
|
+
import { jsx as jsx32, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5707
|
+
var p27 = BRAND.cssPrefix;
|
|
4810
5708
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
4811
|
-
return /* @__PURE__ */
|
|
5709
|
+
return /* @__PURE__ */ jsx32("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
4812
5710
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
4813
5711
|
const selected = m.id === activeTab;
|
|
4814
5712
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
4815
|
-
return /* @__PURE__ */
|
|
5713
|
+
return /* @__PURE__ */ jsxs26(
|
|
4816
5714
|
"button",
|
|
4817
5715
|
{
|
|
4818
5716
|
type: "button",
|
|
4819
5717
|
role: "tab",
|
|
4820
5718
|
"aria-selected": selected,
|
|
4821
|
-
class: `${
|
|
5719
|
+
class: `${p27}-tab`,
|
|
4822
5720
|
onClick: () => onSelect(m.id),
|
|
4823
5721
|
"data-testid": tid(TID.tab, m.id),
|
|
4824
5722
|
children: [
|
|
4825
|
-
/* @__PURE__ */
|
|
4826
|
-
/* @__PURE__ */
|
|
4827
|
-
badge ? /* @__PURE__ */
|
|
5723
|
+
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5724
|
+
/* @__PURE__ */ jsx32(Icon, {}),
|
|
5725
|
+
badge ? /* @__PURE__ */ jsx32("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
4828
5726
|
] }),
|
|
4829
|
-
/* @__PURE__ */
|
|
5727
|
+
/* @__PURE__ */ jsx32("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
4830
5728
|
]
|
|
4831
5729
|
},
|
|
4832
5730
|
m.id
|
|
@@ -4835,12 +5733,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
4835
5733
|
}
|
|
4836
5734
|
|
|
4837
5735
|
// src/ui/iframe-view.tsx
|
|
4838
|
-
import { jsx as
|
|
4839
|
-
var
|
|
5736
|
+
import { jsx as jsx33, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5737
|
+
var p28 = BRAND.cssPrefix;
|
|
4840
5738
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
4841
5739
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
4842
|
-
return /* @__PURE__ */
|
|
4843
|
-
/* @__PURE__ */
|
|
5740
|
+
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5741
|
+
/* @__PURE__ */ jsx33(
|
|
4844
5742
|
BackHeader,
|
|
4845
5743
|
{
|
|
4846
5744
|
title: title || strings.moduleBack,
|
|
@@ -4849,10 +5747,10 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
4849
5747
|
actions
|
|
4850
5748
|
}
|
|
4851
5749
|
),
|
|
4852
|
-
/* @__PURE__ */
|
|
5750
|
+
/* @__PURE__ */ jsx33(
|
|
4853
5751
|
"iframe",
|
|
4854
5752
|
{
|
|
4855
|
-
class: `${
|
|
5753
|
+
class: `${p28}-content-frame`,
|
|
4856
5754
|
src: url,
|
|
4857
5755
|
title: title || "content",
|
|
4858
5756
|
sandbox: SANDBOX,
|
|
@@ -4865,14 +5763,14 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
4865
5763
|
}
|
|
4866
5764
|
|
|
4867
5765
|
// src/ui/content-view.tsx
|
|
4868
|
-
import { useCallback as useCallback3, useEffect as useEffect14, useState as
|
|
4869
|
-
import { jsx as
|
|
4870
|
-
var
|
|
5766
|
+
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5767
|
+
import { jsx as jsx34, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5768
|
+
var p29 = BRAND.cssPrefix;
|
|
4871
5769
|
var log15 = logger.scope("content");
|
|
4872
5770
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
4873
|
-
const [item, setItem] =
|
|
4874
|
-
const [failed, setFailed] =
|
|
4875
|
-
const [reloadKey, setReloadKey] =
|
|
5771
|
+
const [item, setItem] = useState11(null);
|
|
5772
|
+
const [failed, setFailed] = useState11(false);
|
|
5773
|
+
const [reloadKey, setReloadKey] = useState11(0);
|
|
4876
5774
|
const retry = useCallback3(() => {
|
|
4877
5775
|
setFailed(false);
|
|
4878
5776
|
setItem(null);
|
|
@@ -4895,17 +5793,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
4895
5793
|
};
|
|
4896
5794
|
}, [transport, id, reloadKey]);
|
|
4897
5795
|
function renderBody() {
|
|
4898
|
-
if (failed) return /* @__PURE__ */
|
|
4899
|
-
if (item === null) return /* @__PURE__ */
|
|
4900
|
-
return /* @__PURE__ */
|
|
4901
|
-
item.image ? /* @__PURE__ */
|
|
4902
|
-
item.description ? /* @__PURE__ */
|
|
4903
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
4904
|
-
/* @__PURE__ */
|
|
5796
|
+
if (failed) return /* @__PURE__ */ jsx34(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5797
|
+
if (item === null) return /* @__PURE__ */ jsx34(ModuleState, { message: strings.contentLoading, strings });
|
|
5798
|
+
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5799
|
+
item.image ? /* @__PURE__ */ jsx34("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5800
|
+
item.description ? /* @__PURE__ */ jsx34("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5801
|
+
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,
|
|
5802
|
+
/* @__PURE__ */ jsx34(StaticMarkdown, { text: item.content ?? "" })
|
|
4905
5803
|
] });
|
|
4906
5804
|
}
|
|
4907
|
-
return /* @__PURE__ */
|
|
4908
|
-
/* @__PURE__ */
|
|
5805
|
+
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5806
|
+
/* @__PURE__ */ jsx34(
|
|
4909
5807
|
BackHeader,
|
|
4910
5808
|
{
|
|
4911
5809
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -4915,13 +5813,13 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
4915
5813
|
testid: TID.backHeader
|
|
4916
5814
|
}
|
|
4917
5815
|
),
|
|
4918
|
-
/* @__PURE__ */
|
|
5816
|
+
/* @__PURE__ */ jsx34("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
4919
5817
|
] });
|
|
4920
5818
|
}
|
|
4921
5819
|
|
|
4922
5820
|
// src/ui/messenger-home.tsx
|
|
4923
|
-
import { jsx as
|
|
4924
|
-
var
|
|
5821
|
+
import { jsx as jsx35, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5822
|
+
var p30 = BRAND.cssPrefix;
|
|
4925
5823
|
function MessengerHome({
|
|
4926
5824
|
panelProps,
|
|
4927
5825
|
enabledModules,
|
|
@@ -4953,7 +5851,7 @@ function MessengerHome({
|
|
|
4953
5851
|
}, []);
|
|
4954
5852
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
4955
5853
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
4956
|
-
const navState =
|
|
5854
|
+
const navState = useComputed6(() => nav.sig.value).value;
|
|
4957
5855
|
const top = topScreen(navState);
|
|
4958
5856
|
const activeModule = options.modules.byId[navState.activeTab];
|
|
4959
5857
|
const isReader = top?.kind === "iframe" || top?.kind === "content";
|
|
@@ -4989,12 +5887,12 @@ function MessengerHome({
|
|
|
4989
5887
|
nav: moduleNav,
|
|
4990
5888
|
panelProps
|
|
4991
5889
|
});
|
|
4992
|
-
const plainActions = /* @__PURE__ */
|
|
5890
|
+
const plainActions = /* @__PURE__ */ jsx35(HeaderActions, { panelProps, variant: "plain" });
|
|
4993
5891
|
let body;
|
|
4994
5892
|
if (top?.kind === "iframe") {
|
|
4995
|
-
body = /* @__PURE__ */
|
|
5893
|
+
body = /* @__PURE__ */ jsx35(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
4996
5894
|
} else if (top?.kind === "content") {
|
|
4997
|
-
body = /* @__PURE__ */
|
|
5895
|
+
body = /* @__PURE__ */ jsx35(
|
|
4998
5896
|
ContentView,
|
|
4999
5897
|
{
|
|
5000
5898
|
id: top.id,
|
|
@@ -5006,7 +5904,7 @@ function MessengerHome({
|
|
|
5006
5904
|
}
|
|
5007
5905
|
);
|
|
5008
5906
|
} else if (activeModule?.layout === "chat") {
|
|
5009
|
-
body = /* @__PURE__ */
|
|
5907
|
+
body = /* @__PURE__ */ jsx35(
|
|
5010
5908
|
PanelContent,
|
|
5011
5909
|
{
|
|
5012
5910
|
...panelProps,
|
|
@@ -5017,23 +5915,23 @@ function MessengerHome({
|
|
|
5017
5915
|
);
|
|
5018
5916
|
} else if (activeModule) {
|
|
5019
5917
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
5020
|
-
body = Root ? /* @__PURE__ */
|
|
5918
|
+
body = Root ? /* @__PURE__ */ jsx35(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
5021
5919
|
} else {
|
|
5022
5920
|
body = null;
|
|
5023
5921
|
}
|
|
5024
|
-
return /* @__PURE__ */
|
|
5922
|
+
return /* @__PURE__ */ jsxs29(
|
|
5025
5923
|
"div",
|
|
5026
5924
|
{
|
|
5027
5925
|
ref: containerRef,
|
|
5028
|
-
class: `${
|
|
5926
|
+
class: `${p30}-panel ${p30}-messenger`,
|
|
5029
5927
|
role: "dialog",
|
|
5030
5928
|
"aria-modal": "false",
|
|
5031
5929
|
"aria-label": strings.panelTitle,
|
|
5032
5930
|
style: { position: "relative" },
|
|
5033
5931
|
"data-testid": TID.messengerHome,
|
|
5034
5932
|
children: [
|
|
5035
|
-
/* @__PURE__ */
|
|
5036
|
-
showTabBar ? /* @__PURE__ */
|
|
5933
|
+
/* @__PURE__ */ jsx35("div", { class: `${p30}-messenger-body`, children: body }),
|
|
5934
|
+
showTabBar ? /* @__PURE__ */ jsx35(
|
|
5037
5935
|
HomeTabBar,
|
|
5038
5936
|
{
|
|
5039
5937
|
modules: enabledModules,
|
|
@@ -5043,8 +5941,8 @@ function MessengerHome({
|
|
|
5043
5941
|
onSelect: nav.switchTab
|
|
5044
5942
|
}
|
|
5045
5943
|
) : null,
|
|
5046
|
-
/* @__PURE__ */
|
|
5047
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
5944
|
+
/* @__PURE__ */ jsx35(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
5945
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx35(
|
|
5048
5946
|
ResizeGrip,
|
|
5049
5947
|
{
|
|
5050
5948
|
panelEl: containerRef.current,
|
|
@@ -5061,29 +5959,29 @@ function MessengerHome({
|
|
|
5061
5959
|
}
|
|
5062
5960
|
|
|
5063
5961
|
// src/ui/modules-empty.tsx
|
|
5064
|
-
import { jsx as
|
|
5065
|
-
var
|
|
5962
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
5963
|
+
var p31 = BRAND.cssPrefix;
|
|
5066
5964
|
function ModulesEmpty({ strings, onClose }) {
|
|
5067
|
-
return /* @__PURE__ */
|
|
5965
|
+
return /* @__PURE__ */ jsxs30(
|
|
5068
5966
|
"div",
|
|
5069
5967
|
{
|
|
5070
|
-
class: `${
|
|
5968
|
+
class: `${p31}-panel ${p31}-modules-empty`,
|
|
5071
5969
|
role: "dialog",
|
|
5072
5970
|
"aria-label": strings.panelTitle,
|
|
5073
5971
|
"data-testid": TID.modulesEmpty,
|
|
5074
5972
|
children: [
|
|
5075
|
-
onClose ? /* @__PURE__ */
|
|
5973
|
+
onClose ? /* @__PURE__ */ jsx36(
|
|
5076
5974
|
"button",
|
|
5077
5975
|
{
|
|
5078
5976
|
type: "button",
|
|
5079
|
-
class: `${
|
|
5977
|
+
class: `${p31}-icon-btn ${p31}-modules-empty-close`,
|
|
5080
5978
|
onClick: onClose,
|
|
5081
5979
|
"aria-label": strings.close,
|
|
5082
5980
|
title: strings.close,
|
|
5083
|
-
children: /* @__PURE__ */
|
|
5981
|
+
children: /* @__PURE__ */ jsx36(CloseIcon, {})
|
|
5084
5982
|
}
|
|
5085
5983
|
) : null,
|
|
5086
|
-
/* @__PURE__ */
|
|
5984
|
+
/* @__PURE__ */ jsx36("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
5087
5985
|
]
|
|
5088
5986
|
}
|
|
5089
5987
|
);
|
|
@@ -5138,11 +6036,11 @@ function animateTypewriter(msg, text, charsPerSecond, abort) {
|
|
|
5138
6036
|
}
|
|
5139
6037
|
|
|
5140
6038
|
// src/ui/use-launcher-callout.ts
|
|
5141
|
-
import { useCallback as useCallback5, useEffect as useEffect16, useState as
|
|
6039
|
+
import { useCallback as useCallback5, useEffect as useEffect16, useState as useState12 } from "preact/hooks";
|
|
5142
6040
|
function useLauncherCallout({ callout, persistence }) {
|
|
5143
6041
|
const textKey = callout?.text ?? "";
|
|
5144
6042
|
const persistent = callout?.persistent ?? true;
|
|
5145
|
-
const [dismissed, setDismissed] =
|
|
6043
|
+
const [dismissed, setDismissed] = useState12(() => persistent ? false : persistence.loadCalloutDismissed(textKey));
|
|
5146
6044
|
useEffect16(() => {
|
|
5147
6045
|
setDismissed(persistent ? false : persistence.loadCalloutDismissed(textKey));
|
|
5148
6046
|
}, [textKey, persistent, persistence]);
|
|
@@ -5154,21 +6052,21 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
5154
6052
|
}
|
|
5155
6053
|
|
|
5156
6054
|
// src/ui/app.tsx
|
|
5157
|
-
import { jsx as
|
|
6055
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
5158
6056
|
var log16 = logger.scope("app");
|
|
5159
|
-
var
|
|
6057
|
+
var p32 = BRAND.cssPrefix;
|
|
5160
6058
|
function App({ options, hostElement, bus }) {
|
|
5161
|
-
const [persistence] =
|
|
5162
|
-
const [visitorId, setVisitorId] =
|
|
6059
|
+
const [persistence] = useState13(() => createPersistence(options.widgetId, options.storage));
|
|
6060
|
+
const [visitorId, setVisitorId] = useState13(() => persistence.getVisitorId());
|
|
5163
6061
|
const initialSettings = persistence.loadUserPrefs();
|
|
5164
|
-
const [activeLocale, setActiveLocale] =
|
|
5165
|
-
const [activeThemeMode, setActiveThemeMode] =
|
|
6062
|
+
const [activeLocale, setActiveLocale] = useState13(() => initialSettings.locale ?? options.locale);
|
|
6063
|
+
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
5166
6064
|
() => initialSettings.themeMode ?? options.themeMode
|
|
5167
6065
|
);
|
|
5168
|
-
const sessionIdSig =
|
|
5169
|
-
const messagesSig =
|
|
5170
|
-
const unreadCountSig =
|
|
5171
|
-
const [loadingMessages, setLoadingMessages] =
|
|
6066
|
+
const sessionIdSig = useSignal2(persistence.loadSessionId());
|
|
6067
|
+
const messagesSig = useSignal2([]);
|
|
6068
|
+
const unreadCountSig = useSignal2(0);
|
|
6069
|
+
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
5172
6070
|
function landingTab() {
|
|
5173
6071
|
const list = options.modules.list;
|
|
5174
6072
|
const ids = new Set(list.map((m) => m.id));
|
|
@@ -5187,14 +6085,14 @@ function App({ options, hostElement, bus }) {
|
|
|
5187
6085
|
const homeNav = homeNavRef.current;
|
|
5188
6086
|
const chatTabIdRef = useRef8(void 0);
|
|
5189
6087
|
chatTabIdRef.current = chatTabId();
|
|
5190
|
-
const [sessionReady, setSessionReady] =
|
|
6088
|
+
const [sessionReady, setSessionReady] = useState13(false);
|
|
5191
6089
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
5192
6090
|
const initialPanelRef = useRef8(
|
|
5193
6091
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
5194
6092
|
);
|
|
5195
|
-
const [isOpen, setIsOpen] =
|
|
6093
|
+
const [isOpen, setIsOpen] = useState13(initialPanelRef.current.panelOpen);
|
|
5196
6094
|
const initialPanelApplied = useRef8(false);
|
|
5197
|
-
const [launcherLeaving, setLauncherLeaving] =
|
|
6095
|
+
const [launcherLeaving, setLauncherLeaving] = useState13(false);
|
|
5198
6096
|
const { dismissed: calloutDismissed, dismissCallout: dismissCalloutRaw } = useLauncherCallout({
|
|
5199
6097
|
callout: options.launcher.callout,
|
|
5200
6098
|
persistence
|
|
@@ -5205,19 +6103,20 @@ function App({ options, hostElement, bus }) {
|
|
|
5205
6103
|
bus.emit("calloutDismiss", void 0);
|
|
5206
6104
|
dismissCalloutRaw();
|
|
5207
6105
|
}, [bus, dismissCalloutRaw]);
|
|
5208
|
-
const [panelSize, setPanelSize] =
|
|
6106
|
+
const [panelSize, setPanelSize] = useState13(initialPanelRef.current.panelSize);
|
|
5209
6107
|
const initialSizeApplied = useRef8(false);
|
|
5210
|
-
const [view, setView] =
|
|
5211
|
-
const [canSend, setCanSend] =
|
|
5212
|
-
const [streaming, setStreaming] =
|
|
5213
|
-
const [agent, setAgent] =
|
|
5214
|
-
const [suggestions, setSuggestions] =
|
|
5215
|
-
const [activeCancel, setActiveCancel] =
|
|
6108
|
+
const [view, setView] = useState13("chat");
|
|
6109
|
+
const [canSend, setCanSend] = useState13(true);
|
|
6110
|
+
const [streaming, setStreaming] = useState13(false);
|
|
6111
|
+
const [agent, setAgent] = useState13(null);
|
|
6112
|
+
const [suggestions, setSuggestions] = useState13([]);
|
|
6113
|
+
const [activeCancel, setActiveCancel] = useState13(null);
|
|
5216
6114
|
const welcomeAbortRef = useRef8(null);
|
|
5217
|
-
const [parsedSite, setParsedSite] =
|
|
5218
|
-
const [parsedBlocks, setParsedBlocks] =
|
|
5219
|
-
const [sidebarCollapsed, setSidebarCollapsed] =
|
|
5220
|
-
const [
|
|
6115
|
+
const [parsedSite, setParsedSite] = useState13(void 0);
|
|
6116
|
+
const [parsedBlocks, setParsedBlocks] = useState13(void 0);
|
|
6117
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState13(() => persistence.loadSidebarCollapsed() ?? false);
|
|
6118
|
+
const [intakeValues, setIntakeValues] = useState13(() => persistence.loadIntake());
|
|
6119
|
+
const [transport] = useState13(
|
|
5221
6120
|
() => new AgentTransport({
|
|
5222
6121
|
baseUrl: options.baseUrl,
|
|
5223
6122
|
auth: createAuth({
|
|
@@ -5228,8 +6127,8 @@ function App({ options, hostElement, bus }) {
|
|
|
5228
6127
|
endpoints: options.endpoints
|
|
5229
6128
|
})
|
|
5230
6129
|
);
|
|
5231
|
-
const [reducer] =
|
|
5232
|
-
const [feedback] =
|
|
6130
|
+
const [reducer] = useState13(() => new StreamReducer(messagesSig));
|
|
6131
|
+
const [feedback] = useState13(() => new FeedbackBus(options.sound, options.haptics));
|
|
5233
6132
|
const patchAndSync = useCallback6(
|
|
5234
6133
|
(patch) => {
|
|
5235
6134
|
persistence.patchUserPrefs(patch);
|
|
@@ -5399,9 +6298,11 @@ function App({ options, hostElement, bus }) {
|
|
|
5399
6298
|
);
|
|
5400
6299
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
5401
6300
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
6301
|
+
const intakeSig = JSON.stringify(intakeValues ?? null);
|
|
5402
6302
|
useEffect17(() => {
|
|
5403
|
-
|
|
5404
|
-
|
|
6303
|
+
const merged = intakeValues ? { ...intakeValues, ...options.userContext } : options.userContext;
|
|
6304
|
+
transport.setContext(merged, toWirePageContext(options.pageContext));
|
|
6305
|
+
}, [transport, userSig, pageSig, intakeSig]);
|
|
5405
6306
|
const runResume = useCallback6(
|
|
5406
6307
|
async (handle) => {
|
|
5407
6308
|
let bubble = null;
|
|
@@ -5489,24 +6390,8 @@ function App({ options, hostElement, bus }) {
|
|
|
5489
6390
|
document.addEventListener("keydown", onKey);
|
|
5490
6391
|
return () => document.removeEventListener("keydown", onKey);
|
|
5491
6392
|
}, [isOpen, options.mode]);
|
|
5492
|
-
const
|
|
5493
|
-
async (
|
|
5494
|
-
log16.info("send", { textLen: text.length, attachments: attachments.length, streaming });
|
|
5495
|
-
if (streaming) return;
|
|
5496
|
-
bus.emit("send", { text, attachmentCount: attachments.length });
|
|
5497
|
-
if (suggestions.length > 0) setSuggestions([]);
|
|
5498
|
-
const uploaded = await uploadAttachments(transport, attachments, (err) => {
|
|
5499
|
-
log16.warn("upload failed", { err });
|
|
5500
|
-
bus.emit("error", err);
|
|
5501
|
-
options.onError?.(err);
|
|
5502
|
-
});
|
|
5503
|
-
feedback.unlock();
|
|
5504
|
-
feedback.play("messageSent");
|
|
5505
|
-
const userMsg = makeUserMessage(text, uploaded);
|
|
5506
|
-
const assistantMsg = makeAssistantMessage();
|
|
5507
|
-
messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
|
|
5508
|
-
reducer.attach(assistantMsg);
|
|
5509
|
-
emitMessage(bus, options, "user", text);
|
|
6393
|
+
const streamAssistant = useCallback6(
|
|
6394
|
+
async (assistantMsg, trigger) => {
|
|
5510
6395
|
const activeSessionId = sessionIdSig.value ?? uuid7();
|
|
5511
6396
|
if (!sessionIdSig.value) {
|
|
5512
6397
|
sessionIdSig.value = activeSessionId;
|
|
@@ -5515,10 +6400,10 @@ function App({ options, hostElement, bus }) {
|
|
|
5515
6400
|
const body = buildSendMessageRequest({
|
|
5516
6401
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
5517
6402
|
sessionId: activeSessionId,
|
|
5518
|
-
// textModel + imageModel are backend-only — selected per
|
|
5519
|
-
// deployment in the dashboard, never passed up by the widget.
|
|
6403
|
+
// textModel + imageModel are backend-only — selected per deployment.
|
|
5520
6404
|
tools: options.features.tools,
|
|
5521
6405
|
responseMode: options.responseMode,
|
|
6406
|
+
trigger,
|
|
5522
6407
|
// Identity + preferences ride on every message — server may need
|
|
5523
6408
|
// them to route, persist, or reconcile in-flight.
|
|
5524
6409
|
visitorId,
|
|
@@ -5550,19 +6435,95 @@ function App({ options, hostElement, bus }) {
|
|
|
5550
6435
|
messagesSig.value = [...messagesSig.value];
|
|
5551
6436
|
}
|
|
5552
6437
|
},
|
|
5553
|
-
[
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
6438
|
+
[transport, reducer, messagesSig, sessionIdSig, options, bus, feedback, persistence, visitorId]
|
|
6439
|
+
);
|
|
6440
|
+
const resolveTool = useCallback6(
|
|
6441
|
+
(toolCallId, trigger, mutate) => {
|
|
6442
|
+
if (streaming) return;
|
|
6443
|
+
const last = messagesSig.value.at(-1);
|
|
6444
|
+
const part = last?.partsSig.value.find(
|
|
6445
|
+
(pt) => pt.kind === "tool" && pt.toolCallId === toolCallId
|
|
6446
|
+
);
|
|
6447
|
+
if (!part) {
|
|
6448
|
+
log16.warn("resolveTool: tool part not found", { toolCallId });
|
|
6449
|
+
return;
|
|
6450
|
+
}
|
|
6451
|
+
mutate(part);
|
|
6452
|
+
if (last) last.partsSig.value = [...last.partsSig.value];
|
|
6453
|
+
const assistantMsg = makeAssistantMessage();
|
|
6454
|
+
messagesSig.value = [...messagesSig.value, assistantMsg];
|
|
6455
|
+
reducer.attach(assistantMsg);
|
|
6456
|
+
void streamAssistant(assistantMsg, trigger);
|
|
6457
|
+
},
|
|
6458
|
+
[streaming, messagesSig, reducer, streamAssistant]
|
|
6459
|
+
);
|
|
6460
|
+
const handleToolResult = useCallback6(
|
|
6461
|
+
(toolCallId, output) => {
|
|
6462
|
+
log16.info("toolResult", { toolCallId });
|
|
6463
|
+
bus.emit("toolResult", { toolCallId });
|
|
6464
|
+
resolveTool(toolCallId, TRIGGER.toolResult, (part) => {
|
|
6465
|
+
part.outputSig.value = output;
|
|
6466
|
+
part.stateSig.value = "output";
|
|
6467
|
+
});
|
|
6468
|
+
},
|
|
6469
|
+
[bus, resolveTool]
|
|
6470
|
+
);
|
|
6471
|
+
const handleToolDecision = useCallback6(
|
|
6472
|
+
(toolCallId, approved, reason) => {
|
|
6473
|
+
log16.info("toolDecision", { toolCallId, approved });
|
|
6474
|
+
bus.emit("toolDecision", { toolCallId, approved });
|
|
6475
|
+
resolveTool(toolCallId, TRIGGER.toolApproval, (part) => {
|
|
6476
|
+
const id = part.approvalSig.value?.id ?? toolCallId;
|
|
6477
|
+
part.approvalSig.value = { id, approved, reason };
|
|
6478
|
+
part.stateSig.value = "output";
|
|
6479
|
+
});
|
|
6480
|
+
},
|
|
6481
|
+
[bus, resolveTool]
|
|
6482
|
+
);
|
|
6483
|
+
const toolInteraction = useMemo3(
|
|
6484
|
+
() => ({ humanInLoop: options.features.humanInLoop, onResult: handleToolResult, onDecision: handleToolDecision }),
|
|
6485
|
+
[options.features.humanInLoop, handleToolResult, handleToolDecision]
|
|
6486
|
+
);
|
|
6487
|
+
const intakePending = options.intake.enabled && intakeValues === null;
|
|
6488
|
+
const handleIntakeComplete = useCallback6(
|
|
6489
|
+
(values) => {
|
|
6490
|
+
const hasValues = Object.keys(values).length > 0;
|
|
6491
|
+
log16.info("intakeComplete", { fields: Object.keys(values).length, skipped: !hasValues });
|
|
6492
|
+
persistence.saveIntake(values);
|
|
6493
|
+
setIntakeValues(values);
|
|
6494
|
+
bus.emit("intakeSubmit", values);
|
|
6495
|
+
if (!hasValues) return;
|
|
6496
|
+
const activeSessionId = sessionIdSig.value ?? uuid7();
|
|
6497
|
+
if (!sessionIdSig.value) {
|
|
6498
|
+
sessionIdSig.value = activeSessionId;
|
|
6499
|
+
persistence.saveSessionId(activeSessionId);
|
|
6500
|
+
transport.primeIdentity(void 0, activeSessionId);
|
|
6501
|
+
}
|
|
6502
|
+
void transport.submitIntake(activeSessionId, values);
|
|
6503
|
+
},
|
|
6504
|
+
[persistence, bus, sessionIdSig, transport]
|
|
6505
|
+
);
|
|
6506
|
+
const handleSend = useCallback6(
|
|
6507
|
+
async (text, attachments) => {
|
|
6508
|
+
log16.info("send", { textLen: text.length, attachments: attachments.length, streaming });
|
|
6509
|
+
if (streaming) return;
|
|
6510
|
+
bus.emit("send", { text, attachmentCount: attachments.length });
|
|
6511
|
+
if (suggestions.length > 0) setSuggestions([]);
|
|
6512
|
+
const uploaded = await uploadAttachments(transport, attachments, (err) => {
|
|
6513
|
+
log16.warn("upload failed", { err });
|
|
6514
|
+
bus.emit("error", err);
|
|
6515
|
+
options.onError?.(err);
|
|
6516
|
+
});
|
|
6517
|
+
feedback.unlock();
|
|
6518
|
+
feedback.play("messageSent");
|
|
6519
|
+
const userMsg = makeUserMessage(text, uploaded);
|
|
6520
|
+
const assistantMsg = makeAssistantMessage();
|
|
6521
|
+
messagesSig.value = [...messagesSig.value, userMsg, assistantMsg];
|
|
6522
|
+
reducer.attach(assistantMsg);
|
|
6523
|
+
emitMessage(bus, options, "user", text);
|
|
6524
|
+
await streamAssistant(assistantMsg, TRIGGER.submitMessage);
|
|
6525
|
+
},
|
|
6526
|
+
[streaming, transport, bus, options, suggestions.length, messagesSig, reducer, streamAssistant]
|
|
5566
6527
|
);
|
|
5567
6528
|
const handleStop = useCallback6(() => {
|
|
5568
6529
|
log16.info("stop");
|
|
@@ -5766,7 +6727,10 @@ function App({ options, hostElement, bus }) {
|
|
|
5766
6727
|
log16.info("suggestion", { text });
|
|
5767
6728
|
bus.emit("suggestion", { text });
|
|
5768
6729
|
void handleSend(text, []);
|
|
5769
|
-
}
|
|
6730
|
+
},
|
|
6731
|
+
intakePending,
|
|
6732
|
+
onIntakeComplete: handleIntakeComplete,
|
|
6733
|
+
tool: toolInteraction
|
|
5770
6734
|
};
|
|
5771
6735
|
const onSelectSession = (sessionId) => {
|
|
5772
6736
|
void handleSelectHistoryChat(sessionId);
|
|
@@ -5778,12 +6742,12 @@ function App({ options, hostElement, bus }) {
|
|
|
5778
6742
|
const renderSurface = (size) => {
|
|
5779
6743
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
5780
6744
|
if (enabledModules.length === 0) {
|
|
5781
|
-
return /* @__PURE__ */
|
|
6745
|
+
return /* @__PURE__ */ jsx37(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
5782
6746
|
}
|
|
5783
6747
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
5784
|
-
return /* @__PURE__ */
|
|
6748
|
+
return /* @__PURE__ */ jsx37(Panel, { ...panelProps, panelSize: size });
|
|
5785
6749
|
}
|
|
5786
|
-
return /* @__PURE__ */
|
|
6750
|
+
return /* @__PURE__ */ jsx37(
|
|
5787
6751
|
MessengerHome,
|
|
5788
6752
|
{
|
|
5789
6753
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
@@ -5801,7 +6765,7 @@ function App({ options, hostElement, bus }) {
|
|
|
5801
6765
|
void handleSelectHistoryChat(chat.sessionId);
|
|
5802
6766
|
};
|
|
5803
6767
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
5804
|
-
return /* @__PURE__ */
|
|
6768
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
5805
6769
|
PageShell,
|
|
5806
6770
|
{
|
|
5807
6771
|
site: parsedSite,
|
|
@@ -5820,15 +6784,15 @@ function App({ options, hostElement, bus }) {
|
|
|
5820
6784
|
}
|
|
5821
6785
|
if (isInlineLike) {
|
|
5822
6786
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
5823
|
-
return /* @__PURE__ */
|
|
6787
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
5824
6788
|
}
|
|
5825
6789
|
const drawerEdgeTab = options.mode === "drawer";
|
|
5826
6790
|
const triggerOwnedByPage = options.mode === "modal";
|
|
5827
6791
|
const launcherVisible = !triggerOwnedByPage && !options.launcher.hidden && (!isOpen || launcherLeaving);
|
|
5828
6792
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
5829
|
-
return /* @__PURE__ */
|
|
6793
|
+
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
5830
6794
|
isOpen ? renderSurface(panelSize) : null,
|
|
5831
|
-
launcherVisible ? /* @__PURE__ */
|
|
6795
|
+
launcherVisible ? /* @__PURE__ */ jsx37(
|
|
5832
6796
|
Launcher,
|
|
5833
6797
|
{
|
|
5834
6798
|
onToggle: handleOpen,
|
|
@@ -5838,7 +6802,7 @@ function App({ options, hostElement, bus }) {
|
|
|
5838
6802
|
edgeTab: drawerEdgeTab
|
|
5839
6803
|
}
|
|
5840
6804
|
) : null,
|
|
5841
|
-
calloutToRender ? /* @__PURE__ */
|
|
6805
|
+
calloutToRender ? /* @__PURE__ */ jsx37(
|
|
5842
6806
|
LauncherCallout,
|
|
5843
6807
|
{
|
|
5844
6808
|
callout: calloutToRender,
|