@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/index.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",
|
|
@@ -379,7 +377,15 @@ function setLogSink(fn) {
|
|
|
379
377
|
|
|
380
378
|
// src/core/config/user-context.ts
|
|
381
379
|
var log = logger.scope("context");
|
|
382
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
380
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
381
|
+
"visitorId",
|
|
382
|
+
"conversationId",
|
|
383
|
+
"conversationId",
|
|
384
|
+
"jwt",
|
|
385
|
+
"token",
|
|
386
|
+
"authorization",
|
|
387
|
+
"password"
|
|
388
|
+
]);
|
|
383
389
|
var MAX_KEYS = 50;
|
|
384
390
|
var MAX_STRING = 1024;
|
|
385
391
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -624,7 +630,6 @@ function resolveModules(overrides) {
|
|
|
624
630
|
const byId = Object.fromEntries(list.map((m) => [m.id, m]));
|
|
625
631
|
return { list, byId };
|
|
626
632
|
}
|
|
627
|
-
var BLOCKABLE_KINDS = /* @__PURE__ */ new Set(["pre-chat", "after-messages"]);
|
|
628
633
|
function resolveForms(overrides) {
|
|
629
634
|
var _a;
|
|
630
635
|
if (!overrides?.length) return DEFAULT_FORMS;
|
|
@@ -636,7 +641,6 @@ function resolveForms(overrides) {
|
|
|
636
641
|
const triggers = (Array.isArray(def.on) ? def.on : [def.on]).map(parseTrigger).filter((t) => t !== null);
|
|
637
642
|
if (fields.length === 0 || triggers.length === 0) continue;
|
|
638
643
|
seen.add(def.id);
|
|
639
|
-
const blockable = triggers.some((t) => BLOCKABLE_KINDS.has(t.kind));
|
|
640
644
|
list.push({
|
|
641
645
|
id: def.id,
|
|
642
646
|
triggers,
|
|
@@ -646,7 +650,6 @@ function resolveForms(overrides) {
|
|
|
646
650
|
description: def.description,
|
|
647
651
|
submitLabel: def.submitLabel,
|
|
648
652
|
skippable: def.skippable ?? false,
|
|
649
|
-
blocking: (def.blocking ?? false) && blockable,
|
|
650
653
|
frequency: def.frequency ?? "once",
|
|
651
654
|
mirrorToContext: def.mirrorToContext ?? true
|
|
652
655
|
});
|
|
@@ -871,7 +874,7 @@ var REACTIVE_ATTRS = [
|
|
|
871
874
|
...SPECIAL_REACTIVE_ATTRS
|
|
872
875
|
];
|
|
873
876
|
|
|
874
|
-
// src/core/start-
|
|
877
|
+
// src/core/start-conversation-shape.ts
|
|
875
878
|
function isPlainObject(raw) {
|
|
876
879
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
877
880
|
}
|
|
@@ -912,7 +915,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
912
915
|
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';
|
|
913
916
|
|
|
914
917
|
// src/styles/panel.css
|
|
915
|
-
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';
|
|
918
|
+
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';
|
|
916
919
|
|
|
917
920
|
// src/styles/standalone.css
|
|
918
921
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1000,22 +1003,22 @@ function attachAdoptedSheet(shadow, doc) {
|
|
|
1000
1003
|
}
|
|
1001
1004
|
}
|
|
1002
1005
|
function applyThemeOverrides(host, overrides) {
|
|
1003
|
-
const
|
|
1004
|
-
if (overrides.accent) host.style.setProperty(`--${
|
|
1005
|
-
if (overrides.accentText) host.style.setProperty(`--${
|
|
1006
|
-
if (overrides.radius) host.style.setProperty(`--${
|
|
1007
|
-
if (overrides.fontFamily) host.style.setProperty(`--${
|
|
1006
|
+
const p33 = BRAND.cssPrefix;
|
|
1007
|
+
if (overrides.accent) host.style.setProperty(`--${p33}-accent`, overrides.accent);
|
|
1008
|
+
if (overrides.accentText) host.style.setProperty(`--${p33}-accent-text`, overrides.accentText);
|
|
1009
|
+
if (overrides.radius) host.style.setProperty(`--${p33}-radius`, overrides.radius);
|
|
1010
|
+
if (overrides.fontFamily) host.style.setProperty(`--${p33}-font`, overrides.fontFamily);
|
|
1008
1011
|
}
|
|
1009
1012
|
function applyThemeMode(host, mode) {
|
|
1010
1013
|
host.dataset.theme = mode;
|
|
1011
1014
|
}
|
|
1012
1015
|
function applySize(host, size) {
|
|
1013
|
-
const
|
|
1014
|
-
if (size.width !== void 0) host.style.setProperty(`--${
|
|
1015
|
-
if (size.height !== void 0) host.style.setProperty(`--${
|
|
1016
|
-
if (size.expanded?.width !== void 0) host.style.setProperty(`--${
|
|
1017
|
-
if (size.expanded?.height !== void 0) host.style.setProperty(`--${
|
|
1018
|
-
if (size.inset !== void 0) host.style.setProperty(`--${
|
|
1016
|
+
const p33 = BRAND.cssPrefix;
|
|
1017
|
+
if (size.width !== void 0) host.style.setProperty(`--${p33}-panel-w`, size.width);
|
|
1018
|
+
if (size.height !== void 0) host.style.setProperty(`--${p33}-panel-h`, size.height);
|
|
1019
|
+
if (size.expanded?.width !== void 0) host.style.setProperty(`--${p33}-expanded-w`, size.expanded.width);
|
|
1020
|
+
if (size.expanded?.height !== void 0) host.style.setProperty(`--${p33}-expanded-h`, size.expanded.height);
|
|
1021
|
+
if (size.inset !== void 0) host.style.setProperty(`--${p33}-panel-inset`, size.inset);
|
|
1019
1022
|
}
|
|
1020
1023
|
function applyPosition(host, pos) {
|
|
1021
1024
|
host.dataset.position = pos;
|
|
@@ -1186,18 +1189,18 @@ function toBase64Url(json) {
|
|
|
1186
1189
|
var nonEmpty = (ctx) => ctx && Object.keys(ctx).length > 0 ? ctx : void 0;
|
|
1187
1190
|
function encodeContext(user, page) {
|
|
1188
1191
|
const u = nonEmpty(user);
|
|
1189
|
-
const
|
|
1190
|
-
if (!u && !
|
|
1192
|
+
const p33 = nonEmpty(page);
|
|
1193
|
+
if (!u && !p33) return void 0;
|
|
1191
1194
|
const envelope = {};
|
|
1192
1195
|
if (u) envelope.user = u;
|
|
1193
|
-
if (
|
|
1196
|
+
if (p33) envelope.page = p33;
|
|
1194
1197
|
return toBase64Url(JSON.stringify(envelope));
|
|
1195
1198
|
}
|
|
1196
1199
|
|
|
1197
1200
|
// src/stream/protocol.ts
|
|
1198
1201
|
var DEFAULT_PATHS = {
|
|
1199
|
-
/**
|
|
1200
|
-
|
|
1202
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1203
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1201
1204
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1202
1205
|
streamMessage: "/ai/agent/stream-message",
|
|
1203
1206
|
/**
|
|
@@ -1210,20 +1213,20 @@ var DEFAULT_PATHS = {
|
|
|
1210
1213
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1211
1214
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1212
1215
|
/** List the visitor's conversations. `GET`. */
|
|
1213
|
-
|
|
1214
|
-
/** Load one conversation's messages. `GET ?
|
|
1216
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1217
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1215
1218
|
listMessages: "/ai/agent/list-messages",
|
|
1216
1219
|
/**
|
|
1217
1220
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1218
1221
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1219
1222
|
* the client — a failure leaves the local cache valid; the next
|
|
1220
|
-
* `
|
|
1223
|
+
* `startConversation()` reconciles.
|
|
1221
1224
|
*/
|
|
1222
1225
|
updateSettings: "/ai/agent/update-settings",
|
|
1223
1226
|
/**
|
|
1224
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1225
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1226
|
-
* `unreadCount` (returned on `/list-
|
|
1227
|
+
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1228
|
+
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1229
|
+
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1227
1230
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1228
1231
|
*/
|
|
1229
1232
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1232,8 +1235,8 @@ var DEFAULT_PATHS = {
|
|
|
1232
1235
|
content: "/ai/agent/content",
|
|
1233
1236
|
/**
|
|
1234
1237
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1235
|
-
*
|
|
1236
|
-
* immediately, keyed by the same visitor +
|
|
1238
|
+
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1239
|
+
* immediately, keyed by the same visitor + conversation as the conversation.
|
|
1237
1240
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1238
1241
|
*/
|
|
1239
1242
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1248,7 +1251,7 @@ function buildSendMessageRequest(params) {
|
|
|
1248
1251
|
}));
|
|
1249
1252
|
const body = {
|
|
1250
1253
|
messages: wire,
|
|
1251
|
-
|
|
1254
|
+
conversationId: params.conversationId,
|
|
1252
1255
|
trigger: params.trigger ?? "submit-message"
|
|
1253
1256
|
};
|
|
1254
1257
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1260,8 +1263,8 @@ function buildSendMessageRequest(params) {
|
|
|
1260
1263
|
if (Object.keys(data).length > 0) body.data = data;
|
|
1261
1264
|
return body;
|
|
1262
1265
|
}
|
|
1263
|
-
function isResolvedToolPart(
|
|
1264
|
-
return
|
|
1266
|
+
function isResolvedToolPart(p33) {
|
|
1267
|
+
return p33.state === "output" || p33.state === "error" || p33.approval?.approved !== void 0;
|
|
1265
1268
|
}
|
|
1266
1269
|
function normalizeToolRef(ref) {
|
|
1267
1270
|
if (typeof ref === "string") return ref ? { code: ref } : null;
|
|
@@ -1269,24 +1272,24 @@ function normalizeToolRef(ref) {
|
|
|
1269
1272
|
}
|
|
1270
1273
|
function messageToWireParts(m) {
|
|
1271
1274
|
const out = [];
|
|
1272
|
-
for (const
|
|
1273
|
-
if (
|
|
1274
|
-
out.push({ text:
|
|
1275
|
+
for (const p33 of m.parts) {
|
|
1276
|
+
if (p33.kind === "text" && p33.text) {
|
|
1277
|
+
out.push({ text: p33.text, type: "text" });
|
|
1275
1278
|
}
|
|
1276
|
-
if (
|
|
1277
|
-
out.push({ mediaType:
|
|
1279
|
+
if (p33.kind === "file" && p33.url) {
|
|
1280
|
+
out.push({ mediaType: p33.mediaType, type: "file", url: p33.url });
|
|
1278
1281
|
}
|
|
1279
|
-
if (
|
|
1282
|
+
if (p33.kind === "tool" && isResolvedToolPart(p33)) {
|
|
1280
1283
|
const part = {
|
|
1281
1284
|
type: "tool",
|
|
1282
|
-
toolCallId:
|
|
1283
|
-
toolName:
|
|
1284
|
-
state:
|
|
1285
|
+
toolCallId: p33.toolCallId,
|
|
1286
|
+
toolName: p33.toolName,
|
|
1287
|
+
state: p33.state
|
|
1285
1288
|
};
|
|
1286
|
-
if (
|
|
1287
|
-
if (
|
|
1288
|
-
if (
|
|
1289
|
-
if (
|
|
1289
|
+
if (p33.input !== void 0) part.input = p33.input;
|
|
1290
|
+
if (p33.output !== void 0) part.output = p33.output;
|
|
1291
|
+
if (p33.error !== void 0) part.errorText = p33.error;
|
|
1292
|
+
if (p33.approval && p33.approval.approved !== void 0) part.approval = p33.approval;
|
|
1290
1293
|
out.push(part);
|
|
1291
1294
|
}
|
|
1292
1295
|
}
|
|
@@ -1336,11 +1339,11 @@ function sleep(ms, signal7) {
|
|
|
1336
1339
|
var AgentTransport = class {
|
|
1337
1340
|
constructor(opts) {
|
|
1338
1341
|
__publicField(this, "opts", opts);
|
|
1339
|
-
// Identity adopted from the start-
|
|
1342
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1340
1343
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1341
|
-
// (visitor,
|
|
1344
|
+
// (visitor, conversation) pair.
|
|
1342
1345
|
__publicField(this, "visitorId");
|
|
1343
|
-
__publicField(this, "
|
|
1346
|
+
__publicField(this, "conversationId");
|
|
1344
1347
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1345
1348
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1346
1349
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1358,27 +1361,27 @@ var AgentTransport = class {
|
|
|
1358
1361
|
this.pageContext = pageContext;
|
|
1359
1362
|
}
|
|
1360
1363
|
/**
|
|
1361
|
-
* Seed the visitor +
|
|
1362
|
-
* `
|
|
1363
|
-
* with `
|
|
1364
|
-
* `
|
|
1364
|
+
* Seed the visitor + conversation identity from persistence BEFORE the first
|
|
1365
|
+
* `startConversation` resolves. A mount-time `resumeStream()` runs in parallel
|
|
1366
|
+
* with `startConversation`, so without this its envelope would carry no
|
|
1367
|
+
* `conversationId` and the resume GET couldn't identify the thread. `startConversation`
|
|
1365
1368
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1366
1369
|
*/
|
|
1367
|
-
primeIdentity(visitorId,
|
|
1370
|
+
primeIdentity(visitorId, conversationId) {
|
|
1368
1371
|
if (visitorId) this.visitorId = visitorId;
|
|
1369
|
-
if (
|
|
1372
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1370
1373
|
}
|
|
1371
1374
|
/** Build the per-request envelope from the current transport state. */
|
|
1372
1375
|
envelope() {
|
|
1373
1376
|
const out = {};
|
|
1374
1377
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1375
|
-
if (this.
|
|
1378
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1376
1379
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1377
1380
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1378
1381
|
return out;
|
|
1379
1382
|
}
|
|
1380
1383
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1381
|
-
* start-
|
|
1384
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1382
1385
|
* differs from the active one. */
|
|
1383
1386
|
withEnvelope(body) {
|
|
1384
1387
|
return { ...this.envelope(), ...body };
|
|
@@ -1389,8 +1392,8 @@ var AgentTransport = class {
|
|
|
1389
1392
|
return form;
|
|
1390
1393
|
}
|
|
1391
1394
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1392
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1393
|
-
* selector on load-
|
|
1395
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1396
|
+
* selector on load-conversation). */
|
|
1394
1397
|
withEnvelopeQuery(urlOrPath) {
|
|
1395
1398
|
const url = new URL(this.url(urlOrPath));
|
|
1396
1399
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1399,23 +1402,31 @@ var AgentTransport = class {
|
|
|
1399
1402
|
return url.toString();
|
|
1400
1403
|
}
|
|
1401
1404
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1402
|
-
async
|
|
1403
|
-
log4.debug("
|
|
1404
|
-
|
|
1405
|
-
|
|
1405
|
+
async startConversation(body) {
|
|
1406
|
+
log4.debug("startConversation \u2192", {
|
|
1407
|
+
visitorId: body.visitorId,
|
|
1408
|
+
conversationId: body.conversationId,
|
|
1409
|
+
locale: body.locale
|
|
1410
|
+
});
|
|
1411
|
+
const res = await this.postJson(
|
|
1412
|
+
DEFAULT_PATHS.startConversation,
|
|
1413
|
+
body,
|
|
1414
|
+
"startConversation"
|
|
1415
|
+
);
|
|
1416
|
+
log4.debug("startConversation \u2190", {
|
|
1406
1417
|
visitorId: res.visitorId,
|
|
1407
|
-
|
|
1418
|
+
conversationId: res.conversationId,
|
|
1408
1419
|
canContinue: res.canContinue,
|
|
1409
1420
|
hasMessages: !!res.messages?.length,
|
|
1410
1421
|
hasWelcome: !!res.welcome,
|
|
1411
1422
|
hasConfig: !!res.config,
|
|
1412
1423
|
rebind: res.rebind
|
|
1413
1424
|
});
|
|
1414
|
-
if (!
|
|
1415
|
-
log4.warn("
|
|
1425
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1426
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1416
1427
|
}
|
|
1417
1428
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1418
|
-
this.
|
|
1429
|
+
this.conversationId = res.conversationId;
|
|
1419
1430
|
return res;
|
|
1420
1431
|
}
|
|
1421
1432
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1440,45 +1451,45 @@ var AgentTransport = class {
|
|
|
1440
1451
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1441
1452
|
return res;
|
|
1442
1453
|
}
|
|
1443
|
-
async
|
|
1444
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1454
|
+
async listConversations(params = {}) {
|
|
1455
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1445
1456
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1446
1457
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1447
1458
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1448
|
-
log4.debug("
|
|
1459
|
+
log4.debug("listConversations \u2192", {
|
|
1449
1460
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1450
1461
|
limit: params.limit,
|
|
1451
1462
|
cursor: params.cursor
|
|
1452
1463
|
});
|
|
1453
|
-
const res = await this.getJson(url.toString(), "
|
|
1454
|
-
const
|
|
1455
|
-
log4.debug("
|
|
1464
|
+
const res = await this.getJson(url.toString(), "listConversations");
|
|
1465
|
+
const conversations = res.conversations ?? [];
|
|
1466
|
+
log4.debug("listConversations \u2190", { count: conversations.length, nextCursor: res.nextCursor });
|
|
1456
1467
|
return {
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
title:
|
|
1460
|
-
lastMessageAt:
|
|
1461
|
-
preview:
|
|
1462
|
-
canContinue:
|
|
1463
|
-
unreadCount:
|
|
1468
|
+
conversations: conversations.map((conversation) => ({
|
|
1469
|
+
conversationId: conversation.conversationId,
|
|
1470
|
+
title: conversation.title,
|
|
1471
|
+
lastMessageAt: conversation.lastMessageAt,
|
|
1472
|
+
preview: conversation.preview,
|
|
1473
|
+
canContinue: conversation.canContinue,
|
|
1474
|
+
unreadCount: conversation.unreadCount
|
|
1464
1475
|
})),
|
|
1465
1476
|
nextCursor: res.nextCursor
|
|
1466
1477
|
};
|
|
1467
1478
|
}
|
|
1468
|
-
async
|
|
1479
|
+
async loadConversation(conversationId) {
|
|
1469
1480
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1470
|
-
url.searchParams.set("
|
|
1471
|
-
log4.debug("
|
|
1472
|
-
const res = await this.getJson(url.toString(), "
|
|
1481
|
+
url.searchParams.set("conversationId", conversationId);
|
|
1482
|
+
log4.debug("loadConversation \u2192", { conversationId, visitorId: this.visitorId });
|
|
1483
|
+
const res = await this.getJson(url.toString(), "loadConversation");
|
|
1473
1484
|
const messages = res.messages ?? [];
|
|
1474
|
-
log4.debug("
|
|
1475
|
-
|
|
1485
|
+
log4.debug("loadConversation \u2190", {
|
|
1486
|
+
conversationId: res.conversationId,
|
|
1476
1487
|
canContinue: res.canContinue,
|
|
1477
1488
|
messageCount: messages.length,
|
|
1478
1489
|
hasSuggestions: !!res.suggestions
|
|
1479
1490
|
});
|
|
1480
1491
|
return {
|
|
1481
|
-
|
|
1492
|
+
conversationId: res.conversationId,
|
|
1482
1493
|
canContinue: res.canContinue ?? true,
|
|
1483
1494
|
messages,
|
|
1484
1495
|
agent: res.agent,
|
|
@@ -1487,15 +1498,15 @@ var AgentTransport = class {
|
|
|
1487
1498
|
}
|
|
1488
1499
|
/**
|
|
1489
1500
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1490
|
-
* server records `lastReadAt` and clears that
|
|
1491
|
-
* next `/
|
|
1501
|
+
* server records `lastReadAt` and clears that conversation's `unreadCount` on the
|
|
1502
|
+
* next `/conversations`. A failure is non-fatal (the badge just lingers until the
|
|
1492
1503
|
* next sync), so callers don't await this.
|
|
1493
1504
|
*/
|
|
1494
|
-
async markRead(
|
|
1495
|
-
if (!this.visitorId || !
|
|
1496
|
-
log4.debug("markRead \u2192", {
|
|
1505
|
+
async markRead(conversationId) {
|
|
1506
|
+
if (!this.visitorId || !conversationId) return;
|
|
1507
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1497
1508
|
try {
|
|
1498
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1509
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1499
1510
|
} catch (err) {
|
|
1500
1511
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1501
1512
|
}
|
|
@@ -1521,7 +1532,7 @@ var AgentTransport = class {
|
|
|
1521
1532
|
async saveUserPrefs(userPrefs) {
|
|
1522
1533
|
log4.debug("saveUserPrefs \u2192", {
|
|
1523
1534
|
visitorId: this.visitorId,
|
|
1524
|
-
|
|
1535
|
+
conversationId: this.conversationId,
|
|
1525
1536
|
settingsKeys: Object.keys(userPrefs)
|
|
1526
1537
|
});
|
|
1527
1538
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1539,7 +1550,7 @@ var AgentTransport = class {
|
|
|
1539
1550
|
}
|
|
1540
1551
|
/**
|
|
1541
1552
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1542
|
-
* record is captured even if the visitor never sends a message. `
|
|
1553
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1543
1554
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1544
1555
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1545
1556
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1554,7 +1565,7 @@ var AgentTransport = class {
|
|
|
1554
1565
|
}
|
|
1555
1566
|
sendMessage(body) {
|
|
1556
1567
|
log4.debug("message \u2192", {
|
|
1557
|
-
|
|
1568
|
+
conversationId: body.conversationId,
|
|
1558
1569
|
visitorId: body.visitorId,
|
|
1559
1570
|
messageCount: body.messages.length,
|
|
1560
1571
|
trigger: body.trigger,
|
|
@@ -1564,16 +1575,16 @@ var AgentTransport = class {
|
|
|
1564
1575
|
const ctrl = new AbortController();
|
|
1565
1576
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1566
1577
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1567
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1578
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1568
1579
|
return { iter, cancel };
|
|
1569
1580
|
}
|
|
1570
1581
|
/**
|
|
1571
1582
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1572
1583
|
*
|
|
1573
1584
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1574
|
-
* `
|
|
1585
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1575
1586
|
* the user refreshed while the assistant was still streaming, the
|
|
1576
|
-
* `
|
|
1587
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1577
1588
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1578
1589
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1579
1590
|
* (the common case — no bubble is created).
|
|
@@ -1600,7 +1611,7 @@ var AgentTransport = class {
|
|
|
1600
1611
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1601
1612
|
* off first, the reply may still be spinning up server-side);
|
|
1602
1613
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1603
|
-
* parallel with start-
|
|
1614
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1604
1615
|
* user reloaded keeps flowing).
|
|
1605
1616
|
*
|
|
1606
1617
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1609,7 +1620,7 @@ var AgentTransport = class {
|
|
|
1609
1620
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1610
1621
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1611
1622
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1612
|
-
* turn comes from the DB via start-
|
|
1623
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1613
1624
|
*
|
|
1614
1625
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1615
1626
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1675,11 +1686,11 @@ var AgentTransport = class {
|
|
|
1675
1686
|
return false;
|
|
1676
1687
|
}
|
|
1677
1688
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1678
|
-
cancelStream(ctrl,
|
|
1689
|
+
cancelStream(ctrl, conversationId) {
|
|
1679
1690
|
if (ctrl.signal.aborted) return;
|
|
1680
|
-
log4.debug("cancel stream", {
|
|
1691
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1681
1692
|
ctrl.abort();
|
|
1682
|
-
if (!this.visitorId || !
|
|
1693
|
+
if (!this.visitorId || !conversationId) return;
|
|
1683
1694
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1684
1695
|
method: "POST",
|
|
1685
1696
|
credentials: "omit",
|
|
@@ -1704,7 +1715,7 @@ var AgentTransport = class {
|
|
|
1704
1715
|
yield* parseChatStream(res, signal7);
|
|
1705
1716
|
}
|
|
1706
1717
|
/**
|
|
1707
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1718
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1708
1719
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1709
1720
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1710
1721
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1715,7 +1726,7 @@ var AgentTransport = class {
|
|
|
1715
1726
|
return url.toString();
|
|
1716
1727
|
}
|
|
1717
1728
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1718
|
-
// update-settings / mark-read / start-
|
|
1729
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1719
1730
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1720
1731
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1721
1732
|
async postJson(path, body, label) {
|
|
@@ -1799,10 +1810,10 @@ function extensionFor(mimeType) {
|
|
|
1799
1810
|
if (mimeType.includes("wav")) return "wav";
|
|
1800
1811
|
return "bin";
|
|
1801
1812
|
}
|
|
1802
|
-
function
|
|
1813
|
+
function isStartConversationResponseShape(raw) {
|
|
1803
1814
|
if (!raw || typeof raw !== "object") return false;
|
|
1804
1815
|
const r = raw;
|
|
1805
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1816
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1806
1817
|
}
|
|
1807
1818
|
|
|
1808
1819
|
// src/stream/messages.ts
|
|
@@ -1879,7 +1890,7 @@ function fromWireMessage(w) {
|
|
|
1879
1890
|
};
|
|
1880
1891
|
}
|
|
1881
1892
|
return null;
|
|
1882
|
-
}).filter((
|
|
1893
|
+
}).filter((p33) => p33 !== null);
|
|
1883
1894
|
return {
|
|
1884
1895
|
id: w.id,
|
|
1885
1896
|
role: w.role,
|
|
@@ -1909,43 +1920,43 @@ function assistantText(m) {
|
|
|
1909
1920
|
}
|
|
1910
1921
|
return out;
|
|
1911
1922
|
}
|
|
1912
|
-
function partToReactive(
|
|
1913
|
-
if (
|
|
1914
|
-
return { kind:
|
|
1923
|
+
function partToReactive(p33) {
|
|
1924
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1925
|
+
return { kind: p33.kind, id: p33.id, textSig: signal(p33.text), doneSig: signal(p33.done) };
|
|
1915
1926
|
}
|
|
1916
|
-
if (
|
|
1927
|
+
if (p33.kind === "tool") {
|
|
1917
1928
|
return {
|
|
1918
1929
|
kind: "tool",
|
|
1919
|
-
toolCallId:
|
|
1920
|
-
toolName:
|
|
1921
|
-
inputPartialSig: signal(
|
|
1922
|
-
inputSig: signal(
|
|
1923
|
-
outputSig: signal(
|
|
1924
|
-
errorSig: signal(
|
|
1925
|
-
stateSig: signal(
|
|
1926
|
-
approvalSig: signal(
|
|
1930
|
+
toolCallId: p33.toolCallId,
|
|
1931
|
+
toolName: p33.toolName,
|
|
1932
|
+
inputPartialSig: signal(p33.inputPartial),
|
|
1933
|
+
inputSig: signal(p33.input),
|
|
1934
|
+
outputSig: signal(p33.output),
|
|
1935
|
+
errorSig: signal(p33.error),
|
|
1936
|
+
stateSig: signal(p33.state),
|
|
1937
|
+
approvalSig: signal(p33.approval)
|
|
1927
1938
|
};
|
|
1928
1939
|
}
|
|
1929
|
-
return
|
|
1940
|
+
return p33;
|
|
1930
1941
|
}
|
|
1931
|
-
function partFromReactive(
|
|
1932
|
-
if (
|
|
1933
|
-
return { kind:
|
|
1942
|
+
function partFromReactive(p33) {
|
|
1943
|
+
if (p33.kind === "text" || p33.kind === "reasoning") {
|
|
1944
|
+
return { kind: p33.kind, id: p33.id, text: p33.textSig.value, done: p33.doneSig.value };
|
|
1934
1945
|
}
|
|
1935
|
-
if (
|
|
1946
|
+
if (p33.kind === "tool") {
|
|
1936
1947
|
return {
|
|
1937
1948
|
kind: "tool",
|
|
1938
|
-
toolCallId:
|
|
1939
|
-
toolName:
|
|
1940
|
-
inputPartial:
|
|
1941
|
-
input:
|
|
1942
|
-
output:
|
|
1943
|
-
error:
|
|
1944
|
-
state:
|
|
1945
|
-
approval:
|
|
1949
|
+
toolCallId: p33.toolCallId,
|
|
1950
|
+
toolName: p33.toolName,
|
|
1951
|
+
inputPartial: p33.inputPartialSig.value,
|
|
1952
|
+
input: p33.inputSig.value,
|
|
1953
|
+
output: p33.outputSig.value,
|
|
1954
|
+
error: p33.errorSig.value,
|
|
1955
|
+
state: p33.stateSig.value,
|
|
1956
|
+
approval: p33.approvalSig.value
|
|
1946
1957
|
};
|
|
1947
1958
|
}
|
|
1948
|
-
return
|
|
1959
|
+
return p33;
|
|
1949
1960
|
}
|
|
1950
1961
|
|
|
1951
1962
|
// src/stream/reducer.ts
|
|
@@ -2000,8 +2011,8 @@ var StreamReducer = class {
|
|
|
2000
2011
|
ensureTextPart(m, "text", chunk.id);
|
|
2001
2012
|
return;
|
|
2002
2013
|
case "text-delta": {
|
|
2003
|
-
const
|
|
2004
|
-
|
|
2014
|
+
const p33 = ensureTextPart(m, "text", chunk.id);
|
|
2015
|
+
p33.textSig.value += chunk.delta;
|
|
2005
2016
|
return;
|
|
2006
2017
|
}
|
|
2007
2018
|
case "text-end":
|
|
@@ -2011,8 +2022,8 @@ var StreamReducer = class {
|
|
|
2011
2022
|
ensureTextPart(m, "reasoning", chunk.id).doneSig.value = false;
|
|
2012
2023
|
return;
|
|
2013
2024
|
case "reasoning-delta": {
|
|
2014
|
-
const
|
|
2015
|
-
|
|
2025
|
+
const p33 = ensureTextPart(m, "reasoning", chunk.id);
|
|
2026
|
+
p33.textSig.value += chunk.delta;
|
|
2016
2027
|
return;
|
|
2017
2028
|
}
|
|
2018
2029
|
case "reasoning-end":
|
|
@@ -2031,7 +2042,7 @@ var StreamReducer = class {
|
|
|
2031
2042
|
return;
|
|
2032
2043
|
case "source-url": {
|
|
2033
2044
|
const parts = m.partsSig.value;
|
|
2034
|
-
if (parts.some((
|
|
2045
|
+
if (parts.some((p33) => p33.kind === "source" && p33.sourceId === chunk.sourceId)) return;
|
|
2035
2046
|
appendPart(m, { kind: "source", sourceId: chunk.sourceId, url: chunk.url, title: chunk.title });
|
|
2036
2047
|
return;
|
|
2037
2048
|
}
|
|
@@ -2055,14 +2066,14 @@ var StreamReducer = class {
|
|
|
2055
2066
|
}
|
|
2056
2067
|
};
|
|
2057
2068
|
function ensureTextPart(m, kind, id) {
|
|
2058
|
-
const existing = m.partsSig.value.find((
|
|
2069
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === kind && p33.id === id);
|
|
2059
2070
|
if (existing) return existing;
|
|
2060
2071
|
const part = { kind, id, textSig: signal2(""), doneSig: signal2(false) };
|
|
2061
2072
|
appendPart(m, part);
|
|
2062
2073
|
return part;
|
|
2063
2074
|
}
|
|
2064
2075
|
function ensureToolPart(m, toolCallId, toolName) {
|
|
2065
|
-
const existing = m.partsSig.value.find((
|
|
2076
|
+
const existing = m.partsSig.value.find((p33) => p33.kind === "tool" && p33.toolCallId === toolCallId);
|
|
2066
2077
|
if (existing) return existing;
|
|
2067
2078
|
const part = {
|
|
2068
2079
|
kind: "tool",
|
|
@@ -2087,32 +2098,32 @@ function applyTool(m, chunk) {
|
|
|
2087
2098
|
ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2088
2099
|
return;
|
|
2089
2100
|
case "tool-input-delta": {
|
|
2090
|
-
const
|
|
2091
|
-
|
|
2101
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2102
|
+
p33.inputPartialSig.value += chunk.delta;
|
|
2092
2103
|
return;
|
|
2093
2104
|
}
|
|
2094
2105
|
case "tool-input-available": {
|
|
2095
|
-
const
|
|
2096
|
-
|
|
2097
|
-
|
|
2106
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2107
|
+
p33.inputSig.value = chunk.input;
|
|
2108
|
+
p33.stateSig.value = isAskUserInputTool(p33.toolName) ? "awaiting-input" : "awaiting";
|
|
2098
2109
|
return;
|
|
2099
2110
|
}
|
|
2100
2111
|
case "tool-approval-request": {
|
|
2101
|
-
const
|
|
2102
|
-
|
|
2103
|
-
|
|
2112
|
+
const p33 = ensureToolPart(m, chunk.toolCallId, chunk.toolName);
|
|
2113
|
+
p33.approvalSig.value = { id: chunk.approvalId };
|
|
2114
|
+
p33.stateSig.value = "awaiting-approval";
|
|
2104
2115
|
return;
|
|
2105
2116
|
}
|
|
2106
2117
|
case "tool-output-available": {
|
|
2107
|
-
const
|
|
2108
|
-
|
|
2109
|
-
|
|
2118
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2119
|
+
p33.outputSig.value = chunk.output;
|
|
2120
|
+
p33.stateSig.value = "output";
|
|
2110
2121
|
return;
|
|
2111
2122
|
}
|
|
2112
2123
|
case "tool-output-error": {
|
|
2113
|
-
const
|
|
2114
|
-
|
|
2115
|
-
|
|
2124
|
+
const p33 = ensureToolPart(m, chunk.toolCallId);
|
|
2125
|
+
p33.errorSig.value = chunk.errorText;
|
|
2126
|
+
p33.stateSig.value = "error";
|
|
2116
2127
|
return;
|
|
2117
2128
|
}
|
|
2118
2129
|
default:
|
|
@@ -2125,7 +2136,7 @@ var log6 = logger.scope("persistence");
|
|
|
2125
2136
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2126
2137
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2127
2138
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2128
|
-
const
|
|
2139
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2129
2140
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2130
2141
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2131
2142
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2145,13 +2156,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2145
2156
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2146
2157
|
storage.set(KEY_VISITOR, id);
|
|
2147
2158
|
},
|
|
2148
|
-
|
|
2149
|
-
return storage.get(
|
|
2159
|
+
loadConversationId() {
|
|
2160
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2150
2161
|
},
|
|
2151
|
-
|
|
2152
|
-
log6.trace("
|
|
2153
|
-
if (id) storage.set(
|
|
2154
|
-
else storage.remove(
|
|
2162
|
+
saveConversationId(id) {
|
|
2163
|
+
log6.trace("saveConversationId", { id, widgetId });
|
|
2164
|
+
if (id) storage.set(KEY_CONVERSATION, id);
|
|
2165
|
+
else storage.remove(KEY_CONVERSATION);
|
|
2155
2166
|
},
|
|
2156
2167
|
loadUserPrefs() {
|
|
2157
2168
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2235,8 +2246,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2235
2246
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2236
2247
|
}
|
|
2237
2248
|
},
|
|
2238
|
-
|
|
2239
|
-
storage.remove(
|
|
2249
|
+
clearConversation() {
|
|
2250
|
+
storage.remove(KEY_CONVERSATION);
|
|
2240
2251
|
}
|
|
2241
2252
|
};
|
|
2242
2253
|
return persistence;
|
|
@@ -2418,7 +2429,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2418
2429
|
var FeedbackBus = class {
|
|
2419
2430
|
constructor(sound, haptics) {
|
|
2420
2431
|
/**
|
|
2421
|
-
* User/
|
|
2432
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2422
2433
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2423
2434
|
* `Persistence` layer.
|
|
2424
2435
|
*/
|
|
@@ -2736,7 +2747,7 @@ var TID = {
|
|
|
2736
2747
|
historyPane: `${p2}-history-pane`,
|
|
2737
2748
|
/** History pane back / close button. */
|
|
2738
2749
|
historyBack: `${p2}-history-back`,
|
|
2739
|
-
/** Single history list row — suffix `-{
|
|
2750
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2740
2751
|
historyItem: `${p2}-history-item`,
|
|
2741
2752
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2742
2753
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
@@ -2745,7 +2756,7 @@ var TID = {
|
|
|
2745
2756
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2746
2757
|
/** Sidebar "New chat" button. */
|
|
2747
2758
|
sidebarNewChat: `${p2}-sidebar-new-chat`,
|
|
2748
|
-
/** Sidebar history row — suffix `-{
|
|
2759
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2749
2760
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2750
2761
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2751
2762
|
/** Messenger-home surface root. */
|
|
@@ -2778,16 +2789,12 @@ var TID = {
|
|
|
2778
2789
|
/** News list item — suffix `-{id}`. */
|
|
2779
2790
|
newsItem: `${p2}-news-item`,
|
|
2780
2791
|
// ── Forms + human-in-the-loop (forms / ask-input / approval) ─────
|
|
2781
|
-
/**
|
|
2792
|
+
/** Form gate root (replaces the composer, locking the chat). */
|
|
2782
2793
|
formGate: `${p2}-form-gate`,
|
|
2783
|
-
/** Inline form card root (in the transcript). */
|
|
2784
|
-
formCard: `${p2}-form-card`,
|
|
2785
2794
|
/** Form submit button. */
|
|
2786
2795
|
formSubmit: `${p2}-form-submit`,
|
|
2787
|
-
/** Form skip button (
|
|
2796
|
+
/** Form skip button (shown only when `skippable`). */
|
|
2788
2797
|
formSkip: `${p2}-form-skip`,
|
|
2789
|
-
/** Inline form-card dismiss button. */
|
|
2790
|
-
formDismiss: `${p2}-form-dismiss`,
|
|
2791
2798
|
/** A single form field control — suffix `-{name}` at the JSX site. */
|
|
2792
2799
|
formField: `${p2}-form-field`,
|
|
2793
2800
|
/** Ask-input tool root (inline form in a message bubble). */
|
|
@@ -2914,24 +2921,24 @@ import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef
|
|
|
2914
2921
|
import { useEffect as useEffect2, useRef } from "preact/hooks";
|
|
2915
2922
|
import { jsx as jsx3 } from "preact/jsx-runtime";
|
|
2916
2923
|
function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, strings }) {
|
|
2917
|
-
const
|
|
2924
|
+
const p33 = BRAND.cssPrefix;
|
|
2918
2925
|
const dragRef = useRef(null);
|
|
2919
2926
|
useEffect2(() => {
|
|
2920
2927
|
if (!panelEl) return;
|
|
2921
2928
|
const style = panelEl.style;
|
|
2922
|
-
if (resize.minWidth) style.setProperty(`--${
|
|
2923
|
-
if (resize.maxWidth) style.setProperty(`--${
|
|
2924
|
-
if (resize.minHeight) style.setProperty(`--${
|
|
2925
|
-
if (resize.maxHeight) style.setProperty(`--${
|
|
2929
|
+
if (resize.minWidth) style.setProperty(`--${p33}-resize-min-w`, resize.minWidth);
|
|
2930
|
+
if (resize.maxWidth) style.setProperty(`--${p33}-resize-max-w`, resize.maxWidth);
|
|
2931
|
+
if (resize.minHeight) style.setProperty(`--${p33}-resize-min-h`, resize.minHeight);
|
|
2932
|
+
if (resize.maxHeight) style.setProperty(`--${p33}-resize-max-h`, resize.maxHeight);
|
|
2926
2933
|
if (initialSize) {
|
|
2927
|
-
style.setProperty(`--${
|
|
2928
|
-
style.setProperty(`--${
|
|
2934
|
+
style.setProperty(`--${p33}-widget-w`, `${initialSize.width}px`);
|
|
2935
|
+
style.setProperty(`--${p33}-widget-h`, `${initialSize.height}px`);
|
|
2929
2936
|
}
|
|
2930
|
-
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight,
|
|
2937
|
+
}, [panelEl, resize.minWidth, resize.maxWidth, resize.minHeight, resize.maxHeight, p33, initialSize]);
|
|
2931
2938
|
if (!panelEl) return null;
|
|
2932
2939
|
const isTop = position.startsWith("top-");
|
|
2933
2940
|
const isRight = position.endsWith("-right");
|
|
2934
|
-
const cornerClass = `${
|
|
2941
|
+
const cornerClass = `${p33}-resize-grip ${p33}-resize-grip--${isTop ? "bottom" : "top"}-${isRight ? "left" : "right"}`;
|
|
2935
2942
|
const onPointerDown = (e) => {
|
|
2936
2943
|
if (!panelEl) return;
|
|
2937
2944
|
const target = e.currentTarget;
|
|
@@ -2955,8 +2962,8 @@ function ResizeGrip({ panelEl, resize, position, initialSize, onSizeChange, stri
|
|
|
2955
2962
|
if (!d || e.pointerId !== d.pointerId || !panelEl) return;
|
|
2956
2963
|
const dx = (e.clientX - d.startX) * d.dirX;
|
|
2957
2964
|
const dy = (e.clientY - d.startY) * d.dirY;
|
|
2958
|
-
panelEl.style.setProperty(`--${
|
|
2959
|
-
panelEl.style.setProperty(`--${
|
|
2965
|
+
panelEl.style.setProperty(`--${p33}-widget-w`, `${d.startW + dx}px`);
|
|
2966
|
+
panelEl.style.setProperty(`--${p33}-widget-h`, `${d.startH + dy}px`);
|
|
2960
2967
|
};
|
|
2961
2968
|
const onPointerUp = (e) => {
|
|
2962
2969
|
const d = dragRef.current;
|
|
@@ -3691,20 +3698,20 @@ function usePopoverMenu({ itemCount, initialFocusIndex }) {
|
|
|
3691
3698
|
// src/ui/overflow-menu.tsx
|
|
3692
3699
|
import { jsx as jsx8, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
3693
3700
|
function OverflowMenu({ items, triggerLabel }) {
|
|
3694
|
-
const
|
|
3701
|
+
const p33 = BRAND.cssPrefix;
|
|
3695
3702
|
const menu = usePopoverMenu({ itemCount: items.length });
|
|
3696
3703
|
const handleSelect = (item) => {
|
|
3697
3704
|
if (item.disabled) return;
|
|
3698
3705
|
item.onSelect();
|
|
3699
3706
|
if (!item.keepOpen) menu.close();
|
|
3700
3707
|
};
|
|
3701
|
-
return /* @__PURE__ */ jsxs6("div", { class: `${
|
|
3708
|
+
return /* @__PURE__ */ jsxs6("div", { class: `${p33}-menu-wrap`, children: [
|
|
3702
3709
|
/* @__PURE__ */ jsx8(
|
|
3703
3710
|
"button",
|
|
3704
3711
|
{
|
|
3705
3712
|
ref: menu.triggerRef,
|
|
3706
3713
|
type: "button",
|
|
3707
|
-
class: `${
|
|
3714
|
+
class: `${p33}-icon-btn`,
|
|
3708
3715
|
"aria-label": triggerLabel,
|
|
3709
3716
|
"aria-haspopup": "menu",
|
|
3710
3717
|
"aria-expanded": menu.open,
|
|
@@ -3718,7 +3725,7 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3718
3725
|
"div",
|
|
3719
3726
|
{
|
|
3720
3727
|
ref: menu.menuRef,
|
|
3721
|
-
class: `${
|
|
3728
|
+
class: `${p33}-menu`,
|
|
3722
3729
|
role: "menu",
|
|
3723
3730
|
"aria-label": triggerLabel,
|
|
3724
3731
|
onKeyDown: menu.onMenuKey,
|
|
@@ -3728,15 +3735,15 @@ function OverflowMenu({ items, triggerLabel }) {
|
|
|
3728
3735
|
{
|
|
3729
3736
|
type: "button",
|
|
3730
3737
|
role: "menuitem",
|
|
3731
|
-
class: `${
|
|
3738
|
+
class: `${p33}-menu-item`,
|
|
3732
3739
|
"aria-pressed": item.type === "switch" ? item.on : void 0,
|
|
3733
3740
|
disabled: item.disabled,
|
|
3734
3741
|
lang: item.lang,
|
|
3735
3742
|
onClick: () => handleSelect(item),
|
|
3736
3743
|
children: [
|
|
3737
|
-
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3738
|
-
/* @__PURE__ */ jsx8("span", { class: `${
|
|
3739
|
-
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${
|
|
3744
|
+
item.icon ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-icon`, children: item.icon }) : null,
|
|
3745
|
+
/* @__PURE__ */ jsx8("span", { class: `${p33}-menu-label`, children: item.label }),
|
|
3746
|
+
item.type === "switch" && item.on ? /* @__PURE__ */ jsx8("span", { class: `${p33}-menu-check`, "aria-hidden": "true", children: /* @__PURE__ */ jsx8(CheckIcon, {}) }) : null
|
|
3740
3747
|
]
|
|
3741
3748
|
},
|
|
3742
3749
|
item.id
|
|
@@ -4214,40 +4221,6 @@ function FormGate({ form, strings, onSubmit, onSkip }) {
|
|
|
4214
4221
|
import { useEffect as useEffect8, useLayoutEffect, useRef as useRef5, useState as useState6 } from "preact/hooks";
|
|
4215
4222
|
import { useComputed as useComputed5 } from "@preact/signals";
|
|
4216
4223
|
|
|
4217
|
-
// src/ui/form/form-card.tsx
|
|
4218
|
-
import { jsx as jsx12, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4219
|
-
var p12 = BRAND.cssPrefix;
|
|
4220
|
-
function FormCard({ form, strings, onSubmit, onSkip }) {
|
|
4221
|
-
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-form-card`, "data-testid": TID.formCard, children: [
|
|
4222
|
-
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-card-head`, children: [
|
|
4223
|
-
form.title ? /* @__PURE__ */ jsx12("strong", { class: `${p12}-form-card-title`, children: form.title }) : /* @__PURE__ */ jsx12("span", {}),
|
|
4224
|
-
/* @__PURE__ */ jsx12(
|
|
4225
|
-
"button",
|
|
4226
|
-
{
|
|
4227
|
-
type: "button",
|
|
4228
|
-
class: `${p12}-icon-btn`,
|
|
4229
|
-
onClick: onSkip,
|
|
4230
|
-
"aria-label": strings.formDismiss,
|
|
4231
|
-
title: strings.formDismiss,
|
|
4232
|
-
"data-testid": TID.formDismiss,
|
|
4233
|
-
children: /* @__PURE__ */ jsx12(CloseIcon, {})
|
|
4234
|
-
}
|
|
4235
|
-
)
|
|
4236
|
-
] }),
|
|
4237
|
-
form.description ? /* @__PURE__ */ jsx12("p", { class: `${p12}-form-card-desc`, children: form.description }) : null,
|
|
4238
|
-
/* @__PURE__ */ jsx12(
|
|
4239
|
-
DynamicForm,
|
|
4240
|
-
{
|
|
4241
|
-
fields: form.fields,
|
|
4242
|
-
strings,
|
|
4243
|
-
submitLabel: form.submitLabel ?? strings.formSubmit,
|
|
4244
|
-
onSubmit,
|
|
4245
|
-
submitTestId: TID.formSubmit
|
|
4246
|
-
}
|
|
4247
|
-
)
|
|
4248
|
-
] });
|
|
4249
|
-
}
|
|
4250
|
-
|
|
4251
4224
|
// src/ui/message-bubble.tsx
|
|
4252
4225
|
import { useComputed as useComputed4 } from "@preact/signals";
|
|
4253
4226
|
|
|
@@ -4255,7 +4228,7 @@ import { useComputed as useComputed4 } from "@preact/signals";
|
|
|
4255
4228
|
import { useEffect as useEffect7, useMemo, useRef as useRef4 } from "preact/hooks";
|
|
4256
4229
|
import { effect, signal as signal4 } from "@preact/signals";
|
|
4257
4230
|
import * as smd from "streaming-markdown";
|
|
4258
|
-
import { jsx as
|
|
4231
|
+
import { jsx as jsx12 } from "preact/jsx-runtime";
|
|
4259
4232
|
function MarkdownView({ textSig, doneSig }) {
|
|
4260
4233
|
const ref = useRef4(null);
|
|
4261
4234
|
useEffect7(() => {
|
|
@@ -4305,12 +4278,12 @@ function MarkdownView({ textSig, doneSig }) {
|
|
|
4305
4278
|
el.removeEventListener("click", onClick);
|
|
4306
4279
|
};
|
|
4307
4280
|
}, [textSig, doneSig]);
|
|
4308
|
-
return /* @__PURE__ */
|
|
4281
|
+
return /* @__PURE__ */ jsx12("div", { ref });
|
|
4309
4282
|
}
|
|
4310
4283
|
function StaticMarkdown({ text }) {
|
|
4311
4284
|
const textSig = useMemo(() => signal4(text), [text]);
|
|
4312
4285
|
const doneSig = useMemo(() => signal4(true), []);
|
|
4313
|
-
return /* @__PURE__ */
|
|
4286
|
+
return /* @__PURE__ */ jsx12(MarkdownView, { textSig, doneSig });
|
|
4314
4287
|
}
|
|
4315
4288
|
function hardenLink(a) {
|
|
4316
4289
|
const href = a.getAttribute("href") ?? "";
|
|
@@ -4324,8 +4297,8 @@ function hardenLink(a) {
|
|
|
4324
4297
|
|
|
4325
4298
|
// src/ui/tool-approval.tsx
|
|
4326
4299
|
import { useComputed as useComputed2, useSignal } from "@preact/signals";
|
|
4327
|
-
import { Fragment, jsx as
|
|
4328
|
-
var
|
|
4300
|
+
import { Fragment, jsx as jsx13, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
4301
|
+
var p12 = BRAND.cssPrefix;
|
|
4329
4302
|
function ToolApproval({ part, strings, active, onDecision }) {
|
|
4330
4303
|
const approval = useComputed2(() => part.approvalSig.value);
|
|
4331
4304
|
const input = useComputed2(() => part.inputSig.value);
|
|
@@ -4333,24 +4306,24 @@ function ToolApproval({ part, strings, active, onDecision }) {
|
|
|
4333
4306
|
const decided = approval.value?.approved !== void 0;
|
|
4334
4307
|
if (decided) {
|
|
4335
4308
|
const ap = approval.value;
|
|
4336
|
-
return /* @__PURE__ */
|
|
4337
|
-
/* @__PURE__ */
|
|
4338
|
-
/* @__PURE__ */
|
|
4339
|
-
ap?.reason ? /* @__PURE__ */
|
|
4309
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval ${p12}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4310
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-label`, "data-approved": ap?.approved ? "true" : "false", children: ap?.approved ? strings.approved : strings.rejected }),
|
|
4311
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName }),
|
|
4312
|
+
ap?.reason ? /* @__PURE__ */ jsx13("span", { class: `${p12}-tool-decided-value`, children: ap.reason }) : null
|
|
4340
4313
|
] });
|
|
4341
4314
|
}
|
|
4342
4315
|
const args = summarizeInput(input.value);
|
|
4343
|
-
return /* @__PURE__ */
|
|
4344
|
-
/* @__PURE__ */
|
|
4345
|
-
/* @__PURE__ */
|
|
4346
|
-
/* @__PURE__ */
|
|
4316
|
+
return /* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-approval`, "data-testid": TID.toolApproval, children: [
|
|
4317
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-tool-head`, children: [
|
|
4318
|
+
/* @__PURE__ */ jsx13("span", { class: `${p12}-tool-badge`, children: strings.approvalRequired }),
|
|
4319
|
+
/* @__PURE__ */ jsx13("strong", { class: `${p12}-tool-title`, children: part.toolName })
|
|
4347
4320
|
] }),
|
|
4348
|
-
args ? /* @__PURE__ */
|
|
4349
|
-
active ? /* @__PURE__ */
|
|
4350
|
-
/* @__PURE__ */
|
|
4321
|
+
args ? /* @__PURE__ */ jsx13("pre", { class: `${p12}-tool-args`, children: args }) : null,
|
|
4322
|
+
active ? /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
4323
|
+
/* @__PURE__ */ jsx13(
|
|
4351
4324
|
"input",
|
|
4352
4325
|
{
|
|
4353
|
-
class: `${
|
|
4326
|
+
class: `${p12}-field-input`,
|
|
4354
4327
|
value: reason.value,
|
|
4355
4328
|
placeholder: strings.approvalReason,
|
|
4356
4329
|
onInput: (e) => {
|
|
@@ -4358,29 +4331,29 @@ function ToolApproval({ part, strings, active, onDecision }) {
|
|
|
4358
4331
|
}
|
|
4359
4332
|
}
|
|
4360
4333
|
),
|
|
4361
|
-
/* @__PURE__ */
|
|
4362
|
-
/* @__PURE__ */
|
|
4334
|
+
/* @__PURE__ */ jsxs10("div", { class: `${p12}-form-actions`, children: [
|
|
4335
|
+
/* @__PURE__ */ jsx13(
|
|
4363
4336
|
"button",
|
|
4364
4337
|
{
|
|
4365
4338
|
type: "button",
|
|
4366
|
-
class: `${
|
|
4339
|
+
class: `${p12}-tool-reject`,
|
|
4367
4340
|
onClick: () => onDecision(part.toolCallId, false, reason.value.trim() || void 0),
|
|
4368
4341
|
"data-testid": TID.toolReject,
|
|
4369
4342
|
children: strings.reject
|
|
4370
4343
|
}
|
|
4371
4344
|
),
|
|
4372
|
-
/* @__PURE__ */
|
|
4345
|
+
/* @__PURE__ */ jsx13(
|
|
4373
4346
|
"button",
|
|
4374
4347
|
{
|
|
4375
4348
|
type: "button",
|
|
4376
|
-
class: `${
|
|
4349
|
+
class: `${p12}-tool-approve`,
|
|
4377
4350
|
onClick: () => onDecision(part.toolCallId, true, reason.value.trim() || void 0),
|
|
4378
4351
|
"data-testid": TID.toolApprove,
|
|
4379
4352
|
children: strings.approve
|
|
4380
4353
|
}
|
|
4381
4354
|
)
|
|
4382
4355
|
] })
|
|
4383
|
-
] }) : /* @__PURE__ */
|
|
4356
|
+
] }) : /* @__PURE__ */ jsx13("p", { class: `${p12}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4384
4357
|
] });
|
|
4385
4358
|
}
|
|
4386
4359
|
function summarizeInput(input) {
|
|
@@ -4451,49 +4424,49 @@ function num(v) {
|
|
|
4451
4424
|
}
|
|
4452
4425
|
|
|
4453
4426
|
// src/ui/tool-ask-input.tsx
|
|
4454
|
-
import { jsx as
|
|
4455
|
-
var
|
|
4427
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
4428
|
+
var p13 = BRAND.cssPrefix;
|
|
4456
4429
|
function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
4457
4430
|
const state = useComputed3(() => part.stateSig.value);
|
|
4458
4431
|
const request = useComputed3(() => parseAskUserInput(part.inputSig.value));
|
|
4459
4432
|
const decided = state.value === "output" || state.value === "error";
|
|
4460
4433
|
if (decided) {
|
|
4461
|
-
return /* @__PURE__ */
|
|
4434
|
+
return /* @__PURE__ */ jsx14(DecidedSummary, { part, strings });
|
|
4462
4435
|
}
|
|
4463
4436
|
if (!active) {
|
|
4464
|
-
return /* @__PURE__ */
|
|
4465
|
-
/* @__PURE__ */
|
|
4466
|
-
/* @__PURE__ */
|
|
4437
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-stale`, "data-testid": TID.toolAskInput, children: [
|
|
4438
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: request.value.title ?? request.value.question }),
|
|
4439
|
+
/* @__PURE__ */ jsx14("p", { class: `${p13}-tool-stale-note`, children: strings.stepNoLongerActive })
|
|
4467
4440
|
] });
|
|
4468
4441
|
}
|
|
4469
4442
|
const req = request.value;
|
|
4470
4443
|
const isConfirmation = req.responseType === "confirmation";
|
|
4471
|
-
return /* @__PURE__ */
|
|
4472
|
-
/* @__PURE__ */
|
|
4473
|
-
req.description ? /* @__PURE__ */
|
|
4474
|
-
isConfirmation ? /* @__PURE__ */
|
|
4475
|
-
isConfirmation ? /* @__PURE__ */
|
|
4476
|
-
/* @__PURE__ */
|
|
4444
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input`, "data-testid": TID.toolAskInput, children: [
|
|
4445
|
+
/* @__PURE__ */ jsx14(Header, { strings, title: req.title }),
|
|
4446
|
+
req.description ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-desc`, children: req.description }) : null,
|
|
4447
|
+
isConfirmation ? /* @__PURE__ */ jsx14("p", { class: `${p13}-tool-question`, children: req.question }) : null,
|
|
4448
|
+
isConfirmation ? /* @__PURE__ */ jsxs11("div", { class: `${p13}-form-actions`, children: [
|
|
4449
|
+
/* @__PURE__ */ jsx14(
|
|
4477
4450
|
"button",
|
|
4478
4451
|
{
|
|
4479
4452
|
type: "button",
|
|
4480
|
-
class: `${
|
|
4453
|
+
class: `${p13}-form-skip`,
|
|
4481
4454
|
onClick: () => onSubmit(part.toolCallId, { confirmed: false }),
|
|
4482
4455
|
"data-testid": TID.toolInputSkip,
|
|
4483
4456
|
children: strings.reject
|
|
4484
4457
|
}
|
|
4485
4458
|
),
|
|
4486
|
-
/* @__PURE__ */
|
|
4459
|
+
/* @__PURE__ */ jsx14(
|
|
4487
4460
|
"button",
|
|
4488
4461
|
{
|
|
4489
4462
|
type: "button",
|
|
4490
|
-
class: `${
|
|
4463
|
+
class: `${p13}-form-submit`,
|
|
4491
4464
|
onClick: () => onSubmit(part.toolCallId, { confirmed: true }),
|
|
4492
4465
|
"data-testid": TID.toolInputSubmit,
|
|
4493
4466
|
children: strings.approve
|
|
4494
4467
|
}
|
|
4495
4468
|
)
|
|
4496
|
-
] }) : /* @__PURE__ */
|
|
4469
|
+
] }) : /* @__PURE__ */ jsx14(
|
|
4497
4470
|
DynamicForm,
|
|
4498
4471
|
{
|
|
4499
4472
|
fields: askInputToFields(req),
|
|
@@ -4509,17 +4482,17 @@ function ToolAskInput({ part, strings, active, onSubmit }) {
|
|
|
4509
4482
|
] });
|
|
4510
4483
|
}
|
|
4511
4484
|
function Header({ strings, title }) {
|
|
4512
|
-
return /* @__PURE__ */
|
|
4513
|
-
/* @__PURE__ */
|
|
4514
|
-
title ? /* @__PURE__ */
|
|
4485
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-head`, children: [
|
|
4486
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-badge`, children: strings.inputRequired }),
|
|
4487
|
+
title ? /* @__PURE__ */ jsx14("strong", { class: `${p13}-tool-title`, children: title }) : null
|
|
4515
4488
|
] });
|
|
4516
4489
|
}
|
|
4517
4490
|
function DecidedSummary({ part, strings }) {
|
|
4518
4491
|
const output = useComputed3(() => part.outputSig.value);
|
|
4519
4492
|
const text = summarizeOutput(output.value) || strings.inputSubmitted;
|
|
4520
|
-
return /* @__PURE__ */
|
|
4521
|
-
/* @__PURE__ */
|
|
4522
|
-
/* @__PURE__ */
|
|
4493
|
+
return /* @__PURE__ */ jsxs11("div", { class: `${p13}-tool-ask-input ${p13}-tool-decided`, "data-testid": TID.toolDecision, children: [
|
|
4494
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-label`, children: strings.inputSubmitted }),
|
|
4495
|
+
/* @__PURE__ */ jsx14("span", { class: `${p13}-tool-decided-value`, children: text })
|
|
4523
4496
|
] });
|
|
4524
4497
|
}
|
|
4525
4498
|
function summarizeOutput(output) {
|
|
@@ -4534,21 +4507,21 @@ function summarizeOutput(output) {
|
|
|
4534
4507
|
}
|
|
4535
4508
|
|
|
4536
4509
|
// src/ui/tool-chip.tsx
|
|
4537
|
-
import { jsx as
|
|
4510
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
4538
4511
|
function ToolChip({ part, strings }) {
|
|
4539
|
-
const
|
|
4540
|
-
return /* @__PURE__ */
|
|
4541
|
-
/* @__PURE__ */
|
|
4512
|
+
const p33 = BRAND.cssPrefix;
|
|
4513
|
+
return /* @__PURE__ */ jsxs12("span", { class: `${p33}-tool-chip`, role: "status", children: [
|
|
4514
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
4542
4515
|
strings.usedTool,
|
|
4543
4516
|
":"
|
|
4544
4517
|
] }),
|
|
4545
|
-
/* @__PURE__ */
|
|
4518
|
+
/* @__PURE__ */ jsx15("strong", { children: part.toolName })
|
|
4546
4519
|
] });
|
|
4547
4520
|
}
|
|
4548
4521
|
|
|
4549
4522
|
// src/ui/message-bubble.tsx
|
|
4550
|
-
import { jsx as
|
|
4551
|
-
var
|
|
4523
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
|
|
4524
|
+
var p14 = BRAND.cssPrefix;
|
|
4552
4525
|
function MessageBubble({
|
|
4553
4526
|
message,
|
|
4554
4527
|
strings,
|
|
@@ -4571,9 +4544,9 @@ function MessageBubble({
|
|
|
4571
4544
|
const working = streaming && !hasAnswerText.value;
|
|
4572
4545
|
const showStreamDots = streaming && !bufferedHold && !(reasoningVisible.value && working);
|
|
4573
4546
|
const stamp = formatStamp(message.createdAt);
|
|
4574
|
-
return /* @__PURE__ */
|
|
4575
|
-
/* @__PURE__ */
|
|
4576
|
-
bufferedHold ? /* @__PURE__ */
|
|
4547
|
+
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: [
|
|
4548
|
+
/* @__PURE__ */ jsxs13("div", { class: `${p14}-bubble`, children: [
|
|
4549
|
+
bufferedHold ? /* @__PURE__ */ jsx16(LoadingSpinner, { label: strings.loading }) : partList.map((part) => /* @__PURE__ */ jsx16(
|
|
4577
4550
|
PartView,
|
|
4578
4551
|
{
|
|
4579
4552
|
part,
|
|
@@ -4586,10 +4559,10 @@ function MessageBubble({
|
|
|
4586
4559
|
},
|
|
4587
4560
|
partKey(part)
|
|
4588
4561
|
)),
|
|
4589
|
-
showStreamDots && /* @__PURE__ */
|
|
4590
|
-
message.status === "error" && message.errorText ? /* @__PURE__ */
|
|
4562
|
+
showStreamDots && /* @__PURE__ */ jsx16(TypingDots, {}),
|
|
4563
|
+
message.status === "error" && message.errorText ? /* @__PURE__ */ jsx16("div", { class: `${p14}-error`, role: "alert", children: /* @__PURE__ */ jsx16("span", { children: message.errorText }) }) : null
|
|
4591
4564
|
] }),
|
|
4592
|
-
stamp ? /* @__PURE__ */
|
|
4565
|
+
stamp ? /* @__PURE__ */ jsx16("time", { class: `${p14}-bubble-time`, dateTime: stamp.iso, title: stamp.full, children: stamp.short }) : null
|
|
4593
4566
|
] }) });
|
|
4594
4567
|
}
|
|
4595
4568
|
function formatStamp(createdAt) {
|
|
@@ -4616,11 +4589,11 @@ function PartView({
|
|
|
4616
4589
|
}) {
|
|
4617
4590
|
switch (part.kind) {
|
|
4618
4591
|
case "text":
|
|
4619
|
-
return /* @__PURE__ */
|
|
4592
|
+
return /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig });
|
|
4620
4593
|
case "reasoning":
|
|
4621
|
-
return showReasoning ? /* @__PURE__ */
|
|
4594
|
+
return showReasoning ? /* @__PURE__ */ jsx16(ReasoningView, { part, active, strings }) : null;
|
|
4622
4595
|
case "tool":
|
|
4623
|
-
return /* @__PURE__ */
|
|
4596
|
+
return /* @__PURE__ */ jsx16(
|
|
4624
4597
|
ToolPartView,
|
|
4625
4598
|
{
|
|
4626
4599
|
part,
|
|
@@ -4632,9 +4605,9 @@ function PartView({
|
|
|
4632
4605
|
);
|
|
4633
4606
|
case "file":
|
|
4634
4607
|
if (part.mediaType.startsWith("image/")) {
|
|
4635
|
-
return /* @__PURE__ */
|
|
4608
|
+
return /* @__PURE__ */ jsx16("img", { src: part.url, alt: "", loading: "lazy" });
|
|
4636
4609
|
}
|
|
4637
|
-
return /* @__PURE__ */
|
|
4610
|
+
return /* @__PURE__ */ jsx16("a", { href: part.url, target: "_blank", rel: "noreferrer noopener", children: part.url });
|
|
4638
4611
|
case "source":
|
|
4639
4612
|
return null;
|
|
4640
4613
|
}
|
|
@@ -4650,22 +4623,22 @@ function ToolPartView({
|
|
|
4650
4623
|
const hasApproval = useComputed4(() => part.approvalSig.value !== void 0);
|
|
4651
4624
|
if (tool?.humanInLoop) {
|
|
4652
4625
|
if (hasApproval.value || state.value === "awaiting-approval") {
|
|
4653
|
-
return /* @__PURE__ */
|
|
4626
|
+
return /* @__PURE__ */ jsx16(ToolApproval, { part, strings, active: interactive, onDecision: tool.onDecision });
|
|
4654
4627
|
}
|
|
4655
4628
|
if (isAskUserInputTool(part.toolName) || state.value === "awaiting-input") {
|
|
4656
|
-
return /* @__PURE__ */
|
|
4629
|
+
return /* @__PURE__ */ jsx16(ToolAskInput, { part, strings, active: interactive, onSubmit: tool.onResult });
|
|
4657
4630
|
}
|
|
4658
4631
|
}
|
|
4659
|
-
return showToolCalls ? /* @__PURE__ */
|
|
4632
|
+
return showToolCalls ? /* @__PURE__ */ jsx16(ToolChip, { part, strings }) : null;
|
|
4660
4633
|
}
|
|
4661
4634
|
function ReasoningView({
|
|
4662
4635
|
part,
|
|
4663
4636
|
active,
|
|
4664
4637
|
strings
|
|
4665
4638
|
}) {
|
|
4666
|
-
return /* @__PURE__ */
|
|
4667
|
-
/* @__PURE__ */
|
|
4668
|
-
/* @__PURE__ */
|
|
4639
|
+
return /* @__PURE__ */ jsxs13("details", { class: `${p14}-reasoning`, open: active, "data-active": active ? "true" : void 0, children: [
|
|
4640
|
+
/* @__PURE__ */ jsx16("summary", { class: `${p14}-reasoning-summary`, children: /* @__PURE__ */ jsx16("span", { class: `${p14}-reasoning-label`, children: active ? strings.thinking : strings.thoughts }) }),
|
|
4641
|
+
/* @__PURE__ */ jsx16("div", { class: `${p14}-reasoning-body`, children: /* @__PURE__ */ jsx16(MarkdownView, { textSig: part.textSig, doneSig: part.doneSig }) })
|
|
4669
4642
|
] });
|
|
4670
4643
|
}
|
|
4671
4644
|
function partKey(part) {
|
|
@@ -4682,22 +4655,22 @@ function partKey(part) {
|
|
|
4682
4655
|
}
|
|
4683
4656
|
}
|
|
4684
4657
|
function TypingDots() {
|
|
4685
|
-
return /* @__PURE__ */
|
|
4686
|
-
/* @__PURE__ */
|
|
4687
|
-
/* @__PURE__ */
|
|
4688
|
-
/* @__PURE__ */
|
|
4658
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-typing`, "aria-hidden": "true", children: [
|
|
4659
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4660
|
+
/* @__PURE__ */ jsx16("span", {}),
|
|
4661
|
+
/* @__PURE__ */ jsx16("span", {})
|
|
4689
4662
|
] });
|
|
4690
4663
|
}
|
|
4691
4664
|
function LoadingSpinner({ label }) {
|
|
4692
|
-
return /* @__PURE__ */
|
|
4693
|
-
/* @__PURE__ */
|
|
4694
|
-
/* @__PURE__ */
|
|
4665
|
+
return /* @__PURE__ */ jsxs13("span", { class: `${p14}-loading`, role: "status", children: [
|
|
4666
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-spinner`, "aria-hidden": "true" }),
|
|
4667
|
+
/* @__PURE__ */ jsx16("span", { class: `${p14}-loading-label`, children: label })
|
|
4695
4668
|
] });
|
|
4696
4669
|
}
|
|
4697
4670
|
|
|
4698
4671
|
// src/ui/message-list.tsx
|
|
4699
|
-
import { jsx as
|
|
4700
|
-
var
|
|
4672
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
4673
|
+
var p15 = BRAND.cssPrefix;
|
|
4701
4674
|
var STICK_THRESHOLD = 120;
|
|
4702
4675
|
var DIVIDER_IDLE_MS = 1200;
|
|
4703
4676
|
function MessageList({
|
|
@@ -4708,10 +4681,7 @@ function MessageList({
|
|
|
4708
4681
|
showToolCalls,
|
|
4709
4682
|
loading,
|
|
4710
4683
|
idle,
|
|
4711
|
-
tool
|
|
4712
|
-
inlineForm,
|
|
4713
|
-
onFormSubmit,
|
|
4714
|
-
onFormSkip
|
|
4684
|
+
tool
|
|
4715
4685
|
}) {
|
|
4716
4686
|
const ref = useRef5(null);
|
|
4717
4687
|
const messages = useComputed5(() => messagesSig.value);
|
|
@@ -4796,12 +4766,12 @@ function MessageList({
|
|
|
4796
4766
|
const day = dayKey(m.createdAt);
|
|
4797
4767
|
if (day && day !== prevDay) {
|
|
4798
4768
|
rows.push(
|
|
4799
|
-
/* @__PURE__ */
|
|
4769
|
+
/* @__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}`)
|
|
4800
4770
|
);
|
|
4801
4771
|
prevDay = day;
|
|
4802
4772
|
}
|
|
4803
4773
|
rows.push(
|
|
4804
|
-
/* @__PURE__ */
|
|
4774
|
+
/* @__PURE__ */ jsx17(
|
|
4805
4775
|
MessageBubble,
|
|
4806
4776
|
{
|
|
4807
4777
|
message: m,
|
|
@@ -4816,33 +4786,32 @@ function MessageList({
|
|
|
4816
4786
|
)
|
|
4817
4787
|
);
|
|
4818
4788
|
}
|
|
4819
|
-
return /* @__PURE__ */
|
|
4820
|
-
/* @__PURE__ */
|
|
4789
|
+
return /* @__PURE__ */ jsxs14("div", { class: `${p15}-list-wrap`, children: [
|
|
4790
|
+
/* @__PURE__ */ jsxs14(
|
|
4821
4791
|
"div",
|
|
4822
4792
|
{
|
|
4823
4793
|
ref,
|
|
4824
|
-
class: `${
|
|
4794
|
+
class: `${p15}-list`,
|
|
4825
4795
|
role: "log",
|
|
4826
4796
|
"aria-live": "polite",
|
|
4827
4797
|
"aria-relevant": "additions text",
|
|
4828
4798
|
"data-scrolling": scrolling ? "true" : void 0,
|
|
4829
4799
|
children: [
|
|
4830
|
-
loading && messages.value.length === 0 ? /* @__PURE__ */
|
|
4831
|
-
rows
|
|
4832
|
-
inlineForm && onFormSubmit && onFormSkip ? /* @__PURE__ */ jsx18(FormCard, { form: inlineForm, strings, onSubmit: onFormSubmit, onSkip: onFormSkip }) : null
|
|
4800
|
+
loading && messages.value.length === 0 ? /* @__PURE__ */ jsx17("div", { class: `${p15}-list-loading`, role: "status", children: strings.messagesLoading }) : null,
|
|
4801
|
+
rows
|
|
4833
4802
|
]
|
|
4834
4803
|
}
|
|
4835
4804
|
),
|
|
4836
|
-
showJump ? /* @__PURE__ */
|
|
4805
|
+
showJump ? /* @__PURE__ */ jsx17(
|
|
4837
4806
|
"button",
|
|
4838
4807
|
{
|
|
4839
4808
|
type: "button",
|
|
4840
|
-
class: `${
|
|
4809
|
+
class: `${p15}-jump`,
|
|
4841
4810
|
onClick: jumpToBottom,
|
|
4842
4811
|
"aria-label": strings.scrollToBottom,
|
|
4843
4812
|
title: strings.scrollToBottom,
|
|
4844
4813
|
"data-testid": TID.scrollToBottom,
|
|
4845
|
-
children: /* @__PURE__ */
|
|
4814
|
+
children: /* @__PURE__ */ jsx17(ChevronDownIcon, {})
|
|
4846
4815
|
}
|
|
4847
4816
|
) : null
|
|
4848
4817
|
] });
|
|
@@ -4884,15 +4853,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4884
4853
|
if (diffDays < 7) return "lastWeek";
|
|
4885
4854
|
return "older";
|
|
4886
4855
|
}
|
|
4887
|
-
function groupByBucket(nowMs,
|
|
4856
|
+
function groupByBucket(nowMs, conversations) {
|
|
4888
4857
|
const buckets = /* @__PURE__ */ new Map();
|
|
4889
|
-
for (const chat of
|
|
4858
|
+
for (const chat of conversations) {
|
|
4890
4859
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4891
4860
|
const list = buckets.get(b);
|
|
4892
4861
|
if (list) list.push(chat);
|
|
4893
4862
|
else buckets.set(b, [chat]);
|
|
4894
4863
|
}
|
|
4895
|
-
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b,
|
|
4864
|
+
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b, conversations: buckets.get(b) }));
|
|
4896
4865
|
}
|
|
4897
4866
|
function startOfDay(ms) {
|
|
4898
4867
|
const d = new Date(ms);
|
|
@@ -4901,7 +4870,7 @@ function startOfDay(ms) {
|
|
|
4901
4870
|
}
|
|
4902
4871
|
|
|
4903
4872
|
// src/ui/conversation-list.tsx
|
|
4904
|
-
import { Fragment as Fragment2, jsx as
|
|
4873
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
4905
4874
|
var log11 = logger.scope("history");
|
|
4906
4875
|
var BUCKET_TO_STRING = {
|
|
4907
4876
|
today: "dateToday",
|
|
@@ -4910,59 +4879,59 @@ var BUCKET_TO_STRING = {
|
|
|
4910
4879
|
older: "dateOlder"
|
|
4911
4880
|
};
|
|
4912
4881
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
4913
|
-
const
|
|
4882
|
+
const p33 = BRAND.cssPrefix;
|
|
4914
4883
|
const [state, setState] = useState7("loading");
|
|
4915
|
-
const [
|
|
4884
|
+
const [conversations, setChats] = useState7([]);
|
|
4916
4885
|
useEffect9(() => {
|
|
4917
4886
|
let cancelled = false;
|
|
4918
|
-
transport.
|
|
4887
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4919
4888
|
if (cancelled) return;
|
|
4920
|
-
setChats(res.
|
|
4889
|
+
setChats(res.conversations ?? []);
|
|
4921
4890
|
setState("loaded");
|
|
4922
4891
|
}).catch((err) => {
|
|
4923
4892
|
if (cancelled) return;
|
|
4924
|
-
log11.warn("
|
|
4893
|
+
log11.warn("listConversations failed", { err });
|
|
4925
4894
|
setState("error");
|
|
4926
4895
|
});
|
|
4927
4896
|
return () => {
|
|
4928
4897
|
cancelled = true;
|
|
4929
4898
|
};
|
|
4930
4899
|
}, [transport, visitorId]);
|
|
4931
|
-
const newChatButton = onNewChat ? /* @__PURE__ */
|
|
4932
|
-
/* @__PURE__ */
|
|
4900
|
+
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: [
|
|
4901
|
+
/* @__PURE__ */ jsx18(PlusIcon, {}),
|
|
4933
4902
|
strings.historyNewChat
|
|
4934
4903
|
] }) }) : null;
|
|
4935
4904
|
if (state === "loading") {
|
|
4936
|
-
return /* @__PURE__ */
|
|
4937
|
-
/* @__PURE__ */
|
|
4905
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4906
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyLoading }),
|
|
4938
4907
|
newChatButton
|
|
4939
4908
|
] });
|
|
4940
4909
|
}
|
|
4941
|
-
if (state === "error" ||
|
|
4942
|
-
return /* @__PURE__ */
|
|
4943
|
-
/* @__PURE__ */
|
|
4910
|
+
if (state === "error" || conversations.length === 0) {
|
|
4911
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4912
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4944
4913
|
newChatButton
|
|
4945
4914
|
] });
|
|
4946
4915
|
}
|
|
4947
|
-
const groups = groupByBucket(Date.now(),
|
|
4948
|
-
return /* @__PURE__ */
|
|
4949
|
-
/* @__PURE__ */
|
|
4950
|
-
/* @__PURE__ */
|
|
4951
|
-
group.
|
|
4916
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4917
|
+
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4918
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4919
|
+
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4920
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4952
4921
|
"button",
|
|
4953
4922
|
{
|
|
4954
4923
|
type: "button",
|
|
4955
4924
|
role: "listitem",
|
|
4956
|
-
class: `${
|
|
4925
|
+
class: `${p33}-history-item`,
|
|
4957
4926
|
onClick: () => onSelect(chat),
|
|
4958
4927
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4959
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4928
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
4960
4929
|
children: [
|
|
4961
|
-
/* @__PURE__ */
|
|
4962
|
-
chat.preview ? /* @__PURE__ */
|
|
4930
|
+
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4931
|
+
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4963
4932
|
]
|
|
4964
4933
|
},
|
|
4965
|
-
chat.
|
|
4934
|
+
chat.conversationId
|
|
4966
4935
|
))
|
|
4967
4936
|
] }, group.bucket)) }),
|
|
4968
4937
|
newChatButton
|
|
@@ -4970,21 +4939,21 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4970
4939
|
}
|
|
4971
4940
|
|
|
4972
4941
|
// src/ui/chat-history-pane.tsx
|
|
4973
|
-
import { jsx as
|
|
4942
|
+
import { jsx as jsx19 } from "preact/jsx-runtime";
|
|
4974
4943
|
function ChatHistoryPane(props2) {
|
|
4975
|
-
return /* @__PURE__ */
|
|
4944
|
+
return /* @__PURE__ */ jsx19(ConversationList, { ...props2 });
|
|
4976
4945
|
}
|
|
4977
4946
|
|
|
4978
4947
|
// src/ui/suggestions.tsx
|
|
4979
|
-
import { jsx as
|
|
4980
|
-
var
|
|
4948
|
+
import { jsx as jsx20 } from "preact/jsx-runtime";
|
|
4949
|
+
var p16 = BRAND.cssPrefix;
|
|
4981
4950
|
function Suggestions({ suggestions, onPick }) {
|
|
4982
4951
|
if (suggestions.length === 0) return null;
|
|
4983
|
-
return /* @__PURE__ */
|
|
4952
|
+
return /* @__PURE__ */ jsx20("div", { class: `${p16}-suggestions`, role: "group", "aria-label": "Suggested replies", children: suggestions.map((s, i) => /* @__PURE__ */ jsx20(
|
|
4984
4953
|
"button",
|
|
4985
4954
|
{
|
|
4986
4955
|
type: "button",
|
|
4987
|
-
class: `${
|
|
4956
|
+
class: `${p16}-suggestion`,
|
|
4988
4957
|
onClick: () => onPick(s),
|
|
4989
4958
|
"data-testid": tid(TID.suggestion, i),
|
|
4990
4959
|
children: s.label
|
|
@@ -4994,8 +4963,8 @@ function Suggestions({ suggestions, onPick }) {
|
|
|
4994
4963
|
}
|
|
4995
4964
|
|
|
4996
4965
|
// src/ui/panel.tsx
|
|
4997
|
-
import { Fragment as Fragment3, jsx as
|
|
4998
|
-
var
|
|
4966
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
4967
|
+
var p17 = BRAND.cssPrefix;
|
|
4999
4968
|
function Panel(props2) {
|
|
5000
4969
|
const { options, onClose } = props2;
|
|
5001
4970
|
const s = options.strings;
|
|
@@ -5019,18 +4988,18 @@ function Panel(props2) {
|
|
|
5019
4988
|
}, []);
|
|
5020
4989
|
const { visible: dragOver } = useFileDrop({ containerRef, onDrop: onDropItems });
|
|
5021
4990
|
useDragMove(containerRef.current, options.mode === "modal");
|
|
5022
|
-
return /* @__PURE__ */
|
|
4991
|
+
return /* @__PURE__ */ jsxs16(
|
|
5023
4992
|
"div",
|
|
5024
4993
|
{
|
|
5025
4994
|
ref: containerRef,
|
|
5026
|
-
class: `${
|
|
4995
|
+
class: `${p17}-panel`,
|
|
5027
4996
|
role: "dialog",
|
|
5028
4997
|
"aria-modal": "false",
|
|
5029
4998
|
"aria-label": s.panelTitle,
|
|
5030
4999
|
style: { position: "relative" },
|
|
5031
5000
|
"data-testid": TID.panel,
|
|
5032
5001
|
children: [
|
|
5033
|
-
/* @__PURE__ */
|
|
5002
|
+
/* @__PURE__ */ jsx21(
|
|
5034
5003
|
PanelContent,
|
|
5035
5004
|
{
|
|
5036
5005
|
...props2,
|
|
@@ -5039,7 +5008,7 @@ function Panel(props2) {
|
|
|
5039
5008
|
composerAttachApiRef
|
|
5040
5009
|
}
|
|
5041
5010
|
),
|
|
5042
|
-
/* @__PURE__ */
|
|
5011
|
+
/* @__PURE__ */ jsx21(PoweredByBar, { poweredBy: props2.options.poweredBy })
|
|
5043
5012
|
]
|
|
5044
5013
|
}
|
|
5045
5014
|
);
|
|
@@ -5070,8 +5039,7 @@ function PanelContent(props2) {
|
|
|
5070
5039
|
onSend,
|
|
5071
5040
|
onStop,
|
|
5072
5041
|
onSuggestion,
|
|
5073
|
-
|
|
5074
|
-
inlineForm,
|
|
5042
|
+
activeForm,
|
|
5075
5043
|
onFormSubmit,
|
|
5076
5044
|
onFormSkip,
|
|
5077
5045
|
tool,
|
|
@@ -5081,12 +5049,12 @@ function PanelContent(props2) {
|
|
|
5081
5049
|
} = props2;
|
|
5082
5050
|
const s = options.strings;
|
|
5083
5051
|
let composerArea;
|
|
5084
|
-
if (
|
|
5085
|
-
composerArea = /* @__PURE__ */
|
|
5052
|
+
if (activeForm) {
|
|
5053
|
+
composerArea = /* @__PURE__ */ jsx21(FormGate, { form: activeForm, strings: s, onSubmit: onFormSubmit, onSkip: onFormSkip });
|
|
5086
5054
|
} else if (canSend) {
|
|
5087
|
-
composerArea = /* @__PURE__ */
|
|
5088
|
-
/* @__PURE__ */
|
|
5089
|
-
/* @__PURE__ */
|
|
5055
|
+
composerArea = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5056
|
+
/* @__PURE__ */ jsx21(Suggestions, { suggestions, onPick: onSuggestion }),
|
|
5057
|
+
/* @__PURE__ */ jsx21(
|
|
5090
5058
|
Composer,
|
|
5091
5059
|
{
|
|
5092
5060
|
options,
|
|
@@ -5101,10 +5069,10 @@ function PanelContent(props2) {
|
|
|
5101
5069
|
)
|
|
5102
5070
|
] });
|
|
5103
5071
|
} else {
|
|
5104
|
-
composerArea = /* @__PURE__ */
|
|
5072
|
+
composerArea = /* @__PURE__ */ jsx21(ReadOnlyBanner, { label: s.chatClosed, ctaLabel: s.startNewConversation, onNewChat: onClear });
|
|
5105
5073
|
}
|
|
5106
|
-
return /* @__PURE__ */
|
|
5107
|
-
view === "history" ? /* @__PURE__ */
|
|
5074
|
+
return /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5075
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
5108
5076
|
HistoryHeader,
|
|
5109
5077
|
{
|
|
5110
5078
|
strings: s,
|
|
@@ -5112,33 +5080,33 @@ function PanelContent(props2) {
|
|
|
5112
5080
|
onClose,
|
|
5113
5081
|
showClose: canShowClose(options.mode, panelSize, options.actions)
|
|
5114
5082
|
}
|
|
5115
|
-
) : /* @__PURE__ */
|
|
5116
|
-
onBack ? /* @__PURE__ */
|
|
5083
|
+
) : /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, "data-testid": TID.panelHeader, children: [
|
|
5084
|
+
onBack ? /* @__PURE__ */ jsx21(
|
|
5117
5085
|
"button",
|
|
5118
5086
|
{
|
|
5119
5087
|
type: "button",
|
|
5120
|
-
class: `${
|
|
5088
|
+
class: `${p17}-icon-btn`,
|
|
5121
5089
|
onClick: onBack,
|
|
5122
5090
|
"aria-label": s.moduleBack,
|
|
5123
5091
|
title: s.moduleBack,
|
|
5124
|
-
children: /* @__PURE__ */
|
|
5092
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
5125
5093
|
}
|
|
5126
5094
|
) : null,
|
|
5127
|
-
agent ? /* @__PURE__ */
|
|
5128
|
-
/* @__PURE__ */
|
|
5095
|
+
agent ? /* @__PURE__ */ jsx21(AgentBadge, { agent }) : /* @__PURE__ */ jsx21("h1", { children: s.panelTitle }),
|
|
5096
|
+
/* @__PURE__ */ jsx21(HeaderActions, { panelProps: props2, variant: "chat" })
|
|
5129
5097
|
] }),
|
|
5130
|
-
view === "history" ? /* @__PURE__ */
|
|
5098
|
+
view === "history" ? /* @__PURE__ */ jsx21(
|
|
5131
5099
|
ChatHistoryPane,
|
|
5132
5100
|
{
|
|
5133
5101
|
transport,
|
|
5134
5102
|
strings: s,
|
|
5135
5103
|
visitorId,
|
|
5136
|
-
onSelect: (chat) => onSelectHistoryChat(chat.
|
|
5104
|
+
onSelect: (chat) => onSelectHistoryChat(chat.conversationId),
|
|
5137
5105
|
onNewChat
|
|
5138
5106
|
}
|
|
5139
|
-
) : /* @__PURE__ */
|
|
5140
|
-
/* @__PURE__ */
|
|
5141
|
-
/* @__PURE__ */
|
|
5107
|
+
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5108
|
+
/* @__PURE__ */ jsx21(DropZone, { visible: dragOver, strings: s }),
|
|
5109
|
+
/* @__PURE__ */ jsx21(
|
|
5142
5110
|
MessageList,
|
|
5143
5111
|
{
|
|
5144
5112
|
messagesSig,
|
|
@@ -5148,16 +5116,13 @@ function PanelContent(props2) {
|
|
|
5148
5116
|
showToolCalls: options.showToolCalls,
|
|
5149
5117
|
loading: loadingMessages,
|
|
5150
5118
|
idle: !isStreaming,
|
|
5151
|
-
tool
|
|
5152
|
-
inlineForm,
|
|
5153
|
-
onFormSubmit,
|
|
5154
|
-
onFormSkip
|
|
5119
|
+
tool
|
|
5155
5120
|
}
|
|
5156
5121
|
),
|
|
5157
5122
|
composerArea,
|
|
5158
|
-
/* @__PURE__ */
|
|
5123
|
+
/* @__PURE__ */ jsx21(ComposerFooter, { disclaimer: options.composerDisclaimer })
|
|
5159
5124
|
] }),
|
|
5160
|
-
options.size.resize?.enabled ? /* @__PURE__ */
|
|
5125
|
+
options.size.resize?.enabled ? /* @__PURE__ */ jsx21(
|
|
5161
5126
|
ResizeGrip,
|
|
5162
5127
|
{
|
|
5163
5128
|
panelEl: containerEl,
|
|
@@ -5176,55 +5141,55 @@ function HistoryHeader({
|
|
|
5176
5141
|
onClose,
|
|
5177
5142
|
showClose
|
|
5178
5143
|
}) {
|
|
5179
|
-
return /* @__PURE__ */
|
|
5180
|
-
/* @__PURE__ */
|
|
5144
|
+
return /* @__PURE__ */ jsxs16("header", { class: `${p17}-header`, children: [
|
|
5145
|
+
/* @__PURE__ */ jsx21(
|
|
5181
5146
|
"button",
|
|
5182
5147
|
{
|
|
5183
5148
|
type: "button",
|
|
5184
|
-
class: `${
|
|
5149
|
+
class: `${p17}-icon-btn`,
|
|
5185
5150
|
onClick: onBack,
|
|
5186
5151
|
"aria-label": strings.historyBack,
|
|
5187
5152
|
title: strings.historyBack,
|
|
5188
|
-
children: /* @__PURE__ */
|
|
5153
|
+
children: /* @__PURE__ */ jsx21(BackIcon, {})
|
|
5189
5154
|
}
|
|
5190
5155
|
),
|
|
5191
|
-
/* @__PURE__ */
|
|
5192
|
-
showClose ? /* @__PURE__ */
|
|
5156
|
+
/* @__PURE__ */ jsx21("h1", { children: strings.historyTitle }),
|
|
5157
|
+
showClose ? /* @__PURE__ */ jsx21(
|
|
5193
5158
|
"button",
|
|
5194
5159
|
{
|
|
5195
5160
|
type: "button",
|
|
5196
|
-
class: `${
|
|
5161
|
+
class: `${p17}-icon-btn`,
|
|
5197
5162
|
onClick: onClose,
|
|
5198
5163
|
"aria-label": strings.close,
|
|
5199
5164
|
title: strings.close,
|
|
5200
|
-
children: /* @__PURE__ */
|
|
5165
|
+
children: /* @__PURE__ */ jsx21(CloseIcon, {})
|
|
5201
5166
|
}
|
|
5202
5167
|
) : null
|
|
5203
5168
|
] });
|
|
5204
5169
|
}
|
|
5205
5170
|
function ReadOnlyBanner({ label, ctaLabel, onNewChat }) {
|
|
5206
|
-
return /* @__PURE__ */
|
|
5207
|
-
/* @__PURE__ */
|
|
5208
|
-
/* @__PURE__ */
|
|
5171
|
+
return /* @__PURE__ */ jsxs16("div", { class: `${p17}-readonly-banner`, role: "note", children: [
|
|
5172
|
+
/* @__PURE__ */ jsx21("span", { class: `${p17}-readonly-label`, children: label }),
|
|
5173
|
+
/* @__PURE__ */ jsx21("button", { type: "button", class: `${p17}-readonly-cta`, onClick: onNewChat, children: ctaLabel })
|
|
5209
5174
|
] });
|
|
5210
5175
|
}
|
|
5211
5176
|
function ComposerFooter({ disclaimer }) {
|
|
5212
5177
|
if (!disclaimer) return null;
|
|
5213
|
-
return /* @__PURE__ */
|
|
5178
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-composer-footer`, children: /* @__PURE__ */ jsx21("div", { class: `${p17}-disclaimer`, children: disclaimer }) });
|
|
5214
5179
|
}
|
|
5215
5180
|
function PoweredByBar({ poweredBy }) {
|
|
5216
5181
|
if (!poweredBy) return null;
|
|
5217
|
-
return /* @__PURE__ */
|
|
5182
|
+
return /* @__PURE__ */ jsx21("div", { class: `${p17}-poweredby-bar`, children: /* @__PURE__ */ jsx21(PoweredBy, { logoUrl: poweredBy.logoUrl, text: poweredBy.text, href: poweredBy.href }) });
|
|
5218
5183
|
}
|
|
5219
5184
|
function PoweredBy({ logoUrl, text, href }) {
|
|
5220
|
-
const inner = /* @__PURE__ */
|
|
5221
|
-
logoUrl ? /* @__PURE__ */
|
|
5222
|
-
text ? /* @__PURE__ */
|
|
5185
|
+
const inner = /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
5186
|
+
logoUrl ? /* @__PURE__ */ jsx21("img", { class: `${p17}-poweredby-logo`, src: logoUrl, alt: "", loading: "lazy" }) : null,
|
|
5187
|
+
text ? /* @__PURE__ */ jsx21("span", { children: text }) : null
|
|
5223
5188
|
] });
|
|
5224
5189
|
if (href) {
|
|
5225
|
-
return /* @__PURE__ */
|
|
5190
|
+
return /* @__PURE__ */ jsx21("a", { class: `${p17}-poweredby`, href, target: "_blank", rel: "noopener noreferrer", children: inner });
|
|
5226
5191
|
}
|
|
5227
|
-
return /* @__PURE__ */
|
|
5192
|
+
return /* @__PURE__ */ jsx21("span", { class: `${p17}-poweredby`, children: inner });
|
|
5228
5193
|
}
|
|
5229
5194
|
|
|
5230
5195
|
// src/ui/form/form-controller.ts
|
|
@@ -5239,10 +5204,11 @@ function useForms(deps) {
|
|
|
5239
5204
|
}
|
|
5240
5205
|
function createController(depsRef) {
|
|
5241
5206
|
const activeForm = signal5(null);
|
|
5242
|
-
const
|
|
5207
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5208
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5243
5209
|
const isDone = (form) => {
|
|
5244
5210
|
if (form.frequency === "always") return false;
|
|
5245
|
-
if (form.frequency === "
|
|
5211
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5246
5212
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5247
5213
|
};
|
|
5248
5214
|
const fire = (kind, param) => {
|
|
@@ -5265,7 +5231,7 @@ function createController(depsRef) {
|
|
|
5265
5231
|
if (!active) return;
|
|
5266
5232
|
activeForm.value = null;
|
|
5267
5233
|
const { form, trigger } = active;
|
|
5268
|
-
if (form.frequency === "
|
|
5234
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5269
5235
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5270
5236
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5271
5237
|
};
|
|
@@ -5299,34 +5265,34 @@ function whenPasses(form, d) {
|
|
|
5299
5265
|
}
|
|
5300
5266
|
|
|
5301
5267
|
// src/ui/sidebar.tsx
|
|
5302
|
-
import { Fragment as Fragment4, jsx as
|
|
5268
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
5303
5269
|
function Sidebar(props2) {
|
|
5304
|
-
const
|
|
5270
|
+
const p33 = BRAND.cssPrefix;
|
|
5305
5271
|
const { site, blocks, strings, collapsed } = props2;
|
|
5306
5272
|
const navigation = blocks?.navigation ?? [];
|
|
5307
5273
|
const linkCards = blocks?.linkCards ?? [];
|
|
5308
5274
|
const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
|
|
5309
|
-
return /* @__PURE__ */
|
|
5310
|
-
/* @__PURE__ */
|
|
5311
|
-
/* @__PURE__ */
|
|
5312
|
-
/* @__PURE__ */
|
|
5275
|
+
return /* @__PURE__ */ jsxs17("aside", { class: `${p33}-sidebar`, "data-collapsed": collapsed ? "true" : "false", "data-testid": TID.sidebar, children: [
|
|
5276
|
+
/* @__PURE__ */ jsxs17("div", { class: `${p33}-sidebar-header`, children: [
|
|
5277
|
+
/* @__PURE__ */ jsx22(SidebarBrand, { site }),
|
|
5278
|
+
/* @__PURE__ */ jsx22(
|
|
5313
5279
|
"button",
|
|
5314
5280
|
{
|
|
5315
5281
|
type: "button",
|
|
5316
|
-
class: `${
|
|
5282
|
+
class: `${p33}-sidebar-toggle`,
|
|
5317
5283
|
"aria-label": toggleLabel,
|
|
5318
5284
|
"aria-expanded": collapsed ? "false" : "true",
|
|
5319
5285
|
title: toggleLabel,
|
|
5320
5286
|
onClick: props2.onToggleCollapsed,
|
|
5321
5287
|
"data-testid": TID.sidebarToggle,
|
|
5322
|
-
children: /* @__PURE__ */
|
|
5288
|
+
children: /* @__PURE__ */ jsx22(SidebarToggleIcon, { collapsed })
|
|
5323
5289
|
}
|
|
5324
5290
|
)
|
|
5325
5291
|
] }),
|
|
5326
|
-
collapsed ? null : /* @__PURE__ */
|
|
5327
|
-
navigation.length > 0 ? /* @__PURE__ */
|
|
5328
|
-
linkCards.length > 0 ? /* @__PURE__ */
|
|
5329
|
-
props2.showConversations ? /* @__PURE__ */
|
|
5292
|
+
collapsed ? null : /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
5293
|
+
navigation.length > 0 ? /* @__PURE__ */ jsx22("nav", { class: `${p33}-sidebar-section`, "data-section": "navigation", children: /* @__PURE__ */ jsx22(SidebarNav, { items: navigation }) }) : null,
|
|
5294
|
+
linkCards.length > 0 ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-section`, "data-section": "link-cards", children: /* @__PURE__ */ jsx22(SidebarCards, { items: linkCards }) }) : null,
|
|
5295
|
+
props2.showConversations ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-conversations`, children: /* @__PURE__ */ jsx22(
|
|
5330
5296
|
ConversationList,
|
|
5331
5297
|
{
|
|
5332
5298
|
transport: props2.transport,
|
|
@@ -5340,18 +5306,18 @@ function Sidebar(props2) {
|
|
|
5340
5306
|
] });
|
|
5341
5307
|
}
|
|
5342
5308
|
function SidebarBrand({ site }) {
|
|
5343
|
-
const
|
|
5309
|
+
const p33 = BRAND.cssPrefix;
|
|
5344
5310
|
if (site?.logo?.url) {
|
|
5345
5311
|
const alt = site.logo.alt ?? site.title ?? "Logo";
|
|
5346
|
-
return /* @__PURE__ */
|
|
5347
|
-
site.logoDark?.url ? /* @__PURE__ */
|
|
5348
|
-
/* @__PURE__ */
|
|
5312
|
+
return /* @__PURE__ */ jsxs17("picture", { children: [
|
|
5313
|
+
site.logoDark?.url ? /* @__PURE__ */ jsx22("source", { srcset: site.logoDark.url, media: "(prefers-color-scheme: dark)" }) : null,
|
|
5314
|
+
/* @__PURE__ */ jsx22("img", { class: `${p33}-sidebar-logo`, src: site.logo.url, alt })
|
|
5349
5315
|
] });
|
|
5350
5316
|
}
|
|
5351
|
-
return /* @__PURE__ */
|
|
5317
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-title`, children: site?.title ?? BRAND.name });
|
|
5352
5318
|
}
|
|
5353
5319
|
function SidebarToggleIcon({ collapsed }) {
|
|
5354
|
-
return /* @__PURE__ */
|
|
5320
|
+
return /* @__PURE__ */ jsx22(
|
|
5355
5321
|
"svg",
|
|
5356
5322
|
{
|
|
5357
5323
|
width: "16",
|
|
@@ -5361,38 +5327,38 @@ function SidebarToggleIcon({ collapsed }) {
|
|
|
5361
5327
|
stroke: "currentColor",
|
|
5362
5328
|
"stroke-width": "2",
|
|
5363
5329
|
"aria-hidden": "true",
|
|
5364
|
-
children: collapsed ? /* @__PURE__ */
|
|
5330
|
+
children: collapsed ? /* @__PURE__ */ jsx22("polyline", { points: "9 6 15 12 9 18" }) : /* @__PURE__ */ jsx22("polyline", { points: "15 6 9 12 15 18" })
|
|
5365
5331
|
}
|
|
5366
5332
|
);
|
|
5367
5333
|
}
|
|
5368
5334
|
function SidebarNav({ items }) {
|
|
5369
|
-
const
|
|
5370
|
-
return /* @__PURE__ */
|
|
5335
|
+
const p33 = BRAND.cssPrefix;
|
|
5336
|
+
return /* @__PURE__ */ jsx22("ul", { class: `${p33}-sidebar-nav`, children: items.map((item) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsxs17(
|
|
5371
5337
|
"a",
|
|
5372
5338
|
{
|
|
5373
|
-
class: `${
|
|
5339
|
+
class: `${p33}-sidebar-nav-item`,
|
|
5374
5340
|
href: item.href,
|
|
5375
5341
|
target: item.href ? "_blank" : void 0,
|
|
5376
5342
|
rel: item.href ? "noreferrer" : void 0,
|
|
5377
5343
|
children: [
|
|
5378
|
-
item.icon ? /* @__PURE__ */
|
|
5379
|
-
/* @__PURE__ */
|
|
5344
|
+
item.icon ? /* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-icon`, "data-icon": item.icon }) : null,
|
|
5345
|
+
/* @__PURE__ */ jsx22("span", { class: `${p33}-sidebar-nav-label`, children: item.label })
|
|
5380
5346
|
]
|
|
5381
5347
|
}
|
|
5382
5348
|
) }, item.id ?? item.label)) });
|
|
5383
5349
|
}
|
|
5384
5350
|
function SidebarCards({ items }) {
|
|
5385
|
-
const
|
|
5386
|
-
return /* @__PURE__ */
|
|
5351
|
+
const p33 = BRAND.cssPrefix;
|
|
5352
|
+
return /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-cards`, children: items.map((item) => /* @__PURE__ */ jsxs17(
|
|
5387
5353
|
"a",
|
|
5388
5354
|
{
|
|
5389
|
-
class: `${
|
|
5355
|
+
class: `${p33}-sidebar-card`,
|
|
5390
5356
|
href: item.href,
|
|
5391
5357
|
target: item.href ? "_blank" : void 0,
|
|
5392
5358
|
rel: item.href ? "noreferrer" : void 0,
|
|
5393
5359
|
children: [
|
|
5394
|
-
/* @__PURE__ */
|
|
5395
|
-
item.description ? /* @__PURE__ */
|
|
5360
|
+
/* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-label`, children: item.label }),
|
|
5361
|
+
item.description ? /* @__PURE__ */ jsx22("div", { class: `${p33}-sidebar-card-desc`, children: item.description }) : null
|
|
5396
5362
|
]
|
|
5397
5363
|
},
|
|
5398
5364
|
item.id ?? item.label
|
|
@@ -5400,11 +5366,11 @@ function SidebarCards({ items }) {
|
|
|
5400
5366
|
}
|
|
5401
5367
|
|
|
5402
5368
|
// src/ui/page-shell.tsx
|
|
5403
|
-
import { jsx as
|
|
5404
|
-
var
|
|
5369
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
5370
|
+
var p18 = BRAND.cssPrefix;
|
|
5405
5371
|
function PageShell(props2) {
|
|
5406
|
-
return /* @__PURE__ */
|
|
5407
|
-
/* @__PURE__ */
|
|
5372
|
+
return /* @__PURE__ */ jsxs18("main", { class: `${p18}-page-shell`, "data-sidebar-collapsed": props2.sidebarCollapsed ? "true" : "false", children: [
|
|
5373
|
+
/* @__PURE__ */ jsx23(
|
|
5408
5374
|
Sidebar,
|
|
5409
5375
|
{
|
|
5410
5376
|
site: props2.site,
|
|
@@ -5419,7 +5385,7 @@ function PageShell(props2) {
|
|
|
5419
5385
|
onToggleCollapsed: props2.onToggleSidebarCollapsed
|
|
5420
5386
|
}
|
|
5421
5387
|
),
|
|
5422
|
-
/* @__PURE__ */
|
|
5388
|
+
/* @__PURE__ */ jsx23("section", { class: `${p18}-page-chat`, "aria-label": "Chat", children: props2.children })
|
|
5423
5389
|
] });
|
|
5424
5390
|
}
|
|
5425
5391
|
|
|
@@ -5469,80 +5435,80 @@ var chatLayout = {
|
|
|
5469
5435
|
import { useEffect as useEffect11, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
|
|
5470
5436
|
|
|
5471
5437
|
// src/ui/back-header.tsx
|
|
5472
|
-
import { jsx as
|
|
5473
|
-
var
|
|
5438
|
+
import { jsx as jsx24, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
5439
|
+
var p19 = BRAND.cssPrefix;
|
|
5474
5440
|
function TitleBar({ title, actions }) {
|
|
5475
|
-
return /* @__PURE__ */
|
|
5476
|
-
/* @__PURE__ */
|
|
5477
|
-
/* @__PURE__ */
|
|
5478
|
-
actions ?? /* @__PURE__ */
|
|
5441
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-variant": "title", children: [
|
|
5442
|
+
/* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" }),
|
|
5443
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5444
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5479
5445
|
] });
|
|
5480
5446
|
}
|
|
5481
5447
|
function BackHeader({ title, backLabel, onBack, actions, testid }) {
|
|
5482
|
-
return /* @__PURE__ */
|
|
5483
|
-
/* @__PURE__ */
|
|
5484
|
-
/* @__PURE__ */
|
|
5485
|
-
actions ?? /* @__PURE__ */
|
|
5448
|
+
return /* @__PURE__ */ jsxs19("header", { class: `${p19}-back-header`, "data-testid": testid, children: [
|
|
5449
|
+
/* @__PURE__ */ jsx24("button", { type: "button", class: `${p19}-icon-btn`, onClick: onBack, "aria-label": backLabel, title: backLabel, children: /* @__PURE__ */ jsx24(BackIcon, {}) }),
|
|
5450
|
+
/* @__PURE__ */ jsx24("h1", { class: `${p19}-back-title`, children: title }),
|
|
5451
|
+
actions ?? /* @__PURE__ */ jsx24("span", { class: `${p19}-back-spacer`, "aria-hidden": "true" })
|
|
5486
5452
|
] });
|
|
5487
5453
|
}
|
|
5488
5454
|
|
|
5489
5455
|
// src/ui/home-search.tsx
|
|
5490
|
-
import { jsx as
|
|
5491
|
-
var
|
|
5456
|
+
import { jsx as jsx25, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
5457
|
+
var p20 = BRAND.cssPrefix;
|
|
5492
5458
|
function HomeSearchButton({ placeholder, onActivate }) {
|
|
5493
|
-
return /* @__PURE__ */
|
|
5494
|
-
/* @__PURE__ */
|
|
5495
|
-
/* @__PURE__ */
|
|
5459
|
+
return /* @__PURE__ */ jsxs20("button", { type: "button", class: `${p20}-home-search`, onClick: onActivate, "data-testid": TID.homeSearch, children: [
|
|
5460
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-text`, children: placeholder }),
|
|
5461
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
5496
5462
|
] });
|
|
5497
5463
|
}
|
|
5498
5464
|
function HelpSearchInput({ placeholder, value, onInput }) {
|
|
5499
|
-
return /* @__PURE__ */
|
|
5500
|
-
/* @__PURE__ */
|
|
5465
|
+
return /* @__PURE__ */ jsxs20("div", { class: `${p20}-home-search`, "data-input": "true", children: [
|
|
5466
|
+
/* @__PURE__ */ jsx25(
|
|
5501
5467
|
"input",
|
|
5502
5468
|
{
|
|
5503
5469
|
type: "search",
|
|
5504
|
-
class: `${
|
|
5470
|
+
class: `${p20}-home-search-input`,
|
|
5505
5471
|
placeholder,
|
|
5506
5472
|
value,
|
|
5507
5473
|
onInput: (e) => onInput(e.currentTarget.value),
|
|
5508
5474
|
"data-testid": TID.helpSearch
|
|
5509
5475
|
}
|
|
5510
5476
|
),
|
|
5511
|
-
/* @__PURE__ */
|
|
5477
|
+
/* @__PURE__ */ jsx25("span", { class: `${p20}-home-search-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(SearchIcon, {}) })
|
|
5512
5478
|
] });
|
|
5513
5479
|
}
|
|
5514
5480
|
|
|
5515
5481
|
// src/ui/list-row.tsx
|
|
5516
|
-
import { jsx as
|
|
5517
|
-
var
|
|
5482
|
+
import { jsx as jsx26, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
5483
|
+
var p21 = BRAND.cssPrefix;
|
|
5518
5484
|
function ListRow({ title, subtitle, onClick, testid }) {
|
|
5519
|
-
return /* @__PURE__ */
|
|
5520
|
-
/* @__PURE__ */
|
|
5521
|
-
/* @__PURE__ */
|
|
5522
|
-
subtitle ? /* @__PURE__ */
|
|
5485
|
+
return /* @__PURE__ */ jsxs21("button", { type: "button", class: `${p21}-list-row`, onClick, "data-testid": testid, children: [
|
|
5486
|
+
/* @__PURE__ */ jsxs21("span", { class: `${p21}-list-row-body`, children: [
|
|
5487
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-title`, children: title }),
|
|
5488
|
+
subtitle ? /* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-sub`, children: subtitle }) : null
|
|
5523
5489
|
] }),
|
|
5524
|
-
/* @__PURE__ */
|
|
5490
|
+
/* @__PURE__ */ jsx26("span", { class: `${p21}-list-row-chevron`, "aria-hidden": "true", children: /* @__PURE__ */ jsx26(ChevronRightIcon, {}) })
|
|
5525
5491
|
] });
|
|
5526
5492
|
}
|
|
5527
5493
|
|
|
5528
5494
|
// src/ui/module-state.tsx
|
|
5529
|
-
import { jsx as
|
|
5530
|
-
var
|
|
5495
|
+
import { jsx as jsx27, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
5496
|
+
var p22 = BRAND.cssPrefix;
|
|
5531
5497
|
function ModuleState({
|
|
5532
5498
|
tone = "info",
|
|
5533
5499
|
message,
|
|
5534
5500
|
onRetry,
|
|
5535
5501
|
strings
|
|
5536
5502
|
}) {
|
|
5537
|
-
return /* @__PURE__ */
|
|
5538
|
-
/* @__PURE__ */
|
|
5539
|
-
onRetry ? /* @__PURE__ */
|
|
5503
|
+
return /* @__PURE__ */ jsxs22("div", { class: `${p22}-module-empty`, role: tone === "error" ? "alert" : "status", "aria-live": "polite", children: [
|
|
5504
|
+
/* @__PURE__ */ jsx27("span", { children: message }),
|
|
5505
|
+
onRetry ? /* @__PURE__ */ jsx27("button", { type: "button", class: `${p22}-module-retry`, onClick: onRetry, children: strings.errorRetry }) : null
|
|
5540
5506
|
] });
|
|
5541
5507
|
}
|
|
5542
5508
|
|
|
5543
5509
|
// src/ui/modules/help.tsx
|
|
5544
|
-
import { jsx as
|
|
5545
|
-
var
|
|
5510
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
5511
|
+
var p23 = BRAND.cssPrefix;
|
|
5546
5512
|
var log12 = logger.scope("help");
|
|
5547
5513
|
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 });
|
|
5548
5514
|
function groupByCategory(items) {
|
|
@@ -5571,7 +5537,7 @@ function fuzzySearch(items, query) {
|
|
|
5571
5537
|
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);
|
|
5572
5538
|
}
|
|
5573
5539
|
function ArticleRow({ article, nav }) {
|
|
5574
|
-
return /* @__PURE__ */
|
|
5540
|
+
return /* @__PURE__ */ jsx28(
|
|
5575
5541
|
ListRow,
|
|
5576
5542
|
{
|
|
5577
5543
|
title: article.title,
|
|
@@ -5608,46 +5574,46 @@ function HelpRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5608
5574
|
const results = useMemo2(() => fuzzySearch(items, query), [items, query]);
|
|
5609
5575
|
function renderBody() {
|
|
5610
5576
|
if (query.trim().length > 0) {
|
|
5611
|
-
if (results.length === 0) return /* @__PURE__ */
|
|
5612
|
-
return /* @__PURE__ */
|
|
5577
|
+
if (results.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpSearchEmpty, strings });
|
|
5578
|
+
return /* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: results.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) });
|
|
5613
5579
|
}
|
|
5614
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5580
|
+
if (state === "loading") return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpLoading, strings });
|
|
5615
5581
|
if (state === "error") {
|
|
5616
|
-
return /* @__PURE__ */
|
|
5582
|
+
return /* @__PURE__ */ jsx28(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5617
5583
|
}
|
|
5618
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5619
|
-
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */
|
|
5620
|
-
category ? /* @__PURE__ */
|
|
5621
|
-
/* @__PURE__ */
|
|
5584
|
+
if (items.length === 0) return /* @__PURE__ */ jsx28(ModuleState, { message: strings.helpEmpty, strings });
|
|
5585
|
+
return groupByCategory(items).map(([category, rows]) => /* @__PURE__ */ jsxs23("section", { class: `${p23}-help-group`, children: [
|
|
5586
|
+
category ? /* @__PURE__ */ jsx28("h2", { class: `${p23}-help-section-title`, children: category }) : null,
|
|
5587
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-card`, children: rows.map((a) => /* @__PURE__ */ jsx28(ArticleRow, { article: a, nav }, a.id)) })
|
|
5622
5588
|
] }, category));
|
|
5623
5589
|
}
|
|
5624
|
-
return /* @__PURE__ */
|
|
5625
|
-
/* @__PURE__ */
|
|
5626
|
-
/* @__PURE__ */
|
|
5627
|
-
/* @__PURE__ */
|
|
5590
|
+
return /* @__PURE__ */ jsxs23("div", { class: `${p23}-module`, children: [
|
|
5591
|
+
/* @__PURE__ */ jsx28(TitleBar, { title: strings.helpTitle, actions: /* @__PURE__ */ jsx28(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5592
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-module-pad`, children: /* @__PURE__ */ jsx28(HelpSearchInput, { placeholder: strings.helpSearchPlaceholder, value: query, onInput: setQuery }) }),
|
|
5593
|
+
/* @__PURE__ */ jsx28("div", { class: `${p23}-help-list`, children: renderBody() })
|
|
5628
5594
|
] });
|
|
5629
5595
|
}
|
|
5630
5596
|
var helpLayout = {
|
|
5631
5597
|
Icon: HelpIcon,
|
|
5632
|
-
Root: (props2) => /* @__PURE__ */
|
|
5598
|
+
Root: (props2) => /* @__PURE__ */ jsx28(HelpRoot, { ...props2 })
|
|
5633
5599
|
};
|
|
5634
5600
|
|
|
5635
5601
|
// src/ui/modules/home.tsx
|
|
5636
5602
|
import { useEffect as useEffect12, useState as useState9 } from "preact/hooks";
|
|
5637
5603
|
|
|
5638
5604
|
// src/ui/home-card.tsx
|
|
5639
|
-
import { jsx as
|
|
5640
|
-
var
|
|
5605
|
+
import { jsx as jsx29 } from "preact/jsx-runtime";
|
|
5606
|
+
var p24 = BRAND.cssPrefix;
|
|
5641
5607
|
function HomeCard({ onClick, children, testid }) {
|
|
5642
5608
|
if (onClick) {
|
|
5643
|
-
return /* @__PURE__ */
|
|
5609
|
+
return /* @__PURE__ */ jsx29("button", { type: "button", class: `${p24}-home-card`, "data-interactive": "true", onClick, "data-testid": testid, children });
|
|
5644
5610
|
}
|
|
5645
|
-
return /* @__PURE__ */
|
|
5611
|
+
return /* @__PURE__ */ jsx29("div", { class: `${p24}-home-card`, "data-testid": testid, children });
|
|
5646
5612
|
}
|
|
5647
5613
|
|
|
5648
5614
|
// src/ui/modules/home.tsx
|
|
5649
|
-
import { Fragment as Fragment5, jsx as
|
|
5650
|
-
var
|
|
5615
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
5616
|
+
var p25 = BRAND.cssPrefix;
|
|
5651
5617
|
var log13 = logger.scope("home");
|
|
5652
5618
|
function resolveGreeting(props2) {
|
|
5653
5619
|
const name = props2.options.userContext?.name;
|
|
@@ -5667,7 +5633,7 @@ function HomeRoot(props2) {
|
|
|
5667
5633
|
useEffect12(() => {
|
|
5668
5634
|
if (!config.showRecentMessages) return;
|
|
5669
5635
|
let cancelled = false;
|
|
5670
|
-
transport.
|
|
5636
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5671
5637
|
return () => {
|
|
5672
5638
|
cancelled = true;
|
|
5673
5639
|
};
|
|
@@ -5684,49 +5650,49 @@ function HomeRoot(props2) {
|
|
|
5684
5650
|
const avatars = config.userAvatars ?? [];
|
|
5685
5651
|
const status = config.status;
|
|
5686
5652
|
const contentTitle = config.contentBlockTitle ? moduleLabel(strings, config.contentBlockTitle) : strings.homeContentTitle;
|
|
5687
|
-
return /* @__PURE__ */
|
|
5688
|
-
/* @__PURE__ */
|
|
5689
|
-
/* @__PURE__ */
|
|
5690
|
-
config.brandName ? /* @__PURE__ */
|
|
5691
|
-
/* @__PURE__ */
|
|
5692
|
-
avatars.length > 0 ? /* @__PURE__ */
|
|
5693
|
-
/* @__PURE__ */
|
|
5653
|
+
return /* @__PURE__ */ jsx30("div", { class: `${p25}-module ${p25}-home`, "data-testid": TID.homeView, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-scroll`, children: [
|
|
5654
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero`, children: [
|
|
5655
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-top`, children: [
|
|
5656
|
+
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" }),
|
|
5657
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-hero-actions`, children: [
|
|
5658
|
+
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,
|
|
5659
|
+
/* @__PURE__ */ jsx30(HeaderActions, { panelProps, variant: "plain" })
|
|
5694
5660
|
] })
|
|
5695
5661
|
] }),
|
|
5696
|
-
config.showGreeting !== false ? /* @__PURE__ */
|
|
5697
|
-
/* @__PURE__ */
|
|
5698
|
-
greeting.subtitle ? /* @__PURE__ */
|
|
5662
|
+
config.showGreeting !== false ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5663
|
+
/* @__PURE__ */ jsx30("h1", { class: `${p25}-home-greeting`, "data-testid": TID.homeGreeting, children: greeting.title }),
|
|
5664
|
+
greeting.subtitle ? /* @__PURE__ */ jsx30("p", { class: `${p25}-home-lead`, children: greeting.subtitle }) : null
|
|
5699
5665
|
] }) : null
|
|
5700
5666
|
] }),
|
|
5701
|
-
/* @__PURE__ */
|
|
5702
|
-
config.showSearchBar !== false ? /* @__PURE__ */
|
|
5667
|
+
/* @__PURE__ */ jsxs24("div", { class: `${p25}-home-cards`, children: [
|
|
5668
|
+
config.showSearchBar !== false ? /* @__PURE__ */ jsx30(
|
|
5703
5669
|
HomeSearchButton,
|
|
5704
5670
|
{
|
|
5705
5671
|
placeholder: strings.homeSearchPlaceholder,
|
|
5706
5672
|
onActivate: () => nav.switchToLayout("help")
|
|
5707
5673
|
}
|
|
5708
5674
|
) : null,
|
|
5709
|
-
recent ? /* @__PURE__ */
|
|
5710
|
-
/* @__PURE__ */
|
|
5711
|
-
/* @__PURE__ */
|
|
5712
|
-
/* @__PURE__ */
|
|
5713
|
-
recent.preview ? /* @__PURE__ */
|
|
5675
|
+
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: [
|
|
5676
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5677
|
+
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5678
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
5679
|
+
recent.preview ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-preview`, children: recent.preview }) : null
|
|
5714
5680
|
] }),
|
|
5715
|
-
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */
|
|
5681
|
+
(recent.unreadCount ?? 0) > 0 ? /* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-dot`, "aria-label": "Unread" }) : null
|
|
5716
5682
|
] }) }) : null,
|
|
5717
|
-
status ? /* @__PURE__ */
|
|
5683
|
+
status ? /* @__PURE__ */ jsx30(
|
|
5718
5684
|
HomeCard,
|
|
5719
5685
|
{
|
|
5720
5686
|
onClick: status.url ? () => nav.push({ kind: "iframe", url: status.url, title: status.text }) : void 0,
|
|
5721
|
-
children: /* @__PURE__ */
|
|
5722
|
-
/* @__PURE__ */
|
|
5723
|
-
/* @__PURE__ */
|
|
5687
|
+
children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-status`, "data-level": status.level ?? "operational", children: [
|
|
5688
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-icon`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(StatusOkIcon, {}) }),
|
|
5689
|
+
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-status-text`, children: status.text })
|
|
5724
5690
|
] })
|
|
5725
5691
|
}
|
|
5726
5692
|
) : null,
|
|
5727
|
-
content.length > 0 ? /* @__PURE__ */
|
|
5728
|
-
/* @__PURE__ */
|
|
5729
|
-
/* @__PURE__ */
|
|
5693
|
+
content.length > 0 ? /* @__PURE__ */ jsxs24("section", { class: `${p25}-home-content`, children: [
|
|
5694
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-title`, children: contentTitle }),
|
|
5695
|
+
/* @__PURE__ */ jsx30("div", { class: `${p25}-home-content-list`, children: content.map((item) => /* @__PURE__ */ jsx30(
|
|
5730
5696
|
ListRow,
|
|
5731
5697
|
{
|
|
5732
5698
|
title: item.title,
|
|
@@ -5742,13 +5708,13 @@ function HomeRoot(props2) {
|
|
|
5742
5708
|
}
|
|
5743
5709
|
var homeLayout = {
|
|
5744
5710
|
Icon: HomeIcon,
|
|
5745
|
-
Root: (props2) => /* @__PURE__ */
|
|
5711
|
+
Root: (props2) => /* @__PURE__ */ jsx30(HomeRoot, { ...props2 })
|
|
5746
5712
|
};
|
|
5747
5713
|
|
|
5748
5714
|
// src/ui/modules/news.tsx
|
|
5749
5715
|
import { useEffect as useEffect13, useState as useState10 } from "preact/hooks";
|
|
5750
|
-
import { jsx as
|
|
5751
|
-
var
|
|
5716
|
+
import { jsx as jsx31, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
5717
|
+
var p26 = BRAND.cssPrefix;
|
|
5752
5718
|
var log14 = logger.scope("news");
|
|
5753
5719
|
function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
5754
5720
|
const tags = config.contentTags;
|
|
@@ -5774,38 +5740,38 @@ function NewsRoot({ transport, strings, config, nav, panelProps }) {
|
|
|
5774
5740
|
};
|
|
5775
5741
|
}, [transport, tags, reloadKey]);
|
|
5776
5742
|
function renderBody() {
|
|
5777
|
-
if (state === "loading") return /* @__PURE__ */
|
|
5743
|
+
if (state === "loading") return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsLoading, strings });
|
|
5778
5744
|
if (state === "error") {
|
|
5779
|
-
return /* @__PURE__ */
|
|
5745
|
+
return /* @__PURE__ */ jsx31(ModuleState, { tone: "error", message: errorMsg, onRetry: () => setReloadKey((k) => k + 1), strings });
|
|
5780
5746
|
}
|
|
5781
|
-
if (items.length === 0) return /* @__PURE__ */
|
|
5782
|
-
return /* @__PURE__ */
|
|
5747
|
+
if (items.length === 0) return /* @__PURE__ */ jsx31(ModuleState, { message: strings.newsEmpty, strings });
|
|
5748
|
+
return /* @__PURE__ */ jsx31("div", { class: `${p26}-news-list`, children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
5783
5749
|
"button",
|
|
5784
5750
|
{
|
|
5785
5751
|
type: "button",
|
|
5786
|
-
class: `${
|
|
5752
|
+
class: `${p26}-news-card`,
|
|
5787
5753
|
onClick: () => nav.push({ kind: "content", id: item.id, title: item.title }),
|
|
5788
5754
|
"data-testid": tid(TID.newsItem, item.id),
|
|
5789
5755
|
children: [
|
|
5790
|
-
item.image ? /* @__PURE__ */
|
|
5791
|
-
/* @__PURE__ */
|
|
5792
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5793
|
-
/* @__PURE__ */
|
|
5794
|
-
item.description ? /* @__PURE__ */
|
|
5756
|
+
item.image ? /* @__PURE__ */ jsx31("img", { class: `${p26}-news-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5757
|
+
/* @__PURE__ */ jsxs25("span", { class: `${p26}-news-body`, children: [
|
|
5758
|
+
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,
|
|
5759
|
+
/* @__PURE__ */ jsx31("span", { class: `${p26}-news-title`, children: item.title }),
|
|
5760
|
+
item.description ? /* @__PURE__ */ jsx31("span", { class: `${p26}-news-summary`, children: item.description }) : null
|
|
5795
5761
|
] })
|
|
5796
5762
|
]
|
|
5797
5763
|
},
|
|
5798
5764
|
item.id
|
|
5799
5765
|
)) });
|
|
5800
5766
|
}
|
|
5801
|
-
return /* @__PURE__ */
|
|
5802
|
-
/* @__PURE__ */
|
|
5803
|
-
/* @__PURE__ */
|
|
5767
|
+
return /* @__PURE__ */ jsxs25("div", { class: `${p26}-module`, children: [
|
|
5768
|
+
/* @__PURE__ */ jsx31(TitleBar, { title: strings.newsTitle, actions: /* @__PURE__ */ jsx31(HeaderActions, { panelProps, variant: "plain" }) }),
|
|
5769
|
+
/* @__PURE__ */ jsx31("div", { class: `${p26}-module-scroll`, children: renderBody() })
|
|
5804
5770
|
] });
|
|
5805
5771
|
}
|
|
5806
5772
|
var newsLayout = {
|
|
5807
5773
|
Icon: NewsIcon,
|
|
5808
|
-
Root: (props2) => /* @__PURE__ */
|
|
5774
|
+
Root: (props2) => /* @__PURE__ */ jsx31(NewsRoot, { ...props2 })
|
|
5809
5775
|
};
|
|
5810
5776
|
|
|
5811
5777
|
// src/ui/modules/registry.ts
|
|
@@ -5817,28 +5783,28 @@ var LAYOUTS = {
|
|
|
5817
5783
|
};
|
|
5818
5784
|
|
|
5819
5785
|
// src/ui/home-tab-bar.tsx
|
|
5820
|
-
import { jsx as
|
|
5821
|
-
var
|
|
5786
|
+
import { jsx as jsx32, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
5787
|
+
var p27 = BRAND.cssPrefix;
|
|
5822
5788
|
function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
5823
|
-
return /* @__PURE__ */
|
|
5789
|
+
return /* @__PURE__ */ jsx32("nav", { class: `${p27}-tabbar`, role: "tablist", "aria-label": strings.panelTitle, children: modules.map((m) => {
|
|
5824
5790
|
const Icon = LAYOUTS[m.layout].Icon;
|
|
5825
5791
|
const selected = m.id === activeTab;
|
|
5826
5792
|
const badge = m.layout === "chat" && unreadCount > 0 ? unreadCount > 9 ? "9+" : String(unreadCount) : null;
|
|
5827
|
-
return /* @__PURE__ */
|
|
5793
|
+
return /* @__PURE__ */ jsxs26(
|
|
5828
5794
|
"button",
|
|
5829
5795
|
{
|
|
5830
5796
|
type: "button",
|
|
5831
5797
|
role: "tab",
|
|
5832
5798
|
"aria-selected": selected,
|
|
5833
|
-
class: `${
|
|
5799
|
+
class: `${p27}-tab`,
|
|
5834
5800
|
onClick: () => onSelect(m.id),
|
|
5835
5801
|
"data-testid": tid(TID.tab, m.id),
|
|
5836
5802
|
children: [
|
|
5837
|
-
/* @__PURE__ */
|
|
5838
|
-
/* @__PURE__ */
|
|
5839
|
-
badge ? /* @__PURE__ */
|
|
5803
|
+
/* @__PURE__ */ jsxs26("span", { class: `${p27}-tab-icon`, "aria-hidden": "true", children: [
|
|
5804
|
+
/* @__PURE__ */ jsx32(Icon, {}),
|
|
5805
|
+
badge ? /* @__PURE__ */ jsx32("span", { class: `${p27}-tab-badge`, "data-testid": TID.tabBadge, children: badge }) : null
|
|
5840
5806
|
] }),
|
|
5841
|
-
/* @__PURE__ */
|
|
5807
|
+
/* @__PURE__ */ jsx32("span", { class: `${p27}-tab-label`, children: moduleLabel(strings, m.label) })
|
|
5842
5808
|
]
|
|
5843
5809
|
},
|
|
5844
5810
|
m.id
|
|
@@ -5847,12 +5813,12 @@ function HomeTabBar({ modules, activeTab, strings, unreadCount, onSelect }) {
|
|
|
5847
5813
|
}
|
|
5848
5814
|
|
|
5849
5815
|
// src/ui/iframe-view.tsx
|
|
5850
|
-
import { jsx as
|
|
5851
|
-
var
|
|
5816
|
+
import { jsx as jsx33, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
5817
|
+
var p28 = BRAND.cssPrefix;
|
|
5852
5818
|
var SANDBOX = "allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
5853
5819
|
function IframeView({ url, title, strings, onBack, actions }) {
|
|
5854
|
-
return /* @__PURE__ */
|
|
5855
|
-
/* @__PURE__ */
|
|
5820
|
+
return /* @__PURE__ */ jsxs27("div", { class: `${p28}-module`, children: [
|
|
5821
|
+
/* @__PURE__ */ jsx33(
|
|
5856
5822
|
BackHeader,
|
|
5857
5823
|
{
|
|
5858
5824
|
title: title || strings.moduleBack,
|
|
@@ -5861,10 +5827,10 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5861
5827
|
actions
|
|
5862
5828
|
}
|
|
5863
5829
|
),
|
|
5864
|
-
/* @__PURE__ */
|
|
5830
|
+
/* @__PURE__ */ jsx33(
|
|
5865
5831
|
"iframe",
|
|
5866
5832
|
{
|
|
5867
|
-
class: `${
|
|
5833
|
+
class: `${p28}-content-frame`,
|
|
5868
5834
|
src: url,
|
|
5869
5835
|
title: title || "content",
|
|
5870
5836
|
sandbox: SANDBOX,
|
|
@@ -5878,8 +5844,8 @@ function IframeView({ url, title, strings, onBack, actions }) {
|
|
|
5878
5844
|
|
|
5879
5845
|
// src/ui/content-view.tsx
|
|
5880
5846
|
import { useCallback as useCallback3, useEffect as useEffect14, useState as useState11 } from "preact/hooks";
|
|
5881
|
-
import { jsx as
|
|
5882
|
-
var
|
|
5847
|
+
import { jsx as jsx34, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
5848
|
+
var p29 = BRAND.cssPrefix;
|
|
5883
5849
|
var log15 = logger.scope("content");
|
|
5884
5850
|
function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
5885
5851
|
const [item, setItem] = useState11(null);
|
|
@@ -5907,17 +5873,17 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5907
5873
|
};
|
|
5908
5874
|
}, [transport, id, reloadKey]);
|
|
5909
5875
|
function renderBody() {
|
|
5910
|
-
if (failed) return /* @__PURE__ */
|
|
5911
|
-
if (item === null) return /* @__PURE__ */
|
|
5912
|
-
return /* @__PURE__ */
|
|
5913
|
-
item.image ? /* @__PURE__ */
|
|
5914
|
-
item.description ? /* @__PURE__ */
|
|
5915
|
-
item.tags && item.tags.length > 0 ? /* @__PURE__ */
|
|
5916
|
-
/* @__PURE__ */
|
|
5876
|
+
if (failed) return /* @__PURE__ */ jsx34(ModuleState, { tone: "error", message: strings.errorGeneric, onRetry: retry, strings });
|
|
5877
|
+
if (item === null) return /* @__PURE__ */ jsx34(ModuleState, { message: strings.contentLoading, strings });
|
|
5878
|
+
return /* @__PURE__ */ jsxs28("article", { class: `${p29}-content`, "data-testid": TID.contentView, children: [
|
|
5879
|
+
item.image ? /* @__PURE__ */ jsx34("img", { class: `${p29}-content-hero`, src: item.image, alt: "", loading: "lazy" }) : null,
|
|
5880
|
+
item.description ? /* @__PURE__ */ jsx34("p", { class: `${p29}-content-subtitle`, children: item.description }) : null,
|
|
5881
|
+
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,
|
|
5882
|
+
/* @__PURE__ */ jsx34(StaticMarkdown, { text: item.content ?? "" })
|
|
5917
5883
|
] });
|
|
5918
5884
|
}
|
|
5919
|
-
return /* @__PURE__ */
|
|
5920
|
-
/* @__PURE__ */
|
|
5885
|
+
return /* @__PURE__ */ jsxs28("div", { class: `${p29}-module`, children: [
|
|
5886
|
+
/* @__PURE__ */ jsx34(
|
|
5921
5887
|
BackHeader,
|
|
5922
5888
|
{
|
|
5923
5889
|
title: item?.title || title || strings.moduleBack,
|
|
@@ -5927,20 +5893,20 @@ function ContentView({ id, title, transport, strings, onBack, actions }) {
|
|
|
5927
5893
|
testid: TID.backHeader
|
|
5928
5894
|
}
|
|
5929
5895
|
),
|
|
5930
|
-
/* @__PURE__ */
|
|
5896
|
+
/* @__PURE__ */ jsx34("div", { class: `${p29}-module-scroll`, "data-testid": TID.contentScroll, children: renderBody() })
|
|
5931
5897
|
] });
|
|
5932
5898
|
}
|
|
5933
5899
|
|
|
5934
5900
|
// src/ui/messenger-home.tsx
|
|
5935
|
-
import { jsx as
|
|
5936
|
-
var
|
|
5901
|
+
import { jsx as jsx35, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
5902
|
+
var p30 = BRAND.cssPrefix;
|
|
5937
5903
|
function MessengerHome({
|
|
5938
5904
|
panelProps,
|
|
5939
5905
|
enabledModules,
|
|
5940
5906
|
nav,
|
|
5941
5907
|
unreadCount,
|
|
5942
|
-
|
|
5943
|
-
|
|
5908
|
+
onSelectConversation,
|
|
5909
|
+
onStartNewConversation,
|
|
5944
5910
|
onSetPanelSize
|
|
5945
5911
|
}) {
|
|
5946
5912
|
const options = panelProps.options;
|
|
@@ -5989,8 +5955,8 @@ function MessengerHome({
|
|
|
5989
5955
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
5990
5956
|
if (target) nav.switchTab(target.id);
|
|
5991
5957
|
},
|
|
5992
|
-
|
|
5993
|
-
|
|
5958
|
+
selectConversation: onSelectConversation,
|
|
5959
|
+
startNewConversation: onStartNewConversation
|
|
5994
5960
|
};
|
|
5995
5961
|
const screenProps = (module) => ({
|
|
5996
5962
|
options,
|
|
@@ -6001,12 +5967,12 @@ function MessengerHome({
|
|
|
6001
5967
|
nav: moduleNav,
|
|
6002
5968
|
panelProps
|
|
6003
5969
|
});
|
|
6004
|
-
const plainActions = /* @__PURE__ */
|
|
5970
|
+
const plainActions = /* @__PURE__ */ jsx35(HeaderActions, { panelProps, variant: "plain" });
|
|
6005
5971
|
let body;
|
|
6006
5972
|
if (top?.kind === "iframe") {
|
|
6007
|
-
body = /* @__PURE__ */
|
|
5973
|
+
body = /* @__PURE__ */ jsx35(IframeView, { url: top.url, title: top.title, strings, onBack: nav.pop, actions: plainActions });
|
|
6008
5974
|
} else if (top?.kind === "content") {
|
|
6009
|
-
body = /* @__PURE__ */
|
|
5975
|
+
body = /* @__PURE__ */ jsx35(
|
|
6010
5976
|
ContentView,
|
|
6011
5977
|
{
|
|
6012
5978
|
id: top.id,
|
|
@@ -6018,7 +5984,7 @@ function MessengerHome({
|
|
|
6018
5984
|
}
|
|
6019
5985
|
);
|
|
6020
5986
|
} else if (activeModule?.layout === "chat") {
|
|
6021
|
-
body = /* @__PURE__ */
|
|
5987
|
+
body = /* @__PURE__ */ jsx35(
|
|
6022
5988
|
PanelContent,
|
|
6023
5989
|
{
|
|
6024
5990
|
...panelProps,
|
|
@@ -6029,23 +5995,23 @@ function MessengerHome({
|
|
|
6029
5995
|
);
|
|
6030
5996
|
} else if (activeModule) {
|
|
6031
5997
|
const Root = LAYOUTS[activeModule.layout].Root;
|
|
6032
|
-
body = Root ? /* @__PURE__ */
|
|
5998
|
+
body = Root ? /* @__PURE__ */ jsx35(Root, { ...screenProps(activeModule) }, activeModule.id) : null;
|
|
6033
5999
|
} else {
|
|
6034
6000
|
body = null;
|
|
6035
6001
|
}
|
|
6036
|
-
return /* @__PURE__ */
|
|
6002
|
+
return /* @__PURE__ */ jsxs29(
|
|
6037
6003
|
"div",
|
|
6038
6004
|
{
|
|
6039
6005
|
ref: containerRef,
|
|
6040
|
-
class: `${
|
|
6006
|
+
class: `${p30}-panel ${p30}-messenger`,
|
|
6041
6007
|
role: "dialog",
|
|
6042
6008
|
"aria-modal": "false",
|
|
6043
6009
|
"aria-label": strings.panelTitle,
|
|
6044
6010
|
style: { position: "relative" },
|
|
6045
6011
|
"data-testid": TID.messengerHome,
|
|
6046
6012
|
children: [
|
|
6047
|
-
/* @__PURE__ */
|
|
6048
|
-
showTabBar ? /* @__PURE__ */
|
|
6013
|
+
/* @__PURE__ */ jsx35("div", { class: `${p30}-messenger-body`, children: body }),
|
|
6014
|
+
showTabBar ? /* @__PURE__ */ jsx35(
|
|
6049
6015
|
HomeTabBar,
|
|
6050
6016
|
{
|
|
6051
6017
|
modules: enabledModules,
|
|
@@ -6055,8 +6021,8 @@ function MessengerHome({
|
|
|
6055
6021
|
onSelect: nav.switchTab
|
|
6056
6022
|
}
|
|
6057
6023
|
) : null,
|
|
6058
|
-
/* @__PURE__ */
|
|
6059
|
-
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */
|
|
6024
|
+
/* @__PURE__ */ jsx35(PoweredByBar, { poweredBy: options.poweredBy }),
|
|
6025
|
+
options.size.resize?.enabled && !(activeModule?.layout === "chat" && !top) ? /* @__PURE__ */ jsx35(
|
|
6060
6026
|
ResizeGrip,
|
|
6061
6027
|
{
|
|
6062
6028
|
panelEl: containerRef.current,
|
|
@@ -6073,29 +6039,29 @@ function MessengerHome({
|
|
|
6073
6039
|
}
|
|
6074
6040
|
|
|
6075
6041
|
// src/ui/modules-empty.tsx
|
|
6076
|
-
import { jsx as
|
|
6077
|
-
var
|
|
6042
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
6043
|
+
var p31 = BRAND.cssPrefix;
|
|
6078
6044
|
function ModulesEmpty({ strings, onClose }) {
|
|
6079
|
-
return /* @__PURE__ */
|
|
6045
|
+
return /* @__PURE__ */ jsxs30(
|
|
6080
6046
|
"div",
|
|
6081
6047
|
{
|
|
6082
|
-
class: `${
|
|
6048
|
+
class: `${p31}-panel ${p31}-modules-empty`,
|
|
6083
6049
|
role: "dialog",
|
|
6084
6050
|
"aria-label": strings.panelTitle,
|
|
6085
6051
|
"data-testid": TID.modulesEmpty,
|
|
6086
6052
|
children: [
|
|
6087
|
-
onClose ? /* @__PURE__ */
|
|
6053
|
+
onClose ? /* @__PURE__ */ jsx36(
|
|
6088
6054
|
"button",
|
|
6089
6055
|
{
|
|
6090
6056
|
type: "button",
|
|
6091
|
-
class: `${
|
|
6057
|
+
class: `${p31}-icon-btn ${p31}-modules-empty-close`,
|
|
6092
6058
|
onClick: onClose,
|
|
6093
6059
|
"aria-label": strings.close,
|
|
6094
6060
|
title: strings.close,
|
|
6095
|
-
children: /* @__PURE__ */
|
|
6061
|
+
children: /* @__PURE__ */ jsx36(CloseIcon, {})
|
|
6096
6062
|
}
|
|
6097
6063
|
) : null,
|
|
6098
|
-
/* @__PURE__ */
|
|
6064
|
+
/* @__PURE__ */ jsx36("p", { class: `${p31}-modules-empty-text`, children: strings.modulesEmpty })
|
|
6099
6065
|
]
|
|
6100
6066
|
}
|
|
6101
6067
|
);
|
|
@@ -6122,6 +6088,7 @@ function animateTypewriter(msg, text, charsPerSecond, abort) {
|
|
|
6122
6088
|
part.textSig.value = text;
|
|
6123
6089
|
part.doneSig.value = true;
|
|
6124
6090
|
msg.status = "complete";
|
|
6091
|
+
msg.partsSig.value = [...msg.partsSig.value];
|
|
6125
6092
|
resolve();
|
|
6126
6093
|
};
|
|
6127
6094
|
if (typeof requestAnimationFrame === "undefined") {
|
|
@@ -6166,9 +6133,9 @@ function useLauncherCallout({ callout, persistence }) {
|
|
|
6166
6133
|
}
|
|
6167
6134
|
|
|
6168
6135
|
// src/ui/app.tsx
|
|
6169
|
-
import { jsx as
|
|
6136
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
6170
6137
|
var log16 = logger.scope("app");
|
|
6171
|
-
var
|
|
6138
|
+
var p32 = BRAND.cssPrefix;
|
|
6172
6139
|
function App({ options, hostElement, bus }) {
|
|
6173
6140
|
const [persistence] = useState13(() => createPersistence(options.widgetId, options.storage));
|
|
6174
6141
|
const [visitorId, setVisitorId] = useState13(() => persistence.getVisitorId());
|
|
@@ -6177,7 +6144,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6177
6144
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6178
6145
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6179
6146
|
);
|
|
6180
|
-
const
|
|
6147
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6181
6148
|
const messagesSig = useSignal2([]);
|
|
6182
6149
|
const unreadCountSig = useSignal2(0);
|
|
6183
6150
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6199,7 +6166,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6199
6166
|
const homeNav = homeNavRef.current;
|
|
6200
6167
|
const chatTabIdRef = useRef9(void 0);
|
|
6201
6168
|
chatTabIdRef.current = chatTabId();
|
|
6202
|
-
const [
|
|
6169
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6203
6170
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6204
6171
|
const initialPanelRef = useRef9(
|
|
6205
6172
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6279,7 +6246,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6279
6246
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6280
6247
|
}, [options.mode, options.size, persistence]);
|
|
6281
6248
|
useEffect17(() => {
|
|
6282
|
-
if (!
|
|
6249
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6283
6250
|
initialPanelApplied.current = true;
|
|
6284
6251
|
const state = resolveInitialPanelState(
|
|
6285
6252
|
options,
|
|
@@ -6289,12 +6256,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6289
6256
|
);
|
|
6290
6257
|
setIsOpen(state.panelOpen);
|
|
6291
6258
|
setPanelSize(state.panelSize);
|
|
6292
|
-
}, [
|
|
6259
|
+
}, [conversationReady, options, persistence]);
|
|
6293
6260
|
const homeNavSeeded = useRef9(false);
|
|
6294
6261
|
const resumeActiveRef = useRef9(false);
|
|
6295
6262
|
const resumeBubbleRef = useRef9(null);
|
|
6296
6263
|
useEffect17(() => {
|
|
6297
|
-
if (!
|
|
6264
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6298
6265
|
homeNavSeeded.current = true;
|
|
6299
6266
|
if (resumeActiveRef.current) {
|
|
6300
6267
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6302,7 +6269,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6302
6269
|
return;
|
|
6303
6270
|
}
|
|
6304
6271
|
homeNav.reset(landingTab());
|
|
6305
|
-
}, [
|
|
6272
|
+
}, [conversationReady]);
|
|
6306
6273
|
const playWelcome = useCallback6(
|
|
6307
6274
|
(welcomeMessages) => {
|
|
6308
6275
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6321,21 +6288,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6321
6288
|
[messagesSig, options.welcome]
|
|
6322
6289
|
);
|
|
6323
6290
|
const connectGenRef = useRef9(0);
|
|
6324
|
-
const
|
|
6291
|
+
const runStartConversation = useCallback6(
|
|
6325
6292
|
async ({ newConversation }) => {
|
|
6326
6293
|
const myGen = ++connectGenRef.current;
|
|
6327
6294
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6328
|
-
const persistedChatId =
|
|
6329
|
-
const
|
|
6330
|
-
if (
|
|
6331
|
-
|
|
6332
|
-
persistence.
|
|
6295
|
+
const persistedChatId = conversationIdSig.value;
|
|
6296
|
+
const conversationId = newConversation || !persistedChatId ? uuid7() : persistedChatId;
|
|
6297
|
+
if (conversationId !== persistedChatId) {
|
|
6298
|
+
conversationIdSig.value = conversationId;
|
|
6299
|
+
persistence.saveConversationId(conversationId);
|
|
6333
6300
|
}
|
|
6334
6301
|
let res;
|
|
6335
6302
|
try {
|
|
6336
|
-
res = await transport.
|
|
6303
|
+
res = await transport.startConversation({
|
|
6337
6304
|
visitorId,
|
|
6338
|
-
|
|
6305
|
+
conversationId,
|
|
6339
6306
|
userPrefs: persistence.loadUserPrefs(),
|
|
6340
6307
|
locale: options.locale
|
|
6341
6308
|
});
|
|
@@ -6343,7 +6310,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6343
6310
|
if (isStale()) return;
|
|
6344
6311
|
bus.emit("error", err);
|
|
6345
6312
|
options.onError?.(err);
|
|
6346
|
-
if (!newConversation)
|
|
6313
|
+
if (!newConversation) setConversationReady(true);
|
|
6347
6314
|
return;
|
|
6348
6315
|
}
|
|
6349
6316
|
if (isStale()) return;
|
|
@@ -6357,12 +6324,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6357
6324
|
reason: res.rebind?.visitorId
|
|
6358
6325
|
});
|
|
6359
6326
|
}
|
|
6360
|
-
if (res.
|
|
6361
|
-
log16.info("
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6327
|
+
if (res.conversationId && res.conversationId !== conversationId) {
|
|
6328
|
+
log16.info("conversation rebound", {
|
|
6329
|
+
previous: conversationId,
|
|
6330
|
+
current: res.conversationId,
|
|
6331
|
+
reason: res.rebind?.conversationId
|
|
6332
|
+
});
|
|
6333
|
+
bus.emit("conversationRebound", {
|
|
6334
|
+
previous: conversationId,
|
|
6335
|
+
current: res.conversationId,
|
|
6336
|
+
reason: res.rebind?.conversationId
|
|
6366
6337
|
});
|
|
6367
6338
|
}
|
|
6368
6339
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6379,36 +6350,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6379
6350
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6380
6351
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6381
6352
|
}
|
|
6382
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6353
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6383
6354
|
if (isResume) {
|
|
6384
6355
|
setLoadingMessages(true);
|
|
6385
6356
|
try {
|
|
6386
|
-
const chat = res.messages?.length ? {
|
|
6357
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6387
6358
|
if (isStale()) return;
|
|
6388
6359
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6389
6360
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6390
|
-
if (loaded.length || tail.length)
|
|
6391
|
-
|
|
6392
|
-
|
|
6361
|
+
if (loaded.length || tail.length) {
|
|
6362
|
+
messagesSig.value = [...loaded, ...tail];
|
|
6363
|
+
setCanSend(chat.canContinue ?? true);
|
|
6364
|
+
setSuggestions(chat.suggestions ?? []);
|
|
6365
|
+
} else {
|
|
6366
|
+
playWelcome(res.welcome?.messages);
|
|
6367
|
+
}
|
|
6393
6368
|
} catch (err) {
|
|
6394
6369
|
if (isStale()) return;
|
|
6395
|
-
log16.warn("
|
|
6396
|
-
|
|
6397
|
-
persistence.
|
|
6370
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6371
|
+
conversationIdSig.value = void 0;
|
|
6372
|
+
persistence.saveConversationId(void 0);
|
|
6398
6373
|
} finally {
|
|
6399
6374
|
if (!isStale()) setLoadingMessages(false);
|
|
6400
6375
|
}
|
|
6401
6376
|
} else {
|
|
6402
|
-
|
|
6403
|
-
persistence.
|
|
6377
|
+
conversationIdSig.value = res.conversationId;
|
|
6378
|
+
persistence.saveConversationId(res.conversationId);
|
|
6404
6379
|
playWelcome(res.welcome?.messages);
|
|
6405
6380
|
}
|
|
6406
6381
|
if (!newConversation) {
|
|
6407
|
-
bus.emit("
|
|
6408
|
-
|
|
6382
|
+
bus.emit("conversationStarted", res);
|
|
6383
|
+
setConversationReady(true);
|
|
6409
6384
|
}
|
|
6410
6385
|
},
|
|
6411
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6386
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6412
6387
|
);
|
|
6413
6388
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6414
6389
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6462,11 +6437,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6462
6437
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6463
6438
|
);
|
|
6464
6439
|
useEffect17(() => {
|
|
6465
|
-
void
|
|
6466
|
-
const
|
|
6440
|
+
void runStartConversation({ newConversation: false });
|
|
6441
|
+
const persistedConversation = conversationIdSig.value;
|
|
6467
6442
|
let resume = null;
|
|
6468
|
-
if (
|
|
6469
|
-
transport.primeIdentity(visitorId,
|
|
6443
|
+
if (persistedConversation) {
|
|
6444
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6470
6445
|
resume = transport.resumeStream();
|
|
6471
6446
|
void runResume(resume);
|
|
6472
6447
|
}
|
|
@@ -6477,10 +6452,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6477
6452
|
}, []);
|
|
6478
6453
|
const lastUserSig = useRef9(userSig);
|
|
6479
6454
|
useEffect17(() => {
|
|
6480
|
-
if (!
|
|
6455
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6481
6456
|
lastUserSig.current = userSig;
|
|
6482
|
-
void
|
|
6483
|
-
}, [userSig,
|
|
6457
|
+
void runStartConversation({ newConversation: false });
|
|
6458
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6484
6459
|
useEffect17(() => {
|
|
6485
6460
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6486
6461
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6506,14 +6481,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6506
6481
|
}, [isOpen, options.mode]);
|
|
6507
6482
|
const streamAssistant = useCallback6(
|
|
6508
6483
|
async (assistantMsg, trigger) => {
|
|
6509
|
-
const
|
|
6510
|
-
if (!
|
|
6511
|
-
|
|
6512
|
-
persistence.
|
|
6484
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6485
|
+
if (!conversationIdSig.value) {
|
|
6486
|
+
conversationIdSig.value = activeConversationId;
|
|
6487
|
+
persistence.saveConversationId(activeConversationId);
|
|
6513
6488
|
}
|
|
6514
6489
|
const body = buildSendMessageRequest({
|
|
6515
6490
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6516
|
-
|
|
6491
|
+
conversationId: activeConversationId,
|
|
6517
6492
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6518
6493
|
tools: options.features.tools,
|
|
6519
6494
|
responseMode: options.responseMode,
|
|
@@ -6549,7 +6524,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6549
6524
|
messagesSig.value = [...messagesSig.value];
|
|
6550
6525
|
}
|
|
6551
6526
|
},
|
|
6552
|
-
[transport, reducer, messagesSig,
|
|
6527
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6553
6528
|
);
|
|
6554
6529
|
const resolveTool = useCallback6(
|
|
6555
6530
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6605,32 +6580,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6605
6580
|
userContext: () => options.userContext,
|
|
6606
6581
|
messageCount: userMessageCount,
|
|
6607
6582
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6583
|
+
conversationId: () => conversationIdSig.value,
|
|
6608
6584
|
onComplete: (form, trigger, values, skipped) => {
|
|
6609
6585
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6610
6586
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6611
6587
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6612
|
-
const
|
|
6613
|
-
if (!
|
|
6614
|
-
|
|
6615
|
-
persistence.
|
|
6616
|
-
transport.primeIdentity(void 0,
|
|
6588
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6589
|
+
if (!conversationIdSig.value) {
|
|
6590
|
+
conversationIdSig.value = activeConversationId;
|
|
6591
|
+
persistence.saveConversationId(activeConversationId);
|
|
6592
|
+
transport.primeIdentity(void 0, activeConversationId);
|
|
6617
6593
|
}
|
|
6618
6594
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6619
|
-
void transport.submitForm({ formId: form.id,
|
|
6595
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6620
6596
|
}
|
|
6621
6597
|
});
|
|
6622
6598
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6623
6599
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6624
6600
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6625
6601
|
useEffect17(() => {
|
|
6626
|
-
if (
|
|
6627
|
-
}, [
|
|
6602
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6603
|
+
}, [conversationReady, forms]);
|
|
6628
6604
|
useEffect17(() => {
|
|
6629
6605
|
if (!canSend) forms.fire("conversation-closed");
|
|
6630
6606
|
}, [canSend, forms]);
|
|
6631
6607
|
useEffect17(() => {
|
|
6632
|
-
if (pageArea) forms.fire("page-area");
|
|
6633
|
-
}, [pageArea, forms]);
|
|
6608
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6609
|
+
}, [conversationReady, pageArea, forms]);
|
|
6634
6610
|
const idleMs = useMemo3(() => {
|
|
6635
6611
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6636
6612
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6690,16 +6666,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6690
6666
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6691
6667
|
const refreshUnread = useCallback6(() => {
|
|
6692
6668
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6693
|
-
transport.
|
|
6694
|
-
unreadCountSig.value = res.
|
|
6669
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6670
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6695
6671
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6696
6672
|
}, [transport, options.modules, unreadCountSig]);
|
|
6697
6673
|
const unreadSeeded = useRef9(false);
|
|
6698
6674
|
useEffect17(() => {
|
|
6699
|
-
if (!
|
|
6675
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6700
6676
|
unreadSeeded.current = true;
|
|
6701
6677
|
refreshUnread();
|
|
6702
|
-
}, [
|
|
6678
|
+
}, [conversationReady, refreshUnread]);
|
|
6703
6679
|
const handleOpen = useCallback6(() => {
|
|
6704
6680
|
log16.info("open", { mode: options.mode });
|
|
6705
6681
|
feedback.unlock();
|
|
@@ -6718,11 +6694,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6718
6694
|
if (streaming) activeCancel?.();
|
|
6719
6695
|
welcomeAbortRef.current?.abort();
|
|
6720
6696
|
messagesSig.value = [];
|
|
6721
|
-
|
|
6722
|
-
persistence.
|
|
6697
|
+
conversationIdSig.value = void 0;
|
|
6698
|
+
persistence.clearConversation();
|
|
6723
6699
|
setCanSend(true);
|
|
6724
|
-
void
|
|
6725
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6700
|
+
void runStartConversation({ newConversation: true });
|
|
6701
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6726
6702
|
const handleNewChat = useCallback6(() => {
|
|
6727
6703
|
handleClear();
|
|
6728
6704
|
setView("chat");
|
|
@@ -6746,12 +6722,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6746
6722
|
const handlePopOut = useCallback6(() => {
|
|
6747
6723
|
if (!options.popOutUrl) return;
|
|
6748
6724
|
const url = new URL(options.popOutUrl);
|
|
6749
|
-
if (
|
|
6725
|
+
if (conversationIdSig.value) url.searchParams.set("chat", conversationIdSig.value);
|
|
6750
6726
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6751
6727
|
log16.info("popOut", { url: url.toString() });
|
|
6752
6728
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6753
6729
|
bus.emit("popOut", void 0);
|
|
6754
|
-
}, [bus,
|
|
6730
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6755
6731
|
const handleToggleHistory = useCallback6(() => {
|
|
6756
6732
|
setView((v) => {
|
|
6757
6733
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6798,14 +6774,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6798
6774
|
);
|
|
6799
6775
|
const handleSelectHistoryChat = useCallback6(
|
|
6800
6776
|
async (targetChatId) => {
|
|
6801
|
-
log16.info("selectChat", {
|
|
6802
|
-
bus.emit("selectChat", {
|
|
6777
|
+
log16.info("selectChat", { conversationId: targetChatId });
|
|
6778
|
+
bus.emit("selectChat", { conversationId: targetChatId });
|
|
6803
6779
|
try {
|
|
6804
|
-
const res = await transport.
|
|
6780
|
+
const res = await transport.loadConversation(targetChatId);
|
|
6805
6781
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6806
6782
|
messagesSig.value = hydrated;
|
|
6807
|
-
|
|
6808
|
-
persistence.
|
|
6783
|
+
conversationIdSig.value = res.conversationId;
|
|
6784
|
+
persistence.saveConversationId(res.conversationId);
|
|
6809
6785
|
if (res.agent) setAgent(res.agent);
|
|
6810
6786
|
setCanSend(res.canContinue);
|
|
6811
6787
|
setSuggestions(res.suggestions ?? []);
|
|
@@ -6817,7 +6793,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6817
6793
|
options.onError?.(err);
|
|
6818
6794
|
}
|
|
6819
6795
|
},
|
|
6820
|
-
[transport, messagesSig,
|
|
6796
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6821
6797
|
);
|
|
6822
6798
|
useEffect17(() => {
|
|
6823
6799
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6868,48 +6844,47 @@ function App({ options, hostElement, bus }) {
|
|
|
6868
6844
|
bus.emit("suggestion", { text });
|
|
6869
6845
|
void handleSend(text, []);
|
|
6870
6846
|
},
|
|
6871
|
-
// Active form:
|
|
6872
|
-
//
|
|
6873
|
-
|
|
6874
|
-
inlineForm: activeForm.value && !activeForm.value.form.blocking ? activeForm.value.form : null,
|
|
6847
|
+
// Active form: replaces the composer as a gate and locks every chat action
|
|
6848
|
+
// until the visitor submits or (when skippable) skips.
|
|
6849
|
+
activeForm: activeForm.value?.form ?? null,
|
|
6875
6850
|
onFormSubmit: forms.complete,
|
|
6876
6851
|
onFormSkip: forms.skip,
|
|
6877
6852
|
tool: toolInteraction
|
|
6878
6853
|
};
|
|
6879
|
-
const
|
|
6880
|
-
void handleSelectHistoryChat(
|
|
6854
|
+
const onSelectConversation = (conversationId) => {
|
|
6855
|
+
void handleSelectHistoryChat(conversationId);
|
|
6881
6856
|
const chatId = chatTabId();
|
|
6882
6857
|
if (chatId) homeNav.switchTab(chatId);
|
|
6883
6858
|
};
|
|
6884
|
-
if (!
|
|
6859
|
+
if (!conversationReady) return null;
|
|
6885
6860
|
const enabledModules = effectiveOptions.modules.list;
|
|
6886
6861
|
const renderSurface = (size) => {
|
|
6887
6862
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
6888
6863
|
if (enabledModules.length === 0) {
|
|
6889
|
-
return /* @__PURE__ */
|
|
6864
|
+
return /* @__PURE__ */ jsx37(ModulesEmpty, { strings: effectiveOptions.strings, onClose: closeable ? handleClose : void 0 });
|
|
6890
6865
|
}
|
|
6891
6866
|
if (enabledModules.length === 1 && enabledModules[0]?.layout === "chat") {
|
|
6892
|
-
return /* @__PURE__ */
|
|
6867
|
+
return /* @__PURE__ */ jsx37(Panel, { ...panelProps, panelSize: size });
|
|
6893
6868
|
}
|
|
6894
|
-
return /* @__PURE__ */
|
|
6869
|
+
return /* @__PURE__ */ jsx37(
|
|
6895
6870
|
MessengerHome,
|
|
6896
6871
|
{
|
|
6897
6872
|
panelProps: { ...panelProps, panelSize: size, onClose: closeable ? handleClose : void 0 },
|
|
6898
6873
|
enabledModules,
|
|
6899
6874
|
nav: homeNav,
|
|
6900
6875
|
unreadCount: unreadCountSig.value,
|
|
6901
|
-
|
|
6902
|
-
|
|
6876
|
+
onSelectConversation,
|
|
6877
|
+
onStartNewConversation: handleNewChat,
|
|
6903
6878
|
onSetPanelSize: setPanelSize
|
|
6904
6879
|
}
|
|
6905
6880
|
);
|
|
6906
6881
|
};
|
|
6907
6882
|
if (options.mode === "page") {
|
|
6908
6883
|
const onSelectChatFromSidebar = (chat) => {
|
|
6909
|
-
void handleSelectHistoryChat(chat.
|
|
6884
|
+
void handleSelectHistoryChat(chat.conversationId);
|
|
6910
6885
|
};
|
|
6911
6886
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6912
|
-
return /* @__PURE__ */
|
|
6887
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
6913
6888
|
PageShell,
|
|
6914
6889
|
{
|
|
6915
6890
|
site: parsedSite,
|
|
@@ -6928,15 +6903,15 @@ function App({ options, hostElement, bus }) {
|
|
|
6928
6903
|
}
|
|
6929
6904
|
if (isInlineLike) {
|
|
6930
6905
|
const inlineSize = options.mode === "standalone" ? "fullscreen" : panelSize;
|
|
6931
|
-
return /* @__PURE__ */
|
|
6906
|
+
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: renderSurface(inlineSize) });
|
|
6932
6907
|
}
|
|
6933
6908
|
const drawerEdgeTab = options.mode === "drawer";
|
|
6934
6909
|
const triggerOwnedByPage = options.mode === "modal";
|
|
6935
6910
|
const launcherVisible = !triggerOwnedByPage && !options.launcher.hidden && (!isOpen || launcherLeaving);
|
|
6936
6911
|
const calloutToRender = launcherVisible && !launcherLeaving && !calloutDismissed && !drawerEdgeTab ? effectiveOptions.launcher.callout : null;
|
|
6937
|
-
return /* @__PURE__ */
|
|
6912
|
+
return /* @__PURE__ */ jsxs31("div", { class: `${p32}-anchor`, "data-launcher-size": effectiveOptions.launcher.size, children: [
|
|
6938
6913
|
isOpen ? renderSurface(panelSize) : null,
|
|
6939
|
-
launcherVisible ? /* @__PURE__ */
|
|
6914
|
+
launcherVisible ? /* @__PURE__ */ jsx37(
|
|
6940
6915
|
Launcher,
|
|
6941
6916
|
{
|
|
6942
6917
|
onToggle: handleOpen,
|
|
@@ -6946,7 +6921,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6946
6921
|
edgeTab: drawerEdgeTab
|
|
6947
6922
|
}
|
|
6948
6923
|
) : null,
|
|
6949
|
-
calloutToRender ? /* @__PURE__ */
|
|
6924
|
+
calloutToRender ? /* @__PURE__ */ jsx37(
|
|
6950
6925
|
LauncherCallout,
|
|
6951
6926
|
{
|
|
6952
6927
|
callout: calloutToRender,
|
|
@@ -7163,9 +7138,9 @@ var EVENT_NAMES = [
|
|
|
7163
7138
|
"calloutDismiss",
|
|
7164
7139
|
// Lifecycle / errors
|
|
7165
7140
|
"error",
|
|
7166
|
-
"
|
|
7141
|
+
"conversationStarted",
|
|
7167
7142
|
"visitorRebound",
|
|
7168
|
-
"
|
|
7143
|
+
"conversationRebound"
|
|
7169
7144
|
];
|
|
7170
7145
|
|
|
7171
7146
|
// src/index.ts
|
|
@@ -7220,7 +7195,7 @@ function mount(opts) {
|
|
|
7220
7195
|
);
|
|
7221
7196
|
};
|
|
7222
7197
|
renderApp();
|
|
7223
|
-
bus.on("
|
|
7198
|
+
bus.on("conversationStarted", (response) => {
|
|
7224
7199
|
if (!response.config) return;
|
|
7225
7200
|
rawOptions = mergeServerConfig(rawOptions, response.config);
|
|
7226
7201
|
currentOptions = resolveOptions(rawOptions);
|
|
@@ -7249,9 +7224,9 @@ function mount(opts) {
|
|
|
7249
7224
|
log20.debug("update", { patch });
|
|
7250
7225
|
applyUpdate(patch);
|
|
7251
7226
|
},
|
|
7252
|
-
// Host-asserted context (NOT our visitor/
|
|
7227
|
+
// Host-asserted context (NOT our visitor/conversation — those are minted +
|
|
7253
7228
|
// persisted by the widget and untouched here). Merge into the current
|
|
7254
|
-
// context; App re-handshakes with the SAME visitor/
|
|
7229
|
+
// context; App re-handshakes with the SAME visitor/conversation.
|
|
7255
7230
|
setUserContext: (userContext) => {
|
|
7256
7231
|
log20.debug("setUserContext", { keys: Object.keys(userContext) });
|
|
7257
7232
|
applyUpdate({ userContext: { ...rawOptions.userContext, ...userContext } });
|