@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/web-component.mjs
CHANGED
|
@@ -362,7 +362,15 @@ var logger = makeLogger("core");
|
|
|
362
362
|
|
|
363
363
|
// src/core/config/user-context.ts
|
|
364
364
|
var log = logger.scope("context");
|
|
365
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
365
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
366
|
+
"visitorId",
|
|
367
|
+
"conversationId",
|
|
368
|
+
"conversationId",
|
|
369
|
+
"jwt",
|
|
370
|
+
"token",
|
|
371
|
+
"authorization",
|
|
372
|
+
"password"
|
|
373
|
+
]);
|
|
366
374
|
var MAX_KEYS = 50;
|
|
367
375
|
var MAX_STRING = 1024;
|
|
368
376
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -924,7 +932,7 @@ function parseLauncher(get, str2) {
|
|
|
924
932
|
return Object.keys(base).length > 0 ? base : null;
|
|
925
933
|
}
|
|
926
934
|
|
|
927
|
-
// src/core/start-
|
|
935
|
+
// src/core/start-conversation-shape.ts
|
|
928
936
|
function isPlainObject(raw) {
|
|
929
937
|
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
930
938
|
}
|
|
@@ -962,7 +970,7 @@ var tokens_default = ':host{--__P__-accent: __BRAND_ACCENT__;--__P__-accent-text
|
|
|
962
970
|
var reset_default = '*,*:before,*:after{box-sizing:border-box;margin:0;padding:0;border:0}button{font:inherit;color:inherit;background:none;cursor:pointer;-webkit-appearance:none;appearance:none;line-height:1}button:focus-visible,[tabindex]:focus-visible,textarea:focus-visible,input:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}textarea,input{font:inherit;color:inherit;background:none;border:0;outline:0;resize:none}a{color:var(--__P__-accent);text-decoration:underline;text-underline-offset:2px}img,svg{display:block;max-width:100%}ul,ol{list-style:none}.__P__-app{display:block;width:100%;height:100%;font-family:var(--__P__-font);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"cv11","ss01","ss03"}.__P__-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n';
|
|
963
971
|
|
|
964
972
|
// src/styles/panel.css
|
|
965
|
-
var panel_default = '.__P__-anchor{right:16px;bottom:16px}:host([data-position="bottom-left"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{right:auto;left:16px}:host([data-position="top-right"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{bottom:auto;top:16px}.__P__-anchor{position:fixed;display:flex;flex-direction:column;align-items:flex-end;gap:var(--__P__-space-3);pointer-events:none}.__P__-anchor{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=sm]{--__P__-fab-size: 44px}.__P__-anchor[data-launcher-size=md]{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=lg]{--__P__-fab-size: 68px}.__P__-anchor>*{pointer-events:auto}.__P__-fab[data-size=sm]{--__P__-fab-size: 44px;font-size:var(--__P__-text-sm)}.__P__-fab[data-size=md]{--__P__-fab-size: 56px;font-size:14px}.__P__-fab[data-size=lg]{--__P__-fab-size: 68px;font-size:var(--__P__-text-base)}.__P__-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);color:var(--__P__-accent-text);background:var(--__P__-accent);box-shadow:var(--__P__-shadow-fab);font-weight:600;line-height:1;transform-origin:bottom right;animation:__P__-fab-in var(--__P__-dur-base) var(--__P__-ease) both;transition:transform var(--__P__-dur-base) var(--__P__-ease),opacity var(--__P__-dur-base) var(--__P__-ease),box-shadow var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab:hover{transform:translateY(-2px)}.__P__-fab:active{transform:translateY(0)}.__P__-fab:focus-visible{outline:2px solid var(--__P__-on-accent);outline-offset:3px}.__P__-fab svg{width:24px;height:24px;flex-shrink:0}@keyframes __P__-fab-in{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}.__P__-fab[data-leaving]{position:absolute;right:0;bottom:0;animation:__P__-fab-out var(--__P__-dur-quick) var(--__P__-ease) forwards;pointer-events:none}:host([data-position^="top-"]) .__P__-fab[data-leaving]{bottom:auto;top:0}:host([data-position$="-left"]) .__P__-fab[data-leaving]{right:auto;left:0}@keyframes __P__-fab-out{0%{opacity:1;transform:none}to{opacity:0;transform:scale(.85)}}.__P__-fab[data-variant=circle]{width:var(--__P__-fab-size);height:var(--__P__-fab-size);border-radius:999px}.__P__-fab[data-variant=circle] .__P__-fab-label{display:none}.__P__-fab[data-variant=pill]{height:var(--__P__-fab-size);padding:0 18px 0 16px;border-radius:999px}.__P__-fab[data-variant=bar]{height:var(--__P__-fab-size);padding:0 22px;border-radius:var(--__P__-radius)}.__P__-fab[data-variant=minimal]{height:var(--__P__-fab-size);padding:0 var(--__P__-space-4);border-radius:999px;background:transparent;color:var(--__P__-accent);box-shadow:none;border:1px solid currentColor}.__P__-fab[data-variant=minimal]:hover{background:color-mix(in srgb,var(--__P__-accent) 12%,transparent)}.__P__-callout{--__P__-callout-fab-h: var(--__P__-fab-size, 56px);--__P__-callout-gap: clamp(12px, calc(var(--__P__-callout-fab-h) * .25), 22px);--__P__-callout-nudge-direction: -1;position:absolute;display:inline-flex;align-items:center;gap:var(--__P__-space-2);padding:10px 14px;background:var(--__P__-fg);color:var(--__P__-bg);border-radius:999px;font-size:var(--__P__-text-sm);font-weight:600;line-height:1.2;box-shadow:0 10px 30px -8px #00000059;pointer-events:auto;animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease);z-index:1;max-width:240px;white-space:nowrap}.__P__-callout[data-position=left]{right:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%)}.__P__-callout[data-position=right]{left:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%);--__P__-callout-nudge-direction: 1}.__P__-callout[data-position=top]{bottom:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-position=bottom]{top:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}:host([data-position$="-left"]) .__P__-callout[data-position=top],:host([data-position$="-left"]) .__P__-callout[data-position=bottom]{right:auto;left:0}.__P__-callout[data-shape=bubble]{border-radius:var(--__P__-radius-md);white-space:normal;width:max-content;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-shape=callout]{padding:12px 18px;font-size:14px;background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-callout:after{content:"";position:absolute;width:12px;height:12px;background:inherit;border-radius:2px;transform:rotate(45deg)}.__P__-callout[data-position=left]:after{right:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=right]:after{left:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=top]:after{bottom:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-position=bottom]:after{top:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}:host([data-position$="-left"]) .__P__-callout[data-position=top]:after,:host([data-position$="-left"]) .__P__-callout[data-position=bottom]:after{right:auto;left:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-animated]{animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease),__P__-callout-nudge 1.6s var(--__P__-ease-in-out) var(--__P__-dur-slow) infinite}@keyframes __P__-callout-in{0%{opacity:0}to{opacity:1}}@keyframes __P__-callout-nudge{0%,to{margin-left:0;margin-right:0}50%{margin-left:calc(6px * var(--__P__-callout-nudge-direction));margin-right:calc(-6px * var(--__P__-callout-nudge-direction))}}@media(prefers-reduced-motion:reduce){.__P__-callout[data-animated]{animation:__P__-callout-in 1ms var(--__P__-ease)}.__P__-icon-btn[data-recording=true],.__P__-typing span{animation:none}}.__P__-callout-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:inherit;opacity:.7;cursor:pointer}.__P__-callout-close:hover{opacity:1;background:#ffffff26}.__P__-callout-close svg{width:12px;height:12px}.__P__-panel{width:var(--__P__-panel-w);height:var(--__P__-panel-h);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);background:var(--__P__-bg);color:var(--__P__-fg);border-radius:var(--__P__-radius-lg);box-shadow:var(--__P__-shadow-panel);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;animation:__P__-panel-in var(--__P__-dur-slow) var(--__P__-ease);border:1px solid var(--__P__-border)}:host([data-mode="open"]) .__P__-panel{width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));min-width:var(--__P__-resize-min-w, auto);min-height:var(--__P__-resize-min-h, auto);max-width:var(--__P__-resize-max-w, calc(100vw - 32px) );max-height:var(--__P__-resize-max-h, calc(100dvh - 32px) )}@keyframes __P__-panel-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}:host([data-mode="expanded"]) .__P__-panel{width:var(--__P__-expanded-w, 640px);height:var(--__P__-expanded-h, 820px);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px)}:host([data-mode="fullscreen"]){z-index:var(--__P__-z-panel)!important}:host([data-mode="fullscreen"]) .__P__-anchor{inset:0;align-items:stretch;padding:0}:host([data-mode="fullscreen"]) .__P__-panel{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}:host([data-mode="fullscreen"]) .__P__-fab{display:none}:host([data-mode="inline"]) .__P__-anchor,:host([data-mode="standalone"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-height:0}:host([data-mode="inline"]) .__P__-panel,:host([data-mode="standalone"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;animation:none}:host([data-mode="inline"]) .__P__-fab,:host([data-mode="standalone"]) .__P__-fab{display:none}:host([data-mode="inline"]){min-height:320px}:host([data-mode="inline"]) .__P__-panel{border-radius:var(--__P__-radius)}:host([data-mode="standalone"]) .__P__-panel{border-radius:0;border:0;box-shadow:none}:host([data-mode="modal"]){position:fixed!important;inset:0!important;z-index:var(--__P__-z-panel)!important;display:block!important;width:100vw;height:100dvh;background:var(--__P__-modal-backdrop, var(--__P__-backdrop));animation:__P__-backdrop-in var(--__P__-dur-base) var(--__P__-ease) both;--__P__-panel-w: min(960px, 92vw);--__P__-panel-h: min(720px, 88dvh)}:host([data-mode="modal"]) .__P__-anchor{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:var(--__P__-space-6);pointer-events:none}:host([data-mode="modal"]) .__P__-panel{pointer-events:auto;width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));max-width:calc(100vw - 48px);max-height:calc(100dvh - 48px);min-width:0;min-height:0;border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-panel);animation:__P__-modal-in var(--__P__-dur-base) var(--__P__-ease);translate:var(--__P__-modal-dx, 0px) var(--__P__-modal-dy, 0px)}:host([data-mode="modal"]) .__P__-header,:host([data-mode="modal"]) .__P__-back-header,:host([data-mode="modal"]) .__P__-home-hero{cursor:grab;touch-action:none}:host([data-mode="modal"]) .__P__-panel[data-dragging]{cursor:grabbing;user-select:none}:host([data-mode="modal"]) .__P__-panel[data-dragging] *{cursor:grabbing}:host([data-mode="modal"]) .__P__-fab{display:none}@keyframes __P__-backdrop-in{0%{background:#0000}to{background:var(--__P__-modal-backdrop, var(--__P__-backdrop))}}@keyframes __P__-modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}:host([data-mode="drawer"]){--__P__-panel-w: min(440px, calc(100vw - 32px) );--__P__-panel-h: 100dvh}:host([data-mode="drawer"]) .__P__-anchor{position:fixed;--__P__-inset-x: var(--__P__-panel-inset, 12px);--__P__-inset-y: var(--__P__-panel-inset, 3dvh);top:var(--__P__-inset-y);bottom:auto;right:var(--__P__-inset-x);left:auto;width:min(var(--__P__-widget-w, var(--__P__-panel-w)),calc(100vw - var(--__P__-inset-x) * 2));height:min(var(--__P__-widget-h, var(--__P__-panel-h)),calc(100dvh - var(--__P__-inset-y) * 2));padding:0;display:block;pointer-events:auto}:host([data-mode="drawer"][data-position$="-left"]) .__P__-anchor{right:auto;left:var(--__P__-inset-x)}:host([data-mode="drawer"][data-position^="bottom-"]) .__P__-anchor{top:auto;bottom:var(--__P__-inset-y)}:host([data-mode="drawer"]) .__P__-panel{width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border-radius:var(--__P__-radius, 12px);border:1px solid var(--__P__-border);box-shadow:-8px 16px 32px -12px #00000038;animation:__P__-drawer-in var(--__P__-dur-base) var(--__P__-ease)}:host([data-mode="drawer"][data-position$="-left"]) .__P__-panel{box-shadow:8px 16px 32px -12px #00000038;animation:__P__-drawer-in-left var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab[data-edge-tab]{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-2);position:fixed;top:50%;height:140px;width:auto;min-width:0;padding:10px 8px;writing-mode:vertical-rl;text-orientation:mixed;transform:translateY(-50%);transform-origin:center;animation:__P__-edge-tab-in var(--__P__-dur-base) var(--__P__-ease) both}.__P__-fab[data-edge-tab] svg{writing-mode:horizontal-tb}.__P__-fab[data-edge-tab]:hover{transform:translateY(-50%) scale(1.03)}.__P__-fab[data-edge-tab]:active{transform:translateY(-50%) scale(.97)}:host([data-position$="-right"]) .__P__-fab[data-edge-tab]{right:0;left:auto;border-radius:12px 0 0 12px;box-shadow:-6px 0 18px -8px #0000004d}:host([data-position$="-left"]) .__P__-fab[data-edge-tab]{left:0;right:auto;border-radius:0 12px 12px 0;box-shadow:6px 0 18px -8px #0000004d}.__P__-fab[data-edge-tab][data-leaving]{position:fixed;top:50%;bottom:auto;animation:__P__-edge-tab-out var(--__P__-dur-quick) var(--__P__-ease) forwards}@keyframes __P__-edge-tab-in{0%{opacity:0;transform:translateY(-50%) scale(.9)}to{opacity:1;transform:translateY(-50%) scale(1)}}@keyframes __P__-edge-tab-out{0%{opacity:1;transform:translateY(-50%) scale(1)}to{opacity:0;transform:translateY(-50%) scale(.85)}}@keyframes __P__-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes __P__-drawer-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@media(prefers-reduced-motion:reduce){:host([data-mode="drawer"]) .__P__-panel,.__P__-fab[data-edge-tab]{animation:none}}.__P__-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);background:var(--__P__-bg)}.__P__-header h1{font-size:14px;font-weight:600;flex:1;letter-spacing:-.01em}.__P__-header-actions{margin-left:auto;display:flex;align-items:center;gap:var(--__P__-space-1);flex-shrink:0}.__P__-agent{flex:1;display:inline-flex;align-items:center;gap:10px;min-width:0}.__P__-agent-avatar{position:relative;width:32px;height:32px;border-radius:999px;background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--__P__-text-xs);overflow:hidden;flex-shrink:0}.__P__-agent-avatar img{width:100%;height:100%;object-fit:cover}.__P__-agent-avatar:after{content:"";position:absolute;right:-1px;bottom:-1px;width:10px;height:10px;border-radius:999px;border:2px solid var(--__P__-bg);background:var(--__P__-neutral)}.__P__-agent-avatar[data-status=online]:after{background:var(--__P__-success)}.__P__-agent-avatar[data-status=away]:after{background:var(--__P__-warning)}.__P__-agent-avatar[data-status=offline]:after{background:var(--__P__-neutral)}.__P__-agent-meta{display:flex;flex-direction:column;line-height:1.15;min-width:0}.__P__-agent-meta strong{font-size:14px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-agent-meta span{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-suggestions{display:flex;flex-wrap:nowrap;gap:var(--__P__-space-2);padding:6px 14px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;-ms-overflow-style:none;min-width:0}.__P__-suggestions::-webkit-scrollbar{display:none}.__P__-suggestions:before,.__P__-suggestions:after{content:"";flex:1 1 0;min-width:0}.__P__-suggestion{flex:0 0 auto;scroll-snap-align:center;padding:7px 14px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg);font-size:var(--__P__-text-sm);font-weight:500;white-space:nowrap;transition:background var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-suggestion:hover{border-color:var(--__P__-accent);color:var(--__P__-accent);transform:translateY(-1px)}.__P__-suggestion:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px;border-color:var(--__P__-accent)}.__P__-suggestion:active{transform:translateY(0)}.__P__-icon-btn{width:32px;height:32px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);transition:background var(--__P__-dur-quick) var(--__P__-ease),color var(--__P__-dur-quick) var(--__P__-ease)}.__P__-icon-btn:hover{background:var(--__P__-bg-elevated);color:var(--__P__-fg)}.__P__-icon-btn:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-icon-btn:active{background:var(--__P__-border)}.__P__-icon-btn:disabled{opacity:.45;cursor:not-allowed}.__P__-icon-btn:before{content:"";position:absolute;inset:-6px}.__P__-icon-btn{position:relative}.__P__-icon-btn svg{width:18px;height:18px}.__P__-icon-btn[data-recording=true]{color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);animation:__P__-pulse 1.2s var(--__P__-ease) infinite}@keyframes __P__-pulse{0%,to{box-shadow:0 0 color-mix(in srgb,var(--__P__-accent) 40%,transparent)}50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--__P__-accent) 0%,transparent)}}.__P__-list-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}.__P__-jump{position:absolute;right:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:999px;border:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);color:var(--__P__-fg);box-shadow:var(--__P__-shadow-panel);cursor:pointer;opacity:.85;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease);animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-jump:hover{opacity:1}.__P__-jump:active{transform:translateY(1px)}.__P__-jump svg{width:18px;height:18px}.__P__-list{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-4);padding-bottom:var(--__P__-space-8);display:flex;flex-direction:column;gap:14px;scrollbar-width:thin;scrollbar-color:var(--__P__-border-strong) transparent;scrollbar-gutter:stable}.__P__-list::-webkit-scrollbar{width:8px}.__P__-list::-webkit-scrollbar-thumb{background:var(--__P__-border-strong);border-radius:8px}.__P__-date-divider{position:sticky;top:var(--__P__-space-2);z-index:2;display:flex;justify-content:center;margin:var(--__P__-space-1) 0;pointer-events:none}.__P__-date-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--__P__-fg-muted);background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);box-shadow:var(--__P__-shadow-card);opacity:0;pointer-events:none;transition:opacity var(--__P__-dur-base) var(--__P__-ease)}.__P__-list[data-scrolling=true] .__P__-date-pill{opacity:1;pointer-events:auto}@media(prefers-reduced-motion:reduce){.__P__-date-pill{transition:none}}.__P__-bubble-row{display:flex}.__P__-bubble-row[data-role=user]{justify-content:flex-end}.__P__-bubble-row[data-role=assistant]{justify-content:flex-start}.__P__-bubble{max-width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);line-height:1.6;font-size:14px;word-wrap:break-word;overflow-wrap:anywhere;box-shadow:0 1px 2px #0000000a,0 1px 8px -4px #0000000f;animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-bubble ::selection{background:color-mix(in srgb,var(--__P__-accent) 30%,transparent)}.__P__-bubble-row[data-role=user] .__P__-bubble ::selection{background:#fff6;color:var(--__P__-bubble-user-text)}@keyframes __P__-bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.__P__-bubble-row[data-role=user] .__P__-bubble{background:var(--__P__-bubble-user);color:var(--__P__-bubble-user-text);border-bottom-right-radius:5px}.__P__-bubble-row[data-role=assistant] .__P__-bubble{background:var(--__P__-bubble-assistant);color:var(--__P__-bubble-assistant-text);border-bottom-left-radius:5px}.__P__-bubble-col{display:flex;flex-direction:column;max-width:85%;min-width:0}.__P__-bubble-row[data-role=user] .__P__-bubble-col{align-items:flex-end}.__P__-bubble-row[data-role=assistant] .__P__-bubble-col{align-items:flex-start}.__P__-bubble-time{margin-top:3px;padding:0 4px;font-size:11px;line-height:1;color:var(--__P__-fg-muted);user-select:none}.__P__-md>*:first-child{margin-top:0}.__P__-md>*:last-child{margin-bottom:0}.__P__-md p{margin:10px 0}.__P__-md h1,.__P__-md h2,.__P__-md h3,.__P__-md h4,.__P__-md h5,.__P__-md h6{margin:18px 0 8px;line-height:1.3;letter-spacing:-.01em;font-weight:700}.__P__-md h1{font-size:1.4em}.__P__-md h2{font-size:1.22em}.__P__-md h3{font-size:1.08em}.__P__-md h4,.__P__-md h5,.__P__-md h6{font-size:1em}.__P__-md>h1:first-child,.__P__-md>h2:first-child,.__P__-md>h3:first-child,.__P__-md>h4:first-child,.__P__-md>h5:first-child,.__P__-md>h6:first-child{margin-top:0}.__P__-md ul,.__P__-md ol{padding-left:1.5em;margin:10px 0}.__P__-md ul{list-style:disc}.__P__-md ol{list-style:decimal}.__P__-md li{margin:6px 0;padding-left:2px}.__P__-md li::marker{color:var(--__P__-fg-muted)}.__P__-md li>p{margin:6px 0}.__P__-md li>ul,.__P__-md li>ol{margin:6px 0}.__P__-md strong,.__P__-md b{font-weight:650;letter-spacing:-.005em}.__P__-md em,.__P__-md i{font-style:italic}.__P__-md code{font-family:var(--__P__-font-mono);font-size:.86em;padding:1px 6px;border-radius:5px;background:color-mix(in srgb,var(--__P__-accent) 10%,transparent);color:var(--__P__-fg);border:1px solid color-mix(in srgb,var(--__P__-accent) 16%,transparent)}.__P__-md pre{font-family:var(--__P__-font-mono);font-size:12.5px;padding:12px 14px;border-radius:var(--__P__-radius-sm);background:#7f7f7f1f;overflow-x:auto;margin:var(--__P__-space-3) 0;line-height:1.5}.__P__-md pre code{padding:0;background:none}.__P__-md a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}.__P__-md a:hover{text-decoration-thickness:2px}.__P__-md blockquote{margin:14px 0;padding:6px 14px;border-left:3px solid color-mix(in srgb,var(--__P__-accent) 50%,transparent);background:color-mix(in srgb,var(--__P__-accent) 5%,transparent);border-radius:0 var(--__P__-radius-sm) var(--__P__-radius-sm) 0;color:var(--__P__-fg-muted)}.__P__-md blockquote>:first-child{margin-top:0}.__P__-md blockquote>:last-child{margin-bottom:0}.__P__-md hr{border:0;height:1px;background:color-mix(in srgb,currentColor 18%,transparent);margin:var(--__P__-space-4) 0}.__P__-md table{border-collapse:collapse;margin:var(--__P__-space-3) 0;font-size:.95em;display:block;overflow-x:auto;max-width:100%;font-variant-numeric:tabular-nums}.__P__-md th,.__P__-md td{padding:6px 10px;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);text-align:left}.__P__-md th{font-weight:700;background:color-mix(in srgb,currentColor 6%,transparent)}.__P__-md h1+ul,.__P__-md h1+ol,.__P__-md h2+ul,.__P__-md h2+ol,.__P__-md h3+ul,.__P__-md h3+ol,.__P__-md h4+ul,.__P__-md h4+ol{margin-top:var(--__P__-space-1)}.__P__-loading{display:inline-flex;align-items:center;gap:var(--__P__-space-2);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-loading-spinner{width:14px;height:14px;border-radius:999px;border:2px solid currentColor;border-top-color:transparent;animation:__P__-spin .8s linear infinite}@keyframes __P__-spin{to{transform:rotate(1turn)}}.__P__-typing{display:inline-flex;gap:var(--__P__-space-1);padding:var(--__P__-space-1) 0}.__P__-typing span{width:5px;height:5px;border-radius:999px;background:currentColor;opacity:.4;animation:__P__-blink 1.2s var(--__P__-ease) infinite}.__P__-typing span:nth-child(2){animation-delay:.2s}.__P__-typing span:nth-child(3){animation-delay:.4s}@keyframes __P__-blink{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.__P__-reasoning{margin:var(--__P__-space-1) 0 var(--__P__-space-2);padding-left:var(--__P__-space-3);border-left:2px solid var(--__P__-border-strong)}.__P__-reasoning-summary{display:inline-flex;align-items:center;gap:var(--__P__-space-1);cursor:pointer;list-style:none;user-select:none;color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-reasoning-summary::-webkit-details-marker{display:none}.__P__-reasoning-summary:before{content:"";width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);opacity:.7;transition:transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-reasoning[open] .__P__-reasoning-summary:before{transform:rotate(45deg)}.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:__P__-reasoning-pulse 1.4s var(--__P__-ease) infinite}@keyframes __P__-reasoning-pulse{0%,to{opacity:.5}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:none}}.__P__-reasoning-body{margin-top:var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-reasoning-body>:first-child{margin-top:0}.__P__-reasoning-body>:last-child{margin-bottom:0}.__P__-tool-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2);margin-top:6px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs)}.__P__-composer{border-top:1px solid var(--__P__-border);padding:10px 12px;background:var(--__P__-bg);display:flex;flex-direction:column;gap:var(--__P__-space-2)}.__P__-composer-row{display:flex;align-items:flex-end;gap:6px}.__P__-textarea{flex:1;height:40px;max-height:160px;padding:10px 12px;border-radius:var(--__P__-radius);background:var(--__P__-bg-elevated);border:1px solid transparent;font-size:14px;line-height:1.4;transition:height var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),box-shadow var(--__P__-dur-quick) var(--__P__-ease)}.__P__-textarea:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:1px;border-color:var(--__P__-focus)}@media(pointer:coarse){.__P__-textarea,.__P__-home-search-input{font-size:16px}.__P__-textarea{height:44px}}.__P__-send{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease),background var(--__P__-dur-quick) var(--__P__-ease)}.__P__-send[data-shape=circle]{border-radius:999px}.__P__-send[data-shape=square]{border-radius:var(--__P__-radius-sm)}.__P__-send[data-shape=pill]{width:auto;padding:0 18px;border-radius:999px}.__P__-send[data-variant=filled]{background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-send[data-variant=outline]{background:transparent;color:var(--__P__-accent);border-color:var(--__P__-accent)}.__P__-send[data-variant=outline]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 10%,transparent)}.__P__-send[data-variant=ghost]{background:transparent;color:var(--__P__-accent)}.__P__-send[data-variant=ghost]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 8%,transparent)}.__P__-send:disabled{opacity:.4;cursor:not-allowed}.__P__-send:not(:disabled):hover{transform:translateY(-1px)}.__P__-send:not(:disabled):active{transform:translateY(0)}.__P__-send:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-send svg{width:18px;height:18px}.__P__-composer-actions{display:flex;gap:var(--__P__-space-1);flex-wrap:wrap}.__P__-attachments{display:flex;flex-wrap:wrap;gap:6px}.__P__-attachment-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-1);border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);font-size:var(--__P__-text-xs);max-width:200px}.__P__-attachment-thumb{width:24px;height:24px;border-radius:999px;object-fit:cover;background:var(--__P__-border)}.__P__-attachment-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-attachment-remove{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted)}.__P__-attachment-remove:hover{background:var(--__P__-border);color:var(--__P__-fg)}.__P__-dropzone{position:absolute;inset:8px;border:2px dashed var(--__P__-accent);border-radius:var(--__P__-radius);background:color-mix(in srgb,var(--__P__-accent) 8%,transparent);display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--__P__-accent);pointer-events:none;z-index:10;animation:__P__-fade-in var(--__P__-dur-quick) var(--__P__-ease)}@keyframes __P__-fade-in{0%{opacity:0}to{opacity:1}}.__P__-error{margin-top:var(--__P__-space-1);padding:8px 10px;border-radius:var(--__P__-radius-sm);background:var(--__P__-danger-bg);color:var(--__P__-danger-text);font-size:var(--__P__-text-sm);display:flex;align-items:center;gap:var(--__P__-space-2)}.__P__-error button{color:inherit;text-decoration:underline;font-size:var(--__P__-text-sm)}.__P__-history{flex:1;overflow-y:auto;padding:var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-3)}.__P__-history-footer{flex:none;padding:var(--__P__-space-2) var(--__P__-space-3) var(--__P__-space-3);border-top:1px solid var(--__P__-border);background:var(--__P__-surface)}.__P__-history-new{width:100%;display:flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);padding:var(--__P__-space-2) var(--__P__-space-3);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-on-accent);cursor:pointer;font-size:var(--__P__-text-sm);font-weight:600;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-history-new svg{width:16px;height:16px}.__P__-history-new:hover{filter:brightness(1.08)}.__P__-history-new:active{transform:translateY(1px)}.__P__-history-new:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-history-empty{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 16px;color:var(--__P__-fg-muted);font-size:14px;text-align:center}.__P__-history-group{display:flex;flex-direction:column;padding:0 var(--__P__-space-2)}.__P__-history-heading{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-fg-muted);padding:12px 8px 6px;text-transform:uppercase;letter-spacing:.04em}.__P__-history-item{all:unset;display:flex;flex-direction:column;gap:3px;padding:10px 12px;border-radius:var(--__P__-radius-md);cursor:pointer;transition:background var(--__P__-dur-base) var(--__P__-ease)}.__P__-history-item:hover{background:var(--__P__-bg-elevated)}.__P__-history-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-history-title{font-size:14px;font-weight:500;color:var(--__P__-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-preview{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-item[data-closed=true] .__P__-history-title:after{content:"\\2022";margin-left:var(--__P__-space-2);opacity:.5}.__P__-list-loading{margin:auto;padding:var(--__P__-space-6) var(--__P__-space-4);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);text-align:center}.__P__-readonly-banner{display:flex;flex-direction:column;align-items:center;gap:10px;padding:14px 12px;margin:0 var(--__P__-space-3) var(--__P__-space-3);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);text-align:center;font-size:var(--__P__-text-sm)}.__P__-readonly-label{line-height:1.4}.__P__-readonly-cta{appearance:none;border:0;cursor:pointer;padding:var(--__P__-space-2) var(--__P__-space-4);border-radius:999px;background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-readonly-cta:hover,.__P__-readonly-cta:focus-visible{filter:brightness(1.1)}.__P__-readonly-cta:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}.__P__-composer-footer{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:10px 16px;margin:0 var(--__P__-space-3);border-top:1px solid var(--__P__-border);text-align:center;font-size:11px;line-height:1.4;color:var(--__P__-fg-muted)}.__P__-disclaimer{max-width:320px;margin:0 auto;opacity:.9;letter-spacing:.01em}.__P__-poweredby{display:inline-flex;align-items:center;justify-content:center;gap:6px;color:inherit;text-decoration:none;opacity:.7;transition:opacity var(--__P__-dur-base) var(--__P__-ease);font-size:11px;letter-spacing:.02em}.__P__-poweredby:hover{opacity:1}.__P__-poweredby-logo{height:12px;width:auto;display:inline-block;vertical-align:middle}.__P__-poweredby-bar{flex:none;display:flex;align-items:center;justify-content:center;padding:6px 16px;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated)}.__P__-menu-wrap{position:relative;display:inline-flex}.__P__-menu{position:absolute;top:100%;right:0;margin-top:6px;min-width:200px;padding:6px;background:var(--__P__-bg);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);box-shadow:var(--__P__-shadow-panel);z-index:10;display:flex;flex-direction:column;gap:2px;animation:__P__-menu-in var(--__P__-dur-base) var(--__P__-ease)}@media(prefers-reduced-motion:reduce){.__P__-menu{animation:none}}@keyframes __P__-menu-in{0%{opacity:0;transform:translateY(-4px) scale(.98);transform-origin:top right}to{opacity:1;transform:none}}.__P__-menu-item{all:unset;display:flex;align-items:center;gap:10px;padding:8px 10px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);border-radius:var(--__P__-radius-sm);cursor:pointer;user-select:none}.__P__-menu-item:hover{background:var(--__P__-bg-elevated)}.__P__-menu-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-menu-item[disabled]{opacity:.45;cursor:not-allowed}.__P__-menu-icon{display:inline-flex;width:16px;height:16px;color:var(--__P__-fg-muted)}.__P__-menu-icon svg{width:16px;height:16px}.__P__-menu-label{flex:1}.__P__-menu-check{display:inline-flex;color:var(--__P__-accent)}.__P__-menu-check svg{width:14px;height:14px}.__P__-resize-grip{position:absolute;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);opacity:.45;transition:opacity var(--__P__-dur-base) var(--__P__-ease);z-index:2;touch-action:none;user-select:none}.__P__-resize-grip:hover,.__P__-resize-grip:focus-visible{opacity:1}.__P__-resize-grip svg{width:10px;height:10px}.__P__-resize-grip--bottom-left{bottom:2px;left:2px;cursor:nesw-resize;transform:scaleX(-1)}.__P__-resize-grip--bottom-right{bottom:2px;right:2px;cursor:nwse-resize}.__P__-resize-grip--top-left{top:2px;left:2px;cursor:nwse-resize;transform:rotate(180deg)}.__P__-resize-grip--top-right{top:2px;right:2px;cursor:nesw-resize;transform:scaleY(-1)}:host(:not([data-mode="open"])) .__P__-resize-grip{display:none}.__P__-messenger{display:flex;flex-direction:column;overflow:hidden}.__P__-messenger-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}.__P__-module{display:flex;flex-direction:column;height:100%;min-height:0}.__P__-module-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-3);display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-home{background:radial-gradient(125% 65% at 88% 0%,color-mix(in srgb,#fff 16%,transparent),transparent 55%),linear-gradient(180deg,var(--__P__-accent) 0%,var(--__P__-accent) 22%,color-mix(in srgb,var(--__P__-accent) 28%,var(--__P__-surface)) 44%,var(--__P__-surface) 70%);border-radius:var(--__P__-radius-lg) var(--__P__-radius-lg) 0 0}.__P__-home-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;background:transparent}.__P__-home-cards{display:flex;flex-direction:column;gap:var(--__P__-space-3);padding:4px 14px 16px}.__P__-module-pad{padding:var(--__P__-space-3) var(--__P__-space-3) 0}.__P__-module-empty{display:flex;flex-direction:column;align-items:center;gap:var(--__P__-space-3);padding:var(--__P__-space-8) var(--__P__-space-4);text-align:center;color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-module-retry{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border-strong);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);font-weight:600;cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-module-retry:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}.__P__-module-retry:active{background:var(--__P__-border)}.__P__-module-retry:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-help-list{flex:1;min-height:0;overflow-y:auto;padding-bottom:var(--__P__-space-3)}.__P__-help-group{display:flex;flex-direction:column}.__P__-help-section-title{position:sticky;top:0;z-index:1;margin:0;padding:var(--__P__-space-3) var(--__P__-space-5) var(--__P__-space-2);font-size:var(--__P__-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--__P__-fg-muted);background:var(--__P__-bg)}.__P__-help-card{margin:0 var(--__P__-space-3) var(--__P__-space-3);background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden}.__P__-help-card .__P__-list-row{border-bottom:0;border-radius:0}.__P__-help-card .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-help-card .__P__-list-row:hover{background:var(--__P__-hover)}.__P__-module-cta{padding:var(--__P__-space-3);border-top:1px solid var(--__P__-border)}.__P__-tabbar{display:flex;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);flex-shrink:0}.__P__-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-1);min-height:48px;padding:var(--__P__-space-2) var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600;transition:color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-tab:hover{color:var(--__P__-fg)}.__P__-tab[aria-selected=true]{color:var(--__P__-accent)}.__P__-tab:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-tab:active{background:var(--__P__-hover)}.__P__-tab-icon{position:relative;display:inline-flex}.__P__-tab-icon svg{width:22px;height:22px}.__P__-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--__P__-accent);color:var(--__P__-on-accent);font-size:10px;font-weight:600;line-height:1}.__P__-home-hero{flex-shrink:0;padding:var(--__P__-space-5) var(--__P__-space-5) var(--__P__-space-3);color:var(--__P__-on-accent);--__P__-focus: var(--__P__-on-accent)}.__P__-home-hero-top{display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-3);min-height:32px}.__P__-home-brand{font-size:14px;font-weight:600;letter-spacing:.01em;color:color-mix(in srgb,#fff 82%,transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.__P__-home-brand-spacer{flex:1}.__P__-home-hero-actions{display:flex;align-items:center;gap:var(--__P__-space-2);flex-shrink:0}.__P__-home-hero-actions .__P__-icon-btn{color:#fff}.__P__-home-greeting{margin:28px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;overflow-wrap:anywhere}.__P__-home-lead{margin:2px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;color:color-mix(in srgb,var(--__P__-on-accent) 88%,transparent);overflow-wrap:anywhere}.__P__-home-avatars{display:flex}.__P__-home-avatar{width:30px;height:30px;border-radius:999px;overflow:hidden;margin-left:-10px;border:2px solid color-mix(in srgb,#fff 92%,transparent);box-shadow:0 1px 3px #0000002e;background:var(--__P__-surface);display:inline-flex;align-items:center;justify-content:center;font-size:var(--__P__-text-xs);font-weight:700;color:var(--__P__-fg)}.__P__-home-avatar:first-child{margin-left:0}.__P__-home-avatar img{width:100%;height:100%;object-fit:cover}.__P__-home-content{background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-card);overflow:hidden}.__P__-home-content-title{padding:var(--__P__-space-4) var(--__P__-space-4) var(--__P__-space-3);font-size:var(--__P__-text-sm);font-weight:700}.__P__-home-content-list{display:flex;flex-direction:column;padding:0 var(--__P__-space-2) var(--__P__-space-2)}.__P__-home-content-list .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-home-card{display:block;width:100%;text-align:left;background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);padding:var(--__P__-space-4);box-shadow:var(--__P__-shadow-card)}.__P__-home-card[data-interactive=true]{cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-home-card[data-interactive=true]:hover{background:var(--__P__-bg-elevated)}.__P__-home-card[data-interactive=true]:active{transform:translateY(1px)}.__P__-home-card[data-interactive=true]:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-recent-row{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-recent-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;flex-shrink:0;border-radius:999px;background:color-mix(in oklch,var(--__P__-accent) 14%,transparent);color:var(--__P__-accent)}.__P__-home-recent-avatar svg{width:20px;height:20px}.__P__-home-recent-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.__P__-home-recent-title{font-weight:600;font-size:14px}.__P__-home-recent-preview{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-home-recent-at{color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);flex-shrink:0}.__P__-home-recent-dot{width:8px;height:8px;border-radius:999px;background:var(--__P__-accent);flex-shrink:0}.__P__-home-recent-row[data-unread=true] .__P__-home-recent-title{font-weight:700}.__P__-home-status{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-status-icon svg{width:22px;height:22px;color:var(--__P__-success)}.__P__-home-status[data-level=degraded] .__P__-home-status-icon svg{color:var(--__P__-warning)}.__P__-home-status[data-level=down] .__P__-home-status-icon svg{color:var(--__P__-danger)}.__P__-home-status-text{font-weight:600;font-size:14px}.__P__-home-search{display:flex;align-items:center;gap:var(--__P__-space-2);width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);border:1px solid var(--__P__-border);background:var(--__P__-surface);text-align:left}.__P__-home-search[data-input=true]{background:var(--__P__-bg-elevated)}.__P__-home-search:hover{border-color:var(--__P__-border-strong)}.__P__-home-search:focus-visible,.__P__-home-search:focus-within{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-search-text{flex:1;color:var(--__P__-fg-muted);font-size:14px}.__P__-home-search-input{flex:1;border:0;background:transparent;font-size:14px;color:var(--__P__-fg);outline:none}.__P__-home-search-icon svg{width:18px;height:18px;color:var(--__P__-accent)}.__P__-list-row{display:flex;align-items:center;gap:var(--__P__-space-3);width:100%;min-height:44px;text-align:left;padding:var(--__P__-space-3) var(--__P__-space-2);border-radius:var(--__P__-radius-sm)}.__P__-list-row:hover{background:var(--__P__-bg-elevated)}.__P__-list-row:active{background:var(--__P__-border)}.__P__-list-row:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-list-row-body{display:flex;flex-direction:column;min-width:0;flex:1}.__P__-list-row-title{font-weight:600;font-size:var(--__P__-text-md);line-height:1.35}.__P__-list-row-sub{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);margin-top:var(--__P__-space-1);line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-list-row-chevron svg{width:18px;height:18px;color:var(--__P__-accent);flex-shrink:0}.__P__-back-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);flex-shrink:0}.__P__-back-title{flex:1;text-align:center;font-size:var(--__P__-text-md);font-weight:700;margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-back-spacer{width:32px;height:1px}.__P__-content{display:flex;flex-direction:column;gap:14px;width:100%;max-width:68ch;margin:0 auto}.__P__-content-hero{width:100%;border-radius:var(--__P__-radius)}.__P__-content-subtitle{color:var(--__P__-fg-muted);margin:0}.__P__-content-frame{flex:1;min-height:0;width:100%;border:0;background:#fff}.__P__-news-list{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-news-card{display:block;width:100%;text-align:left;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden;background:var(--__P__-surface)}.__P__-news-card{transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-news-card:hover{background:var(--__P__-bg-elevated)}.__P__-news-card:active{transform:translateY(1px)}.__P__-news-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-news-hero{width:100%;display:block}.__P__-news-body{display:flex;flex-direction:column;gap:6px;padding:14px 16px}.__P__-news-tags{display:flex;gap:6px;flex-wrap:wrap}.__P__-news-tag{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);padding:2px 8px;border-radius:999px}.__P__-news-title{font-weight:700;font-size:var(--__P__-text-md)}.__P__-news-summary{color:var(--__P__-fg-muted);font-size:14px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-modules-empty{display:flex;align-items:center;justify-content:center;position:relative}.__P__-modules-empty-close{position:absolute;top:12px;right:12px}.__P__-modules-empty-text{color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-form{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-field{display:flex;flex-direction:column;gap:4px}.__P__-field-label{font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-field-req{color:var(--__P__-danger)}.__P__-field-input{width:100%;box-sizing:border-box;padding:var(--__P__-space-2) var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg);color:var(--__P__-fg);font:inherit;font-size:var(--__P__-text-sm);resize:vertical;transition:border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-field-input:focus-visible{outline:none;border-color:var(--__P__-accent)}.__P__-field[data-invalid=true] .__P__-field-input{border-color:var(--__P__-danger)}.__P__-field-hint{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-field-error{font-size:var(--__P__-text-xs);color:var(--__P__-danger)}.__P__-field-choices{display:flex;flex-direction:column;gap:6px}.__P__-choice{display:flex;align-items:flex-start;gap:8px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);cursor:pointer}.__P__-choice input{margin-top:2px;accent-color:var(--__P__-accent)}.__P__-form-actions{display:flex;justify-content:flex-end;gap:var(--__P__-space-2);margin-top:2px}.__P__-form-submit,.__P__-tool-approve{padding:var(--__P__-space-2) var(--__P__-space-4);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);cursor:pointer;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-submit:hover:not(:disabled),.__P__-tool-approve:hover:not(:disabled){filter:brightness(1.06)}.__P__-form-submit:disabled{opacity:.6;cursor:default}.__P__-form-skip,.__P__-tool-reject{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:transparent;color:var(--__P__-fg-muted);font:inherit;font-size:var(--__P__-text-sm);cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-skip:hover:not(:disabled),.__P__-tool-reject:hover:not(:disabled){background:var(--__P__-bg-elevated)}.__P__-form-gate{display:flex;flex-direction:column;gap:var(--__P__-space-2);padding:var(--__P__-space-3) var(--__P__-space-4) var(--__P__-space-4);border-top:1px solid var(--__P__-border);max-height:60%;overflow-y:auto}.__P__-form-gate-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-form-gate-desc{margin:0 0 var(--__P__-space-1);font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-ask-input,.__P__-tool-approval{display:flex;flex-direction:column;gap:var(--__P__-space-2);margin-top:6px;padding:var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated)}.__P__-tool-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-badge{padding:2px 8px;border-radius:999px;background:var(--__P__-warning, #f59e0b);color:#1a1206;font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-title{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}.__P__-tool-question{margin:0;font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-tool-desc{margin:0;font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-args{margin:0;padding:var(--__P__-space-2);max-height:160px;overflow:auto;border-radius:var(--__P__-radius-sm);background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);white-space:pre-wrap;word-break:break-word}.__P__-tool-stale-note{margin:0;font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-tool-decided{flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-decided-label{padding:2px 8px;border-radius:999px;background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-decided-label[data-approved=true]{color:var(--__P__-success, #16a34a);border-color:var(--__P__-success, #16a34a)}.__P__-tool-decided-label[data-approved=false]{color:var(--__P__-danger);border-color:var(--__P__-danger)}.__P__-tool-decided-value{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}\n';
|
|
973
|
+
var panel_default = '.__P__-anchor{right:16px;bottom:16px}:host([data-position="bottom-left"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{right:auto;left:16px}:host([data-position="top-right"]) .__P__-anchor,:host([data-position="top-left"]) .__P__-anchor{bottom:auto;top:16px}.__P__-anchor{position:fixed;display:flex;flex-direction:column;align-items:flex-end;gap:var(--__P__-space-3);pointer-events:none}.__P__-anchor{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=sm]{--__P__-fab-size: 44px}.__P__-anchor[data-launcher-size=md]{--__P__-fab-size: 56px}.__P__-anchor[data-launcher-size=lg]{--__P__-fab-size: 68px}.__P__-anchor>*{pointer-events:auto}.__P__-fab[data-size=sm]{--__P__-fab-size: 44px;font-size:var(--__P__-text-sm)}.__P__-fab[data-size=md]{--__P__-fab-size: 56px;font-size:14px}.__P__-fab[data-size=lg]{--__P__-fab-size: 68px;font-size:var(--__P__-text-base)}.__P__-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);color:var(--__P__-accent-text);background:var(--__P__-accent);box-shadow:var(--__P__-shadow-fab);font-weight:600;line-height:1;transform-origin:bottom right;animation:__P__-fab-in var(--__P__-dur-base) var(--__P__-ease) both;transition:transform var(--__P__-dur-base) var(--__P__-ease),opacity var(--__P__-dur-base) var(--__P__-ease),box-shadow var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab:hover{transform:translateY(-2px)}.__P__-fab:active{transform:translateY(0)}.__P__-fab:focus-visible{outline:2px solid var(--__P__-on-accent);outline-offset:3px}.__P__-fab svg{width:24px;height:24px;flex-shrink:0}@keyframes __P__-fab-in{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}.__P__-fab[data-leaving]{position:absolute;right:0;bottom:0;animation:__P__-fab-out var(--__P__-dur-quick) var(--__P__-ease) forwards;pointer-events:none}:host([data-position^="top-"]) .__P__-fab[data-leaving]{bottom:auto;top:0}:host([data-position$="-left"]) .__P__-fab[data-leaving]{right:auto;left:0}@keyframes __P__-fab-out{0%{opacity:1;transform:none}to{opacity:0;transform:scale(.85)}}.__P__-fab[data-variant=circle]{width:var(--__P__-fab-size);height:var(--__P__-fab-size);border-radius:999px}.__P__-fab[data-variant=circle] .__P__-fab-label{display:none}.__P__-fab[data-variant=pill]{height:var(--__P__-fab-size);padding:0 18px 0 16px;border-radius:999px}.__P__-fab[data-variant=bar]{height:var(--__P__-fab-size);padding:0 22px;border-radius:var(--__P__-radius)}.__P__-fab[data-variant=minimal]{height:var(--__P__-fab-size);padding:0 var(--__P__-space-4);border-radius:999px;background:transparent;color:var(--__P__-accent);box-shadow:none;border:1px solid currentColor}.__P__-fab[data-variant=minimal]:hover{background:color-mix(in srgb,var(--__P__-accent) 12%,transparent)}.__P__-callout{--__P__-callout-fab-h: var(--__P__-fab-size, 56px);--__P__-callout-gap: clamp(12px, calc(var(--__P__-callout-fab-h) * .25), 22px);--__P__-callout-nudge-direction: -1;position:absolute;display:inline-flex;align-items:center;gap:var(--__P__-space-2);padding:10px 14px;background:var(--__P__-fg);color:var(--__P__-bg);border-radius:999px;font-size:var(--__P__-text-sm);font-weight:600;line-height:1.2;box-shadow:0 10px 30px -8px #00000059;pointer-events:auto;animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease);z-index:1;max-width:240px;white-space:nowrap}.__P__-callout[data-position=left]{right:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%)}.__P__-callout[data-position=right]{left:calc(100% + var(--__P__-callout-gap));bottom:calc(var(--__P__-callout-fab-h) / 2);transform:translateY(50%);--__P__-callout-nudge-direction: 1}.__P__-callout[data-position=top]{bottom:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-position=bottom]{top:calc(100% + var(--__P__-callout-gap));right:0;max-width:min(280px,calc(100vw - 32px))}:host([data-position$="-left"]) .__P__-callout[data-position=top],:host([data-position$="-left"]) .__P__-callout[data-position=bottom]{right:auto;left:0}.__P__-callout[data-shape=bubble]{border-radius:var(--__P__-radius-md);white-space:normal;width:max-content;max-width:min(280px,calc(100vw - 32px))}.__P__-callout[data-shape=callout]{padding:12px 18px;font-size:14px;background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-callout:after{content:"";position:absolute;width:12px;height:12px;background:inherit;border-radius:2px;transform:rotate(45deg)}.__P__-callout[data-position=left]:after{right:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=right]:after{left:-5px;top:50%;margin-top:-6px}.__P__-callout[data-position=top]:after{bottom:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-position=bottom]:after{top:-5px;right:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}:host([data-position$="-left"]) .__P__-callout[data-position=top]:after,:host([data-position$="-left"]) .__P__-callout[data-position=bottom]:after{right:auto;left:calc(var(--__P__-fab-size, 56px) / 2 - 6px)}.__P__-callout[data-animated]{animation:__P__-callout-in var(--__P__-dur-slow) var(--__P__-ease),__P__-callout-nudge 1.6s var(--__P__-ease-in-out) var(--__P__-dur-slow) infinite}@keyframes __P__-callout-in{0%{opacity:0}to{opacity:1}}@keyframes __P__-callout-nudge{0%,to{margin-left:0;margin-right:0}50%{margin-left:calc(6px * var(--__P__-callout-nudge-direction));margin-right:calc(-6px * var(--__P__-callout-nudge-direction))}}@media(prefers-reduced-motion:reduce){.__P__-callout[data-animated]{animation:__P__-callout-in 1ms var(--__P__-ease)}.__P__-icon-btn[data-recording=true],.__P__-typing span{animation:none}}.__P__-callout-close{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:inherit;opacity:.7;cursor:pointer}.__P__-callout-close:hover{opacity:1;background:#ffffff26}.__P__-callout-close svg{width:12px;height:12px}.__P__-panel{width:var(--__P__-panel-w);height:var(--__P__-panel-h);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);background:var(--__P__-bg);color:var(--__P__-fg);border-radius:var(--__P__-radius-lg);box-shadow:var(--__P__-shadow-panel);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;animation:__P__-panel-in var(--__P__-dur-slow) var(--__P__-ease);border:1px solid var(--__P__-border)}:host([data-mode="open"]) .__P__-panel{width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));min-width:var(--__P__-resize-min-w, auto);min-height:var(--__P__-resize-min-h, auto);max-width:var(--__P__-resize-max-w, calc(100vw - 32px) );max-height:var(--__P__-resize-max-h, calc(100dvh - 32px) )}@keyframes __P__-panel-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}:host([data-mode="expanded"]) .__P__-panel{width:var(--__P__-expanded-w, 640px);height:var(--__P__-expanded-h, 820px);max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px)}:host([data-mode="fullscreen"]){z-index:var(--__P__-z-panel)!important}:host([data-mode="fullscreen"]) .__P__-anchor{inset:0;align-items:stretch;padding:0}:host([data-mode="fullscreen"]) .__P__-panel{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}:host([data-mode="fullscreen"]) .__P__-fab{display:none}:host([data-mode="inline"]) .__P__-anchor,:host([data-mode="standalone"]) .__P__-anchor{position:static;inset:auto;padding:0;align-items:stretch;width:100%;height:100%;min-height:0}:host([data-mode="inline"]) .__P__-panel,:host([data-mode="standalone"]) .__P__-panel{width:100%;height:100%;min-width:0;min-height:0;max-width:none;max-height:none;animation:none}:host([data-mode="inline"]) .__P__-fab,:host([data-mode="standalone"]) .__P__-fab{display:none}:host([data-mode="inline"]){min-height:320px}:host([data-mode="inline"]) .__P__-panel{border-radius:var(--__P__-radius)}:host([data-mode="standalone"]) .__P__-panel{border-radius:0;border:0;box-shadow:none}:host([data-mode="modal"]){position:fixed!important;inset:0!important;z-index:var(--__P__-z-panel)!important;display:block!important;width:100vw;height:100dvh;background:var(--__P__-modal-backdrop, var(--__P__-backdrop));animation:__P__-backdrop-in var(--__P__-dur-base) var(--__P__-ease) both;--__P__-panel-w: min(960px, 92vw);--__P__-panel-h: min(720px, 88dvh)}:host([data-mode="modal"]) .__P__-anchor{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:var(--__P__-space-6);pointer-events:none}:host([data-mode="modal"]) .__P__-panel{pointer-events:auto;width:var(--__P__-widget-w, var(--__P__-panel-w));height:var(--__P__-widget-h, var(--__P__-panel-h));max-width:calc(100vw - 48px);max-height:calc(100dvh - 48px);min-width:0;min-height:0;border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-panel);animation:__P__-modal-in var(--__P__-dur-base) var(--__P__-ease);translate:var(--__P__-modal-dx, 0px) var(--__P__-modal-dy, 0px)}:host([data-mode="modal"]) .__P__-header,:host([data-mode="modal"]) .__P__-back-header,:host([data-mode="modal"]) .__P__-home-hero{cursor:grab;touch-action:none}:host([data-mode="modal"]) .__P__-panel[data-dragging]{cursor:grabbing;user-select:none}:host([data-mode="modal"]) .__P__-panel[data-dragging] *{cursor:grabbing}:host([data-mode="modal"]) .__P__-fab{display:none}@keyframes __P__-backdrop-in{0%{background:#0000}to{background:var(--__P__-modal-backdrop, var(--__P__-backdrop))}}@keyframes __P__-modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}:host([data-mode="drawer"]){--__P__-panel-w: min(440px, calc(100vw - 32px) );--__P__-panel-h: 100dvh}:host([data-mode="drawer"]) .__P__-anchor{position:fixed;--__P__-inset-x: var(--__P__-panel-inset, 12px);--__P__-inset-y: var(--__P__-panel-inset, 3dvh);top:var(--__P__-inset-y);bottom:auto;right:var(--__P__-inset-x);left:auto;width:min(var(--__P__-widget-w, var(--__P__-panel-w)),calc(100vw - var(--__P__-inset-x) * 2));height:min(var(--__P__-widget-h, var(--__P__-panel-h)),calc(100dvh - var(--__P__-inset-y) * 2));padding:0;display:block;pointer-events:auto}:host([data-mode="drawer"][data-position$="-left"]) .__P__-anchor{right:auto;left:var(--__P__-inset-x)}:host([data-mode="drawer"][data-position^="bottom-"]) .__P__-anchor{top:auto;bottom:var(--__P__-inset-y)}:host([data-mode="drawer"]) .__P__-panel{width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border-radius:var(--__P__-radius, 12px);border:1px solid var(--__P__-border);box-shadow:-8px 16px 32px -12px #00000038;animation:__P__-drawer-in var(--__P__-dur-base) var(--__P__-ease)}:host([data-mode="drawer"][data-position$="-left"]) .__P__-panel{box-shadow:8px 16px 32px -12px #00000038;animation:__P__-drawer-in-left var(--__P__-dur-base) var(--__P__-ease)}.__P__-fab[data-edge-tab]{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-2);position:fixed;top:50%;height:140px;width:auto;min-width:0;padding:10px 8px;writing-mode:vertical-rl;text-orientation:mixed;transform:translateY(-50%);transform-origin:center;animation:__P__-edge-tab-in var(--__P__-dur-base) var(--__P__-ease) both}.__P__-fab[data-edge-tab] svg{writing-mode:horizontal-tb}.__P__-fab[data-edge-tab]:hover{transform:translateY(-50%) scale(1.03)}.__P__-fab[data-edge-tab]:active{transform:translateY(-50%) scale(.97)}:host([data-position$="-right"]) .__P__-fab[data-edge-tab]{right:0;left:auto;border-radius:12px 0 0 12px;box-shadow:-6px 0 18px -8px #0000004d}:host([data-position$="-left"]) .__P__-fab[data-edge-tab]{left:0;right:auto;border-radius:0 12px 12px 0;box-shadow:6px 0 18px -8px #0000004d}.__P__-fab[data-edge-tab][data-leaving]{position:fixed;top:50%;bottom:auto;animation:__P__-edge-tab-out var(--__P__-dur-quick) var(--__P__-ease) forwards}@keyframes __P__-edge-tab-in{0%{opacity:0;transform:translateY(-50%) scale(.9)}to{opacity:1;transform:translateY(-50%) scale(1)}}@keyframes __P__-edge-tab-out{0%{opacity:1;transform:translateY(-50%) scale(1)}to{opacity:0;transform:translateY(-50%) scale(.85)}}@keyframes __P__-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes __P__-drawer-in-left{0%{transform:translate(-100%)}to{transform:translate(0)}}@media(prefers-reduced-motion:reduce){:host([data-mode="drawer"]) .__P__-panel,.__P__-fab[data-edge-tab]{animation:none}}.__P__-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);background:var(--__P__-bg)}.__P__-header h1{font-size:14px;font-weight:600;flex:1;letter-spacing:-.01em}.__P__-header-actions{margin-left:auto;display:flex;align-items:center;gap:var(--__P__-space-1);flex-shrink:0}.__P__-agent{flex:1;display:inline-flex;align-items:center;gap:10px;min-width:0}.__P__-agent-avatar{position:relative;width:32px;height:32px;border-radius:999px;background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--__P__-text-xs);overflow:hidden;flex-shrink:0}.__P__-agent-avatar img{width:100%;height:100%;object-fit:cover}.__P__-agent-avatar:after{content:"";position:absolute;right:-1px;bottom:-1px;width:10px;height:10px;border-radius:999px;border:2px solid var(--__P__-bg);background:var(--__P__-neutral)}.__P__-agent-avatar[data-status=online]:after{background:var(--__P__-success)}.__P__-agent-avatar[data-status=away]:after{background:var(--__P__-warning)}.__P__-agent-avatar[data-status=offline]:after{background:var(--__P__-neutral)}.__P__-agent-meta{display:flex;flex-direction:column;line-height:1.15;min-width:0}.__P__-agent-meta strong{font-size:14px;font-weight:600;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-agent-meta span{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-suggestions{display:flex;flex-wrap:nowrap;gap:var(--__P__-space-2);padding:6px 14px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scroll-snap-type:x proximity;scrollbar-width:none;-ms-overflow-style:none;min-width:0}.__P__-suggestions::-webkit-scrollbar{display:none}.__P__-suggestions:before,.__P__-suggestions:after{content:"";flex:1 1 0;min-width:0}.__P__-suggestion{flex:0 0 auto;scroll-snap-align:center;padding:7px 14px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg);font-size:var(--__P__-text-sm);font-weight:500;white-space:nowrap;transition:background var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-suggestion:hover{border-color:var(--__P__-accent);color:var(--__P__-accent);transform:translateY(-1px)}.__P__-suggestion:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px;border-color:var(--__P__-accent)}.__P__-suggestion:active{transform:translateY(0)}.__P__-icon-btn{width:32px;height:32px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);transition:background var(--__P__-dur-quick) var(--__P__-ease),color var(--__P__-dur-quick) var(--__P__-ease)}.__P__-icon-btn:hover{background:var(--__P__-bg-elevated);color:var(--__P__-fg)}.__P__-icon-btn:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-icon-btn:active{background:var(--__P__-border)}.__P__-icon-btn:disabled{opacity:.45;cursor:not-allowed}.__P__-icon-btn:before{content:"";position:absolute;inset:-6px}.__P__-icon-btn{position:relative}.__P__-icon-btn svg{width:18px;height:18px}.__P__-icon-btn[data-recording=true]{color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);animation:__P__-pulse 1.2s var(--__P__-ease) infinite}@keyframes __P__-pulse{0%,to{box-shadow:0 0 color-mix(in srgb,var(--__P__-accent) 40%,transparent)}50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--__P__-accent) 0%,transparent)}}.__P__-list-wrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}.__P__-jump{position:absolute;right:14px;bottom:14px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:999px;border:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);color:var(--__P__-fg);box-shadow:var(--__P__-shadow-panel);cursor:pointer;opacity:.85;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease);animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-jump:hover{opacity:1}.__P__-jump:active{transform:translateY(1px)}.__P__-jump svg{width:18px;height:18px}.__P__-list{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-4);padding-bottom:var(--__P__-space-8);display:flex;flex-direction:column;gap:14px;scrollbar-width:thin;scrollbar-color:var(--__P__-border-strong) transparent;scrollbar-gutter:stable}.__P__-list::-webkit-scrollbar{width:8px}.__P__-list::-webkit-scrollbar-thumb{background:var(--__P__-border-strong);border-radius:8px}.__P__-date-divider{position:sticky;top:var(--__P__-space-2);z-index:2;display:flex;justify-content:center;align-items:flex-start;height:0;margin:0;pointer-events:none}.__P__-date-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--__P__-fg-muted);background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);box-shadow:var(--__P__-shadow-card);opacity:0;pointer-events:none;transition:opacity var(--__P__-dur-base) var(--__P__-ease)}.__P__-list[data-scrolling=true] .__P__-date-pill{opacity:1;pointer-events:auto}@media(prefers-reduced-motion:reduce){.__P__-date-pill{transition:none}}.__P__-bubble-row{display:flex}.__P__-bubble-row[data-role=user]{justify-content:flex-end}.__P__-bubble-row[data-role=assistant]{justify-content:flex-start}.__P__-bubble{max-width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);line-height:1.6;font-size:14px;word-wrap:break-word;overflow-wrap:anywhere;box-shadow:0 1px 2px #0000000a,0 1px 8px -4px #0000000f;animation:__P__-bubble-in var(--__P__-dur-base) var(--__P__-ease)}.__P__-bubble ::selection{background:color-mix(in srgb,var(--__P__-accent) 30%,transparent)}.__P__-bubble-row[data-role=user] .__P__-bubble ::selection{background:#fff6;color:var(--__P__-bubble-user-text)}@keyframes __P__-bubble-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.__P__-bubble-row[data-role=user] .__P__-bubble{background:var(--__P__-bubble-user);color:var(--__P__-bubble-user-text);border-bottom-right-radius:5px}.__P__-bubble-row[data-role=assistant] .__P__-bubble{background:var(--__P__-bubble-assistant);color:var(--__P__-bubble-assistant-text);border-bottom-left-radius:5px}.__P__-bubble-col{display:flex;flex-direction:column;max-width:85%;min-width:0}.__P__-bubble-row[data-role=user] .__P__-bubble-col{align-items:flex-end}.__P__-bubble-row[data-role=assistant] .__P__-bubble-col{align-items:flex-start}.__P__-bubble-time{margin-top:3px;padding:0 4px;font-size:11px;line-height:1;color:var(--__P__-fg-muted);user-select:none}.__P__-md>*:first-child{margin-top:0}.__P__-md>*:last-child{margin-bottom:0}.__P__-md p{margin:10px 0}.__P__-md h1,.__P__-md h2,.__P__-md h3,.__P__-md h4,.__P__-md h5,.__P__-md h6{margin:18px 0 8px;line-height:1.3;letter-spacing:-.01em;font-weight:700}.__P__-md h1{font-size:1.4em}.__P__-md h2{font-size:1.22em}.__P__-md h3{font-size:1.08em}.__P__-md h4,.__P__-md h5,.__P__-md h6{font-size:1em}.__P__-md>h1:first-child,.__P__-md>h2:first-child,.__P__-md>h3:first-child,.__P__-md>h4:first-child,.__P__-md>h5:first-child,.__P__-md>h6:first-child{margin-top:0}.__P__-md ul,.__P__-md ol{padding-left:1.5em;margin:10px 0}.__P__-md ul{list-style:disc}.__P__-md ol{list-style:decimal}.__P__-md li{margin:6px 0;padding-left:2px}.__P__-md li::marker{color:var(--__P__-fg-muted)}.__P__-md li>p{margin:6px 0}.__P__-md li>ul,.__P__-md li>ol{margin:6px 0}.__P__-md strong,.__P__-md b{font-weight:650;letter-spacing:-.005em}.__P__-md em,.__P__-md i{font-style:italic}.__P__-md code{font-family:var(--__P__-font-mono);font-size:.86em;padding:1px 6px;border-radius:5px;background:color-mix(in srgb,var(--__P__-accent) 10%,transparent);color:var(--__P__-fg);border:1px solid color-mix(in srgb,var(--__P__-accent) 16%,transparent)}.__P__-md pre{font-family:var(--__P__-font-mono);font-size:12.5px;padding:12px 14px;border-radius:var(--__P__-radius-sm);background:#7f7f7f1f;overflow-x:auto;margin:var(--__P__-space-3) 0;line-height:1.5}.__P__-md pre code{padding:0;background:none}.__P__-md a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}.__P__-md a:hover{text-decoration-thickness:2px}.__P__-md blockquote{margin:14px 0;padding:6px 14px;border-left:3px solid color-mix(in srgb,var(--__P__-accent) 50%,transparent);background:color-mix(in srgb,var(--__P__-accent) 5%,transparent);border-radius:0 var(--__P__-radius-sm) var(--__P__-radius-sm) 0;color:var(--__P__-fg-muted)}.__P__-md blockquote>:first-child{margin-top:0}.__P__-md blockquote>:last-child{margin-bottom:0}.__P__-md hr{border:0;height:1px;background:color-mix(in srgb,currentColor 18%,transparent);margin:var(--__P__-space-4) 0}.__P__-md table{border-collapse:collapse;margin:var(--__P__-space-3) 0;font-size:.95em;display:block;overflow-x:auto;max-width:100%;font-variant-numeric:tabular-nums}.__P__-md th,.__P__-md td{padding:6px 10px;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);text-align:left}.__P__-md th{font-weight:700;background:color-mix(in srgb,currentColor 6%,transparent)}.__P__-md h1+ul,.__P__-md h1+ol,.__P__-md h2+ul,.__P__-md h2+ol,.__P__-md h3+ul,.__P__-md h3+ol,.__P__-md h4+ul,.__P__-md h4+ol{margin-top:var(--__P__-space-1)}.__P__-loading{display:inline-flex;align-items:center;gap:var(--__P__-space-2);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-loading-spinner{width:14px;height:14px;border-radius:999px;border:2px solid currentColor;border-top-color:transparent;animation:__P__-spin .8s linear infinite}@keyframes __P__-spin{to{transform:rotate(1turn)}}.__P__-typing{display:inline-flex;gap:var(--__P__-space-1);padding:var(--__P__-space-1) 0}.__P__-typing span{width:5px;height:5px;border-radius:999px;background:currentColor;opacity:.4;animation:__P__-blink 1.2s var(--__P__-ease) infinite}.__P__-typing span:nth-child(2){animation-delay:.2s}.__P__-typing span:nth-child(3){animation-delay:.4s}@keyframes __P__-blink{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.__P__-reasoning{margin:var(--__P__-space-1) 0 var(--__P__-space-2);padding-left:var(--__P__-space-3);border-left:2px solid var(--__P__-border-strong)}.__P__-reasoning-summary{display:inline-flex;align-items:center;gap:var(--__P__-space-1);cursor:pointer;list-style:none;user-select:none;color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-reasoning-summary::-webkit-details-marker{display:none}.__P__-reasoning-summary:before{content:"";width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);opacity:.7;transition:transform var(--__P__-dur-quick) var(--__P__-ease)}.__P__-reasoning[open] .__P__-reasoning-summary:before{transform:rotate(45deg)}.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:__P__-reasoning-pulse 1.4s var(--__P__-ease) infinite}@keyframes __P__-reasoning-pulse{0%,to{opacity:.5}50%{opacity:1}}@media(prefers-reduced-motion:reduce){.__P__-reasoning[data-active=true] .__P__-reasoning-label{animation:none}}.__P__-reasoning-body{margin-top:var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm)}.__P__-reasoning-body>:first-child{margin-top:0}.__P__-reasoning-body>:last-child{margin-bottom:0}.__P__-tool-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2);margin-top:6px;border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs)}.__P__-composer{border-top:1px solid var(--__P__-border);padding:10px 12px;background:var(--__P__-bg);display:flex;flex-direction:column;gap:var(--__P__-space-2)}.__P__-composer-row{display:flex;align-items:flex-end;gap:6px}.__P__-textarea{flex:1;height:40px;max-height:160px;padding:10px 12px;border-radius:var(--__P__-radius);background:var(--__P__-bg-elevated);border:1px solid transparent;font-size:14px;line-height:1.4;transition:height var(--__P__-dur-quick) var(--__P__-ease),border-color var(--__P__-dur-quick) var(--__P__-ease),box-shadow var(--__P__-dur-quick) var(--__P__-ease)}.__P__-textarea:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:1px;border-color:var(--__P__-focus)}@media(pointer:coarse){.__P__-textarea,.__P__-home-search-input{font-size:16px}.__P__-textarea{height:44px}}.__P__-send{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;transition:opacity var(--__P__-dur-quick) var(--__P__-ease),transform var(--__P__-dur-quick) var(--__P__-ease),background var(--__P__-dur-quick) var(--__P__-ease)}.__P__-send[data-shape=circle]{border-radius:999px}.__P__-send[data-shape=square]{border-radius:var(--__P__-radius-sm)}.__P__-send[data-shape=pill]{width:auto;padding:0 18px;border-radius:999px}.__P__-send[data-variant=filled]{background:var(--__P__-accent);color:var(--__P__-accent-text)}.__P__-send[data-variant=outline]{background:transparent;color:var(--__P__-accent);border-color:var(--__P__-accent)}.__P__-send[data-variant=outline]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 10%,transparent)}.__P__-send[data-variant=ghost]{background:transparent;color:var(--__P__-accent)}.__P__-send[data-variant=ghost]:not(:disabled):hover{background:color-mix(in srgb,var(--__P__-accent) 8%,transparent)}.__P__-send:disabled{opacity:.4;cursor:not-allowed}.__P__-send:not(:disabled):hover{transform:translateY(-1px)}.__P__-send:not(:disabled):active{transform:translateY(0)}.__P__-send:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-send svg{width:18px;height:18px}.__P__-composer-actions{display:flex;gap:var(--__P__-space-1);flex-wrap:wrap}.__P__-attachments{display:flex;flex-wrap:wrap;gap:6px}.__P__-attachment-chip{display:inline-flex;align-items:center;gap:6px;padding:var(--__P__-space-1) var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-1);border-radius:999px;background:var(--__P__-bg-elevated);border:1px solid var(--__P__-border);font-size:var(--__P__-text-xs);max-width:200px}.__P__-attachment-thumb{width:24px;height:24px;border-radius:999px;object-fit:cover;background:var(--__P__-border)}.__P__-attachment-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-attachment-remove{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted)}.__P__-attachment-remove:hover{background:var(--__P__-border);color:var(--__P__-fg)}.__P__-dropzone{position:absolute;inset:8px;border:2px dashed var(--__P__-accent);border-radius:var(--__P__-radius);background:color-mix(in srgb,var(--__P__-accent) 8%,transparent);display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--__P__-accent);pointer-events:none;z-index:10;animation:__P__-fade-in var(--__P__-dur-quick) var(--__P__-ease)}@keyframes __P__-fade-in{0%{opacity:0}to{opacity:1}}.__P__-error{margin-top:var(--__P__-space-1);padding:8px 10px;border-radius:var(--__P__-radius-sm);background:var(--__P__-danger-bg);color:var(--__P__-danger-text);font-size:var(--__P__-text-sm);display:flex;align-items:center;gap:var(--__P__-space-2)}.__P__-error button{color:inherit;text-decoration:underline;font-size:var(--__P__-text-sm)}.__P__-history{flex:1;overflow-y:auto;padding:var(--__P__-space-2) var(--__P__-space-1) var(--__P__-space-3)}.__P__-history-footer{flex:none;padding:var(--__P__-space-2) var(--__P__-space-3) var(--__P__-space-3);border-top:1px solid var(--__P__-border);background:var(--__P__-surface)}.__P__-history-new{width:100%;display:flex;align-items:center;justify-content:center;gap:var(--__P__-space-2);padding:var(--__P__-space-2) var(--__P__-space-3);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-on-accent);cursor:pointer;font-size:var(--__P__-text-sm);font-weight:600;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-history-new svg{width:16px;height:16px}.__P__-history-new:hover{filter:brightness(1.08)}.__P__-history-new:active{transform:translateY(1px)}.__P__-history-new:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-history-empty{flex:1;display:flex;align-items:center;justify-content:center;padding:40px 16px;color:var(--__P__-fg-muted);font-size:14px;text-align:center}.__P__-history-group{display:flex;flex-direction:column;padding:0 var(--__P__-space-2)}.__P__-history-heading{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-fg-muted);padding:12px 8px 6px;text-transform:uppercase;letter-spacing:.04em}.__P__-history-item{all:unset;display:flex;flex-direction:column;gap:3px;padding:10px 12px;border-radius:var(--__P__-radius-md);cursor:pointer;transition:background var(--__P__-dur-base) var(--__P__-ease)}.__P__-history-item:hover{background:var(--__P__-bg-elevated)}.__P__-history-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-history-title{font-size:14px;font-weight:500;color:var(--__P__-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-preview{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-history-item[data-closed=true] .__P__-history-title:after{content:"\\2022";margin-left:var(--__P__-space-2);opacity:.5}.__P__-list-loading{margin:auto;padding:var(--__P__-space-6) var(--__P__-space-4);color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);text-align:center}.__P__-readonly-banner{display:flex;flex-direction:column;align-items:center;gap:10px;padding:14px 12px;margin:0 var(--__P__-space-3) var(--__P__-space-3);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated);color:var(--__P__-fg-muted);text-align:center;font-size:var(--__P__-text-sm)}.__P__-readonly-label{line-height:1.4}.__P__-readonly-cta{appearance:none;border:0;cursor:pointer;padding:var(--__P__-space-2) var(--__P__-space-4);border-radius:999px;background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-readonly-cta:hover,.__P__-readonly-cta:focus-visible{filter:brightness(1.1)}.__P__-readonly-cta:focus-visible{outline:2px solid var(--__P__-accent);outline-offset:2px}.__P__-composer-footer{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:10px 16px;margin:0 var(--__P__-space-3);border-top:1px solid var(--__P__-border);text-align:center;font-size:11px;line-height:1.4;color:var(--__P__-fg-muted)}.__P__-disclaimer{max-width:320px;margin:0 auto;opacity:.9;letter-spacing:.01em}.__P__-poweredby{display:inline-flex;align-items:center;justify-content:center;gap:6px;color:inherit;text-decoration:none;opacity:.7;transition:opacity var(--__P__-dur-base) var(--__P__-ease);font-size:11px;letter-spacing:.02em}.__P__-poweredby:hover{opacity:1}.__P__-poweredby-logo{height:12px;width:auto;display:inline-block;vertical-align:middle}.__P__-poweredby-bar{flex:none;display:flex;align-items:center;justify-content:center;padding:6px 16px;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated)}.__P__-menu-wrap{position:relative;display:inline-flex}.__P__-menu{position:absolute;top:100%;right:0;margin-top:6px;min-width:200px;padding:6px;background:var(--__P__-bg);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);box-shadow:var(--__P__-shadow-panel);z-index:10;display:flex;flex-direction:column;gap:2px;animation:__P__-menu-in var(--__P__-dur-base) var(--__P__-ease)}@media(prefers-reduced-motion:reduce){.__P__-menu{animation:none}}@keyframes __P__-menu-in{0%{opacity:0;transform:translateY(-4px) scale(.98);transform-origin:top right}to{opacity:1;transform:none}}.__P__-menu-item{all:unset;display:flex;align-items:center;gap:10px;padding:8px 10px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);border-radius:var(--__P__-radius-sm);cursor:pointer;user-select:none}.__P__-menu-item:hover{background:var(--__P__-bg-elevated)}.__P__-menu-item:focus-visible{background:var(--__P__-bg-elevated);outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-menu-item[disabled]{opacity:.45;cursor:not-allowed}.__P__-menu-icon{display:inline-flex;width:16px;height:16px;color:var(--__P__-fg-muted)}.__P__-menu-icon svg{width:16px;height:16px}.__P__-menu-label{flex:1}.__P__-menu-check{display:inline-flex;color:var(--__P__-accent)}.__P__-menu-check svg{width:14px;height:14px}.__P__-resize-grip{position:absolute;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:var(--__P__-fg-muted);opacity:.45;transition:opacity var(--__P__-dur-base) var(--__P__-ease);z-index:2;touch-action:none;user-select:none}.__P__-resize-grip:hover,.__P__-resize-grip:focus-visible{opacity:1}.__P__-resize-grip svg{width:10px;height:10px}.__P__-resize-grip--bottom-left{bottom:2px;left:2px;cursor:nesw-resize;transform:scaleX(-1)}.__P__-resize-grip--bottom-right{bottom:2px;right:2px;cursor:nwse-resize}.__P__-resize-grip--top-left{top:2px;left:2px;cursor:nwse-resize;transform:rotate(180deg)}.__P__-resize-grip--top-right{top:2px;right:2px;cursor:nesw-resize;transform:scaleY(-1)}:host(:not([data-mode="open"])) .__P__-resize-grip{display:none}.__P__-messenger{display:flex;flex-direction:column;overflow:hidden}.__P__-messenger-body{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}.__P__-module{display:flex;flex-direction:column;height:100%;min-height:0}.__P__-module-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--__P__-space-3);display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-home{background:radial-gradient(125% 65% at 88% 0%,color-mix(in srgb,#fff 16%,transparent),transparent 55%),linear-gradient(180deg,var(--__P__-accent) 0%,var(--__P__-accent) 22%,color-mix(in srgb,var(--__P__-accent) 28%,var(--__P__-surface)) 44%,var(--__P__-surface) 70%);border-radius:var(--__P__-radius-lg) var(--__P__-radius-lg) 0 0}.__P__-home-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;background:transparent}.__P__-home-cards{display:flex;flex-direction:column;gap:var(--__P__-space-3);padding:4px 14px 16px}.__P__-module-pad{padding:var(--__P__-space-3) var(--__P__-space-3) 0}.__P__-module-empty{display:flex;flex-direction:column;align-items:center;gap:var(--__P__-space-3);padding:var(--__P__-space-8) var(--__P__-space-4);text-align:center;color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-module-retry{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border-strong);border-radius:var(--__P__-radius-sm);color:var(--__P__-fg);font-weight:600;cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-module-retry:hover{background:var(--__P__-hover);border-color:var(--__P__-accent)}.__P__-module-retry:active{background:var(--__P__-border)}.__P__-module-retry:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-help-list{flex:1;min-height:0;overflow-y:auto;padding-bottom:var(--__P__-space-3)}.__P__-help-group{display:flex;flex-direction:column}.__P__-help-section-title{position:sticky;top:0;z-index:1;margin:0;padding:var(--__P__-space-3) var(--__P__-space-5) var(--__P__-space-2);font-size:var(--__P__-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--__P__-fg-muted);background:var(--__P__-bg)}.__P__-help-card{margin:0 var(--__P__-space-3) var(--__P__-space-3);background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden}.__P__-help-card .__P__-list-row{border-bottom:0;border-radius:0}.__P__-help-card .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-help-card .__P__-list-row:hover{background:var(--__P__-hover)}.__P__-module-cta{padding:var(--__P__-space-3);border-top:1px solid var(--__P__-border)}.__P__-tabbar{display:flex;border-top:1px solid var(--__P__-border);background:var(--__P__-bg-elevated);flex-shrink:0}.__P__-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--__P__-space-1);min-height:48px;padding:var(--__P__-space-2) var(--__P__-space-1);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600;transition:color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-tab:hover{color:var(--__P__-fg)}.__P__-tab[aria-selected=true]{color:var(--__P__-accent)}.__P__-tab:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-tab:active{background:var(--__P__-hover)}.__P__-tab-icon{position:relative;display:inline-flex}.__P__-tab-icon svg{width:22px;height:22px}.__P__-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;background:var(--__P__-accent);color:var(--__P__-on-accent);font-size:10px;font-weight:600;line-height:1}.__P__-home-hero{flex-shrink:0;padding:var(--__P__-space-5) var(--__P__-space-5) var(--__P__-space-3);color:var(--__P__-on-accent);--__P__-focus: var(--__P__-on-accent)}.__P__-home-hero-top{display:flex;align-items:center;justify-content:space-between;gap:var(--__P__-space-3);min-height:32px}.__P__-home-brand{font-size:14px;font-weight:600;letter-spacing:.01em;color:color-mix(in srgb,#fff 82%,transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.__P__-home-brand-spacer{flex:1}.__P__-home-hero-actions{display:flex;align-items:center;gap:var(--__P__-space-2);flex-shrink:0}.__P__-home-hero-actions .__P__-icon-btn{color:#fff}.__P__-home-greeting{margin:28px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;overflow-wrap:anywhere}.__P__-home-lead{margin:2px 0 0;font-family:var(--__P__-font-display);font-size:var(--__P__-text-2xl);font-weight:800;line-height:1.18;letter-spacing:-.01em;color:color-mix(in srgb,var(--__P__-on-accent) 88%,transparent);overflow-wrap:anywhere}.__P__-home-avatars{display:flex}.__P__-home-avatar{width:30px;height:30px;border-radius:999px;overflow:hidden;margin-left:-10px;border:2px solid color-mix(in srgb,#fff 92%,transparent);box-shadow:0 1px 3px #0000002e;background:var(--__P__-surface);display:inline-flex;align-items:center;justify-content:center;font-size:var(--__P__-text-xs);font-weight:700;color:var(--__P__-fg)}.__P__-home-avatar:first-child{margin-left:0}.__P__-home-avatar img{width:100%;height:100%;object-fit:cover}.__P__-home-content{background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);box-shadow:var(--__P__-shadow-card);overflow:hidden}.__P__-home-content-title{padding:var(--__P__-space-4) var(--__P__-space-4) var(--__P__-space-3);font-size:var(--__P__-text-sm);font-weight:700}.__P__-home-content-list{display:flex;flex-direction:column;padding:0 var(--__P__-space-2) var(--__P__-space-2)}.__P__-home-content-list .__P__-list-row+.__P__-list-row{border-top:1px solid var(--__P__-border)}.__P__-home-card{display:block;width:100%;text-align:left;background:var(--__P__-surface);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);padding:var(--__P__-space-4);box-shadow:var(--__P__-shadow-card)}.__P__-home-card[data-interactive=true]{cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-home-card[data-interactive=true]:hover{background:var(--__P__-bg-elevated)}.__P__-home-card[data-interactive=true]:active{transform:translateY(1px)}.__P__-home-card[data-interactive=true]:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-recent-row{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-recent-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;flex-shrink:0;border-radius:999px;background:color-mix(in oklch,var(--__P__-accent) 14%,transparent);color:var(--__P__-accent)}.__P__-home-recent-avatar svg{width:20px;height:20px}.__P__-home-recent-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.__P__-home-recent-title{font-weight:600;font-size:14px}.__P__-home-recent-preview{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.__P__-home-recent-at{color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);flex-shrink:0}.__P__-home-recent-dot{width:8px;height:8px;border-radius:999px;background:var(--__P__-accent);flex-shrink:0}.__P__-home-recent-row[data-unread=true] .__P__-home-recent-title{font-weight:700}.__P__-home-status{display:flex;align-items:center;gap:var(--__P__-space-3)}.__P__-home-status-icon svg{width:22px;height:22px;color:var(--__P__-success)}.__P__-home-status[data-level=degraded] .__P__-home-status-icon svg{color:var(--__P__-warning)}.__P__-home-status[data-level=down] .__P__-home-status-icon svg{color:var(--__P__-danger)}.__P__-home-status-text{font-weight:600;font-size:14px}.__P__-home-search{display:flex;align-items:center;gap:var(--__P__-space-2);width:100%;padding:var(--__P__-space-3) var(--__P__-space-4);border-radius:var(--__P__-radius);border:1px solid var(--__P__-border);background:var(--__P__-surface);text-align:left}.__P__-home-search[data-input=true]{background:var(--__P__-bg-elevated)}.__P__-home-search:hover{border-color:var(--__P__-border-strong)}.__P__-home-search:focus-visible,.__P__-home-search:focus-within{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-home-search-text{flex:1;color:var(--__P__-fg-muted);font-size:14px}.__P__-home-search-input{flex:1;border:0;background:transparent;font-size:14px;color:var(--__P__-fg);outline:none}.__P__-home-search-icon svg{width:18px;height:18px;color:var(--__P__-accent)}.__P__-list-row{display:flex;align-items:center;gap:var(--__P__-space-3);width:100%;min-height:44px;text-align:left;padding:var(--__P__-space-3) var(--__P__-space-2);border-radius:var(--__P__-radius-sm)}.__P__-list-row:hover{background:var(--__P__-bg-elevated)}.__P__-list-row:active{background:var(--__P__-border)}.__P__-list-row:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:-2px}.__P__-list-row-body{display:flex;flex-direction:column;min-width:0;flex:1}.__P__-list-row-title{font-weight:600;font-size:var(--__P__-text-md);line-height:1.35}.__P__-list-row-sub{color:var(--__P__-fg-muted);font-size:var(--__P__-text-sm);margin-top:var(--__P__-space-1);line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-list-row-chevron svg{width:18px;height:18px;color:var(--__P__-accent);flex-shrink:0}.__P__-back-header{display:flex;align-items:center;gap:var(--__P__-space-2);padding:10px 12px;border-bottom:1px solid var(--__P__-border);flex-shrink:0}.__P__-back-title{flex:1;text-align:center;font-size:var(--__P__-text-md);font-weight:700;margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__P__-back-spacer{width:32px;height:1px}.__P__-content{display:flex;flex-direction:column;gap:14px;width:100%;max-width:68ch;margin:0 auto}.__P__-content-hero{width:100%;border-radius:var(--__P__-radius)}.__P__-content-subtitle{color:var(--__P__-fg-muted);margin:0}.__P__-content-frame{flex:1;min-height:0;width:100%;border:0;background:#fff}.__P__-news-list{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-news-card{display:block;width:100%;text-align:left;border:1px solid var(--__P__-border);border-radius:var(--__P__-radius);overflow:hidden;background:var(--__P__-surface)}.__P__-news-card{transition:background var(--__P__-dur-quick) var(--__P__-ease-out),transform var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-news-card:hover{background:var(--__P__-bg-elevated)}.__P__-news-card:active{transform:translateY(1px)}.__P__-news-card:focus-visible{outline:2px solid var(--__P__-focus);outline-offset:2px}.__P__-news-hero{width:100%;display:block}.__P__-news-body{display:flex;flex-direction:column;gap:6px;padding:14px 16px}.__P__-news-tags{display:flex;gap:6px;flex-wrap:wrap}.__P__-news-tag{font-size:var(--__P__-text-xs);font-weight:600;color:var(--__P__-accent);background:color-mix(in srgb,var(--__P__-accent) 12%,transparent);padding:2px 8px;border-radius:999px}.__P__-news-title{font-weight:700;font-size:var(--__P__-text-md)}.__P__-news-summary{color:var(--__P__-fg-muted);font-size:14px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.__P__-modules-empty{display:flex;align-items:center;justify-content:center;position:relative}.__P__-modules-empty-close{position:absolute;top:12px;right:12px}.__P__-modules-empty-text{color:var(--__P__-fg-muted);font-size:var(--__P__-text-base)}.__P__-form{display:flex;flex-direction:column;gap:var(--__P__-space-3)}.__P__-field{display:flex;flex-direction:column;gap:4px}.__P__-field-label{font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-field-req{color:var(--__P__-danger)}.__P__-field-input{width:100%;box-sizing:border-box;padding:var(--__P__-space-2) var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg);color:var(--__P__-fg);font:inherit;font-size:var(--__P__-text-sm);resize:vertical;transition:border-color var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-field-input:focus-visible{outline:none;border-color:var(--__P__-accent)}.__P__-field[data-invalid=true] .__P__-field-input{border-color:var(--__P__-danger)}.__P__-field-hint{font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-field-error{font-size:var(--__P__-text-xs);color:var(--__P__-danger)}.__P__-field-choices{display:flex;flex-direction:column;gap:6px}.__P__-choice{display:flex;align-items:flex-start;gap:8px;font-size:var(--__P__-text-sm);color:var(--__P__-fg);cursor:pointer}.__P__-choice input{margin-top:2px;accent-color:var(--__P__-accent)}.__P__-form-actions{display:flex;justify-content:flex-end;gap:var(--__P__-space-2);margin-top:2px}.__P__-form-submit,.__P__-tool-approve{padding:var(--__P__-space-2) var(--__P__-space-4);border:none;border-radius:var(--__P__-radius-md);background:var(--__P__-accent);color:var(--__P__-accent-text, #fff);font:inherit;font-weight:600;font-size:var(--__P__-text-sm);cursor:pointer;transition:filter var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-submit:hover:not(:disabled),.__P__-tool-approve:hover:not(:disabled){filter:brightness(1.06)}.__P__-form-submit:disabled{opacity:.6;cursor:default}.__P__-form-skip,.__P__-tool-reject{padding:var(--__P__-space-2) var(--__P__-space-4);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:transparent;color:var(--__P__-fg-muted);font:inherit;font-size:var(--__P__-text-sm);cursor:pointer;transition:background var(--__P__-dur-quick) var(--__P__-ease-out)}.__P__-form-skip:hover:not(:disabled),.__P__-tool-reject:hover:not(:disabled){background:var(--__P__-bg-elevated)}.__P__-form-gate{display:flex;flex-direction:column;gap:var(--__P__-space-2);padding:var(--__P__-space-3) var(--__P__-space-4) var(--__P__-space-4);border-top:1px solid var(--__P__-border);flex:1 1 auto;min-height:0;overflow-y:auto}.__P__-list-wrap:has(+.__P__-form-gate){flex:0 1 auto;max-height:40%}.__P__-list-wrap:has(+.__P__-form-gate) .__P__-list:empty{padding:0}.__P__-form-gate-title{margin:0;font-size:var(--__P__-text-base);font-weight:700;color:var(--__P__-fg)}.__P__-form-gate-desc{margin:0 0 var(--__P__-space-1);font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-ask-input,.__P__-tool-approval{display:flex;flex-direction:column;gap:var(--__P__-space-2);margin-top:6px;padding:var(--__P__-space-3);border:1px solid var(--__P__-border);border-radius:var(--__P__-radius-md);background:var(--__P__-bg-elevated)}.__P__-tool-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-badge{padding:2px 8px;border-radius:999px;background:var(--__P__-warning, #f59e0b);color:#1a1206;font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-title{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}.__P__-tool-question{margin:0;font-size:var(--__P__-text-sm);font-weight:600;color:var(--__P__-fg)}.__P__-tool-desc{margin:0;font-size:var(--__P__-text-sm);color:var(--__P__-fg-muted)}.__P__-tool-args{margin:0;padding:var(--__P__-space-2);max-height:160px;overflow:auto;border-radius:var(--__P__-radius-sm);background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);white-space:pre-wrap;word-break:break-word}.__P__-tool-stale-note{margin:0;font-size:var(--__P__-text-xs);color:var(--__P__-fg-muted)}.__P__-tool-decided{flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}.__P__-tool-decided-label{padding:2px 8px;border-radius:999px;background:var(--__P__-bg);border:1px solid var(--__P__-border);color:var(--__P__-fg-muted);font-size:var(--__P__-text-xs);font-weight:600}.__P__-tool-decided-label[data-approved=true]{color:var(--__P__-success, #16a34a);border-color:var(--__P__-success, #16a34a)}.__P__-tool-decided-label[data-approved=false]{color:var(--__P__-danger);border-color:var(--__P__-danger)}.__P__-tool-decided-value{font-size:var(--__P__-text-sm);color:var(--__P__-fg)}\n';
|
|
966
974
|
|
|
967
975
|
// src/styles/standalone.css
|
|
968
976
|
var standalone_default = ".__P__-standalone-page{margin:0;height:100vh;background:var(--__P__-bg, #fff);display:grid;place-items:stretch}\n";
|
|
@@ -1246,8 +1254,8 @@ function encodeContext(user, page) {
|
|
|
1246
1254
|
|
|
1247
1255
|
// src/stream/protocol.ts
|
|
1248
1256
|
var DEFAULT_PATHS = {
|
|
1249
|
-
/**
|
|
1250
|
-
|
|
1257
|
+
/** Conversation bootstrap. `POST` → deployment config + per-visitor state. */
|
|
1258
|
+
startConversation: "/ai/agent/start-conversation",
|
|
1251
1259
|
/** Send a message + stream the reply (SSE). `POST`. */
|
|
1252
1260
|
streamMessage: "/ai/agent/stream-message",
|
|
1253
1261
|
/**
|
|
@@ -1260,20 +1268,20 @@ var DEFAULT_PATHS = {
|
|
|
1260
1268
|
/** Abort the in-flight reply stream. `POST`. */
|
|
1261
1269
|
cancelStream: "/ai/agent/cancel-stream",
|
|
1262
1270
|
/** List the visitor's conversations. `GET`. */
|
|
1263
|
-
|
|
1264
|
-
/** Load one conversation's messages. `GET ?
|
|
1271
|
+
listConversations: "/ai/agent/list-conversations",
|
|
1272
|
+
/** Load one conversation's messages. `GET ?conversationId=…`. */
|
|
1265
1273
|
listMessages: "/ai/agent/list-messages",
|
|
1266
1274
|
/**
|
|
1267
1275
|
* Persist a user-driven settings change. POST `{ visitorId, userPrefs }` →
|
|
1268
1276
|
* server persists, returns the merged authoritative copy. Fire-and-forget on
|
|
1269
1277
|
* the client — a failure leaves the local cache valid; the next
|
|
1270
|
-
* `
|
|
1278
|
+
* `startConversation()` reconciles.
|
|
1271
1279
|
*/
|
|
1272
1280
|
updateSettings: "/ai/agent/update-settings",
|
|
1273
1281
|
/**
|
|
1274
|
-
* Mark a conversation read. POST `{ visitorId,
|
|
1275
|
-
* records `lastReadAt = now` for that (visitor,
|
|
1276
|
-
* `unreadCount` (returned on `/list-
|
|
1282
|
+
* Mark a conversation read. POST `{ visitorId, conversationId }` → the server
|
|
1283
|
+
* records `lastReadAt = now` for that (visitor, conversation) and recomputes
|
|
1284
|
+
* `unreadCount` (returned on `/list-conversations`) accordingly. Fire-and-forget
|
|
1277
1285
|
* on the client; a failure just leaves the badge until the next sync.
|
|
1278
1286
|
*/
|
|
1279
1287
|
markRead: "/ai/agent/mark-read",
|
|
@@ -1282,8 +1290,8 @@ var DEFAULT_PATHS = {
|
|
|
1282
1290
|
content: "/ai/agent/content",
|
|
1283
1291
|
/**
|
|
1284
1292
|
* Form submission (the event-driven forms engine). POST `{ visitorId,
|
|
1285
|
-
*
|
|
1286
|
-
* immediately, keyed by the same visitor +
|
|
1293
|
+
* conversationId, formId, trigger, values, skipped? }` → record the form's answers
|
|
1294
|
+
* immediately, keyed by the same visitor + conversation as the conversation.
|
|
1287
1295
|
* Overridable via `endpoints.submitForm`. Fire-and-forget; 404 is ignored.
|
|
1288
1296
|
*/
|
|
1289
1297
|
submitForm: "/ai/agent/submit-form"
|
|
@@ -1298,7 +1306,7 @@ function buildSendMessageRequest(params) {
|
|
|
1298
1306
|
}));
|
|
1299
1307
|
const body = {
|
|
1300
1308
|
messages: wire,
|
|
1301
|
-
|
|
1309
|
+
conversationId: params.conversationId,
|
|
1302
1310
|
trigger: params.trigger ?? "submit-message"
|
|
1303
1311
|
};
|
|
1304
1312
|
if (params.visitorId) body.visitorId = params.visitorId;
|
|
@@ -1386,11 +1394,11 @@ function sleep(ms, signal7) {
|
|
|
1386
1394
|
var AgentTransport = class {
|
|
1387
1395
|
constructor(opts) {
|
|
1388
1396
|
__publicField(this, "opts", opts);
|
|
1389
|
-
// Identity adopted from the start-
|
|
1397
|
+
// Identity adopted from the start-conversation response; rides the request envelope
|
|
1390
1398
|
// (see `envelope()`) on every subsequent call so the backend can validate the
|
|
1391
|
-
// (visitor,
|
|
1399
|
+
// (visitor, conversation) pair.
|
|
1392
1400
|
__publicField(this, "visitorId");
|
|
1393
|
-
__publicField(this, "
|
|
1401
|
+
__publicField(this, "conversationId");
|
|
1394
1402
|
// Host-asserted context (sanitised `userContext` / `pageContext`), refreshed via
|
|
1395
1403
|
// `setContext` and carried as the envelope's optional `context` so the backend
|
|
1396
1404
|
// always sees the visitor's latest context as they navigate.
|
|
@@ -1408,27 +1416,27 @@ var AgentTransport = class {
|
|
|
1408
1416
|
this.pageContext = pageContext;
|
|
1409
1417
|
}
|
|
1410
1418
|
/**
|
|
1411
|
-
* Seed the visitor +
|
|
1412
|
-
* `
|
|
1413
|
-
* with `
|
|
1414
|
-
* `
|
|
1419
|
+
* Seed the visitor + conversation identity from persistence BEFORE the first
|
|
1420
|
+
* `startConversation` resolves. A mount-time `resumeStream()` runs in parallel
|
|
1421
|
+
* with `startConversation`, so without this its envelope would carry no
|
|
1422
|
+
* `conversationId` and the resume GET couldn't identify the thread. `startConversation`
|
|
1415
1423
|
* later overwrites these with the server's authoritative ids (rebind-safe).
|
|
1416
1424
|
*/
|
|
1417
|
-
primeIdentity(visitorId,
|
|
1425
|
+
primeIdentity(visitorId, conversationId) {
|
|
1418
1426
|
if (visitorId) this.visitorId = visitorId;
|
|
1419
|
-
if (
|
|
1427
|
+
if (conversationId) this.conversationId = conversationId;
|
|
1420
1428
|
}
|
|
1421
1429
|
/** Build the per-request envelope from the current transport state. */
|
|
1422
1430
|
envelope() {
|
|
1423
1431
|
const out = {};
|
|
1424
1432
|
if (this.visitorId) out.visitorId = this.visitorId;
|
|
1425
|
-
if (this.
|
|
1433
|
+
if (this.conversationId) out.conversationId = this.conversationId;
|
|
1426
1434
|
const context = encodeContext(this.userContext, this.pageContext);
|
|
1427
1435
|
if (context) out[CONTEXT_PARAM] = context;
|
|
1428
1436
|
return out;
|
|
1429
1437
|
}
|
|
1430
1438
|
/** Merge the envelope into a JSON body (POSTs). Explicit body fields win — e.g.
|
|
1431
|
-
* start-
|
|
1439
|
+
* start-conversation's client-proposed ids, or a mark-read target conversation that
|
|
1432
1440
|
* differs from the active one. */
|
|
1433
1441
|
withEnvelope(body) {
|
|
1434
1442
|
return { ...this.envelope(), ...body };
|
|
@@ -1439,8 +1447,8 @@ var AgentTransport = class {
|
|
|
1439
1447
|
return form;
|
|
1440
1448
|
}
|
|
1441
1449
|
/** Resolve a path to its full URL and append the envelope as query params (GETs).
|
|
1442
|
-
* Won't clobber params the caller already set (e.g. a `
|
|
1443
|
-
* selector on load-
|
|
1450
|
+
* Won't clobber params the caller already set (e.g. a `conversationId` resource
|
|
1451
|
+
* selector on load-conversation). */
|
|
1444
1452
|
withEnvelopeQuery(urlOrPath) {
|
|
1445
1453
|
const url = new URL(this.url(urlOrPath));
|
|
1446
1454
|
for (const [key, value] of Object.entries(this.envelope())) {
|
|
@@ -1449,23 +1457,31 @@ var AgentTransport = class {
|
|
|
1449
1457
|
return url.toString();
|
|
1450
1458
|
}
|
|
1451
1459
|
/** One-shot runtime bootstrap. Called once after the widget mounts. */
|
|
1452
|
-
async
|
|
1453
|
-
log4.debug("
|
|
1454
|
-
|
|
1455
|
-
|
|
1460
|
+
async startConversation(body) {
|
|
1461
|
+
log4.debug("startConversation \u2192", {
|
|
1462
|
+
visitorId: body.visitorId,
|
|
1463
|
+
conversationId: body.conversationId,
|
|
1464
|
+
locale: body.locale
|
|
1465
|
+
});
|
|
1466
|
+
const res = await this.postJson(
|
|
1467
|
+
DEFAULT_PATHS.startConversation,
|
|
1468
|
+
body,
|
|
1469
|
+
"startConversation"
|
|
1470
|
+
);
|
|
1471
|
+
log4.debug("startConversation \u2190", {
|
|
1456
1472
|
visitorId: res.visitorId,
|
|
1457
|
-
|
|
1473
|
+
conversationId: res.conversationId,
|
|
1458
1474
|
canContinue: res.canContinue,
|
|
1459
1475
|
hasMessages: !!res.messages?.length,
|
|
1460
1476
|
hasWelcome: !!res.welcome,
|
|
1461
1477
|
hasConfig: !!res.config,
|
|
1462
1478
|
rebind: res.rebind
|
|
1463
1479
|
});
|
|
1464
|
-
if (!
|
|
1465
|
-
log4.warn("
|
|
1480
|
+
if (!isStartConversationResponseShape(res)) {
|
|
1481
|
+
log4.warn("startConversation response did not match expected shape; using raw response", { response: res });
|
|
1466
1482
|
}
|
|
1467
1483
|
this.visitorId = res.visitorId ?? body.visitorId;
|
|
1468
|
-
this.
|
|
1484
|
+
this.conversationId = res.conversationId;
|
|
1469
1485
|
return res;
|
|
1470
1486
|
}
|
|
1471
1487
|
/** Upload a file attachment. Returns the `{id, url}` the backend assigns. */
|
|
@@ -1490,45 +1506,45 @@ var AgentTransport = class {
|
|
|
1490
1506
|
log4.debug("transcribe \u2190", { textLen: res.text.length });
|
|
1491
1507
|
return res;
|
|
1492
1508
|
}
|
|
1493
|
-
async
|
|
1494
|
-
const url = new URL(this.url(DEFAULT_PATHS.
|
|
1509
|
+
async listConversations(params = {}) {
|
|
1510
|
+
const url = new URL(this.url(DEFAULT_PATHS.listConversations));
|
|
1495
1511
|
if (params.visitorId) url.searchParams.set("visitorId", params.visitorId);
|
|
1496
1512
|
if (params.limit) url.searchParams.set("limit", String(params.limit));
|
|
1497
1513
|
if (params.cursor) url.searchParams.set("cursor", params.cursor);
|
|
1498
|
-
log4.debug("
|
|
1514
|
+
log4.debug("listConversations \u2192", {
|
|
1499
1515
|
visitorId: params.visitorId ?? this.visitorId,
|
|
1500
1516
|
limit: params.limit,
|
|
1501
1517
|
cursor: params.cursor
|
|
1502
1518
|
});
|
|
1503
|
-
const res = await this.getJson(url.toString(), "
|
|
1504
|
-
const
|
|
1505
|
-
log4.debug("
|
|
1519
|
+
const res = await this.getJson(url.toString(), "listConversations");
|
|
1520
|
+
const conversations = res.conversations ?? [];
|
|
1521
|
+
log4.debug("listConversations \u2190", { count: conversations.length, nextCursor: res.nextCursor });
|
|
1506
1522
|
return {
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
title:
|
|
1510
|
-
lastMessageAt:
|
|
1511
|
-
preview:
|
|
1512
|
-
canContinue:
|
|
1513
|
-
unreadCount:
|
|
1523
|
+
conversations: conversations.map((conversation) => ({
|
|
1524
|
+
conversationId: conversation.conversationId,
|
|
1525
|
+
title: conversation.title,
|
|
1526
|
+
lastMessageAt: conversation.lastMessageAt,
|
|
1527
|
+
preview: conversation.preview,
|
|
1528
|
+
canContinue: conversation.canContinue,
|
|
1529
|
+
unreadCount: conversation.unreadCount
|
|
1514
1530
|
})),
|
|
1515
1531
|
nextCursor: res.nextCursor
|
|
1516
1532
|
};
|
|
1517
1533
|
}
|
|
1518
|
-
async
|
|
1534
|
+
async loadConversation(conversationId) {
|
|
1519
1535
|
const url = new URL(this.url(DEFAULT_PATHS.listMessages));
|
|
1520
|
-
url.searchParams.set("
|
|
1521
|
-
log4.debug("
|
|
1522
|
-
const res = await this.getJson(url.toString(), "
|
|
1536
|
+
url.searchParams.set("conversationId", conversationId);
|
|
1537
|
+
log4.debug("loadConversation \u2192", { conversationId, visitorId: this.visitorId });
|
|
1538
|
+
const res = await this.getJson(url.toString(), "loadConversation");
|
|
1523
1539
|
const messages = res.messages ?? [];
|
|
1524
|
-
log4.debug("
|
|
1525
|
-
|
|
1540
|
+
log4.debug("loadConversation \u2190", {
|
|
1541
|
+
conversationId: res.conversationId,
|
|
1526
1542
|
canContinue: res.canContinue,
|
|
1527
1543
|
messageCount: messages.length,
|
|
1528
1544
|
hasSuggestions: !!res.suggestions
|
|
1529
1545
|
});
|
|
1530
1546
|
return {
|
|
1531
|
-
|
|
1547
|
+
conversationId: res.conversationId,
|
|
1532
1548
|
canContinue: res.canContinue ?? true,
|
|
1533
1549
|
messages,
|
|
1534
1550
|
agent: res.agent,
|
|
@@ -1537,15 +1553,15 @@ var AgentTransport = class {
|
|
|
1537
1553
|
}
|
|
1538
1554
|
/**
|
|
1539
1555
|
* Mark a conversation read up to its latest message. Fire-and-forget — the
|
|
1540
|
-
* server records `lastReadAt` and clears that
|
|
1541
|
-
* next `/
|
|
1556
|
+
* server records `lastReadAt` and clears that conversation's `unreadCount` on the
|
|
1557
|
+
* next `/conversations`. A failure is non-fatal (the badge just lingers until the
|
|
1542
1558
|
* next sync), so callers don't await this.
|
|
1543
1559
|
*/
|
|
1544
|
-
async markRead(
|
|
1545
|
-
if (!this.visitorId || !
|
|
1546
|
-
log4.debug("markRead \u2192", {
|
|
1560
|
+
async markRead(conversationId) {
|
|
1561
|
+
if (!this.visitorId || !conversationId) return;
|
|
1562
|
+
log4.debug("markRead \u2192", { conversationId, visitorId: this.visitorId });
|
|
1547
1563
|
try {
|
|
1548
|
-
await this.postJson(DEFAULT_PATHS.markRead, {
|
|
1564
|
+
await this.postJson(DEFAULT_PATHS.markRead, { conversationId }, "markRead");
|
|
1549
1565
|
} catch (err) {
|
|
1550
1566
|
log4.debug("markRead failed (non-fatal)", { err });
|
|
1551
1567
|
}
|
|
@@ -1571,7 +1587,7 @@ var AgentTransport = class {
|
|
|
1571
1587
|
async saveUserPrefs(userPrefs) {
|
|
1572
1588
|
log4.debug("saveUserPrefs \u2192", {
|
|
1573
1589
|
visitorId: this.visitorId,
|
|
1574
|
-
|
|
1590
|
+
conversationId: this.conversationId,
|
|
1575
1591
|
settingsKeys: Object.keys(userPrefs)
|
|
1576
1592
|
});
|
|
1577
1593
|
const res = await this.postJson(DEFAULT_PATHS.updateSettings, { userPrefs }, "saveUserPrefs");
|
|
@@ -1589,7 +1605,7 @@ var AgentTransport = class {
|
|
|
1589
1605
|
}
|
|
1590
1606
|
/**
|
|
1591
1607
|
* Record a completed form (intake, CSAT, claim, …). Fire-and-forget — the
|
|
1592
|
-
* record is captured even if the visitor never sends a message. `
|
|
1608
|
+
* record is captured even if the visitor never sends a message. `conversationId`,
|
|
1593
1609
|
* `formId`, and `trigger` are explicit so the backend can tie + route;
|
|
1594
1610
|
* `visitorId` + context ride the envelope. A failure (e.g. 404 on a backend
|
|
1595
1611
|
* that doesn't implement the endpoint) is non-fatal, so callers don't await.
|
|
@@ -1604,7 +1620,7 @@ var AgentTransport = class {
|
|
|
1604
1620
|
}
|
|
1605
1621
|
sendMessage(body) {
|
|
1606
1622
|
log4.debug("message \u2192", {
|
|
1607
|
-
|
|
1623
|
+
conversationId: body.conversationId,
|
|
1608
1624
|
visitorId: body.visitorId,
|
|
1609
1625
|
messageCount: body.messages.length,
|
|
1610
1626
|
trigger: body.trigger,
|
|
@@ -1614,16 +1630,16 @@ var AgentTransport = class {
|
|
|
1614
1630
|
const ctrl = new AbortController();
|
|
1615
1631
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1616
1632
|
const iter = this.runStream(body, ctrl, seenIds);
|
|
1617
|
-
const cancel = () => this.cancelStream(ctrl, body.
|
|
1633
|
+
const cancel = () => this.cancelStream(ctrl, body.conversationId);
|
|
1618
1634
|
return { iter, cancel };
|
|
1619
1635
|
}
|
|
1620
1636
|
/**
|
|
1621
1637
|
* Re-attach to an in-flight reply on a cold page load / refresh.
|
|
1622
1638
|
*
|
|
1623
1639
|
* UNCONDITIONAL by design — the caller runs this in parallel with
|
|
1624
|
-
* `
|
|
1640
|
+
* `startConversation`, never gated on whether there are persisted messages. If
|
|
1625
1641
|
* the user refreshed while the assistant was still streaming, the
|
|
1626
|
-
* `
|
|
1642
|
+
* `startConversation` reply carries no messages (the turn isn't persisted until
|
|
1627
1643
|
* it finishes) and THIS is the channel that resumes the live reply. When
|
|
1628
1644
|
* nothing is in flight the server answers 204 and the handle yields nothing
|
|
1629
1645
|
* (the common case — no bubble is created).
|
|
@@ -1650,7 +1666,7 @@ var AgentTransport = class {
|
|
|
1650
1666
|
* - after a POST /stream-message drops mid-reply (`immediate=false` — back
|
|
1651
1667
|
* off first, the reply may still be spinning up server-side);
|
|
1652
1668
|
* - on a cold page load / refresh (`immediate=true` — hit it at once, in
|
|
1653
|
-
* parallel with start-
|
|
1669
|
+
* parallel with start-conversation, so a reply that was streaming when the
|
|
1654
1670
|
* user reloaded keeps flowing).
|
|
1655
1671
|
*
|
|
1656
1672
|
* The endpoint ALWAYS opens a 200 SSE stream (mirrors the AI SDK
|
|
@@ -1659,7 +1675,7 @@ var AgentTransport = class {
|
|
|
1659
1675
|
* nothing ever started) — closes an EMPTY stream. So "nothing to resume" is
|
|
1660
1676
|
* signalled by a segment that ends without a terminal chunk AND surfaced no
|
|
1661
1677
|
* NEW events — not by a status code. We stop gracefully there; the completed
|
|
1662
|
-
* turn comes from the DB via start-
|
|
1678
|
+
* turn comes from the DB via start-conversation / list-messages.
|
|
1663
1679
|
*
|
|
1664
1680
|
* Returns (no throw) on a terminal chunk, an empty/no-new-events segment, or
|
|
1665
1681
|
* a 204 / non-OK (a backend that signals "nothing" by status, or lacks the
|
|
@@ -1725,11 +1741,11 @@ var AgentTransport = class {
|
|
|
1725
1741
|
return false;
|
|
1726
1742
|
}
|
|
1727
1743
|
/** Abort + fire-and-forget POST to `/ai/agent/cancel-stream`. Idempotent. */
|
|
1728
|
-
cancelStream(ctrl,
|
|
1744
|
+
cancelStream(ctrl, conversationId) {
|
|
1729
1745
|
if (ctrl.signal.aborted) return;
|
|
1730
|
-
log4.debug("cancel stream", {
|
|
1746
|
+
log4.debug("cancel stream", { conversationId, visitorId: this.visitorId });
|
|
1731
1747
|
ctrl.abort();
|
|
1732
|
-
if (!this.visitorId || !
|
|
1748
|
+
if (!this.visitorId || !conversationId) return;
|
|
1733
1749
|
this.fetchImpl(this.url(DEFAULT_PATHS.cancelStream), {
|
|
1734
1750
|
method: "POST",
|
|
1735
1751
|
credentials: "omit",
|
|
@@ -1754,7 +1770,7 @@ var AgentTransport = class {
|
|
|
1754
1770
|
yield* parseChatStream(res, signal7);
|
|
1755
1771
|
}
|
|
1756
1772
|
/**
|
|
1757
|
-
* Resume URL: `GET /stream-resume` with the envelope (visitorId /
|
|
1773
|
+
* Resume URL: `GET /stream-resume` with the envelope (visitorId / conversationId /
|
|
1758
1774
|
* context) as query params plus `resumeAt` — the count of events already
|
|
1759
1775
|
* consumed, so the server knows where the client is. The server replies 200
|
|
1760
1776
|
* (SSE, still in-flight) or 204 (nothing to resume).
|
|
@@ -1765,7 +1781,7 @@ var AgentTransport = class {
|
|
|
1765
1781
|
return url.toString();
|
|
1766
1782
|
}
|
|
1767
1783
|
// JSON requests are idempotent (reads, or full-snapshot writes like
|
|
1768
|
-
// update-settings / mark-read / start-
|
|
1784
|
+
// update-settings / mark-read / start-conversation), so they auto-retry transient
|
|
1769
1785
|
// failures. The message POST is NOT in here — re-sending could duplicate the
|
|
1770
1786
|
// reply, so it surfaces an error for the user to retry (see `openMessageStream`).
|
|
1771
1787
|
async postJson(path, body, label) {
|
|
@@ -1849,10 +1865,10 @@ function extensionFor(mimeType) {
|
|
|
1849
1865
|
if (mimeType.includes("wav")) return "wav";
|
|
1850
1866
|
return "bin";
|
|
1851
1867
|
}
|
|
1852
|
-
function
|
|
1868
|
+
function isStartConversationResponseShape(raw) {
|
|
1853
1869
|
if (!raw || typeof raw !== "object") return false;
|
|
1854
1870
|
const r = raw;
|
|
1855
|
-
return typeof r.visitorId === "string" && typeof r.
|
|
1871
|
+
return typeof r.visitorId === "string" && typeof r.conversationId === "string" && typeof r.canContinue === "boolean";
|
|
1856
1872
|
}
|
|
1857
1873
|
|
|
1858
1874
|
// src/stream/messages.ts
|
|
@@ -2175,7 +2191,7 @@ var log6 = logger.scope("persistence");
|
|
|
2175
2191
|
function createPersistence(widgetId, storage = defaultStorage) {
|
|
2176
2192
|
const prefix = `${BRAND.cssPrefix}.${widgetId}`;
|
|
2177
2193
|
const KEY_VISITOR = `${prefix}.visitorId`;
|
|
2178
|
-
const
|
|
2194
|
+
const KEY_CONVERSATION = `${prefix}.conversationId`;
|
|
2179
2195
|
const KEY_USER_PREFS = `${prefix}.userPrefs`;
|
|
2180
2196
|
const KEY_PANEL_OPEN = `${prefix}.panelOpen`;
|
|
2181
2197
|
const KEY_PANEL_SIZE = `${prefix}.panelSize`;
|
|
@@ -2195,13 +2211,13 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2195
2211
|
log6.debug("setVisitorId (rebind)", { id, widgetId });
|
|
2196
2212
|
storage.set(KEY_VISITOR, id);
|
|
2197
2213
|
},
|
|
2198
|
-
|
|
2199
|
-
return storage.get(
|
|
2214
|
+
loadConversationId() {
|
|
2215
|
+
return storage.get(KEY_CONVERSATION) ?? void 0;
|
|
2200
2216
|
},
|
|
2201
|
-
|
|
2202
|
-
log6.trace("
|
|
2203
|
-
if (id) storage.set(
|
|
2204
|
-
else storage.remove(
|
|
2217
|
+
saveConversationId(id) {
|
|
2218
|
+
log6.trace("saveConversationId", { id, widgetId });
|
|
2219
|
+
if (id) storage.set(KEY_CONVERSATION, id);
|
|
2220
|
+
else storage.remove(KEY_CONVERSATION);
|
|
2205
2221
|
},
|
|
2206
2222
|
loadUserPrefs() {
|
|
2207
2223
|
const raw = storage.get(KEY_USER_PREFS);
|
|
@@ -2285,8 +2301,8 @@ function createPersistence(widgetId, storage = defaultStorage) {
|
|
|
2285
2301
|
log6.warn("saveFormDone serialise failed", { error });
|
|
2286
2302
|
}
|
|
2287
2303
|
},
|
|
2288
|
-
|
|
2289
|
-
storage.remove(
|
|
2304
|
+
clearConversation() {
|
|
2305
|
+
storage.remove(KEY_CONVERSATION);
|
|
2290
2306
|
}
|
|
2291
2307
|
};
|
|
2292
2308
|
return persistence;
|
|
@@ -2468,7 +2484,7 @@ var DEDUP_WINDOW_MS = 100;
|
|
|
2468
2484
|
var FeedbackBus = class {
|
|
2469
2485
|
constructor(sound, haptics) {
|
|
2470
2486
|
/**
|
|
2471
|
-
* User/
|
|
2487
|
+
* User/conversation mute state. Reactive — UI subscribes to drive the toggle
|
|
2472
2488
|
* icon, and the App layer subscribes to persist changes via the unified
|
|
2473
2489
|
* `Persistence` layer.
|
|
2474
2490
|
*/
|
|
@@ -2786,7 +2802,7 @@ var TID = {
|
|
|
2786
2802
|
historyPane: `${p2}-history-pane`,
|
|
2787
2803
|
/** History pane back / close button. */
|
|
2788
2804
|
historyBack: `${p2}-history-back`,
|
|
2789
|
-
/** Single history list row — suffix `-{
|
|
2805
|
+
/** Single history list row — suffix `-{conversationId}` at the JSX site. */
|
|
2790
2806
|
historyItem: `${p2}-history-item`,
|
|
2791
2807
|
// ── Page-mode sidebar ───────────────────────────────────────────
|
|
2792
2808
|
/** Page-mode sidebar (full-bleed left rail). */
|
|
@@ -2795,7 +2811,7 @@ var TID = {
|
|
|
2795
2811
|
sidebarToggle: `${p2}-sidebar-toggle`,
|
|
2796
2812
|
/** Sidebar "New chat" button. */
|
|
2797
2813
|
sidebarNewChat: `${p2}-sidebar-new-chat`,
|
|
2798
|
-
/** Sidebar history row — suffix `-{
|
|
2814
|
+
/** Sidebar history row — suffix `-{conversationId}` at the JSX site. */
|
|
2799
2815
|
sidebarItem: `${p2}-sidebar-item`,
|
|
2800
2816
|
// ── Messenger modules ───────────────────────────────────────────
|
|
2801
2817
|
/** Messenger-home surface root. */
|
|
@@ -4892,15 +4908,15 @@ function bucketFor(nowMs, iso) {
|
|
|
4892
4908
|
if (diffDays < 7) return "lastWeek";
|
|
4893
4909
|
return "older";
|
|
4894
4910
|
}
|
|
4895
|
-
function groupByBucket(nowMs,
|
|
4911
|
+
function groupByBucket(nowMs, conversations) {
|
|
4896
4912
|
const buckets = /* @__PURE__ */ new Map();
|
|
4897
|
-
for (const chat of
|
|
4913
|
+
for (const chat of conversations) {
|
|
4898
4914
|
const b = bucketFor(nowMs, chat.lastMessageAt);
|
|
4899
4915
|
const list = buckets.get(b);
|
|
4900
4916
|
if (list) list.push(chat);
|
|
4901
4917
|
else buckets.set(b, [chat]);
|
|
4902
4918
|
}
|
|
4903
|
-
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b,
|
|
4919
|
+
return HISTORY_BUCKETS.filter((b) => buckets.has(b)).map((b) => ({ bucket: b, conversations: buckets.get(b) }));
|
|
4904
4920
|
}
|
|
4905
4921
|
function startOfDay(ms) {
|
|
4906
4922
|
const d = new Date(ms);
|
|
@@ -4920,16 +4936,16 @@ var BUCKET_TO_STRING = {
|
|
|
4920
4936
|
function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }) {
|
|
4921
4937
|
const p33 = BRAND.cssPrefix;
|
|
4922
4938
|
const [state, setState] = useState7("loading");
|
|
4923
|
-
const [
|
|
4939
|
+
const [conversations, setChats] = useState7([]);
|
|
4924
4940
|
useEffect9(() => {
|
|
4925
4941
|
let cancelled = false;
|
|
4926
|
-
transport.
|
|
4942
|
+
transport.listConversations({ visitorId }).then((res) => {
|
|
4927
4943
|
if (cancelled) return;
|
|
4928
|
-
setChats(res.
|
|
4944
|
+
setChats(res.conversations ?? []);
|
|
4929
4945
|
setState("loaded");
|
|
4930
4946
|
}).catch((err) => {
|
|
4931
4947
|
if (cancelled) return;
|
|
4932
|
-
log11.warn("
|
|
4948
|
+
log11.warn("listConversations failed", { err });
|
|
4933
4949
|
setState("error");
|
|
4934
4950
|
});
|
|
4935
4951
|
return () => {
|
|
@@ -4946,17 +4962,17 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4946
4962
|
newChatButton
|
|
4947
4963
|
] });
|
|
4948
4964
|
}
|
|
4949
|
-
if (state === "error" ||
|
|
4965
|
+
if (state === "error" || conversations.length === 0) {
|
|
4950
4966
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4951
4967
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-empty`, children: strings.historyEmpty }),
|
|
4952
4968
|
newChatButton
|
|
4953
4969
|
] });
|
|
4954
4970
|
}
|
|
4955
|
-
const groups = groupByBucket(Date.now(),
|
|
4971
|
+
const groups = groupByBucket(Date.now(), conversations);
|
|
4956
4972
|
return /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4957
4973
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history`, role: "list", children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { class: `${p33}-history-group`, children: [
|
|
4958
4974
|
/* @__PURE__ */ jsx18("div", { class: `${p33}-history-heading`, children: strings[BUCKET_TO_STRING[group.bucket]] }),
|
|
4959
|
-
group.
|
|
4975
|
+
group.conversations.map((chat) => /* @__PURE__ */ jsxs15(
|
|
4960
4976
|
"button",
|
|
4961
4977
|
{
|
|
4962
4978
|
type: "button",
|
|
@@ -4964,13 +4980,13 @@ function ConversationList({ transport, strings, visitorId, onSelect, onNewChat }
|
|
|
4964
4980
|
class: `${p33}-history-item`,
|
|
4965
4981
|
onClick: () => onSelect(chat),
|
|
4966
4982
|
"data-closed": chat.canContinue ? void 0 : "true",
|
|
4967
|
-
"data-testid": tid(TID.historyItem, chat.
|
|
4983
|
+
"data-testid": tid(TID.historyItem, chat.conversationId),
|
|
4968
4984
|
children: [
|
|
4969
4985
|
/* @__PURE__ */ jsx18("span", { class: `${p33}-history-title`, children: chat.title }),
|
|
4970
4986
|
chat.preview ? /* @__PURE__ */ jsx18("span", { class: `${p33}-history-preview`, children: chat.preview }) : null
|
|
4971
4987
|
]
|
|
4972
4988
|
},
|
|
4973
|
-
chat.
|
|
4989
|
+
chat.conversationId
|
|
4974
4990
|
))
|
|
4975
4991
|
] }, group.bucket)) }),
|
|
4976
4992
|
newChatButton
|
|
@@ -5140,7 +5156,7 @@ function PanelContent(props2) {
|
|
|
5140
5156
|
transport,
|
|
5141
5157
|
strings: s,
|
|
5142
5158
|
visitorId,
|
|
5143
|
-
onSelect: (chat) => onSelectHistoryChat(chat.
|
|
5159
|
+
onSelect: (chat) => onSelectHistoryChat(chat.conversationId),
|
|
5144
5160
|
onNewChat
|
|
5145
5161
|
}
|
|
5146
5162
|
) : /* @__PURE__ */ jsxs16(Fragment3, { children: [
|
|
@@ -5243,10 +5259,11 @@ function useForms(deps) {
|
|
|
5243
5259
|
}
|
|
5244
5260
|
function createController(depsRef) {
|
|
5245
5261
|
const activeForm = signal5(null);
|
|
5246
|
-
const
|
|
5262
|
+
const conversationDone = /* @__PURE__ */ new Set();
|
|
5263
|
+
const conversationKey = (formId) => `${depsRef.current.conversationId() ?? ""}:${formId}`;
|
|
5247
5264
|
const isDone = (form) => {
|
|
5248
5265
|
if (form.frequency === "always") return false;
|
|
5249
|
-
if (form.frequency === "
|
|
5266
|
+
if (form.frequency === "conversation") return conversationDone.has(conversationKey(form.id));
|
|
5250
5267
|
return form.id in depsRef.current.persistence.loadFormsDone();
|
|
5251
5268
|
};
|
|
5252
5269
|
const fire = (kind, param) => {
|
|
@@ -5269,7 +5286,7 @@ function createController(depsRef) {
|
|
|
5269
5286
|
if (!active) return;
|
|
5270
5287
|
activeForm.value = null;
|
|
5271
5288
|
const { form, trigger } = active;
|
|
5272
|
-
if (form.frequency === "
|
|
5289
|
+
if (form.frequency === "conversation") conversationDone.add(conversationKey(form.id));
|
|
5273
5290
|
else if (form.frequency !== "always") depsRef.current.persistence.saveFormDone(form.id);
|
|
5274
5291
|
depsRef.current.onComplete(form, trigger, values, skipped);
|
|
5275
5292
|
};
|
|
@@ -5671,7 +5688,7 @@ function HomeRoot(props2) {
|
|
|
5671
5688
|
useEffect12(() => {
|
|
5672
5689
|
if (!config.showRecentMessages) return;
|
|
5673
5690
|
let cancelled = false;
|
|
5674
|
-
transport.
|
|
5691
|
+
transport.listConversations({ limit: 1 }).then((res) => !cancelled && setRecent(res.conversations?.[0] ?? null)).catch((err) => !cancelled && log13.warn("listConversations (home) failed", { err }));
|
|
5675
5692
|
return () => {
|
|
5676
5693
|
cancelled = true;
|
|
5677
5694
|
};
|
|
@@ -5710,7 +5727,7 @@ function HomeRoot(props2) {
|
|
|
5710
5727
|
onActivate: () => nav.switchToLayout("help")
|
|
5711
5728
|
}
|
|
5712
5729
|
) : null,
|
|
5713
|
-
recent ? /* @__PURE__ */ jsx30(HomeCard, { onClick: () => nav.
|
|
5730
|
+
recent ? /* @__PURE__ */ jsx30(HomeCard, { onClick: () => nav.selectConversation(recent.conversationId), testid: TID.homeRecent, children: /* @__PURE__ */ jsxs24("div", { class: `${p25}-home-recent-row`, "data-unread": (recent.unreadCount ?? 0) > 0 ? "true" : void 0, children: [
|
|
5714
5731
|
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-avatar`, "aria-hidden": "true", children: /* @__PURE__ */ jsx30(BubblesIcon, {}) }),
|
|
5715
5732
|
/* @__PURE__ */ jsxs24("span", { class: `${p25}-home-recent-body`, children: [
|
|
5716
5733
|
/* @__PURE__ */ jsx30("span", { class: `${p25}-home-recent-title`, children: recent.title }),
|
|
@@ -5943,8 +5960,8 @@ function MessengerHome({
|
|
|
5943
5960
|
enabledModules,
|
|
5944
5961
|
nav,
|
|
5945
5962
|
unreadCount,
|
|
5946
|
-
|
|
5947
|
-
|
|
5963
|
+
onSelectConversation,
|
|
5964
|
+
onStartNewConversation,
|
|
5948
5965
|
onSetPanelSize
|
|
5949
5966
|
}) {
|
|
5950
5967
|
const options = panelProps.options;
|
|
@@ -5993,8 +6010,8 @@ function MessengerHome({
|
|
|
5993
6010
|
const target = enabledModules.find((m) => m.layout === layout);
|
|
5994
6011
|
if (target) nav.switchTab(target.id);
|
|
5995
6012
|
},
|
|
5996
|
-
|
|
5997
|
-
|
|
6013
|
+
selectConversation: onSelectConversation,
|
|
6014
|
+
startNewConversation: onStartNewConversation
|
|
5998
6015
|
};
|
|
5999
6016
|
const screenProps = (module) => ({
|
|
6000
6017
|
options,
|
|
@@ -6182,7 +6199,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6182
6199
|
const [activeThemeMode, setActiveThemeMode] = useState13(
|
|
6183
6200
|
() => initialSettings.themeMode ?? options.themeMode
|
|
6184
6201
|
);
|
|
6185
|
-
const
|
|
6202
|
+
const conversationIdSig = useSignal2(persistence.loadConversationId());
|
|
6186
6203
|
const messagesSig = useSignal2([]);
|
|
6187
6204
|
const unreadCountSig = useSignal2(0);
|
|
6188
6205
|
const [loadingMessages, setLoadingMessages] = useState13(false);
|
|
@@ -6204,7 +6221,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6204
6221
|
const homeNav = homeNavRef.current;
|
|
6205
6222
|
const chatTabIdRef = useRef9(void 0);
|
|
6206
6223
|
chatTabIdRef.current = chatTabId();
|
|
6207
|
-
const [
|
|
6224
|
+
const [conversationReady, setConversationReady] = useState13(false);
|
|
6208
6225
|
const isInlineLike = options.mode === "standalone" || options.mode === "inline";
|
|
6209
6226
|
const initialPanelRef = useRef9(
|
|
6210
6227
|
resolveInitialPanelState(options, currentViewportWidth(), persistence.loadPanelOpen(), persistence.loadPanelSize())
|
|
@@ -6284,7 +6301,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6284
6301
|
setPanelSize(pickInitialPanelSize(options.mode, options.size, currentViewportWidth()));
|
|
6285
6302
|
}, [options.mode, options.size, persistence]);
|
|
6286
6303
|
useEffect17(() => {
|
|
6287
|
-
if (!
|
|
6304
|
+
if (!conversationReady || initialPanelApplied.current) return;
|
|
6288
6305
|
initialPanelApplied.current = true;
|
|
6289
6306
|
const state = resolveInitialPanelState(
|
|
6290
6307
|
options,
|
|
@@ -6294,12 +6311,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6294
6311
|
);
|
|
6295
6312
|
setIsOpen(state.panelOpen);
|
|
6296
6313
|
setPanelSize(state.panelSize);
|
|
6297
|
-
}, [
|
|
6314
|
+
}, [conversationReady, options, persistence]);
|
|
6298
6315
|
const homeNavSeeded = useRef9(false);
|
|
6299
6316
|
const resumeActiveRef = useRef9(false);
|
|
6300
6317
|
const resumeBubbleRef = useRef9(null);
|
|
6301
6318
|
useEffect17(() => {
|
|
6302
|
-
if (!
|
|
6319
|
+
if (!conversationReady || homeNavSeeded.current) return;
|
|
6303
6320
|
homeNavSeeded.current = true;
|
|
6304
6321
|
if (resumeActiveRef.current) {
|
|
6305
6322
|
const chatTab = chatTabIdRef.current;
|
|
@@ -6307,7 +6324,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6307
6324
|
return;
|
|
6308
6325
|
}
|
|
6309
6326
|
homeNav.reset(landingTab());
|
|
6310
|
-
}, [
|
|
6327
|
+
}, [conversationReady]);
|
|
6311
6328
|
const playWelcome = useCallback6(
|
|
6312
6329
|
(welcomeMessages) => {
|
|
6313
6330
|
if (!welcomeMessages || welcomeMessages.length === 0) return;
|
|
@@ -6326,21 +6343,21 @@ function App({ options, hostElement, bus }) {
|
|
|
6326
6343
|
[messagesSig, options.welcome]
|
|
6327
6344
|
);
|
|
6328
6345
|
const connectGenRef = useRef9(0);
|
|
6329
|
-
const
|
|
6346
|
+
const runStartConversation = useCallback6(
|
|
6330
6347
|
async ({ newConversation }) => {
|
|
6331
6348
|
const myGen = ++connectGenRef.current;
|
|
6332
6349
|
const isStale = () => myGen !== connectGenRef.current;
|
|
6333
|
-
const persistedChatId =
|
|
6334
|
-
const
|
|
6335
|
-
if (
|
|
6336
|
-
|
|
6337
|
-
persistence.
|
|
6350
|
+
const persistedChatId = conversationIdSig.value;
|
|
6351
|
+
const conversationId = newConversation || !persistedChatId ? uuid7() : persistedChatId;
|
|
6352
|
+
if (conversationId !== persistedChatId) {
|
|
6353
|
+
conversationIdSig.value = conversationId;
|
|
6354
|
+
persistence.saveConversationId(conversationId);
|
|
6338
6355
|
}
|
|
6339
6356
|
let res;
|
|
6340
6357
|
try {
|
|
6341
|
-
res = await transport.
|
|
6358
|
+
res = await transport.startConversation({
|
|
6342
6359
|
visitorId,
|
|
6343
|
-
|
|
6360
|
+
conversationId,
|
|
6344
6361
|
userPrefs: persistence.loadUserPrefs(),
|
|
6345
6362
|
locale: options.locale
|
|
6346
6363
|
});
|
|
@@ -6348,7 +6365,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6348
6365
|
if (isStale()) return;
|
|
6349
6366
|
bus.emit("error", err);
|
|
6350
6367
|
options.onError?.(err);
|
|
6351
|
-
if (!newConversation)
|
|
6368
|
+
if (!newConversation) setConversationReady(true);
|
|
6352
6369
|
return;
|
|
6353
6370
|
}
|
|
6354
6371
|
if (isStale()) return;
|
|
@@ -6362,12 +6379,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6362
6379
|
reason: res.rebind?.visitorId
|
|
6363
6380
|
});
|
|
6364
6381
|
}
|
|
6365
|
-
if (res.
|
|
6366
|
-
log16.info("
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6382
|
+
if (res.conversationId && res.conversationId !== conversationId) {
|
|
6383
|
+
log16.info("conversation rebound", {
|
|
6384
|
+
previous: conversationId,
|
|
6385
|
+
current: res.conversationId,
|
|
6386
|
+
reason: res.rebind?.conversationId
|
|
6387
|
+
});
|
|
6388
|
+
bus.emit("conversationRebound", {
|
|
6389
|
+
previous: conversationId,
|
|
6390
|
+
current: res.conversationId,
|
|
6391
|
+
reason: res.rebind?.conversationId
|
|
6371
6392
|
});
|
|
6372
6393
|
}
|
|
6373
6394
|
if (res.agent) setAgent(res.agent);
|
|
@@ -6384,36 +6405,40 @@ function App({ options, hostElement, bus }) {
|
|
|
6384
6405
|
if (res.userPrefs.soundMuted !== void 0) feedback.setMuted(res.userPrefs.soundMuted);
|
|
6385
6406
|
if (res.userPrefs.themeMode) setActiveThemeMode(res.userPrefs.themeMode);
|
|
6386
6407
|
}
|
|
6387
|
-
const isResume = !newConversation && persistedChatId && res.
|
|
6408
|
+
const isResume = !newConversation && persistedChatId && res.conversationId === persistedChatId;
|
|
6388
6409
|
if (isResume) {
|
|
6389
6410
|
setLoadingMessages(true);
|
|
6390
6411
|
try {
|
|
6391
|
-
const chat = res.messages?.length ? {
|
|
6412
|
+
const chat = res.messages?.length ? { conversationId: persistedChatId, canContinue: res.canContinue ?? true, messages: res.messages } : await transport.loadConversation(persistedChatId);
|
|
6392
6413
|
if (isStale()) return;
|
|
6393
6414
|
const loaded = (chat.messages ?? []).map(fromWireMessage);
|
|
6394
6415
|
const tail = resumeBubbleRef.current ? [resumeBubbleRef.current] : [];
|
|
6395
|
-
if (loaded.length || tail.length)
|
|
6396
|
-
|
|
6397
|
-
|
|
6416
|
+
if (loaded.length || tail.length) {
|
|
6417
|
+
messagesSig.value = [...loaded, ...tail];
|
|
6418
|
+
setCanSend(chat.canContinue ?? true);
|
|
6419
|
+
setSuggestions(chat.suggestions ?? []);
|
|
6420
|
+
} else {
|
|
6421
|
+
playWelcome(res.welcome?.messages);
|
|
6422
|
+
}
|
|
6398
6423
|
} catch (err) {
|
|
6399
6424
|
if (isStale()) return;
|
|
6400
|
-
log16.warn("
|
|
6401
|
-
|
|
6402
|
-
persistence.
|
|
6425
|
+
log16.warn("loadConversation failed; resetting conversationId", { err, conversationId: persistedChatId });
|
|
6426
|
+
conversationIdSig.value = void 0;
|
|
6427
|
+
persistence.saveConversationId(void 0);
|
|
6403
6428
|
} finally {
|
|
6404
6429
|
if (!isStale()) setLoadingMessages(false);
|
|
6405
6430
|
}
|
|
6406
6431
|
} else {
|
|
6407
|
-
|
|
6408
|
-
persistence.
|
|
6432
|
+
conversationIdSig.value = res.conversationId;
|
|
6433
|
+
persistence.saveConversationId(res.conversationId);
|
|
6409
6434
|
playWelcome(res.welcome?.messages);
|
|
6410
6435
|
}
|
|
6411
6436
|
if (!newConversation) {
|
|
6412
|
-
bus.emit("
|
|
6413
|
-
|
|
6437
|
+
bus.emit("conversationStarted", res);
|
|
6438
|
+
setConversationReady(true);
|
|
6414
6439
|
}
|
|
6415
6440
|
},
|
|
6416
|
-
[transport, visitorId, persistence, options, bus, messagesSig,
|
|
6441
|
+
[transport, visitorId, persistence, options, bus, messagesSig, conversationIdSig, feedback, playWelcome]
|
|
6417
6442
|
);
|
|
6418
6443
|
const userSig = JSON.stringify(options.userContext ?? null);
|
|
6419
6444
|
const pageSig = JSON.stringify(options.pageContext ?? null);
|
|
@@ -6467,11 +6492,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6467
6492
|
[reducer, messagesSig, feedback, bus, options, homeNav]
|
|
6468
6493
|
);
|
|
6469
6494
|
useEffect17(() => {
|
|
6470
|
-
void
|
|
6471
|
-
const
|
|
6495
|
+
void runStartConversation({ newConversation: false });
|
|
6496
|
+
const persistedConversation = conversationIdSig.value;
|
|
6472
6497
|
let resume = null;
|
|
6473
|
-
if (
|
|
6474
|
-
transport.primeIdentity(visitorId,
|
|
6498
|
+
if (persistedConversation) {
|
|
6499
|
+
transport.primeIdentity(visitorId, persistedConversation);
|
|
6475
6500
|
resume = transport.resumeStream();
|
|
6476
6501
|
void runResume(resume);
|
|
6477
6502
|
}
|
|
@@ -6482,10 +6507,10 @@ function App({ options, hostElement, bus }) {
|
|
|
6482
6507
|
}, []);
|
|
6483
6508
|
const lastUserSig = useRef9(userSig);
|
|
6484
6509
|
useEffect17(() => {
|
|
6485
|
-
if (!
|
|
6510
|
+
if (!conversationReady || lastUserSig.current === userSig) return;
|
|
6486
6511
|
lastUserSig.current = userSig;
|
|
6487
|
-
void
|
|
6488
|
-
}, [userSig,
|
|
6512
|
+
void runStartConversation({ newConversation: false });
|
|
6513
|
+
}, [userSig, conversationReady, runStartConversation]);
|
|
6489
6514
|
useEffect17(() => {
|
|
6490
6515
|
applyMode(hostElement, computeHostMode(options.mode, panelSize, isOpen));
|
|
6491
6516
|
}, [hostElement, isOpen, panelSize, options.mode]);
|
|
@@ -6511,14 +6536,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6511
6536
|
}, [isOpen, options.mode]);
|
|
6512
6537
|
const streamAssistant = useCallback6(
|
|
6513
6538
|
async (assistantMsg, trigger) => {
|
|
6514
|
-
const
|
|
6515
|
-
if (!
|
|
6516
|
-
|
|
6517
|
-
persistence.
|
|
6539
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6540
|
+
if (!conversationIdSig.value) {
|
|
6541
|
+
conversationIdSig.value = activeConversationId;
|
|
6542
|
+
persistence.saveConversationId(activeConversationId);
|
|
6518
6543
|
}
|
|
6519
6544
|
const body = buildSendMessageRequest({
|
|
6520
6545
|
messages: messagesSig.value.slice(0, -1).map(fromReactive),
|
|
6521
|
-
|
|
6546
|
+
conversationId: activeConversationId,
|
|
6522
6547
|
// textModel + imageModel are backend-only — selected per deployment.
|
|
6523
6548
|
tools: options.features.tools,
|
|
6524
6549
|
responseMode: options.responseMode,
|
|
@@ -6554,7 +6579,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6554
6579
|
messagesSig.value = [...messagesSig.value];
|
|
6555
6580
|
}
|
|
6556
6581
|
},
|
|
6557
|
-
[transport, reducer, messagesSig,
|
|
6582
|
+
[transport, reducer, messagesSig, conversationIdSig, options, bus, feedback, persistence, visitorId]
|
|
6558
6583
|
);
|
|
6559
6584
|
const resolveTool = useCallback6(
|
|
6560
6585
|
(toolCallId, trigger, mutate) => {
|
|
@@ -6610,32 +6635,33 @@ function App({ options, hostElement, bus }) {
|
|
|
6610
6635
|
userContext: () => options.userContext,
|
|
6611
6636
|
messageCount: userMessageCount,
|
|
6612
6637
|
pageArea: () => options.pageContext?.area ? String(options.pageContext.area) : void 0,
|
|
6638
|
+
conversationId: () => conversationIdSig.value,
|
|
6613
6639
|
onComplete: (form, trigger, values, skipped) => {
|
|
6614
6640
|
log16.info("formSubmit", { formId: form.id, trigger, skipped });
|
|
6615
6641
|
bus.emit("formSubmit", { formId: form.id, values, skipped });
|
|
6616
6642
|
if (skipped || Object.keys(values).length === 0) return;
|
|
6617
|
-
const
|
|
6618
|
-
if (!
|
|
6619
|
-
|
|
6620
|
-
persistence.
|
|
6621
|
-
transport.primeIdentity(void 0,
|
|
6643
|
+
const activeConversationId = conversationIdSig.value ?? uuid7();
|
|
6644
|
+
if (!conversationIdSig.value) {
|
|
6645
|
+
conversationIdSig.value = activeConversationId;
|
|
6646
|
+
persistence.saveConversationId(activeConversationId);
|
|
6647
|
+
transport.primeIdentity(void 0, activeConversationId);
|
|
6622
6648
|
}
|
|
6623
6649
|
if (form.mirrorToContext) setFormContext((prev) => ({ ...prev, ...values }));
|
|
6624
|
-
void transport.submitForm({ formId: form.id,
|
|
6650
|
+
void transport.submitForm({ formId: form.id, conversationId: activeConversationId, trigger, values });
|
|
6625
6651
|
}
|
|
6626
6652
|
});
|
|
6627
6653
|
const activeForm = useComputed7(() => forms.activeForm.value);
|
|
6628
6654
|
const pageArea = options.pageContext?.area ? String(options.pageContext.area) : void 0;
|
|
6629
6655
|
const msgCount = useComputed7(() => messagesSig.value.length);
|
|
6630
6656
|
useEffect17(() => {
|
|
6631
|
-
if (
|
|
6632
|
-
}, [
|
|
6657
|
+
if (conversationReady) forms.fire("pre-chat");
|
|
6658
|
+
}, [conversationReady, forms]);
|
|
6633
6659
|
useEffect17(() => {
|
|
6634
6660
|
if (!canSend) forms.fire("conversation-closed");
|
|
6635
6661
|
}, [canSend, forms]);
|
|
6636
6662
|
useEffect17(() => {
|
|
6637
|
-
if (
|
|
6638
|
-
}, [
|
|
6663
|
+
if (conversationReady && pageArea) forms.fire("page-area");
|
|
6664
|
+
}, [conversationReady, pageArea, forms]);
|
|
6639
6665
|
const idleMs = useMemo3(() => {
|
|
6640
6666
|
const secs = options.forms.list.flatMap((f) => f.triggers).filter((t) => t.kind === "idle").map((t) => Number(t.param));
|
|
6641
6667
|
return secs.length ? Math.min(...secs) * 1e3 : 0;
|
|
@@ -6695,16 +6721,16 @@ function App({ options, hostElement, bus }) {
|
|
|
6695
6721
|
}, [bus, options, persistence, panelSize, forms]);
|
|
6696
6722
|
const refreshUnread = useCallback6(() => {
|
|
6697
6723
|
if (!options.modules.list.some((m) => m.layout === "chat")) return;
|
|
6698
|
-
transport.
|
|
6699
|
-
unreadCountSig.value = res.
|
|
6724
|
+
transport.listConversations({ limit: 50 }).then((res) => {
|
|
6725
|
+
unreadCountSig.value = res.conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0);
|
|
6700
6726
|
}).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
|
|
6701
6727
|
}, [transport, options.modules, unreadCountSig]);
|
|
6702
6728
|
const unreadSeeded = useRef9(false);
|
|
6703
6729
|
useEffect17(() => {
|
|
6704
|
-
if (!
|
|
6730
|
+
if (!conversationReady || unreadSeeded.current) return;
|
|
6705
6731
|
unreadSeeded.current = true;
|
|
6706
6732
|
refreshUnread();
|
|
6707
|
-
}, [
|
|
6733
|
+
}, [conversationReady, refreshUnread]);
|
|
6708
6734
|
const handleOpen = useCallback6(() => {
|
|
6709
6735
|
log16.info("open", { mode: options.mode });
|
|
6710
6736
|
feedback.unlock();
|
|
@@ -6723,11 +6749,11 @@ function App({ options, hostElement, bus }) {
|
|
|
6723
6749
|
if (streaming) activeCancel?.();
|
|
6724
6750
|
welcomeAbortRef.current?.abort();
|
|
6725
6751
|
messagesSig.value = [];
|
|
6726
|
-
|
|
6727
|
-
persistence.
|
|
6752
|
+
conversationIdSig.value = void 0;
|
|
6753
|
+
persistence.clearConversation();
|
|
6728
6754
|
setCanSend(true);
|
|
6729
|
-
void
|
|
6730
|
-
}, [streaming, activeCancel, messagesSig,
|
|
6755
|
+
void runStartConversation({ newConversation: true });
|
|
6756
|
+
}, [streaming, activeCancel, messagesSig, conversationIdSig, persistence, runStartConversation, bus]);
|
|
6731
6757
|
const handleNewChat = useCallback6(() => {
|
|
6732
6758
|
handleClear();
|
|
6733
6759
|
setView("chat");
|
|
@@ -6751,12 +6777,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6751
6777
|
const handlePopOut = useCallback6(() => {
|
|
6752
6778
|
if (!options.popOutUrl) return;
|
|
6753
6779
|
const url = new URL(options.popOutUrl);
|
|
6754
|
-
if (
|
|
6780
|
+
if (conversationIdSig.value) url.searchParams.set("chat", conversationIdSig.value);
|
|
6755
6781
|
if (options.widgetId !== "default") url.searchParams.set("widgetId", options.widgetId);
|
|
6756
6782
|
log16.info("popOut", { url: url.toString() });
|
|
6757
6783
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
6758
6784
|
bus.emit("popOut", void 0);
|
|
6759
|
-
}, [bus,
|
|
6785
|
+
}, [bus, conversationIdSig, options.popOutUrl, options.widgetId]);
|
|
6760
6786
|
const handleToggleHistory = useCallback6(() => {
|
|
6761
6787
|
setView((v) => {
|
|
6762
6788
|
const next = v === "history" ? "chat" : "history";
|
|
@@ -6803,14 +6829,14 @@ function App({ options, hostElement, bus }) {
|
|
|
6803
6829
|
);
|
|
6804
6830
|
const handleSelectHistoryChat = useCallback6(
|
|
6805
6831
|
async (targetChatId) => {
|
|
6806
|
-
log16.info("selectChat", {
|
|
6807
|
-
bus.emit("selectChat", {
|
|
6832
|
+
log16.info("selectChat", { conversationId: targetChatId });
|
|
6833
|
+
bus.emit("selectChat", { conversationId: targetChatId });
|
|
6808
6834
|
try {
|
|
6809
|
-
const res = await transport.
|
|
6835
|
+
const res = await transport.loadConversation(targetChatId);
|
|
6810
6836
|
const hydrated = res.messages.map(fromWireMessage);
|
|
6811
6837
|
messagesSig.value = hydrated;
|
|
6812
|
-
|
|
6813
|
-
persistence.
|
|
6838
|
+
conversationIdSig.value = res.conversationId;
|
|
6839
|
+
persistence.saveConversationId(res.conversationId);
|
|
6814
6840
|
if (res.agent) setAgent(res.agent);
|
|
6815
6841
|
setCanSend(res.canContinue);
|
|
6816
6842
|
setSuggestions(res.suggestions ?? []);
|
|
@@ -6822,7 +6848,7 @@ function App({ options, hostElement, bus }) {
|
|
|
6822
6848
|
options.onError?.(err);
|
|
6823
6849
|
}
|
|
6824
6850
|
},
|
|
6825
|
-
[transport, messagesSig,
|
|
6851
|
+
[transport, messagesSig, conversationIdSig, bus, options, persistence, refreshUnread]
|
|
6826
6852
|
);
|
|
6827
6853
|
useEffect17(() => {
|
|
6828
6854
|
const unsub = bindHostCommands(hostElement, {
|
|
@@ -6880,12 +6906,12 @@ function App({ options, hostElement, bus }) {
|
|
|
6880
6906
|
onFormSkip: forms.skip,
|
|
6881
6907
|
tool: toolInteraction
|
|
6882
6908
|
};
|
|
6883
|
-
const
|
|
6884
|
-
void handleSelectHistoryChat(
|
|
6909
|
+
const onSelectConversation = (conversationId) => {
|
|
6910
|
+
void handleSelectHistoryChat(conversationId);
|
|
6885
6911
|
const chatId = chatTabId();
|
|
6886
6912
|
if (chatId) homeNav.switchTab(chatId);
|
|
6887
6913
|
};
|
|
6888
|
-
if (!
|
|
6914
|
+
if (!conversationReady) return null;
|
|
6889
6915
|
const enabledModules = effectiveOptions.modules.list;
|
|
6890
6916
|
const renderSurface = (size) => {
|
|
6891
6917
|
const closeable = isActionVisible("close", effectiveOptions.mode, size);
|
|
@@ -6902,15 +6928,15 @@ function App({ options, hostElement, bus }) {
|
|
|
6902
6928
|
enabledModules,
|
|
6903
6929
|
nav: homeNav,
|
|
6904
6930
|
unreadCount: unreadCountSig.value,
|
|
6905
|
-
|
|
6906
|
-
|
|
6931
|
+
onSelectConversation,
|
|
6932
|
+
onStartNewConversation: handleNewChat,
|
|
6907
6933
|
onSetPanelSize: setPanelSize
|
|
6908
6934
|
}
|
|
6909
6935
|
);
|
|
6910
6936
|
};
|
|
6911
6937
|
if (options.mode === "page") {
|
|
6912
6938
|
const onSelectChatFromSidebar = (chat) => {
|
|
6913
|
-
void handleSelectHistoryChat(chat.
|
|
6939
|
+
void handleSelectHistoryChat(chat.conversationId);
|
|
6914
6940
|
};
|
|
6915
6941
|
const messagesEnabled = enabledModules.some((m) => m.layout === "chat");
|
|
6916
6942
|
return /* @__PURE__ */ jsx37("div", { class: `${p32}-anchor`, children: /* @__PURE__ */ jsx37(
|
|
@@ -7059,7 +7085,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7059
7085
|
/**
|
|
7060
7086
|
* Raw options accumulator. Starts as whatever the page-owner set via
|
|
7061
7087
|
* HTML attributes; gets server-side settings merged in on the
|
|
7062
|
-
* `
|
|
7088
|
+
* `conversationStarted` event so subsequent re-renders pick up the server's
|
|
7063
7089
|
* mode / theme / launcher / etc.
|
|
7064
7090
|
*
|
|
7065
7091
|
* Mirrors `index.ts`'s `rawOptions` so both entry points share the
|
|
@@ -7089,7 +7115,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7089
7115
|
existingHost: this,
|
|
7090
7116
|
position: hostPositionForMode(resolved.mode)
|
|
7091
7117
|
});
|
|
7092
|
-
this.bus.on("
|
|
7118
|
+
this.bus.on("conversationStarted", (response) => {
|
|
7093
7119
|
if (!response.config) return;
|
|
7094
7120
|
this.rawOptions = mergeServerConfig(this.rawOptions, response.config);
|
|
7095
7121
|
this.renderApp();
|
|
@@ -7099,7 +7125,7 @@ var ChatElement = class extends HTMLElement {
|
|
|
7099
7125
|
}
|
|
7100
7126
|
/**
|
|
7101
7127
|
* Apply the current `rawOptions` to the host element + App tree.
|
|
7102
|
-
* Called by both the initial boot and every `
|
|
7128
|
+
* Called by both the initial boot and every `conversationStarted` merge.
|
|
7103
7129
|
*/
|
|
7104
7130
|
renderApp() {
|
|
7105
7131
|
if (!this.mountResult) return;
|