@helpai/elements 0.14.0 → 0.14.2
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 +16 -16
- package/elements-web-component.esm.js +25 -25
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +27 -27
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +27 -27
- package/elements.esm.js.map +4 -4
- package/elements.js +25 -25
- package/elements.js.map +4 -4
- package/index.d.ts +46 -45
- package/index.mjs +663 -688
- package/package.json +1 -1
- package/schema.d.ts +55 -57
- package/schema.json +17 -33
- package/schema.mjs +18 -18
- package/style.css +1 -1
- package/web-component.d.ts +1 -1
- package/web-component.mjs +661 -686
package/web-component.mjs
CHANGED
|
@@ -109,7 +109,6 @@ var STRINGS_EN = {
|
|
|
109
109
|
// ── Forms + human-in-the-loop (forms / ask-input / approval) ────
|
|
110
110
|
formSubmit: "Submit",
|
|
111
111
|
formSkip: "Skip for now",
|
|
112
|
-
formDismiss: "Dismiss",
|
|
113
112
|
formRequired: "This field is required",
|
|
114
113
|
formInvalidEmail: "Enter a valid email address",
|
|
115
114
|
formInvalidTel: "Enter a valid phone number",
|
|
@@ -215,7 +214,6 @@ var STRINGS_FR = {
|
|
|
215
214
|
// ── Forms + human-in-the-loop (forms / ask-input / approval) ────
|
|
216
215
|
formSubmit: "Envoyer",
|
|
217
216
|
formSkip: "Ignorer pour l'instant",
|
|
218
|
-
formDismiss: "Fermer",
|
|
219
217
|
formRequired: "Ce champ est obligatoire",
|
|
220
218
|
formInvalidEmail: "Saisissez une adresse e-mail valide",
|
|
221
219
|
formInvalidTel: "Saisissez un num\xE9ro de t\xE9l\xE9phone valide",
|
|
@@ -364,7 +362,15 @@ var logger = makeLogger("core");
|
|
|
364
362
|
|
|
365
363
|
// src/core/config/user-context.ts
|
|
366
364
|
var log = logger.scope("context");
|
|
367
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
365
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
366
|
+
"visitorId",
|
|
367
|
+
"conversationId",
|
|
368
|
+
"conversationId",
|
|
369
|
+
"jwt",
|
|
370
|
+
"token",
|
|
371
|
+
"authorization",
|
|
372
|
+
"password"
|
|
373
|
+
]);
|
|
368
374
|
var MAX_KEYS = 50;
|
|
369
375
|
var MAX_STRING = 1024;
|
|
370
376
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -609,7 +615,6 @@ function resolveModules(overrides) {
|
|
|
609
615
|
const byId = Object.fromEntries(list.map((m) => [m.id, m]));
|
|
610
616
|
return { list, byId };
|
|
611
617
|
}
|
|
612
|
-
var BLOCKABLE_KINDS = /* @__PURE__ */ new Set(["pre-chat", "after-messages"]);
|
|
613
618
|
function resolveForms(overrides) {
|
|
614
619
|
var _a;
|
|
615
620
|
if (!overrides?.length) return DEFAULT_FORMS;
|
|
@@ -621,7 +626,6 @@ function resolveForms(overrides) {
|
|
|
621
626
|
const triggers = (Array.isArray(def.on) ? def.on : [def.on]).map(parseTrigger).filter((t) => t !== null);
|
|
622
627
|
if (fields.length === 0 || triggers.length === 0) continue;
|
|
623
628
|
seen.add(def.id);
|
|
624
|
-
const blockable = triggers.some((t) => BLOCKABLE_KINDS.has(t.kind));
|
|
625
629
|
list.push({
|
|
626
630
|
id: def.id,
|
|
627
631
|
triggers,
|
|
@@ -631,7 +635,6 @@ function resolveForms(overrides) {
|
|
|
631
635
|
description: def.description,
|
|
632
636
|
submitLabel: def.submitLabel,
|
|
633
637
|
skippable: def.skippable ?? false,
|
|
634
|
-
blocking: (def.blocking ?? false) && blockable,
|
|
635
638
|
frequency: def.frequency ?? "once",
|
|
636
639
|
mirrorToContext: def.mirrorToContext ?? true
|
|
637
640
|
});
|
|
@@ -929,7 +932,7 @@ function parseLauncher(get, str2) {
|
|
|
929
932
|
return Object.keys(base).length > 0 ? base : null;
|
|
930
933
|
}
|
|
931
934
|
|
|
932
|
-
// src/core/start-
|
|
935
|
+
// src/core/start-conversation-shape.ts
|
|
933
936
|
function isPlainObject(raw) {
|
|
934
937
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
935
938
|
}
|
|
@@ -967,7 +970,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
967
970
|
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';
|
|
968
971
|
|
|
969
972
|
// src/styles/panel.css
|
|
970
|
-
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);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__-form-card{display:flex;flex-direction:column;gap:var(--__P__-space-2);margin:var(--__P__-space-2) 0;padding:var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated)}.__P__-form-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.__P__-form-card-title{font-size:var(--__P__-text-sm);font-weight:700;color:var(--__P__-fg)}.__P__-form-card-desc{margin:0;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';
|
|
973
|
+
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';
|
|
971
974
|
|
|
972
975
|
// src/styles/standalone.css
|
|
973
976
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1055,22 +1058,22 @@ function attachAdoptedSheet(shadow, doc) {
|
|
|
1055
1058
|
}
|
|
1056
1059
|
}
|
|
1057
1060
|
function applyThemeOverrides(host, overrides) {
|
|
1058
|
-
const
|
|
1059
|
-
if (overrides.accent) host.style.setProperty(`--${
|
|
1060
|
-
if (overrides.accentText) host.style.setProperty(`--${
|
|
1061
|
-
if (overrides.radius) host.style.setProperty(`--${
|
|
1062
|
-
if (overrides.fontFamily) host.style.setProperty(`--${
|
|
1061
|
+
const p33 = BRAND.cssPrefix;
|
|
1062
|
+
if (overrides.accent) host.style.setProperty(`--${p33}-accent`, overrides.accent);
|
|
1063
|
+
if (overrides.accentText) host.style.setProperty(`--${p33}-accent-text`, overrides.accentText);
|
|
1064
|
+
if (overrides.radius) host.style.setProperty(`--${p33}-radius`, overrides.radius);
|
|
1065
|
+
if (overrides.fontFamily) host.style.setProperty(`--${p33}-font`, overrides.fontFamily);
|
|
1063
1066
|
}
|
|
1064
1067
|
function applyThemeMode(host, mode) {
|
|
1065
1068
|
host.dataset.theme = mode;
|
|
1066
1069
|
}
|
|
1067
1070
|
function applySize(host, size) {
|
|
1068
|
-
const
|
|
1069
|
-
if (size.width !== void 0) host.style.setProperty(`--${
|
|
1070
|
-
if (size.height !== void 0) host.style.setProperty(`--${
|
|
1071
|
-
if (size.expanded?.width !== void 0) host.style.setProperty(`--${
|
|
1072
|
-
if (size.expanded?.height !== void 0) host.style.setProperty(`--${
|
|
1073
|
-
if (size.inset !== void 0) host.style.setProperty(`--${
|
|
1071
|
+
const p33 = BRAND.cssPrefix;
|
|
1072
|
+
if (size.width !== void 0) host.style.setProperty(`--${p33}-panel-w`, size.width);
|
|
1073
|
+
if (size.height !== void 0) host.style.setProperty(`--${p33}-panel-h`, size.height);
|
|
1074
|
+
if (size.expanded?.width !== void 0) host.style.setProperty(`--${p33}-expanded-w`, size.expanded.width);
|
|
1075
|
+
if (size.expanded?.height !== void 0) host.style.setProperty(`--${p33}-expanded-h`, size.expanded.height);
|
|
1076
|
+
if (size.inset !== void 0) host.style.setProperty(`--${p33}-panel-inset`, size.inset);
|
|
1074
1077
|
}
|
|
1075
1078
|
function applyPosition(host, pos) {
|
|
1076
1079
|
host.dataset.position = pos;
|
|
@@ -1241,18 +1244,18 @@ function toBase64Url(json) {
|
|
|
1241
1244
|
var nonEmpty = (ctx) => ctx && Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
1242
1245
|
function encodeContext(user, page) {
|
|
1243
1246
|
const u = nonEmpty(user);
|
|
1244
|
-
const
|
|
1245
|
-
if (!u && !
|
|
1247
|
+
const p33 = nonEmpty(page);
|
|
1248
|
+
if (!u && !p33) return void 0;
|
|
1246
1249
|
const envelope = {};
|
|
1247
1250
|
if (u) envelope.user = u;
|
|
1248
|
-
if (
|
|
1251
|
+
if (p33) envelope.page = p33;
|
|
1249
1252
|
return toBase64Url(JSON.stringify(envelope));
|
|
1250
1253
|
}
|
|
1251
1254
|
|
|
1252
1255
|
// src/stream/protocol.ts
|
|
1253
1256
|
var DEFAULT_PATHS = {
|
|
1254
|
-
/**
|
|
1255
|
-
|
|
1257
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1258
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1256
1259
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1257
1260
|
streamMessage: "/ai/agent/stream-message",
|
|
1258
1261
|
/**
|
|
@@ -1265,20 +1268,20 @@ var DEFAULT_PATHS = {
|
|
|
1265
1268
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1266
1269
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1267
1270
|
/** List the visitor's conversations. `GET`. */
|
|
1268
|
-
|
|
1269
|
-
/** Load one conversation's messages. `GET ?
|
|
1271
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1272
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1270
1273
|
listMessages: "/ai/agent/list-messages",
|
|
1271
1274
|
/**
|
|
1272
1275
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1273
1276
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1274
1277
|
* the client — a failure leaves the local cache valid; the next
|
|
1275
|
-
* `
|
|
1278
|
+
* `startConversation()` reconciles.
|
|
1276
1279
|
*/
|
|
1277
1280
|
updateSettings: "/ai/agent/update-settings",
|
|
1278
1281
|
/**
|
|
1279
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1280
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1281
|
-
* `unreadCount` (returned on `/list-
|
|
1282
|
+
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1283
|
+
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1284
|
+
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1282
1285
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1283
1286
|
*/
|
|
1284
1287
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1287,8 +1290,8 @@ var DEFAULT_PATHS = {
|
|
|
1287
1290
|
content: "/ai/agent/content",
|
|
1288
1291
|
/**
|
|
1289
1292
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1290
|
-
*
|
|
1291
|
-
* immediately, keyed by the same visitor +
|
|
1293
|
+
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1294
|
+
* immediately, keyed by the same visitor + conversation as the conversation.
|
|
1292
1295
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1293
1296
|
*/
|
|
1294
1297
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1303,7 +1306,7 @@ function buildSendMessageRequest(params) {
|
|
|
1303
1306
|
}));
|
|
1304
1307
|
const body = {
|
|
1305
1308
|
messages: wire,
|
|
1306
|
-
|
|
1309
|
+
conversationId: params.conversationId,
|
|
1307
1310
|
trigger: params.trigger ?? "submit-message"
|
|
1308
1311
|
};
|
|
1309
1312
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1315,8 +1318,8 @@ function buildSendMessageRequest(params) {
|
|
|
1315
1318
|
if (Object.keys(data).length > 0) body.data = data;
|
|
1316
1319
|
return body;
|
|
1317
1320
|
}
|
|
1318
|
-
function isResolvedToolPart(
|
|
1319
|
-
return
|
|
1321
|
+
function isResolvedToolPart(p33) {
|
|
1322
|
+
return p33.state === "output" || p33.state === "error" || p33.approval?.approved !== void 0;
|
|
1320
1323
|
}
|
|
1321
1324
|
function normalizeToolRef(ref) {
|
|
1322
1325
|
if (typeof ref === "string") return ref ? { code: ref } : null;
|
|
@@ -1324,24 +1327,24 @@ function normalizeToolRef(ref) {
|
|
|
1324
1327
|
}
|
|
1325
1328
|
function messageToWireParts(m) {
|
|
1326
1329
|
const out = [];
|
|
1327
|
-
for (const
|
|
1328
|
-
if (
|
|
1329
|
-
out.push({ text:
|
|
1330
|
+
for (const p33 of m.parts) {
|
|
1331
|
+
if (p33.kind === "text" && p33.text) {
|
|
1332
|
+
out.push({ text: p33.text, type: "text" });
|
|
1330
1333
|
}
|
|
1331
|
-
if (
|
|
1332
|
-
out.push({ mediaType:
|
|
1334
|
+
if (p33.kind === "file" && p33.url) {
|
|
1335
|
+
out.push({ mediaType: p33.mediaType, type: "file", url: p33.url });
|
|
1333
1336
|
}
|
|
1334
|
-
if (
|
|
1337
|
+
if (p33.kind === "tool" && isResolvedToolPart(p33)) {
|
|
1335
1338
|
const part = {
|
|
1336
1339
|
type: "tool",
|
|
1337
|
-
toolCallId:
|
|
1338
|
-
toolName:
|
|
1339
|
-
state:
|
|
1340
|
+
toolCallId: p33.toolCallId,
|
|
1341
|
+
toolName: p33.toolName,
|
|
1342
|
+
state: p33.state
|
|
1340
1343
|
};
|
|
1341
|
-
if (
|
|
1342
|
-
if (
|
|
1343
|
-
if (
|
|
1344
|
-
if (
|
|
1344
|
+
if (p33.input !== void 0) part.input = p33.input;
|
|
1345
|
+
if (p33.output !== void 0) part.output = p33.output;
|
|
1346
|
+
if (p33.error !== void 0) part.errorText = p33.error;
|
|
1347
|
+
if (p33.approval && p33.approval.approved !== void 0) part.approval = p33.approval;
|
|
1345
1348
|
out.push(part);
|
|
1346
1349
|
}
|
|
1347
1350
|
}
|
|
@@ -1391,11 +1394,11 @@ function sleep(ms, signal7) {
|
|
|
1391
1394
|
var AgentTransport = class {
|
|
1392
1395
|
constructor(opts) {
|
|
1393
1396
|
__publicField(this, "opts", opts);
|
|
1394
|
-
// Identity adopted from the start-
|
|
1397
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1395
1398
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1396
|
-
// (visitor,
|
|
1399
|
+
// (visitor, conversation) pair.
|
|
1397
1400
|
__publicField(this, "visitorId");
|
|
1398
|
-
__publicField(this, "
|
|
1401
|
+
__publicField(this, "conversationId");
|
|
1399
1402
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1400
1403
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1401
1404
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1413,27 +1416,27 @@ var AgentTransport = class {
|
|
|
1413
1416
|
this.pageContext = pageContext;
|
|
1414
1417
|
}
|
|
1415
1418
|
/**
|
|
1416
|
-
* Seed the visitor +
|
|
1417
|
-
* `
|
|
1418
|
-
* with `
|
|
1419
|
-
* `
|
|
1419
|
+
* Seed the visitor + conversation identity from persistence BEFORE the first
|
|
1420
|
+
* `startConversation` resolves. A mount-time `resumeStream()` runs in parallel
|
|
1421
|
+
* with `startConversation`, so without this its envelope would carry no
|
|
1422
|
+
* `conversationId` and the resume GET couldn't identify the thread. `startConversation`
|
|
1420
1423
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1421
1424
|
*/
|
|
1422
|
-
primeIdentity(visitorId,
|
|
1425
|
+
primeIdentity(visitorId, conversationId) {
|
|
1423
1426
|
if (visitorId) this.visitorId = visitorId;
|
|
1424
|
-
if (
|
|
1427
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1425
1428
|
}
|
|
1426
1429
|
/** Build the per-request envelope from the current transport state. */
|
|
1427
1430
|
envelope() {
|
|
1428
1431
|
const out = {};
|
|
1429
1432
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1430
|
-
if (this.
|
|
1433
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1431
1434
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1432
1435
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1433
1436
|
return out;
|
|
1434
1437
|
}
|
|
1435
1438
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1436
|
-
* start-
|
|
1439
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1437
1440
|
* differs from the active one. */
|
|
1438
1441
|
withEnvelope(body) {
|
|
1439
1442
|
return { ...this.envelope(), ...body };
|
|
@@ -1444,8 +1447,8 @@ var AgentTransport = class {
|
|
|
1444
1447
|
return form;
|
|
1445
1448
|
}
|
|
1446
1449
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1447
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1448
|
-
* selector on load-
|
|
1450
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1451
|
+
* selector on load-conversation). */
|
|
1449
1452
|
withEnvelopeQuery(urlOrPath) {
|
|
1450
1453
|
const url = new URL(this.url(urlOrPath));
|
|
1451
1454
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1454,23 +1457,31 @@ var AgentTransport = class {
|
|
|
1454
1457
|
return url.toString();
|
|
1455
1458
|
}
|
|
1456
1459
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1457
|
-
async
|
|
1458
|
-
log4.debug("
|
|
1459
|
-
|
|
1460
|
-
|
|
1460
|
+
async startConversation(body) {
|
|
1461
|
+
log4.debug("startConversation \u2192", {
|
|
1462
|
+
visitorId: body.visitorId,
|
|
1463
|
+
conversationId: body.conversationId,
|
|
1464
|
+
locale: body.locale
|
|
1465
|
+
});
|
|
1466
|
+
const res = await this.postJson(
|
|
1467
|
+
DEFAULT_PATHS.startConversation,
|
|
1468
|
+
body,
|
|
1469
|
+
"startConversation"
|
|
1470
|
+
);
|
|
1471
|
+
log4.debug("startConversation \u2190", {
|
|
1461
1472
|
visitorId: res.visitorId,
|
|
1462
|
-
|
|
1473
|
+
conversationId: res.conversationId,
|
|
1463
1474
|
canContinue: res.canContinue,
|
|
1464
1475
|
hasMessages: !!res.messages?.length,
|
|
1465
1476
|
hasWelcome: !!res.welcome,
|
|
1466
1477
|
hasConfig: !!res.config,
|
|
1467
1478
|
rebind: res.rebind
|
|
1468
1479
|
});
|
|
1469
|
-
if (!
|
|
1470
|
-
log4.warn("
|
|
1480
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1481
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1471
1482
|
}
|
|
1472
1483
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1473
|
-
this.
|
|
1484
|
+
this.conversationId = res.conversationId;
|
|
1474
1485
|
return res;
|
|
1475
1486
|
}
|
|
1476
1487
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1495,45 +1506,45 @@ var AgentTransport = class {
|
|
|
1495
1506
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1496
1507
|
return res;
|
|
1497
1508
|
}
|
|
1498
|
-
async
|
|
1499
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1509
|
+
async listConversations(params = {}) {
|
|
1510
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1500
1511
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1501
1512
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1502
1513
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1503
|
-
log4.debug("
|
|
1514
|
+
log4.debug("listConversations \u2192", {
|
|
1504
1515
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1505
1516
|
limit: params.limit,
|
|
1506
1517
|
cursor: params.cursor
|
|
1507
1518
|
});
|
|
1508
|
-
const res = await this.getJson(url.toString(), "
|
|
1509
|
-
const
|
|
1510
|
-
log4.debug("
|
|
1519
|
+
const res = await this.getJson(url.toString(), "listConversations");
|
|
1520
|
+
const conversations = res.conversations ?? [];
|
|
1521
|
+
log4.debug("listConversations \u2190", { count: conversations.length, nextCursor: res.nextCursor });
|
|
1511
1522
|
return {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
title:
|
|
1515
|
-
lastMessageAt:
|
|
1516
|
-
preview:
|
|
1517
|
-
canContinue:
|
|
1518
|
-
unreadCount:
|
|
1523
|
+
conversations: conversations.map((conversation) => ({
|
|
1524
|
+
conversationId: conversation.conversationId,
|
|
1525
|
+
title: conversation.title,
|
|
1526
|
+
lastMessageAt: conversation.lastMessageAt,
|
|
1527
|
+
preview: conversation.preview,
|
|
1528
|
+
canContinue: conversation.canContinue,
|
|
1529
|
+
unreadCount: conversation.unreadCount
|
|
1519
1530
|
})),
|
|
1520
1531
|
nextCursor: res.nextCursor
|
|
1521
1532
|
};
|
|
1522
1533
|
}
|
|
1523
|
-
async
|
|
1534
|
+
async loadConversation(conversationId) {
|
|
1524
1535
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1525
|
-
url.searchParams.set("
|
|
1526
|
-
log4.debug("
|
|
1527
|
-
const res = await this.getJson(url.toString(), "
|
|
1536
|
+
url.searchParams.set("conversationId", conversationId);
|
|
1537
|
+
log4.debug("loadConversation \u2192", { conversationId, visitorId: this.visitorId });
|
|
1538
|
+
const res = await this.getJson(url.toString(), "loadConversation");
|
|
1528
1539
|
const messages = res.messages ?? [];
|
|
1529
|
-
log4.debug("
|
|
1530
|
-
|
|
1540
|
+
log4.debug("loadConversation \u2190", {
|
|
1541
|
+
conversationId: res.conversationId,
|
|
1531
1542
|
canContinue: res.canContinue,
|
|
1532
1543
|
messageCount: messages.length,
|
|
1533
1544
|
hasSuggestions: !!res.suggestions
|
|
1534
1545
|
});
|
|
1535
1546
|
return {
|
|
1536
|
-
|
|
1547
|
+
conversationId: res.conversationId,
|
|
1537
1548
|
canContinue: res.canContinue ?? true,
|
|
1538
1549
|
messages,
|
|
1539
1550
|
agent: res.agent,
|
|
@@ -1542,15 +1553,15 @@ var AgentTransport = class {
|
|
|
1542
1553
|
}
|
|
1543
1554
|
/**
|
|
1544
1555
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1545
|
-
* server records `lastReadAt` and clears that
|
|
1546
|
-
* next `/
|
|
1556
|
+
* server records `lastReadAt` and clears that conversation's `unreadCount` on the
|
|
1557
|
+
* next `/conversations`. A failure is non-fatal (the badge just lingers until the
|
|
1547
1558
|
* next sync), so callers don't await this.
|
|
1548
1559
|
*/
|
|
1549
|
-
async markRead(
|
|
1550
|
-
if (!this.visitorId || !
|
|
1551
|
-
log4.debug("markRead \u2192", {
|
|
1560
|
+
async markRead(conversationId) {
|
|
1561
|
+
if (!this.visitorId || !conversationId) return;
|
|
1562
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1552
1563
|
try {
|
|
1553
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1564
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1554
1565
|
} catch (err) {
|
|
1555
1566
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1556
1567
|
}
|
|
@@ -1576,7 +1587,7 @@ var AgentTransport = class {
|
|
|
1576
1587
|
async saveUserPrefs(userPrefs) {
|
|
1577
1588
|
log4.debug("saveUserPrefs \u2192", {
|
|
1578
1589
|
visitorId: this.visitorId,
|
|
1579
|
-
|
|
1590
|
+
conversationId: this.conversationId,
|
|
1580
1591
|
settingsKeys: Object.keys(userPrefs)
|
|
1581
1592
|
});
|
|
1582
1593
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1594,7 +1605,7 @@ var AgentTransport = class {
|
|
|
1594
1605
|
}
|
|
1595
1606
|
/**
|
|
1596
1607
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1597
|
-
* record is captured even if the visitor never sends a message. `
|
|
1608
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1598
1609
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1599
1610
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1600
1611
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1609,7 +1620,7 @@ var AgentTransport = class {
|
|
|
1609
1620
|
}
|
|
1610
1621
|
sendMessage(body) {
|
|
1611
1622
|
log4.debug("message \u2192", {
|
|
1612
|
-
|
|
1623
|
+
conversationId: body.conversationId,
|
|
1613
1624
|
visitorId: body.visitorId,
|
|
1614
1625
|
messageCount: body.messages.length,
|
|
1615
1626
|
trigger: body.trigger,
|
|
@@ -1619,16 +1630,16 @@ var AgentTransport = class {
|
|
|
1619
1630
|
const ctrl = new AbortController();
|
|
1620
1631
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1621
1632
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1622
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1633
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1623
1634
|
return { iter, cancel };
|
|
1624
1635
|
}
|
|
1625
1636
|
/**
|
|
1626
1637
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1627
1638
|
*
|
|
1628
1639
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1629
|
-
* `
|
|
1640
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1630
1641
|
* the user refreshed while the assistant was still streaming, the
|
|
1631
|
-
* `
|
|
1642
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1632
1643
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1633
1644
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1634
1645
|
* (the common case — no bubble is created).
|
|
@@ -1655,7 +1666,7 @@ var AgentTransport = class {
|
|
|
1655
1666
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1656
1667
|
* off first, the reply may still be spinning up server-side);
|
|
1657
1668
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1658
|
-
* parallel with start-
|
|
1669
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1659
1670
|
* user reloaded keeps flowing).
|
|
1660
1671
|
*
|
|
1661
1672
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1664,7 +1675,7 @@ var AgentTransport = class {
|
|
|
1664
1675
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1665
1676
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1666
1677
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1667
|
-
* turn comes from the DB via start-
|
|
1678
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1668
1679
|
*
|
|
1669
1680
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1670
1681
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1730,11 +1741,11 @@ var AgentTransport = class {
|
|
|
1730
1741
|
return false;
|
|
1731
1742
|
}
|
|
1732
1743
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1733
|
-
cancelStream(ctrl,
|
|
1744
|
+
cancelStream(ctrl, conversationId) {
|
|
1734
1745
|
if (ctrl.signal.aborted) return;
|
|
1735
|
-
log4.debug("cancel stream", {
|
|
1746
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1736
1747
|
ctrl.abort();
|
|
1737
|
-
if (!this.visitorId || !
|
|
1748
|
+
if (!this.visitorId || !conversationId) return;
|
|
1738
1749
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1739
1750
|
method: "POST",
|
|
1740
1751
|
credentials: "omit",
|
|
@@ -1759,7 +1770,7 @@ var AgentTransport = class {
|
|
|
1759
1770
|
yield* parseChatStream(res, signal7);
|
|
1760
1771
|
}
|
|
1761
1772
|
/**
|
|
1762
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1773
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1763
1774
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1764
1775
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1765
1776
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1770,7 +1781,7 @@ var AgentTransport = class {
|
|
|
1770
1781
|
return url.toString();
|
|
1771
1782
|
}
|
|
1772
1783
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1773
|
-
// update-settings / mark-read / start-
|
|
1784
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1774
1785
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1775
1786
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1776
1787
|
async postJson(path, body, label) {
|
|
@@ -1854,10 +1865,10 @@ function extensionFor(mimeType) {
|
|
|
1854
1865
|
if (mimeType.includes("wav")) return "wav";
|
|
1855
1866
|
return "bin";
|
|
1856
1867
|
}
|
|
1857
|
-
function
|
|
1868
|
+
function isStartConversationResponseShape(raw) {
|
|
1858
1869
|
if (!raw || typeof raw !== "object") return false;
|
|
1859
1870
|
const r = raw;
|
|
1860
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1871
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1861
1872
|
}
|
|
1862
1873
|
|
|
1863
1874
|
// src/stream/messages.ts
|
|
@@ -1934,7 +1945,7 @@ function fromWireMessage(w) {
|
|
|
1934
1945
|
};
|
|
1935
1946
|
}
|
|
1936
1947
|
return null;
|
|
1937
|
-
}).filter((
|
|
1948
|
+
}).filter((p33) => p33 !== null);
|
|
1938
1949
|
return {
|
|
1939
1950
|
id: w.id,
|
|
1940
1951
|
role: w.role,
|
|
@@ -1964,43 +1975,43 @@ function assistantText(m) {
|
|
|
1964
1975
|
}
|
|
1965
1976
|
return out;
|
|
1966
1977
|
}
|
|
1967
|
-
function partToReactive(
|
|
1968
|
-
if (
|
|
1969
|
-
return { kind:
|
|
1978
|
+
function partToReactive(p33) {
|
|
1979
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1980
|
+
return { kind: p33.kind, id: p33.id, textSig: signal(p33.text), doneSig: signal(p33.done) };
|
|
1970
1981
|
}
|
|
1971
|
-
if (
|
|
1982
|
+
if (p33.kind === "tool") {
|
|
1972
1983
|
return {
|
|
1973
1984
|
kind: "tool",
|
|
1974
|
-
toolCallId:
|
|
1975
|
-
toolName:
|
|
1976
|
-
inputPartialSig: signal(
|
|
1977
|
-
inputSig: signal(
|
|
1978
|
-
outputSig: signal(
|
|
1979
|
-
errorSig: signal(
|
|
1980
|
-
stateSig: signal(
|
|
1981
|
-
approvalSig: signal(
|
|
1985
|
+
toolCallId: p33.toolCallId,
|
|
1986
|
+
toolName: p33.toolName,
|
|
1987
|
+
inputPartialSig: signal(p33.inputPartial),
|
|
1988
|
+
inputSig: signal(p33.input),
|
|
1989
|
+
outputSig: signal(p33.output),
|
|
1990
|
+
errorSig: signal(p33.error),
|
|
1991
|
+
stateSig: signal(p33.state),
|
|
1992
|
+
approvalSig: signal(p33.approval)
|
|
1982
1993
|
};
|
|
1983
1994
|
}
|
|
1984
|
-
return
|
|
1995
|
+
return p33;
|
|
1985
1996
|
}
|
|
1986
|
-
function partFromReactive(
|
|
1987
|
-
if (
|
|
1988
|
-
return { kind:
|
|
1997
|
+
function partFromReactive(p33) {
|
|
1998
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1999
|
+
return { kind: p33.kind, id: p33.id, text: p33.textSig.value, done: p33.doneSig.value };
|
|
1989
2000
|
}
|
|
1990
|
-
if (
|
|
2001
|
+
if (p33.kind === "tool") {
|
|
1991
2002
|
return {
|
|
1992
2003
|
kind: "tool",
|
|
1993
|
-
toolCallId:
|
|
1994
|
-
toolName:
|
|
1995
|
-
inputPartial:
|
|
1996
|
-
input:
|
|
1997
|
-
output:
|
|
1998
|
-
error:
|
|
1999
|
-
state:
|
|
2000
|
-
approval:
|
|
2004
|
+
toolCallId: p33.toolCallId,
|
|
2005
|
+
toolName: p33.toolName,
|
|
2006
|
+
inputPartial: p33.inputPartialSig.value,
|
|
2007
|
+
input: p33.inputSig.value,
|
|
2008
|
+
output: p33.outputSig.value,
|
|
2009
|
+
error: p33.errorSig.value,
|
|
2010
|
+
state: p33.stateSig.value,
|
|
2011
|
+
approval: p33.approvalSig.value
|
|
2001
2012
|
};
|
|
2002
2013
|
}
|
|
2003
|
-
return
|
|
2014
|
+
return p33;
|
|
2004
2015
|
}
|
|
2005
2016
|
|
|
2006
2017
|
// src/stream/reducer.ts
|
|
@@ -2055,8 +2066,8 @@ var StreamReducer = class {
|
|
|
2055
2066
|
ensureTextPart(m, "text", chunk.id);
|
|
2056
2067
|
return;
|
|
2057
2068
|
case "text-delta": {
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2069
|
+
const p33 = ensureTextPart(m, "text", chunk.id);
|
|
2070
|
+
p33.textSig.value += chunk.delta;
|
|
2060
2071
|
return;
|
|
2061
2072
|
}
|
|
2062
2073
|
case "text-end":
|
|
@@ -2066,8 +2077,8 @@ var StreamReducer = class {
|
|
|
2066
2077
|
ensureTextPart(m, "reasoning", chunk.id).doneSig.value = false;
|
|
2067
2078
|
return;
|
|
2068
2079
|
case "reasoning-delta": {
|
|
2069
|
-
const
|
|
2070
|
-
|
|
2080
|
+
const p33 = ensureTextPart(m, "reasoning", chunk.id);
|
|
2081
|
+
p33.textSig.value += chunk.delta;
|
|
2071
2082
|
return;
|
|
2072
2083
|
}
|
|
2073
2084
|
case "reasoning-end":
|
|
@@ -2086,7 +2097,7 @@ var StreamReducer = class {
|
|
|
2086
2097
|
return;
|
|
2087
2098
|
case "source-url": {
|
|
2088
2099
|
const parts = m.partsSig.value;
|
|
2089
|
-
if (parts.some((
|
|
2100
|
+
if (parts.some((p33) => p33.kind === "source" && p33.sourceId === chunk.sourceId)) return;
|
|
2090
2101
|
appendPart(m, { kind: "source", sourceId: chunk.sourceId, url: chunk.url, title: chunk.title });
|
|
2091
2102
|
return;
|
|
2092
2103
|
}
|
|
@@ -2110,14 +2121,14 @@ var StreamReducer = class {
|
|
|
2110
2121
|
}
|
|
2111
2122
|
};
|
|
2112
2123
|
function ensureTextPart(m, kind, id) {
|
|
2113
|
-
const existing = m.partsSig.value.find((
|
|
2124
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === kind && p33.id === id);
|
|
2114
2125
|
if (existing) return existing;
|
|
2115
2126
|
const part = { kind, id, textSig: signal2(""), doneSig: signal2(false) };
|
|
2116
2127
|
appendPart(m, part);
|
|
2117
2128
|
return part;
|
|
2118
2129
|
}
|
|
2119
2130
|
function ensureToolPart(m, toolCallId, toolName) {
|
|
2120
|
-
const existing = m.partsSig.value.find((
|
|
2131
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === "tool" && p33.toolCallId === toolCallId);
|
|
2121
2132
|
if (existing) return existing;
|
|
2122
2133
|
const part = {
|
|
2123
2134
|
kind: "tool",
|
|
@@ -2142,32 +2153,32 @@ function applyTool(m, chunk) {
|
|
|
2142
2153
|
ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2143
2154
|
return;
|
|
2144
2155
|
case "tool-input-delta": {
|
|
2145
|
-
const
|
|
2146
|
-
|
|
2156
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2157
|
+
p33.inputPartialSig.value += chunk.delta;
|
|
2147
2158
|
return;
|
|
2148
2159
|
}
|
|
2149
2160
|
case "tool-input-available": {
|
|
2150
|
-
const
|
|
2151
|
-
|
|
2152
|
-
|
|
2161
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2162
|
+
p33.inputSig.value = chunk.input;
|
|
2163
|
+
p33.stateSig.value = isAskUserInputTool(p33.toolName) ? "awaiting-input" : "awaiting";
|
|
2153
2164
|
return;
|
|
2154
2165
|
}
|
|
2155
2166
|
case "tool-approval-request": {
|
|
2156
|
-
const
|
|
2157
|
-
|
|
2158
|
-
|
|
2167
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2168
|
+
p33.approvalSig.value = { id: chunk.approvalId };
|
|
2169
|
+
p33.stateSig.value = "awaiting-approval";
|
|
2159
2170
|
return;
|
|
2160
2171
|
}
|
|
2161
2172
|
case "tool-output-available": {
|
|
2162
|
-
const
|
|
2163
|
-
|
|
2164
|
-
|
|
2173
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2174
|
+
p33.outputSig.value = chunk.output;
|
|
2175
|
+
p33.stateSig.value = "output";
|
|
2165
2176
|
return;
|
|
2166
2177
|
}
|
|
2167
2178
|
case "tool-output-error": {
|
|
2168
|
-
const
|
|
2169
|
-
|
|
2170
|
-
|
|
2179
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2180
|
+
p33.errorSig.value = chunk.errorText;
|
|
2181
|
+
p33.stateSig.value = "error";
|
|
2171
2182
|
return;
|
|
2172
2183
|
}
|
|
2173
2184
|
default:
|
|
@@ -2180,7 +2191,7 @@ var log6 = logger.scope("persistence");
|
|
|
2180
2191
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2181
2192
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2182
2193
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2183
|
-
const
|
|
2194
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2184
2195
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2185
2196
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2186
2197
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2200,13 +2211,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2200
2211
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2201
2212
|
storage.set(KEY_VISITOR, id);
|
|
2202
2213
|
},
|
|
2203
|
-
|
|
2204
|
-
return storage.get(
|
|
2214
|
+
loadConversationId() {
|
|
2215
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2205
2216
|
},
|
|
2206
|
-
|
|
2207
|
-
log6.trace("
|
|
2208
|
-
if (id) storage.set(
|
|
2209
|
-
else storage.remove(
|
|
2217
|
+
saveConversationId(id) {
|
|
2218
|
+
log6.trace("saveConversationId", { id, widgetId });
|
|
2219
|
+
if (id) storage.set(KEY_CONVERSATION, id);
|
|
2220
|
+
else storage.remove(KEY_CONVERSATION);
|
|
2210
2221
|
},
|
|
2211
2222
|
loadUserPrefs() {
|
|
2212
2223
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2290,8 +2301,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2290
2301
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2291
2302
|
}
|
|
2292
2303
|
},
|
|
2293
|
-
|
|
2294
|
-
storage.remove(
|
|
2304
|
+
clearConversation() {
|
|
2305
|
+
storage.remove(KEY_CONVERSATION);
|
|
2295
2306
|
}
|
|
2296
2307
|
};
|
|
2297
2308
|
return persistence;
|
|
@@ -2473,7 +2484,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2473
2484
|
var FeedbackBus = class {
|
|
2474
2485
|
constructor(sound, haptics) {
|
|
2475
2486
|
/**
|
|
2476
|
-
* User/
|
|
2487
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2477
2488
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2478
2489
|
* `Persistence` layer.
|
|
2479
2490
|
*/
|
|
@@ -2791,7 +2802,7 @@ var TID = {
|
|
|
2791
2802
|
historyPane: `${p2}-history-pane`,
|
|
2792
2803
|
/** History pane back / close button. */
|
|
2793
2804
|
historyBack: `${p2}-history-back`,
|
|
2794
|
-
/** Single history list row — suffix `-{
|
|
2805
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2795
2806
|
historyItem: `${p2}-history-item`,
|
|
2796
2807
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2797
2808
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
@@ -2800,7 +2811,7 @@ var TID = {
|
|
|
2800
2811
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2801
2812
|
/** Sidebar "New chat" button. */
|
|
2802
2813
|
sidebarNewChat: `${p2}-sidebar-new-chat`,
|
|
2803
|
-
/** Sidebar history row — suffix `-{
|
|
2814
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2804
2815
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2805
2816
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2806
2817
|
/** Messenger-home surface root. */
|
|
@@ -2833,16 +2844,12 @@ var TID = {
|
|
|
2833
2844
|
/** News list item — suffix `-{id}`. */
|
|
2834
2845
|
newsItem: `${p2}-news-item`,
|
|
2835
2846
|
// ── Forms + human-in-the-loop (forms / ask-input / approval) ─────
|
|
2836
|
-
/**
|
|
2847
|
+
/** Form gate root (replaces the composer, locking the chat). */
|
|
2837
2848
|
formGate: `${p2}-form-gate`,
|
|
2838
|
-
/** Inline form card root (in the transcript). */
|
|
2839
|
-
formCard: `${p2}-form-card`,
|
|
2840
2849
|
/** Form submit button. */
|
|
2841
2850
|
formSubmit: `${p2}-form-submit`,
|
|
2842
|
-
/** Form skip button (
|
|
2851
|
+
/** Form skip button (shown only when `skippable`). */
|
|
2843
2852
|
formSkip: `${p2}-form-skip`,
|
|
2844
|
-
/** Inline form-card dismiss button. */
|
|
2845
|
-
formDismiss: `${p2}-form-dismiss`,
|
|
2846
2853
|
/** A single form field control — suffix `-{name}` at the JSX site. */
|
|
2847
2854
|
formField: `${p2}-form-field`,
|
|
2848
2855
|
/** Ask-input tool root (inline form in a message bubble). */
|
|
@@ -2969,24 +2976,24 @@ import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef
|
|
|
2969
2976
|
import { useEffect as useEffect2, useRef } from "preact/hooks";
|
|
2970
2977
|
import { jsx as jsx3 } from "preact/jsx-runtime";
|
|
2971
2978
|
function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, strings }) {
|
|
2972
|
-
const
|
|
2979
|
+
const p33 = BRAND.cssPrefix;
|
|
2973
2980
|
const dragRef = useRef(null);
|
|
2974
2981
|
useEffect2(() => {
|
|
2975
2982
|
if (!panelEl) return;
|
|
2976
2983
|
const style = panelEl.style;
|
|
2977
|
-
if (resize.minWidth) style.setProperty(`--${
|
|
2978
|
-
if (resize.maxWidth) style.setProperty(`--${
|
|
2979
|
-
if (resize.minHeight) style.setProperty(`--${
|
|
2980
|
-
if (resize.maxHeight) style.setProperty(`--${
|
|
2984
|
+
if (resize.minWidth) style.setProperty(`--${p33}-resize-min-w`, resize.minWidth);
|
|
2985
|
+
if (resize.maxWidth) style.setProperty(`--${p33}-resize-max-w`, resize.maxWidth);
|
|
2986
|
+
if (resize.minHeight) style.setProperty(`--${p33}-resize-min-h`, resize.minHeight);
|
|
2987
|
+
if (resize.maxHeight) style.setProperty(`--${p33}-resize-max-h`, resize.maxHeight);
|
|
2981
2988
|
if (initialSize) {
|
|
2982
|
-
style.setProperty(`--${
|
|
2983
|
-
style.setProperty(`--${
|
|
2989
|
+
style.setProperty(`--${p33}-widget-w`, `${initialSize.width}px`);
|
|
2990
|
+
style.setProperty(`--${p33}-widget-h`, `${initialSize.height}px`);
|
|
2984
2991
|
}
|
|
2985
|
-
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight,
|
|
2992
|
+
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight, p33, initialSize]);
|
|
2986
2993
|
if (!panelEl) return null;
|
|
2987
2994
|
const isTop = position.startsWith("top-");
|
|
2988
2995
|
const isRight = position.endsWith("-right");
|
|
2989
|
-
const cornerClass = `${
|
|
2996
|
+
const cornerClass = `${p33}-resize-grip ${p33}-resize-grip--${isTop ? "bottom" : "top"}-${isRight ? "left" : "right"}`;
|
|
2990
2997
|
const onPointerDown = (e) => {
|
|
2991
2998
|
if (!panelEl) return;
|
|
2992
2999
|
const target = e.currentTarget;
|
|
@@ -3010,8 +3017,8 @@ function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, stri
|
|
|
3010
3017
|
if (!d || e.pointerId !== d.pointerId || !panelEl) return;
|
|
3011
3018
|
const dx = (e.clientX - d.startX) * d.dirX;
|
|
3012
3019
|
const dy = (e.clientY - d.startY) * d.dirY;
|
|
3013
|
-
panelEl.style.setProperty(`--${
|
|
3014
|
-
panelEl.style.setProperty(`--${
|
|
3020
|
+
panelEl.style.setProperty(`--${p33}-widget-w`, `${d.startW + dx}px`);
|
|
3021
|
+
panelEl.style.setProperty(`--${p33}-widget-h`, `${d.startH + dy}px`);
|
|
3015
3022
|
};
|
|
3016
3023
|
const onPointerUp = (e) => {
|
|
3017
3024
|
const d = dragRef.current;
|
|
@@ -3746,20 +3753,20 @@ function usePopoverMenu({ itemCount, initialFocusIndex }) {
|
|
|
3746
3753
|
// src/ui/overflow-menu.tsx
|
|
3747
3754
|
import { jsx as jsx8, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
3748
3755
|
function OverflowMenu({ items, triggerLabel }) {
|
|
3749
|
-
const
|
|
3756
|
+
const p33 = BRAND.cssPrefix;
|
|
3750
3757
|
const menu = usePopoverMenu({ itemCount: items.length });
|
|
3751
3758
|
const handleSelect = (item) => {
|
|
3752
3759
|
if (item.disabled) return;
|
|
3753
3760
|
item.onSelect();
|
|
3754
3761
|
if (!item.keepOpen) menu.close();
|
|
3755
3762
|
};
|
|
3756
|
-
return /* @__PURE__ */ jsxs6("div", { class: `${
|
|
3763
|
+
return /* @__PURE__ */ jsxs6("div", { class: `${p33}-menu-wrap`, children: [
|
|
3757
3764
|
/* @__PURE__ */ jsx8(
|
|
3758
3765
|
"button",
|
|
3759
3766
|
{
|
|
3760
3767
|
ref: menu.triggerRef,
|
|
3761
3768
|
type: "button",
|
|
3762
|
-
class: `${
|
|
3769
|
+
class: `${p33}-icon-btn`,
|
|
3763
3770
|
"aria-label": triggerLabel,
|
|
3764
3771
|
"aria-haspopup": "menu",
|
|
3765
3772
|
"aria-expanded": menu.open,
|
|
@@ -3773,7 +3780,7 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3773
3780
|
"div",
|
|
3774
3781
|
{
|
|
3775
3782
|
ref: menu.menuRef,
|
|
3776
|
-
class: `${
|
|
3783
|
+
class: `${p33}-menu`,
|
|
3777
3784
|
role: "menu",
|
|
3778
3785
|
"aria-label": triggerLabel,
|
|
3779
3786
|
onKeyDown: menu.onMenuKey,
|
|
@@ -3783,15 +3790,15 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3783
3790
|
{
|
|
3784
3791
|
type: "button",
|
|
3785
3792
|
role: "menuitem",
|
|
3786
|
-
class: `${
|
|
3793
|
+
class: `${p33}-menu-item`,
|
|
3787
3794
|
"aria-pressed": item.type === "switch" ? item.on : void 0,
|
|
3788
3795
|
disabled: item.disabled,
|
|
3789
3796
|
lang: item.lang,
|
|
3790
3797
|
onClick: () => handleSelect(item),
|
|
3791
3798
|
children: [
|
|
3792
|
-
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3793
|
-
/* @__PURE__ */ jsx8("span", { class: `${
|
|
3794
|
-
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3799
|
+
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-icon`, children: item.icon }) : null,
|
|
3800
|
+
/* @__PURE__ */ jsx8("span", { class: `${p33}-menu-label`, children: item.label }),
|
|
3801
|
+
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-check`, "aria-hidden": "true", children: /* @__PURE__ */ jsx8(CheckIcon, {}) }) : null
|
|
3795
3802
|
]
|
|
3796
3803
|
},
|
|
3797
3804
|
item.id
|
|
@@ -4269,40 +4276,6 @@ function FormGate({ form, strings, onSubmit, onSkip }) {
|
|
|
4269
4276
|
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as useState6 } from "preact/hooks";
|
|
4270
4277
|
import { useComputed as useComputed5 } from "@preact/signals";
|
|
4271
4278
|
|
|
4272
|
-
// src/ui/form/form-card.tsx
|
|
4273
|
-
import { jsx as jsx12, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4274
|
-
var p12 = BRAND.cssPrefix;
|
|
4275
|
-
function FormCard({ form, strings, onSubmit, onSkip }) {
|
|
4276
|
-
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-form-card`, "data-testid": TID.formCard, children: [
|
|
4277
|
-
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-card-head`, children: [
|
|
4278
|
-
form.title ? /* @__PURE__ */ jsx12("strong", { class: `${p12}-form-card-title`, children: form.title }) : /* @__PURE__ */ jsx12("span", {}),
|
|
4279
|
-
/* @__PURE__ */ jsx12(
|
|
4280
|
-
"button",
|
|
4281
|
-
{
|
|
4282
|
-
type: "button",
|
|
4283
|
-
class: `${p12}-icon-btn`,
|
|
4284
|
-
onClick: onSkip,
|
|
4285
|
-
"aria-label": strings.formDismiss,
|
|
4286
|
-
title: strings.formDismiss,
|
|
4287
|
-
"data-testid": TID.formDismiss,
|
|
4288
|
-
children: /* @__PURE__ */ jsx12(CloseIcon, {})
|
|
4289
|
-
}
|
|
4290
|
-
)
|
|
4291
|
-
] }),
|
|
4292
|
-
form.description ? /* @__PURE__ */ jsx12("p", { class: `${p12}-form-card-desc`, children: form.description }) : null,
|
|
4293
|
-
/* @__PURE__ */ jsx12(
|
|
4294
|
-
DynamicForm,
|
|
4295
|
-
{
|
|
4296
|
-
fields: form.fields,
|
|
4297
|
-
strings,
|
|
4298
|
-
submitLabel: form.submitLabel ?? strings.formSubmit,
|
|
4299
|
-
onSubmit,
|
|
4300
|
-
submitTestId: TID.formSubmit
|
|
4301
|
-
}
|
|
4302
|
-
)
|
|
4303
|
-
] });
|
|
4304
|
-
}
|
|
4305
|
-
|
|
4306
4279
|
// src/ui/message-bubble.tsx
|
|
4307
4280
|
import { useComputed as useComputed4 } from "@preact/signals";
|
|
4308
4281
|
|
|
@@ -4310,7 +4283,7 @@ import { useComputed as useComputed4 } from "@preact/signals";
|
|
|
4310
4283
|
import { useEffect as useEffect7, useMemo, useRef as useRef4 } from "preact/hooks";
|
|
4311
4284
|
import { effect, signal as signal4 } from "@preact/signals";
|
|
4312
4285
|
import * as smd from "streaming-markdown";
|
|
4313
|
-
import { jsx as
|
|
4286
|
+
import { jsx as jsx12 } from "preact/jsx-runtime";
|
|
4314
4287
|
function MarkdownView({ textSig, doneSig }) {
|
|
4315
4288
|
const ref = useRef4(null);
|
|
4316
4289
|
useEffect7(() => {
|
|
@@ -4360,12 +4333,12 @@ function MarkdownView({ textSig, doneSig }) {
|
|
|
4360
4333
|
el.removeEventListener("click", onClick);
|
|
4361
4334
|
};
|
|
4362
4335
|
}, [textSig, doneSig]);
|
|
4363
|
-
return /* @__PURE__ */
|
|
4336
|
+
return /* @__PURE__ */ jsx12("div", { ref });
|
|
4364
4337
|
}
|
|
4365
4338
|
function StaticMarkdown({ text }) {
|
|
4366
4339
|
const textSig = useMemo(() => signal4(text), [text]);
|
|
4367
4340
|
const doneSig = useMemo(() => signal4(true), []);
|
|
4368
|
-
return /* @__PURE__ */
|
|
4341
|
+
return /* @__PURE__ */ jsx12(MarkdownView, { textSig, doneSig });
|
|
4369
4342
|
}
|
|
4370
4343
|
function hardenLink(a) {
|
|
4371
4344
|
const href = a.getAttribute("href") ?? "";
|
|
@@ -4379,8 +4352,8 @@ function hardenLink(a) {
|
|
|
4379
4352
|
|
|
4380
4353
|
// src/ui/tool-approval.tsx
|
|
4381
4354
|
import { useComputed as useComputed2, useSignal } from "@preact/signals";
|
|
4382
|
-
import { Fragment, jsx as
|
|
4383
|
-
var
|
|
4355
|
+
import { Fragment, jsx as jsx13, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4356
|
+
var p12 = BRAND.cssPrefix;
|
|
4384
4357
|
function ToolApproval({ part, strings, active, onDecision }) {
|
|
4385
4358
|
const approval = useComputed2(() => part.approvalSig.value);
|
|
4386
4359
|
const input = useComputed2(() => part.inputSig.value);
|
|
@@ -4388,24 +4361,24 @@ function ToolApproval({ part, strings, active, onDecision }) {
|
|
|
4388
4361
|
const decided = approval.value?.approved !== void 0;
|
|
4389
4362
|
if (decided) {
|
|
4390
4363
|
const ap = approval.value;
|
|
4391
|
-
return /* @__PURE__ */
|
|
4392
|
-
/* @__PURE__ */
|
|
4393
|
-
/* @__PURE__ */
|
|
4394
|
-
ap?.reason ? /* @__PURE__ */
|
|
4364
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval ${p12}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4365
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-label`, "data-approved": ap?.approved ? "true" : "false", children: ap?.approved ? strings.approved : strings.rejected }),
|
|
4366
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName }),
|
|
4367
|
+
ap?.reason ? /* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-value`, children: ap.reason }) : null
|
|
4395
4368
|
] });
|
|
4396
4369
|
}
|
|
4397
4370
|
const args = summarizeInput(input.value);
|
|
4398
|
-
return /* @__PURE__ */
|
|
4399
|
-
/* @__PURE__ */
|
|
4400
|
-
/* @__PURE__ */
|
|
4401
|
-
/* @__PURE__ */
|
|
4371
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval`, "data-testid": TID.toolApproval, children: [
|
|
4372
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-head`, children: [
|
|
4373
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-badge`, children: strings.approvalRequired }),
|
|
4374
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName })
|
|
4402
4375
|
] }),
|
|
4403
|
-
args ? /* @__PURE__ */
|
|
4404
|
-
active ? /* @__PURE__ */
|
|
4405
|
-
/* @__PURE__ */
|
|
4376
|
+
args ? /* @__PURE__ */ jsx13("pre", { class: `${p12}-tool-args`, children: args }) : null,
|
|
4377
|
+
active ? /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
4378
|
+
/* @__PURE__ */ jsx13(
|
|
4406
4379
|
"input",
|
|
4407
4380
|
{
|
|
4408
|
-
class: `${
|
|
4381
|
+
class: `${p12}-field-input`,
|
|
4409
4382
|
value: reason.value,
|
|
4410
4383
|
placeholder: strings.approvalReason,
|
|
4411
4384
|
onInput: (e) => {
|
|
@@ -4413,29 +4386,29 @@ function ToolApproval({ part, strings, active, onDecision }) {
|
|
|
4413
4386
|
}
|
|
4414
4387
|
}
|
|
4415
4388
|
),
|
|
4416
|
-
/* @__PURE__ */
|
|
4417
|
-
/* @__PURE__ */
|
|
4389
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-actions`, children: [
|
|
4390
|
+
/* @__PURE__ */ jsx13(
|
|
4418
4391
|
"button",
|
|
4419
4392
|
{
|
|
4420
4393
|
type: "button",
|
|
4421
|
-
class: `${
|
|
4394
|
+
class: `${p12}-tool-reject`,
|
|
4422
4395
|
onClick: () => onDecision(part.toolCallId, false, reason.value.trim() || void 0),
|
|
4423
4396
|
"data-testid": TID.toolReject,
|
|
4424
4397
|
children: strings.reject
|
|
4425
4398
|
}
|
|
4426
4399
|
),
|
|
4427
|
-
/* @__PURE__ */
|
|
4400
|
+
/* @__PURE__ */ jsx13(
|
|
4428
4401
|
"button",
|
|
4429
4402
|
{
|
|
4430
4403
|
type: "button",
|
|
4431
|
-
class: `${
|
|
4404
|
+
class: `${p12}-tool-approve`,
|
|
4432
4405
|
onClick: () => onDecision(part.toolCallId, true, reason.value.trim() || void 0),
|
|
4433
4406
|
"data-testid": TID.toolApprove,
|
|
4434
4407
|
children: strings.approve
|
|
4435
4408
|
}
|
|
4436
4409
|
)
|
|
4437
4410
|
] })
|
|
4438
|
-
] }) : /* @__PURE__ */
|
|
4411
|
+
] }) : /* @__PURE__ */ jsx13("p", { class: `${p12}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4439
4412
|
] });
|
|
4440
4413
|
}
|
|
4441
4414
|
function summarizeInput(input) {
|
|
@@ -4506,49 +4479,49 @@ function num(v) {
|
|
|
4506
4479
|
}
|
|
4507
4480
|
|
|
4508
4481
|
// src/ui/tool-ask-input.tsx
|
|
4509
|
-
import { jsx as
|
|
4510
|
-
var
|
|
4482
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
4483
|
+
var p13 = BRAND.cssPrefix;
|
|
4511
4484
|
function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
4512
4485
|
const state = useComputed3(() => part.stateSig.value);
|
|
4513
4486
|
const request = useComputed3(() => parseAskUserInput(part.inputSig.value));
|
|
4514
4487
|
const decided = state.value === "output" || state.value === "error";
|
|
4515
4488
|
if (decided) {
|
|
4516
|
-
return /* @__PURE__ */
|
|
4489
|
+
return /* @__PURE__ */ jsx14(DecidedSummary, { part, strings });
|
|
4517
4490
|
}
|
|
4518
4491
|
if (!active) {
|
|
4519
|
-
return /* @__PURE__ */
|
|
4520
|
-
/* @__PURE__ */
|
|
4521
|
-
/* @__PURE__ */
|
|
4492
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-stale`, "data-testid": TID.toolAskInput, children: [
|
|
4493
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: request.value.title ?? request.value.question }),
|
|
4494
|
+
/* @__PURE__ */ jsx14("p", { class: `${p13}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4522
4495
|
] });
|
|
4523
4496
|
}
|
|
4524
4497
|
const req = request.value;
|
|
4525
4498
|
const isConfirmation = req.responseType === "confirmation";
|
|
4526
|
-
return /* @__PURE__ */
|
|
4527
|
-
/* @__PURE__ */
|
|
4528
|
-
req.description ? /* @__PURE__ */
|
|
4529
|
-
isConfirmation ? /* @__PURE__ */
|
|
4530
|
-
isConfirmation ? /* @__PURE__ */
|
|
4531
|
-
/* @__PURE__ */
|
|
4499
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input`, "data-testid": TID.toolAskInput, children: [
|
|
4500
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: req.title }),
|
|
4501
|
+
req.description ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-desc`, children: req.description }) : null,
|
|
4502
|
+
isConfirmation ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-question`, children: req.question }) : null,
|
|
4503
|
+
isConfirmation ? /* @__PURE__ */ jsxs11("div", { class: `${p13}-form-actions`, children: [
|
|
4504
|
+
/* @__PURE__ */ jsx14(
|
|
4532
4505
|
"button",
|
|
4533
4506
|
{
|
|
4534
4507
|
type: "button",
|
|
4535
|
-
class: `${
|
|
4508
|
+
class: `${p13}-form-skip`,
|
|
4536
4509
|
onClick: () => onSubmit(part.toolCallId, { confirmed: false }),
|
|
4537
4510
|
"data-testid": TID.toolInputSkip,
|
|
4538
4511
|
children: strings.reject
|
|
4539
4512
|
}
|
|
4540
4513
|
),
|
|
4541
|
-
/* @__PURE__ */
|
|
4514
|
+
/* @__PURE__ */ jsx14(
|
|
4542
4515
|
"button",
|
|
4543
4516
|
{
|
|
4544
4517
|
type: "button",
|
|
4545
|
-
class: `${
|
|
4518
|
+
class: `${p13}-form-submit`,
|
|
4546
4519
|
onClick: () => onSubmit(part.toolCallId, { confirmed: true }),
|
|
4547
4520
|
"data-testid": TID.toolInputSubmit,
|
|
4548
4521
|
children: strings.approve
|
|
4549
4522
|
}
|
|
4550
4523
|
)
|
|
4551
|
-
] }) : /* @__PURE__ */
|
|
4524
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
4552
4525
|
DynamicForm,
|
|
4553
4526
|
{
|
|
4554
4527
|
fields: askInputToFields(req),
|
|
@@ -4564,17 +4537,17 @@ function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
|
4564
4537
|
] });
|
|
4565
4538
|
}
|
|
4566
4539
|
function Header({ strings, title }) {
|
|
4567
|
-
return /* @__PURE__ */
|
|
4568
|
-
/* @__PURE__ */
|
|
4569
|
-
title ? /* @__PURE__ */
|
|
4540
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-head`, children: [
|
|
4541
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-badge`, children: strings.inputRequired }),
|
|
4542
|
+
title ? /* @__PURE__ */ jsx14("strong", { class: `${p13}-tool-title`, children: title }) : null
|
|
4570
4543
|
] });
|
|
4571
4544
|
}
|
|
4572
4545
|
function DecidedSummary({ part, strings }) {
|
|
4573
4546
|
const output = useComputed3(() => part.outputSig.value);
|
|
4574
4547
|
const text = summarizeOutput(output.value) || strings.inputSubmitted;
|
|
4575
|
-
return /* @__PURE__ */
|
|
4576
|
-
/* @__PURE__ */
|
|
4577
|
-
/* @__PURE__ */
|
|
4548
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4549
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-label`, children: strings.inputSubmitted }),
|
|
4550
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-value`, children: text })
|
|
4578
4551
|
] });
|
|
4579
4552
|
}
|
|
4580
4553
|
function summarizeOutput(output) {
|
|
@@ -4589,21 +4562,21 @@ function summarizeOutput(output) {
|
|
|
4589
4562
|
}
|
|
4590
4563
|
|
|
4591
4564
|
// src/ui/tool-chip.tsx
|
|
4592
|
-
import { jsx as
|
|
4565
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
4593
4566
|
function ToolChip({ part, strings }) {
|
|
4594
|
-
const
|
|
4595
|
-
return /* @__PURE__ */
|
|
4596
|
-
/* @__PURE__ */
|
|
4567
|
+
const p33 = BRAND.cssPrefix;
|
|
4568
|
+
return /* @__PURE__ */ jsxs12("span", { class: `${p33}-tool-chip`, role: "status", children: [
|
|
4569
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
4597
4570
|
strings.usedTool,
|
|
4598
4571
|
":"
|
|
4599
4572
|
] }),
|
|
4600
|
-
/* @__PURE__ */
|
|
4573
|
+
/* @__PURE__ */ jsx15("strong", { children: part.toolName })
|
|
4601
4574
|
] });
|
|
4602
4575
|
}
|
|
4603
4576
|
|
|
4604
4577
|
// src/ui/message-bubble.tsx
|
|
4605
|
-
import { jsx as
|
|
4606
|
-
var
|
|
4578
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
|
|
4579
|
+
var p14 = BRAND.cssPrefix;
|
|
4607
4580
|
function MessageBubble({
|
|
4608
4581
|
message,
|
|
4609
4582
|
strings,
|
|
@@ -4626,9 +4599,9 @@ function MessageBubble({
|
|
|
4626
4599
|
const working = streaming && !hasAnswerText.value;
|
|
4627
4600
|
const showStreamDots = streaming && !bufferedHold && !(reasoningVisible.value && working);
|
|
4628
4601
|
const stamp = formatStamp(message.createdAt);
|
|
4629
|
-
return /* @__PURE__ */
|
|
4630
|
-
/* @__PURE__ */
|
|
4631
|
-
bufferedHold ? /* @__PURE__ */
|
|
4602
|
+
return /* @__PURE__ */ jsx16("div", { class: `${p14}-bubble-row`, "data-role": message.role, "data-testid": tid(TID.messageBubble, message.id), children: /* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble-col`, children: [
|
|
4603
|
+
/* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble`, children: [
|
|
4604
|
+
bufferedHold ? /* @__PURE__ */ jsx16(LoadingSpinner, { label: strings.loading }) : partList.map((part) => /* @__PURE__ */ jsx16(
|
|
4632
4605
|
PartView,
|
|
4633
4606
|
{
|
|
4634
4607
|
part,
|
|
@@ -4641,10 +4614,10 @@ function MessageBubble({
|
|
|
4641
4614
|
},
|
|
4642
4615
|
partKey(part)
|
|
4643
4616
|
)),
|
|
4644
|
-
showStreamDots && /* @__PURE__ */
|
|
4645
|
-
message.status === "error" && message.errorText ? /* @__PURE__ */
|
|
4617
|
+
showStreamDots && /* @__PURE__ */ jsx16(TypingDots, {}),
|
|
4618
|
+
message.status === "error" && message.errorText ? /* @__PURE__ */ jsx16("div", { class: `${p14}-error`, role: "alert", children: /* @__PURE__ */ jsx16("span", { children: message.errorText }) }) : null
|
|
4646
4619
|
] }),
|
|
4647
|
-
stamp ? /* @__PURE__ */
|
|
4620
|
+
stamp ? /* @__PURE__ */ jsx16("time", { class: `${p14}-bubble-time`, dateTime: stamp.iso, title: stamp.full, children: stamp.short }) : null
|
|
4648
4621
|
] }) });
|
|
4649
4622
|
}
|
|
4650
4623
|
function formatStamp(createdAt) {
|
|
@@ -4671,11 +4644,11 @@ function PartView({
|
|
|
4671
4644
|
}) {
|
|
4672
4645
|
switch (part.kind) {
|
|
4673
4646
|
case "text":
|
|
4674
|
-
return /* @__PURE__ */
|
|
4647
|
+
return /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig });
|
|
4675
4648
|
case "reasoning":
|
|
4676
|
-
return showReasoning ? /* @__PURE__ */
|
|
4649
|
+
return showReasoning ? /* @__PURE__ */ jsx16(ReasoningView, { part, active, strings }) : null;
|
|
4677
4650
|
case "tool":
|
|
4678
|
-
return /* @__PURE__ */
|
|
4651
|
+
return /* @__PURE__ */ jsx16(
|
|
4679
4652
|
ToolPartView,
|
|
4680
4653
|
{
|
|
4681
4654
|
part,
|
|
@@ -4687,9 +4660,9 @@ function PartView({
|
|
|
4687
4660
|
);
|
|
4688
4661
|
case "file":
|
|
4689
4662
|
if (part.mediaType.startsWith("image/")) {
|
|
4690
|
-
return /* @__PURE__ */
|
|
4663
|
+
return /* @__PURE__ */ jsx16("img", { src: part.url, alt: "", loading: "lazy" });
|
|
4691
4664
|
}
|
|
4692
|
-
return /* @__PURE__ */
|
|
4665
|
+
return /* @__PURE__ */ jsx16("a", { href: part.url, target: "_blank", rel: "noreferrer noopener", children: part.url });
|
|
4693
4666
|
case "source":
|
|
4694
4667
|
return null;
|
|
4695
4668
|
}
|
|
@@ -4705,22 +4678,22 @@ function ToolPartView({
|
|
|
4705
4678
|
const hasApproval = useComputed4(() => part.approvalSig.value !== void 0);
|
|
4706
4679
|
if (tool?.humanInLoop) {
|
|
4707
4680
|
if (hasApproval.value || state.value === "awaiting-approval") {
|
|
4708
|
-
return /* @__PURE__ */
|
|
4681
|
+
return /* @__PURE__ */ jsx16(ToolApproval, { part, strings, active: interactive, onDecision: tool.onDecision });
|
|
4709
4682
|
}
|
|
4710
4683
|
if (isAskUserInputTool(part.toolName) || state.value === "awaiting-input") {
|
|
4711
|
-
return /* @__PURE__ */
|
|
4684
|
+
return /* @__PURE__ */ jsx16(ToolAskInput, { part, strings, active: interactive, onSubmit: tool.onResult });
|
|
4712
4685
|
}
|
|
4713
4686
|
}
|
|
4714
|
-
return showToolCalls ? /* @__PURE__ */
|
|
4687
|
+
return showToolCalls ? /* @__PURE__ */ jsx16(ToolChip, { part, strings }) : null;
|
|
4715
4688
|
}
|
|
4716
4689
|
function ReasoningView({
|
|
4717
4690
|
part,
|
|
4718
4691
|
active,
|
|
4719
4692
|
strings
|
|
4720
4693
|
}) {
|
|
4721
|
-
return /* @__PURE__ */
|
|
4722
|
-
/* @__PURE__ */
|
|
4723
|
-
/* @__PURE__ */
|
|
4694
|
+
return /* @__PURE__ */ jsxs13("details", { class: `${p14}-reasoning`, open: active, "data-active": active ? "true" : void 0, children: [
|
|
4695
|
+
/* @__PURE__ */ jsx16("summary", { class: `${p14}-reasoning-summary`, children: /* @__PURE__ */ jsx16("span", { class: `${p14}-reasoning-label`, children: active ? strings.thinking : strings.thoughts }) }),
|
|
4696
|
+
/* @__PURE__ */ jsx16("div", { class: `${p14}-reasoning-body`, children: /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig }) })
|
|
4724
4697
|
] });
|
|
4725
4698
|
}
|
|
4726
4699
|
function partKey(part) {
|
|
@@ -4737,22 +4710,22 @@ function partKey(part) {
|
|
|
4737
4710
|
}
|
|
4738
4711
|
}
|
|
4739
4712
|
function TypingDots() {
|
|
4740
|
-
return /* @__PURE__ */
|
|
4741
|
-
/* @__PURE__ */
|
|
4742
|
-
/* @__PURE__ */
|
|
4743
|
-
/* @__PURE__ */
|
|
4713
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-typing`, "aria-hidden": "true", children: [
|
|
4714
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4715
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4716
|
+
/* @__PURE__ */ jsx16("span", {})
|
|
4744
4717
|
] });
|
|
4745
4718
|
}
|
|
4746
4719
|
function LoadingSpinner({ label }) {
|
|
4747
|
-
return /* @__PURE__ */
|
|
4748
|
-
/* @__PURE__ */
|
|
4749
|
-
/* @__PURE__ */
|
|
4720
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-loading`, role: "status", children: [
|
|
4721
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-spinner`, "aria-hidden": "true" }),
|
|
4722
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-label`, children: label })
|
|
4750
4723
|
] });
|
|
4751
4724
|
}
|
|
4752
4725
|
|
|
4753
4726
|
// src/ui/message-list.tsx
|
|
4754
|
-
import { jsx as
|
|
4755
|
-
var
|
|
4727
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
4728
|
+
var p15 = BRAND.cssPrefix;
|
|
4756
4729
|
var STICK_THRESHOLD = 120;
|
|
4757
4730
|
var DIVIDER_IDLE_MS = 1200;
|
|
4758
4731
|
function MessageList({
|
|
@@ -4763,10 +4736,7 @@ function MessageList({
|
|
|
4763
4736
|
showToolCalls,
|
|
4764
4737
|
loading,
|
|
4765
4738
|
idle,
|
|
4766
|
-
tool
|
|
4767
|
-
inlineForm,
|
|
4768
|
-
onFormSubmit,
|
|
4769
|
-
onFormSkip
|
|
4739
|
+
tool
|
|
4770
4740
|
}) {
|
|
4771
4741
|
const ref = useRef5(null);
|
|
4772
4742
|
const messages = useComputed5(() => messagesSig.value);
|
|
@@ -4851,12 +4821,12 @@ function MessageList({
|
|
|
4851
4821
|
const day = dayKey(m.createdAt);
|
|
4852
4822
|
if (day && day !== prevDay) {
|
|
4853
4823
|
rows.push(
|
|
4854
|
-
/* @__PURE__ */
|
|
4824
|
+
/* @__PURE__ */ jsx17("div", { class: `${p15}-date-divider`, children: /* @__PURE__ */ jsx17("span", { class: `${p15}-date-pill`, title: fullDate(m.createdAt), children: dayLabel(m.createdAt, strings) }) }, `day:${day}`)
|
|
4855
4825
|
);
|
|
4856
4826
|
prevDay = day;
|
|
4857
4827
|
}
|
|
4858
4828
|
rows.push(
|
|
4859
|
-
/* @__PURE__ */
|
|
4829
|
+
/* @__PURE__ */ jsx17(
|
|
4860
4830
|
MessageBubble,
|
|
4861
4831
|
{
|
|
4862
4832
|
message: m,
|
|
@@ -4871,33 +4841,32 @@ function MessageList({
|
|
|
4871
4841
|
)
|
|
4872
4842
|
);
|
|
4873
4843
|
}
|
|
4874
|
-
return /* @__PURE__ */
|
|
4875
|
-
/* @__PURE__ */
|
|
4844
|
+
return /* @__PURE__ */ jsxs14("div", { class: `${p15}-list-wrap`, children: [
|
|
4845
|
+
/* @__PURE__ */ jsxs14(
|
|
4876
4846
|
"div",
|
|
4877
4847
|
{
|
|
4878
4848
|
ref,
|
|
4879
|
-
class: `${
|
|
4849
|
+
class: `${p15}-list`,
|
|
4880
4850
|
role: "log",
|
|
4881
4851
|
"aria-live": "polite",
|
|
4882
4852
|
"aria-relevant": "additions text",
|
|
4883
4853
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
4884
4854
|
children: [
|
|
4885
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */
|
|
4886
|
-
rows
|
|
4887
|
-
inlineForm && onFormSubmit && onFormSkip ? /* @__PURE__ */ jsx18(FormCard, { form: inlineForm, strings, onSubmit: onFormSubmit, onSkip: onFormSkip }) : null
|
|
4855
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.messagesLoading }) : null,
|
|
4856
|
+
rows
|
|
4888
4857
|
]
|
|
4889
4858
|
}
|
|
4890
4859
|
),
|
|
4891
|
-
showJump ? /* @__PURE__ */
|
|
4860
|
+
showJump ? /* @__PURE__ */ jsx17(
|
|
4892
4861
|
"button",
|
|
4893
4862
|
{
|
|
4894
4863
|
type: "button",
|
|
4895
|
-
class: `${
|
|
4864
|
+
class: `${p15}-jump`,
|
|
4896
4865
|
onClick: jumpToBottom,
|
|
4897
4866
|
"aria-label": strings.scrollToBottom,
|
|
4898
4867
|
title: strings.scrollToBottom,
|
|
4899
4868
|
"data-testid": TID.scrollToBottom,
|
|
4900
|
-
children: /* @__PURE__ */
|
|
4869
|
+
children: /* @__PURE__ */ jsx17(ChevronDownIcon, {})
|
|
4901
4870
|
}
|
|
4902
4871
|
) : null
|
|
4903
4872
|
] });
|
|
@@ -4939,15 +4908,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4939
4908
|
if (diffDays < 7) return "lastWeek";
|
|
4940
4909
|
return "older";
|
|
4941
4910
|
}
|
|
4942
|
-
function groupByBucket(nowMs,
|
|
4911
|
+
function groupByBucket(nowMs, conversations) {
|
|
4943
4912
|
const buckets = /* @__PURE__ */ new Map();
|
|
4944
|
-
for (const chat of
|
|
4913
|
+
for (const chat of conversations) {
|
|
4945
4914
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4946
4915
|
const list = buckets.get(b);
|
|
4947
4916
|
if (list) list.push(chat);
|
|
4948
4917
|
else buckets.set(b, [chat]);
|
|
4949
4918
|
}
|
|
4950
|
-
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b,
|
|
4919
|
+
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b, conversations: buckets.get(b) }));
|
|
4951
4920
|
}
|
|
4952
4921
|
function startOfDay(ms) {
|
|
4953
4922
|
const d = new Date(ms);
|
|
@@ -4956,7 +4925,7 @@ function startOfDay(ms) {
|
|
|
4956
4925
|
}
|
|
4957
4926
|
|
|
4958
4927
|
// src/ui/conversation-list.tsx
|
|
4959
|
-
import { Fragment as Fragment2, jsx as
|
|
4928
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
4960
4929
|
var log11 = logger.scope("history");
|
|
4961
4930
|
var BUCKET_TO_STRING = {
|
|
4962
4931
|
today: "dateToday",
|
|
@@ -4965,59 +4934,59 @@ var BUCKET_TO_STRING = {
|
|
|
4965
4934
|
older: "dateOlder"
|
|
4966
4935
|
};
|
|
4967
4936
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
4968
|
-
const
|
|
4937
|
+
const p33 = BRAND.cssPrefix;
|
|
4969
4938
|
const [state, setState] = useState7("loading");
|
|
4970
|
-
const [
|
|
4939
|
+
const [conversations, setChats] = useState7([]);
|
|
4971
4940
|
useEffect9(() => {
|
|
4972
4941
|
let cancelled = false;
|
|
4973
|
-
transport.
|
|
4942
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4974
4943
|
if (cancelled) return;
|
|
4975
|
-
setChats(res.
|
|
4944
|
+
setChats(res.conversations ?? []);
|
|
4976
4945
|
setState("loaded");
|
|
4977
4946
|
}).catch((err) => {
|
|
4978
4947
|
if (cancelled) return;
|
|
4979
|
-
log11.warn("
|
|
4948
|
+
log11.warn("listConversations failed", { err });
|
|
4980
4949
|
setState("error");
|
|
4981
4950
|
});
|
|
4982
4951
|
return () => {
|
|
4983
4952
|
cancelled = true;
|
|
4984
4953
|
};
|
|
4985
4954
|
}, [transport, visitorId]);
|
|
4986
|
-
const newChatButton = onNewChat ? /* @__PURE__ */
|
|
4987
|
-
/* @__PURE__ */
|
|
4955
|
+
const newChatButton = onNewChat ? /* @__PURE__ */ jsx18("div", { class: `${p33}-history-footer`, children: /* @__PURE__ */ jsxs15("button", { type: "button", class: `${p33}-history-new`, onClick: onNewChat, "data-testid": TID.sidebarNewChat, children: [
|
|
4956
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
4988
4957
|
strings.historyNewChat
|
|
4989
4958
|
] }) }) : null;
|
|
4990
4959
|
if (state === "loading") {
|
|
4991
|
-
return /* @__PURE__ */
|
|
4992
|
-
/* @__PURE__ */
|
|
4960
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4961
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
4993
4962
|
newChatButton
|
|
4994
4963
|
] });
|
|
4995
4964
|
}
|
|
4996
|
-
if (state === "error" ||
|
|
4997
|
-
return /* @__PURE__ */
|
|
4998
|
-
/* @__PURE__ */
|
|
4965
|
+
if (state === "error" || conversations.length === 0) {
|
|
4966
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4967
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4999
4968
|
newChatButton
|
|
5000
4969
|
] });
|
|
5001
4970
|
}
|
|
5002
|
-
const groups = groupByBucket(Date.now(),
|
|
5003
|
-
return /* @__PURE__ */
|
|
5004
|
-
/* @__PURE__ */
|
|
5005
|
-
/* @__PURE__ */
|
|
5006
|
-
group.
|
|
4971
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4972
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4973
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4974
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4975
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
5007
4976
|
"button",
|
|
5008
4977
|
{
|
|
5009
4978
|
type: "button",
|
|
5010
4979
|
role: "listitem",
|
|
5011
|
-
class: `${
|
|
4980
|
+
class: `${p33}-history-item`,
|
|
5012
4981
|
onClick: () => onSelect(chat),
|
|
5013
4982
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
5014
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4983
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
5015
4984
|
children: [
|
|
5016
|
-
/* @__PURE__ */
|
|
5017
|
-
chat.preview ? /* @__PURE__ */
|
|
4985
|
+
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4986
|
+
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
5018
4987
|
]
|
|
5019
4988
|
},
|
|
5020
|
-
chat.
|
|
4989
|
+
chat.conversationId
|
|
5021
4990
|
))
|
|
5022
4991
|
] }, group.bucket)) }),
|
|
5023
4992
|
newChatButton
|
|
@@ -5025,21 +4994,21 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
5025
4994
|
}
|
|
5026
4995
|
|
|
5027
4996
|
// src/ui/chat-history-pane.tsx
|
|
5028
|
-
import { jsx as
|
|
4997
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
5029
4998
|
function ChatHistoryPane(props2) {
|
|
5030
|
-
return /* @__PURE__ */
|
|
4999
|
+
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
5031
5000
|
}
|
|
5032
5001
|
|
|
5033
5002
|
// src/ui/suggestions.tsx
|
|
5034
|
-
import { jsx as
|
|
5035
|
-
var
|
|
5003
|
+
import { jsx as jsx20 } from "preact/jsx-runtime";
|
|
5004
|
+
var p16 = BRAND.cssPrefix;
|
|
5036
5005
|
function Suggestions({ suggestions, onPick }) {
|
|
5037
5006
|
if (suggestions.length === 0) return null;
|
|
5038
|
-
return /* @__PURE__ */
|
|
5007
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx20(
|
|
5039
5008
|
"button",
|
|
5040
5009
|
{
|
|
5041
5010
|
type: "button",
|
|
5042
|
-
class: `${
|
|
5011
|
+
class: `${p16}-suggestion`,
|
|
5043
5012
|
onClick: () => onPick(s),
|
|
5044
5013
|
"data-testid": tid(TID.suggestion, i),
|
|
5045
5014
|
children: s.label
|
|
@@ -5049,8 +5018,8 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
5049
5018
|
}
|
|
5050
5019
|
|
|
5051
5020
|
// src/ui/panel.tsx
|
|
5052
|
-
import { Fragment as Fragment3, jsx as
|
|
5053
|
-
var
|
|
5021
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
5022
|
+
var p17 = BRAND.cssPrefix;
|
|
5054
5023
|
function Panel(props2) {
|
|
5055
5024
|
const { options, onClose } = props2;
|
|
5056
5025
|
const s = options.strings;
|
|
@@ -5074,18 +5043,18 @@ function Panel(props2) {
|
|
|
5074
5043
|
}, []);
|
|
5075
5044
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
5076
5045
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
5077
|
-
return /* @__PURE__ */
|
|
5046
|
+
return /* @__PURE__ */ jsxs16(
|
|
5078
5047
|
"div",
|
|
5079
5048
|
{
|
|
5080
5049
|
ref: containerRef,
|
|
5081
|
-
class: `${
|
|
5050
|
+
class: `${p17}-panel`,
|
|
5082
5051
|
role: "dialog",
|
|
5083
5052
|
"aria-modal": "false",
|
|
5084
5053
|
"aria-label": s.panelTitle,
|
|
5085
5054
|
style: { position: "relative" },
|
|
5086
5055
|
"data-testid": TID.panel,
|
|
5087
5056
|
children: [
|
|
5088
|
-
/* @__PURE__ */
|
|
5057
|
+
/* @__PURE__ */ jsx21(
|
|
5089
5058
|
PanelContent,
|
|
5090
5059
|
{
|
|
5091
5060
|
...props2,
|
|
@@ -5094,7 +5063,7 @@ function Panel(props2) {
|
|
|
5094
5063
|
composerAttachApiRef
|
|
5095
5064
|
}
|
|
5096
5065
|
),
|
|
5097
|
-
/* @__PURE__ */
|
|
5066
|
+
/* @__PURE__ */ jsx21(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
5098
5067
|
]
|
|
5099
5068
|
}
|
|
5100
5069
|
);
|
|
@@ -5125,8 +5094,7 @@ function PanelContent(props2) {
|
|
|
5125
5094
|
onSend,
|
|
5126
5095
|
onStop,
|
|
5127
5096
|
onSuggestion,
|
|
5128
|
-
|
|
5129
|
-
inlineForm,
|
|
5097
|
+
activeForm,
|
|
5130
5098
|
onFormSubmit,
|
|
5131
5099
|
onFormSkip,
|
|
5132
5100
|
tool,
|
|
@@ -5136,12 +5104,12 @@ function PanelContent(props2) {
|
|
|
5136
5104
|
} = props2;
|
|
5137
5105
|
const s = options.strings;
|
|
5138
5106
|
let composerArea;
|
|
5139
|
-
if (
|
|
5140
|
-
composerArea = /* @__PURE__ */
|
|
5107
|
+
if (activeForm) {
|
|
5108
|
+
composerArea = /* @__PURE__ */ jsx21(FormGate, { form: activeForm, strings: s, onSubmit: onFormSubmit, onSkip: onFormSkip });
|
|
5141
5109
|
} else if (canSend) {
|
|
5142
|
-
composerArea = /* @__PURE__ */
|
|
5143
|
-
/* @__PURE__ */
|
|
5144
|
-
/* @__PURE__ */
|
|
5110
|
+
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5111
|
+
/* @__PURE__ */ jsx21(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
5112
|
+
/* @__PURE__ */ jsx21(
|
|
5145
5113
|
Composer,
|
|
5146
5114
|
{
|
|
5147
5115
|
options,
|
|
@@ -5156,10 +5124,10 @@ function PanelContent(props2) {
|
|
|
5156
5124
|
)
|
|
5157
5125
|
] });
|
|
5158
5126
|
} else {
|
|
5159
|
-
composerArea = /* @__PURE__ */
|
|
5127
|
+
composerArea = /* @__PURE__ */ jsx21(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear });
|
|
5160
5128
|
}
|
|
5161
|
-
return /* @__PURE__ */
|
|
5162
|
-
view === "history" ? /* @__PURE__ */
|
|
5129
|
+
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5130
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
5163
5131
|
HistoryHeader,
|
|
5164
5132
|
{
|
|
5165
5133
|
strings: s,
|
|
@@ -5167,33 +5135,33 @@ function PanelContent(props2) {
|
|
|
5167
5135
|
onClose,
|
|
5168
5136
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
5169
5137
|
}
|
|
5170
|
-
) : /* @__PURE__ */
|
|
5171
|
-
onBack ? /* @__PURE__ */
|
|
5138
|
+
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5139
|
+
onBack ? /* @__PURE__ */ jsx21(
|
|
5172
5140
|
"button",
|
|
5173
5141
|
{
|
|
5174
5142
|
type: "button",
|
|
5175
|
-
class: `${
|
|
5143
|
+
class: `${p17}-icon-btn`,
|
|
5176
5144
|
onClick: onBack,
|
|
5177
5145
|
"aria-label": s.moduleBack,
|
|
5178
5146
|
title: s.moduleBack,
|
|
5179
|
-
children: /* @__PURE__ */
|
|
5147
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
5180
5148
|
}
|
|
5181
5149
|
) : null,
|
|
5182
|
-
agent ? /* @__PURE__ */
|
|
5183
|
-
/* @__PURE__ */
|
|
5150
|
+
agent ? /* @__PURE__ */ jsx21(AgentBadge, { agent }) : /* @__PURE__ */ jsx21("h1", { children: s.panelTitle }),
|
|
5151
|
+
/* @__PURE__ */ jsx21(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
5184
5152
|
] }),
|
|
5185
|
-
view === "history" ? /* @__PURE__ */
|
|
5153
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
5186
5154
|
ChatHistoryPane,
|
|
5187
5155
|
{
|
|
5188
5156
|
transport,
|
|
5189
5157
|
strings: s,
|
|
5190
5158
|
visitorId,
|
|
5191
|
-
onSelect: (chat) => onSelectHistoryChat(chat.
|
|
5159
|
+
onSelect: (chat) => onSelectHistoryChat(chat.conversationId),
|
|
5192
5160
|
onNewChat
|
|
5193
5161
|
}
|
|
5194
|
-
) : /* @__PURE__ */
|
|
5195
|
-
/* @__PURE__ */
|
|
5196
|
-
/* @__PURE__ */
|
|
5162
|
+
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5163
|
+
/* @__PURE__ */ jsx21(DropZone, { visible: dragOver, strings: s }),
|
|
5164
|
+
/* @__PURE__ */ jsx21(
|
|
5197
5165
|
MessageList,
|
|
5198
5166
|
{
|
|
5199
5167
|
messagesSig,
|
|
@@ -5203,16 +5171,13 @@ function PanelContent(props2) {
|
|
|
5203
5171
|
showToolCalls: options.showToolCalls,
|
|
5204
5172
|
loading: loadingMessages,
|
|
5205
5173
|
idle: !isStreaming,
|
|
5206
|
-
tool
|
|
5207
|
-
inlineForm,
|
|
5208
|
-
onFormSubmit,
|
|
5209
|
-
onFormSkip
|
|
5174
|
+
tool
|
|
5210
5175
|
}
|
|
5211
5176
|
),
|
|
5212
5177
|
composerArea,
|
|
5213
|
-
/* @__PURE__ */
|
|
5178
|
+
/* @__PURE__ */ jsx21(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5214
5179
|
] }),
|
|
5215
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5180
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx21(
|
|
5216
5181
|
ResizeGrip,
|
|
5217
5182
|
{
|
|
5218
5183
|
panelEl: containerEl,
|
|
@@ -5231,55 +5196,55 @@ function HistoryHeader({
|
|
|
5231
5196
|
onClose,
|
|
5232
5197
|
showClose
|
|
5233
5198
|
}) {
|
|
5234
|
-
return /* @__PURE__ */
|
|
5235
|
-
/* @__PURE__ */
|
|
5199
|
+
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5200
|
+
/* @__PURE__ */ jsx21(
|
|
5236
5201
|
"button",
|
|
5237
5202
|
{
|
|
5238
5203
|
type: "button",
|
|
5239
|
-
class: `${
|
|
5204
|
+
class: `${p17}-icon-btn`,
|
|
5240
5205
|
onClick: onBack,
|
|
5241
5206
|
"aria-label": strings.historyBack,
|
|
5242
5207
|
title: strings.historyBack,
|
|
5243
|
-
children: /* @__PURE__ */
|
|
5208
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
5244
5209
|
}
|
|
5245
5210
|
),
|
|
5246
|
-
/* @__PURE__ */
|
|
5247
|
-
showClose ? /* @__PURE__ */
|
|
5211
|
+
/* @__PURE__ */ jsx21("h1", { children: strings.historyTitle }),
|
|
5212
|
+
showClose ? /* @__PURE__ */ jsx21(
|
|
5248
5213
|
"button",
|
|
5249
5214
|
{
|
|
5250
5215
|
type: "button",
|
|
5251
|
-
class: `${
|
|
5216
|
+
class: `${p17}-icon-btn`,
|
|
5252
5217
|
onClick: onClose,
|
|
5253
5218
|
"aria-label": strings.close,
|
|
5254
5219
|
title: strings.close,
|
|
5255
|
-
children: /* @__PURE__ */
|
|
5220
|
+
children: /* @__PURE__ */ jsx21(CloseIcon, {})
|
|
5256
5221
|
}
|
|
5257
5222
|
) : null
|
|
5258
5223
|
] });
|
|
5259
5224
|
}
|
|
5260
5225
|
function ReadOnlyBanner({ label, ctaLabel, onNewChat }) {
|
|
5261
|
-
return /* @__PURE__ */
|
|
5262
|
-
/* @__PURE__ */
|
|
5263
|
-
/* @__PURE__ */
|
|
5226
|
+
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5227
|
+
/* @__PURE__ */ jsx21("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5228
|
+
/* @__PURE__ */ jsx21("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewChat, children: ctaLabel })
|
|
5264
5229
|
] });
|
|
5265
5230
|
}
|
|
5266
5231
|
function ComposerFooter({ disclaimer }) {
|
|
5267
5232
|
if (!disclaimer) return null;
|
|
5268
|
-
return /* @__PURE__ */
|
|
5233
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx21("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
5269
5234
|
}
|
|
5270
5235
|
function PoweredByBar({ poweredBy }) {
|
|
5271
5236
|
if (!poweredBy) return null;
|
|
5272
|
-
return /* @__PURE__ */
|
|
5237
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx21(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
5273
5238
|
}
|
|
5274
5239
|
function PoweredBy({ logoUrl, text, href }) {
|
|
5275
|
-
const inner = /* @__PURE__ */
|
|
5276
|
-
logoUrl ? /* @__PURE__ */
|
|
5277
|
-
text ? /* @__PURE__ */
|
|
5240
|
+
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5241
|
+
logoUrl ? /* @__PURE__ */ jsx21("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5242
|
+
text ? /* @__PURE__ */ jsx21("span", { children: text }) : null
|
|
5278
5243
|
] });
|
|
5279
5244
|
if (href) {
|
|
5280
|
-
return /* @__PURE__ */
|
|
5245
|
+
return /* @__PURE__ */ jsx21("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
5281
5246
|
}
|
|
5282
|
-
return /* @__PURE__ */
|
|
5247
|
+
return /* @__PURE__ */ jsx21("span", { class: `${p17}-poweredby`, children: inner });
|
|
5283
5248
|
}
|
|
5284
5249
|
|
|
5285
5250
|
// src/ui/form/form-controller.ts
|
|
@@ -5294,10 +5259,11 @@ function useForms(deps) {
|
|
|
5294
5259
|
}
|
|
5295
5260
|
function createController(depsRef) {
|
|
5296
5261
|
const activeForm = signal5(null);
|
|
5297
|
-
const
|
|
5262
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5263
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5298
5264
|
const isDone = (form) => {
|
|
5299
5265
|
if (form.frequency === "always") return false;
|
|
5300
|
-
if (form.frequency === "
|
|
5266
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5301
5267
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5302
5268
|
};
|
|
5303
5269
|
const fire = (kind, param) => {
|
|
@@ -5320,7 +5286,7 @@ function createController(depsRef) {
|
|
|
5320
5286
|
if (!active) return;
|
|
5321
5287
|
activeForm.value = null;
|
|
5322
5288
|
const { form, trigger } = active;
|
|
5323
|
-
if (form.frequency === "
|
|
5289
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5324
5290
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5325
5291
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5326
5292
|
};
|
|
@@ -5354,34 +5320,34 @@ function whenPasses(form, d) {
|
|
|
5354
5320
|
}
|
|
5355
5321
|
|
|
5356
5322
|
// src/ui/sidebar.tsx
|
|
5357
|
-
import { Fragment as Fragment4, jsx as
|
|
5323
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
5358
5324
|
function Sidebar(props2) {
|
|
5359
|
-
const
|
|
5325
|
+
const p33 = BRAND.cssPrefix;
|
|
5360
5326
|
const { site, blocks, strings, collapsed } = props2;
|
|
5361
5327
|
const navigation = blocks?.navigation ?? [];
|
|
5362
5328
|
const linkCards = blocks?.linkCards ?? [];
|
|
5363
5329
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
5364
|
-
return /* @__PURE__ */
|
|
5365
|
-
/* @__PURE__ */
|
|
5366
|
-
/* @__PURE__ */
|
|
5367
|
-
/* @__PURE__ */
|
|
5330
|
+
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5331
|
+
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5332
|
+
/* @__PURE__ */ jsx22(SidebarBrand, { site }),
|
|
5333
|
+
/* @__PURE__ */ jsx22(
|
|
5368
5334
|
"button",
|
|
5369
5335
|
{
|
|
5370
5336
|
type: "button",
|
|
5371
|
-
class: `${
|
|
5337
|
+
class: `${p33}-sidebar-toggle`,
|
|
5372
5338
|
"aria-label": toggleLabel,
|
|
5373
5339
|
"aria-expanded": collapsed ? "false" : "true",
|
|
5374
5340
|
title: toggleLabel,
|
|
5375
5341
|
onClick: props2.onToggleCollapsed,
|
|
5376
5342
|
"data-testid": TID.sidebarToggle,
|
|
5377
|
-
children: /* @__PURE__ */
|
|
5343
|
+
children: /* @__PURE__ */ jsx22(SidebarToggleIcon, { collapsed })
|
|
5378
5344
|
}
|
|
5379
5345
|
)
|
|
5380
5346
|
] }),
|
|
5381
|
-
collapsed ? null : /* @__PURE__ */
|
|
5382
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
5383
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
5384
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5347
|
+
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5348
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx22("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx22(SidebarNav, { items: navigation }) }) : null,
|
|
5349
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx22(SidebarCards, { items: linkCards }) }) : null,
|
|
5350
|
+
props2.showConversations ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx22(
|
|
5385
5351
|
ConversationList,
|
|
5386
5352
|
{
|
|
5387
5353
|
transport: props2.transport,
|
|
@@ -5395,18 +5361,18 @@ function Sidebar(props2) {
|
|
|
5395
5361
|
] });
|
|
5396
5362
|
}
|
|
5397
5363
|
function SidebarBrand({ site }) {
|
|
5398
|
-
const
|
|
5364
|
+
const p33 = BRAND.cssPrefix;
|
|
5399
5365
|
if (site?.logo?.url) {
|
|
5400
5366
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
5401
|
-
return /* @__PURE__ */
|
|
5402
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
5403
|
-
/* @__PURE__ */
|
|
5367
|
+
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5368
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx22("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5369
|
+
/* @__PURE__ */ jsx22("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
5404
5370
|
] });
|
|
5405
5371
|
}
|
|
5406
|
-
return /* @__PURE__ */
|
|
5372
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
5407
5373
|
}
|
|
5408
5374
|
function SidebarToggleIcon({ collapsed }) {
|
|
5409
|
-
return /* @__PURE__ */
|
|
5375
|
+
return /* @__PURE__ */ jsx22(
|
|
5410
5376
|
"svg",
|
|
5411
5377
|
{
|
|
5412
5378
|
width: "16",
|
|
@@ -5416,38 +5382,38 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
5416
5382
|
stroke: "currentColor",
|
|
5417
5383
|
"stroke-width": "2",
|
|
5418
5384
|
"aria-hidden": "true",
|
|
5419
|
-
children: collapsed ? /* @__PURE__ */
|
|
5385
|
+
children: collapsed ? /* @__PURE__ */ jsx22("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx22("polyline", { points: "15 6 9 12 15 18" })
|
|
5420
5386
|
}
|
|
5421
5387
|
);
|
|
5422
5388
|
}
|
|
5423
5389
|
function SidebarNav({ items }) {
|
|
5424
|
-
const
|
|
5425
|
-
return /* @__PURE__ */
|
|
5390
|
+
const p33 = BRAND.cssPrefix;
|
|
5391
|
+
return /* @__PURE__ */ jsx22("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsxs17(
|
|
5426
5392
|
"a",
|
|
5427
5393
|
{
|
|
5428
|
-
class: `${
|
|
5394
|
+
class: `${p33}-sidebar-nav-item`,
|
|
5429
5395
|
href: item.href,
|
|
5430
5396
|
target: item.href ? "_blank" : void 0,
|
|
5431
5397
|
rel: item.href ? "noreferrer" : void 0,
|
|
5432
5398
|
children: [
|
|
5433
|
-
item.icon ? /* @__PURE__ */
|
|
5434
|
-
/* @__PURE__ */
|
|
5399
|
+
item.icon ? /* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5400
|
+
/* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
5435
5401
|
]
|
|
5436
5402
|
}
|
|
5437
5403
|
) }, item.id ?? item.label)) });
|
|
5438
5404
|
}
|
|
5439
5405
|
function SidebarCards({ items }) {
|
|
5440
|
-
const
|
|
5441
|
-
return /* @__PURE__ */
|
|
5406
|
+
const p33 = BRAND.cssPrefix;
|
|
5407
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
5442
5408
|
"a",
|
|
5443
5409
|
{
|
|
5444
|
-
class: `${
|
|
5410
|
+
class: `${p33}-sidebar-card`,
|
|
5445
5411
|
href: item.href,
|
|
5446
5412
|
target: item.href ? "_blank" : void 0,
|
|
5447
5413
|
rel: item.href ? "noreferrer" : void 0,
|
|
5448
5414
|
children: [
|
|
5449
|
-
/* @__PURE__ */
|
|
5450
|
-
item.description ? /* @__PURE__ */
|
|
5415
|
+
/* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5416
|
+
item.description ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
5451
5417
|
]
|
|
5452
5418
|
},
|
|
5453
5419
|
item.id ?? item.label
|
|
@@ -5455,11 +5421,11 @@ function SidebarCards({ items }) {
|
|
|
5455
5421
|
}
|
|
5456
5422
|
|
|
5457
5423
|
// src/ui/page-shell.tsx
|
|
5458
|
-
import { jsx as
|
|
5459
|
-
var
|
|
5424
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5425
|
+
var p18 = BRAND.cssPrefix;
|
|
5460
5426
|
function PageShell(props2) {
|
|
5461
|
-
return /* @__PURE__ */
|
|
5462
|
-
/* @__PURE__ */
|
|
5427
|
+
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5428
|
+
/* @__PURE__ */ jsx23(
|
|
5463
5429
|
Sidebar,
|
|
5464
5430
|
{
|
|
5465
5431
|
site: props2.site,
|
|
@@ -5474,7 +5440,7 @@ function PageShell(props2) {
|
|
|
5474
5440
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
5475
5441
|
}
|
|
5476
5442
|
),
|
|
5477
|
-
/* @__PURE__ */
|
|
5443
|
+
/* @__PURE__ */ jsx23("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
5478
5444
|
] });
|
|
5479
5445
|
}
|
|
5480
5446
|
|
|
@@ -5524,80 +5490,80 @@ var chatLayout = {
|
|
|
5524
5490
|
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
5525
5491
|
|
|
5526
5492
|
// src/ui/back-header.tsx
|
|
5527
|
-
import { jsx as
|
|
5528
|
-
var
|
|
5493
|
+
import { jsx as jsx24, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5494
|
+
var p19 = BRAND.cssPrefix;
|
|
5529
5495
|
function TitleBar({ title, actions }) {
|
|
5530
|
-
return /* @__PURE__ */
|
|
5531
|
-
/* @__PURE__ */
|
|
5532
|
-
/* @__PURE__ */
|
|
5533
|
-
actions ?? /* @__PURE__ */
|
|
5496
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5497
|
+
/* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5498
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5499
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5534
5500
|
] });
|
|
5535
5501
|
}
|
|
5536
5502
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
5537
|
-
return /* @__PURE__ */
|
|
5538
|
-
/* @__PURE__ */
|
|
5539
|
-
/* @__PURE__ */
|
|
5540
|
-
actions ?? /* @__PURE__ */
|
|
5503
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5504
|
+
/* @__PURE__ */ jsx24("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx24(BackIcon, {}) }),
|
|
5505
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5506
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5541
5507
|
] });
|
|
5542
5508
|
}
|
|
5543
5509
|
|
|
5544
5510
|
// src/ui/home-search.tsx
|
|
5545
|
-
import { jsx as
|
|
5546
|
-
var
|
|
5511
|
+
import { jsx as jsx25, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5512
|
+
var p20 = BRAND.cssPrefix;
|
|
5547
5513
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
5548
|
-
return /* @__PURE__ */
|
|
5549
|
-
/* @__PURE__ */
|
|
5550
|
-
/* @__PURE__ */
|
|
5514
|
+
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5515
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5516
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
5551
5517
|
] });
|
|
5552
5518
|
}
|
|
5553
5519
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
5554
|
-
return /* @__PURE__ */
|
|
5555
|
-
/* @__PURE__ */
|
|
5520
|
+
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5521
|
+
/* @__PURE__ */ jsx25(
|
|
5556
5522
|
"input",
|
|
5557
5523
|
{
|
|
5558
5524
|
type: "search",
|
|
5559
|
-
class: `${
|
|
5525
|
+
class: `${p20}-home-search-input`,
|
|
5560
5526
|
placeholder,
|
|
5561
5527
|
value,
|
|
5562
5528
|
onInput: (e) => onInput(e.currentTarget.value),
|
|
5563
5529
|
"data-testid": TID.helpSearch
|
|
5564
5530
|
}
|
|
5565
5531
|
),
|
|
5566
|
-
/* @__PURE__ */
|
|
5532
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
5567
5533
|
] });
|
|
5568
5534
|
}
|
|
5569
5535
|
|
|
5570
5536
|
// src/ui/list-row.tsx
|
|
5571
|
-
import { jsx as
|
|
5572
|
-
var
|
|
5537
|
+
import { jsx as jsx26, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5538
|
+
var p21 = BRAND.cssPrefix;
|
|
5573
5539
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
5574
|
-
return /* @__PURE__ */
|
|
5575
|
-
/* @__PURE__ */
|
|
5576
|
-
/* @__PURE__ */
|
|
5577
|
-
subtitle ? /* @__PURE__ */
|
|
5540
|
+
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5541
|
+
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5542
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5543
|
+
subtitle ? /* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
5578
5544
|
] }),
|
|
5579
|
-
/* @__PURE__ */
|
|
5545
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx26(ChevronRightIcon, {}) })
|
|
5580
5546
|
] });
|
|
5581
5547
|
}
|
|
5582
5548
|
|
|
5583
5549
|
// src/ui/module-state.tsx
|
|
5584
|
-
import { jsx as
|
|
5585
|
-
var
|
|
5550
|
+
import { jsx as jsx27, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5551
|
+
var p22 = BRAND.cssPrefix;
|
|
5586
5552
|
function ModuleState({
|
|
5587
5553
|
tone = "info",
|
|
5588
5554
|
message,
|
|
5589
5555
|
onRetry,
|
|
5590
5556
|
strings
|
|
5591
5557
|
}) {
|
|
5592
|
-
return /* @__PURE__ */
|
|
5593
|
-
/* @__PURE__ */
|
|
5594
|
-
onRetry ? /* @__PURE__ */
|
|
5558
|
+
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5559
|
+
/* @__PURE__ */ jsx27("span", { children: message }),
|
|
5560
|
+
onRetry ? /* @__PURE__ */ jsx27("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
5595
5561
|
] });
|
|
5596
5562
|
}
|
|
5597
5563
|
|
|
5598
5564
|
// src/ui/modules/help.tsx
|
|
5599
|
-
import { jsx as
|
|
5600
|
-
var
|
|
5565
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5566
|
+
var p23 = BRAND.cssPrefix;
|
|
5601
5567
|
var log12 = logger.scope("help");
|
|
5602
5568
|
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 });
|
|
5603
5569
|
function groupByCategory(items) {
|
|
@@ -5626,7 +5592,7 @@ function fuzzySearch(items, query) {
|
|
|
5626
5592
|
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);
|
|
5627
5593
|
}
|
|
5628
5594
|
function ArticleRow({ article, nav }) {
|
|
5629
|
-
return /* @__PURE__ */
|
|
5595
|
+
return /* @__PURE__ */ jsx28(
|
|
5630
5596
|
ListRow,
|
|
5631
5597
|
{
|
|
5632
5598
|
title: article.title,
|
|
@@ -5663,46 +5629,46 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5663
5629
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
5664
5630
|
function renderBody() {
|
|
5665
5631
|
if (query.trim().length > 0) {
|
|
5666
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
5667
|
-
return /* @__PURE__ */
|
|
5632
|
+
if (results.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5633
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) });
|
|
5668
5634
|
}
|
|
5669
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5635
|
+
if (state === "loading") return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpLoading, strings });
|
|
5670
5636
|
if (state === "error") {
|
|
5671
|
-
return /* @__PURE__ */
|
|
5637
|
+
return /* @__PURE__ */ jsx28(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5672
5638
|
}
|
|
5673
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5674
|
-
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */
|
|
5675
|
-
category ? /* @__PURE__ */
|
|
5676
|
-
/* @__PURE__ */
|
|
5639
|
+
if (items.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpEmpty, strings });
|
|
5640
|
+
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5641
|
+
category ? /* @__PURE__ */ jsx28("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5642
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) })
|
|
5677
5643
|
] }, category));
|
|
5678
5644
|
}
|
|
5679
|
-
return /* @__PURE__ */
|
|
5680
|
-
/* @__PURE__ */
|
|
5681
|
-
/* @__PURE__ */
|
|
5682
|
-
/* @__PURE__ */
|
|
5645
|
+
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5646
|
+
/* @__PURE__ */ jsx28(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx28(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5647
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx28(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5648
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
5683
5649
|
] });
|
|
5684
5650
|
}
|
|
5685
5651
|
var helpLayout = {
|
|
5686
5652
|
Icon: HelpIcon,
|
|
5687
|
-
Root: (props2) => /* @__PURE__ */
|
|
5653
|
+
Root: (props2) => /* @__PURE__ */ jsx28(HelpRoot, { ...props2 })
|
|
5688
5654
|
};
|
|
5689
5655
|
|
|
5690
5656
|
// src/ui/modules/home.tsx
|
|
5691
5657
|
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
5692
5658
|
|
|
5693
5659
|
// src/ui/home-card.tsx
|
|
5694
|
-
import { jsx as
|
|
5695
|
-
var
|
|
5660
|
+
import { jsx as jsx29 } from "preact/jsx-runtime";
|
|
5661
|
+
var p24 = BRAND.cssPrefix;
|
|
5696
5662
|
function HomeCard({ onClick, children, testid }) {
|
|
5697
5663
|
if (onClick) {
|
|
5698
|
-
return /* @__PURE__ */
|
|
5664
|
+
return /* @__PURE__ */ jsx29("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
5699
5665
|
}
|
|
5700
|
-
return /* @__PURE__ */
|
|
5666
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
5701
5667
|
}
|
|
5702
5668
|
|
|
5703
5669
|
// src/ui/modules/home.tsx
|
|
5704
|
-
import { Fragment as Fragment5, jsx as
|
|
5705
|
-
var
|
|
5670
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5671
|
+
var p25 = BRAND.cssPrefix;
|
|
5706
5672
|
var log13 = logger.scope("home");
|
|
5707
5673
|
function resolveGreeting(props2) {
|
|
5708
5674
|
const name = props2.options.userContext?.name;
|
|
@@ -5722,7 +5688,7 @@ function HomeRoot(props2) {
|
|
|
5722
5688
|
useEffect12(() => {
|
|
5723
5689
|
if (!config.showRecentMessages) return;
|
|
5724
5690
|
let cancelled = false;
|
|
5725
|
-
transport.
|
|
5691
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5726
5692
|
return () => {
|
|
5727
5693
|
cancelled = true;
|
|
5728
5694
|
};
|
|
@@ -5739,49 +5705,49 @@ function HomeRoot(props2) {
|
|
|
5739
5705
|
const avatars = config.userAvatars ?? [];
|
|
5740
5706
|
const status = config.status;
|
|
5741
5707
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
5742
|
-
return /* @__PURE__ */
|
|
5743
|
-
/* @__PURE__ */
|
|
5744
|
-
/* @__PURE__ */
|
|
5745
|
-
config.brandName ? /* @__PURE__ */
|
|
5746
|
-
/* @__PURE__ */
|
|
5747
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
5748
|
-
/* @__PURE__ */
|
|
5708
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5709
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5710
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5711
|
+
config.brandName ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-brand`, "data-testid": TID.homeBrand, children: config.brandName }) : /* @__PURE__ */ jsx30("span", { class: `${p25}-home-brand-spacer`, "aria-hidden": "true" }),
|
|
5712
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5713
|
+
avatars.length > 0 ? /* @__PURE__ */ jsx30("div", { class: `${p25}-home-avatars`, children: avatars.map((a) => /* @__PURE__ */ jsx30("span", { class: `${p25}-home-avatar`, title: a.role ? `${a.name} \xB7 ${a.role}` : a.name, children: a.avatar ? /* @__PURE__ */ jsx30("img", { src: a.avatar, alt: "", loading: "lazy" }) : /* @__PURE__ */ jsx30("span", { children: initials(a.name) }) }, a.name)) }) : null,
|
|
5714
|
+
/* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" })
|
|
5749
5715
|
] })
|
|
5750
5716
|
] }),
|
|
5751
|
-
config.showGreeting !== false ? /* @__PURE__ */
|
|
5752
|
-
/* @__PURE__ */
|
|
5753
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5717
|
+
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5718
|
+
/* @__PURE__ */ jsx30("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5719
|
+
greeting.subtitle ? /* @__PURE__ */ jsx30("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
5754
5720
|
] }) : null
|
|
5755
5721
|
] }),
|
|
5756
|
-
/* @__PURE__ */
|
|
5757
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5722
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5723
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx30(
|
|
5758
5724
|
HomeSearchButton,
|
|
5759
5725
|
{
|
|
5760
5726
|
placeholder: strings.homeSearchPlaceholder,
|
|
5761
5727
|
onActivate: () => nav.switchToLayout("help")
|
|
5762
5728
|
}
|
|
5763
5729
|
) : null,
|
|
5764
|
-
recent ? /* @__PURE__ */
|
|
5765
|
-
/* @__PURE__ */
|
|
5766
|
-
/* @__PURE__ */
|
|
5767
|
-
/* @__PURE__ */
|
|
5768
|
-
recent.preview ? /* @__PURE__ */
|
|
5730
|
+
recent ? /* @__PURE__ */ jsx30(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: [
|
|
5731
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5732
|
+
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5733
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5734
|
+
recent.preview ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
5769
5735
|
] }),
|
|
5770
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5736
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
5771
5737
|
] }) }) : null,
|
|
5772
|
-
status ? /* @__PURE__ */
|
|
5738
|
+
status ? /* @__PURE__ */ jsx30(
|
|
5773
5739
|
HomeCard,
|
|
5774
5740
|
{
|
|
5775
5741
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
5776
|
-
children: /* @__PURE__ */
|
|
5777
|
-
/* @__PURE__ */
|
|
5778
|
-
/* @__PURE__ */
|
|
5742
|
+
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5743
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(StatusOkIcon, {}) }),
|
|
5744
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
5779
5745
|
] })
|
|
5780
5746
|
}
|
|
5781
5747
|
) : null,
|
|
5782
|
-
content.length > 0 ? /* @__PURE__ */
|
|
5783
|
-
/* @__PURE__ */
|
|
5784
|
-
/* @__PURE__ */
|
|
5748
|
+
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5749
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5750
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx30(
|
|
5785
5751
|
ListRow,
|
|
5786
5752
|
{
|
|
5787
5753
|
title: item.title,
|
|
@@ -5797,13 +5763,13 @@ function HomeRoot(props2) {
|
|
|
5797
5763
|
}
|
|
5798
5764
|
var homeLayout = {
|
|
5799
5765
|
Icon: HomeIcon,
|
|
5800
|
-
Root: (props2) => /* @__PURE__ */
|
|
5766
|
+
Root: (props2) => /* @__PURE__ */ jsx30(HomeRoot, { ...props2 })
|
|
5801
5767
|
};
|
|
5802
5768
|
|
|
5803
5769
|
// src/ui/modules/news.tsx
|
|
5804
5770
|
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5805
|
-
import { jsx as
|
|
5806
|
-
var
|
|
5771
|
+
import { jsx as jsx31, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5772
|
+
var p26 = BRAND.cssPrefix;
|
|
5807
5773
|
var log14 = logger.scope("news");
|
|
5808
5774
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
5809
5775
|
const tags = config.contentTags;
|
|
@@ -5829,38 +5795,38 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5829
5795
|
};
|
|
5830
5796
|
}, [transport, tags, reloadKey]);
|
|
5831
5797
|
function renderBody() {
|
|
5832
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5798
|
+
if (state === "loading") return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsLoading, strings });
|
|
5833
5799
|
if (state === "error") {
|
|
5834
|
-
return /* @__PURE__ */
|
|
5800
|
+
return /* @__PURE__ */ jsx31(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5835
5801
|
}
|
|
5836
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5837
|
-
return /* @__PURE__ */
|
|
5802
|
+
if (items.length === 0) return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsEmpty, strings });
|
|
5803
|
+
return /* @__PURE__ */ jsx31("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
5838
5804
|
"button",
|
|
5839
5805
|
{
|
|
5840
5806
|
type: "button",
|
|
5841
|
-
class: `${
|
|
5807
|
+
class: `${p26}-news-card`,
|
|
5842
5808
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
5843
5809
|
"data-testid": tid(TID.newsItem, item.id),
|
|
5844
5810
|
children: [
|
|
5845
|
-
item.image ? /* @__PURE__ */
|
|
5846
|
-
/* @__PURE__ */
|
|
5847
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5848
|
-
/* @__PURE__ */
|
|
5849
|
-
item.description ? /* @__PURE__ */
|
|
5811
|
+
item.image ? /* @__PURE__ */ jsx31("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5812
|
+
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5813
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx31("span", { class: `${p26}-news-tag`, children: t }, t)) }) : null,
|
|
5814
|
+
/* @__PURE__ */ jsx31("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5815
|
+
item.description ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
5850
5816
|
] })
|
|
5851
5817
|
]
|
|
5852
5818
|
},
|
|
5853
5819
|
item.id
|
|
5854
5820
|
)) });
|
|
5855
5821
|
}
|
|
5856
|
-
return /* @__PURE__ */
|
|
5857
|
-
/* @__PURE__ */
|
|
5858
|
-
/* @__PURE__ */
|
|
5822
|
+
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5823
|
+
/* @__PURE__ */ jsx31(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx31(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5824
|
+
/* @__PURE__ */ jsx31("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
5859
5825
|
] });
|
|
5860
5826
|
}
|
|
5861
5827
|
var newsLayout = {
|
|
5862
5828
|
Icon: NewsIcon,
|
|
5863
|
-
Root: (props2) => /* @__PURE__ */
|
|
5829
|
+
Root: (props2) => /* @__PURE__ */ jsx31(NewsRoot, { ...props2 })
|
|
5864
5830
|
};
|
|
5865
5831
|
|
|
5866
5832
|
// src/ui/modules/registry.ts
|
|
@@ -5872,28 +5838,28 @@ var LAYOUTS = {
|
|
|
5872
5838
|
};
|
|
5873
5839
|
|
|
5874
5840
|
// src/ui/home-tab-bar.tsx
|
|
5875
|
-
import { jsx as
|
|
5876
|
-
var
|
|
5841
|
+
import { jsx as jsx32, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5842
|
+
var p27 = BRAND.cssPrefix;
|
|
5877
5843
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
5878
|
-
return /* @__PURE__ */
|
|
5844
|
+
return /* @__PURE__ */ jsx32("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
5879
5845
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
5880
5846
|
const selected = m.id === activeTab;
|
|
5881
5847
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
5882
|
-
return /* @__PURE__ */
|
|
5848
|
+
return /* @__PURE__ */ jsxs26(
|
|
5883
5849
|
"button",
|
|
5884
5850
|
{
|
|
5885
5851
|
type: "button",
|
|
5886
5852
|
role: "tab",
|
|
5887
5853
|
"aria-selected": selected,
|
|
5888
|
-
class: `${
|
|
5854
|
+
class: `${p27}-tab`,
|
|
5889
5855
|
onClick: () => onSelect(m.id),
|
|
5890
5856
|
"data-testid": tid(TID.tab, m.id),
|
|
5891
5857
|
children: [
|
|
5892
|
-
/* @__PURE__ */
|
|
5893
|
-
/* @__PURE__ */
|
|
5894
|
-
badge ? /* @__PURE__ */
|
|
5858
|
+
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5859
|
+
/* @__PURE__ */ jsx32(Icon, {}),
|
|
5860
|
+
badge ? /* @__PURE__ */ jsx32("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
5895
5861
|
] }),
|
|
5896
|
-
/* @__PURE__ */
|
|
5862
|
+
/* @__PURE__ */ jsx32("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
5897
5863
|
]
|
|
5898
5864
|
},
|
|
5899
5865
|
m.id
|
|
@@ -5902,12 +5868,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5902
5868
|
}
|
|
5903
5869
|
|
|
5904
5870
|
// src/ui/iframe-view.tsx
|
|
5905
|
-
import { jsx as
|
|
5906
|
-
var
|
|
5871
|
+
import { jsx as jsx33, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5872
|
+
var p28 = BRAND.cssPrefix;
|
|
5907
5873
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
5908
5874
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
5909
|
-
return /* @__PURE__ */
|
|
5910
|
-
/* @__PURE__ */
|
|
5875
|
+
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5876
|
+
/* @__PURE__ */ jsx33(
|
|
5911
5877
|
BackHeader,
|
|
5912
5878
|
{
|
|
5913
5879
|
title: title || strings.moduleBack,
|
|
@@ -5916,10 +5882,10 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5916
5882
|
actions
|
|
5917
5883
|
}
|
|
5918
5884
|
),
|
|
5919
|
-
/* @__PURE__ */
|
|
5885
|
+
/* @__PURE__ */ jsx33(
|
|
5920
5886
|
"iframe",
|
|
5921
5887
|
{
|
|
5922
|
-
class: `${
|
|
5888
|
+
class: `${p28}-content-frame`,
|
|
5923
5889
|
src: url,
|
|
5924
5890
|
title: title || "content",
|
|
5925
5891
|
sandbox: SANDBOX,
|
|
@@ -5933,8 +5899,8 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5933
5899
|
|
|
5934
5900
|
// src/ui/content-view.tsx
|
|
5935
5901
|
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5936
|
-
import { jsx as
|
|
5937
|
-
var
|
|
5902
|
+
import { jsx as jsx34, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5903
|
+
var p29 = BRAND.cssPrefix;
|
|
5938
5904
|
var log15 = logger.scope("content");
|
|
5939
5905
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
5940
5906
|
const [item, setItem] = useState11(null);
|
|
@@ -5962,17 +5928,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5962
5928
|
};
|
|
5963
5929
|
}, [transport, id, reloadKey]);
|
|
5964
5930
|
function renderBody() {
|
|
5965
|
-
if (failed) return /* @__PURE__ */
|
|
5966
|
-
if (item === null) return /* @__PURE__ */
|
|
5967
|
-
return /* @__PURE__ */
|
|
5968
|
-
item.image ? /* @__PURE__ */
|
|
5969
|
-
item.description ? /* @__PURE__ */
|
|
5970
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5971
|
-
/* @__PURE__ */
|
|
5931
|
+
if (failed) return /* @__PURE__ */ jsx34(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5932
|
+
if (item === null) return /* @__PURE__ */ jsx34(ModuleState, { message: strings.contentLoading, strings });
|
|
5933
|
+
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5934
|
+
item.image ? /* @__PURE__ */ jsx34("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5935
|
+
item.description ? /* @__PURE__ */ jsx34("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5936
|
+
item.tags && item.tags.length > 0 ? /* @__PURE__ */ jsx34("span", { class: `${p29}-news-tags`, children: item.tags.map((t) => /* @__PURE__ */ jsx34("span", { class: `${p29}-news-tag`, children: t }, t)) }) : null,
|
|
5937
|
+
/* @__PURE__ */ jsx34(StaticMarkdown, { text: item.content ?? "" })
|
|
5972
5938
|
] });
|
|
5973
5939
|
}
|
|
5974
|
-
return /* @__PURE__ */
|
|
5975
|
-
/* @__PURE__ */
|
|
5940
|
+
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5941
|
+
/* @__PURE__ */ jsx34(
|
|
5976
5942
|
BackHeader,
|
|
5977
5943
|
{
|
|
5978
5944
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -5982,20 +5948,20 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5982
5948
|
testid: TID.backHeader
|
|
5983
5949
|
}
|
|
5984
5950
|
),
|
|
5985
|
-
/* @__PURE__ */
|
|
5951
|
+
/* @__PURE__ */ jsx34("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
5986
5952
|
] });
|
|
5987
5953
|
}
|
|
5988
5954
|
|
|
5989
5955
|
// src/ui/messenger-home.tsx
|
|
5990
|
-
import { jsx as
|
|
5991
|
-
var
|
|
5956
|
+
import { jsx as jsx35, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5957
|
+
var p30 = BRAND.cssPrefix;
|
|
5992
5958
|
function MessengerHome({
|
|
5993
5959
|
panelProps,
|
|
5994
5960
|
enabledModules,
|
|
5995
5961
|
nav,
|
|
5996
5962
|
unreadCount,
|
|
5997
|
-
|
|
5998
|
-
|
|
5963
|
+
onSelectConversation,
|
|
5964
|
+
onStartNewConversation,
|
|
5999
5965
|
onSetPanelSize
|
|
6000
5966
|
}) {
|
|
6001
5967
|
const options = panelProps.options;
|
|
@@ -6044,8 +6010,8 @@ function MessengerHome({
|
|
|
6044
6010
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
6045
6011
|
if (target) nav.switchTab(target.id);
|
|
6046
6012
|
},
|
|
6047
|
-
|
|
6048
|
-
|
|
6013
|
+
selectConversation: onSelectConversation,
|
|
6014
|
+
startNewConversation: onStartNewConversation
|
|
6049
6015
|
};
|
|
6050
6016
|
const screenProps = (module) => ({
|
|
6051
6017
|
options,
|
|
@@ -6056,12 +6022,12 @@ function MessengerHome({
|
|
|
6056
6022
|
nav: moduleNav,
|
|
6057
6023
|
panelProps
|
|
6058
6024
|
});
|
|
6059
|
-
const plainActions = /* @__PURE__ */
|
|
6025
|
+
const plainActions = /* @__PURE__ */ jsx35(HeaderActions, { panelProps, variant: "plain" });
|
|
6060
6026
|
let body;
|
|
6061
6027
|
if (top?.kind === "iframe") {
|
|
6062
|
-
body = /* @__PURE__ */
|
|
6028
|
+
body = /* @__PURE__ */ jsx35(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
6063
6029
|
} else if (top?.kind === "content") {
|
|
6064
|
-
body = /* @__PURE__ */
|
|
6030
|
+
body = /* @__PURE__ */ jsx35(
|
|
6065
6031
|
ContentView,
|
|
6066
6032
|
{
|
|
6067
6033
|
id: top.id,
|
|
@@ -6073,7 +6039,7 @@ function MessengerHome({
|
|
|
6073
6039
|
}
|
|
6074
6040
|
);
|
|
6075
6041
|
} else if (activeModule?.layout === "chat") {
|
|
6076
|
-
body = /* @__PURE__ */
|
|
6042
|
+
body = /* @__PURE__ */ jsx35(
|
|
6077
6043
|
PanelContent,
|
|
6078
6044
|
{
|
|
6079
6045
|
...panelProps,
|
|
@@ -6084,23 +6050,23 @@ function MessengerHome({
|
|
|
6084
6050
|
);
|
|
6085
6051
|
} else if (activeModule) {
|
|
6086
6052
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
6087
|
-
body = Root ? /* @__PURE__ */
|
|
6053
|
+
body = Root ? /* @__PURE__ */ jsx35(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
6088
6054
|
} else {
|
|
6089
6055
|
body = null;
|
|
6090
6056
|
}
|
|
6091
|
-
return /* @__PURE__ */
|
|
6057
|
+
return /* @__PURE__ */ jsxs29(
|
|
6092
6058
|
"div",
|
|
6093
6059
|
{
|
|
6094
6060
|
ref: containerRef,
|
|
6095
|
-
class: `${
|
|
6061
|
+
class: `${p30}-panel ${p30}-messenger`,
|
|
6096
6062
|
role: "dialog",
|
|
6097
6063
|
"aria-modal": "false",
|
|
6098
6064
|
"aria-label": strings.panelTitle,
|
|
6099
6065
|
style: { position: "relative" },
|
|
6100
6066
|
"data-testid": TID.messengerHome,
|
|
6101
6067
|
children: [
|
|
6102
|
-
/* @__PURE__ */
|
|
6103
|
-
showTabBar ? /* @__PURE__ */
|
|
6068
|
+
/* @__PURE__ */ jsx35("div", { class: `${p30}-messenger-body`, children: body }),
|
|
6069
|
+
showTabBar ? /* @__PURE__ */ jsx35(
|
|
6104
6070
|
HomeTabBar,
|
|
6105
6071
|
{
|
|
6106
6072
|
modules: enabledModules,
|
|
@@ -6110,8 +6076,8 @@ function MessengerHome({
|
|
|
6110
6076
|
onSelect: nav.switchTab
|
|
6111
6077
|
}
|
|
6112
6078
|
) : null,
|
|
6113
|
-
/* @__PURE__ */
|
|
6114
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
6079
|
+
/* @__PURE__ */ jsx35(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
6080
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx35(
|
|
6115
6081
|
ResizeGrip,
|
|
6116
6082
|
{
|
|
6117
6083
|
panelEl: containerRef.current,
|
|
@@ -6128,29 +6094,29 @@ function MessengerHome({
|
|
|
6128
6094
|
}
|
|
6129
6095
|
|
|
6130
6096
|
// src/ui/modules-empty.tsx
|
|
6131
|
-
import { jsx as
|
|
6132
|
-
var
|
|
6097
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
6098
|
+
var p31 = BRAND.cssPrefix;
|
|
6133
6099
|
function ModulesEmpty({ strings, onClose }) {
|
|
6134
|
-
return /* @__PURE__ */
|
|
6100
|
+
return /* @__PURE__ */ jsxs30(
|
|
6135
6101
|
"div",
|
|
6136
6102
|
{
|
|
6137
|
-
class: `${
|
|
6103
|
+
class: `${p31}-panel ${p31}-modules-empty`,
|
|
6138
6104
|
role: "dialog",
|
|
6139
6105
|
"aria-label": strings.panelTitle,
|
|
6140
6106
|
"data-testid": TID.modulesEmpty,
|
|
6141
6107
|
children: [
|
|
6142
|
-
onClose ? /* @__PURE__ */
|
|
6108
|
+
onClose ? /* @__PURE__ */ jsx36(
|
|
6143
6109
|
"button",
|
|
6144
6110
|
{
|
|
6145
6111
|
type: "button",
|
|
6146
|
-
class: `${
|
|
6112
|
+
class: `${p31}-icon-btn ${p31}-modules-empty-close`,
|
|
6147
6113
|
onClick: onClose,
|
|
6148
6114
|
"aria-label": strings.close,
|
|
6149
6115
|
title: strings.close,
|
|
6150
|
-
children: /* @__PURE__ */
|
|
6116
|
+
children: /* @__PURE__ */ jsx36(CloseIcon, {})
|
|
6151
6117
|
}
|
|
6152
6118
|
) : null,
|
|
6153
|
-
/* @__PURE__ */
|
|
6119
|
+
/* @__PURE__ */ jsx36("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
6154
6120
|
]
|
|
6155
6121
|
}
|
|
6156
6122
|
);
|
|
@@ -6177,6 +6143,7 @@ function animateTypewriter(msg, text, charsPerSecond, abort) {
|
|
|
6177
6143
|
part.textSig.value = text;
|
|
6178
6144
|
part.doneSig.value = true;
|
|
6179
6145
|
msg.status = "complete";
|
|
6146
|
+
msg.partsSig.value = [...msg.partsSig.value];
|
|
6180
6147
|
resolve();
|
|
6181
6148
|
};
|
|
6182
6149
|
if (typeof requestAnimationFrame === "undefined") {
|
|
@@ -6221,9 +6188,9 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
6221
6188
|
}
|
|
6222
6189
|
|
|
6223
6190
|
// src/ui/app.tsx
|
|
6224
|
-
import { jsx as
|
|
6191
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
6225
6192
|
var log16 = logger.scope("app");
|
|
6226
|
-
var
|
|
6193
|
+
var p32 = BRAND.cssPrefix;
|
|
6227
6194
|
function App({ options, hostElement, bus }) {
|
|
6228
6195
|
const [persistence] = useState13(() => createPersistence(options.widgetId, options.storage));
|
|
6229
6196
|
const [visitorId, setVisitorId] = useState13(() => persistence.getVisitorId());
|
|
@@ -6232,7 +6199,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6232
6199
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6233
6200
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6234
6201
|
);
|
|
6235
|
-
const
|
|
6202
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6236
6203
|
const messagesSig = useSignal2([]);
|
|
6237
6204
|
const unreadCountSig = useSignal2(0);
|
|
6238
6205
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6254,7 +6221,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6254
6221
|
const homeNav = homeNavRef.current;
|
|
6255
6222
|
const chatTabIdRef = useRef9(void 0);
|
|
6256
6223
|
chatTabIdRef.current = chatTabId();
|
|
6257
|
-
const [
|
|
6224
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6258
6225
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6259
6226
|
const initialPanelRef = useRef9(
|
|
6260
6227
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6334,7 +6301,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6334
6301
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6335
6302
|
}, [options.mode, options.size, persistence]);
|
|
6336
6303
|
useEffect17(() => {
|
|
6337
|
-
if (!
|
|
6304
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6338
6305
|
initialPanelApplied.current = true;
|
|
6339
6306
|
const state = resolveInitialPanelState(
|
|
6340
6307
|
options,
|
|
@@ -6344,12 +6311,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6344
6311
|
);
|
|
6345
6312
|
setIsOpen(state.panelOpen);
|
|
6346
6313
|
setPanelSize(state.panelSize);
|
|
6347
|
-
}, [
|
|
6314
|
+
}, [conversationReady, options, persistence]);
|
|
6348
6315
|
const homeNavSeeded = useRef9(false);
|
|
6349
6316
|
const resumeActiveRef = useRef9(false);
|
|
6350
6317
|
const resumeBubbleRef = useRef9(null);
|
|
6351
6318
|
useEffect17(() => {
|
|
6352
|
-
if (!
|
|
6319
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6353
6320
|
homeNavSeeded.current = true;
|
|
6354
6321
|
if (resumeActiveRef.current) {
|
|
6355
6322
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6357,7 +6324,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6357
6324
|
return;
|
|
6358
6325
|
}
|
|
6359
6326
|
homeNav.reset(landingTab());
|
|
6360
|
-
}, [
|
|
6327
|
+
}, [conversationReady]);
|
|
6361
6328
|
const playWelcome = useCallback6(
|
|
6362
6329
|
(welcomeMessages) => {
|
|
6363
6330
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6376,21 +6343,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6376
6343
|
[messagesSig, options.welcome]
|
|
6377
6344
|
);
|
|
6378
6345
|
const connectGenRef = useRef9(0);
|
|
6379
|
-
const
|
|
6346
|
+
const runStartConversation = useCallback6(
|
|
6380
6347
|
async ({ newConversation }) => {
|
|
6381
6348
|
const myGen = ++connectGenRef.current;
|
|
6382
6349
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6383
|
-
const persistedChatId =
|
|
6384
|
-
const
|
|
6385
|
-
if (
|
|
6386
|
-
|
|
6387
|
-
persistence.
|
|
6350
|
+
const persistedChatId = conversationIdSig.value;
|
|
6351
|
+
const conversationId = newConversation || !persistedChatId ? uuid7() : persistedChatId;
|
|
6352
|
+
if (conversationId !== persistedChatId) {
|
|
6353
|
+
conversationIdSig.value = conversationId;
|
|
6354
|
+
persistence.saveConversationId(conversationId);
|
|
6388
6355
|
}
|
|
6389
6356
|
let res;
|
|
6390
6357
|
try {
|
|
6391
|
-
res = await transport.
|
|
6358
|
+
res = await transport.startConversation({
|
|
6392
6359
|
visitorId,
|
|
6393
|
-
|
|
6360
|
+
conversationId,
|
|
6394
6361
|
userPrefs: persistence.loadUserPrefs(),
|
|
6395
6362
|
locale: options.locale
|
|
6396
6363
|
});
|
|
@@ -6398,7 +6365,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6398
6365
|
if (isStale()) return;
|
|
6399
6366
|
bus.emit("error", err);
|
|
6400
6367
|
options.onError?.(err);
|
|
6401
|
-
if (!newConversation)
|
|
6368
|
+
if (!newConversation) setConversationReady(true);
|
|
6402
6369
|
return;
|
|
6403
6370
|
}
|
|
6404
6371
|
if (isStale()) return;
|
|
@@ -6412,12 +6379,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6412
6379
|
reason: res.rebind?.visitorId
|
|
6413
6380
|
});
|
|
6414
6381
|
}
|
|
6415
|
-
if (res.
|
|
6416
|
-
log16.info("
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6382
|
+
if (res.conversationId && res.conversationId !== conversationId) {
|
|
6383
|
+
log16.info("conversation rebound", {
|
|
6384
|
+
previous: conversationId,
|
|
6385
|
+
current: res.conversationId,
|
|
6386
|
+
reason: res.rebind?.conversationId
|
|
6387
|
+
});
|
|
6388
|
+
bus.emit("conversationRebound", {
|
|
6389
|
+
previous: conversationId,
|
|
6390
|
+
current: res.conversationId,
|
|
6391
|
+
reason: res.rebind?.conversationId
|
|
6421
6392
|
});
|
|
6422
6393
|
}
|
|
6423
6394
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6434,36 +6405,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6434
6405
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6435
6406
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6436
6407
|
}
|
|
6437
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6408
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6438
6409
|
if (isResume) {
|
|
6439
6410
|
setLoadingMessages(true);
|
|
6440
6411
|
try {
|
|
6441
|
-
const chat = res.messages?.length ? {
|
|
6412
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6442
6413
|
if (isStale()) return;
|
|
6443
6414
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6444
6415
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6445
|
-
if (loaded.length || tail.length)
|
|
6446
|
-
|
|
6447
|
-
|
|
6416
|
+
if (loaded.length || tail.length) {
|
|
6417
|
+
messagesSig.value = [...loaded, ...tail];
|
|
6418
|
+
setCanSend(chat.canContinue ?? true);
|
|
6419
|
+
setSuggestions(chat.suggestions ?? []);
|
|
6420
|
+
} else {
|
|
6421
|
+
playWelcome(res.welcome?.messages);
|
|
6422
|
+
}
|
|
6448
6423
|
} catch (err) {
|
|
6449
6424
|
if (isStale()) return;
|
|
6450
|
-
log16.warn("
|
|
6451
|
-
|
|
6452
|
-
persistence.
|
|
6425
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6426
|
+
conversationIdSig.value = void 0;
|
|
6427
|
+
persistence.saveConversationId(void 0);
|
|
6453
6428
|
} finally {
|
|
6454
6429
|
if (!isStale()) setLoadingMessages(false);
|
|
6455
6430
|
}
|
|
6456
6431
|
} else {
|
|
6457
|
-
|
|
6458
|
-
persistence.
|
|
6432
|
+
conversationIdSig.value = res.conversationId;
|
|
6433
|
+
persistence.saveConversationId(res.conversationId);
|
|
6459
6434
|
playWelcome(res.welcome?.messages);
|
|
6460
6435
|
}
|
|
6461
6436
|
if (!newConversation) {
|
|
6462
|
-
bus.emit("
|
|
6463
|
-
|
|
6437
|
+
bus.emit("conversationStarted", res);
|
|
6438
|
+
setConversationReady(true);
|
|
6464
6439
|
}
|
|
6465
6440
|
},
|
|
6466
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6441
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6467
6442
|
);
|
|
6468
6443
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6469
6444
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6517,11 +6492,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6517
6492
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6518
6493
|
);
|
|
6519
6494
|
useEffect17(() => {
|
|
6520
|
-
void
|
|
6521
|
-
const
|
|
6495
|
+
void runStartConversation({ newConversation: false });
|
|
6496
|
+
const persistedConversation = conversationIdSig.value;
|
|
6522
6497
|
let resume = null;
|
|
6523
|
-
if (
|
|
6524
|
-
transport.primeIdentity(visitorId,
|
|
6498
|
+
if (persistedConversation) {
|
|
6499
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6525
6500
|
resume = transport.resumeStream();
|
|
6526
6501
|
void runResume(resume);
|
|
6527
6502
|
}
|
|
@@ -6532,10 +6507,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6532
6507
|
}, []);
|
|
6533
6508
|
const lastUserSig = useRef9(userSig);
|
|
6534
6509
|
useEffect17(() => {
|
|
6535
|
-
if (!
|
|
6510
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6536
6511
|
lastUserSig.current = userSig;
|
|
6537
|
-
void
|
|
6538
|
-
}, [userSig,
|
|
6512
|
+
void runStartConversation({ newConversation: false });
|
|
6513
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6539
6514
|
useEffect17(() => {
|
|
6540
6515
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6541
6516
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6561,14 +6536,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6561
6536
|
}, [isOpen, options.mode]);
|
|
6562
6537
|
const streamAssistant = useCallback6(
|
|
6563
6538
|
async (assistantMsg, trigger) => {
|
|
6564
|
-
const
|
|
6565
|
-
if (!
|
|
6566
|
-
|
|
6567
|
-
persistence.
|
|
6539
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6540
|
+
if (!conversationIdSig.value) {
|
|
6541
|
+
conversationIdSig.value = activeConversationId;
|
|
6542
|
+
persistence.saveConversationId(activeConversationId);
|
|
6568
6543
|
}
|
|
6569
6544
|
const body = buildSendMessageRequest({
|
|
6570
6545
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6571
|
-
|
|
6546
|
+
conversationId: activeConversationId,
|
|
6572
6547
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6573
6548
|
tools: options.features.tools,
|
|
6574
6549
|
responseMode: options.responseMode,
|
|
@@ -6604,7 +6579,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6604
6579
|
messagesSig.value = [...messagesSig.value];
|
|
6605
6580
|
}
|
|
6606
6581
|
},
|
|
6607
|
-
[transport, reducer, messagesSig,
|
|
6582
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6608
6583
|
);
|
|
6609
6584
|
const resolveTool = useCallback6(
|
|
6610
6585
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6660,32 +6635,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6660
6635
|
userContext: () => options.userContext,
|
|
6661
6636
|
messageCount: userMessageCount,
|
|
6662
6637
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6638
|
+
conversationId: () => conversationIdSig.value,
|
|
6663
6639
|
onComplete: (form, trigger, values, skipped) => {
|
|
6664
6640
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6665
6641
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6666
6642
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6667
|
-
const
|
|
6668
|
-
if (!
|
|
6669
|
-
|
|
6670
|
-
persistence.
|
|
6671
|
-
transport.primeIdentity(void 0,
|
|
6643
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6644
|
+
if (!conversationIdSig.value) {
|
|
6645
|
+
conversationIdSig.value = activeConversationId;
|
|
6646
|
+
persistence.saveConversationId(activeConversationId);
|
|
6647
|
+
transport.primeIdentity(void 0, activeConversationId);
|
|
6672
6648
|
}
|
|
6673
6649
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6674
|
-
void transport.submitForm({ formId: form.id,
|
|
6650
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6675
6651
|
}
|
|
6676
6652
|
});
|
|
6677
6653
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6678
6654
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6679
6655
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6680
6656
|
useEffect17(() => {
|
|
6681
|
-
if (
|
|
6682
|
-
}, [
|
|
6657
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6658
|
+
}, [conversationReady, forms]);
|
|
6683
6659
|
useEffect17(() => {
|
|
6684
6660
|
if (!canSend) forms.fire("conversation-closed");
|
|
6685
6661
|
}, [canSend, forms]);
|
|
6686
6662
|
useEffect17(() => {
|
|
6687
|
-
if (pageArea) forms.fire("page-area");
|
|
6688
|
-
}, [pageArea, forms]);
|
|
6663
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6664
|
+
}, [conversationReady, pageArea, forms]);
|
|
6689
6665
|
const idleMs = useMemo3(() => {
|
|
6690
6666
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6691
6667
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6745,16 +6721,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6745
6721
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6746
6722
|
const refreshUnread = useCallback6(() => {
|
|
6747
6723
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6748
|
-
transport.
|
|
6749
|
-
unreadCountSig.value = res.
|
|
6724
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6725
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6750
6726
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6751
6727
|
}, [transport, options.modules, unreadCountSig]);
|
|
6752
6728
|
const unreadSeeded = useRef9(false);
|
|
6753
6729
|
useEffect17(() => {
|
|
6754
|
-
if (!
|
|
6730
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6755
6731
|
unreadSeeded.current = true;
|
|
6756
6732
|
refreshUnread();
|
|
6757
|
-
}, [
|
|
6733
|
+
}, [conversationReady, refreshUnread]);
|
|
6758
6734
|
const handleOpen = useCallback6(() => {
|
|
6759
6735
|
log16.info("open", { mode: options.mode });
|
|
6760
6736
|
feedback.unlock();
|
|
@@ -6773,11 +6749,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6773
6749
|
if (streaming) activeCancel?.();
|
|
6774
6750
|
welcomeAbortRef.current?.abort();
|
|
6775
6751
|
messagesSig.value = [];
|
|
6776
|
-
|
|
6777
|
-
persistence.
|
|
6752
|
+
conversationIdSig.value = void 0;
|
|
6753
|
+
persistence.clearConversation();
|
|
6778
6754
|
setCanSend(true);
|
|
6779
|
-
void
|
|
6780
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6755
|
+
void runStartConversation({ newConversation: true });
|
|
6756
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6781
6757
|
const handleNewChat = useCallback6(() => {
|
|
6782
6758
|
handleClear();
|
|
6783
6759
|
setView("chat");
|
|
@@ -6801,12 +6777,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6801
6777
|
const handlePopOut = useCallback6(() => {
|
|
6802
6778
|
if (!options.popOutUrl) return;
|
|
6803
6779
|
const url = new URL(options.popOutUrl);
|
|
6804
|
-
if (
|
|
6780
|
+
if (conversationIdSig.value) url.searchParams.set("chat", conversationIdSig.value);
|
|
6805
6781
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6806
6782
|
log16.info("popOut", { url: url.toString() });
|
|
6807
6783
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6808
6784
|
bus.emit("popOut", void 0);
|
|
6809
|
-
}, [bus,
|
|
6785
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6810
6786
|
const handleToggleHistory = useCallback6(() => {
|
|
6811
6787
|
setView((v) => {
|
|
6812
6788
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6853,14 +6829,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6853
6829
|
);
|
|
6854
6830
|
const handleSelectHistoryChat = useCallback6(
|
|
6855
6831
|
async (targetChatId) => {
|
|
6856
|
-
log16.info("selectChat", {
|
|
6857
|
-
bus.emit("selectChat", {
|
|
6832
|
+
log16.info("selectChat", { conversationId: targetChatId });
|
|
6833
|
+
bus.emit("selectChat", { conversationId: targetChatId });
|
|
6858
6834
|
try {
|
|
6859
|
-
const res = await transport.
|
|
6835
|
+
const res = await transport.loadConversation(targetChatId);
|
|
6860
6836
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6861
6837
|
messagesSig.value = hydrated;
|
|
6862
|
-
|
|
6863
|
-
persistence.
|
|
6838
|
+
conversationIdSig.value = res.conversationId;
|
|
6839
|
+
persistence.saveConversationId(res.conversationId);
|
|
6864
6840
|
if (res.agent) setAgent(res.agent);
|
|
6865
6841
|
setCanSend(res.canContinue);
|
|
6866
6842
|
setSuggestions(res.suggestions ?? []);
|
|
@@ -6872,7 +6848,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6872
6848
|
options.onError?.(err);
|
|
6873
6849
|
}
|
|
6874
6850
|
},
|
|
6875
|
-
[transport, messagesSig,
|
|
6851
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6876
6852
|
);
|
|
6877
6853
|
useEffect17(() => {
|
|
6878
6854
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6923,48 +6899,47 @@ function App({ options, hostElement, bus }) {
|
|
|
6923
6899
|
bus.emit("suggestion", { text });
|
|
6924
6900
|
void handleSend(text, []);
|
|
6925
6901
|
},
|
|
6926
|
-
// Active form:
|
|
6927
|
-
//
|
|
6928
|
-
|
|
6929
|
-
inlineForm: activeForm.value && !activeForm.value.form.blocking ? activeForm.value.form : null,
|
|
6902
|
+
// Active form: replaces the composer as a gate and locks every chat action
|
|
6903
|
+
// until the visitor submits or (when skippable) skips.
|
|
6904
|
+
activeForm: activeForm.value?.form ?? null,
|
|
6930
6905
|
onFormSubmit: forms.complete,
|
|
6931
6906
|
onFormSkip: forms.skip,
|
|
6932
6907
|
tool: toolInteraction
|
|
6933
6908
|
};
|
|
6934
|
-
const
|
|
6935
|
-
void handleSelectHistoryChat(
|
|
6909
|
+
const onSelectConversation = (conversationId) => {
|
|
6910
|
+
void handleSelectHistoryChat(conversationId);
|
|
6936
6911
|
const chatId = chatTabId();
|
|
6937
6912
|
if (chatId) homeNav.switchTab(chatId);
|
|
6938
6913
|
};
|
|
6939
|
-
if (!
|
|
6914
|
+
if (!conversationReady) return null;
|
|
6940
6915
|
const enabledModules = effectiveOptions.modules.list;
|
|
6941
6916
|
const renderSurface = (size) => {
|
|
6942
6917
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
6943
6918
|
if (enabledModules.length === 0) {
|
|
6944
|
-
return /* @__PURE__ */
|
|
6919
|
+
return /* @__PURE__ */ jsx37(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
6945
6920
|
}
|
|
6946
6921
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
6947
|
-
return /* @__PURE__ */
|
|
6922
|
+
return /* @__PURE__ */ jsx37(Panel, { ...panelProps, panelSize: size });
|
|
6948
6923
|
}
|
|
6949
|
-
return /* @__PURE__ */
|
|
6924
|
+
return /* @__PURE__ */ jsx37(
|
|
6950
6925
|
MessengerHome,
|
|
6951
6926
|
{
|
|
6952
6927
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
6953
6928
|
enabledModules,
|
|
6954
6929
|
nav: homeNav,
|
|
6955
6930
|
unreadCount: unreadCountSig.value,
|
|
6956
|
-
|
|
6957
|
-
|
|
6931
|
+
onSelectConversation,
|
|
6932
|
+
onStartNewConversation: handleNewChat,
|
|
6958
6933
|
onSetPanelSize: setPanelSize
|
|
6959
6934
|
}
|
|
6960
6935
|
);
|
|
6961
6936
|
};
|
|
6962
6937
|
if (options.mode === "page") {
|
|
6963
6938
|
const onSelectChatFromSidebar = (chat) => {
|
|
6964
|
-
void handleSelectHistoryChat(chat.
|
|
6939
|
+
void handleSelectHistoryChat(chat.conversationId);
|
|
6965
6940
|
};
|
|
6966
6941
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6967
|
-
return /* @__PURE__ */
|
|
6942
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
6968
6943
|
PageShell,
|
|
6969
6944
|
{
|
|
6970
6945
|
site: parsedSite,
|
|
@@ -6983,15 +6958,15 @@ function App({ options, hostElement, bus }) {
|
|
|
6983
6958
|
}
|
|
6984
6959
|
if (isInlineLike) {
|
|
6985
6960
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
6986
|
-
return /* @__PURE__ */
|
|
6961
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
6987
6962
|
}
|
|
6988
6963
|
const drawerEdgeTab = options.mode === "drawer";
|
|
6989
6964
|
const triggerOwnedByPage = options.mode === "modal";
|
|
6990
6965
|
const launcherVisible = !triggerOwnedByPage && !options.launcher.hidden && (!isOpen || launcherLeaving);
|
|
6991
6966
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
6992
|
-
return /* @__PURE__ */
|
|
6967
|
+
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
6993
6968
|
isOpen ? renderSurface(panelSize) : null,
|
|
6994
|
-
launcherVisible ? /* @__PURE__ */
|
|
6969
|
+
launcherVisible ? /* @__PURE__ */ jsx37(
|
|
6995
6970
|
Launcher,
|
|
6996
6971
|
{
|
|
6997
6972
|
onToggle: handleOpen,
|
|
@@ -7001,7 +6976,7 @@ function App({ options, hostElement, bus }) {
|
|
|
7001
6976
|
edgeTab: drawerEdgeTab
|
|
7002
6977
|
}
|
|
7003
6978
|
) : null,
|
|
7004
|
-
calloutToRender ? /* @__PURE__ */
|
|
6979
|
+
calloutToRender ? /* @__PURE__ */ jsx37(
|
|
7005
6980
|
LauncherCallout,
|
|
7006
6981
|
{
|
|
7007
6982
|
callout: calloutToRender,
|
|
@@ -7110,7 +7085,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7110
7085
|
/**
|
|
7111
7086
|
* Raw options accumulator. Starts as whatever the page-owner set via
|
|
7112
7087
|
* HTML attributes; gets server-side settings merged in on the
|
|
7113
|
-
* `
|
|
7088
|
+
* `conversationStarted` event so subsequent re-renders pick up the server's
|
|
7114
7089
|
* mode / theme / launcher / etc.
|
|
7115
7090
|
*
|
|
7116
7091
|
* Mirrors `index.ts`'s `rawOptions` so both entry points share the
|
|
@@ -7140,7 +7115,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7140
7115
|
existingHost: this,
|
|
7141
7116
|
position: hostPositionForMode(resolved.mode)
|
|
7142
7117
|
});
|
|
7143
|
-
this.bus.on("
|
|
7118
|
+
this.bus.on("conversationStarted", (response) => {
|
|
7144
7119
|
if (!response.config) return;
|
|
7145
7120
|
this.rawOptions = mergeServerConfig(this.rawOptions, response.config);
|
|
7146
7121
|
this.renderApp();
|
|
@@ -7150,7 +7125,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7150
7125
|
}
|
|
7151
7126
|
/**
|
|
7152
7127
|
* Apply the current `rawOptions` to the host element + App tree.
|
|
7153
|
-
* Called by both the initial boot and every `
|
|
7128
|
+
* Called by both the initial boot and every `conversationStarted` merge.
|
|
7154
7129
|
*/
|
|
7155
7130
|
renderApp() {
|
|
7156
7131
|
if (!this.mountResult) return;
|