@helpai/elements 0.14.1 → 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 +13 -11
- package/elements-web-component.esm.js +12 -12
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +12 -12
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +12 -12
- package/elements.esm.js.map +4 -4
- package/elements.js +12 -12
- package/elements.js.map +4 -4
- package/index.d.ts +38 -35
- package/index.mjs +220 -194
- package/package.json +1 -1
- package/schema.d.ts +53 -53
- package/schema.json +13 -13
- package/schema.mjs +15 -13
- package/style.css +1 -1
- package/web-component.d.ts +1 -1
- package/web-component.mjs +218 -192
package/index.mjs
CHANGED
|
@@ -377,7 +377,15 @@ function setLogSink(fn) {
|
|
|
377
377
|
|
|
378
378
|
// src/core/config/user-context.ts
|
|
379
379
|
var log = logger.scope("context");
|
|
380
|
-
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
|
+
]);
|
|
381
389
|
var MAX_KEYS = 50;
|
|
382
390
|
var MAX_STRING = 1024;
|
|
383
391
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -866,7 +874,7 @@ var REACTIVE_ATTRS = [
|
|
|
866
874
|
...SPECIAL_REACTIVE_ATTRS
|
|
867
875
|
];
|
|
868
876
|
|
|
869
|
-
// src/core/start-
|
|
877
|
+
// src/core/start-conversation-shape.ts
|
|
870
878
|
function isPlainObject(raw) {
|
|
871
879
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
872
880
|
}
|
|
@@ -907,7 +915,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
907
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';
|
|
908
916
|
|
|
909
917
|
// src/styles/panel.css
|
|
910
|
-
var panel_default = '.__P__-anchor{right:16px;bottom:16px}:host([data-position="bottom-left"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{right:auto;left:16px}:host([data-position="top-right"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{bottom:auto;top:16px}.__P__-anchor{position:fixed;display:flex;flex-direction:column;align-items:flex-end;gap:var(--__P__-space-3);pointer-events:none}.__P__-anchor{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=sm]{--__P__-fab-size: 44px}.__P__-anchor[data-launcher-size=md]{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=lg]{--__P__-fab-size: 68px}.__P__-anchor>*{pointer-events:auto}.__P__-fab[data-size=sm]{--__P__-fab-size: 44px;font-size:var(--__P__-text-sm)}.__P__-fab[data-size=md]{--__P__-fab-size: 56px;font-size:14px}.__P__-fab[data-size=lg]{--__P__-fab-size: 68px;font-size:var(--__P__-text-base)}.__P__-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);color:var(--__P__-accent-text);background:var(--__P__-accent);box-shadow:var(--__P__-shadow-fab);font-weight:600;line-height:1;transform-origin:bottom right;animation:__P__-fab-in var(--__P__-dur-base) var(--__P__-ease) both;transition:transform var(--__P__-dur-base) var(--__P__-ease),opacity var(--__P__-dur-base) var(--__P__-ease),box-shadow var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab:hover{transform:translateY(-2px)}.__P__-fab:active{transform:translateY(0)}.__P__-fab:focus-visible{outline:2px solid var(--__P__-on-accent);outline-offset:3px}.__P__-fab svg{width:24px;height:24px;flex-shrink:0}@keyframes __P__-fab-in{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}.__P__-fab[data-leaving]{position:absolute;right:0;bottom:0;animation:__P__-fab-out var(--__P__-dur-quick) var(--__P__-ease) forwards;pointer-events:none}:host([data-position^="top-"]) .__P__-fab[data-leaving]{bottom:auto;top:0}:host([data-position$="-left"]) .__P__-fab[data-leaving]{right:auto;left:0}@keyframes __P__-fab-out{0%{opacity:1;transform:none}to{opacity:0;transform:scale(.85)}}.__P__-fab[data-variant=circle]{width:var(--__P__-fab-size);height:var(--__P__-fab-size);border-radius:999px}.__P__-fab[data-variant=circle] .__P__-fab-label{display:none}.__P__-fab[data-variant=pill]{height:var(--__P__-fab-size);padding:0 18px 0 16px;border-radius:999px}.__P__-fab[data-variant=bar]{height:var(--__P__-fab-size);padding:0 22px;border-radius:var(--__P__-radius)}.__P__-fab[data-variant=minimal]{height:var(--__P__-fab-size);padding:0 var(--__P__-space-4);border-radius:999px;background:transparent;color:var(--__P__-accent);box-shadow:none;border:1px solid currentColor}.__P__-fab[data-variant=minimal]:hover{background:color-mix(in srgb,var(--__P__-accent) 12%,transparent)}.__P__-callout{--__P__-callout-fab-h: var(--__P__-fab-size, 56px);--__P__-callout-gap: clamp(12px, calc(var(--__P__-callout-fab-h) * .25), 22px);--__P__-callout-nudge-direction: -1;position:absolute;display:inline-flex;align-items:center;gap:var(--__P__-space-2);padding:10px 14px;background:var(--__P__-fg);color:var(--__P__-bg);border-radius:999px;font-size:var(--__P__-text-sm);font-weight:600;line-height:1.2;box-shadow:0 10px 30px -8px #00000059;pointer-events:auto;animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease);z-index:1;max-width:240px;white-space:nowrap}.__P__-callout[data-position=left]{right:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%)}.__P__-callout[data-position=right]{left:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%);--__P__-callout-nudge-direction: 1}.__P__-callout[data-position=top]{bottom:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-position=bottom]{top:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}:host([data-position$="-left"]) .__P__-callout[data-position=top],:host([data-position$="-left"]) .__P__-callout[data-position=bottom]{right:auto;left:0}.__P__-callout[data-shape=bubble]{border-radius:var(--__P__-radius-md);white-space:normal;width:max-content;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-shape=callout]{padding:12px 18px;font-size:14px;background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-callout:after{content:"";position:absolute;width:12px;height:12px;background:inherit;border-radius:2px;transform:rotate(45deg)}.__P__-callout[data-position=left]:after{right:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=right]:after{left:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=top]:after{bottom:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-position=bottom]:after{top:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}:host([data-position$="-left"]) .__P__-callout[data-position=top]:after,:host([data-position$="-left"]) .__P__-callout[data-position=bottom]:after{right:auto;left:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-animated]{animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease),__P__-callout-nudge 1.6s var(--__P__-ease-in-out) var(--__P__-dur-slow) infinite}@keyframes __P__-callout-in{0%{opacity:0}to{opacity:1}}@keyframes __P__-callout-nudge{0%,to{margin-left:0;margin-right:0}50%{margin-left:calc(6px * var(--__P__-callout-nudge-direction));margin-right:calc(-6px * var(--__P__-callout-nudge-direction))}}@media(prefers-reduced-motion:reduce){.__P__-callout[data-animated]{animation:__P__-callout-in 1ms var(--__P__-ease)}.__P__-icon-btn[data-recording=true],.__P__-typing span{animation:none}}.__P__-callout-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:inherit;opacity:.7;cursor:pointer}.__P__-callout-close:hover{opacity:1;background:#ffffff26}.__P__-callout-close svg{width:12px;height:12px}.__P__-panel{width:var(--__P__-panel-w);height:var(--__P__-panel-h);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);background:var(--__P__-bg);color:var(--__P__-fg);border-radius:var(--__P__-radius-lg);box-shadow:var(--__P__-shadow-panel);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;animation:__P__-panel-in var(--__P__-dur-slow) var(--__P__-ease);border:1px solid var(--__P__-border)}:host([data-mode="open"]) .__P__-panel{width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));min-width:var(--__P__-resize-min-w, auto);min-height:var(--__P__-resize-min-h, auto);max-width:var(--__P__-resize-max-w, calc(100vw - 32px) );max-height:var(--__P__-resize-max-h, calc(100dvh - 32px) )}@keyframes __P__-panel-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}:host([data-mode="expanded"]) .__P__-panel{width:var(--__P__-expanded-w, 640px);height:var(--__P__-expanded-h, 820px);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px)}:host([data-mode="fullscreen"]){z-index:var(--__P__-z-panel)!important}:host([data-mode="fullscreen"]) .__P__-anchor{inset:0;align-items:stretch;padding:0}:host([data-mode="fullscreen"]) .__P__-panel{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}:host([data-mode="fullscreen"]) .__P__-fab{display:none}:host([data-mode="inline"]) .__P__-anchor,:host([data-mode="standalone"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-height:0}:host([data-mode="inline"]) .__P__-panel,:host([data-mode="standalone"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;animation:none}:host([data-mode="inline"]) .__P__-fab,:host([data-mode="standalone"]) .__P__-fab{display:none}:host([data-mode="inline"]){min-height:320px}:host([data-mode="inline"]) .__P__-panel{border-radius:var(--__P__-radius)}:host([data-mode="standalone"]) .__P__-panel{border-radius:0;border:0;box-shadow:none}:host([data-mode="modal"]){position:fixed!important;inset:0!important;z-index:var(--__P__-z-panel)!important;display:block!important;width:100vw;height:100dvh;background:var(--__P__-modal-backdrop, var(--__P__-backdrop));animation:__P__-backdrop-in var(--__P__-dur-base) var(--__P__-ease) both;--__P__-panel-w: min(960px, 92vw);--__P__-panel-h: min(720px, 88dvh)}:host([data-mode="modal"]) .__P__-anchor{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:var(--__P__-space-6);pointer-events:none}:host([data-mode="modal"]) .__P__-panel{pointer-events:auto;width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));max-width:calc(100vw - 48px);max-height:calc(100dvh - 48px);min-width:0;min-height:0;border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-panel);animation:__P__-modal-in var(--__P__-dur-base) var(--__P__-ease);translate:var(--__P__-modal-dx, 0px) var(--__P__-modal-dy, 0px)}:host([data-mode="modal"]) .__P__-header,:host([data-mode="modal"]) .__P__-back-header,:host([data-mode="modal"]) .__P__-home-hero{cursor:grab;touch-action:none}:host([data-mode="modal"]) .__P__-panel[data-dragging]{cursor:grabbing;user-select:none}:host([data-mode="modal"]) .__P__-panel[data-dragging] *{cursor:grabbing}:host([data-mode="modal"]) .__P__-fab{display:none}@keyframes __P__-backdrop-in{0%{background:#0000}to{background:var(--__P__-modal-backdrop, var(--__P__-backdrop))}}@keyframes __P__-modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}:host([data-mode="drawer"]){--__P__-panel-w: min(440px, calc(100vw - 32px) );--__P__-panel-h: 100dvh}:host([data-mode="drawer"]) .__P__-anchor{position:fixed;--__P__-inset-x: var(--__P__-panel-inset, 12px);--__P__-inset-y: var(--__P__-panel-inset, 3dvh);top:var(--__P__-inset-y);bottom:auto;right:var(--__P__-inset-x);left:auto;width:min(var(--__P__-widget-w, var(--__P__-panel-w)),calc(100vw - var(--__P__-inset-x) * 2));height:min(var(--__P__-widget-h, var(--__P__-panel-h)),calc(100dvh - var(--__P__-inset-y) * 2));padding:0;display:block;pointer-events:auto}:host([data-mode="drawer"][data-position$="-left"]) .__P__-anchor{right:auto;left:var(--__P__-inset-x)}:host([data-mode="drawer"][data-position^="bottom-"]) .__P__-anchor{top:auto;bottom:var(--__P__-inset-y)}:host([data-mode="drawer"]) .__P__-panel{width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border-radius:var(--__P__-radius, 12px);border:1px solid var(--__P__-border);box-shadow:-8px 16px 32px -12px #00000038;animation:__P__-drawer-in var(--__P__-dur-base) var(--__P__-ease)}:host([data-mode="drawer"][data-position$="-left"]) .__P__-panel{box-shadow:8px 16px 32px -12px #00000038;animation:__P__-drawer-in-left var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab[data-edge-tab]{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-2);position:fixed;top:50%;height:140px;width:auto;min-width:0;padding:10px 8px;writing-mode:vertical-rl;text-orientation:mixed;transform:translateY(-50%);transform-origin:center;animation:__P__-edge-tab-in var(--__P__-dur-base) var(--__P__-ease) both}.__P__-fab[data-edge-tab] svg{writing-mode:horizontal-tb}.__P__-fab[data-edge-tab]:hover{transform:translateY(-50%) scale(1.03)}.__P__-fab[data-edge-tab]:active{transform:translateY(-50%) scale(.97)}:host([data-position$="-right"]) .__P__-fab[data-edge-tab]{right:0;left:auto;border-radius:12px 0 0 12px;box-shadow:-6px 0 18px -8px #0000004d}:host([data-position$="-left"]) .__P__-fab[data-edge-tab]{left:0;right:auto;border-radius:0 12px 12px 0;box-shadow:6px 0 18px -8px #0000004d}.__P__-fab[data-edge-tab][data-leaving]{position:fixed;top:50%;bottom:auto;animation:__P__-edge-tab-out var(--__P__-dur-quick) var(--__P__-ease) forwards}@keyframes __P__-edge-tab-in{0%{opacity:0;transform:translateY(-50%) scale(.9)}to{opacity:1;transform:translateY(-50%) scale(1)}}@keyframes __P__-edge-tab-out{0%{opacity:1;transform:translateY(-50%) scale(1)}to{opacity:0;transform:translateY(-50%) scale(.85)}}@keyframes __P__-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes __P__-drawer-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@media(prefers-reduced-motion:reduce){:host([data-mode="drawer"]) .__P__-panel,.__P__-fab[data-edge-tab]{animation:none}}.__P__-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);background:var(--__P__-bg)}.__P__-header h1{font-size:14px;font-weight:600;flex:1;letter-spacing:-.01em}.__P__-header-actions{margin-left:auto;display:flex;align-items:center;gap:var(--__P__-space-1);flex-shrink:0}.__P__-agent{flex:1;display:inline-flex;align-items:center;gap:10px;min-width:0}.__P__-agent-avatar{position:relative;width:32px;height:32px;border-radius:999px;background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--__P__-text-xs);overflow:hidden;flex-shrink:0}.__P__-agent-avatar img{width:100%;height:100%;object-fit:cover}.__P__-agent-avatar:after{content:"";position:absolute;right:-1px;bottom:-1px;width:10px;height:10px;border-radius:999px;border:2px solid var(--__P__-bg);background:var(--__P__-neutral)}.__P__-agent-avatar[data-status=online]:after{background:var(--__P__-success)}.__P__-agent-avatar[data-status=away]:after{background:var(--__P__-warning)}.__P__-agent-avatar[data-status=offline]:after{background:var(--__P__-neutral)}.__P__-agent-meta{display:flex;flex-direction:column;line-height:1.15;min-width:0}.__P__-agent-meta strong{font-size:14px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-agent-meta span{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-suggestions{display:flex;flex-wrap:nowrap;gap:var(--__P__-space-2);padding:6px 14px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;-ms-overflow-style:none;min-width:0}.__P__-suggestions::-webkit-scrollbar{display:none}.__P__-suggestions:before,.__P__-suggestions:after{content:"";flex:1 1 0;min-width:0}.__P__-suggestion{flex:0 0 auto;scroll-snap-align:center;padding:7px 14px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg);font-size:var(--__P__-text-sm);font-weight:500;white-space:nowrap;transition:background var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-suggestion:hover{border-color:var(--__P__-accent);color:var(--__P__-accent);transform:translateY(-1px)}.__P__-suggestion:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px;border-color:var(--__P__-accent)}.__P__-suggestion:active{transform:translateY(0)}.__P__-icon-btn{width:32px;height:32px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);transition:background var(--__P__-dur-quick) var(--__P__-ease),color var(--__P__-dur-quick) var(--__P__-ease)}.__P__-icon-btn:hover{background:var(--__P__-bg-elevated);color:var(--__P__-fg)}.__P__-icon-btn:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-icon-btn:active{background:var(--__P__-border)}.__P__-icon-btn:disabled{opacity:.45;cursor:not-allowed}.__P__-icon-btn:before{content:"";position:absolute;inset:-6px}.__P__-icon-btn{position:relative}.__P__-icon-btn svg{width:18px;height:18px}.__P__-icon-btn[data-recording=true]{color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);animation:__P__-pulse 1.2s var(--__P__-ease) infinite}@keyframes __P__-pulse{0%,to{box-shadow:0 0 color-mix(in srgb,var(--__P__-accent) 40%,transparent)}50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--__P__-accent) 0%,transparent)}}.__P__-list-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}.__P__-jump{position:absolute;right:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:999px;border:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);color:var(--__P__-fg);box-shadow:var(--__P__-shadow-panel);cursor:pointer;opacity:.85;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease);animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-jump:hover{opacity:1}.__P__-jump:active{transform:translateY(1px)}.__P__-jump svg{width:18px;height:18px}.__P__-list{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-4);padding-bottom:var(--__P__-space-8);display:flex;flex-direction:column;gap:14px;scrollbar-width:thin;scrollbar-color:var(--__P__-border-strong) transparent;scrollbar-gutter:stable}.__P__-list::-webkit-scrollbar{width:8px}.__P__-list::-webkit-scrollbar-thumb{background:var(--__P__-border-strong);border-radius:8px}.__P__-date-divider{position:sticky;top:var(--__P__-space-2);z-index:2;display:flex;justify-content:center;margin:var(--__P__-space-1) 0;pointer-events:none}.__P__-date-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--__P__-fg-muted);background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);box-shadow:var(--__P__-shadow-card);opacity:0;pointer-events:none;transition:opacity var(--__P__-dur-base) var(--__P__-ease)}.__P__-list[data-scrolling=true] .__P__-date-pill{opacity:1;pointer-events:auto}@media(prefers-reduced-motion:reduce){.__P__-date-pill{transition:none}}.__P__-bubble-row{display:flex}.__P__-bubble-row[data-role=user]{justify-content:flex-end}.__P__-bubble-row[data-role=assistant]{justify-content:flex-start}.__P__-bubble{max-width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);line-height:1.6;font-size:14px;word-wrap:break-word;overflow-wrap:anywhere;box-shadow:0 1px 2px #0000000a,0 1px 8px -4px #0000000f;animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-bubble ::selection{background:color-mix(in srgb,var(--__P__-accent) 30%,transparent)}.__P__-bubble-row[data-role=user] .__P__-bubble ::selection{background:#fff6;color:var(--__P__-bubble-user-text)}@keyframes __P__-bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.__P__-bubble-row[data-role=user] .__P__-bubble{background:var(--__P__-bubble-user);color:var(--__P__-bubble-user-text);border-bottom-right-radius:5px}.__P__-bubble-row[data-role=assistant] .__P__-bubble{background:var(--__P__-bubble-assistant);color:var(--__P__-bubble-assistant-text);border-bottom-left-radius:5px}.__P__-bubble-col{display:flex;flex-direction:column;max-width:85%;min-width:0}.__P__-bubble-row[data-role=user] .__P__-bubble-col{align-items:flex-end}.__P__-bubble-row[data-role=assistant] .__P__-bubble-col{align-items:flex-start}.__P__-bubble-time{margin-top:3px;padding:0 4px;font-size:11px;line-height:1;color:var(--__P__-fg-muted);user-select:none}.__P__-md>*:first-child{margin-top:0}.__P__-md>*:last-child{margin-bottom:0}.__P__-md p{margin:10px 0}.__P__-md h1,.__P__-md h2,.__P__-md h3,.__P__-md h4,.__P__-md h5,.__P__-md h6{margin:18px 0 8px;line-height:1.3;letter-spacing:-.01em;font-weight:700}.__P__-md h1{font-size:1.4em}.__P__-md h2{font-size:1.22em}.__P__-md h3{font-size:1.08em}.__P__-md h4,.__P__-md h5,.__P__-md h6{font-size:1em}.__P__-md>h1:first-child,.__P__-md>h2:first-child,.__P__-md>h3:first-child,.__P__-md>h4:first-child,.__P__-md>h5:first-child,.__P__-md>h6:first-child{margin-top:0}.__P__-md ul,.__P__-md ol{padding-left:1.5em;margin:10px 0}.__P__-md ul{list-style:disc}.__P__-md ol{list-style:decimal}.__P__-md li{margin:6px 0;padding-left:2px}.__P__-md li::marker{color:var(--__P__-fg-muted)}.__P__-md li>p{margin:6px 0}.__P__-md li>ul,.__P__-md li>ol{margin:6px 0}.__P__-md strong,.__P__-md b{font-weight:650;letter-spacing:-.005em}.__P__-md em,.__P__-md i{font-style:italic}.__P__-md code{font-family:var(--__P__-font-mono);font-size:.86em;padding:1px 6px;border-radius:5px;background:color-mix(in srgb,var(--__P__-accent) 10%,transparent);color:var(--__P__-fg);border:1px solid color-mix(in srgb,var(--__P__-accent) 16%,transparent)}.__P__-md pre{font-family:var(--__P__-font-mono);font-size:12.5px;padding:12px 14px;border-radius:var(--__P__-radius-sm);background:#7f7f7f1f;overflow-x:auto;margin:var(--__P__-space-3) 0;line-height:1.5}.__P__-md pre code{padding:0;background:none}.__P__-md a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}.__P__-md a:hover{text-decoration-thickness:2px}.__P__-md blockquote{margin:14px 0;padding:6px 14px;border-left:3px solid color-mix(in srgb,var(--__P__-accent) 50%,transparent);background:color-mix(in srgb,var(--__P__-accent) 5%,transparent);border-radius:0 var(--__P__-radius-sm) var(--__P__-radius-sm) 0;color:var(--__P__-fg-muted)}.__P__-md blockquote>:first-child{margin-top:0}.__P__-md blockquote>:last-child{margin-bottom:0}.__P__-md hr{border:0;height:1px;background:color-mix(in srgb,currentColor 18%,transparent);margin:var(--__P__-space-4) 0}.__P__-md table{border-collapse:collapse;margin:var(--__P__-space-3) 0;font-size:.95em;display:block;overflow-x:auto;max-width:100%;font-variant-numeric:tabular-nums}.__P__-md th,.__P__-md td{padding:6px 10px;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);text-align:left}.__P__-md th{font-weight:700;background:color-mix(in srgb,currentColor 6%,transparent)}.__P__-md h1+ul,.__P__-md h1+ol,.__P__-md h2+ul,.__P__-md h2+ol,.__P__-md h3+ul,.__P__-md h3+ol,.__P__-md h4+ul,.__P__-md h4+ol{margin-top:var(--__P__-space-1)}.__P__-loading{display:inline-flex;align-items:center;gap:var(--__P__-space-2);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-loading-spinner{width:14px;height:14px;border-radius:999px;border:2px solid currentColor;border-top-color:transparent;animation:__P__-spin .8s linear infinite}@keyframes __P__-spin{to{transform:rotate(1turn)}}.__P__-typing{display:inline-flex;gap:var(--__P__-space-1);padding:var(--__P__-space-1) 0}.__P__-typing span{width:5px;height:5px;border-radius:999px;background:currentColor;opacity:.4;animation:__P__-blink 1.2s var(--__P__-ease) infinite}.__P__-typing span:nth-child(2){animation-delay:.2s}.__P__-typing span:nth-child(3){animation-delay:.4s}@keyframes __P__-blink{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.__P__-reasoning{margin:var(--__P__-space-1) 0 var(--__P__-space-2);padding-left:var(--__P__-space-3);border-left:2px solid var(--__P__-border-strong)}.__P__-reasoning-summary{display:inline-flex;align-items:center;gap:var(--__P__-space-1);cursor:pointer;list-style:none;user-select:none;color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-reasoning-summary::-webkit-details-marker{display:none}.__P__-reasoning-summary:before{content:"";width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);opacity:.7;transition:transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-reasoning[open] .__P__-reasoning-summary:before{transform:rotate(45deg)}.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:__P__-reasoning-pulse 1.4s var(--__P__-ease) infinite}@keyframes __P__-reasoning-pulse{0%,to{opacity:.5}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:none}}.__P__-reasoning-body{margin-top:var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-reasoning-body>:first-child{margin-top:0}.__P__-reasoning-body>:last-child{margin-bottom:0}.__P__-tool-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2);margin-top:6px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs)}.__P__-composer{border-top:1px solid var(--__P__-border);padding:10px 12px;background:var(--__P__-bg);display:flex;flex-direction:column;gap:var(--__P__-space-2)}.__P__-composer-row{display:flex;align-items:flex-end;gap:6px}.__P__-textarea{flex:1;height:40px;max-height:160px;padding:10px 12px;border-radius:var(--__P__-radius);background:var(--__P__-bg-elevated);border:1px solid transparent;font-size:14px;line-height:1.4;transition:height var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),box-shadow var(--__P__-dur-quick) var(--__P__-ease)}.__P__-textarea:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:1px;border-color:var(--__P__-focus)}@media(pointer:coarse){.__P__-textarea,.__P__-home-search-input{font-size:16px}.__P__-textarea{height:44px}}.__P__-send{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease),background var(--__P__-dur-quick) var(--__P__-ease)}.__P__-send[data-shape=circle]{border-radius:999px}.__P__-send[data-shape=square]{border-radius:var(--__P__-radius-sm)}.__P__-send[data-shape=pill]{width:auto;padding:0 18px;border-radius:999px}.__P__-send[data-variant=filled]{background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-send[data-variant=outline]{background:transparent;color:var(--__P__-accent);border-color:var(--__P__-accent)}.__P__-send[data-variant=outline]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 10%,transparent)}.__P__-send[data-variant=ghost]{background:transparent;color:var(--__P__-accent)}.__P__-send[data-variant=ghost]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 8%,transparent)}.__P__-send:disabled{opacity:.4;cursor:not-allowed}.__P__-send:not(:disabled):hover{transform:translateY(-1px)}.__P__-send:not(:disabled):active{transform:translateY(0)}.__P__-send:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-send svg{width:18px;height:18px}.__P__-composer-actions{display:flex;gap:var(--__P__-space-1);flex-wrap:wrap}.__P__-attachments{display:flex;flex-wrap:wrap;gap:6px}.__P__-attachment-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-1);border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);font-size:var(--__P__-text-xs);max-width:200px}.__P__-attachment-thumb{width:24px;height:24px;border-radius:999px;object-fit:cover;background:var(--__P__-border)}.__P__-attachment-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-attachment-remove{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted)}.__P__-attachment-remove:hover{background:var(--__P__-border);color:var(--__P__-fg)}.__P__-dropzone{position:absolute;inset:8px;border:2px dashed var(--__P__-accent);border-radius:var(--__P__-radius);background:color-mix(in srgb,var(--__P__-accent) 8%,transparent);display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--__P__-accent);pointer-events:none;z-index:10;animation:__P__-fade-in var(--__P__-dur-quick) var(--__P__-ease)}@keyframes __P__-fade-in{0%{opacity:0}to{opacity:1}}.__P__-error{margin-top:var(--__P__-space-1);padding:8px 10px;border-radius:var(--__P__-radius-sm);background:var(--__P__-danger-bg);color:var(--__P__-danger-text);font-size:var(--__P__-text-sm);display:flex;align-items:center;gap:var(--__P__-space-2)}.__P__-error button{color:inherit;text-decoration:underline;font-size:var(--__P__-text-sm)}.__P__-history{flex:1;overflow-y:auto;padding:var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-3)}.__P__-history-footer{flex:none;padding:var(--__P__-space-2) var(--__P__-space-3) var(--__P__-space-3);border-top:1px solid var(--__P__-border);background:var(--__P__-surface)}.__P__-history-new{width:100%;display:flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);padding:var(--__P__-space-2) var(--__P__-space-3);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-on-accent);cursor:pointer;font-size:var(--__P__-text-sm);font-weight:600;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-history-new svg{width:16px;height:16px}.__P__-history-new:hover{filter:brightness(1.08)}.__P__-history-new:active{transform:translateY(1px)}.__P__-history-new:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-history-empty{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 16px;color:var(--__P__-fg-muted);font-size:14px;text-align:center}.__P__-history-group{display:flex;flex-direction:column;padding:0 var(--__P__-space-2)}.__P__-history-heading{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-fg-muted);padding:12px 8px 6px;text-transform:uppercase;letter-spacing:.04em}.__P__-history-item{all:unset;display:flex;flex-direction:column;gap:3px;padding:10px 12px;border-radius:var(--__P__-radius-md);cursor:pointer;transition:background var(--__P__-dur-base) var(--__P__-ease)}.__P__-history-item:hover{background:var(--__P__-bg-elevated)}.__P__-history-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-history-title{font-size:14px;font-weight:500;color:var(--__P__-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-preview{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-item[data-closed=true] .__P__-history-title:after{content:"\\2022";margin-left:var(--__P__-space-2);opacity:.5}.__P__-list-loading{margin:auto;padding:var(--__P__-space-6) var(--__P__-space-4);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);text-align:center}.__P__-readonly-banner{display:flex;flex-direction:column;align-items:center;gap:10px;padding:14px 12px;margin:0 var(--__P__-space-3) var(--__P__-space-3);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);text-align:center;font-size:var(--__P__-text-sm)}.__P__-readonly-label{line-height:1.4}.__P__-readonly-cta{appearance:none;border:0;cursor:pointer;padding:var(--__P__-space-2) var(--__P__-space-4);border-radius:999px;background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-readonly-cta:hover,.__P__-readonly-cta:focus-visible{filter:brightness(1.1)}.__P__-readonly-cta:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}.__P__-composer-footer{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:10px 16px;margin:0 var(--__P__-space-3);border-top:1px solid var(--__P__-border);text-align:center;font-size:11px;line-height:1.4;color:var(--__P__-fg-muted)}.__P__-disclaimer{max-width:320px;margin:0 auto;opacity:.9;letter-spacing:.01em}.__P__-poweredby{display:inline-flex;align-items:center;justify-content:center;gap:6px;color:inherit;text-decoration:none;opacity:.7;transition:opacity var(--__P__-dur-base) var(--__P__-ease);font-size:11px;letter-spacing:.02em}.__P__-poweredby:hover{opacity:1}.__P__-poweredby-logo{height:12px;width:auto;display:inline-block;vertical-align:middle}.__P__-poweredby-bar{flex:none;display:flex;align-items:center;justify-content:center;padding:6px 16px;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated)}.__P__-menu-wrap{position:relative;display:inline-flex}.__P__-menu{position:absolute;top:100%;right:0;margin-top:6px;min-width:200px;padding:6px;background:var(--__P__-bg);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);box-shadow:var(--__P__-shadow-panel);z-index:10;display:flex;flex-direction:column;gap:2px;animation:__P__-menu-in var(--__P__-dur-base) var(--__P__-ease)}@media(prefers-reduced-motion:reduce){.__P__-menu{animation:none}}@keyframes __P__-menu-in{0%{opacity:0;transform:translateY(-4px) scale(.98);transform-origin:top right}to{opacity:1;transform:none}}.__P__-menu-item{all:unset;display:flex;align-items:center;gap:10px;padding:8px 10px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);border-radius:var(--__P__-radius-sm);cursor:pointer;user-select:none}.__P__-menu-item:hover{background:var(--__P__-bg-elevated)}.__P__-menu-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-menu-item[disabled]{opacity:.45;cursor:not-allowed}.__P__-menu-icon{display:inline-flex;width:16px;height:16px;color:var(--__P__-fg-muted)}.__P__-menu-icon svg{width:16px;height:16px}.__P__-menu-label{flex:1}.__P__-menu-check{display:inline-flex;color:var(--__P__-accent)}.__P__-menu-check svg{width:14px;height:14px}.__P__-resize-grip{position:absolute;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);opacity:.45;transition:opacity var(--__P__-dur-base) var(--__P__-ease);z-index:2;touch-action:none;user-select:none}.__P__-resize-grip:hover,.__P__-resize-grip:focus-visible{opacity:1}.__P__-resize-grip svg{width:10px;height:10px}.__P__-resize-grip--bottom-left{bottom:2px;left:2px;cursor:nesw-resize;transform:scaleX(-1)}.__P__-resize-grip--bottom-right{bottom:2px;right:2px;cursor:nwse-resize}.__P__-resize-grip--top-left{top:2px;left:2px;cursor:nwse-resize;transform:rotate(180deg)}.__P__-resize-grip--top-right{top:2px;right:2px;cursor:nesw-resize;transform:scaleY(-1)}:host(:not([data-mode="open"])) .__P__-resize-grip{display:none}.__P__-messenger{display:flex;flex-direction:column;overflow:hidden}.__P__-messenger-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}.__P__-module{display:flex;flex-direction:column;height:100%;min-height:0}.__P__-module-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-3);display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-home{background:radial-gradient(125% 65% at 88% 0%,color-mix(in srgb,#fff 16%,transparent),transparent 55%),linear-gradient(180deg,var(--__P__-accent) 0%,var(--__P__-accent) 22%,color-mix(in srgb,var(--__P__-accent) 28%,var(--__P__-surface)) 44%,var(--__P__-surface) 70%);border-radius:var(--__P__-radius-lg) var(--__P__-radius-lg) 0 0}.__P__-home-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;background:transparent}.__P__-home-cards{display:flex;flex-direction:column;gap:var(--__P__-space-3);padding:4px 14px 16px}.__P__-module-pad{padding:var(--__P__-space-3) var(--__P__-space-3) 0}.__P__-module-empty{display:flex;flex-direction:column;align-items:center;gap:var(--__P__-space-3);padding:var(--__P__-space-8) var(--__P__-space-4);text-align:center;color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-module-retry{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border-strong);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);font-weight:600;cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-module-retry:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}.__P__-module-retry:active{background:var(--__P__-border)}.__P__-module-retry:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-help-list{flex:1;min-height:0;overflow-y:auto;padding-bottom:var(--__P__-space-3)}.__P__-help-group{display:flex;flex-direction:column}.__P__-help-section-title{position:sticky;top:0;z-index:1;margin:0;padding:var(--__P__-space-3) var(--__P__-space-5) var(--__P__-space-2);font-size:var(--__P__-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--__P__-fg-muted);background:var(--__P__-bg)}.__P__-help-card{margin:0 var(--__P__-space-3) var(--__P__-space-3);background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden}.__P__-help-card .__P__-list-row{border-bottom:0;border-radius:0}.__P__-help-card .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-help-card .__P__-list-row:hover{background:var(--__P__-hover)}.__P__-module-cta{padding:var(--__P__-space-3);border-top:1px solid var(--__P__-border)}.__P__-tabbar{display:flex;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);flex-shrink:0}.__P__-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-1);min-height:48px;padding:var(--__P__-space-2) var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600;transition:color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-tab:hover{color:var(--__P__-fg)}.__P__-tab[aria-selected=true]{color:var(--__P__-accent)}.__P__-tab:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-tab:active{background:var(--__P__-hover)}.__P__-tab-icon{position:relative;display:inline-flex}.__P__-tab-icon svg{width:22px;height:22px}.__P__-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--__P__-accent);color:var(--__P__-on-accent);font-size:10px;font-weight:600;line-height:1}.__P__-home-hero{flex-shrink:0;padding:var(--__P__-space-5) var(--__P__-space-5) var(--__P__-space-3);color:var(--__P__-on-accent);--__P__-focus: var(--__P__-on-accent)}.__P__-home-hero-top{display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-3);min-height:32px}.__P__-home-brand{font-size:14px;font-weight:600;letter-spacing:.01em;color:color-mix(in srgb,#fff 82%,transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.__P__-home-brand-spacer{flex:1}.__P__-home-hero-actions{display:flex;align-items:center;gap:var(--__P__-space-2);flex-shrink:0}.__P__-home-hero-actions .__P__-icon-btn{color:#fff}.__P__-home-greeting{margin:28px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;overflow-wrap:anywhere}.__P__-home-lead{margin:2px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;color:color-mix(in srgb,var(--__P__-on-accent) 88%,transparent);overflow-wrap:anywhere}.__P__-home-avatars{display:flex}.__P__-home-avatar{width:30px;height:30px;border-radius:999px;overflow:hidden;margin-left:-10px;border:2px solid color-mix(in srgb,#fff 92%,transparent);box-shadow:0 1px 3px #0000002e;background:var(--__P__-surface);display:inline-flex;align-items:center;justify-content:center;font-size:var(--__P__-text-xs);font-weight:700;color:var(--__P__-fg)}.__P__-home-avatar:first-child{margin-left:0}.__P__-home-avatar img{width:100%;height:100%;object-fit:cover}.__P__-home-content{background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-card);overflow:hidden}.__P__-home-content-title{padding:var(--__P__-space-4) var(--__P__-space-4) var(--__P__-space-3);font-size:var(--__P__-text-sm);font-weight:700}.__P__-home-content-list{display:flex;flex-direction:column;padding:0 var(--__P__-space-2) var(--__P__-space-2)}.__P__-home-content-list .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-home-card{display:block;width:100%;text-align:left;background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);padding:var(--__P__-space-4);box-shadow:var(--__P__-shadow-card)}.__P__-home-card[data-interactive=true]{cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-home-card[data-interactive=true]:hover{background:var(--__P__-bg-elevated)}.__P__-home-card[data-interactive=true]:active{transform:translateY(1px)}.__P__-home-card[data-interactive=true]:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-recent-row{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-recent-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;flex-shrink:0;border-radius:999px;background:color-mix(in oklch,var(--__P__-accent) 14%,transparent);color:var(--__P__-accent)}.__P__-home-recent-avatar svg{width:20px;height:20px}.__P__-home-recent-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.__P__-home-recent-title{font-weight:600;font-size:14px}.__P__-home-recent-preview{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-home-recent-at{color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);flex-shrink:0}.__P__-home-recent-dot{width:8px;height:8px;border-radius:999px;background:var(--__P__-accent);flex-shrink:0}.__P__-home-recent-row[data-unread=true] .__P__-home-recent-title{font-weight:700}.__P__-home-status{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-status-icon svg{width:22px;height:22px;color:var(--__P__-success)}.__P__-home-status[data-level=degraded] .__P__-home-status-icon svg{color:var(--__P__-warning)}.__P__-home-status[data-level=down] .__P__-home-status-icon svg{color:var(--__P__-danger)}.__P__-home-status-text{font-weight:600;font-size:14px}.__P__-home-search{display:flex;align-items:center;gap:var(--__P__-space-2);width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);border:1px solid var(--__P__-border);background:var(--__P__-surface);text-align:left}.__P__-home-search[data-input=true]{background:var(--__P__-bg-elevated)}.__P__-home-search:hover{border-color:var(--__P__-border-strong)}.__P__-home-search:focus-visible,.__P__-home-search:focus-within{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-search-text{flex:1;color:var(--__P__-fg-muted);font-size:14px}.__P__-home-search-input{flex:1;border:0;background:transparent;font-size:14px;color:var(--__P__-fg);outline:none}.__P__-home-search-icon svg{width:18px;height:18px;color:var(--__P__-accent)}.__P__-list-row{display:flex;align-items:center;gap:var(--__P__-space-3);width:100%;min-height:44px;text-align:left;padding:var(--__P__-space-3) var(--__P__-space-2);border-radius:var(--__P__-radius-sm)}.__P__-list-row:hover{background:var(--__P__-bg-elevated)}.__P__-list-row:active{background:var(--__P__-border)}.__P__-list-row:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-list-row-body{display:flex;flex-direction:column;min-width:0;flex:1}.__P__-list-row-title{font-weight:600;font-size:var(--__P__-text-md);line-height:1.35}.__P__-list-row-sub{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);margin-top:var(--__P__-space-1);line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-list-row-chevron svg{width:18px;height:18px;color:var(--__P__-accent);flex-shrink:0}.__P__-back-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);flex-shrink:0}.__P__-back-title{flex:1;text-align:center;font-size:var(--__P__-text-md);font-weight:700;margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-back-spacer{width:32px;height:1px}.__P__-content{display:flex;flex-direction:column;gap:14px;width:100%;max-width:68ch;margin:0 auto}.__P__-content-hero{width:100%;border-radius:var(--__P__-radius)}.__P__-content-subtitle{color:var(--__P__-fg-muted);margin:0}.__P__-content-frame{flex:1;min-height:0;width:100%;border:0;background:#fff}.__P__-news-list{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-news-card{display:block;width:100%;text-align:left;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden;background:var(--__P__-surface)}.__P__-news-card{transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-news-card:hover{background:var(--__P__-bg-elevated)}.__P__-news-card:active{transform:translateY(1px)}.__P__-news-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-news-hero{width:100%;display:block}.__P__-news-body{display:flex;flex-direction:column;gap:6px;padding:14px 16px}.__P__-news-tags{display:flex;gap:6px;flex-wrap:wrap}.__P__-news-tag{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);padding:2px 8px;border-radius:999px}.__P__-news-title{font-weight:700;font-size:var(--__P__-text-md)}.__P__-news-summary{color:var(--__P__-fg-muted);font-size:14px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-modules-empty{display:flex;align-items:center;justify-content:center;position:relative}.__P__-modules-empty-close{position:absolute;top:12px;right:12px}.__P__-modules-empty-text{color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-form{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-field{display:flex;flex-direction:column;gap:4px}.__P__-field-label{font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-field-req{color:var(--__P__-danger)}.__P__-field-input{width:100%;box-sizing:border-box;padding:var(--__P__-space-2) var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg);color:var(--__P__-fg);font:inherit;font-size:var(--__P__-text-sm);resize:vertical;transition:border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-field-input:focus-visible{outline:none;border-color:var(--__P__-accent)}.__P__-field[data-invalid=true] .__P__-field-input{border-color:var(--__P__-danger)}.__P__-field-hint{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-field-error{font-size:var(--__P__-text-xs);color:var(--__P__-danger)}.__P__-field-choices{display:flex;flex-direction:column;gap:6px}.__P__-choice{display:flex;align-items:flex-start;gap:8px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);cursor:pointer}.__P__-choice input{margin-top:2px;accent-color:var(--__P__-accent)}.__P__-form-actions{display:flex;justify-content:flex-end;gap:var(--__P__-space-2);margin-top:2px}.__P__-form-submit,.__P__-tool-approve{padding:var(--__P__-space-2) var(--__P__-space-4);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);cursor:pointer;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-submit:hover:not(:disabled),.__P__-tool-approve:hover:not(:disabled){filter:brightness(1.06)}.__P__-form-submit:disabled{opacity:.6;cursor:default}.__P__-form-skip,.__P__-tool-reject{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:transparent;color:var(--__P__-fg-muted);font:inherit;font-size:var(--__P__-text-sm);cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-skip:hover:not(:disabled),.__P__-tool-reject:hover:not(:disabled){background:var(--__P__-bg-elevated)}.__P__-form-gate{display:flex;flex-direction:column;gap:var(--__P__-space-2);padding:var(--__P__-space-3) var(--__P__-space-4) var(--__P__-space-4);border-top:1px solid var(--__P__-border);max-height:60%;overflow-y:auto}.__P__-form-gate-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-form-gate-desc{margin:0 0 var(--__P__-space-1);font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-ask-input,.__P__-tool-approval{display:flex;flex-direction:column;gap:var(--__P__-space-2);margin-top:6px;padding:var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated)}.__P__-tool-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-badge{padding:2px 8px;border-radius:999px;background:var(--__P__-warning, #f59e0b);color:#1a1206;font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-title{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}.__P__-tool-question{margin:0;font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-tool-desc{margin:0;font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-args{margin:0;padding:var(--__P__-space-2);max-height:160px;overflow:auto;border-radius:var(--__P__-radius-sm);background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);white-space:pre-wrap;word-break:break-word}.__P__-tool-stale-note{margin:0;font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-tool-decided{flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-decided-label{padding:2px 8px;border-radius:999px;background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-decided-label[data-approved=true]{color:var(--__P__-success, #16a34a);border-color:var(--__P__-success, #16a34a)}.__P__-tool-decided-label[data-approved=false]{color:var(--__P__-danger);border-color:var(--__P__-danger)}.__P__-tool-decided-value{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}\n';
|
|
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';
|
|
911
919
|
|
|
912
920
|
// src/styles/standalone.css
|
|
913
921
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1191,8 +1199,8 @@ function encodeContext(user, page) {
|
|
|
1191
1199
|
|
|
1192
1200
|
// src/stream/protocol.ts
|
|
1193
1201
|
var DEFAULT_PATHS = {
|
|
1194
|
-
/**
|
|
1195
|
-
|
|
1202
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1203
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1196
1204
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1197
1205
|
streamMessage: "/ai/agent/stream-message",
|
|
1198
1206
|
/**
|
|
@@ -1205,20 +1213,20 @@ var DEFAULT_PATHS = {
|
|
|
1205
1213
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1206
1214
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1207
1215
|
/** List the visitor's conversations. `GET`. */
|
|
1208
|
-
|
|
1209
|
-
/** Load one conversation's messages. `GET ?
|
|
1216
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1217
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1210
1218
|
listMessages: "/ai/agent/list-messages",
|
|
1211
1219
|
/**
|
|
1212
1220
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1213
1221
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1214
1222
|
* the client — a failure leaves the local cache valid; the next
|
|
1215
|
-
* `
|
|
1223
|
+
* `startConversation()` reconciles.
|
|
1216
1224
|
*/
|
|
1217
1225
|
updateSettings: "/ai/agent/update-settings",
|
|
1218
1226
|
/**
|
|
1219
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1220
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1221
|
-
* `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
|
|
1222
1230
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1223
1231
|
*/
|
|
1224
1232
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1227,8 +1235,8 @@ var DEFAULT_PATHS = {
|
|
|
1227
1235
|
content: "/ai/agent/content",
|
|
1228
1236
|
/**
|
|
1229
1237
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1230
|
-
*
|
|
1231
|
-
* 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.
|
|
1232
1240
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1233
1241
|
*/
|
|
1234
1242
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1243,7 +1251,7 @@ function buildSendMessageRequest(params) {
|
|
|
1243
1251
|
}));
|
|
1244
1252
|
const body = {
|
|
1245
1253
|
messages: wire,
|
|
1246
|
-
|
|
1254
|
+
conversationId: params.conversationId,
|
|
1247
1255
|
trigger: params.trigger ?? "submit-message"
|
|
1248
1256
|
};
|
|
1249
1257
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1331,11 +1339,11 @@ function sleep(ms, signal7) {
|
|
|
1331
1339
|
var AgentTransport = class {
|
|
1332
1340
|
constructor(opts) {
|
|
1333
1341
|
__publicField(this, "opts", opts);
|
|
1334
|
-
// Identity adopted from the start-
|
|
1342
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1335
1343
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1336
|
-
// (visitor,
|
|
1344
|
+
// (visitor, conversation) pair.
|
|
1337
1345
|
__publicField(this, "visitorId");
|
|
1338
|
-
__publicField(this, "
|
|
1346
|
+
__publicField(this, "conversationId");
|
|
1339
1347
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1340
1348
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1341
1349
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1353,27 +1361,27 @@ var AgentTransport = class {
|
|
|
1353
1361
|
this.pageContext = pageContext;
|
|
1354
1362
|
}
|
|
1355
1363
|
/**
|
|
1356
|
-
* Seed the visitor +
|
|
1357
|
-
* `
|
|
1358
|
-
* with `
|
|
1359
|
-
* `
|
|
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`
|
|
1360
1368
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1361
1369
|
*/
|
|
1362
|
-
primeIdentity(visitorId,
|
|
1370
|
+
primeIdentity(visitorId, conversationId) {
|
|
1363
1371
|
if (visitorId) this.visitorId = visitorId;
|
|
1364
|
-
if (
|
|
1372
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1365
1373
|
}
|
|
1366
1374
|
/** Build the per-request envelope from the current transport state. */
|
|
1367
1375
|
envelope() {
|
|
1368
1376
|
const out = {};
|
|
1369
1377
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1370
|
-
if (this.
|
|
1378
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1371
1379
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1372
1380
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1373
1381
|
return out;
|
|
1374
1382
|
}
|
|
1375
1383
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1376
|
-
* start-
|
|
1384
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1377
1385
|
* differs from the active one. */
|
|
1378
1386
|
withEnvelope(body) {
|
|
1379
1387
|
return { ...this.envelope(), ...body };
|
|
@@ -1384,8 +1392,8 @@ var AgentTransport = class {
|
|
|
1384
1392
|
return form;
|
|
1385
1393
|
}
|
|
1386
1394
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1387
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1388
|
-
* selector on load-
|
|
1395
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1396
|
+
* selector on load-conversation). */
|
|
1389
1397
|
withEnvelopeQuery(urlOrPath) {
|
|
1390
1398
|
const url = new URL(this.url(urlOrPath));
|
|
1391
1399
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1394,23 +1402,31 @@ var AgentTransport = class {
|
|
|
1394
1402
|
return url.toString();
|
|
1395
1403
|
}
|
|
1396
1404
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1397
|
-
async
|
|
1398
|
-
log4.debug("
|
|
1399
|
-
|
|
1400
|
-
|
|
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", {
|
|
1401
1417
|
visitorId: res.visitorId,
|
|
1402
|
-
|
|
1418
|
+
conversationId: res.conversationId,
|
|
1403
1419
|
canContinue: res.canContinue,
|
|
1404
1420
|
hasMessages: !!res.messages?.length,
|
|
1405
1421
|
hasWelcome: !!res.welcome,
|
|
1406
1422
|
hasConfig: !!res.config,
|
|
1407
1423
|
rebind: res.rebind
|
|
1408
1424
|
});
|
|
1409
|
-
if (!
|
|
1410
|
-
log4.warn("
|
|
1425
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1426
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1411
1427
|
}
|
|
1412
1428
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1413
|
-
this.
|
|
1429
|
+
this.conversationId = res.conversationId;
|
|
1414
1430
|
return res;
|
|
1415
1431
|
}
|
|
1416
1432
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1435,45 +1451,45 @@ var AgentTransport = class {
|
|
|
1435
1451
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1436
1452
|
return res;
|
|
1437
1453
|
}
|
|
1438
|
-
async
|
|
1439
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1454
|
+
async listConversations(params = {}) {
|
|
1455
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1440
1456
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1441
1457
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1442
1458
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1443
|
-
log4.debug("
|
|
1459
|
+
log4.debug("listConversations \u2192", {
|
|
1444
1460
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1445
1461
|
limit: params.limit,
|
|
1446
1462
|
cursor: params.cursor
|
|
1447
1463
|
});
|
|
1448
|
-
const res = await this.getJson(url.toString(), "
|
|
1449
|
-
const
|
|
1450
|
-
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 });
|
|
1451
1467
|
return {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
title:
|
|
1455
|
-
lastMessageAt:
|
|
1456
|
-
preview:
|
|
1457
|
-
canContinue:
|
|
1458
|
-
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
|
|
1459
1475
|
})),
|
|
1460
1476
|
nextCursor: res.nextCursor
|
|
1461
1477
|
};
|
|
1462
1478
|
}
|
|
1463
|
-
async
|
|
1479
|
+
async loadConversation(conversationId) {
|
|
1464
1480
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1465
|
-
url.searchParams.set("
|
|
1466
|
-
log4.debug("
|
|
1467
|
-
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");
|
|
1468
1484
|
const messages = res.messages ?? [];
|
|
1469
|
-
log4.debug("
|
|
1470
|
-
|
|
1485
|
+
log4.debug("loadConversation \u2190", {
|
|
1486
|
+
conversationId: res.conversationId,
|
|
1471
1487
|
canContinue: res.canContinue,
|
|
1472
1488
|
messageCount: messages.length,
|
|
1473
1489
|
hasSuggestions: !!res.suggestions
|
|
1474
1490
|
});
|
|
1475
1491
|
return {
|
|
1476
|
-
|
|
1492
|
+
conversationId: res.conversationId,
|
|
1477
1493
|
canContinue: res.canContinue ?? true,
|
|
1478
1494
|
messages,
|
|
1479
1495
|
agent: res.agent,
|
|
@@ -1482,15 +1498,15 @@ var AgentTransport = class {
|
|
|
1482
1498
|
}
|
|
1483
1499
|
/**
|
|
1484
1500
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1485
|
-
* server records `lastReadAt` and clears that
|
|
1486
|
-
* 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
|
|
1487
1503
|
* next sync), so callers don't await this.
|
|
1488
1504
|
*/
|
|
1489
|
-
async markRead(
|
|
1490
|
-
if (!this.visitorId || !
|
|
1491
|
-
log4.debug("markRead \u2192", {
|
|
1505
|
+
async markRead(conversationId) {
|
|
1506
|
+
if (!this.visitorId || !conversationId) return;
|
|
1507
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1492
1508
|
try {
|
|
1493
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1509
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1494
1510
|
} catch (err) {
|
|
1495
1511
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1496
1512
|
}
|
|
@@ -1516,7 +1532,7 @@ var AgentTransport = class {
|
|
|
1516
1532
|
async saveUserPrefs(userPrefs) {
|
|
1517
1533
|
log4.debug("saveUserPrefs \u2192", {
|
|
1518
1534
|
visitorId: this.visitorId,
|
|
1519
|
-
|
|
1535
|
+
conversationId: this.conversationId,
|
|
1520
1536
|
settingsKeys: Object.keys(userPrefs)
|
|
1521
1537
|
});
|
|
1522
1538
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1534,7 +1550,7 @@ var AgentTransport = class {
|
|
|
1534
1550
|
}
|
|
1535
1551
|
/**
|
|
1536
1552
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1537
|
-
* record is captured even if the visitor never sends a message. `
|
|
1553
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1538
1554
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1539
1555
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1540
1556
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1549,7 +1565,7 @@ var AgentTransport = class {
|
|
|
1549
1565
|
}
|
|
1550
1566
|
sendMessage(body) {
|
|
1551
1567
|
log4.debug("message \u2192", {
|
|
1552
|
-
|
|
1568
|
+
conversationId: body.conversationId,
|
|
1553
1569
|
visitorId: body.visitorId,
|
|
1554
1570
|
messageCount: body.messages.length,
|
|
1555
1571
|
trigger: body.trigger,
|
|
@@ -1559,16 +1575,16 @@ var AgentTransport = class {
|
|
|
1559
1575
|
const ctrl = new AbortController();
|
|
1560
1576
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1561
1577
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1562
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1578
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1563
1579
|
return { iter, cancel };
|
|
1564
1580
|
}
|
|
1565
1581
|
/**
|
|
1566
1582
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1567
1583
|
*
|
|
1568
1584
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1569
|
-
* `
|
|
1585
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1570
1586
|
* the user refreshed while the assistant was still streaming, the
|
|
1571
|
-
* `
|
|
1587
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1572
1588
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1573
1589
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1574
1590
|
* (the common case — no bubble is created).
|
|
@@ -1595,7 +1611,7 @@ var AgentTransport = class {
|
|
|
1595
1611
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1596
1612
|
* off first, the reply may still be spinning up server-side);
|
|
1597
1613
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1598
|
-
* parallel with start-
|
|
1614
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1599
1615
|
* user reloaded keeps flowing).
|
|
1600
1616
|
*
|
|
1601
1617
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1604,7 +1620,7 @@ var AgentTransport = class {
|
|
|
1604
1620
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1605
1621
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1606
1622
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1607
|
-
* turn comes from the DB via start-
|
|
1623
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1608
1624
|
*
|
|
1609
1625
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1610
1626
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1670,11 +1686,11 @@ var AgentTransport = class {
|
|
|
1670
1686
|
return false;
|
|
1671
1687
|
}
|
|
1672
1688
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1673
|
-
cancelStream(ctrl,
|
|
1689
|
+
cancelStream(ctrl, conversationId) {
|
|
1674
1690
|
if (ctrl.signal.aborted) return;
|
|
1675
|
-
log4.debug("cancel stream", {
|
|
1691
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1676
1692
|
ctrl.abort();
|
|
1677
|
-
if (!this.visitorId || !
|
|
1693
|
+
if (!this.visitorId || !conversationId) return;
|
|
1678
1694
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1679
1695
|
method: "POST",
|
|
1680
1696
|
credentials: "omit",
|
|
@@ -1699,7 +1715,7 @@ var AgentTransport = class {
|
|
|
1699
1715
|
yield* parseChatStream(res, signal7);
|
|
1700
1716
|
}
|
|
1701
1717
|
/**
|
|
1702
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1718
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1703
1719
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1704
1720
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1705
1721
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1710,7 +1726,7 @@ var AgentTransport = class {
|
|
|
1710
1726
|
return url.toString();
|
|
1711
1727
|
}
|
|
1712
1728
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1713
|
-
// update-settings / mark-read / start-
|
|
1729
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1714
1730
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1715
1731
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1716
1732
|
async postJson(path, body, label) {
|
|
@@ -1794,10 +1810,10 @@ function extensionFor(mimeType) {
|
|
|
1794
1810
|
if (mimeType.includes("wav")) return "wav";
|
|
1795
1811
|
return "bin";
|
|
1796
1812
|
}
|
|
1797
|
-
function
|
|
1813
|
+
function isStartConversationResponseShape(raw) {
|
|
1798
1814
|
if (!raw || typeof raw !== "object") return false;
|
|
1799
1815
|
const r = raw;
|
|
1800
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1816
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1801
1817
|
}
|
|
1802
1818
|
|
|
1803
1819
|
// src/stream/messages.ts
|
|
@@ -2120,7 +2136,7 @@ var log6 = logger.scope("persistence");
|
|
|
2120
2136
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2121
2137
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2122
2138
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2123
|
-
const
|
|
2139
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2124
2140
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2125
2141
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2126
2142
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2140,13 +2156,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2140
2156
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2141
2157
|
storage.set(KEY_VISITOR, id);
|
|
2142
2158
|
},
|
|
2143
|
-
|
|
2144
|
-
return storage.get(
|
|
2159
|
+
loadConversationId() {
|
|
2160
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2145
2161
|
},
|
|
2146
|
-
|
|
2147
|
-
log6.trace("
|
|
2148
|
-
if (id) storage.set(
|
|
2149
|
-
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);
|
|
2150
2166
|
},
|
|
2151
2167
|
loadUserPrefs() {
|
|
2152
2168
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2230,8 +2246,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2230
2246
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2231
2247
|
}
|
|
2232
2248
|
},
|
|
2233
|
-
|
|
2234
|
-
storage.remove(
|
|
2249
|
+
clearConversation() {
|
|
2250
|
+
storage.remove(KEY_CONVERSATION);
|
|
2235
2251
|
}
|
|
2236
2252
|
};
|
|
2237
2253
|
return persistence;
|
|
@@ -2413,7 +2429,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2413
2429
|
var FeedbackBus = class {
|
|
2414
2430
|
constructor(sound, haptics) {
|
|
2415
2431
|
/**
|
|
2416
|
-
* User/
|
|
2432
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2417
2433
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2418
2434
|
* `Persistence` layer.
|
|
2419
2435
|
*/
|
|
@@ -2731,7 +2747,7 @@ var TID = {
|
|
|
2731
2747
|
historyPane: `${p2}-history-pane`,
|
|
2732
2748
|
/** History pane back / close button. */
|
|
2733
2749
|
historyBack: `${p2}-history-back`,
|
|
2734
|
-
/** Single history list row — suffix `-{
|
|
2750
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2735
2751
|
historyItem: `${p2}-history-item`,
|
|
2736
2752
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2737
2753
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
@@ -2740,7 +2756,7 @@ var TID = {
|
|
|
2740
2756
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2741
2757
|
/** Sidebar "New chat" button. */
|
|
2742
2758
|
sidebarNewChat: `${p2}-sidebar-new-chat`,
|
|
2743
|
-
/** Sidebar history row — suffix `-{
|
|
2759
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2744
2760
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2745
2761
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2746
2762
|
/** Messenger-home surface root. */
|
|
@@ -4837,15 +4853,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4837
4853
|
if (diffDays < 7) return "lastWeek";
|
|
4838
4854
|
return "older";
|
|
4839
4855
|
}
|
|
4840
|
-
function groupByBucket(nowMs,
|
|
4856
|
+
function groupByBucket(nowMs, conversations) {
|
|
4841
4857
|
const buckets = /* @__PURE__ */ new Map();
|
|
4842
|
-
for (const chat of
|
|
4858
|
+
for (const chat of conversations) {
|
|
4843
4859
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4844
4860
|
const list = buckets.get(b);
|
|
4845
4861
|
if (list) list.push(chat);
|
|
4846
4862
|
else buckets.set(b, [chat]);
|
|
4847
4863
|
}
|
|
4848
|
-
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) }));
|
|
4849
4865
|
}
|
|
4850
4866
|
function startOfDay(ms) {
|
|
4851
4867
|
const d = new Date(ms);
|
|
@@ -4865,16 +4881,16 @@ var BUCKET_TO_STRING = {
|
|
|
4865
4881
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
4866
4882
|
const p33 = BRAND.cssPrefix;
|
|
4867
4883
|
const [state, setState] = useState7("loading");
|
|
4868
|
-
const [
|
|
4884
|
+
const [conversations, setChats] = useState7([]);
|
|
4869
4885
|
useEffect9(() => {
|
|
4870
4886
|
let cancelled = false;
|
|
4871
|
-
transport.
|
|
4887
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4872
4888
|
if (cancelled) return;
|
|
4873
|
-
setChats(res.
|
|
4889
|
+
setChats(res.conversations ?? []);
|
|
4874
4890
|
setState("loaded");
|
|
4875
4891
|
}).catch((err) => {
|
|
4876
4892
|
if (cancelled) return;
|
|
4877
|
-
log11.warn("
|
|
4893
|
+
log11.warn("listConversations failed", { err });
|
|
4878
4894
|
setState("error");
|
|
4879
4895
|
});
|
|
4880
4896
|
return () => {
|
|
@@ -4891,17 +4907,17 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4891
4907
|
newChatButton
|
|
4892
4908
|
] });
|
|
4893
4909
|
}
|
|
4894
|
-
if (state === "error" ||
|
|
4910
|
+
if (state === "error" || conversations.length === 0) {
|
|
4895
4911
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4896
4912
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4897
4913
|
newChatButton
|
|
4898
4914
|
] });
|
|
4899
4915
|
}
|
|
4900
|
-
const groups = groupByBucket(Date.now(),
|
|
4916
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4901
4917
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4902
4918
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4903
4919
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4904
|
-
group.
|
|
4920
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4905
4921
|
"button",
|
|
4906
4922
|
{
|
|
4907
4923
|
type: "button",
|
|
@@ -4909,13 +4925,13 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4909
4925
|
class: `${p33}-history-item`,
|
|
4910
4926
|
onClick: () => onSelect(chat),
|
|
4911
4927
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4912
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4928
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
4913
4929
|
children: [
|
|
4914
4930
|
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4915
4931
|
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4916
4932
|
]
|
|
4917
4933
|
},
|
|
4918
|
-
chat.
|
|
4934
|
+
chat.conversationId
|
|
4919
4935
|
))
|
|
4920
4936
|
] }, group.bucket)) }),
|
|
4921
4937
|
newChatButton
|
|
@@ -5085,7 +5101,7 @@ function PanelContent(props2) {
|
|
|
5085
5101
|
transport,
|
|
5086
5102
|
strings: s,
|
|
5087
5103
|
visitorId,
|
|
5088
|
-
onSelect: (chat) => onSelectHistoryChat(chat.
|
|
5104
|
+
onSelect: (chat) => onSelectHistoryChat(chat.conversationId),
|
|
5089
5105
|
onNewChat
|
|
5090
5106
|
}
|
|
5091
5107
|
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
@@ -5188,10 +5204,11 @@ function useForms(deps) {
|
|
|
5188
5204
|
}
|
|
5189
5205
|
function createController(depsRef) {
|
|
5190
5206
|
const activeForm = signal5(null);
|
|
5191
|
-
const
|
|
5207
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5208
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5192
5209
|
const isDone = (form) => {
|
|
5193
5210
|
if (form.frequency === "always") return false;
|
|
5194
|
-
if (form.frequency === "
|
|
5211
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5195
5212
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5196
5213
|
};
|
|
5197
5214
|
const fire = (kind, param) => {
|
|
@@ -5214,7 +5231,7 @@ function createController(depsRef) {
|
|
|
5214
5231
|
if (!active) return;
|
|
5215
5232
|
activeForm.value = null;
|
|
5216
5233
|
const { form, trigger } = active;
|
|
5217
|
-
if (form.frequency === "
|
|
5234
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5218
5235
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5219
5236
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5220
5237
|
};
|
|
@@ -5616,7 +5633,7 @@ function HomeRoot(props2) {
|
|
|
5616
5633
|
useEffect12(() => {
|
|
5617
5634
|
if (!config.showRecentMessages) return;
|
|
5618
5635
|
let cancelled = false;
|
|
5619
|
-
transport.
|
|
5636
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5620
5637
|
return () => {
|
|
5621
5638
|
cancelled = true;
|
|
5622
5639
|
};
|
|
@@ -5655,7 +5672,7 @@ function HomeRoot(props2) {
|
|
|
5655
5672
|
onActivate: () => nav.switchToLayout("help")
|
|
5656
5673
|
}
|
|
5657
5674
|
) : null,
|
|
5658
|
-
recent ? /* @__PURE__ */ jsx30(HomeCard, { onClick: () => nav.
|
|
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: [
|
|
5659
5676
|
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5660
5677
|
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5661
5678
|
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
@@ -5888,8 +5905,8 @@ function MessengerHome({
|
|
|
5888
5905
|
enabledModules,
|
|
5889
5906
|
nav,
|
|
5890
5907
|
unreadCount,
|
|
5891
|
-
|
|
5892
|
-
|
|
5908
|
+
onSelectConversation,
|
|
5909
|
+
onStartNewConversation,
|
|
5893
5910
|
onSetPanelSize
|
|
5894
5911
|
}) {
|
|
5895
5912
|
const options = panelProps.options;
|
|
@@ -5938,8 +5955,8 @@ function MessengerHome({
|
|
|
5938
5955
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
5939
5956
|
if (target) nav.switchTab(target.id);
|
|
5940
5957
|
},
|
|
5941
|
-
|
|
5942
|
-
|
|
5958
|
+
selectConversation: onSelectConversation,
|
|
5959
|
+
startNewConversation: onStartNewConversation
|
|
5943
5960
|
};
|
|
5944
5961
|
const screenProps = (module) => ({
|
|
5945
5962
|
options,
|
|
@@ -6127,7 +6144,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6127
6144
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6128
6145
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6129
6146
|
);
|
|
6130
|
-
const
|
|
6147
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6131
6148
|
const messagesSig = useSignal2([]);
|
|
6132
6149
|
const unreadCountSig = useSignal2(0);
|
|
6133
6150
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6149,7 +6166,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6149
6166
|
const homeNav = homeNavRef.current;
|
|
6150
6167
|
const chatTabIdRef = useRef9(void 0);
|
|
6151
6168
|
chatTabIdRef.current = chatTabId();
|
|
6152
|
-
const [
|
|
6169
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6153
6170
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6154
6171
|
const initialPanelRef = useRef9(
|
|
6155
6172
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6229,7 +6246,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6229
6246
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6230
6247
|
}, [options.mode, options.size, persistence]);
|
|
6231
6248
|
useEffect17(() => {
|
|
6232
|
-
if (!
|
|
6249
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6233
6250
|
initialPanelApplied.current = true;
|
|
6234
6251
|
const state = resolveInitialPanelState(
|
|
6235
6252
|
options,
|
|
@@ -6239,12 +6256,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6239
6256
|
);
|
|
6240
6257
|
setIsOpen(state.panelOpen);
|
|
6241
6258
|
setPanelSize(state.panelSize);
|
|
6242
|
-
}, [
|
|
6259
|
+
}, [conversationReady, options, persistence]);
|
|
6243
6260
|
const homeNavSeeded = useRef9(false);
|
|
6244
6261
|
const resumeActiveRef = useRef9(false);
|
|
6245
6262
|
const resumeBubbleRef = useRef9(null);
|
|
6246
6263
|
useEffect17(() => {
|
|
6247
|
-
if (!
|
|
6264
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6248
6265
|
homeNavSeeded.current = true;
|
|
6249
6266
|
if (resumeActiveRef.current) {
|
|
6250
6267
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6252,7 +6269,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6252
6269
|
return;
|
|
6253
6270
|
}
|
|
6254
6271
|
homeNav.reset(landingTab());
|
|
6255
|
-
}, [
|
|
6272
|
+
}, [conversationReady]);
|
|
6256
6273
|
const playWelcome = useCallback6(
|
|
6257
6274
|
(welcomeMessages) => {
|
|
6258
6275
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6271,21 +6288,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6271
6288
|
[messagesSig, options.welcome]
|
|
6272
6289
|
);
|
|
6273
6290
|
const connectGenRef = useRef9(0);
|
|
6274
|
-
const
|
|
6291
|
+
const runStartConversation = useCallback6(
|
|
6275
6292
|
async ({ newConversation }) => {
|
|
6276
6293
|
const myGen = ++connectGenRef.current;
|
|
6277
6294
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6278
|
-
const persistedChatId =
|
|
6279
|
-
const
|
|
6280
|
-
if (
|
|
6281
|
-
|
|
6282
|
-
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);
|
|
6283
6300
|
}
|
|
6284
6301
|
let res;
|
|
6285
6302
|
try {
|
|
6286
|
-
res = await transport.
|
|
6303
|
+
res = await transport.startConversation({
|
|
6287
6304
|
visitorId,
|
|
6288
|
-
|
|
6305
|
+
conversationId,
|
|
6289
6306
|
userPrefs: persistence.loadUserPrefs(),
|
|
6290
6307
|
locale: options.locale
|
|
6291
6308
|
});
|
|
@@ -6293,7 +6310,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6293
6310
|
if (isStale()) return;
|
|
6294
6311
|
bus.emit("error", err);
|
|
6295
6312
|
options.onError?.(err);
|
|
6296
|
-
if (!newConversation)
|
|
6313
|
+
if (!newConversation) setConversationReady(true);
|
|
6297
6314
|
return;
|
|
6298
6315
|
}
|
|
6299
6316
|
if (isStale()) return;
|
|
@@ -6307,12 +6324,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6307
6324
|
reason: res.rebind?.visitorId
|
|
6308
6325
|
});
|
|
6309
6326
|
}
|
|
6310
|
-
if (res.
|
|
6311
|
-
log16.info("
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
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
|
|
6316
6337
|
});
|
|
6317
6338
|
}
|
|
6318
6339
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6329,36 +6350,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6329
6350
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6330
6351
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6331
6352
|
}
|
|
6332
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6353
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6333
6354
|
if (isResume) {
|
|
6334
6355
|
setLoadingMessages(true);
|
|
6335
6356
|
try {
|
|
6336
|
-
const chat = res.messages?.length ? {
|
|
6357
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6337
6358
|
if (isStale()) return;
|
|
6338
6359
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6339
6360
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6340
|
-
if (loaded.length || tail.length)
|
|
6341
|
-
|
|
6342
|
-
|
|
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
|
+
}
|
|
6343
6368
|
} catch (err) {
|
|
6344
6369
|
if (isStale()) return;
|
|
6345
|
-
log16.warn("
|
|
6346
|
-
|
|
6347
|
-
persistence.
|
|
6370
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6371
|
+
conversationIdSig.value = void 0;
|
|
6372
|
+
persistence.saveConversationId(void 0);
|
|
6348
6373
|
} finally {
|
|
6349
6374
|
if (!isStale()) setLoadingMessages(false);
|
|
6350
6375
|
}
|
|
6351
6376
|
} else {
|
|
6352
|
-
|
|
6353
|
-
persistence.
|
|
6377
|
+
conversationIdSig.value = res.conversationId;
|
|
6378
|
+
persistence.saveConversationId(res.conversationId);
|
|
6354
6379
|
playWelcome(res.welcome?.messages);
|
|
6355
6380
|
}
|
|
6356
6381
|
if (!newConversation) {
|
|
6357
|
-
bus.emit("
|
|
6358
|
-
|
|
6382
|
+
bus.emit("conversationStarted", res);
|
|
6383
|
+
setConversationReady(true);
|
|
6359
6384
|
}
|
|
6360
6385
|
},
|
|
6361
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6386
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6362
6387
|
);
|
|
6363
6388
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6364
6389
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6412,11 +6437,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6412
6437
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6413
6438
|
);
|
|
6414
6439
|
useEffect17(() => {
|
|
6415
|
-
void
|
|
6416
|
-
const
|
|
6440
|
+
void runStartConversation({ newConversation: false });
|
|
6441
|
+
const persistedConversation = conversationIdSig.value;
|
|
6417
6442
|
let resume = null;
|
|
6418
|
-
if (
|
|
6419
|
-
transport.primeIdentity(visitorId,
|
|
6443
|
+
if (persistedConversation) {
|
|
6444
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6420
6445
|
resume = transport.resumeStream();
|
|
6421
6446
|
void runResume(resume);
|
|
6422
6447
|
}
|
|
@@ -6427,10 +6452,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6427
6452
|
}, []);
|
|
6428
6453
|
const lastUserSig = useRef9(userSig);
|
|
6429
6454
|
useEffect17(() => {
|
|
6430
|
-
if (!
|
|
6455
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6431
6456
|
lastUserSig.current = userSig;
|
|
6432
|
-
void
|
|
6433
|
-
}, [userSig,
|
|
6457
|
+
void runStartConversation({ newConversation: false });
|
|
6458
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6434
6459
|
useEffect17(() => {
|
|
6435
6460
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6436
6461
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6456,14 +6481,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6456
6481
|
}, [isOpen, options.mode]);
|
|
6457
6482
|
const streamAssistant = useCallback6(
|
|
6458
6483
|
async (assistantMsg, trigger) => {
|
|
6459
|
-
const
|
|
6460
|
-
if (!
|
|
6461
|
-
|
|
6462
|
-
persistence.
|
|
6484
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6485
|
+
if (!conversationIdSig.value) {
|
|
6486
|
+
conversationIdSig.value = activeConversationId;
|
|
6487
|
+
persistence.saveConversationId(activeConversationId);
|
|
6463
6488
|
}
|
|
6464
6489
|
const body = buildSendMessageRequest({
|
|
6465
6490
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6466
|
-
|
|
6491
|
+
conversationId: activeConversationId,
|
|
6467
6492
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6468
6493
|
tools: options.features.tools,
|
|
6469
6494
|
responseMode: options.responseMode,
|
|
@@ -6499,7 +6524,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6499
6524
|
messagesSig.value = [...messagesSig.value];
|
|
6500
6525
|
}
|
|
6501
6526
|
},
|
|
6502
|
-
[transport, reducer, messagesSig,
|
|
6527
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6503
6528
|
);
|
|
6504
6529
|
const resolveTool = useCallback6(
|
|
6505
6530
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6555,32 +6580,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6555
6580
|
userContext: () => options.userContext,
|
|
6556
6581
|
messageCount: userMessageCount,
|
|
6557
6582
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6583
|
+
conversationId: () => conversationIdSig.value,
|
|
6558
6584
|
onComplete: (form, trigger, values, skipped) => {
|
|
6559
6585
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6560
6586
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6561
6587
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6562
|
-
const
|
|
6563
|
-
if (!
|
|
6564
|
-
|
|
6565
|
-
persistence.
|
|
6566
|
-
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);
|
|
6567
6593
|
}
|
|
6568
6594
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6569
|
-
void transport.submitForm({ formId: form.id,
|
|
6595
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6570
6596
|
}
|
|
6571
6597
|
});
|
|
6572
6598
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6573
6599
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6574
6600
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6575
6601
|
useEffect17(() => {
|
|
6576
|
-
if (
|
|
6577
|
-
}, [
|
|
6602
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6603
|
+
}, [conversationReady, forms]);
|
|
6578
6604
|
useEffect17(() => {
|
|
6579
6605
|
if (!canSend) forms.fire("conversation-closed");
|
|
6580
6606
|
}, [canSend, forms]);
|
|
6581
6607
|
useEffect17(() => {
|
|
6582
|
-
if (
|
|
6583
|
-
}, [
|
|
6608
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6609
|
+
}, [conversationReady, pageArea, forms]);
|
|
6584
6610
|
const idleMs = useMemo3(() => {
|
|
6585
6611
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6586
6612
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6640,16 +6666,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6640
6666
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6641
6667
|
const refreshUnread = useCallback6(() => {
|
|
6642
6668
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6643
|
-
transport.
|
|
6644
|
-
unreadCountSig.value = res.
|
|
6669
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6670
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6645
6671
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6646
6672
|
}, [transport, options.modules, unreadCountSig]);
|
|
6647
6673
|
const unreadSeeded = useRef9(false);
|
|
6648
6674
|
useEffect17(() => {
|
|
6649
|
-
if (!
|
|
6675
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6650
6676
|
unreadSeeded.current = true;
|
|
6651
6677
|
refreshUnread();
|
|
6652
|
-
}, [
|
|
6678
|
+
}, [conversationReady, refreshUnread]);
|
|
6653
6679
|
const handleOpen = useCallback6(() => {
|
|
6654
6680
|
log16.info("open", { mode: options.mode });
|
|
6655
6681
|
feedback.unlock();
|
|
@@ -6668,11 +6694,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6668
6694
|
if (streaming) activeCancel?.();
|
|
6669
6695
|
welcomeAbortRef.current?.abort();
|
|
6670
6696
|
messagesSig.value = [];
|
|
6671
|
-
|
|
6672
|
-
persistence.
|
|
6697
|
+
conversationIdSig.value = void 0;
|
|
6698
|
+
persistence.clearConversation();
|
|
6673
6699
|
setCanSend(true);
|
|
6674
|
-
void
|
|
6675
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6700
|
+
void runStartConversation({ newConversation: true });
|
|
6701
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6676
6702
|
const handleNewChat = useCallback6(() => {
|
|
6677
6703
|
handleClear();
|
|
6678
6704
|
setView("chat");
|
|
@@ -6696,12 +6722,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6696
6722
|
const handlePopOut = useCallback6(() => {
|
|
6697
6723
|
if (!options.popOutUrl) return;
|
|
6698
6724
|
const url = new URL(options.popOutUrl);
|
|
6699
|
-
if (
|
|
6725
|
+
if (conversationIdSig.value) url.searchParams.set("chat", conversationIdSig.value);
|
|
6700
6726
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6701
6727
|
log16.info("popOut", { url: url.toString() });
|
|
6702
6728
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6703
6729
|
bus.emit("popOut", void 0);
|
|
6704
|
-
}, [bus,
|
|
6730
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6705
6731
|
const handleToggleHistory = useCallback6(() => {
|
|
6706
6732
|
setView((v) => {
|
|
6707
6733
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6748,14 +6774,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6748
6774
|
);
|
|
6749
6775
|
const handleSelectHistoryChat = useCallback6(
|
|
6750
6776
|
async (targetChatId) => {
|
|
6751
|
-
log16.info("selectChat", {
|
|
6752
|
-
bus.emit("selectChat", {
|
|
6777
|
+
log16.info("selectChat", { conversationId: targetChatId });
|
|
6778
|
+
bus.emit("selectChat", { conversationId: targetChatId });
|
|
6753
6779
|
try {
|
|
6754
|
-
const res = await transport.
|
|
6780
|
+
const res = await transport.loadConversation(targetChatId);
|
|
6755
6781
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6756
6782
|
messagesSig.value = hydrated;
|
|
6757
|
-
|
|
6758
|
-
persistence.
|
|
6783
|
+
conversationIdSig.value = res.conversationId;
|
|
6784
|
+
persistence.saveConversationId(res.conversationId);
|
|
6759
6785
|
if (res.agent) setAgent(res.agent);
|
|
6760
6786
|
setCanSend(res.canContinue);
|
|
6761
6787
|
setSuggestions(res.suggestions ?? []);
|
|
@@ -6767,7 +6793,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6767
6793
|
options.onError?.(err);
|
|
6768
6794
|
}
|
|
6769
6795
|
},
|
|
6770
|
-
[transport, messagesSig,
|
|
6796
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6771
6797
|
);
|
|
6772
6798
|
useEffect17(() => {
|
|
6773
6799
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6825,12 +6851,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6825
6851
|
onFormSkip: forms.skip,
|
|
6826
6852
|
tool: toolInteraction
|
|
6827
6853
|
};
|
|
6828
|
-
const
|
|
6829
|
-
void handleSelectHistoryChat(
|
|
6854
|
+
const onSelectConversation = (conversationId) => {
|
|
6855
|
+
void handleSelectHistoryChat(conversationId);
|
|
6830
6856
|
const chatId = chatTabId();
|
|
6831
6857
|
if (chatId) homeNav.switchTab(chatId);
|
|
6832
6858
|
};
|
|
6833
|
-
if (!
|
|
6859
|
+
if (!conversationReady) return null;
|
|
6834
6860
|
const enabledModules = effectiveOptions.modules.list;
|
|
6835
6861
|
const renderSurface = (size) => {
|
|
6836
6862
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
@@ -6847,15 +6873,15 @@ function App({ options, hostElement, bus }) {
|
|
|
6847
6873
|
enabledModules,
|
|
6848
6874
|
nav: homeNav,
|
|
6849
6875
|
unreadCount: unreadCountSig.value,
|
|
6850
|
-
|
|
6851
|
-
|
|
6876
|
+
onSelectConversation,
|
|
6877
|
+
onStartNewConversation: handleNewChat,
|
|
6852
6878
|
onSetPanelSize: setPanelSize
|
|
6853
6879
|
}
|
|
6854
6880
|
);
|
|
6855
6881
|
};
|
|
6856
6882
|
if (options.mode === "page") {
|
|
6857
6883
|
const onSelectChatFromSidebar = (chat) => {
|
|
6858
|
-
void handleSelectHistoryChat(chat.
|
|
6884
|
+
void handleSelectHistoryChat(chat.conversationId);
|
|
6859
6885
|
};
|
|
6860
6886
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6861
6887
|
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
@@ -7112,9 +7138,9 @@ var EVENT_NAMES = [
|
|
|
7112
7138
|
"calloutDismiss",
|
|
7113
7139
|
// Lifecycle / errors
|
|
7114
7140
|
"error",
|
|
7115
|
-
"
|
|
7141
|
+
"conversationStarted",
|
|
7116
7142
|
"visitorRebound",
|
|
7117
|
-
"
|
|
7143
|
+
"conversationRebound"
|
|
7118
7144
|
];
|
|
7119
7145
|
|
|
7120
7146
|
// src/index.ts
|
|
@@ -7169,7 +7195,7 @@ function mount(opts) {
|
|
|
7169
7195
|
);
|
|
7170
7196
|
};
|
|
7171
7197
|
renderApp();
|
|
7172
|
-
bus.on("
|
|
7198
|
+
bus.on("conversationStarted", (response) => {
|
|
7173
7199
|
if (!response.config) return;
|
|
7174
7200
|
rawOptions = mergeServerConfig(rawOptions, response.config);
|
|
7175
7201
|
currentOptions = resolveOptions(rawOptions);
|
|
@@ -7198,9 +7224,9 @@ function mount(opts) {
|
|
|
7198
7224
|
log20.debug("update", { patch });
|
|
7199
7225
|
applyUpdate(patch);
|
|
7200
7226
|
},
|
|
7201
|
-
// Host-asserted context (NOT our visitor/
|
|
7227
|
+
// Host-asserted context (NOT our visitor/conversation — those are minted +
|
|
7202
7228
|
// persisted by the widget and untouched here). Merge into the current
|
|
7203
|
-
// context; App re-handshakes with the SAME visitor/
|
|
7229
|
+
// context; App re-handshakes with the SAME visitor/conversation.
|
|
7204
7230
|
setUserContext: (userContext) => {
|
|
7205
7231
|
log20.debug("setUserContext", { keys: Object.keys(userContext) });
|
|
7206
7232
|
applyUpdate({ userContext: { ...rawOptions.userContext, ...userContext } });
|