@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/index.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",
|
|
@@ -377,7 +375,15 @@ function setLogSink(fn) {
|
|
|
377
375
|
|
|
378
376
|
// src/core/config/user-context.ts
|
|
379
377
|
var log = logger.scope("context");
|
|
380
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
378
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
379
|
+
"visitorId",
|
|
380
|
+
"conversationId",
|
|
381
|
+
"conversationId",
|
|
382
|
+
"jwt",
|
|
383
|
+
"token",
|
|
384
|
+
"authorization",
|
|
385
|
+
"password"
|
|
386
|
+
]);
|
|
381
387
|
var MAX_KEYS = 50;
|
|
382
388
|
var MAX_STRING = 1024;
|
|
383
389
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -480,7 +486,7 @@ var DEFAULT_HAPTICS = {
|
|
|
480
486
|
enabled: true,
|
|
481
487
|
events: void 0
|
|
482
488
|
};
|
|
483
|
-
var DEFAULT_MODULES = [{ label: "
|
|
489
|
+
var DEFAULT_MODULES = [{ label: "tabConversations", layout: "chat" }];
|
|
484
490
|
var DEFAULT_HOME_MODULE = { showSearchBar: true };
|
|
485
491
|
|
|
486
492
|
// src/core/config/resolve.ts
|
|
@@ -612,7 +618,7 @@ function resolveModules(overrides) {
|
|
|
612
618
|
resolved.greetingText = m.greetingText;
|
|
613
619
|
resolved.showGreeting = m.showGreeting ?? true;
|
|
614
620
|
resolved.showSearchBar = m.showSearchBar ?? DEFAULT_HOME_MODULE.showSearchBar;
|
|
615
|
-
resolved.
|
|
621
|
+
resolved.showRecentConversations = m.showRecentConversations ?? true;
|
|
616
622
|
if (m.userAvatars && m.userAvatars.length > 0) resolved.userAvatars = m.userAvatars;
|
|
617
623
|
if (m.status) resolved.status = m.status;
|
|
618
624
|
resolved.contentBlockTitle = m.contentBlockTitle;
|
|
@@ -866,7 +872,7 @@ var REACTIVE_ATTRS = [
|
|
|
866
872
|
...SPECIAL_REACTIVE_ATTRS
|
|
867
873
|
];
|
|
868
874
|
|
|
869
|
-
// src/core/start-
|
|
875
|
+
// src/core/start-conversation-shape.ts
|
|
870
876
|
function isPlainObject(raw) {
|
|
871
877
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
872
878
|
}
|
|
@@ -907,7 +913,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
907
913
|
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';
|
|
908
914
|
|
|
909
915
|
// src/styles/panel.css
|
|
910
|
-
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';
|
|
916
|
+
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';
|
|
911
917
|
|
|
912
918
|
// src/styles/standalone.css
|
|
913
919
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1191,8 +1197,8 @@ function encodeContext(user, page) {
|
|
|
1191
1197
|
|
|
1192
1198
|
// src/stream/protocol.ts
|
|
1193
1199
|
var DEFAULT_PATHS = {
|
|
1194
|
-
/**
|
|
1195
|
-
|
|
1200
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1201
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1196
1202
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1197
1203
|
streamMessage: "/ai/agent/stream-message",
|
|
1198
1204
|
/**
|
|
@@ -1205,20 +1211,20 @@ var DEFAULT_PATHS = {
|
|
|
1205
1211
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1206
1212
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1207
1213
|
/** List the visitor's conversations. `GET`. */
|
|
1208
|
-
|
|
1209
|
-
/** Load one conversation's messages. `GET ?
|
|
1214
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1215
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1210
1216
|
listMessages: "/ai/agent/list-messages",
|
|
1211
1217
|
/**
|
|
1212
1218
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1213
1219
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1214
1220
|
* the client — a failure leaves the local cache valid; the next
|
|
1215
|
-
* `
|
|
1221
|
+
* `startConversation()` reconciles.
|
|
1216
1222
|
*/
|
|
1217
1223
|
updateSettings: "/ai/agent/update-settings",
|
|
1218
1224
|
/**
|
|
1219
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1220
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1221
|
-
* `unreadCount` (returned on `/list-
|
|
1225
|
+
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1226
|
+
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1227
|
+
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1222
1228
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1223
1229
|
*/
|
|
1224
1230
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1227,8 +1233,8 @@ var DEFAULT_PATHS = {
|
|
|
1227
1233
|
content: "/ai/agent/content",
|
|
1228
1234
|
/**
|
|
1229
1235
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1230
|
-
*
|
|
1231
|
-
* immediately, keyed by the same visitor +
|
|
1236
|
+
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1237
|
+
* immediately, keyed by the same visitor + conversation as the conversation.
|
|
1232
1238
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1233
1239
|
*/
|
|
1234
1240
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1243,7 +1249,7 @@ function buildSendMessageRequest(params) {
|
|
|
1243
1249
|
}));
|
|
1244
1250
|
const body = {
|
|
1245
1251
|
messages: wire,
|
|
1246
|
-
|
|
1252
|
+
conversationId: params.conversationId,
|
|
1247
1253
|
trigger: params.trigger ?? "submit-message"
|
|
1248
1254
|
};
|
|
1249
1255
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1331,11 +1337,11 @@ function sleep(ms, signal7) {
|
|
|
1331
1337
|
var AgentTransport = class {
|
|
1332
1338
|
constructor(opts) {
|
|
1333
1339
|
__publicField(this, "opts", opts);
|
|
1334
|
-
// Identity adopted from the start-
|
|
1340
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1335
1341
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1336
|
-
// (visitor,
|
|
1342
|
+
// (visitor, conversation) pair.
|
|
1337
1343
|
__publicField(this, "visitorId");
|
|
1338
|
-
__publicField(this, "
|
|
1344
|
+
__publicField(this, "conversationId");
|
|
1339
1345
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1340
1346
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1341
1347
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1353,27 +1359,27 @@ var AgentTransport = class {
|
|
|
1353
1359
|
this.pageContext = pageContext;
|
|
1354
1360
|
}
|
|
1355
1361
|
/**
|
|
1356
|
-
* Seed the visitor +
|
|
1357
|
-
* `
|
|
1358
|
-
* with `
|
|
1359
|
-
* `
|
|
1362
|
+
* Seed the visitor + conversation identity from persistence BEFORE the first
|
|
1363
|
+
* `startConversation` resolves. A mount-time `resumeStream()` runs in parallel
|
|
1364
|
+
* with `startConversation`, so without this its envelope would carry no
|
|
1365
|
+
* `conversationId` and the resume GET couldn't identify the thread. `startConversation`
|
|
1360
1366
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1361
1367
|
*/
|
|
1362
|
-
primeIdentity(visitorId,
|
|
1368
|
+
primeIdentity(visitorId, conversationId) {
|
|
1363
1369
|
if (visitorId) this.visitorId = visitorId;
|
|
1364
|
-
if (
|
|
1370
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1365
1371
|
}
|
|
1366
1372
|
/** Build the per-request envelope from the current transport state. */
|
|
1367
1373
|
envelope() {
|
|
1368
1374
|
const out = {};
|
|
1369
1375
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1370
|
-
if (this.
|
|
1376
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1371
1377
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1372
1378
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1373
1379
|
return out;
|
|
1374
1380
|
}
|
|
1375
1381
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1376
|
-
* start-
|
|
1382
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1377
1383
|
* differs from the active one. */
|
|
1378
1384
|
withEnvelope(body) {
|
|
1379
1385
|
return { ...this.envelope(), ...body };
|
|
@@ -1384,8 +1390,8 @@ var AgentTransport = class {
|
|
|
1384
1390
|
return form;
|
|
1385
1391
|
}
|
|
1386
1392
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1387
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1388
|
-
* selector on load-
|
|
1393
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1394
|
+
* selector on load-conversation). */
|
|
1389
1395
|
withEnvelopeQuery(urlOrPath) {
|
|
1390
1396
|
const url = new URL(this.url(urlOrPath));
|
|
1391
1397
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1394,23 +1400,31 @@ var AgentTransport = class {
|
|
|
1394
1400
|
return url.toString();
|
|
1395
1401
|
}
|
|
1396
1402
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1397
|
-
async
|
|
1398
|
-
log4.debug("
|
|
1399
|
-
|
|
1400
|
-
|
|
1403
|
+
async startConversation(body) {
|
|
1404
|
+
log4.debug("startConversation \u2192", {
|
|
1405
|
+
visitorId: body.visitorId,
|
|
1406
|
+
conversationId: body.conversationId,
|
|
1407
|
+
locale: body.locale
|
|
1408
|
+
});
|
|
1409
|
+
const res = await this.postJson(
|
|
1410
|
+
DEFAULT_PATHS.startConversation,
|
|
1411
|
+
body,
|
|
1412
|
+
"startConversation"
|
|
1413
|
+
);
|
|
1414
|
+
log4.debug("startConversation \u2190", {
|
|
1401
1415
|
visitorId: res.visitorId,
|
|
1402
|
-
|
|
1416
|
+
conversationId: res.conversationId,
|
|
1403
1417
|
canContinue: res.canContinue,
|
|
1404
1418
|
hasMessages: !!res.messages?.length,
|
|
1405
1419
|
hasWelcome: !!res.welcome,
|
|
1406
1420
|
hasConfig: !!res.config,
|
|
1407
1421
|
rebind: res.rebind
|
|
1408
1422
|
});
|
|
1409
|
-
if (!
|
|
1410
|
-
log4.warn("
|
|
1423
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1424
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1411
1425
|
}
|
|
1412
1426
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1413
|
-
this.
|
|
1427
|
+
this.conversationId = res.conversationId;
|
|
1414
1428
|
return res;
|
|
1415
1429
|
}
|
|
1416
1430
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1435,45 +1449,45 @@ var AgentTransport = class {
|
|
|
1435
1449
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1436
1450
|
return res;
|
|
1437
1451
|
}
|
|
1438
|
-
async
|
|
1439
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1452
|
+
async listConversations(params = {}) {
|
|
1453
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1440
1454
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1441
1455
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1442
1456
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1443
|
-
log4.debug("
|
|
1457
|
+
log4.debug("listConversations \u2192", {
|
|
1444
1458
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1445
1459
|
limit: params.limit,
|
|
1446
1460
|
cursor: params.cursor
|
|
1447
1461
|
});
|
|
1448
|
-
const res = await this.getJson(url.toString(), "
|
|
1449
|
-
const
|
|
1450
|
-
log4.debug("
|
|
1462
|
+
const res = await this.getJson(url.toString(), "listConversations");
|
|
1463
|
+
const conversations = res.conversations ?? [];
|
|
1464
|
+
log4.debug("listConversations \u2190", { count: conversations.length, nextCursor: res.nextCursor });
|
|
1451
1465
|
return {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
title:
|
|
1455
|
-
lastMessageAt:
|
|
1456
|
-
preview:
|
|
1457
|
-
canContinue:
|
|
1458
|
-
unreadCount:
|
|
1466
|
+
conversations: conversations.map((conversation) => ({
|
|
1467
|
+
conversationId: conversation.conversationId,
|
|
1468
|
+
title: conversation.title,
|
|
1469
|
+
lastMessageAt: conversation.lastMessageAt,
|
|
1470
|
+
preview: conversation.preview,
|
|
1471
|
+
canContinue: conversation.canContinue,
|
|
1472
|
+
unreadCount: conversation.unreadCount
|
|
1459
1473
|
})),
|
|
1460
1474
|
nextCursor: res.nextCursor
|
|
1461
1475
|
};
|
|
1462
1476
|
}
|
|
1463
|
-
async
|
|
1477
|
+
async loadConversation(conversationId) {
|
|
1464
1478
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1465
|
-
url.searchParams.set("
|
|
1466
|
-
log4.debug("
|
|
1467
|
-
const res = await this.getJson(url.toString(), "
|
|
1479
|
+
url.searchParams.set("conversationId", conversationId);
|
|
1480
|
+
log4.debug("loadConversation \u2192", { conversationId, visitorId: this.visitorId });
|
|
1481
|
+
const res = await this.getJson(url.toString(), "loadConversation");
|
|
1468
1482
|
const messages = res.messages ?? [];
|
|
1469
|
-
log4.debug("
|
|
1470
|
-
|
|
1483
|
+
log4.debug("loadConversation \u2190", {
|
|
1484
|
+
conversationId: res.conversationId,
|
|
1471
1485
|
canContinue: res.canContinue,
|
|
1472
1486
|
messageCount: messages.length,
|
|
1473
1487
|
hasSuggestions: !!res.suggestions
|
|
1474
1488
|
});
|
|
1475
1489
|
return {
|
|
1476
|
-
|
|
1490
|
+
conversationId: res.conversationId,
|
|
1477
1491
|
canContinue: res.canContinue ?? true,
|
|
1478
1492
|
messages,
|
|
1479
1493
|
agent: res.agent,
|
|
@@ -1482,15 +1496,15 @@ var AgentTransport = class {
|
|
|
1482
1496
|
}
|
|
1483
1497
|
/**
|
|
1484
1498
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1485
|
-
* server records `lastReadAt` and clears that
|
|
1486
|
-
* next `/
|
|
1499
|
+
* server records `lastReadAt` and clears that conversation's `unreadCount` on the
|
|
1500
|
+
* next `/conversations`. A failure is non-fatal (the badge just lingers until the
|
|
1487
1501
|
* next sync), so callers don't await this.
|
|
1488
1502
|
*/
|
|
1489
|
-
async markRead(
|
|
1490
|
-
if (!this.visitorId || !
|
|
1491
|
-
log4.debug("markRead \u2192", {
|
|
1503
|
+
async markRead(conversationId) {
|
|
1504
|
+
if (!this.visitorId || !conversationId) return;
|
|
1505
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1492
1506
|
try {
|
|
1493
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1507
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1494
1508
|
} catch (err) {
|
|
1495
1509
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1496
1510
|
}
|
|
@@ -1516,7 +1530,7 @@ var AgentTransport = class {
|
|
|
1516
1530
|
async saveUserPrefs(userPrefs) {
|
|
1517
1531
|
log4.debug("saveUserPrefs \u2192", {
|
|
1518
1532
|
visitorId: this.visitorId,
|
|
1519
|
-
|
|
1533
|
+
conversationId: this.conversationId,
|
|
1520
1534
|
settingsKeys: Object.keys(userPrefs)
|
|
1521
1535
|
});
|
|
1522
1536
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1534,7 +1548,7 @@ var AgentTransport = class {
|
|
|
1534
1548
|
}
|
|
1535
1549
|
/**
|
|
1536
1550
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1537
|
-
* record is captured even if the visitor never sends a message. `
|
|
1551
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1538
1552
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1539
1553
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1540
1554
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1549,7 +1563,7 @@ var AgentTransport = class {
|
|
|
1549
1563
|
}
|
|
1550
1564
|
sendMessage(body) {
|
|
1551
1565
|
log4.debug("message \u2192", {
|
|
1552
|
-
|
|
1566
|
+
conversationId: body.conversationId,
|
|
1553
1567
|
visitorId: body.visitorId,
|
|
1554
1568
|
messageCount: body.messages.length,
|
|
1555
1569
|
trigger: body.trigger,
|
|
@@ -1559,16 +1573,16 @@ var AgentTransport = class {
|
|
|
1559
1573
|
const ctrl = new AbortController();
|
|
1560
1574
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1561
1575
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1562
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1576
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1563
1577
|
return { iter, cancel };
|
|
1564
1578
|
}
|
|
1565
1579
|
/**
|
|
1566
1580
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1567
1581
|
*
|
|
1568
1582
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1569
|
-
* `
|
|
1583
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1570
1584
|
* the user refreshed while the assistant was still streaming, the
|
|
1571
|
-
* `
|
|
1585
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1572
1586
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1573
1587
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1574
1588
|
* (the common case — no bubble is created).
|
|
@@ -1595,7 +1609,7 @@ var AgentTransport = class {
|
|
|
1595
1609
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1596
1610
|
* off first, the reply may still be spinning up server-side);
|
|
1597
1611
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1598
|
-
* parallel with start-
|
|
1612
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1599
1613
|
* user reloaded keeps flowing).
|
|
1600
1614
|
*
|
|
1601
1615
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1604,7 +1618,7 @@ var AgentTransport = class {
|
|
|
1604
1618
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1605
1619
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1606
1620
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1607
|
-
* turn comes from the DB via start-
|
|
1621
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1608
1622
|
*
|
|
1609
1623
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1610
1624
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1670,11 +1684,11 @@ var AgentTransport = class {
|
|
|
1670
1684
|
return false;
|
|
1671
1685
|
}
|
|
1672
1686
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1673
|
-
cancelStream(ctrl,
|
|
1687
|
+
cancelStream(ctrl, conversationId) {
|
|
1674
1688
|
if (ctrl.signal.aborted) return;
|
|
1675
|
-
log4.debug("cancel stream", {
|
|
1689
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1676
1690
|
ctrl.abort();
|
|
1677
|
-
if (!this.visitorId || !
|
|
1691
|
+
if (!this.visitorId || !conversationId) return;
|
|
1678
1692
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1679
1693
|
method: "POST",
|
|
1680
1694
|
credentials: "omit",
|
|
@@ -1699,7 +1713,7 @@ var AgentTransport = class {
|
|
|
1699
1713
|
yield* parseChatStream(res, signal7);
|
|
1700
1714
|
}
|
|
1701
1715
|
/**
|
|
1702
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1716
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1703
1717
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1704
1718
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1705
1719
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1710,7 +1724,7 @@ var AgentTransport = class {
|
|
|
1710
1724
|
return url.toString();
|
|
1711
1725
|
}
|
|
1712
1726
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1713
|
-
// update-settings / mark-read / start-
|
|
1727
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1714
1728
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1715
1729
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1716
1730
|
async postJson(path, body, label) {
|
|
@@ -1794,10 +1808,10 @@ function extensionFor(mimeType) {
|
|
|
1794
1808
|
if (mimeType.includes("wav")) return "wav";
|
|
1795
1809
|
return "bin";
|
|
1796
1810
|
}
|
|
1797
|
-
function
|
|
1811
|
+
function isStartConversationResponseShape(raw) {
|
|
1798
1812
|
if (!raw || typeof raw !== "object") return false;
|
|
1799
1813
|
const r = raw;
|
|
1800
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1814
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1801
1815
|
}
|
|
1802
1816
|
|
|
1803
1817
|
// src/stream/messages.ts
|
|
@@ -2120,7 +2134,7 @@ var log6 = logger.scope("persistence");
|
|
|
2120
2134
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2121
2135
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2122
2136
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2123
|
-
const
|
|
2137
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2124
2138
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2125
2139
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2126
2140
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2140,13 +2154,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2140
2154
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2141
2155
|
storage.set(KEY_VISITOR, id);
|
|
2142
2156
|
},
|
|
2143
|
-
|
|
2144
|
-
return storage.get(
|
|
2157
|
+
loadConversationId() {
|
|
2158
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2145
2159
|
},
|
|
2146
|
-
|
|
2147
|
-
log6.trace("
|
|
2148
|
-
if (id) storage.set(
|
|
2149
|
-
else storage.remove(
|
|
2160
|
+
saveConversationId(id) {
|
|
2161
|
+
log6.trace("saveConversationId", { id, widgetId });
|
|
2162
|
+
if (id) storage.set(KEY_CONVERSATION, id);
|
|
2163
|
+
else storage.remove(KEY_CONVERSATION);
|
|
2150
2164
|
},
|
|
2151
2165
|
loadUserPrefs() {
|
|
2152
2166
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2230,8 +2244,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2230
2244
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2231
2245
|
}
|
|
2232
2246
|
},
|
|
2233
|
-
|
|
2234
|
-
storage.remove(
|
|
2247
|
+
clearConversation() {
|
|
2248
|
+
storage.remove(KEY_CONVERSATION);
|
|
2235
2249
|
}
|
|
2236
2250
|
};
|
|
2237
2251
|
return persistence;
|
|
@@ -2413,7 +2427,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2413
2427
|
var FeedbackBus = class {
|
|
2414
2428
|
constructor(sound, haptics) {
|
|
2415
2429
|
/**
|
|
2416
|
-
* User/
|
|
2430
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2417
2431
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2418
2432
|
* `Persistence` layer.
|
|
2419
2433
|
*/
|
|
@@ -2731,16 +2745,16 @@ var TID = {
|
|
|
2731
2745
|
historyPane: `${p2}-history-pane`,
|
|
2732
2746
|
/** History pane back / close button. */
|
|
2733
2747
|
historyBack: `${p2}-history-back`,
|
|
2734
|
-
/** Single history list row — suffix `-{
|
|
2748
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2735
2749
|
historyItem: `${p2}-history-item`,
|
|
2736
2750
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2737
2751
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
2738
2752
|
sidebar: `${p2}-sidebar`,
|
|
2739
2753
|
/** Sidebar collapse / expand toggle. */
|
|
2740
2754
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2741
|
-
/** Sidebar "New
|
|
2742
|
-
|
|
2743
|
-
/** Sidebar history row — suffix `-{
|
|
2755
|
+
/** Sidebar "New conversation" button. */
|
|
2756
|
+
sidebarNewConversation: `${p2}-sidebar-new-conversation`,
|
|
2757
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2744
2758
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2745
2759
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2746
2760
|
/** Messenger-home surface root. */
|
|
@@ -2749,7 +2763,7 @@ var TID = {
|
|
|
2749
2763
|
modulesEmpty: `${p2}-modules-empty`,
|
|
2750
2764
|
/** Bottom-nav tab button — suffix `-{moduleId}` at the JSX site. */
|
|
2751
2765
|
tab: `${p2}-tab`,
|
|
2752
|
-
/** Unread badge on the
|
|
2766
|
+
/** Unread badge on the Conversations tab. */
|
|
2753
2767
|
tabBadge: `${p2}-tab-badge`,
|
|
2754
2768
|
/** Home module root. */
|
|
2755
2769
|
homeView: `${p2}-home-view`,
|
|
@@ -2764,7 +2778,7 @@ var TID = {
|
|
|
2764
2778
|
/** Home / Help search bar. */
|
|
2765
2779
|
homeSearch: `${p2}-home-search`,
|
|
2766
2780
|
helpSearch: `${p2}-help-search`,
|
|
2767
|
-
/** Home recent-
|
|
2781
|
+
/** Home recent-conversation card. */
|
|
2768
2782
|
homeRecent: `${p2}-home-recent`,
|
|
2769
2783
|
/** Home content-list row ("Popular articles") — suffix `-{id}`. */
|
|
2770
2784
|
homeContentRow: `${p2}-home-content-row`,
|
|
@@ -4781,7 +4795,7 @@ function MessageList({
|
|
|
4781
4795
|
"aria-relevant": "additions text",
|
|
4782
4796
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
4783
4797
|
children: [
|
|
4784
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.
|
|
4798
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.conversationLoading }) : null,
|
|
4785
4799
|
rows
|
|
4786
4800
|
]
|
|
4787
4801
|
}
|
|
@@ -4837,15 +4851,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4837
4851
|
if (diffDays < 7) return "lastWeek";
|
|
4838
4852
|
return "older";
|
|
4839
4853
|
}
|
|
4840
|
-
function groupByBucket(nowMs,
|
|
4854
|
+
function groupByBucket(nowMs, conversations) {
|
|
4841
4855
|
const buckets = /* @__PURE__ */ new Map();
|
|
4842
|
-
for (const chat of
|
|
4856
|
+
for (const chat of conversations) {
|
|
4843
4857
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4844
4858
|
const list = buckets.get(b);
|
|
4845
4859
|
if (list) list.push(chat);
|
|
4846
4860
|
else buckets.set(b, [chat]);
|
|
4847
4861
|
}
|
|
4848
|
-
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b,
|
|
4862
|
+
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b, conversations: buckets.get(b) }));
|
|
4849
4863
|
}
|
|
4850
4864
|
function startOfDay(ms) {
|
|
4851
4865
|
const d = new Date(ms);
|
|
@@ -4862,46 +4876,61 @@ var BUCKET_TO_STRING = {
|
|
|
4862
4876
|
lastWeek: "dateLastWeek",
|
|
4863
4877
|
older: "dateOlder"
|
|
4864
4878
|
};
|
|
4865
|
-
function ConversationList({
|
|
4879
|
+
function ConversationList({
|
|
4880
|
+
transport,
|
|
4881
|
+
strings,
|
|
4882
|
+
visitorId,
|
|
4883
|
+
onSelect,
|
|
4884
|
+
onNewConversation
|
|
4885
|
+
}) {
|
|
4866
4886
|
const p33 = BRAND.cssPrefix;
|
|
4867
4887
|
const [state, setState] = useState7("loading");
|
|
4868
|
-
const [
|
|
4888
|
+
const [conversations, setChats] = useState7([]);
|
|
4869
4889
|
useEffect9(() => {
|
|
4870
4890
|
let cancelled = false;
|
|
4871
|
-
transport.
|
|
4891
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4872
4892
|
if (cancelled) return;
|
|
4873
|
-
setChats(res.
|
|
4893
|
+
setChats(res.conversations ?? []);
|
|
4874
4894
|
setState("loaded");
|
|
4875
4895
|
}).catch((err) => {
|
|
4876
4896
|
if (cancelled) return;
|
|
4877
|
-
log11.warn("
|
|
4897
|
+
log11.warn("listConversations failed", { err });
|
|
4878
4898
|
setState("error");
|
|
4879
4899
|
});
|
|
4880
4900
|
return () => {
|
|
4881
4901
|
cancelled = true;
|
|
4882
4902
|
};
|
|
4883
4903
|
}, [transport, visitorId]);
|
|
4884
|
-
const newChatButton =
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4904
|
+
const newChatButton = onNewConversation ? /* @__PURE__ */ jsx18("div", { class: `${p33}-history-footer`, children: /* @__PURE__ */ jsxs15(
|
|
4905
|
+
"button",
|
|
4906
|
+
{
|
|
4907
|
+
type: "button",
|
|
4908
|
+
class: `${p33}-history-new`,
|
|
4909
|
+
onClick: onNewConversation,
|
|
4910
|
+
"data-testid": TID.sidebarNewConversation,
|
|
4911
|
+
children: [
|
|
4912
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
4913
|
+
strings.newConversation
|
|
4914
|
+
]
|
|
4915
|
+
}
|
|
4916
|
+
) }) : null;
|
|
4888
4917
|
if (state === "loading") {
|
|
4889
4918
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4890
4919
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
4891
4920
|
newChatButton
|
|
4892
4921
|
] });
|
|
4893
4922
|
}
|
|
4894
|
-
if (state === "error" ||
|
|
4923
|
+
if (state === "error" || conversations.length === 0) {
|
|
4895
4924
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4896
4925
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4897
4926
|
newChatButton
|
|
4898
4927
|
] });
|
|
4899
4928
|
}
|
|
4900
|
-
const groups = groupByBucket(Date.now(),
|
|
4929
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4901
4930
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4902
4931
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4903
4932
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4904
|
-
group.
|
|
4933
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4905
4934
|
"button",
|
|
4906
4935
|
{
|
|
4907
4936
|
type: "button",
|
|
@@ -4909,31 +4938,25 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4909
4938
|
class: `${p33}-history-item`,
|
|
4910
4939
|
onClick: () => onSelect(chat),
|
|
4911
4940
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4912
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4941
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
4913
4942
|
children: [
|
|
4914
4943
|
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4915
4944
|
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4916
4945
|
]
|
|
4917
4946
|
},
|
|
4918
|
-
chat.
|
|
4947
|
+
chat.conversationId
|
|
4919
4948
|
))
|
|
4920
4949
|
] }, group.bucket)) }),
|
|
4921
4950
|
newChatButton
|
|
4922
4951
|
] });
|
|
4923
4952
|
}
|
|
4924
4953
|
|
|
4925
|
-
// src/ui/chat-history-pane.tsx
|
|
4926
|
-
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4927
|
-
function ChatHistoryPane(props2) {
|
|
4928
|
-
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
4929
|
-
}
|
|
4930
|
-
|
|
4931
4954
|
// src/ui/suggestions.tsx
|
|
4932
|
-
import { jsx as
|
|
4955
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4933
4956
|
var p16 = BRAND.cssPrefix;
|
|
4934
4957
|
function Suggestions({ suggestions, onPick }) {
|
|
4935
4958
|
if (suggestions.length === 0) return null;
|
|
4936
|
-
return /* @__PURE__ */
|
|
4959
|
+
return /* @__PURE__ */ jsx19("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx19(
|
|
4937
4960
|
"button",
|
|
4938
4961
|
{
|
|
4939
4962
|
type: "button",
|
|
@@ -4947,7 +4970,7 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
4947
4970
|
}
|
|
4948
4971
|
|
|
4949
4972
|
// src/ui/panel.tsx
|
|
4950
|
-
import { Fragment as Fragment3, jsx as
|
|
4973
|
+
import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
4951
4974
|
var p17 = BRAND.cssPrefix;
|
|
4952
4975
|
function Panel(props2) {
|
|
4953
4976
|
const { options, onClose } = props2;
|
|
@@ -4983,7 +5006,7 @@ function Panel(props2) {
|
|
|
4983
5006
|
style: { position: "relative" },
|
|
4984
5007
|
"data-testid": TID.panel,
|
|
4985
5008
|
children: [
|
|
4986
|
-
/* @__PURE__ */
|
|
5009
|
+
/* @__PURE__ */ jsx20(
|
|
4987
5010
|
PanelContent,
|
|
4988
5011
|
{
|
|
4989
5012
|
...props2,
|
|
@@ -4992,7 +5015,7 @@ function Panel(props2) {
|
|
|
4992
5015
|
composerAttachApiRef
|
|
4993
5016
|
}
|
|
4994
5017
|
),
|
|
4995
|
-
/* @__PURE__ */
|
|
5018
|
+
/* @__PURE__ */ jsx20(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
4996
5019
|
]
|
|
4997
5020
|
}
|
|
4998
5021
|
);
|
|
@@ -5017,8 +5040,8 @@ function PanelContent(props2) {
|
|
|
5017
5040
|
onBack,
|
|
5018
5041
|
onClear,
|
|
5019
5042
|
onToggleHistory,
|
|
5020
|
-
|
|
5021
|
-
|
|
5043
|
+
onSelectHistoryConversation,
|
|
5044
|
+
onNewConversation,
|
|
5022
5045
|
onWidgetSizeChange,
|
|
5023
5046
|
onSend,
|
|
5024
5047
|
onStop,
|
|
@@ -5034,11 +5057,11 @@ function PanelContent(props2) {
|
|
|
5034
5057
|
const s = options.strings;
|
|
5035
5058
|
let composerArea;
|
|
5036
5059
|
if (activeForm) {
|
|
5037
|
-
composerArea = /* @__PURE__ */
|
|
5060
|
+
composerArea = /* @__PURE__ */ jsx20(FormGate, { form: activeForm, strings: s, onSubmit: onFormSubmit, onSkip: onFormSkip });
|
|
5038
5061
|
} else if (canSend) {
|
|
5039
5062
|
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5040
|
-
/* @__PURE__ */
|
|
5041
|
-
/* @__PURE__ */
|
|
5063
|
+
/* @__PURE__ */ jsx20(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
5064
|
+
/* @__PURE__ */ jsx20(
|
|
5042
5065
|
Composer,
|
|
5043
5066
|
{
|
|
5044
5067
|
options,
|
|
@@ -5053,10 +5076,10 @@ function PanelContent(props2) {
|
|
|
5053
5076
|
)
|
|
5054
5077
|
] });
|
|
5055
5078
|
} else {
|
|
5056
|
-
composerArea = /* @__PURE__ */
|
|
5079
|
+
composerArea = /* @__PURE__ */ jsx20(ReadOnlyBanner, { label: s.conversationClosed, ctaLabel: s.startNewConversation, onNewConversation: onClear });
|
|
5057
5080
|
}
|
|
5058
5081
|
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5059
|
-
view === "history" ? /* @__PURE__ */
|
|
5082
|
+
view === "history" ? /* @__PURE__ */ jsx20(
|
|
5060
5083
|
HistoryHeader,
|
|
5061
5084
|
{
|
|
5062
5085
|
strings: s,
|
|
@@ -5065,7 +5088,7 @@ function PanelContent(props2) {
|
|
|
5065
5088
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
5066
5089
|
}
|
|
5067
5090
|
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5068
|
-
onBack ? /* @__PURE__ */
|
|
5091
|
+
onBack ? /* @__PURE__ */ jsx20(
|
|
5069
5092
|
"button",
|
|
5070
5093
|
{
|
|
5071
5094
|
type: "button",
|
|
@@ -5073,24 +5096,24 @@ function PanelContent(props2) {
|
|
|
5073
5096
|
onClick: onBack,
|
|
5074
5097
|
"aria-label": s.moduleBack,
|
|
5075
5098
|
title: s.moduleBack,
|
|
5076
|
-
children: /* @__PURE__ */
|
|
5099
|
+
children: /* @__PURE__ */ jsx20(BackIcon, {})
|
|
5077
5100
|
}
|
|
5078
5101
|
) : null,
|
|
5079
|
-
agent ? /* @__PURE__ */
|
|
5080
|
-
/* @__PURE__ */
|
|
5102
|
+
agent ? /* @__PURE__ */ jsx20(AgentBadge, { agent }) : /* @__PURE__ */ jsx20("h1", { children: s.panelTitle }),
|
|
5103
|
+
/* @__PURE__ */ jsx20(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
5081
5104
|
] }),
|
|
5082
|
-
view === "history" ? /* @__PURE__ */
|
|
5083
|
-
|
|
5105
|
+
view === "history" ? /* @__PURE__ */ jsx20(
|
|
5106
|
+
ConversationList,
|
|
5084
5107
|
{
|
|
5085
5108
|
transport,
|
|
5086
5109
|
strings: s,
|
|
5087
5110
|
visitorId,
|
|
5088
|
-
onSelect: (
|
|
5089
|
-
|
|
5111
|
+
onSelect: (conversation) => onSelectHistoryConversation(conversation.conversationId),
|
|
5112
|
+
onNewConversation
|
|
5090
5113
|
}
|
|
5091
5114
|
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5092
|
-
/* @__PURE__ */
|
|
5093
|
-
/* @__PURE__ */
|
|
5115
|
+
/* @__PURE__ */ jsx20(DropZone, { visible: dragOver, strings: s }),
|
|
5116
|
+
/* @__PURE__ */ jsx20(
|
|
5094
5117
|
MessageList,
|
|
5095
5118
|
{
|
|
5096
5119
|
messagesSig,
|
|
@@ -5104,9 +5127,9 @@ function PanelContent(props2) {
|
|
|
5104
5127
|
}
|
|
5105
5128
|
),
|
|
5106
5129
|
composerArea,
|
|
5107
|
-
/* @__PURE__ */
|
|
5130
|
+
/* @__PURE__ */ jsx20(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5108
5131
|
] }),
|
|
5109
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5132
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx20(
|
|
5110
5133
|
ResizeGrip,
|
|
5111
5134
|
{
|
|
5112
5135
|
panelEl: containerEl,
|
|
@@ -5126,7 +5149,7 @@ function HistoryHeader({
|
|
|
5126
5149
|
showClose
|
|
5127
5150
|
}) {
|
|
5128
5151
|
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5129
|
-
/* @__PURE__ */
|
|
5152
|
+
/* @__PURE__ */ jsx20(
|
|
5130
5153
|
"button",
|
|
5131
5154
|
{
|
|
5132
5155
|
type: "button",
|
|
@@ -5134,11 +5157,11 @@ function HistoryHeader({
|
|
|
5134
5157
|
onClick: onBack,
|
|
5135
5158
|
"aria-label": strings.historyBack,
|
|
5136
5159
|
title: strings.historyBack,
|
|
5137
|
-
children: /* @__PURE__ */
|
|
5160
|
+
children: /* @__PURE__ */ jsx20(BackIcon, {})
|
|
5138
5161
|
}
|
|
5139
5162
|
),
|
|
5140
|
-
/* @__PURE__ */
|
|
5141
|
-
showClose ? /* @__PURE__ */
|
|
5163
|
+
/* @__PURE__ */ jsx20("h1", { children: strings.historyTitle }),
|
|
5164
|
+
showClose ? /* @__PURE__ */ jsx20(
|
|
5142
5165
|
"button",
|
|
5143
5166
|
{
|
|
5144
5167
|
type: "button",
|
|
@@ -5146,34 +5169,38 @@ function HistoryHeader({
|
|
|
5146
5169
|
onClick: onClose,
|
|
5147
5170
|
"aria-label": strings.close,
|
|
5148
5171
|
title: strings.close,
|
|
5149
|
-
children: /* @__PURE__ */
|
|
5172
|
+
children: /* @__PURE__ */ jsx20(CloseIcon, {})
|
|
5150
5173
|
}
|
|
5151
5174
|
) : null
|
|
5152
5175
|
] });
|
|
5153
5176
|
}
|
|
5154
|
-
function ReadOnlyBanner({
|
|
5177
|
+
function ReadOnlyBanner({
|
|
5178
|
+
label,
|
|
5179
|
+
ctaLabel,
|
|
5180
|
+
onNewConversation
|
|
5181
|
+
}) {
|
|
5155
5182
|
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5156
|
-
/* @__PURE__ */
|
|
5157
|
-
/* @__PURE__ */
|
|
5183
|
+
/* @__PURE__ */ jsx20("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5184
|
+
/* @__PURE__ */ jsx20("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewConversation, children: ctaLabel })
|
|
5158
5185
|
] });
|
|
5159
5186
|
}
|
|
5160
5187
|
function ComposerFooter({ disclaimer }) {
|
|
5161
5188
|
if (!disclaimer) return null;
|
|
5162
|
-
return /* @__PURE__ */
|
|
5189
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx20("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
5163
5190
|
}
|
|
5164
5191
|
function PoweredByBar({ poweredBy }) {
|
|
5165
5192
|
if (!poweredBy) return null;
|
|
5166
|
-
return /* @__PURE__ */
|
|
5193
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx20(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
5167
5194
|
}
|
|
5168
5195
|
function PoweredBy({ logoUrl, text, href }) {
|
|
5169
5196
|
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5170
|
-
logoUrl ? /* @__PURE__ */
|
|
5171
|
-
text ? /* @__PURE__ */
|
|
5197
|
+
logoUrl ? /* @__PURE__ */ jsx20("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5198
|
+
text ? /* @__PURE__ */ jsx20("span", { children: text }) : null
|
|
5172
5199
|
] });
|
|
5173
5200
|
if (href) {
|
|
5174
|
-
return /* @__PURE__ */
|
|
5201
|
+
return /* @__PURE__ */ jsx20("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
5175
5202
|
}
|
|
5176
|
-
return /* @__PURE__ */
|
|
5203
|
+
return /* @__PURE__ */ jsx20("span", { class: `${p17}-poweredby`, children: inner });
|
|
5177
5204
|
}
|
|
5178
5205
|
|
|
5179
5206
|
// src/ui/form/form-controller.ts
|
|
@@ -5188,10 +5215,11 @@ function useForms(deps) {
|
|
|
5188
5215
|
}
|
|
5189
5216
|
function createController(depsRef) {
|
|
5190
5217
|
const activeForm = signal5(null);
|
|
5191
|
-
const
|
|
5218
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5219
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5192
5220
|
const isDone = (form) => {
|
|
5193
5221
|
if (form.frequency === "always") return false;
|
|
5194
|
-
if (form.frequency === "
|
|
5222
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5195
5223
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5196
5224
|
};
|
|
5197
5225
|
const fire = (kind, param) => {
|
|
@@ -5214,7 +5242,7 @@ function createController(depsRef) {
|
|
|
5214
5242
|
if (!active) return;
|
|
5215
5243
|
activeForm.value = null;
|
|
5216
5244
|
const { form, trigger } = active;
|
|
5217
|
-
if (form.frequency === "
|
|
5245
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5218
5246
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5219
5247
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5220
5248
|
};
|
|
@@ -5248,7 +5276,7 @@ function whenPasses(form, d) {
|
|
|
5248
5276
|
}
|
|
5249
5277
|
|
|
5250
5278
|
// src/ui/sidebar.tsx
|
|
5251
|
-
import { Fragment as Fragment4, jsx as
|
|
5279
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
5252
5280
|
function Sidebar(props2) {
|
|
5253
5281
|
const p33 = BRAND.cssPrefix;
|
|
5254
5282
|
const { site, blocks, strings, collapsed } = props2;
|
|
@@ -5257,8 +5285,8 @@ function Sidebar(props2) {
|
|
|
5257
5285
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
5258
5286
|
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5259
5287
|
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5260
|
-
/* @__PURE__ */
|
|
5261
|
-
/* @__PURE__ */
|
|
5288
|
+
/* @__PURE__ */ jsx21(SidebarBrand, { site }),
|
|
5289
|
+
/* @__PURE__ */ jsx21(
|
|
5262
5290
|
"button",
|
|
5263
5291
|
{
|
|
5264
5292
|
type: "button",
|
|
@@ -5268,21 +5296,21 @@ function Sidebar(props2) {
|
|
|
5268
5296
|
title: toggleLabel,
|
|
5269
5297
|
onClick: props2.onToggleCollapsed,
|
|
5270
5298
|
"data-testid": TID.sidebarToggle,
|
|
5271
|
-
children: /* @__PURE__ */
|
|
5299
|
+
children: /* @__PURE__ */ jsx21(SidebarToggleIcon, { collapsed })
|
|
5272
5300
|
}
|
|
5273
5301
|
)
|
|
5274
5302
|
] }),
|
|
5275
5303
|
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5276
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
5277
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
5278
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5304
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx21("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx21(SidebarNav, { items: navigation }) }) : null,
|
|
5305
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx21(SidebarCards, { items: linkCards }) }) : null,
|
|
5306
|
+
props2.showConversations ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx21(
|
|
5279
5307
|
ConversationList,
|
|
5280
5308
|
{
|
|
5281
5309
|
transport: props2.transport,
|
|
5282
5310
|
strings: props2.strings,
|
|
5283
5311
|
visitorId: props2.visitorId,
|
|
5284
|
-
onSelect: props2.
|
|
5285
|
-
|
|
5312
|
+
onSelect: props2.onSelectConversation,
|
|
5313
|
+
onNewConversation: props2.onNewConversation
|
|
5286
5314
|
}
|
|
5287
5315
|
) }) : null
|
|
5288
5316
|
] })
|
|
@@ -5293,14 +5321,14 @@ function SidebarBrand({ site }) {
|
|
|
5293
5321
|
if (site?.logo?.url) {
|
|
5294
5322
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
5295
5323
|
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5296
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
5297
|
-
/* @__PURE__ */
|
|
5324
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx21("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5325
|
+
/* @__PURE__ */ jsx21("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
5298
5326
|
] });
|
|
5299
5327
|
}
|
|
5300
|
-
return /* @__PURE__ */
|
|
5328
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
5301
5329
|
}
|
|
5302
5330
|
function SidebarToggleIcon({ collapsed }) {
|
|
5303
|
-
return /* @__PURE__ */
|
|
5331
|
+
return /* @__PURE__ */ jsx21(
|
|
5304
5332
|
"svg",
|
|
5305
5333
|
{
|
|
5306
5334
|
width: "16",
|
|
@@ -5310,13 +5338,13 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
5310
5338
|
stroke: "currentColor",
|
|
5311
5339
|
"stroke-width": "2",
|
|
5312
5340
|
"aria-hidden": "true",
|
|
5313
|
-
children: collapsed ? /* @__PURE__ */
|
|
5341
|
+
children: collapsed ? /* @__PURE__ */ jsx21("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx21("polyline", { points: "15 6 9 12 15 18" })
|
|
5314
5342
|
}
|
|
5315
5343
|
);
|
|
5316
5344
|
}
|
|
5317
5345
|
function SidebarNav({ items }) {
|
|
5318
5346
|
const p33 = BRAND.cssPrefix;
|
|
5319
|
-
return /* @__PURE__ */
|
|
5347
|
+
return /* @__PURE__ */ jsx21("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx21("li", { children: /* @__PURE__ */ jsxs17(
|
|
5320
5348
|
"a",
|
|
5321
5349
|
{
|
|
5322
5350
|
class: `${p33}-sidebar-nav-item`,
|
|
@@ -5324,15 +5352,15 @@ function SidebarNav({ items }) {
|
|
|
5324
5352
|
target: item.href ? "_blank" : void 0,
|
|
5325
5353
|
rel: item.href ? "noreferrer" : void 0,
|
|
5326
5354
|
children: [
|
|
5327
|
-
item.icon ? /* @__PURE__ */
|
|
5328
|
-
/* @__PURE__ */
|
|
5355
|
+
item.icon ? /* @__PURE__ */ jsx21("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5356
|
+
/* @__PURE__ */ jsx21("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
5329
5357
|
]
|
|
5330
5358
|
}
|
|
5331
5359
|
) }, item.id ?? item.label)) });
|
|
5332
5360
|
}
|
|
5333
5361
|
function SidebarCards({ items }) {
|
|
5334
5362
|
const p33 = BRAND.cssPrefix;
|
|
5335
|
-
return /* @__PURE__ */
|
|
5363
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
5336
5364
|
"a",
|
|
5337
5365
|
{
|
|
5338
5366
|
class: `${p33}-sidebar-card`,
|
|
@@ -5340,8 +5368,8 @@ function SidebarCards({ items }) {
|
|
|
5340
5368
|
target: item.href ? "_blank" : void 0,
|
|
5341
5369
|
rel: item.href ? "noreferrer" : void 0,
|
|
5342
5370
|
children: [
|
|
5343
|
-
/* @__PURE__ */
|
|
5344
|
-
item.description ? /* @__PURE__ */
|
|
5371
|
+
/* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5372
|
+
item.description ? /* @__PURE__ */ jsx21("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
5345
5373
|
]
|
|
5346
5374
|
},
|
|
5347
5375
|
item.id ?? item.label
|
|
@@ -5349,11 +5377,11 @@ function SidebarCards({ items }) {
|
|
|
5349
5377
|
}
|
|
5350
5378
|
|
|
5351
5379
|
// src/ui/page-shell.tsx
|
|
5352
|
-
import { jsx as
|
|
5380
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5353
5381
|
var p18 = BRAND.cssPrefix;
|
|
5354
5382
|
function PageShell(props2) {
|
|
5355
5383
|
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5356
|
-
/* @__PURE__ */
|
|
5384
|
+
/* @__PURE__ */ jsx22(
|
|
5357
5385
|
Sidebar,
|
|
5358
5386
|
{
|
|
5359
5387
|
site: props2.site,
|
|
@@ -5362,13 +5390,13 @@ function PageShell(props2) {
|
|
|
5362
5390
|
strings: props2.strings,
|
|
5363
5391
|
visitorId: props2.visitorId,
|
|
5364
5392
|
showConversations: props2.showConversations,
|
|
5365
|
-
|
|
5366
|
-
|
|
5393
|
+
onSelectConversation: props2.onSelectConversation,
|
|
5394
|
+
onNewConversation: props2.onNewConversation,
|
|
5367
5395
|
collapsed: props2.sidebarCollapsed,
|
|
5368
5396
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
5369
5397
|
}
|
|
5370
5398
|
),
|
|
5371
|
-
/* @__PURE__ */
|
|
5399
|
+
/* @__PURE__ */ jsx22("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
5372
5400
|
] });
|
|
5373
5401
|
}
|
|
5374
5402
|
|
|
@@ -5408,7 +5436,7 @@ var atTabRoot = (s) => activeStack(s).length === 0;
|
|
|
5408
5436
|
import { useCallback as useCallback4, useEffect as useEffect15, useRef as useRef8 } from "preact/hooks";
|
|
5409
5437
|
import { useComputed as useComputed6 } from "@preact/signals";
|
|
5410
5438
|
|
|
5411
|
-
// src/ui/modules/
|
|
5439
|
+
// src/ui/modules/chat.tsx
|
|
5412
5440
|
var chatLayout = {
|
|
5413
5441
|
Icon: BubblesIcon
|
|
5414
5442
|
// No `Root`: MessengerHome renders the existing chat panel for this tab.
|
|
@@ -5418,35 +5446,35 @@ var chatLayout = {
|
|
|
5418
5446
|
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
5419
5447
|
|
|
5420
5448
|
// src/ui/back-header.tsx
|
|
5421
|
-
import { jsx as
|
|
5449
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5422
5450
|
var p19 = BRAND.cssPrefix;
|
|
5423
5451
|
function TitleBar({ title, actions }) {
|
|
5424
5452
|
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5425
|
-
/* @__PURE__ */
|
|
5426
|
-
/* @__PURE__ */
|
|
5427
|
-
actions ?? /* @__PURE__ */
|
|
5453
|
+
/* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5454
|
+
/* @__PURE__ */ jsx23("h1", { class: `${p19}-back-title`, children: title }),
|
|
5455
|
+
actions ?? /* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5428
5456
|
] });
|
|
5429
5457
|
}
|
|
5430
5458
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
5431
5459
|
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5432
|
-
/* @__PURE__ */
|
|
5433
|
-
/* @__PURE__ */
|
|
5434
|
-
actions ?? /* @__PURE__ */
|
|
5460
|
+
/* @__PURE__ */ jsx23("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx23(BackIcon, {}) }),
|
|
5461
|
+
/* @__PURE__ */ jsx23("h1", { class: `${p19}-back-title`, children: title }),
|
|
5462
|
+
actions ?? /* @__PURE__ */ jsx23("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5435
5463
|
] });
|
|
5436
5464
|
}
|
|
5437
5465
|
|
|
5438
5466
|
// src/ui/home-search.tsx
|
|
5439
|
-
import { jsx as
|
|
5467
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5440
5468
|
var p20 = BRAND.cssPrefix;
|
|
5441
5469
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
5442
5470
|
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5443
|
-
/* @__PURE__ */
|
|
5444
|
-
/* @__PURE__ */
|
|
5471
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5472
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx24(SearchIcon, {}) })
|
|
5445
5473
|
] });
|
|
5446
5474
|
}
|
|
5447
5475
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
5448
5476
|
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5449
|
-
/* @__PURE__ */
|
|
5477
|
+
/* @__PURE__ */ jsx24(
|
|
5450
5478
|
"input",
|
|
5451
5479
|
{
|
|
5452
5480
|
type: "search",
|
|
@@ -5457,25 +5485,25 @@ function HelpSearchInput({ placeholder, value, onInput }) {
|
|
|
5457
5485
|
"data-testid": TID.helpSearch
|
|
5458
5486
|
}
|
|
5459
5487
|
),
|
|
5460
|
-
/* @__PURE__ */
|
|
5488
|
+
/* @__PURE__ */ jsx24("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx24(SearchIcon, {}) })
|
|
5461
5489
|
] });
|
|
5462
5490
|
}
|
|
5463
5491
|
|
|
5464
5492
|
// src/ui/list-row.tsx
|
|
5465
|
-
import { jsx as
|
|
5493
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5466
5494
|
var p21 = BRAND.cssPrefix;
|
|
5467
5495
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
5468
5496
|
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5469
5497
|
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5470
|
-
/* @__PURE__ */
|
|
5471
|
-
subtitle ? /* @__PURE__ */
|
|
5498
|
+
/* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5499
|
+
subtitle ? /* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
5472
5500
|
] }),
|
|
5473
|
-
/* @__PURE__ */
|
|
5501
|
+
/* @__PURE__ */ jsx25("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(ChevronRightIcon, {}) })
|
|
5474
5502
|
] });
|
|
5475
5503
|
}
|
|
5476
5504
|
|
|
5477
5505
|
// src/ui/module-state.tsx
|
|
5478
|
-
import { jsx as
|
|
5506
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5479
5507
|
var p22 = BRAND.cssPrefix;
|
|
5480
5508
|
function ModuleState({
|
|
5481
5509
|
tone = "info",
|
|
@@ -5484,13 +5512,13 @@ function ModuleState({
|
|
|
5484
5512
|
strings
|
|
5485
5513
|
}) {
|
|
5486
5514
|
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5487
|
-
/* @__PURE__ */
|
|
5488
|
-
onRetry ? /* @__PURE__ */
|
|
5515
|
+
/* @__PURE__ */ jsx26("span", { children: message }),
|
|
5516
|
+
onRetry ? /* @__PURE__ */ jsx26("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
5489
5517
|
] });
|
|
5490
5518
|
}
|
|
5491
5519
|
|
|
5492
5520
|
// src/ui/modules/help.tsx
|
|
5493
|
-
import { jsx as
|
|
5521
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5494
5522
|
var p23 = BRAND.cssPrefix;
|
|
5495
5523
|
var log12 = logger.scope("help");
|
|
5496
5524
|
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 });
|
|
@@ -5520,7 +5548,7 @@ function fuzzySearch(items, query) {
|
|
|
5520
5548
|
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);
|
|
5521
5549
|
}
|
|
5522
5550
|
function ArticleRow({ article, nav }) {
|
|
5523
|
-
return /* @__PURE__ */
|
|
5551
|
+
return /* @__PURE__ */ jsx27(
|
|
5524
5552
|
ListRow,
|
|
5525
5553
|
{
|
|
5526
5554
|
title: article.title,
|
|
@@ -5557,45 +5585,45 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5557
5585
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
5558
5586
|
function renderBody() {
|
|
5559
5587
|
if (query.trim().length > 0) {
|
|
5560
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
5561
|
-
return /* @__PURE__ */
|
|
5588
|
+
if (results.length === 0) return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5589
|
+
return /* @__PURE__ */ jsx27("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx27(ArticleRow, { article: a, nav }, a.id)) });
|
|
5562
5590
|
}
|
|
5563
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5591
|
+
if (state === "loading") return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpLoading, strings });
|
|
5564
5592
|
if (state === "error") {
|
|
5565
|
-
return /* @__PURE__ */
|
|
5593
|
+
return /* @__PURE__ */ jsx27(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5566
5594
|
}
|
|
5567
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5595
|
+
if (items.length === 0) return /* @__PURE__ */ jsx27(ModuleState, { message: strings.helpEmpty, strings });
|
|
5568
5596
|
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5569
|
-
category ? /* @__PURE__ */
|
|
5570
|
-
/* @__PURE__ */
|
|
5597
|
+
category ? /* @__PURE__ */ jsx27("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5598
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx27(ArticleRow, { article: a, nav }, a.id)) })
|
|
5571
5599
|
] }, category));
|
|
5572
5600
|
}
|
|
5573
5601
|
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5574
|
-
/* @__PURE__ */
|
|
5575
|
-
/* @__PURE__ */
|
|
5576
|
-
/* @__PURE__ */
|
|
5602
|
+
/* @__PURE__ */ jsx27(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx27(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5603
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx27(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5604
|
+
/* @__PURE__ */ jsx27("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
5577
5605
|
] });
|
|
5578
5606
|
}
|
|
5579
5607
|
var helpLayout = {
|
|
5580
5608
|
Icon: HelpIcon,
|
|
5581
|
-
Root: (props2) => /* @__PURE__ */
|
|
5609
|
+
Root: (props2) => /* @__PURE__ */ jsx27(HelpRoot, { ...props2 })
|
|
5582
5610
|
};
|
|
5583
5611
|
|
|
5584
5612
|
// src/ui/modules/home.tsx
|
|
5585
5613
|
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
5586
5614
|
|
|
5587
5615
|
// src/ui/home-card.tsx
|
|
5588
|
-
import { jsx as
|
|
5616
|
+
import { jsx as jsx28 } from "preact/jsx-runtime";
|
|
5589
5617
|
var p24 = BRAND.cssPrefix;
|
|
5590
5618
|
function HomeCard({ onClick, children, testid }) {
|
|
5591
5619
|
if (onClick) {
|
|
5592
|
-
return /* @__PURE__ */
|
|
5620
|
+
return /* @__PURE__ */ jsx28("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
5593
5621
|
}
|
|
5594
|
-
return /* @__PURE__ */
|
|
5622
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
5595
5623
|
}
|
|
5596
5624
|
|
|
5597
5625
|
// src/ui/modules/home.tsx
|
|
5598
|
-
import { Fragment as Fragment5, jsx as
|
|
5626
|
+
import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5599
5627
|
var p25 = BRAND.cssPrefix;
|
|
5600
5628
|
var log13 = logger.scope("home");
|
|
5601
5629
|
function resolveGreeting(props2) {
|
|
@@ -5614,13 +5642,13 @@ function HomeRoot(props2) {
|
|
|
5614
5642
|
const [content, setContent] = useState9([]);
|
|
5615
5643
|
const tagsKey = config.contentTags?.join(",");
|
|
5616
5644
|
useEffect12(() => {
|
|
5617
|
-
if (!config.
|
|
5645
|
+
if (!config.showRecentConversations) return;
|
|
5618
5646
|
let cancelled = false;
|
|
5619
|
-
transport.
|
|
5647
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5620
5648
|
return () => {
|
|
5621
5649
|
cancelled = true;
|
|
5622
5650
|
};
|
|
5623
|
-
}, [transport, config.
|
|
5651
|
+
}, [transport, config.showRecentConversations]);
|
|
5624
5652
|
useEffect12(() => {
|
|
5625
5653
|
if (!config.contentTags?.length) return;
|
|
5626
5654
|
let cancelled = false;
|
|
@@ -5633,49 +5661,49 @@ function HomeRoot(props2) {
|
|
|
5633
5661
|
const avatars = config.userAvatars ?? [];
|
|
5634
5662
|
const status = config.status;
|
|
5635
5663
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
5636
|
-
return /* @__PURE__ */
|
|
5664
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5637
5665
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5638
5666
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5639
|
-
config.brandName ? /* @__PURE__ */
|
|
5667
|
+
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" }),
|
|
5640
5668
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5641
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
5642
|
-
/* @__PURE__ */
|
|
5669
|
+
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,
|
|
5670
|
+
/* @__PURE__ */ jsx29(HeaderActions, { panelProps, variant: "plain" })
|
|
5643
5671
|
] })
|
|
5644
5672
|
] }),
|
|
5645
5673
|
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5646
|
-
/* @__PURE__ */
|
|
5647
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5674
|
+
/* @__PURE__ */ jsx29("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5675
|
+
greeting.subtitle ? /* @__PURE__ */ jsx29("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
5648
5676
|
] }) : null
|
|
5649
5677
|
] }),
|
|
5650
5678
|
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5651
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5679
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx29(
|
|
5652
5680
|
HomeSearchButton,
|
|
5653
5681
|
{
|
|
5654
5682
|
placeholder: strings.homeSearchPlaceholder,
|
|
5655
5683
|
onActivate: () => nav.switchToLayout("help")
|
|
5656
5684
|
}
|
|
5657
5685
|
) : null,
|
|
5658
|
-
recent ? /* @__PURE__ */
|
|
5659
|
-
/* @__PURE__ */
|
|
5686
|
+
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: [
|
|
5687
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx29(BubblesIcon, {}) }),
|
|
5660
5688
|
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5661
|
-
/* @__PURE__ */
|
|
5662
|
-
recent.preview ? /* @__PURE__ */
|
|
5689
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5690
|
+
recent.preview ? /* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
5663
5691
|
] }),
|
|
5664
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5692
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx29("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
5665
5693
|
] }) }) : null,
|
|
5666
|
-
status ? /* @__PURE__ */
|
|
5694
|
+
status ? /* @__PURE__ */ jsx29(
|
|
5667
5695
|
HomeCard,
|
|
5668
5696
|
{
|
|
5669
5697
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
5670
5698
|
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5671
|
-
/* @__PURE__ */
|
|
5672
|
-
/* @__PURE__ */
|
|
5699
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx29(StatusOkIcon, {}) }),
|
|
5700
|
+
/* @__PURE__ */ jsx29("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
5673
5701
|
] })
|
|
5674
5702
|
}
|
|
5675
5703
|
) : null,
|
|
5676
5704
|
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5677
|
-
/* @__PURE__ */
|
|
5678
|
-
/* @__PURE__ */
|
|
5705
|
+
/* @__PURE__ */ jsx29("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5706
|
+
/* @__PURE__ */ jsx29("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx29(
|
|
5679
5707
|
ListRow,
|
|
5680
5708
|
{
|
|
5681
5709
|
title: item.title,
|
|
@@ -5691,12 +5719,12 @@ function HomeRoot(props2) {
|
|
|
5691
5719
|
}
|
|
5692
5720
|
var homeLayout = {
|
|
5693
5721
|
Icon: HomeIcon,
|
|
5694
|
-
Root: (props2) => /* @__PURE__ */
|
|
5722
|
+
Root: (props2) => /* @__PURE__ */ jsx29(HomeRoot, { ...props2 })
|
|
5695
5723
|
};
|
|
5696
5724
|
|
|
5697
5725
|
// src/ui/modules/news.tsx
|
|
5698
5726
|
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5699
|
-
import { jsx as
|
|
5727
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5700
5728
|
var p26 = BRAND.cssPrefix;
|
|
5701
5729
|
var log14 = logger.scope("news");
|
|
5702
5730
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
@@ -5723,12 +5751,12 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5723
5751
|
};
|
|
5724
5752
|
}, [transport, tags, reloadKey]);
|
|
5725
5753
|
function renderBody() {
|
|
5726
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5754
|
+
if (state === "loading") return /* @__PURE__ */ jsx30(ModuleState, { message: strings.newsLoading, strings });
|
|
5727
5755
|
if (state === "error") {
|
|
5728
|
-
return /* @__PURE__ */
|
|
5756
|
+
return /* @__PURE__ */ jsx30(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5729
5757
|
}
|
|
5730
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5731
|
-
return /* @__PURE__ */
|
|
5758
|
+
if (items.length === 0) return /* @__PURE__ */ jsx30(ModuleState, { message: strings.newsEmpty, strings });
|
|
5759
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
5732
5760
|
"button",
|
|
5733
5761
|
{
|
|
5734
5762
|
type: "button",
|
|
@@ -5736,11 +5764,11 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5736
5764
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
5737
5765
|
"data-testid": tid(TID.newsItem, item.id),
|
|
5738
5766
|
children: [
|
|
5739
|
-
item.image ? /* @__PURE__ */
|
|
5767
|
+
item.image ? /* @__PURE__ */ jsx30("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5740
5768
|
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5741
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5742
|
-
/* @__PURE__ */
|
|
5743
|
-
item.description ? /* @__PURE__ */
|
|
5769
|
+
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,
|
|
5770
|
+
/* @__PURE__ */ jsx30("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5771
|
+
item.description ? /* @__PURE__ */ jsx30("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
5744
5772
|
] })
|
|
5745
5773
|
]
|
|
5746
5774
|
},
|
|
@@ -5748,13 +5776,13 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5748
5776
|
)) });
|
|
5749
5777
|
}
|
|
5750
5778
|
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5751
|
-
/* @__PURE__ */
|
|
5752
|
-
/* @__PURE__ */
|
|
5779
|
+
/* @__PURE__ */ jsx30(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5780
|
+
/* @__PURE__ */ jsx30("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
5753
5781
|
] });
|
|
5754
5782
|
}
|
|
5755
5783
|
var newsLayout = {
|
|
5756
5784
|
Icon: NewsIcon,
|
|
5757
|
-
Root: (props2) => /* @__PURE__ */
|
|
5785
|
+
Root: (props2) => /* @__PURE__ */ jsx30(NewsRoot, { ...props2 })
|
|
5758
5786
|
};
|
|
5759
5787
|
|
|
5760
5788
|
// src/ui/modules/registry.ts
|
|
@@ -5766,10 +5794,10 @@ var LAYOUTS = {
|
|
|
5766
5794
|
};
|
|
5767
5795
|
|
|
5768
5796
|
// src/ui/home-tab-bar.tsx
|
|
5769
|
-
import { jsx as
|
|
5797
|
+
import { jsx as jsx31, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5770
5798
|
var p27 = BRAND.cssPrefix;
|
|
5771
5799
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
5772
|
-
return /* @__PURE__ */
|
|
5800
|
+
return /* @__PURE__ */ jsx31("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
5773
5801
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
5774
5802
|
const selected = m.id === activeTab;
|
|
5775
5803
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
@@ -5784,10 +5812,10 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5784
5812
|
"data-testid": tid(TID.tab, m.id),
|
|
5785
5813
|
children: [
|
|
5786
5814
|
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5787
|
-
/* @__PURE__ */
|
|
5788
|
-
badge ? /* @__PURE__ */
|
|
5815
|
+
/* @__PURE__ */ jsx31(Icon, {}),
|
|
5816
|
+
badge ? /* @__PURE__ */ jsx31("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
5789
5817
|
] }),
|
|
5790
|
-
/* @__PURE__ */
|
|
5818
|
+
/* @__PURE__ */ jsx31("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
5791
5819
|
]
|
|
5792
5820
|
},
|
|
5793
5821
|
m.id
|
|
@@ -5796,12 +5824,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5796
5824
|
}
|
|
5797
5825
|
|
|
5798
5826
|
// src/ui/iframe-view.tsx
|
|
5799
|
-
import { jsx as
|
|
5827
|
+
import { jsx as jsx32, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5800
5828
|
var p28 = BRAND.cssPrefix;
|
|
5801
5829
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
5802
5830
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
5803
5831
|
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5804
|
-
/* @__PURE__ */
|
|
5832
|
+
/* @__PURE__ */ jsx32(
|
|
5805
5833
|
BackHeader,
|
|
5806
5834
|
{
|
|
5807
5835
|
title: title || strings.moduleBack,
|
|
@@ -5810,7 +5838,7 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5810
5838
|
actions
|
|
5811
5839
|
}
|
|
5812
5840
|
),
|
|
5813
|
-
/* @__PURE__ */
|
|
5841
|
+
/* @__PURE__ */ jsx32(
|
|
5814
5842
|
"iframe",
|
|
5815
5843
|
{
|
|
5816
5844
|
class: `${p28}-content-frame`,
|
|
@@ -5827,7 +5855,7 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5827
5855
|
|
|
5828
5856
|
// src/ui/content-view.tsx
|
|
5829
5857
|
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5830
|
-
import { jsx as
|
|
5858
|
+
import { jsx as jsx33, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5831
5859
|
var p29 = BRAND.cssPrefix;
|
|
5832
5860
|
var log15 = logger.scope("content");
|
|
5833
5861
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
@@ -5856,17 +5884,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5856
5884
|
};
|
|
5857
5885
|
}, [transport, id, reloadKey]);
|
|
5858
5886
|
function renderBody() {
|
|
5859
|
-
if (failed) return /* @__PURE__ */
|
|
5860
|
-
if (item === null) return /* @__PURE__ */
|
|
5887
|
+
if (failed) return /* @__PURE__ */ jsx33(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5888
|
+
if (item === null) return /* @__PURE__ */ jsx33(ModuleState, { message: strings.contentLoading, strings });
|
|
5861
5889
|
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5862
|
-
item.image ? /* @__PURE__ */
|
|
5863
|
-
item.description ? /* @__PURE__ */
|
|
5864
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5865
|
-
/* @__PURE__ */
|
|
5890
|
+
item.image ? /* @__PURE__ */ jsx33("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5891
|
+
item.description ? /* @__PURE__ */ jsx33("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5892
|
+
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,
|
|
5893
|
+
/* @__PURE__ */ jsx33(StaticMarkdown, { text: item.content ?? "" })
|
|
5866
5894
|
] });
|
|
5867
5895
|
}
|
|
5868
5896
|
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5869
|
-
/* @__PURE__ */
|
|
5897
|
+
/* @__PURE__ */ jsx33(
|
|
5870
5898
|
BackHeader,
|
|
5871
5899
|
{
|
|
5872
5900
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -5876,20 +5904,20 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5876
5904
|
testid: TID.backHeader
|
|
5877
5905
|
}
|
|
5878
5906
|
),
|
|
5879
|
-
/* @__PURE__ */
|
|
5907
|
+
/* @__PURE__ */ jsx33("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
5880
5908
|
] });
|
|
5881
5909
|
}
|
|
5882
5910
|
|
|
5883
5911
|
// src/ui/messenger-home.tsx
|
|
5884
|
-
import { jsx as
|
|
5912
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5885
5913
|
var p30 = BRAND.cssPrefix;
|
|
5886
5914
|
function MessengerHome({
|
|
5887
5915
|
panelProps,
|
|
5888
5916
|
enabledModules,
|
|
5889
5917
|
nav,
|
|
5890
5918
|
unreadCount,
|
|
5891
|
-
|
|
5892
|
-
|
|
5919
|
+
onSelectConversation,
|
|
5920
|
+
onStartNewConversation,
|
|
5893
5921
|
onSetPanelSize
|
|
5894
5922
|
}) {
|
|
5895
5923
|
const options = panelProps.options;
|
|
@@ -5938,8 +5966,8 @@ function MessengerHome({
|
|
|
5938
5966
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
5939
5967
|
if (target) nav.switchTab(target.id);
|
|
5940
5968
|
},
|
|
5941
|
-
|
|
5942
|
-
|
|
5969
|
+
selectConversation: onSelectConversation,
|
|
5970
|
+
startNewConversation: onStartNewConversation
|
|
5943
5971
|
};
|
|
5944
5972
|
const screenProps = (module) => ({
|
|
5945
5973
|
options,
|
|
@@ -5950,12 +5978,12 @@ function MessengerHome({
|
|
|
5950
5978
|
nav: moduleNav,
|
|
5951
5979
|
panelProps
|
|
5952
5980
|
});
|
|
5953
|
-
const plainActions = /* @__PURE__ */
|
|
5981
|
+
const plainActions = /* @__PURE__ */ jsx34(HeaderActions, { panelProps, variant: "plain" });
|
|
5954
5982
|
let body;
|
|
5955
5983
|
if (top?.kind === "iframe") {
|
|
5956
|
-
body = /* @__PURE__ */
|
|
5984
|
+
body = /* @__PURE__ */ jsx34(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
5957
5985
|
} else if (top?.kind === "content") {
|
|
5958
|
-
body = /* @__PURE__ */
|
|
5986
|
+
body = /* @__PURE__ */ jsx34(
|
|
5959
5987
|
ContentView,
|
|
5960
5988
|
{
|
|
5961
5989
|
id: top.id,
|
|
@@ -5967,7 +5995,7 @@ function MessengerHome({
|
|
|
5967
5995
|
}
|
|
5968
5996
|
);
|
|
5969
5997
|
} else if (activeModule?.layout === "chat") {
|
|
5970
|
-
body = /* @__PURE__ */
|
|
5998
|
+
body = /* @__PURE__ */ jsx34(
|
|
5971
5999
|
PanelContent,
|
|
5972
6000
|
{
|
|
5973
6001
|
...panelProps,
|
|
@@ -5978,7 +6006,7 @@ function MessengerHome({
|
|
|
5978
6006
|
);
|
|
5979
6007
|
} else if (activeModule) {
|
|
5980
6008
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
5981
|
-
body = Root ? /* @__PURE__ */
|
|
6009
|
+
body = Root ? /* @__PURE__ */ jsx34(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
5982
6010
|
} else {
|
|
5983
6011
|
body = null;
|
|
5984
6012
|
}
|
|
@@ -5993,8 +6021,8 @@ function MessengerHome({
|
|
|
5993
6021
|
style: { position: "relative" },
|
|
5994
6022
|
"data-testid": TID.messengerHome,
|
|
5995
6023
|
children: [
|
|
5996
|
-
/* @__PURE__ */
|
|
5997
|
-
showTabBar ? /* @__PURE__ */
|
|
6024
|
+
/* @__PURE__ */ jsx34("div", { class: `${p30}-messenger-body`, children: body }),
|
|
6025
|
+
showTabBar ? /* @__PURE__ */ jsx34(
|
|
5998
6026
|
HomeTabBar,
|
|
5999
6027
|
{
|
|
6000
6028
|
modules: enabledModules,
|
|
@@ -6004,8 +6032,8 @@ function MessengerHome({
|
|
|
6004
6032
|
onSelect: nav.switchTab
|
|
6005
6033
|
}
|
|
6006
6034
|
) : null,
|
|
6007
|
-
/* @__PURE__ */
|
|
6008
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
6035
|
+
/* @__PURE__ */ jsx34(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
6036
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx34(
|
|
6009
6037
|
ResizeGrip,
|
|
6010
6038
|
{
|
|
6011
6039
|
panelEl: containerRef.current,
|
|
@@ -6022,7 +6050,7 @@ function MessengerHome({
|
|
|
6022
6050
|
}
|
|
6023
6051
|
|
|
6024
6052
|
// src/ui/modules-empty.tsx
|
|
6025
|
-
import { jsx as
|
|
6053
|
+
import { jsx as jsx35, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
6026
6054
|
var p31 = BRAND.cssPrefix;
|
|
6027
6055
|
function ModulesEmpty({ strings, onClose }) {
|
|
6028
6056
|
return /* @__PURE__ */ jsxs30(
|
|
@@ -6033,7 +6061,7 @@ function ModulesEmpty({ strings, onClose }) {
|
|
|
6033
6061
|
"aria-label": strings.panelTitle,
|
|
6034
6062
|
"data-testid": TID.modulesEmpty,
|
|
6035
6063
|
children: [
|
|
6036
|
-
onClose ? /* @__PURE__ */
|
|
6064
|
+
onClose ? /* @__PURE__ */ jsx35(
|
|
6037
6065
|
"button",
|
|
6038
6066
|
{
|
|
6039
6067
|
type: "button",
|
|
@@ -6041,10 +6069,10 @@ function ModulesEmpty({ strings, onClose }) {
|
|
|
6041
6069
|
onClick: onClose,
|
|
6042
6070
|
"aria-label": strings.close,
|
|
6043
6071
|
title: strings.close,
|
|
6044
|
-
children: /* @__PURE__ */
|
|
6072
|
+
children: /* @__PURE__ */ jsx35(CloseIcon, {})
|
|
6045
6073
|
}
|
|
6046
6074
|
) : null,
|
|
6047
|
-
/* @__PURE__ */
|
|
6075
|
+
/* @__PURE__ */ jsx35("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
6048
6076
|
]
|
|
6049
6077
|
}
|
|
6050
6078
|
);
|
|
@@ -6116,7 +6144,7 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
6116
6144
|
}
|
|
6117
6145
|
|
|
6118
6146
|
// src/ui/app.tsx
|
|
6119
|
-
import { jsx as
|
|
6147
|
+
import { jsx as jsx36, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
6120
6148
|
var log16 = logger.scope("app");
|
|
6121
6149
|
var p32 = BRAND.cssPrefix;
|
|
6122
6150
|
function App({ options, hostElement, bus }) {
|
|
@@ -6127,7 +6155,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6127
6155
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6128
6156
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6129
6157
|
);
|
|
6130
|
-
const
|
|
6158
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6131
6159
|
const messagesSig = useSignal2([]);
|
|
6132
6160
|
const unreadCountSig = useSignal2(0);
|
|
6133
6161
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6149,7 +6177,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6149
6177
|
const homeNav = homeNavRef.current;
|
|
6150
6178
|
const chatTabIdRef = useRef9(void 0);
|
|
6151
6179
|
chatTabIdRef.current = chatTabId();
|
|
6152
|
-
const [
|
|
6180
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6153
6181
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6154
6182
|
const initialPanelRef = useRef9(
|
|
6155
6183
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6229,7 +6257,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6229
6257
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6230
6258
|
}, [options.mode, options.size, persistence]);
|
|
6231
6259
|
useEffect17(() => {
|
|
6232
|
-
if (!
|
|
6260
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6233
6261
|
initialPanelApplied.current = true;
|
|
6234
6262
|
const state = resolveInitialPanelState(
|
|
6235
6263
|
options,
|
|
@@ -6239,12 +6267,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6239
6267
|
);
|
|
6240
6268
|
setIsOpen(state.panelOpen);
|
|
6241
6269
|
setPanelSize(state.panelSize);
|
|
6242
|
-
}, [
|
|
6270
|
+
}, [conversationReady, options, persistence]);
|
|
6243
6271
|
const homeNavSeeded = useRef9(false);
|
|
6244
6272
|
const resumeActiveRef = useRef9(false);
|
|
6245
6273
|
const resumeBubbleRef = useRef9(null);
|
|
6246
6274
|
useEffect17(() => {
|
|
6247
|
-
if (!
|
|
6275
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6248
6276
|
homeNavSeeded.current = true;
|
|
6249
6277
|
if (resumeActiveRef.current) {
|
|
6250
6278
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6252,7 +6280,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6252
6280
|
return;
|
|
6253
6281
|
}
|
|
6254
6282
|
homeNav.reset(landingTab());
|
|
6255
|
-
}, [
|
|
6283
|
+
}, [conversationReady]);
|
|
6256
6284
|
const playWelcome = useCallback6(
|
|
6257
6285
|
(welcomeMessages) => {
|
|
6258
6286
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6271,21 +6299,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6271
6299
|
[messagesSig, options.welcome]
|
|
6272
6300
|
);
|
|
6273
6301
|
const connectGenRef = useRef9(0);
|
|
6274
|
-
const
|
|
6302
|
+
const runStartConversation = useCallback6(
|
|
6275
6303
|
async ({ newConversation }) => {
|
|
6276
6304
|
const myGen = ++connectGenRef.current;
|
|
6277
6305
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6278
|
-
const persistedChatId =
|
|
6279
|
-
const
|
|
6280
|
-
if (
|
|
6281
|
-
|
|
6282
|
-
persistence.
|
|
6306
|
+
const persistedChatId = conversationIdSig.value;
|
|
6307
|
+
const conversationId = newConversation || !persistedChatId ? uuid7() : persistedChatId;
|
|
6308
|
+
if (conversationId !== persistedChatId) {
|
|
6309
|
+
conversationIdSig.value = conversationId;
|
|
6310
|
+
persistence.saveConversationId(conversationId);
|
|
6283
6311
|
}
|
|
6284
6312
|
let res;
|
|
6285
6313
|
try {
|
|
6286
|
-
res = await transport.
|
|
6314
|
+
res = await transport.startConversation({
|
|
6287
6315
|
visitorId,
|
|
6288
|
-
|
|
6316
|
+
conversationId,
|
|
6289
6317
|
userPrefs: persistence.loadUserPrefs(),
|
|
6290
6318
|
locale: options.locale
|
|
6291
6319
|
});
|
|
@@ -6293,7 +6321,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6293
6321
|
if (isStale()) return;
|
|
6294
6322
|
bus.emit("error", err);
|
|
6295
6323
|
options.onError?.(err);
|
|
6296
|
-
if (!newConversation)
|
|
6324
|
+
if (!newConversation) setConversationReady(true);
|
|
6297
6325
|
return;
|
|
6298
6326
|
}
|
|
6299
6327
|
if (isStale()) return;
|
|
@@ -6307,12 +6335,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6307
6335
|
reason: res.rebind?.visitorId
|
|
6308
6336
|
});
|
|
6309
6337
|
}
|
|
6310
|
-
if (res.
|
|
6311
|
-
log16.info("
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6338
|
+
if (res.conversationId && res.conversationId !== conversationId) {
|
|
6339
|
+
log16.info("conversation rebound", {
|
|
6340
|
+
previous: conversationId,
|
|
6341
|
+
current: res.conversationId,
|
|
6342
|
+
reason: res.rebind?.conversationId
|
|
6343
|
+
});
|
|
6344
|
+
bus.emit("conversationRebound", {
|
|
6345
|
+
previous: conversationId,
|
|
6346
|
+
current: res.conversationId,
|
|
6347
|
+
reason: res.rebind?.conversationId
|
|
6316
6348
|
});
|
|
6317
6349
|
}
|
|
6318
6350
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6329,36 +6361,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6329
6361
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6330
6362
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6331
6363
|
}
|
|
6332
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6364
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6333
6365
|
if (isResume) {
|
|
6334
6366
|
setLoadingMessages(true);
|
|
6335
6367
|
try {
|
|
6336
|
-
const chat = res.messages?.length ? {
|
|
6368
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6337
6369
|
if (isStale()) return;
|
|
6338
6370
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6339
6371
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6340
|
-
if (loaded.length || tail.length)
|
|
6341
|
-
|
|
6342
|
-
|
|
6372
|
+
if (loaded.length || tail.length) {
|
|
6373
|
+
messagesSig.value = [...loaded, ...tail];
|
|
6374
|
+
setCanSend(chat.canContinue ?? true);
|
|
6375
|
+
setSuggestions(chat.suggestions ?? []);
|
|
6376
|
+
} else {
|
|
6377
|
+
playWelcome(res.welcome?.messages);
|
|
6378
|
+
}
|
|
6343
6379
|
} catch (err) {
|
|
6344
6380
|
if (isStale()) return;
|
|
6345
|
-
log16.warn("
|
|
6346
|
-
|
|
6347
|
-
persistence.
|
|
6381
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6382
|
+
conversationIdSig.value = void 0;
|
|
6383
|
+
persistence.saveConversationId(void 0);
|
|
6348
6384
|
} finally {
|
|
6349
6385
|
if (!isStale()) setLoadingMessages(false);
|
|
6350
6386
|
}
|
|
6351
6387
|
} else {
|
|
6352
|
-
|
|
6353
|
-
persistence.
|
|
6388
|
+
conversationIdSig.value = res.conversationId;
|
|
6389
|
+
persistence.saveConversationId(res.conversationId);
|
|
6354
6390
|
playWelcome(res.welcome?.messages);
|
|
6355
6391
|
}
|
|
6356
6392
|
if (!newConversation) {
|
|
6357
|
-
bus.emit("
|
|
6358
|
-
|
|
6393
|
+
bus.emit("conversationStarted", res);
|
|
6394
|
+
setConversationReady(true);
|
|
6359
6395
|
}
|
|
6360
6396
|
},
|
|
6361
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6397
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6362
6398
|
);
|
|
6363
6399
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6364
6400
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6412,11 +6448,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6412
6448
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6413
6449
|
);
|
|
6414
6450
|
useEffect17(() => {
|
|
6415
|
-
void
|
|
6416
|
-
const
|
|
6451
|
+
void runStartConversation({ newConversation: false });
|
|
6452
|
+
const persistedConversation = conversationIdSig.value;
|
|
6417
6453
|
let resume = null;
|
|
6418
|
-
if (
|
|
6419
|
-
transport.primeIdentity(visitorId,
|
|
6454
|
+
if (persistedConversation) {
|
|
6455
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6420
6456
|
resume = transport.resumeStream();
|
|
6421
6457
|
void runResume(resume);
|
|
6422
6458
|
}
|
|
@@ -6427,10 +6463,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6427
6463
|
}, []);
|
|
6428
6464
|
const lastUserSig = useRef9(userSig);
|
|
6429
6465
|
useEffect17(() => {
|
|
6430
|
-
if (!
|
|
6466
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6431
6467
|
lastUserSig.current = userSig;
|
|
6432
|
-
void
|
|
6433
|
-
}, [userSig,
|
|
6468
|
+
void runStartConversation({ newConversation: false });
|
|
6469
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6434
6470
|
useEffect17(() => {
|
|
6435
6471
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6436
6472
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6456,14 +6492,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6456
6492
|
}, [isOpen, options.mode]);
|
|
6457
6493
|
const streamAssistant = useCallback6(
|
|
6458
6494
|
async (assistantMsg, trigger) => {
|
|
6459
|
-
const
|
|
6460
|
-
if (!
|
|
6461
|
-
|
|
6462
|
-
persistence.
|
|
6495
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6496
|
+
if (!conversationIdSig.value) {
|
|
6497
|
+
conversationIdSig.value = activeConversationId;
|
|
6498
|
+
persistence.saveConversationId(activeConversationId);
|
|
6463
6499
|
}
|
|
6464
6500
|
const body = buildSendMessageRequest({
|
|
6465
6501
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6466
|
-
|
|
6502
|
+
conversationId: activeConversationId,
|
|
6467
6503
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6468
6504
|
tools: options.features.tools,
|
|
6469
6505
|
responseMode: options.responseMode,
|
|
@@ -6499,7 +6535,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6499
6535
|
messagesSig.value = [...messagesSig.value];
|
|
6500
6536
|
}
|
|
6501
6537
|
},
|
|
6502
|
-
[transport, reducer, messagesSig,
|
|
6538
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6503
6539
|
);
|
|
6504
6540
|
const resolveTool = useCallback6(
|
|
6505
6541
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6555,32 +6591,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6555
6591
|
userContext: () => options.userContext,
|
|
6556
6592
|
messageCount: userMessageCount,
|
|
6557
6593
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6594
|
+
conversationId: () => conversationIdSig.value,
|
|
6558
6595
|
onComplete: (form, trigger, values, skipped) => {
|
|
6559
6596
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6560
6597
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6561
6598
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6562
|
-
const
|
|
6563
|
-
if (!
|
|
6564
|
-
|
|
6565
|
-
persistence.
|
|
6566
|
-
transport.primeIdentity(void 0,
|
|
6599
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6600
|
+
if (!conversationIdSig.value) {
|
|
6601
|
+
conversationIdSig.value = activeConversationId;
|
|
6602
|
+
persistence.saveConversationId(activeConversationId);
|
|
6603
|
+
transport.primeIdentity(void 0, activeConversationId);
|
|
6567
6604
|
}
|
|
6568
6605
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6569
|
-
void transport.submitForm({ formId: form.id,
|
|
6606
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6570
6607
|
}
|
|
6571
6608
|
});
|
|
6572
6609
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6573
6610
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6574
6611
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6575
6612
|
useEffect17(() => {
|
|
6576
|
-
if (
|
|
6577
|
-
}, [
|
|
6613
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6614
|
+
}, [conversationReady, forms]);
|
|
6578
6615
|
useEffect17(() => {
|
|
6579
6616
|
if (!canSend) forms.fire("conversation-closed");
|
|
6580
6617
|
}, [canSend, forms]);
|
|
6581
6618
|
useEffect17(() => {
|
|
6582
|
-
if (
|
|
6583
|
-
}, [
|
|
6619
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6620
|
+
}, [conversationReady, pageArea, forms]);
|
|
6584
6621
|
const idleMs = useMemo3(() => {
|
|
6585
6622
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6586
6623
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6640,16 +6677,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6640
6677
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6641
6678
|
const refreshUnread = useCallback6(() => {
|
|
6642
6679
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6643
|
-
transport.
|
|
6644
|
-
unreadCountSig.value = res.
|
|
6680
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6681
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6645
6682
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6646
6683
|
}, [transport, options.modules, unreadCountSig]);
|
|
6647
6684
|
const unreadSeeded = useRef9(false);
|
|
6648
6685
|
useEffect17(() => {
|
|
6649
|
-
if (!
|
|
6686
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6650
6687
|
unreadSeeded.current = true;
|
|
6651
6688
|
refreshUnread();
|
|
6652
|
-
}, [
|
|
6689
|
+
}, [conversationReady, refreshUnread]);
|
|
6653
6690
|
const handleOpen = useCallback6(() => {
|
|
6654
6691
|
log16.info("open", { mode: options.mode });
|
|
6655
6692
|
feedback.unlock();
|
|
@@ -6668,11 +6705,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6668
6705
|
if (streaming) activeCancel?.();
|
|
6669
6706
|
welcomeAbortRef.current?.abort();
|
|
6670
6707
|
messagesSig.value = [];
|
|
6671
|
-
|
|
6672
|
-
persistence.
|
|
6708
|
+
conversationIdSig.value = void 0;
|
|
6709
|
+
persistence.clearConversation();
|
|
6673
6710
|
setCanSend(true);
|
|
6674
|
-
void
|
|
6675
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6711
|
+
void runStartConversation({ newConversation: true });
|
|
6712
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6676
6713
|
const handleNewChat = useCallback6(() => {
|
|
6677
6714
|
handleClear();
|
|
6678
6715
|
setView("chat");
|
|
@@ -6696,12 +6733,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6696
6733
|
const handlePopOut = useCallback6(() => {
|
|
6697
6734
|
if (!options.popOutUrl) return;
|
|
6698
6735
|
const url = new URL(options.popOutUrl);
|
|
6699
|
-
if (
|
|
6736
|
+
if (conversationIdSig.value) url.searchParams.set("conversation", conversationIdSig.value);
|
|
6700
6737
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6701
6738
|
log16.info("popOut", { url: url.toString() });
|
|
6702
6739
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6703
6740
|
bus.emit("popOut", void 0);
|
|
6704
|
-
}, [bus,
|
|
6741
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6705
6742
|
const handleToggleHistory = useCallback6(() => {
|
|
6706
6743
|
setView((v) => {
|
|
6707
6744
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6746,28 +6783,28 @@ function App({ options, hostElement, bus }) {
|
|
|
6746
6783
|
},
|
|
6747
6784
|
[patchAndSync, bus]
|
|
6748
6785
|
);
|
|
6749
|
-
const
|
|
6750
|
-
async (
|
|
6751
|
-
log16.info("
|
|
6752
|
-
bus.emit("
|
|
6786
|
+
const handleSelectHistoryConversation = useCallback6(
|
|
6787
|
+
async (targetConversationId) => {
|
|
6788
|
+
log16.info("selectConversation", { conversationId: targetConversationId });
|
|
6789
|
+
bus.emit("selectConversation", { conversationId: targetConversationId });
|
|
6753
6790
|
try {
|
|
6754
|
-
const res = await transport.
|
|
6791
|
+
const res = await transport.loadConversation(targetConversationId);
|
|
6755
6792
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6756
6793
|
messagesSig.value = hydrated;
|
|
6757
|
-
|
|
6758
|
-
persistence.
|
|
6794
|
+
conversationIdSig.value = res.conversationId;
|
|
6795
|
+
persistence.saveConversationId(res.conversationId);
|
|
6759
6796
|
if (res.agent) setAgent(res.agent);
|
|
6760
6797
|
setCanSend(res.canContinue);
|
|
6761
6798
|
setSuggestions(res.suggestions ?? []);
|
|
6762
6799
|
setView("chat");
|
|
6763
|
-
await transport.markRead(
|
|
6800
|
+
await transport.markRead(targetConversationId);
|
|
6764
6801
|
refreshUnread();
|
|
6765
6802
|
} catch (err) {
|
|
6766
6803
|
bus.emit("error", err);
|
|
6767
6804
|
options.onError?.(err);
|
|
6768
6805
|
}
|
|
6769
6806
|
},
|
|
6770
|
-
[transport, messagesSig,
|
|
6807
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6771
6808
|
);
|
|
6772
6809
|
useEffect17(() => {
|
|
6773
6810
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6805,8 +6842,8 @@ function App({ options, hostElement, bus }) {
|
|
|
6805
6842
|
onPopOut: handlePopOut,
|
|
6806
6843
|
onSoundToggle: handleSoundToggle,
|
|
6807
6844
|
onToggleHistory: handleToggleHistory,
|
|
6808
|
-
|
|
6809
|
-
|
|
6845
|
+
onSelectHistoryConversation: handleSelectHistoryConversation,
|
|
6846
|
+
onNewConversation: handleNewChat,
|
|
6810
6847
|
onLocaleChange: handleLocaleChange,
|
|
6811
6848
|
onThemeChange: handleThemeChange,
|
|
6812
6849
|
onWidgetSizeChange: handleWidgetSizeChange,
|
|
@@ -6825,40 +6862,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6825
6862
|
onFormSkip: forms.skip,
|
|
6826
6863
|
tool: toolInteraction
|
|
6827
6864
|
};
|
|
6828
|
-
const
|
|
6829
|
-
void
|
|
6865
|
+
const onSelectConversation = (conversationId) => {
|
|
6866
|
+
void handleSelectHistoryConversation(conversationId);
|
|
6830
6867
|
const chatId = chatTabId();
|
|
6831
6868
|
if (chatId) homeNav.switchTab(chatId);
|
|
6832
6869
|
};
|
|
6833
|
-
if (!
|
|
6870
|
+
if (!conversationReady) return null;
|
|
6834
6871
|
const enabledModules = effectiveOptions.modules.list;
|
|
6835
6872
|
const renderSurface = (size) => {
|
|
6836
6873
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
6837
6874
|
if (enabledModules.length === 0) {
|
|
6838
|
-
return /* @__PURE__ */
|
|
6875
|
+
return /* @__PURE__ */ jsx36(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
6839
6876
|
}
|
|
6840
6877
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
6841
|
-
return /* @__PURE__ */
|
|
6878
|
+
return /* @__PURE__ */ jsx36(Panel, { ...panelProps, panelSize: size });
|
|
6842
6879
|
}
|
|
6843
|
-
return /* @__PURE__ */
|
|
6880
|
+
return /* @__PURE__ */ jsx36(
|
|
6844
6881
|
MessengerHome,
|
|
6845
6882
|
{
|
|
6846
6883
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
6847
6884
|
enabledModules,
|
|
6848
6885
|
nav: homeNav,
|
|
6849
6886
|
unreadCount: unreadCountSig.value,
|
|
6850
|
-
|
|
6851
|
-
|
|
6887
|
+
onSelectConversation,
|
|
6888
|
+
onStartNewConversation: handleNewChat,
|
|
6852
6889
|
onSetPanelSize: setPanelSize
|
|
6853
6890
|
}
|
|
6854
6891
|
);
|
|
6855
6892
|
};
|
|
6856
6893
|
if (options.mode === "page") {
|
|
6857
|
-
const
|
|
6858
|
-
void
|
|
6894
|
+
const onSelectConversationFromSidebar = (chat) => {
|
|
6895
|
+
void handleSelectHistoryConversation(chat.conversationId);
|
|
6859
6896
|
};
|
|
6860
|
-
const
|
|
6861
|
-
return /* @__PURE__ */
|
|
6897
|
+
const conversationsEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6898
|
+
return /* @__PURE__ */ jsx36("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx36(
|
|
6862
6899
|
PageShell,
|
|
6863
6900
|
{
|
|
6864
6901
|
site: parsedSite,
|
|
@@ -6866,9 +6903,9 @@ function App({ options, hostElement, bus }) {
|
|
|
6866
6903
|
transport,
|
|
6867
6904
|
strings: effectiveOptions.strings,
|
|
6868
6905
|
visitorId,
|
|
6869
|
-
showConversations:
|
|
6870
|
-
|
|
6871
|
-
|
|
6906
|
+
showConversations: conversationsEnabled,
|
|
6907
|
+
onSelectConversation: onSelectConversationFromSidebar,
|
|
6908
|
+
onNewConversation: handleNewChat,
|
|
6872
6909
|
sidebarCollapsed,
|
|
6873
6910
|
onToggleSidebarCollapsed: handleToggleSidebarCollapsed,
|
|
6874
6911
|
children: renderSurface("fullscreen")
|
|
@@ -6877,7 +6914,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6877
6914
|
}
|
|
6878
6915
|
if (isInlineLike) {
|
|
6879
6916
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
6880
|
-
return /* @__PURE__ */
|
|
6917
|
+
return /* @__PURE__ */ jsx36("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
6881
6918
|
}
|
|
6882
6919
|
const drawerEdgeTab = options.mode === "drawer";
|
|
6883
6920
|
const triggerOwnedByPage = options.mode === "modal";
|
|
@@ -6885,7 +6922,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6885
6922
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
6886
6923
|
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
6887
6924
|
isOpen ? renderSurface(panelSize) : null,
|
|
6888
|
-
launcherVisible ? /* @__PURE__ */
|
|
6925
|
+
launcherVisible ? /* @__PURE__ */ jsx36(
|
|
6889
6926
|
Launcher,
|
|
6890
6927
|
{
|
|
6891
6928
|
onToggle: handleOpen,
|
|
@@ -6895,7 +6932,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6895
6932
|
edgeTab: drawerEdgeTab
|
|
6896
6933
|
}
|
|
6897
6934
|
) : null,
|
|
6898
|
-
calloutToRender ? /* @__PURE__ */
|
|
6935
|
+
calloutToRender ? /* @__PURE__ */ jsx36(
|
|
6899
6936
|
LauncherCallout,
|
|
6900
6937
|
{
|
|
6901
6938
|
callout: calloutToRender,
|
|
@@ -7091,7 +7128,7 @@ var EVENT_NAMES = [
|
|
|
7091
7128
|
"send",
|
|
7092
7129
|
"stop",
|
|
7093
7130
|
"clear",
|
|
7094
|
-
"
|
|
7131
|
+
"selectConversation",
|
|
7095
7132
|
"suggestion",
|
|
7096
7133
|
"toggleHistory",
|
|
7097
7134
|
// Forms + human-in-the-loop
|
|
@@ -7112,9 +7149,9 @@ var EVENT_NAMES = [
|
|
|
7112
7149
|
"calloutDismiss",
|
|
7113
7150
|
// Lifecycle / errors
|
|
7114
7151
|
"error",
|
|
7115
|
-
"
|
|
7152
|
+
"conversationStarted",
|
|
7116
7153
|
"visitorRebound",
|
|
7117
|
-
"
|
|
7154
|
+
"conversationRebound"
|
|
7118
7155
|
];
|
|
7119
7156
|
|
|
7120
7157
|
// src/index.ts
|
|
@@ -7169,7 +7206,7 @@ function mount(opts) {
|
|
|
7169
7206
|
);
|
|
7170
7207
|
};
|
|
7171
7208
|
renderApp();
|
|
7172
|
-
bus.on("
|
|
7209
|
+
bus.on("conversationStarted", (response) => {
|
|
7173
7210
|
if (!response.config) return;
|
|
7174
7211
|
rawOptions = mergeServerConfig(rawOptions, response.config);
|
|
7175
7212
|
currentOptions = resolveOptions(rawOptions);
|
|
@@ -7198,9 +7235,9 @@ function mount(opts) {
|
|
|
7198
7235
|
log20.debug("update", { patch });
|
|
7199
7236
|
applyUpdate(patch);
|
|
7200
7237
|
},
|
|
7201
|
-
// Host-asserted context (NOT our visitor/
|
|
7238
|
+
// Host-asserted context (NOT our visitor/conversation — those are minted +
|
|
7202
7239
|
// persisted by the widget and untouched here). Merge into the current
|
|
7203
|
-
// context; App re-handshakes with the SAME visitor/
|
|
7240
|
+
// context; App re-handshakes with the SAME visitor/conversation.
|
|
7204
7241
|
setUserContext: (userContext) => {
|
|
7205
7242
|
log20.debug("setUserContext", { keys: Object.keys(userContext) });
|
|
7206
7243
|
applyUpdate({ userContext: { ...rawOptions.userContext, ...userContext } });
|