@helpai/elements 0.14.1 → 0.15.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/README.md +3 -3
- package/configurator.mjs +17 -15
- package/elements-web-component.esm.js +13 -13
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +13 -13
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +13 -13
- package/elements.esm.js.map +4 -4
- package/elements.js +13 -13
- package/elements.js.map +4 -4
- package/index.d.ts +43 -40
- package/index.mjs +439 -402
- package/package.json +1 -1
- package/schema.d.ts +7 -7
- package/schema.json +21 -21
- package/schema.mjs +19 -17
- package/style.css +1 -1
- package/web-component.d.ts +1 -1
- package/web-component.mjs +436 -399
package/web-component.mjs
CHANGED
|
@@ -35,7 +35,8 @@ var STRINGS_EN = {
|
|
|
35
35
|
attachmentMimeRejected: "File type not supported",
|
|
36
36
|
attachmentTooLarge: "File is too large",
|
|
37
37
|
attachmentTooMany: "Attachment limit reached",
|
|
38
|
-
|
|
38
|
+
conversationClosed: "This conversation is closed",
|
|
39
|
+
conversationLoading: "Loading conversation\u2026",
|
|
39
40
|
close: "Close",
|
|
40
41
|
collapse: "Collapse",
|
|
41
42
|
collapseSidebar: "Collapse sidebar",
|
|
@@ -55,12 +56,10 @@ var STRINGS_EN = {
|
|
|
55
56
|
history: "History",
|
|
56
57
|
historyBack: "Back to chat",
|
|
57
58
|
historyEmpty: "No previous conversations yet",
|
|
58
|
-
historyLoading: "Loading your
|
|
59
|
-
|
|
60
|
-
historyTitle: "Chat history",
|
|
59
|
+
historyLoading: "Loading your conversations\u2026",
|
|
60
|
+
historyTitle: "Conversation history",
|
|
61
61
|
language: "Language",
|
|
62
62
|
launcherOpen: "Open chat",
|
|
63
|
-
messagesLoading: "Loading conversation\u2026",
|
|
64
63
|
micStart: "Start voice input",
|
|
65
64
|
micStop: "Stop voice input",
|
|
66
65
|
micUnsupported: "Voice input is not supported in this browser",
|
|
@@ -85,7 +84,7 @@ var STRINGS_EN = {
|
|
|
85
84
|
usedTool: "Used tool",
|
|
86
85
|
// ── Messenger modules ──────────────────────────────────────────
|
|
87
86
|
tabHome: "Home",
|
|
88
|
-
|
|
87
|
+
tabConversations: "Conversations",
|
|
89
88
|
tabHelp: "Help",
|
|
90
89
|
tabNews: "News",
|
|
91
90
|
modulesEmpty: "Nothing here yet",
|
|
@@ -140,7 +139,8 @@ var STRINGS_FR = {
|
|
|
140
139
|
attachmentMimeRejected: "Type de fichier non pris en charge",
|
|
141
140
|
attachmentTooLarge: "Le fichier est trop volumineux",
|
|
142
141
|
attachmentTooMany: "Limite de pi\xE8ces jointes atteinte",
|
|
143
|
-
|
|
142
|
+
conversationClosed: "Cette conversation est ferm\xE9e",
|
|
143
|
+
conversationLoading: "Chargement de la conversation\u2026",
|
|
144
144
|
close: "Fermer",
|
|
145
145
|
collapse: "R\xE9duire",
|
|
146
146
|
collapseSidebar: "R\xE9duire la barre lat\xE9rale",
|
|
@@ -161,11 +161,9 @@ var STRINGS_FR = {
|
|
|
161
161
|
historyBack: "Retour au chat",
|
|
162
162
|
historyEmpty: "Aucune conversation pour le moment",
|
|
163
163
|
historyLoading: "Chargement de vos conversations\u2026",
|
|
164
|
-
historyNewChat: "Nouvelle conversation",
|
|
165
164
|
historyTitle: "Historique des conversations",
|
|
166
165
|
language: "Langue",
|
|
167
166
|
launcherOpen: "Ouvrir le chat",
|
|
168
|
-
messagesLoading: "Chargement de la conversation\u2026",
|
|
169
167
|
micStart: "D\xE9marrer la saisie vocale",
|
|
170
168
|
micStop: "Arr\xEAter la saisie vocale",
|
|
171
169
|
micUnsupported: "La saisie vocale n'est pas prise en charge par ce navigateur",
|
|
@@ -190,7 +188,7 @@ var STRINGS_FR = {
|
|
|
190
188
|
usedTool: "Outil utilis\xE9",
|
|
191
189
|
// ── Messenger modules ──────────────────────────────────────────
|
|
192
190
|
tabHome: "Accueil",
|
|
193
|
-
|
|
191
|
+
tabConversations: "Conversations",
|
|
194
192
|
tabHelp: "Aide",
|
|
195
193
|
tabNews: "Actualit\xE9s",
|
|
196
194
|
modulesEmpty: "Rien pour le moment",
|
|
@@ -362,7 +360,15 @@ var logger = makeLogger("core");
|
|
|
362
360
|
|
|
363
361
|
// src/core/config/user-context.ts
|
|
364
362
|
var log = logger.scope("context");
|
|
365
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
363
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
364
|
+
"visitorId",
|
|
365
|
+
"conversationId",
|
|
366
|
+
"conversationId",
|
|
367
|
+
"jwt",
|
|
368
|
+
"token",
|
|
369
|
+
"authorization",
|
|
370
|
+
"password"
|
|
371
|
+
]);
|
|
366
372
|
var MAX_KEYS = 50;
|
|
367
373
|
var MAX_STRING = 1024;
|
|
368
374
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -465,7 +471,7 @@ var DEFAULT_HAPTICS = {
|
|
|
465
471
|
enabled: true,
|
|
466
472
|
events: void 0
|
|
467
473
|
};
|
|
468
|
-
var DEFAULT_MODULES = [{ label: "
|
|
474
|
+
var DEFAULT_MODULES = [{ label: "tabConversations", layout: "chat" }];
|
|
469
475
|
var DEFAULT_HOME_MODULE = { showSearchBar: true };
|
|
470
476
|
|
|
471
477
|
// src/core/config/resolve.ts
|
|
@@ -597,7 +603,7 @@ function resolveModules(overrides) {
|
|
|
597
603
|
resolved.greetingText = m.greetingText;
|
|
598
604
|
resolved.showGreeting = m.showGreeting ?? true;
|
|
599
605
|
resolved.showSearchBar = m.showSearchBar ?? DEFAULT_HOME_MODULE.showSearchBar;
|
|
600
|
-
resolved.
|
|
606
|
+
resolved.showRecentConversations = m.showRecentConversations ?? true;
|
|
601
607
|
if (m.userAvatars && m.userAvatars.length > 0) resolved.userAvatars = m.userAvatars;
|
|
602
608
|
if (m.status) resolved.status = m.status;
|
|
603
609
|
resolved.contentBlockTitle = m.contentBlockTitle;
|
|
@@ -924,7 +930,7 @@ function parseLauncher(get, str2) {
|
|
|
924
930
|
return Object.keys(base).length > 0 ? base : null;
|
|
925
931
|
}
|
|
926
932
|
|
|
927
|
-
// src/core/start-
|
|
933
|
+
// src/core/start-conversation-shape.ts
|
|
928
934
|
function isPlainObject(raw) {
|
|
929
935
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
930
936
|
}
|
|
@@ -962,7 +968,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
962
968
|
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';
|
|
963
969
|
|
|
964
970
|
// src/styles/panel.css
|
|
965
|
-
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__-form-gate{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);max-height:60%;overflow-y:auto}.__P__-form-gate-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-form-gate-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';
|
|
971
|
+
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;align-items:flex-start;height:0;margin: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__-form-gate{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);flex:1 1 auto;min-height:0;overflow-y:auto}.__P__-list-wrap:has(+.__P__-form-gate){flex:0 1 auto;max-height:40%}.__P__-list-wrap:has(+.__P__-form-gate) .__P__-list:empty{padding:0}.__P__-form-gate-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-form-gate-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';
|
|
966
972
|
|
|
967
973
|
// src/styles/standalone.css
|
|
968
974
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1246,8 +1252,8 @@ function encodeContext(user, page) {
|
|
|
1246
1252
|
|
|
1247
1253
|
// src/stream/protocol.ts
|
|
1248
1254
|
var DEFAULT_PATHS = {
|
|
1249
|
-
/**
|
|
1250
|
-
|
|
1255
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1256
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1251
1257
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1252
1258
|
streamMessage: "/ai/agent/stream-message",
|
|
1253
1259
|
/**
|
|
@@ -1260,20 +1266,20 @@ var DEFAULT_PATHS = {
|
|
|
1260
1266
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1261
1267
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1262
1268
|
/** List the visitor's conversations. `GET`. */
|
|
1263
|
-
|
|
1264
|
-
/** Load one conversation's messages. `GET ?
|
|
1269
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1270
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1265
1271
|
listMessages: "/ai/agent/list-messages",
|
|
1266
1272
|
/**
|
|
1267
1273
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1268
1274
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1269
1275
|
* the client — a failure leaves the local cache valid; the next
|
|
1270
|
-
* `
|
|
1276
|
+
* `startConversation()` reconciles.
|
|
1271
1277
|
*/
|
|
1272
1278
|
updateSettings: "/ai/agent/update-settings",
|
|
1273
1279
|
/**
|
|
1274
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1275
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1276
|
-
* `unreadCount` (returned on `/list-
|
|
1280
|
+
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1281
|
+
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1282
|
+
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1277
1283
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1278
1284
|
*/
|
|
1279
1285
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1282,8 +1288,8 @@ var DEFAULT_PATHS = {
|
|
|
1282
1288
|
content: "/ai/agent/content",
|
|
1283
1289
|
/**
|
|
1284
1290
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1285
|
-
*
|
|
1286
|
-
* immediately, keyed by the same visitor +
|
|
1291
|
+
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1292
|
+
* immediately, keyed by the same visitor + conversation as the conversation.
|
|
1287
1293
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1288
1294
|
*/
|
|
1289
1295
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1298,7 +1304,7 @@ function buildSendMessageRequest(params) {
|
|
|
1298
1304
|
}));
|
|
1299
1305
|
const body = {
|
|
1300
1306
|
messages: wire,
|
|
1301
|
-
|
|
1307
|
+
conversationId: params.conversationId,
|
|
1302
1308
|
trigger: params.trigger ?? "submit-message"
|
|
1303
1309
|
};
|
|
1304
1310
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1386,11 +1392,11 @@ function sleep(ms, signal7) {
|
|
|
1386
1392
|
var AgentTransport = class {
|
|
1387
1393
|
constructor(opts) {
|
|
1388
1394
|
__publicField(this, "opts", opts);
|
|
1389
|
-
// Identity adopted from the start-
|
|
1395
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1390
1396
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1391
|
-
// (visitor,
|
|
1397
|
+
// (visitor, conversation) pair.
|
|
1392
1398
|
__publicField(this, "visitorId");
|
|
1393
|
-
__publicField(this, "
|
|
1399
|
+
__publicField(this, "conversationId");
|
|
1394
1400
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1395
1401
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1396
1402
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1408,27 +1414,27 @@ var AgentTransport = class {
|
|
|
1408
1414
|
this.pageContext = pageContext;
|
|
1409
1415
|
}
|
|
1410
1416
|
/**
|
|
1411
|
-
* Seed the visitor +
|
|
1412
|
-
* `
|
|
1413
|
-
* with `
|
|
1414
|
-
* `
|
|
1417
|
+
* Seed the visitor + conversation identity from persistence BEFORE the first
|
|
1418
|
+
* `startConversation` resolves. A mount-time `resumeStream()` runs in parallel
|
|
1419
|
+
* with `startConversation`, so without this its envelope would carry no
|
|
1420
|
+
* `conversationId` and the resume GET couldn't identify the thread. `startConversation`
|
|
1415
1421
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1416
1422
|
*/
|
|
1417
|
-
primeIdentity(visitorId,
|
|
1423
|
+
primeIdentity(visitorId, conversationId) {
|
|
1418
1424
|
if (visitorId) this.visitorId = visitorId;
|
|
1419
|
-
if (
|
|
1425
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1420
1426
|
}
|
|
1421
1427
|
/** Build the per-request envelope from the current transport state. */
|
|
1422
1428
|
envelope() {
|
|
1423
1429
|
const out = {};
|
|
1424
1430
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1425
|
-
if (this.
|
|
1431
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1426
1432
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1427
1433
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1428
1434
|
return out;
|
|
1429
1435
|
}
|
|
1430
1436
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1431
|
-
* start-
|
|
1437
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1432
1438
|
* differs from the active one. */
|
|
1433
1439
|
withEnvelope(body) {
|
|
1434
1440
|
return { ...this.envelope(), ...body };
|
|
@@ -1439,8 +1445,8 @@ var AgentTransport = class {
|
|
|
1439
1445
|
return form;
|
|
1440
1446
|
}
|
|
1441
1447
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1442
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1443
|
-
* selector on load-
|
|
1448
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1449
|
+
* selector on load-conversation). */
|
|
1444
1450
|
withEnvelopeQuery(urlOrPath) {
|
|
1445
1451
|
const url = new URL(this.url(urlOrPath));
|
|
1446
1452
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1449,23 +1455,31 @@ var AgentTransport = class {
|
|
|
1449
1455
|
return url.toString();
|
|
1450
1456
|
}
|
|
1451
1457
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1452
|
-
async
|
|
1453
|
-
log4.debug("
|
|
1454
|
-
|
|
1455
|
-
|
|
1458
|
+
async startConversation(body) {
|
|
1459
|
+
log4.debug("startConversation \u2192", {
|
|
1460
|
+
visitorId: body.visitorId,
|
|
1461
|
+
conversationId: body.conversationId,
|
|
1462
|
+
locale: body.locale
|
|
1463
|
+
});
|
|
1464
|
+
const res = await this.postJson(
|
|
1465
|
+
DEFAULT_PATHS.startConversation,
|
|
1466
|
+
body,
|
|
1467
|
+
"startConversation"
|
|
1468
|
+
);
|
|
1469
|
+
log4.debug("startConversation \u2190", {
|
|
1456
1470
|
visitorId: res.visitorId,
|
|
1457
|
-
|
|
1471
|
+
conversationId: res.conversationId,
|
|
1458
1472
|
canContinue: res.canContinue,
|
|
1459
1473
|
hasMessages: !!res.messages?.length,
|
|
1460
1474
|
hasWelcome: !!res.welcome,
|
|
1461
1475
|
hasConfig: !!res.config,
|
|
1462
1476
|
rebind: res.rebind
|
|
1463
1477
|
});
|
|
1464
|
-
if (!
|
|
1465
|
-
log4.warn("
|
|
1478
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1479
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1466
1480
|
}
|
|
1467
1481
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1468
|
-
this.
|
|
1482
|
+
this.conversationId = res.conversationId;
|
|
1469
1483
|
return res;
|
|
1470
1484
|
}
|
|
1471
1485
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1490,45 +1504,45 @@ var AgentTransport = class {
|
|
|
1490
1504
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1491
1505
|
return res;
|
|
1492
1506
|
}
|
|
1493
|
-
async
|
|
1494
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1507
|
+
async listConversations(params = {}) {
|
|
1508
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1495
1509
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1496
1510
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1497
1511
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1498
|
-
log4.debug("
|
|
1512
|
+
log4.debug("listConversations \u2192", {
|
|
1499
1513
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1500
1514
|
limit: params.limit,
|
|
1501
1515
|
cursor: params.cursor
|
|
1502
1516
|
});
|
|
1503
|
-
const res = await this.getJson(url.toString(), "
|
|
1504
|
-
const
|
|
1505
|
-
log4.debug("
|
|
1517
|
+
const res = await this.getJson(url.toString(), "listConversations");
|
|
1518
|
+
const conversations = res.conversations ?? [];
|
|
1519
|
+
log4.debug("listConversations \u2190", { count: conversations.length, nextCursor: res.nextCursor });
|
|
1506
1520
|
return {
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
title:
|
|
1510
|
-
lastMessageAt:
|
|
1511
|
-
preview:
|
|
1512
|
-
canContinue:
|
|
1513
|
-
unreadCount:
|
|
1521
|
+
conversations: conversations.map((conversation) => ({
|
|
1522
|
+
conversationId: conversation.conversationId,
|
|
1523
|
+
title: conversation.title,
|
|
1524
|
+
lastMessageAt: conversation.lastMessageAt,
|
|
1525
|
+
preview: conversation.preview,
|
|
1526
|
+
canContinue: conversation.canContinue,
|
|
1527
|
+
unreadCount: conversation.unreadCount
|
|
1514
1528
|
})),
|
|
1515
1529
|
nextCursor: res.nextCursor
|
|
1516
1530
|
};
|
|
1517
1531
|
}
|
|
1518
|
-
async
|
|
1532
|
+
async loadConversation(conversationId) {
|
|
1519
1533
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1520
|
-
url.searchParams.set("
|
|
1521
|
-
log4.debug("
|
|
1522
|
-
const res = await this.getJson(url.toString(), "
|
|
1534
|
+
url.searchParams.set("conversationId", conversationId);
|
|
1535
|
+
log4.debug("loadConversation \u2192", { conversationId, visitorId: this.visitorId });
|
|
1536
|
+
const res = await this.getJson(url.toString(), "loadConversation");
|
|
1523
1537
|
const messages = res.messages ?? [];
|
|
1524
|
-
log4.debug("
|
|
1525
|
-
|
|
1538
|
+
log4.debug("loadConversation \u2190", {
|
|
1539
|
+
conversationId: res.conversationId,
|
|
1526
1540
|
canContinue: res.canContinue,
|
|
1527
1541
|
messageCount: messages.length,
|
|
1528
1542
|
hasSuggestions: !!res.suggestions
|
|
1529
1543
|
});
|
|
1530
1544
|
return {
|
|
1531
|
-
|
|
1545
|
+
conversationId: res.conversationId,
|
|
1532
1546
|
canContinue: res.canContinue ?? true,
|
|
1533
1547
|
messages,
|
|
1534
1548
|
agent: res.agent,
|
|
@@ -1537,15 +1551,15 @@ var AgentTransport = class {
|
|
|
1537
1551
|
}
|
|
1538
1552
|
/**
|
|
1539
1553
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1540
|
-
* server records `lastReadAt` and clears that
|
|
1541
|
-
* next `/
|
|
1554
|
+
* server records `lastReadAt` and clears that conversation's `unreadCount` on the
|
|
1555
|
+
* next `/conversations`. A failure is non-fatal (the badge just lingers until the
|
|
1542
1556
|
* next sync), so callers don't await this.
|
|
1543
1557
|
*/
|
|
1544
|
-
async markRead(
|
|
1545
|
-
if (!this.visitorId || !
|
|
1546
|
-
log4.debug("markRead \u2192", {
|
|
1558
|
+
async markRead(conversationId) {
|
|
1559
|
+
if (!this.visitorId || !conversationId) return;
|
|
1560
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1547
1561
|
try {
|
|
1548
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1562
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1549
1563
|
} catch (err) {
|
|
1550
1564
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1551
1565
|
}
|
|
@@ -1571,7 +1585,7 @@ var AgentTransport = class {
|
|
|
1571
1585
|
async saveUserPrefs(userPrefs) {
|
|
1572
1586
|
log4.debug("saveUserPrefs \u2192", {
|
|
1573
1587
|
visitorId: this.visitorId,
|
|
1574
|
-
|
|
1588
|
+
conversationId: this.conversationId,
|
|
1575
1589
|
settingsKeys: Object.keys(userPrefs)
|
|
1576
1590
|
});
|
|
1577
1591
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1589,7 +1603,7 @@ var AgentTransport = class {
|
|
|
1589
1603
|
}
|
|
1590
1604
|
/**
|
|
1591
1605
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1592
|
-
* record is captured even if the visitor never sends a message. `
|
|
1606
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1593
1607
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1594
1608
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1595
1609
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1604,7 +1618,7 @@ var AgentTransport = class {
|
|
|
1604
1618
|
}
|
|
1605
1619
|
sendMessage(body) {
|
|
1606
1620
|
log4.debug("message \u2192", {
|
|
1607
|
-
|
|
1621
|
+
conversationId: body.conversationId,
|
|
1608
1622
|
visitorId: body.visitorId,
|
|
1609
1623
|
messageCount: body.messages.length,
|
|
1610
1624
|
trigger: body.trigger,
|
|
@@ -1614,16 +1628,16 @@ var AgentTransport = class {
|
|
|
1614
1628
|
const ctrl = new AbortController();
|
|
1615
1629
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1616
1630
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1617
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1631
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1618
1632
|
return { iter, cancel };
|
|
1619
1633
|
}
|
|
1620
1634
|
/**
|
|
1621
1635
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1622
1636
|
*
|
|
1623
1637
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1624
|
-
* `
|
|
1638
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1625
1639
|
* the user refreshed while the assistant was still streaming, the
|
|
1626
|
-
* `
|
|
1640
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1627
1641
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1628
1642
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1629
1643
|
* (the common case — no bubble is created).
|
|
@@ -1650,7 +1664,7 @@ var AgentTransport = class {
|
|
|
1650
1664
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1651
1665
|
* off first, the reply may still be spinning up server-side);
|
|
1652
1666
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1653
|
-
* parallel with start-
|
|
1667
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1654
1668
|
* user reloaded keeps flowing).
|
|
1655
1669
|
*
|
|
1656
1670
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1659,7 +1673,7 @@ var AgentTransport = class {
|
|
|
1659
1673
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1660
1674
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1661
1675
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1662
|
-
* turn comes from the DB via start-
|
|
1676
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1663
1677
|
*
|
|
1664
1678
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1665
1679
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1725,11 +1739,11 @@ var AgentTransport = class {
|
|
|
1725
1739
|
return false;
|
|
1726
1740
|
}
|
|
1727
1741
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1728
|
-
cancelStream(ctrl,
|
|
1742
|
+
cancelStream(ctrl, conversationId) {
|
|
1729
1743
|
if (ctrl.signal.aborted) return;
|
|
1730
|
-
log4.debug("cancel stream", {
|
|
1744
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1731
1745
|
ctrl.abort();
|
|
1732
|
-
if (!this.visitorId || !
|
|
1746
|
+
if (!this.visitorId || !conversationId) return;
|
|
1733
1747
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1734
1748
|
method: "POST",
|
|
1735
1749
|
credentials: "omit",
|
|
@@ -1754,7 +1768,7 @@ var AgentTransport = class {
|
|
|
1754
1768
|
yield* parseChatStream(res, signal7);
|
|
1755
1769
|
}
|
|
1756
1770
|
/**
|
|
1757
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1771
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1758
1772
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1759
1773
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1760
1774
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1765,7 +1779,7 @@ var AgentTransport = class {
|
|
|
1765
1779
|
return url.toString();
|
|
1766
1780
|
}
|
|
1767
1781
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1768
|
-
// update-settings / mark-read / start-
|
|
1782
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1769
1783
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1770
1784
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1771
1785
|
async postJson(path, body, label) {
|
|
@@ -1849,10 +1863,10 @@ function extensionFor(mimeType) {
|
|
|
1849
1863
|
if (mimeType.includes("wav")) return "wav";
|
|
1850
1864
|
return "bin";
|
|
1851
1865
|
}
|
|
1852
|
-
function
|
|
1866
|
+
function isStartConversationResponseShape(raw) {
|
|
1853
1867
|
if (!raw || typeof raw !== "object") return false;
|
|
1854
1868
|
const r = raw;
|
|
1855
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1869
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1856
1870
|
}
|
|
1857
1871
|
|
|
1858
1872
|
// src/stream/messages.ts
|
|
@@ -2175,7 +2189,7 @@ var log6 = logger.scope("persistence");
|
|
|
2175
2189
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2176
2190
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2177
2191
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2178
|
-
const
|
|
2192
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2179
2193
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2180
2194
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2181
2195
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2195,13 +2209,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2195
2209
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2196
2210
|
storage.set(KEY_VISITOR, id);
|
|
2197
2211
|
},
|
|
2198
|
-
|
|
2199
|
-
return storage.get(
|
|
2212
|
+
loadConversationId() {
|
|
2213
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2200
2214
|
},
|
|
2201
|
-
|
|
2202
|
-
log6.trace("
|
|
2203
|
-
if (id) storage.set(
|
|
2204
|
-
else storage.remove(
|
|
2215
|
+
saveConversationId(id) {
|
|
2216
|
+
log6.trace("saveConversationId", { id, widgetId });
|
|
2217
|
+
if (id) storage.set(KEY_CONVERSATION, id);
|
|
2218
|
+
else storage.remove(KEY_CONVERSATION);
|
|
2205
2219
|
},
|
|
2206
2220
|
loadUserPrefs() {
|
|
2207
2221
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2285,8 +2299,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2285
2299
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2286
2300
|
}
|
|
2287
2301
|
},
|
|
2288
|
-
|
|
2289
|
-
storage.remove(
|
|
2302
|
+
clearConversation() {
|
|
2303
|
+
storage.remove(KEY_CONVERSATION);
|
|
2290
2304
|
}
|
|
2291
2305
|
};
|
|
2292
2306
|
return persistence;
|
|
@@ -2468,7 +2482,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2468
2482
|
var FeedbackBus = class {
|
|
2469
2483
|
constructor(sound, haptics) {
|
|
2470
2484
|
/**
|
|
2471
|
-
* User/
|
|
2485
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2472
2486
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2473
2487
|
* `Persistence` layer.
|
|
2474
2488
|
*/
|
|
@@ -2786,16 +2800,16 @@ var TID = {
|
|
|
2786
2800
|
historyPane: `${p2}-history-pane`,
|
|
2787
2801
|
/** History pane back / close button. */
|
|
2788
2802
|
historyBack: `${p2}-history-back`,
|
|
2789
|
-
/** Single history list row — suffix `-{
|
|
2803
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2790
2804
|
historyItem: `${p2}-history-item`,
|
|
2791
2805
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2792
2806
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
2793
2807
|
sidebar: `${p2}-sidebar`,
|
|
2794
2808
|
/** Sidebar collapse / expand toggle. */
|
|
2795
2809
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2796
|
-
/** Sidebar "New
|
|
2797
|
-
|
|
2798
|
-
/** Sidebar history row — suffix `-{
|
|
2810
|
+
/** Sidebar "New conversation" button. */
|
|
2811
|
+
sidebarNewConversation: `${p2}-sidebar-new-conversation`,
|
|
2812
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2799
2813
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2800
2814
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2801
2815
|
/** Messenger-home surface root. */
|
|
@@ -2804,7 +2818,7 @@ var TID = {
|
|
|
2804
2818
|
modulesEmpty: `${p2}-modules-empty`,
|
|
2805
2819
|
/** Bottom-nav tab button — suffix `-{moduleId}` at the JSX site. */
|
|
2806
2820
|
tab: `${p2}-tab`,
|
|
2807
|
-
/** Unread badge on the
|
|
2821
|
+
/** Unread badge on the Conversations tab. */
|
|
2808
2822
|
tabBadge: `${p2}-tab-badge`,
|
|
2809
2823
|
/** Home module root. */
|
|
2810
2824
|
homeView: `${p2}-home-view`,
|
|
@@ -2819,7 +2833,7 @@ var TID = {
|
|
|
2819
2833
|
/** Home / Help search bar. */
|
|
2820
2834
|
homeSearch: `${p2}-home-search`,
|
|
2821
2835
|
helpSearch: `${p2}-help-search`,
|
|
2822
|
-
/** Home recent-
|
|
2836
|
+
/** Home recent-conversation card. */
|
|
2823
2837
|
homeRecent: `${p2}-home-recent`,
|
|
2824
2838
|
/** Home content-list row ("Popular articles") — suffix `-{id}`. */
|
|
2825
2839
|
homeContentRow: `${p2}-home-content-row`,
|
|
@@ -4836,7 +4850,7 @@ function MessageList({
|
|
|
4836
4850
|
"aria-relevant": "additions text",
|
|
4837
4851
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
4838
4852
|
children: [
|
|
4839
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.
|
|
4853
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.conversationLoading }) : null,
|
|
4840
4854
|
rows
|
|
4841
4855
|
]
|
|
4842
4856
|
}
|
|
@@ -4892,15 +4906,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4892
4906
|
if (diffDays < 7) return "lastWeek";
|
|
4893
4907
|
return "older";
|
|
4894
4908
|
}
|
|
4895
|
-
function groupByBucket(nowMs,
|
|
4909
|
+
function groupByBucket(nowMs, conversations) {
|
|
4896
4910
|
const buckets = /* @__PURE__ */ new Map();
|
|
4897
|
-
for (const chat of
|
|
4911
|
+
for (const chat of conversations) {
|
|
4898
4912
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4899
4913
|
const list = buckets.get(b);
|
|
4900
4914
|
if (list) list.push(chat);
|
|
4901
4915
|
else buckets.set(b, [chat]);
|
|
4902
4916
|
}
|
|
4903
|
-
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b,
|
|
4917
|
+
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b, conversations: buckets.get(b) }));
|
|
4904
4918
|
}
|
|
4905
4919
|
function startOfDay(ms) {
|
|
4906
4920
|
const d = new Date(ms);
|
|
@@ -4917,46 +4931,61 @@ var BUCKET_TO_STRING = {
|
|
|
4917
4931
|
lastWeek: "dateLastWeek",
|
|
4918
4932
|
older: "dateOlder"
|
|
4919
4933
|
};
|
|
4920
|
-
function ConversationList({
|
|
4934
|
+
function ConversationList({
|
|
4935
|
+
transport,
|
|
4936
|
+
strings,
|
|
4937
|
+
visitorId,
|
|
4938
|
+
onSelect,
|
|
4939
|
+
onNewConversation
|
|
4940
|
+
}) {
|
|
4921
4941
|
const p33 = BRAND.cssPrefix;
|
|
4922
4942
|
const [state, setState] = useState7("loading");
|
|
4923
|
-
const [
|
|
4943
|
+
const [conversations, setChats] = useState7([]);
|
|
4924
4944
|
useEffect9(() => {
|
|
4925
4945
|
let cancelled = false;
|
|
4926
|
-
transport.
|
|
4946
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4927
4947
|
if (cancelled) return;
|
|
4928
|
-
setChats(res.
|
|
4948
|
+
setChats(res.conversations ?? []);
|
|
4929
4949
|
setState("loaded");
|
|
4930
4950
|
}).catch((err) => {
|
|
4931
4951
|
if (cancelled) return;
|
|
4932
|
-
log11.warn("
|
|
4952
|
+
log11.warn("listConversations failed", { err });
|
|
4933
4953
|
setState("error");
|
|
4934
4954
|
});
|
|
4935
4955
|
return () => {
|
|
4936
4956
|
cancelled = true;
|
|
4937
4957
|
};
|
|
4938
4958
|
}, [transport, visitorId]);
|
|
4939
|
-
const newChatButton =
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4959
|
+
const newChatButton = onNewConversation ? /* @__PURE__ */ jsx18("div", { class: `${p33}-history-footer`, children: /* @__PURE__ */ jsxs15(
|
|
4960
|
+
"button",
|
|
4961
|
+
{
|
|
4962
|
+
type: "button",
|
|
4963
|
+
class: `${p33}-history-new`,
|
|
4964
|
+
onClick: onNewConversation,
|
|
4965
|
+
"data-testid": TID.sidebarNewConversation,
|
|
4966
|
+
children: [
|
|
4967
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
4968
|
+
strings.newConversation
|
|
4969
|
+
]
|
|
4970
|
+
}
|
|
4971
|
+
) }) : null;
|
|
4943
4972
|
if (state === "loading") {
|
|
4944
4973
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4945
4974
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
4946
4975
|
newChatButton
|
|
4947
4976
|
] });
|
|
4948
4977
|
}
|
|
4949
|
-
if (state === "error" ||
|
|
4978
|
+
if (state === "error" || conversations.length === 0) {
|
|
4950
4979
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4951
4980
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4952
4981
|
newChatButton
|
|
4953
4982
|
] });
|
|
4954
4983
|
}
|
|
4955
|
-
const groups = groupByBucket(Date.now(),
|
|
4984
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4956
4985
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4957
4986
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4958
4987
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4959
|
-
group.
|
|
4988
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4960
4989
|
"button",
|
|
4961
4990
|
{
|
|
4962
4991
|
type: "button",
|
|
@@ -4964,31 +4993,25 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4964
4993
|
class: `${p33}-history-item`,
|
|
4965
4994
|
onClick: () => onSelect(chat),
|
|
4966
4995
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4967
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4996
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
4968
4997
|
children: [
|
|
4969
4998
|
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4970
4999
|
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4971
5000
|
]
|
|
4972
5001
|
},
|
|
4973
|
-
chat.
|
|
5002
|
+
chat.conversationId
|
|
4974
5003
|
))
|
|
4975
5004
|
] }, group.bucket)) }),
|
|
4976
5005
|
newChatButton
|
|
4977
5006
|
] });
|
|
4978
5007
|
}
|
|
4979
5008
|
|
|
4980
|
-
// src/ui/chat-history-pane.tsx
|
|
4981
|
-
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4982
|
-
function ChatHistoryPane(props2) {
|
|
4983
|
-
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
4984
|
-
}
|
|
4985
|
-
|
|
4986
5009
|
// src/ui/suggestions.tsx
|
|
4987
|
-
import { jsx as
|
|
5010
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4988
5011
|
var p16 = BRAND.cssPrefix;
|
|
4989
5012
|
function Suggestions({ suggestions, onPick }) {
|
|
4990
5013
|
if (suggestions.length === 0) return null;
|
|
4991
|
-
return /* @__PURE__ */
|
|
5014
|
+
return /* @__PURE__ */ jsx19("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx19(
|
|
4992
5015
|
"button",
|
|
4993
5016
|
{
|
|
4994
5017
|
type: "button",
|
|
@@ -5002,7 +5025,7 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
5002
5025
|
}
|
|
5003
5026
|
|
|
5004
5027
|
// src/ui/panel.tsx
|
|
5005
|
-
import { Fragment as Fragment3, jsx as
|
|
5028
|
+
import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
5006
5029
|
var p17 = BRAND.cssPrefix;
|
|
5007
5030
|
function Panel(props2) {
|
|
5008
5031
|
const { options, onClose } = props2;
|
|
@@ -5038,7 +5061,7 @@ function Panel(props2) {
|
|
|
5038
5061
|
style: { position: "relative" },
|
|
5039
5062
|
"data-testid": TID.panel,
|
|
5040
5063
|
children: [
|
|
5041
|
-
/* @__PURE__ */
|
|
5064
|
+
/* @__PURE__ */ jsx20(
|
|
5042
5065
|
PanelContent,
|
|
5043
5066
|
{
|
|
5044
5067
|
...props2,
|
|
@@ -5047,7 +5070,7 @@ function Panel(props2) {
|
|
|
5047
5070
|
composerAttachApiRef
|
|
5048
5071
|
}
|
|
5049
5072
|
),
|
|
5050
|
-
/* @__PURE__ */
|
|
5073
|
+
/* @__PURE__ */ jsx20(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
5051
5074
|
]
|
|
5052
5075
|
}
|
|
5053
5076
|
);
|
|
@@ -5072,8 +5095,8 @@ function PanelContent(props2) {
|
|
|
5072
5095
|
onBack,
|
|
5073
5096
|
onClear,
|
|
5074
5097
|
onToggleHistory,
|
|
5075
|
-
|
|
5076
|
-
|
|
5098
|
+
onSelectHistoryConversation,
|
|
5099
|
+
onNewConversation,
|
|
5077
5100
|
onWidgetSizeChange,
|
|
5078
5101
|
onSend,
|
|
5079
5102
|
onStop,
|
|
@@ -5089,11 +5112,11 @@ function PanelContent(props2) {
|
|
|
5089
5112
|
const s = options.strings;
|
|
5090
5113
|
let composerArea;
|
|
5091
5114
|
if (activeForm) {
|
|
5092
|
-
composerArea = /* @__PURE__ */
|
|
5115
|
+
composerArea = /* @__PURE__ */ jsx20(FormGate, { form: activeForm, strings: s, onSubmit: onFormSubmit, onSkip: onFormSkip });
|
|
5093
5116
|
} else if (canSend) {
|
|
5094
5117
|
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5095
|
-
/* @__PURE__ */
|
|
5096
|
-
/* @__PURE__ */
|
|
5118
|
+
/* @__PURE__ */ jsx20(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
5119
|
+
/* @__PURE__ */ jsx20(
|
|
5097
5120
|
Composer,
|
|
5098
5121
|
{
|
|
5099
5122
|
options,
|
|
@@ -5108,10 +5131,10 @@ function PanelContent(props2) {
|
|
|
5108
5131
|
)
|
|
5109
5132
|
] });
|
|
5110
5133
|
} else {
|
|
5111
|
-
composerArea = /* @__PURE__ */
|
|
5134
|
+
composerArea = /* @__PURE__ */ jsx20(ReadOnlyBanner, { label: s.conversationClosed, ctaLabel: s.startNewConversation, onNewConversation: onClear });
|
|
5112
5135
|
}
|
|
5113
5136
|
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5114
|
-
view === "history" ? /* @__PURE__ */
|
|
5137
|
+
view === "history" ? /* @__PURE__ */ jsx20(
|
|
5115
5138
|
HistoryHeader,
|
|
5116
5139
|
{
|
|
5117
5140
|
strings: s,
|
|
@@ -5120,7 +5143,7 @@ function PanelContent(props2) {
|
|
|
5120
5143
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
5121
5144
|
}
|
|
5122
5145
|
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5123
|
-
onBack ? /* @__PURE__ */
|
|
5146
|
+
onBack ? /* @__PURE__ */ jsx20(
|
|
5124
5147
|
"button",
|
|
5125
5148
|
{
|
|
5126
5149
|
type: "button",
|
|
@@ -5128,24 +5151,24 @@ function PanelContent(props2) {
|
|
|
5128
5151
|
onClick: onBack,
|
|
5129
5152
|
"aria-label": s.moduleBack,
|
|
5130
5153
|
title: s.moduleBack,
|
|
5131
|
-
children: /* @__PURE__ */
|
|
5154
|
+
children: /* @__PURE__ */ jsx20(BackIcon, {})
|
|
5132
5155
|
}
|
|
5133
5156
|
) : null,
|
|
5134
|
-
agent ? /* @__PURE__ */
|
|
5135
|
-
/* @__PURE__ */
|
|
5157
|
+
agent ? /* @__PURE__ */ jsx20(AgentBadge, { agent }) : /* @__PURE__ */ jsx20("h1", { children: s.panelTitle }),
|
|
5158
|
+
/* @__PURE__ */ jsx20(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
5136
5159
|
] }),
|
|
5137
|
-
view === "history" ? /* @__PURE__ */
|
|
5138
|
-
|
|
5160
|
+
view === "history" ? /* @__PURE__ */ jsx20(
|
|
5161
|
+
ConversationList,
|
|
5139
5162
|
{
|
|
5140
5163
|
transport,
|
|
5141
5164
|
strings: s,
|
|
5142
5165
|
visitorId,
|
|
5143
|
-
onSelect: (
|
|
5144
|
-
|
|
5166
|
+
onSelect: (conversation) => onSelectHistoryConversation(conversation.conversationId),
|
|
5167
|
+
onNewConversation
|
|
5145
5168
|
}
|
|
5146
5169
|
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5147
|
-
/* @__PURE__ */
|
|
5148
|
-
/* @__PURE__ */
|
|
5170
|
+
/* @__PURE__ */ jsx20(DropZone, { visible: dragOver, strings: s }),
|
|
5171
|
+
/* @__PURE__ */ jsx20(
|
|
5149
5172
|
MessageList,
|
|
5150
5173
|
{
|
|
5151
5174
|
messagesSig,
|
|
@@ -5159,9 +5182,9 @@ function PanelContent(props2) {
|
|
|
5159
5182
|
}
|
|
5160
5183
|
),
|
|
5161
5184
|
composerArea,
|
|
5162
|
-
/* @__PURE__ */
|
|
5185
|
+
/* @__PURE__ */ jsx20(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5163
5186
|
] }),
|
|
5164
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5187
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx20(
|
|
5165
5188
|
ResizeGrip,
|
|
5166
5189
|
{
|
|
5167
5190
|
panelEl: containerEl,
|
|
@@ -5181,7 +5204,7 @@ function HistoryHeader({
|
|
|
5181
5204
|
showClose
|
|
5182
5205
|
}) {
|
|
5183
5206
|
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5184
|
-
/* @__PURE__ */
|
|
5207
|
+
/* @__PURE__ */ jsx20(
|
|
5185
5208
|
"button",
|
|
5186
5209
|
{
|
|
5187
5210
|
type: "button",
|
|
@@ -5189,11 +5212,11 @@ function HistoryHeader({
|
|
|
5189
5212
|
onClick: onBack,
|
|
5190
5213
|
"aria-label": strings.historyBack,
|
|
5191
5214
|
title: strings.historyBack,
|
|
5192
|
-
children: /* @__PURE__ */
|
|
5215
|
+
children: /* @__PURE__ */ jsx20(BackIcon, {})
|
|
5193
5216
|
}
|
|
5194
5217
|
),
|
|
5195
|
-
/* @__PURE__ */
|
|
5196
|
-
showClose ? /* @__PURE__ */
|
|
5218
|
+
/* @__PURE__ */ jsx20("h1", { children: strings.historyTitle }),
|
|
5219
|
+
showClose ? /* @__PURE__ */ jsx20(
|
|
5197
5220
|
"button",
|
|
5198
5221
|
{
|
|
5199
5222
|
type: "button",
|
|
@@ -5201,34 +5224,38 @@ function HistoryHeader({
|
|
|
5201
5224
|
onClick: onClose,
|
|
5202
5225
|
"aria-label": strings.close,
|
|
5203
5226
|
title: strings.close,
|
|
5204
|
-
children: /* @__PURE__ */
|
|
5227
|
+
children: /* @__PURE__ */ jsx20(CloseIcon, {})
|
|
5205
5228
|
}
|
|
5206
5229
|
) : null
|
|
5207
5230
|
] });
|
|
5208
5231
|
}
|
|
5209
|
-
function ReadOnlyBanner({
|
|
5232
|
+
function ReadOnlyBanner({
|
|
5233
|
+
label,
|
|
5234
|
+
ctaLabel,
|
|
5235
|
+
onNewConversation
|
|
5236
|
+
}) {
|
|
5210
5237
|
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5211
|
-
/* @__PURE__ */
|
|
5212
|
-
/* @__PURE__ */
|
|
5238
|
+
/* @__PURE__ */ jsx20("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5239
|
+
/* @__PURE__ */ jsx20("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewConversation, children: ctaLabel })
|
|
5213
5240
|
] });
|
|
5214
5241
|
}
|
|
5215
5242
|
function ComposerFooter({ disclaimer }) {
|
|
5216
5243
|
if (!disclaimer) return null;
|
|
5217
|
-
return /* @__PURE__ */
|
|
5244
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx20("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
5218
5245
|
}
|
|
5219
5246
|
function PoweredByBar({ poweredBy }) {
|
|
5220
5247
|
if (!poweredBy) return null;
|
|
5221
|
-
return /* @__PURE__ */
|
|
5248
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx20(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
5222
5249
|
}
|
|
5223
5250
|
function PoweredBy({ logoUrl, text, href }) {
|
|
5224
5251
|
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5225
|
-
logoUrl ? /* @__PURE__ */
|
|
5226
|
-
text ? /* @__PURE__ */
|
|
5252
|
+
logoUrl ? /* @__PURE__ */ jsx20("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5253
|
+
text ? /* @__PURE__ */ jsx20("span", { children: text }) : null
|
|
5227
5254
|
] });
|
|
5228
5255
|
if (href) {
|
|
5229
|
-
return /* @__PURE__ */
|
|
5256
|
+
return /* @__PURE__ */ jsx20("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
5230
5257
|
}
|
|
5231
|
-
return /* @__PURE__ */
|
|
5258
|
+
return /* @__PURE__ */ jsx20("span", { class: `${p17}-poweredby`, children: inner });
|
|
5232
5259
|
}
|
|
5233
5260
|
|
|
5234
5261
|
// src/ui/form/form-controller.ts
|
|
@@ -5243,10 +5270,11 @@ function useForms(deps) {
|
|
|
5243
5270
|
}
|
|
5244
5271
|
function createController(depsRef) {
|
|
5245
5272
|
const activeForm = signal5(null);
|
|
5246
|
-
const
|
|
5273
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5274
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5247
5275
|
const isDone = (form) => {
|
|
5248
5276
|
if (form.frequency === "always") return false;
|
|
5249
|
-
if (form.frequency === "
|
|
5277
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5250
5278
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5251
5279
|
};
|
|
5252
5280
|
const fire = (kind, param) => {
|
|
@@ -5269,7 +5297,7 @@ function createController(depsRef) {
|
|
|
5269
5297
|
if (!active) return;
|
|
5270
5298
|
activeForm.value = null;
|
|
5271
5299
|
const { form, trigger } = active;
|
|
5272
|
-
if (form.frequency === "
|
|
5300
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5273
5301
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5274
5302
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5275
5303
|
};
|
|
@@ -5303,7 +5331,7 @@ function whenPasses(form, d) {
|
|
|
5303
5331
|
}
|
|
5304
5332
|
|
|
5305
5333
|
// src/ui/sidebar.tsx
|
|
5306
|
-
import { Fragment as Fragment4, jsx as
|
|
5334
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
5307
5335
|
function Sidebar(props2) {
|
|
5308
5336
|
const p33 = BRAND.cssPrefix;
|
|
5309
5337
|
const { site, blocks, strings, collapsed } = props2;
|
|
@@ -5312,8 +5340,8 @@ function Sidebar(props2) {
|
|
|
5312
5340
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
5313
5341
|
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5314
5342
|
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5315
|
-
/* @__PURE__ */
|
|
5316
|
-
/* @__PURE__ */
|
|
5343
|
+
/* @__PURE__ */ jsx21(SidebarBrand, { site }),
|
|
5344
|
+
/* @__PURE__ */ jsx21(
|
|
5317
5345
|
"button",
|
|
5318
5346
|
{
|
|
5319
5347
|
type: "button",
|
|
@@ -5323,21 +5351,21 @@ function Sidebar(props2) {
|
|
|
5323
5351
|
title: toggleLabel,
|
|
5324
5352
|
onClick: props2.onToggleCollapsed,
|
|
5325
5353
|
"data-testid": TID.sidebarToggle,
|
|
5326
|
-
children: /* @__PURE__ */
|
|
5354
|
+
children: /* @__PURE__ */ jsx21(SidebarToggleIcon, { collapsed })
|
|
5327
5355
|
}
|
|
5328
5356
|
)
|
|
5329
5357
|
] }),
|
|
5330
5358
|
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5331
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
5332
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
5333
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5359
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx21("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx21(SidebarNav, { items: navigation }) }) : null,
|
|
5360
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx21(SidebarCards, { items: linkCards }) }) : null,
|
|
5361
|
+
props2.showConversations ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx21(
|
|
5334
5362
|
ConversationList,
|
|
5335
5363
|
{
|
|
5336
5364
|
transport: props2.transport,
|
|
5337
5365
|
strings: props2.strings,
|
|
5338
5366
|
visitorId: props2.visitorId,
|
|
5339
|
-
onSelect: props2.
|
|
5340
|
-
|
|
5367
|
+
onSelect: props2.onSelectConversation,
|
|
5368
|
+
onNewConversation: props2.onNewConversation
|
|
5341
5369
|
}
|
|
5342
5370
|
) }) : null
|
|
5343
5371
|
] })
|
|
@@ -5348,14 +5376,14 @@ function SidebarBrand({ site }) {
|
|
|
5348
5376
|
if (site?.logo?.url) {
|
|
5349
5377
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
5350
5378
|
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5351
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
5352
|
-
/* @__PURE__ */
|
|
5379
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx21("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5380
|
+
/* @__PURE__ */ jsx21("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
5353
5381
|
] });
|
|
5354
5382
|
}
|
|
5355
|
-
return /* @__PURE__ */
|
|
5383
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
5356
5384
|
}
|
|
5357
5385
|
function SidebarToggleIcon({ collapsed }) {
|
|
5358
|
-
return /* @__PURE__ */
|
|
5386
|
+
return /* @__PURE__ */ jsx21(
|
|
5359
5387
|
"svg",
|
|
5360
5388
|
{
|
|
5361
5389
|
width: "16",
|
|
@@ -5365,13 +5393,13 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
5365
5393
|
stroke: "currentColor",
|
|
5366
5394
|
"stroke-width": "2",
|
|
5367
5395
|
"aria-hidden": "true",
|
|
5368
|
-
children: collapsed ? /* @__PURE__ */
|
|
5396
|
+
children: collapsed ? /* @__PURE__ */ jsx21("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx21("polyline", { points: "15 6 9 12 15 18" })
|
|
5369
5397
|
}
|
|
5370
5398
|
);
|
|
5371
5399
|
}
|
|
5372
5400
|
function SidebarNav({ items }) {
|
|
5373
5401
|
const p33 = BRAND.cssPrefix;
|
|
5374
|
-
return /* @__PURE__ */
|
|
5402
|
+
return /* @__PURE__ */ jsx21("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx21("li", { children: /* @__PURE__ */ jsxs17(
|
|
5375
5403
|
"a",
|
|
5376
5404
|
{
|
|
5377
5405
|
class: `${p33}-sidebar-nav-item`,
|
|
@@ -5379,15 +5407,15 @@ function SidebarNav({ items }) {
|
|
|
5379
5407
|
target: item.href ? "_blank" : void 0,
|
|
5380
5408
|
rel: item.href ? "noreferrer" : void 0,
|
|
5381
5409
|
children: [
|
|
5382
|
-
item.icon ? /* @__PURE__ */
|
|
5383
|
-
/* @__PURE__ */
|
|
5410
|
+
item.icon ? /* @__PURE__ */ jsx21("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5411
|
+
/* @__PURE__ */ jsx21("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
5384
5412
|
]
|
|
5385
5413
|
}
|
|
5386
5414
|
) }, item.id ?? item.label)) });
|
|
5387
5415
|
}
|
|
5388
5416
|
function SidebarCards({ items }) {
|
|
5389
5417
|
const p33 = BRAND.cssPrefix;
|
|
5390
|
-
return /* @__PURE__ */
|
|
5418
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
5391
5419
|
"a",
|
|
5392
5420
|
{
|
|
5393
5421
|
class: `${p33}-sidebar-card`,
|
|
@@ -5395,8 +5423,8 @@ function SidebarCards({ items }) {
|
|
|
5395
5423
|
target: item.href ? "_blank" : void 0,
|
|
5396
5424
|
rel: item.href ? "noreferrer" : void 0,
|
|
5397
5425
|
children: [
|
|
5398
|
-
/* @__PURE__ */
|
|
5399
|
-
item.description ? /* @__PURE__ */
|
|
5426
|
+
/* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5427
|
+
item.description ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
5400
5428
|
]
|
|
5401
5429
|
},
|
|
5402
5430
|
item.id ?? item.label
|
|
@@ -5404,11 +5432,11 @@ function SidebarCards({ items }) {
|
|
|
5404
5432
|
}
|
|
5405
5433
|
|
|
5406
5434
|
// src/ui/page-shell.tsx
|
|
5407
|
-
import { jsx as
|
|
5435
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5408
5436
|
var p18 = BRAND.cssPrefix;
|
|
5409
5437
|
function PageShell(props2) {
|
|
5410
5438
|
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5411
|
-
/* @__PURE__ */
|
|
5439
|
+
/* @__PURE__ */ jsx22(
|
|
5412
5440
|
Sidebar,
|
|
5413
5441
|
{
|
|
5414
5442
|
site: props2.site,
|
|
@@ -5417,13 +5445,13 @@ function PageShell(props2) {
|
|
|
5417
5445
|
strings: props2.strings,
|
|
5418
5446
|
visitorId: props2.visitorId,
|
|
5419
5447
|
showConversations: props2.showConversations,
|
|
5420
|
-
|
|
5421
|
-
|
|
5448
|
+
onSelectConversation: props2.onSelectConversation,
|
|
5449
|
+
onNewConversation: props2.onNewConversation,
|
|
5422
5450
|
collapsed: props2.sidebarCollapsed,
|
|
5423
5451
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
5424
5452
|
}
|
|
5425
5453
|
),
|
|
5426
|
-
/* @__PURE__ */
|
|
5454
|
+
/* @__PURE__ */ jsx22("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
5427
5455
|
] });
|
|
5428
5456
|
}
|
|
5429
5457
|
|
|
@@ -5463,7 +5491,7 @@ var atTabRoot = (s) => activeStack(s).length === 0;
|
|
|
5463
5491
|
import { useCallback as useCallback4, useEffect as useEffect15, useRef as useRef8 } from "preact/hooks";
|
|
5464
5492
|
import { useComputed as useComputed6 } from "@preact/signals";
|
|
5465
5493
|
|
|
5466
|
-
// src/ui/modules/
|
|
5494
|
+
// src/ui/modules/chat.tsx
|
|
5467
5495
|
var chatLayout = {
|
|
5468
5496
|
Icon: BubblesIcon
|
|
5469
5497
|
// No `Root`: MessengerHome renders the existing chat panel for this tab.
|
|
@@ -5473,35 +5501,35 @@ var chatLayout = {
|
|
|
5473
5501
|
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
5474
5502
|
|
|
5475
5503
|
// src/ui/back-header.tsx
|
|
5476
|
-
import { jsx as
|
|
5504
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5477
5505
|
var p19 = BRAND.cssPrefix;
|
|
5478
5506
|
function TitleBar({ title, actions }) {
|
|
5479
5507
|
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5480
|
-
/* @__PURE__ */
|
|
5481
|
-
/* @__PURE__ */
|
|
5482
|
-
actions ?? /* @__PURE__ */
|
|
5508
|
+
/* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5509
|
+
/* @__PURE__ */ jsx23("h1", { class: `${p19}-back-title`, children: title }),
|
|
5510
|
+
actions ?? /* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5483
5511
|
] });
|
|
5484
5512
|
}
|
|
5485
5513
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
5486
5514
|
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5487
|
-
/* @__PURE__ */
|
|
5488
|
-
/* @__PURE__ */
|
|
5489
|
-
actions ?? /* @__PURE__ */
|
|
5515
|
+
/* @__PURE__ */ jsx23("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx23(BackIcon, {}) }),
|
|
5516
|
+
/* @__PURE__ */ jsx23("h1", { class: `${p19}-back-title`, children: title }),
|
|
5517
|
+
actions ?? /* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5490
5518
|
] });
|
|
5491
5519
|
}
|
|
5492
5520
|
|
|
5493
5521
|
// src/ui/home-search.tsx
|
|
5494
|
-
import { jsx as
|
|
5522
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5495
5523
|
var p20 = BRAND.cssPrefix;
|
|
5496
5524
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
5497
5525
|
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5498
|
-
/* @__PURE__ */
|
|
5499
|
-
/* @__PURE__ */
|
|
5526
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5527
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx24(SearchIcon, {}) })
|
|
5500
5528
|
] });
|
|
5501
5529
|
}
|
|
5502
5530
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
5503
5531
|
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5504
|
-
/* @__PURE__ */
|
|
5532
|
+
/* @__PURE__ */ jsx24(
|
|
5505
5533
|
"input",
|
|
5506
5534
|
{
|
|
5507
5535
|
type: "search",
|
|
@@ -5512,25 +5540,25 @@ function HelpSearchInput({ placeholder, value, onInput }) {
|
|
|
5512
5540
|
"data-testid": TID.helpSearch
|
|
5513
5541
|
}
|
|
5514
5542
|
),
|
|
5515
|
-
/* @__PURE__ */
|
|
5543
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx24(SearchIcon, {}) })
|
|
5516
5544
|
] });
|
|
5517
5545
|
}
|
|
5518
5546
|
|
|
5519
5547
|
// src/ui/list-row.tsx
|
|
5520
|
-
import { jsx as
|
|
5548
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5521
5549
|
var p21 = BRAND.cssPrefix;
|
|
5522
5550
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
5523
5551
|
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5524
5552
|
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5525
|
-
/* @__PURE__ */
|
|
5526
|
-
subtitle ? /* @__PURE__ */
|
|
5553
|
+
/* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5554
|
+
subtitle ? /* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
5527
5555
|
] }),
|
|
5528
|
-
/* @__PURE__ */
|
|
5556
|
+
/* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(ChevronRightIcon, {}) })
|
|
5529
5557
|
] });
|
|
5530
5558
|
}
|
|
5531
5559
|
|
|
5532
5560
|
// src/ui/module-state.tsx
|
|
5533
|
-
import { jsx as
|
|
5561
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5534
5562
|
var p22 = BRAND.cssPrefix;
|
|
5535
5563
|
function ModuleState({
|
|
5536
5564
|
tone = "info",
|
|
@@ -5539,13 +5567,13 @@ function ModuleState({
|
|
|
5539
5567
|
strings
|
|
5540
5568
|
}) {
|
|
5541
5569
|
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5542
|
-
/* @__PURE__ */
|
|
5543
|
-
onRetry ? /* @__PURE__ */
|
|
5570
|
+
/* @__PURE__ */ jsx26("span", { children: message }),
|
|
5571
|
+
onRetry ? /* @__PURE__ */ jsx26("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
5544
5572
|
] });
|
|
5545
5573
|
}
|
|
5546
5574
|
|
|
5547
5575
|
// src/ui/modules/help.tsx
|
|
5548
|
-
import { jsx as
|
|
5576
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5549
5577
|
var p23 = BRAND.cssPrefix;
|
|
5550
5578
|
var log12 = logger.scope("help");
|
|
5551
5579
|
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 });
|
|
@@ -5575,7 +5603,7 @@ function fuzzySearch(items, query) {
|
|
|
5575
5603
|
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);
|
|
5576
5604
|
}
|
|
5577
5605
|
function ArticleRow({ article, nav }) {
|
|
5578
|
-
return /* @__PURE__ */
|
|
5606
|
+
return /* @__PURE__ */ jsx27(
|
|
5579
5607
|
ListRow,
|
|
5580
5608
|
{
|
|
5581
5609
|
title: article.title,
|
|
@@ -5612,45 +5640,45 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5612
5640
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
5613
5641
|
function renderBody() {
|
|
5614
5642
|
if (query.trim().length > 0) {
|
|
5615
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
5616
|
-
return /* @__PURE__ */
|
|
5643
|
+
if (results.length === 0) return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5644
|
+
return /* @__PURE__ */ jsx27("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx27(ArticleRow, { article: a, nav }, a.id)) });
|
|
5617
5645
|
}
|
|
5618
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5646
|
+
if (state === "loading") return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpLoading, strings });
|
|
5619
5647
|
if (state === "error") {
|
|
5620
|
-
return /* @__PURE__ */
|
|
5648
|
+
return /* @__PURE__ */ jsx27(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5621
5649
|
}
|
|
5622
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5650
|
+
if (items.length === 0) return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpEmpty, strings });
|
|
5623
5651
|
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5624
|
-
category ? /* @__PURE__ */
|
|
5625
|
-
/* @__PURE__ */
|
|
5652
|
+
category ? /* @__PURE__ */ jsx27("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5653
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx27(ArticleRow, { article: a, nav }, a.id)) })
|
|
5626
5654
|
] }, category));
|
|
5627
5655
|
}
|
|
5628
5656
|
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5629
|
-
/* @__PURE__ */
|
|
5630
|
-
/* @__PURE__ */
|
|
5631
|
-
/* @__PURE__ */
|
|
5657
|
+
/* @__PURE__ */ jsx27(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx27(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5658
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx27(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5659
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
5632
5660
|
] });
|
|
5633
5661
|
}
|
|
5634
5662
|
var helpLayout = {
|
|
5635
5663
|
Icon: HelpIcon,
|
|
5636
|
-
Root: (props2) => /* @__PURE__ */
|
|
5664
|
+
Root: (props2) => /* @__PURE__ */ jsx27(HelpRoot, { ...props2 })
|
|
5637
5665
|
};
|
|
5638
5666
|
|
|
5639
5667
|
// src/ui/modules/home.tsx
|
|
5640
5668
|
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
5641
5669
|
|
|
5642
5670
|
// src/ui/home-card.tsx
|
|
5643
|
-
import { jsx as
|
|
5671
|
+
import { jsx as jsx28 } from "preact/jsx-runtime";
|
|
5644
5672
|
var p24 = BRAND.cssPrefix;
|
|
5645
5673
|
function HomeCard({ onClick, children, testid }) {
|
|
5646
5674
|
if (onClick) {
|
|
5647
|
-
return /* @__PURE__ */
|
|
5675
|
+
return /* @__PURE__ */ jsx28("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
5648
5676
|
}
|
|
5649
|
-
return /* @__PURE__ */
|
|
5677
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
5650
5678
|
}
|
|
5651
5679
|
|
|
5652
5680
|
// src/ui/modules/home.tsx
|
|
5653
|
-
import { Fragment as Fragment5, jsx as
|
|
5681
|
+
import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5654
5682
|
var p25 = BRAND.cssPrefix;
|
|
5655
5683
|
var log13 = logger.scope("home");
|
|
5656
5684
|
function resolveGreeting(props2) {
|
|
@@ -5669,13 +5697,13 @@ function HomeRoot(props2) {
|
|
|
5669
5697
|
const [content, setContent] = useState9([]);
|
|
5670
5698
|
const tagsKey = config.contentTags?.join(",");
|
|
5671
5699
|
useEffect12(() => {
|
|
5672
|
-
if (!config.
|
|
5700
|
+
if (!config.showRecentConversations) return;
|
|
5673
5701
|
let cancelled = false;
|
|
5674
|
-
transport.
|
|
5702
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5675
5703
|
return () => {
|
|
5676
5704
|
cancelled = true;
|
|
5677
5705
|
};
|
|
5678
|
-
}, [transport, config.
|
|
5706
|
+
}, [transport, config.showRecentConversations]);
|
|
5679
5707
|
useEffect12(() => {
|
|
5680
5708
|
if (!config.contentTags?.length) return;
|
|
5681
5709
|
let cancelled = false;
|
|
@@ -5688,49 +5716,49 @@ function HomeRoot(props2) {
|
|
|
5688
5716
|
const avatars = config.userAvatars ?? [];
|
|
5689
5717
|
const status = config.status;
|
|
5690
5718
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
5691
|
-
return /* @__PURE__ */
|
|
5719
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5692
5720
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5693
5721
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5694
|
-
config.brandName ? /* @__PURE__ */
|
|
5722
|
+
config.brandName ? /* @__PURE__ */ jsx29("span", { class: `${p25}-home-brand`, "data-testid": TID.homeBrand, children: config.brandName }) : /* @__PURE__ */ jsx29("span", { class: `${p25}-home-brand-spacer`, "aria-hidden": "true" }),
|
|
5695
5723
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5696
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
5697
|
-
/* @__PURE__ */
|
|
5724
|
+
avatars.length > 0 ? /* @__PURE__ */ jsx29("div", { class: `${p25}-home-avatars`, children: avatars.map((a) => /* @__PURE__ */ jsx29("span", { class: `${p25}-home-avatar`, title: a.role ? `${a.name} \xB7 ${a.role}` : a.name, children: a.avatar ? /* @__PURE__ */ jsx29("img", { src: a.avatar, alt: "", loading: "lazy" }) : /* @__PURE__ */ jsx29("span", { children: initials(a.name) }) }, a.name)) }) : null,
|
|
5725
|
+
/* @__PURE__ */ jsx29(HeaderActions, { panelProps, variant: "plain" })
|
|
5698
5726
|
] })
|
|
5699
5727
|
] }),
|
|
5700
5728
|
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5701
|
-
/* @__PURE__ */
|
|
5702
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5729
|
+
/* @__PURE__ */ jsx29("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5730
|
+
greeting.subtitle ? /* @__PURE__ */ jsx29("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
5703
5731
|
] }) : null
|
|
5704
5732
|
] }),
|
|
5705
5733
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5706
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5734
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx29(
|
|
5707
5735
|
HomeSearchButton,
|
|
5708
5736
|
{
|
|
5709
5737
|
placeholder: strings.homeSearchPlaceholder,
|
|
5710
5738
|
onActivate: () => nav.switchToLayout("help")
|
|
5711
5739
|
}
|
|
5712
5740
|
) : null,
|
|
5713
|
-
recent ? /* @__PURE__ */
|
|
5714
|
-
/* @__PURE__ */
|
|
5741
|
+
recent ? /* @__PURE__ */ jsx29(HomeCard, { onClick: () => nav.selectConversation(recent.conversationId), testid: TID.homeRecent, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-recent-row`, "data-unread": (recent.unreadCount ?? 0) > 0 ? "true" : void 0, children: [
|
|
5742
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx29(BubblesIcon, {}) }),
|
|
5715
5743
|
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5716
|
-
/* @__PURE__ */
|
|
5717
|
-
recent.preview ? /* @__PURE__ */
|
|
5744
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5745
|
+
recent.preview ? /* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
5718
5746
|
] }),
|
|
5719
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5747
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
5720
5748
|
] }) }) : null,
|
|
5721
|
-
status ? /* @__PURE__ */
|
|
5749
|
+
status ? /* @__PURE__ */ jsx29(
|
|
5722
5750
|
HomeCard,
|
|
5723
5751
|
{
|
|
5724
5752
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
5725
5753
|
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5726
|
-
/* @__PURE__ */
|
|
5727
|
-
/* @__PURE__ */
|
|
5754
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx29(StatusOkIcon, {}) }),
|
|
5755
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
5728
5756
|
] })
|
|
5729
5757
|
}
|
|
5730
5758
|
) : null,
|
|
5731
5759
|
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5732
|
-
/* @__PURE__ */
|
|
5733
|
-
/* @__PURE__ */
|
|
5760
|
+
/* @__PURE__ */ jsx29("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5761
|
+
/* @__PURE__ */ jsx29("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx29(
|
|
5734
5762
|
ListRow,
|
|
5735
5763
|
{
|
|
5736
5764
|
title: item.title,
|
|
@@ -5746,12 +5774,12 @@ function HomeRoot(props2) {
|
|
|
5746
5774
|
}
|
|
5747
5775
|
var homeLayout = {
|
|
5748
5776
|
Icon: HomeIcon,
|
|
5749
|
-
Root: (props2) => /* @__PURE__ */
|
|
5777
|
+
Root: (props2) => /* @__PURE__ */ jsx29(HomeRoot, { ...props2 })
|
|
5750
5778
|
};
|
|
5751
5779
|
|
|
5752
5780
|
// src/ui/modules/news.tsx
|
|
5753
5781
|
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5754
|
-
import { jsx as
|
|
5782
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5755
5783
|
var p26 = BRAND.cssPrefix;
|
|
5756
5784
|
var log14 = logger.scope("news");
|
|
5757
5785
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
@@ -5778,12 +5806,12 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5778
5806
|
};
|
|
5779
5807
|
}, [transport, tags, reloadKey]);
|
|
5780
5808
|
function renderBody() {
|
|
5781
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5809
|
+
if (state === "loading") return /* @__PURE__ */ jsx30(ModuleState, { message: strings.newsLoading, strings });
|
|
5782
5810
|
if (state === "error") {
|
|
5783
|
-
return /* @__PURE__ */
|
|
5811
|
+
return /* @__PURE__ */ jsx30(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5784
5812
|
}
|
|
5785
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5786
|
-
return /* @__PURE__ */
|
|
5813
|
+
if (items.length === 0) return /* @__PURE__ */ jsx30(ModuleState, { message: strings.newsEmpty, strings });
|
|
5814
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
5787
5815
|
"button",
|
|
5788
5816
|
{
|
|
5789
5817
|
type: "button",
|
|
@@ -5791,11 +5819,11 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5791
5819
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
5792
5820
|
"data-testid": tid(TID.newsItem, item.id),
|
|
5793
5821
|
children: [
|
|
5794
|
-
item.image ? /* @__PURE__ */
|
|
5822
|
+
item.image ? /* @__PURE__ */ jsx30("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5795
5823
|
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5796
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5797
|
-
/* @__PURE__ */
|
|
5798
|
-
item.description ? /* @__PURE__ */
|
|
5824
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx30("span", { class: `${p26}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx30("span", { class: `${p26}-news-tag`, children: t }, t)) }) : null,
|
|
5825
|
+
/* @__PURE__ */ jsx30("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5826
|
+
item.description ? /* @__PURE__ */ jsx30("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
5799
5827
|
] })
|
|
5800
5828
|
]
|
|
5801
5829
|
},
|
|
@@ -5803,13 +5831,13 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5803
5831
|
)) });
|
|
5804
5832
|
}
|
|
5805
5833
|
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5806
|
-
/* @__PURE__ */
|
|
5807
|
-
/* @__PURE__ */
|
|
5834
|
+
/* @__PURE__ */ jsx30(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5835
|
+
/* @__PURE__ */ jsx30("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
5808
5836
|
] });
|
|
5809
5837
|
}
|
|
5810
5838
|
var newsLayout = {
|
|
5811
5839
|
Icon: NewsIcon,
|
|
5812
|
-
Root: (props2) => /* @__PURE__ */
|
|
5840
|
+
Root: (props2) => /* @__PURE__ */ jsx30(NewsRoot, { ...props2 })
|
|
5813
5841
|
};
|
|
5814
5842
|
|
|
5815
5843
|
// src/ui/modules/registry.ts
|
|
@@ -5821,10 +5849,10 @@ var LAYOUTS = {
|
|
|
5821
5849
|
};
|
|
5822
5850
|
|
|
5823
5851
|
// src/ui/home-tab-bar.tsx
|
|
5824
|
-
import { jsx as
|
|
5852
|
+
import { jsx as jsx31, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5825
5853
|
var p27 = BRAND.cssPrefix;
|
|
5826
5854
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
5827
|
-
return /* @__PURE__ */
|
|
5855
|
+
return /* @__PURE__ */ jsx31("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
5828
5856
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
5829
5857
|
const selected = m.id === activeTab;
|
|
5830
5858
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
@@ -5839,10 +5867,10 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5839
5867
|
"data-testid": tid(TID.tab, m.id),
|
|
5840
5868
|
children: [
|
|
5841
5869
|
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5842
|
-
/* @__PURE__ */
|
|
5843
|
-
badge ? /* @__PURE__ */
|
|
5870
|
+
/* @__PURE__ */ jsx31(Icon, {}),
|
|
5871
|
+
badge ? /* @__PURE__ */ jsx31("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
5844
5872
|
] }),
|
|
5845
|
-
/* @__PURE__ */
|
|
5873
|
+
/* @__PURE__ */ jsx31("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
5846
5874
|
]
|
|
5847
5875
|
},
|
|
5848
5876
|
m.id
|
|
@@ -5851,12 +5879,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5851
5879
|
}
|
|
5852
5880
|
|
|
5853
5881
|
// src/ui/iframe-view.tsx
|
|
5854
|
-
import { jsx as
|
|
5882
|
+
import { jsx as jsx32, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5855
5883
|
var p28 = BRAND.cssPrefix;
|
|
5856
5884
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
5857
5885
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
5858
5886
|
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5859
|
-
/* @__PURE__ */
|
|
5887
|
+
/* @__PURE__ */ jsx32(
|
|
5860
5888
|
BackHeader,
|
|
5861
5889
|
{
|
|
5862
5890
|
title: title || strings.moduleBack,
|
|
@@ -5865,7 +5893,7 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5865
5893
|
actions
|
|
5866
5894
|
}
|
|
5867
5895
|
),
|
|
5868
|
-
/* @__PURE__ */
|
|
5896
|
+
/* @__PURE__ */ jsx32(
|
|
5869
5897
|
"iframe",
|
|
5870
5898
|
{
|
|
5871
5899
|
class: `${p28}-content-frame`,
|
|
@@ -5882,7 +5910,7 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5882
5910
|
|
|
5883
5911
|
// src/ui/content-view.tsx
|
|
5884
5912
|
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5885
|
-
import { jsx as
|
|
5913
|
+
import { jsx as jsx33, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5886
5914
|
var p29 = BRAND.cssPrefix;
|
|
5887
5915
|
var log15 = logger.scope("content");
|
|
5888
5916
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
@@ -5911,17 +5939,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5911
5939
|
};
|
|
5912
5940
|
}, [transport, id, reloadKey]);
|
|
5913
5941
|
function renderBody() {
|
|
5914
|
-
if (failed) return /* @__PURE__ */
|
|
5915
|
-
if (item === null) return /* @__PURE__ */
|
|
5942
|
+
if (failed) return /* @__PURE__ */ jsx33(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5943
|
+
if (item === null) return /* @__PURE__ */ jsx33(ModuleState, { message: strings.contentLoading, strings });
|
|
5916
5944
|
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5917
|
-
item.image ? /* @__PURE__ */
|
|
5918
|
-
item.description ? /* @__PURE__ */
|
|
5919
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5920
|
-
/* @__PURE__ */
|
|
5945
|
+
item.image ? /* @__PURE__ */ jsx33("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5946
|
+
item.description ? /* @__PURE__ */ jsx33("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5947
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx33("span", { class: `${p29}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx33("span", { class: `${p29}-news-tag`, children: t }, t)) }) : null,
|
|
5948
|
+
/* @__PURE__ */ jsx33(StaticMarkdown, { text: item.content ?? "" })
|
|
5921
5949
|
] });
|
|
5922
5950
|
}
|
|
5923
5951
|
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5924
|
-
/* @__PURE__ */
|
|
5952
|
+
/* @__PURE__ */ jsx33(
|
|
5925
5953
|
BackHeader,
|
|
5926
5954
|
{
|
|
5927
5955
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -5931,20 +5959,20 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5931
5959
|
testid: TID.backHeader
|
|
5932
5960
|
}
|
|
5933
5961
|
),
|
|
5934
|
-
/* @__PURE__ */
|
|
5962
|
+
/* @__PURE__ */ jsx33("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
5935
5963
|
] });
|
|
5936
5964
|
}
|
|
5937
5965
|
|
|
5938
5966
|
// src/ui/messenger-home.tsx
|
|
5939
|
-
import { jsx as
|
|
5967
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5940
5968
|
var p30 = BRAND.cssPrefix;
|
|
5941
5969
|
function MessengerHome({
|
|
5942
5970
|
panelProps,
|
|
5943
5971
|
enabledModules,
|
|
5944
5972
|
nav,
|
|
5945
5973
|
unreadCount,
|
|
5946
|
-
|
|
5947
|
-
|
|
5974
|
+
onSelectConversation,
|
|
5975
|
+
onStartNewConversation,
|
|
5948
5976
|
onSetPanelSize
|
|
5949
5977
|
}) {
|
|
5950
5978
|
const options = panelProps.options;
|
|
@@ -5993,8 +6021,8 @@ function MessengerHome({
|
|
|
5993
6021
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
5994
6022
|
if (target) nav.switchTab(target.id);
|
|
5995
6023
|
},
|
|
5996
|
-
|
|
5997
|
-
|
|
6024
|
+
selectConversation: onSelectConversation,
|
|
6025
|
+
startNewConversation: onStartNewConversation
|
|
5998
6026
|
};
|
|
5999
6027
|
const screenProps = (module) => ({
|
|
6000
6028
|
options,
|
|
@@ -6005,12 +6033,12 @@ function MessengerHome({
|
|
|
6005
6033
|
nav: moduleNav,
|
|
6006
6034
|
panelProps
|
|
6007
6035
|
});
|
|
6008
|
-
const plainActions = /* @__PURE__ */
|
|
6036
|
+
const plainActions = /* @__PURE__ */ jsx34(HeaderActions, { panelProps, variant: "plain" });
|
|
6009
6037
|
let body;
|
|
6010
6038
|
if (top?.kind === "iframe") {
|
|
6011
|
-
body = /* @__PURE__ */
|
|
6039
|
+
body = /* @__PURE__ */ jsx34(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
6012
6040
|
} else if (top?.kind === "content") {
|
|
6013
|
-
body = /* @__PURE__ */
|
|
6041
|
+
body = /* @__PURE__ */ jsx34(
|
|
6014
6042
|
ContentView,
|
|
6015
6043
|
{
|
|
6016
6044
|
id: top.id,
|
|
@@ -6022,7 +6050,7 @@ function MessengerHome({
|
|
|
6022
6050
|
}
|
|
6023
6051
|
);
|
|
6024
6052
|
} else if (activeModule?.layout === "chat") {
|
|
6025
|
-
body = /* @__PURE__ */
|
|
6053
|
+
body = /* @__PURE__ */ jsx34(
|
|
6026
6054
|
PanelContent,
|
|
6027
6055
|
{
|
|
6028
6056
|
...panelProps,
|
|
@@ -6033,7 +6061,7 @@ function MessengerHome({
|
|
|
6033
6061
|
);
|
|
6034
6062
|
} else if (activeModule) {
|
|
6035
6063
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
6036
|
-
body = Root ? /* @__PURE__ */
|
|
6064
|
+
body = Root ? /* @__PURE__ */ jsx34(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
6037
6065
|
} else {
|
|
6038
6066
|
body = null;
|
|
6039
6067
|
}
|
|
@@ -6048,8 +6076,8 @@ function MessengerHome({
|
|
|
6048
6076
|
style: { position: "relative" },
|
|
6049
6077
|
"data-testid": TID.messengerHome,
|
|
6050
6078
|
children: [
|
|
6051
|
-
/* @__PURE__ */
|
|
6052
|
-
showTabBar ? /* @__PURE__ */
|
|
6079
|
+
/* @__PURE__ */ jsx34("div", { class: `${p30}-messenger-body`, children: body }),
|
|
6080
|
+
showTabBar ? /* @__PURE__ */ jsx34(
|
|
6053
6081
|
HomeTabBar,
|
|
6054
6082
|
{
|
|
6055
6083
|
modules: enabledModules,
|
|
@@ -6059,8 +6087,8 @@ function MessengerHome({
|
|
|
6059
6087
|
onSelect: nav.switchTab
|
|
6060
6088
|
}
|
|
6061
6089
|
) : null,
|
|
6062
|
-
/* @__PURE__ */
|
|
6063
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
6090
|
+
/* @__PURE__ */ jsx34(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
6091
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx34(
|
|
6064
6092
|
ResizeGrip,
|
|
6065
6093
|
{
|
|
6066
6094
|
panelEl: containerRef.current,
|
|
@@ -6077,7 +6105,7 @@ function MessengerHome({
|
|
|
6077
6105
|
}
|
|
6078
6106
|
|
|
6079
6107
|
// src/ui/modules-empty.tsx
|
|
6080
|
-
import { jsx as
|
|
6108
|
+
import { jsx as jsx35, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
6081
6109
|
var p31 = BRAND.cssPrefix;
|
|
6082
6110
|
function ModulesEmpty({ strings, onClose }) {
|
|
6083
6111
|
return /* @__PURE__ */ jsxs30(
|
|
@@ -6088,7 +6116,7 @@ function ModulesEmpty({ strings, onClose }) {
|
|
|
6088
6116
|
"aria-label": strings.panelTitle,
|
|
6089
6117
|
"data-testid": TID.modulesEmpty,
|
|
6090
6118
|
children: [
|
|
6091
|
-
onClose ? /* @__PURE__ */
|
|
6119
|
+
onClose ? /* @__PURE__ */ jsx35(
|
|
6092
6120
|
"button",
|
|
6093
6121
|
{
|
|
6094
6122
|
type: "button",
|
|
@@ -6096,10 +6124,10 @@ function ModulesEmpty({ strings, onClose }) {
|
|
|
6096
6124
|
onClick: onClose,
|
|
6097
6125
|
"aria-label": strings.close,
|
|
6098
6126
|
title: strings.close,
|
|
6099
|
-
children: /* @__PURE__ */
|
|
6127
|
+
children: /* @__PURE__ */ jsx35(CloseIcon, {})
|
|
6100
6128
|
}
|
|
6101
6129
|
) : null,
|
|
6102
|
-
/* @__PURE__ */
|
|
6130
|
+
/* @__PURE__ */ jsx35("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
6103
6131
|
]
|
|
6104
6132
|
}
|
|
6105
6133
|
);
|
|
@@ -6171,7 +6199,7 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
6171
6199
|
}
|
|
6172
6200
|
|
|
6173
6201
|
// src/ui/app.tsx
|
|
6174
|
-
import { jsx as
|
|
6202
|
+
import { jsx as jsx36, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
6175
6203
|
var log16 = logger.scope("app");
|
|
6176
6204
|
var p32 = BRAND.cssPrefix;
|
|
6177
6205
|
function App({ options, hostElement, bus }) {
|
|
@@ -6182,7 +6210,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6182
6210
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6183
6211
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6184
6212
|
);
|
|
6185
|
-
const
|
|
6213
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6186
6214
|
const messagesSig = useSignal2([]);
|
|
6187
6215
|
const unreadCountSig = useSignal2(0);
|
|
6188
6216
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6204,7 +6232,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6204
6232
|
const homeNav = homeNavRef.current;
|
|
6205
6233
|
const chatTabIdRef = useRef9(void 0);
|
|
6206
6234
|
chatTabIdRef.current = chatTabId();
|
|
6207
|
-
const [
|
|
6235
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6208
6236
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6209
6237
|
const initialPanelRef = useRef9(
|
|
6210
6238
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6284,7 +6312,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6284
6312
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6285
6313
|
}, [options.mode, options.size, persistence]);
|
|
6286
6314
|
useEffect17(() => {
|
|
6287
|
-
if (!
|
|
6315
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6288
6316
|
initialPanelApplied.current = true;
|
|
6289
6317
|
const state = resolveInitialPanelState(
|
|
6290
6318
|
options,
|
|
@@ -6294,12 +6322,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6294
6322
|
);
|
|
6295
6323
|
setIsOpen(state.panelOpen);
|
|
6296
6324
|
setPanelSize(state.panelSize);
|
|
6297
|
-
}, [
|
|
6325
|
+
}, [conversationReady, options, persistence]);
|
|
6298
6326
|
const homeNavSeeded = useRef9(false);
|
|
6299
6327
|
const resumeActiveRef = useRef9(false);
|
|
6300
6328
|
const resumeBubbleRef = useRef9(null);
|
|
6301
6329
|
useEffect17(() => {
|
|
6302
|
-
if (!
|
|
6330
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6303
6331
|
homeNavSeeded.current = true;
|
|
6304
6332
|
if (resumeActiveRef.current) {
|
|
6305
6333
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6307,7 +6335,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6307
6335
|
return;
|
|
6308
6336
|
}
|
|
6309
6337
|
homeNav.reset(landingTab());
|
|
6310
|
-
}, [
|
|
6338
|
+
}, [conversationReady]);
|
|
6311
6339
|
const playWelcome = useCallback6(
|
|
6312
6340
|
(welcomeMessages) => {
|
|
6313
6341
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6326,21 +6354,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6326
6354
|
[messagesSig, options.welcome]
|
|
6327
6355
|
);
|
|
6328
6356
|
const connectGenRef = useRef9(0);
|
|
6329
|
-
const
|
|
6357
|
+
const runStartConversation = useCallback6(
|
|
6330
6358
|
async ({ newConversation }) => {
|
|
6331
6359
|
const myGen = ++connectGenRef.current;
|
|
6332
6360
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6333
|
-
const persistedChatId =
|
|
6334
|
-
const
|
|
6335
|
-
if (
|
|
6336
|
-
|
|
6337
|
-
persistence.
|
|
6361
|
+
const persistedChatId = conversationIdSig.value;
|
|
6362
|
+
const conversationId = newConversation || !persistedChatId ? uuid7() : persistedChatId;
|
|
6363
|
+
if (conversationId !== persistedChatId) {
|
|
6364
|
+
conversationIdSig.value = conversationId;
|
|
6365
|
+
persistence.saveConversationId(conversationId);
|
|
6338
6366
|
}
|
|
6339
6367
|
let res;
|
|
6340
6368
|
try {
|
|
6341
|
-
res = await transport.
|
|
6369
|
+
res = await transport.startConversation({
|
|
6342
6370
|
visitorId,
|
|
6343
|
-
|
|
6371
|
+
conversationId,
|
|
6344
6372
|
userPrefs: persistence.loadUserPrefs(),
|
|
6345
6373
|
locale: options.locale
|
|
6346
6374
|
});
|
|
@@ -6348,7 +6376,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6348
6376
|
if (isStale()) return;
|
|
6349
6377
|
bus.emit("error", err);
|
|
6350
6378
|
options.onError?.(err);
|
|
6351
|
-
if (!newConversation)
|
|
6379
|
+
if (!newConversation) setConversationReady(true);
|
|
6352
6380
|
return;
|
|
6353
6381
|
}
|
|
6354
6382
|
if (isStale()) return;
|
|
@@ -6362,12 +6390,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6362
6390
|
reason: res.rebind?.visitorId
|
|
6363
6391
|
});
|
|
6364
6392
|
}
|
|
6365
|
-
if (res.
|
|
6366
|
-
log16.info("
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6393
|
+
if (res.conversationId && res.conversationId !== conversationId) {
|
|
6394
|
+
log16.info("conversation rebound", {
|
|
6395
|
+
previous: conversationId,
|
|
6396
|
+
current: res.conversationId,
|
|
6397
|
+
reason: res.rebind?.conversationId
|
|
6398
|
+
});
|
|
6399
|
+
bus.emit("conversationRebound", {
|
|
6400
|
+
previous: conversationId,
|
|
6401
|
+
current: res.conversationId,
|
|
6402
|
+
reason: res.rebind?.conversationId
|
|
6371
6403
|
});
|
|
6372
6404
|
}
|
|
6373
6405
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6384,36 +6416,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6384
6416
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6385
6417
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6386
6418
|
}
|
|
6387
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6419
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6388
6420
|
if (isResume) {
|
|
6389
6421
|
setLoadingMessages(true);
|
|
6390
6422
|
try {
|
|
6391
|
-
const chat = res.messages?.length ? {
|
|
6423
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6392
6424
|
if (isStale()) return;
|
|
6393
6425
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6394
6426
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6395
|
-
if (loaded.length || tail.length)
|
|
6396
|
-
|
|
6397
|
-
|
|
6427
|
+
if (loaded.length || tail.length) {
|
|
6428
|
+
messagesSig.value = [...loaded, ...tail];
|
|
6429
|
+
setCanSend(chat.canContinue ?? true);
|
|
6430
|
+
setSuggestions(chat.suggestions ?? []);
|
|
6431
|
+
} else {
|
|
6432
|
+
playWelcome(res.welcome?.messages);
|
|
6433
|
+
}
|
|
6398
6434
|
} catch (err) {
|
|
6399
6435
|
if (isStale()) return;
|
|
6400
|
-
log16.warn("
|
|
6401
|
-
|
|
6402
|
-
persistence.
|
|
6436
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6437
|
+
conversationIdSig.value = void 0;
|
|
6438
|
+
persistence.saveConversationId(void 0);
|
|
6403
6439
|
} finally {
|
|
6404
6440
|
if (!isStale()) setLoadingMessages(false);
|
|
6405
6441
|
}
|
|
6406
6442
|
} else {
|
|
6407
|
-
|
|
6408
|
-
persistence.
|
|
6443
|
+
conversationIdSig.value = res.conversationId;
|
|
6444
|
+
persistence.saveConversationId(res.conversationId);
|
|
6409
6445
|
playWelcome(res.welcome?.messages);
|
|
6410
6446
|
}
|
|
6411
6447
|
if (!newConversation) {
|
|
6412
|
-
bus.emit("
|
|
6413
|
-
|
|
6448
|
+
bus.emit("conversationStarted", res);
|
|
6449
|
+
setConversationReady(true);
|
|
6414
6450
|
}
|
|
6415
6451
|
},
|
|
6416
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6452
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6417
6453
|
);
|
|
6418
6454
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6419
6455
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6467,11 +6503,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6467
6503
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6468
6504
|
);
|
|
6469
6505
|
useEffect17(() => {
|
|
6470
|
-
void
|
|
6471
|
-
const
|
|
6506
|
+
void runStartConversation({ newConversation: false });
|
|
6507
|
+
const persistedConversation = conversationIdSig.value;
|
|
6472
6508
|
let resume = null;
|
|
6473
|
-
if (
|
|
6474
|
-
transport.primeIdentity(visitorId,
|
|
6509
|
+
if (persistedConversation) {
|
|
6510
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6475
6511
|
resume = transport.resumeStream();
|
|
6476
6512
|
void runResume(resume);
|
|
6477
6513
|
}
|
|
@@ -6482,10 +6518,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6482
6518
|
}, []);
|
|
6483
6519
|
const lastUserSig = useRef9(userSig);
|
|
6484
6520
|
useEffect17(() => {
|
|
6485
|
-
if (!
|
|
6521
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6486
6522
|
lastUserSig.current = userSig;
|
|
6487
|
-
void
|
|
6488
|
-
}, [userSig,
|
|
6523
|
+
void runStartConversation({ newConversation: false });
|
|
6524
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6489
6525
|
useEffect17(() => {
|
|
6490
6526
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6491
6527
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6511,14 +6547,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6511
6547
|
}, [isOpen, options.mode]);
|
|
6512
6548
|
const streamAssistant = useCallback6(
|
|
6513
6549
|
async (assistantMsg, trigger) => {
|
|
6514
|
-
const
|
|
6515
|
-
if (!
|
|
6516
|
-
|
|
6517
|
-
persistence.
|
|
6550
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6551
|
+
if (!conversationIdSig.value) {
|
|
6552
|
+
conversationIdSig.value = activeConversationId;
|
|
6553
|
+
persistence.saveConversationId(activeConversationId);
|
|
6518
6554
|
}
|
|
6519
6555
|
const body = buildSendMessageRequest({
|
|
6520
6556
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6521
|
-
|
|
6557
|
+
conversationId: activeConversationId,
|
|
6522
6558
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6523
6559
|
tools: options.features.tools,
|
|
6524
6560
|
responseMode: options.responseMode,
|
|
@@ -6554,7 +6590,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6554
6590
|
messagesSig.value = [...messagesSig.value];
|
|
6555
6591
|
}
|
|
6556
6592
|
},
|
|
6557
|
-
[transport, reducer, messagesSig,
|
|
6593
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6558
6594
|
);
|
|
6559
6595
|
const resolveTool = useCallback6(
|
|
6560
6596
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6610,32 +6646,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6610
6646
|
userContext: () => options.userContext,
|
|
6611
6647
|
messageCount: userMessageCount,
|
|
6612
6648
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6649
|
+
conversationId: () => conversationIdSig.value,
|
|
6613
6650
|
onComplete: (form, trigger, values, skipped) => {
|
|
6614
6651
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6615
6652
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6616
6653
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6617
|
-
const
|
|
6618
|
-
if (!
|
|
6619
|
-
|
|
6620
|
-
persistence.
|
|
6621
|
-
transport.primeIdentity(void 0,
|
|
6654
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6655
|
+
if (!conversationIdSig.value) {
|
|
6656
|
+
conversationIdSig.value = activeConversationId;
|
|
6657
|
+
persistence.saveConversationId(activeConversationId);
|
|
6658
|
+
transport.primeIdentity(void 0, activeConversationId);
|
|
6622
6659
|
}
|
|
6623
6660
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6624
|
-
void transport.submitForm({ formId: form.id,
|
|
6661
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6625
6662
|
}
|
|
6626
6663
|
});
|
|
6627
6664
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6628
6665
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6629
6666
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6630
6667
|
useEffect17(() => {
|
|
6631
|
-
if (
|
|
6632
|
-
}, [
|
|
6668
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6669
|
+
}, [conversationReady, forms]);
|
|
6633
6670
|
useEffect17(() => {
|
|
6634
6671
|
if (!canSend) forms.fire("conversation-closed");
|
|
6635
6672
|
}, [canSend, forms]);
|
|
6636
6673
|
useEffect17(() => {
|
|
6637
|
-
if (
|
|
6638
|
-
}, [
|
|
6674
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6675
|
+
}, [conversationReady, pageArea, forms]);
|
|
6639
6676
|
const idleMs = useMemo3(() => {
|
|
6640
6677
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6641
6678
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6695,16 +6732,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6695
6732
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6696
6733
|
const refreshUnread = useCallback6(() => {
|
|
6697
6734
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6698
|
-
transport.
|
|
6699
|
-
unreadCountSig.value = res.
|
|
6735
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6736
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6700
6737
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6701
6738
|
}, [transport, options.modules, unreadCountSig]);
|
|
6702
6739
|
const unreadSeeded = useRef9(false);
|
|
6703
6740
|
useEffect17(() => {
|
|
6704
|
-
if (!
|
|
6741
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6705
6742
|
unreadSeeded.current = true;
|
|
6706
6743
|
refreshUnread();
|
|
6707
|
-
}, [
|
|
6744
|
+
}, [conversationReady, refreshUnread]);
|
|
6708
6745
|
const handleOpen = useCallback6(() => {
|
|
6709
6746
|
log16.info("open", { mode: options.mode });
|
|
6710
6747
|
feedback.unlock();
|
|
@@ -6723,11 +6760,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6723
6760
|
if (streaming) activeCancel?.();
|
|
6724
6761
|
welcomeAbortRef.current?.abort();
|
|
6725
6762
|
messagesSig.value = [];
|
|
6726
|
-
|
|
6727
|
-
persistence.
|
|
6763
|
+
conversationIdSig.value = void 0;
|
|
6764
|
+
persistence.clearConversation();
|
|
6728
6765
|
setCanSend(true);
|
|
6729
|
-
void
|
|
6730
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6766
|
+
void runStartConversation({ newConversation: true });
|
|
6767
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6731
6768
|
const handleNewChat = useCallback6(() => {
|
|
6732
6769
|
handleClear();
|
|
6733
6770
|
setView("chat");
|
|
@@ -6751,12 +6788,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6751
6788
|
const handlePopOut = useCallback6(() => {
|
|
6752
6789
|
if (!options.popOutUrl) return;
|
|
6753
6790
|
const url = new URL(options.popOutUrl);
|
|
6754
|
-
if (
|
|
6791
|
+
if (conversationIdSig.value) url.searchParams.set("conversation", conversationIdSig.value);
|
|
6755
6792
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6756
6793
|
log16.info("popOut", { url: url.toString() });
|
|
6757
6794
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6758
6795
|
bus.emit("popOut", void 0);
|
|
6759
|
-
}, [bus,
|
|
6796
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6760
6797
|
const handleToggleHistory = useCallback6(() => {
|
|
6761
6798
|
setView((v) => {
|
|
6762
6799
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6801,28 +6838,28 @@ function App({ options, hostElement, bus }) {
|
|
|
6801
6838
|
},
|
|
6802
6839
|
[patchAndSync, bus]
|
|
6803
6840
|
);
|
|
6804
|
-
const
|
|
6805
|
-
async (
|
|
6806
|
-
log16.info("
|
|
6807
|
-
bus.emit("
|
|
6841
|
+
const handleSelectHistoryConversation = useCallback6(
|
|
6842
|
+
async (targetConversationId) => {
|
|
6843
|
+
log16.info("selectConversation", { conversationId: targetConversationId });
|
|
6844
|
+
bus.emit("selectConversation", { conversationId: targetConversationId });
|
|
6808
6845
|
try {
|
|
6809
|
-
const res = await transport.
|
|
6846
|
+
const res = await transport.loadConversation(targetConversationId);
|
|
6810
6847
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6811
6848
|
messagesSig.value = hydrated;
|
|
6812
|
-
|
|
6813
|
-
persistence.
|
|
6849
|
+
conversationIdSig.value = res.conversationId;
|
|
6850
|
+
persistence.saveConversationId(res.conversationId);
|
|
6814
6851
|
if (res.agent) setAgent(res.agent);
|
|
6815
6852
|
setCanSend(res.canContinue);
|
|
6816
6853
|
setSuggestions(res.suggestions ?? []);
|
|
6817
6854
|
setView("chat");
|
|
6818
|
-
await transport.markRead(
|
|
6855
|
+
await transport.markRead(targetConversationId);
|
|
6819
6856
|
refreshUnread();
|
|
6820
6857
|
} catch (err) {
|
|
6821
6858
|
bus.emit("error", err);
|
|
6822
6859
|
options.onError?.(err);
|
|
6823
6860
|
}
|
|
6824
6861
|
},
|
|
6825
|
-
[transport, messagesSig,
|
|
6862
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6826
6863
|
);
|
|
6827
6864
|
useEffect17(() => {
|
|
6828
6865
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6860,8 +6897,8 @@ function App({ options, hostElement, bus }) {
|
|
|
6860
6897
|
onPopOut: handlePopOut,
|
|
6861
6898
|
onSoundToggle: handleSoundToggle,
|
|
6862
6899
|
onToggleHistory: handleToggleHistory,
|
|
6863
|
-
|
|
6864
|
-
|
|
6900
|
+
onSelectHistoryConversation: handleSelectHistoryConversation,
|
|
6901
|
+
onNewConversation: handleNewChat,
|
|
6865
6902
|
onLocaleChange: handleLocaleChange,
|
|
6866
6903
|
onThemeChange: handleThemeChange,
|
|
6867
6904
|
onWidgetSizeChange: handleWidgetSizeChange,
|
|
@@ -6880,40 +6917,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6880
6917
|
onFormSkip: forms.skip,
|
|
6881
6918
|
tool: toolInteraction
|
|
6882
6919
|
};
|
|
6883
|
-
const
|
|
6884
|
-
void
|
|
6920
|
+
const onSelectConversation = (conversationId) => {
|
|
6921
|
+
void handleSelectHistoryConversation(conversationId);
|
|
6885
6922
|
const chatId = chatTabId();
|
|
6886
6923
|
if (chatId) homeNav.switchTab(chatId);
|
|
6887
6924
|
};
|
|
6888
|
-
if (!
|
|
6925
|
+
if (!conversationReady) return null;
|
|
6889
6926
|
const enabledModules = effectiveOptions.modules.list;
|
|
6890
6927
|
const renderSurface = (size) => {
|
|
6891
6928
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
6892
6929
|
if (enabledModules.length === 0) {
|
|
6893
|
-
return /* @__PURE__ */
|
|
6930
|
+
return /* @__PURE__ */ jsx36(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
6894
6931
|
}
|
|
6895
6932
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
6896
|
-
return /* @__PURE__ */
|
|
6933
|
+
return /* @__PURE__ */ jsx36(Panel, { ...panelProps, panelSize: size });
|
|
6897
6934
|
}
|
|
6898
|
-
return /* @__PURE__ */
|
|
6935
|
+
return /* @__PURE__ */ jsx36(
|
|
6899
6936
|
MessengerHome,
|
|
6900
6937
|
{
|
|
6901
6938
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
6902
6939
|
enabledModules,
|
|
6903
6940
|
nav: homeNav,
|
|
6904
6941
|
unreadCount: unreadCountSig.value,
|
|
6905
|
-
|
|
6906
|
-
|
|
6942
|
+
onSelectConversation,
|
|
6943
|
+
onStartNewConversation: handleNewChat,
|
|
6907
6944
|
onSetPanelSize: setPanelSize
|
|
6908
6945
|
}
|
|
6909
6946
|
);
|
|
6910
6947
|
};
|
|
6911
6948
|
if (options.mode === "page") {
|
|
6912
|
-
const
|
|
6913
|
-
void
|
|
6949
|
+
const onSelectConversationFromSidebar = (chat) => {
|
|
6950
|
+
void handleSelectHistoryConversation(chat.conversationId);
|
|
6914
6951
|
};
|
|
6915
|
-
const
|
|
6916
|
-
return /* @__PURE__ */
|
|
6952
|
+
const conversationsEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6953
|
+
return /* @__PURE__ */ jsx36("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx36(
|
|
6917
6954
|
PageShell,
|
|
6918
6955
|
{
|
|
6919
6956
|
site: parsedSite,
|
|
@@ -6921,9 +6958,9 @@ function App({ options, hostElement, bus }) {
|
|
|
6921
6958
|
transport,
|
|
6922
6959
|
strings: effectiveOptions.strings,
|
|
6923
6960
|
visitorId,
|
|
6924
|
-
showConversations:
|
|
6925
|
-
|
|
6926
|
-
|
|
6961
|
+
showConversations: conversationsEnabled,
|
|
6962
|
+
onSelectConversation: onSelectConversationFromSidebar,
|
|
6963
|
+
onNewConversation: handleNewChat,
|
|
6927
6964
|
sidebarCollapsed,
|
|
6928
6965
|
onToggleSidebarCollapsed: handleToggleSidebarCollapsed,
|
|
6929
6966
|
children: renderSurface("fullscreen")
|
|
@@ -6932,7 +6969,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6932
6969
|
}
|
|
6933
6970
|
if (isInlineLike) {
|
|
6934
6971
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
6935
|
-
return /* @__PURE__ */
|
|
6972
|
+
return /* @__PURE__ */ jsx36("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
6936
6973
|
}
|
|
6937
6974
|
const drawerEdgeTab = options.mode === "drawer";
|
|
6938
6975
|
const triggerOwnedByPage = options.mode === "modal";
|
|
@@ -6940,7 +6977,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6940
6977
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
6941
6978
|
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
6942
6979
|
isOpen ? renderSurface(panelSize) : null,
|
|
6943
|
-
launcherVisible ? /* @__PURE__ */
|
|
6980
|
+
launcherVisible ? /* @__PURE__ */ jsx36(
|
|
6944
6981
|
Launcher,
|
|
6945
6982
|
{
|
|
6946
6983
|
onToggle: handleOpen,
|
|
@@ -6950,7 +6987,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6950
6987
|
edgeTab: drawerEdgeTab
|
|
6951
6988
|
}
|
|
6952
6989
|
) : null,
|
|
6953
|
-
calloutToRender ? /* @__PURE__ */
|
|
6990
|
+
calloutToRender ? /* @__PURE__ */ jsx36(
|
|
6954
6991
|
LauncherCallout,
|
|
6955
6992
|
{
|
|
6956
6993
|
callout: calloutToRender,
|
|
@@ -7059,7 +7096,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7059
7096
|
/**
|
|
7060
7097
|
* Raw options accumulator. Starts as whatever the page-owner set via
|
|
7061
7098
|
* HTML attributes; gets server-side settings merged in on the
|
|
7062
|
-
* `
|
|
7099
|
+
* `conversationStarted` event so subsequent re-renders pick up the server's
|
|
7063
7100
|
* mode / theme / launcher / etc.
|
|
7064
7101
|
*
|
|
7065
7102
|
* Mirrors `index.ts`'s `rawOptions` so both entry points share the
|
|
@@ -7089,7 +7126,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7089
7126
|
existingHost: this,
|
|
7090
7127
|
position: hostPositionForMode(resolved.mode)
|
|
7091
7128
|
});
|
|
7092
|
-
this.bus.on("
|
|
7129
|
+
this.bus.on("conversationStarted", (response) => {
|
|
7093
7130
|
if (!response.config) return;
|
|
7094
7131
|
this.rawOptions = mergeServerConfig(this.rawOptions, response.config);
|
|
7095
7132
|
this.renderApp();
|
|
@@ -7099,7 +7136,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7099
7136
|
}
|
|
7100
7137
|
/**
|
|
7101
7138
|
* Apply the current `rawOptions` to the host element + App tree.
|
|
7102
|
-
* Called by both the initial boot and every `
|
|
7139
|
+
* Called by both the initial boot and every `conversationStarted` merge.
|
|
7103
7140
|
*/
|
|
7104
7141
|
renderApp() {
|
|
7105
7142
|
if (!this.mountResult) return;
|