@webless/agent 0.6.11 → 0.7.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.
@@ -1617,6 +1617,20 @@ function latestTurnEvents(events) {
1617
1617
  }
1618
1618
  return startIndex >= 0 ? events.slice(startIndex) : [];
1619
1619
  }
1620
+ function streamIndexBeforeLastTurn(input) {
1621
+ let turnStart = -1;
1622
+ for (let index = input.events.length - 1; index >= 0; index -= 1) {
1623
+ if (input.events[index]?.type === "message.received") {
1624
+ turnStart = index;
1625
+ break;
1626
+ }
1627
+ }
1628
+ if (turnStart < 0) return null;
1629
+ return Math.max(
1630
+ 0,
1631
+ input.currentStreamIndex - (input.events.length - turnStart)
1632
+ );
1633
+ }
1620
1634
  function renderTurn(events) {
1621
1635
  let rendered = "";
1622
1636
  for (const event of events) {
@@ -1801,6 +1815,40 @@ var AgentSession = class {
1801
1815
  this.storeOptions
1802
1816
  );
1803
1817
  }
1818
+ async rewindBeforeLastTurn(signal) {
1819
+ const persisted = loadPersistedAgentSession(
1820
+ this.visitorSessionId,
1821
+ this.storeOptions
1822
+ );
1823
+ if (!persisted?.sessionId) return false;
1824
+ const client = this.ensureClient();
1825
+ const attached = client.sessions.attach(persisted.sessionId, {
1826
+ streamIndex: persisted.streamIndex
1827
+ });
1828
+ const snapshot = await withCapabilityRefresh(
1829
+ this.capability,
1830
+ () => attached.snapshot({ signal })
1831
+ );
1832
+ const rewindStreamIndex = streamIndexBeforeLastTurn({
1833
+ currentStreamIndex: snapshot.session.streamIndex,
1834
+ events: snapshot.events
1835
+ });
1836
+ if (rewindStreamIndex === null) return false;
1837
+ this.session = client.sessions.attach(persisted.sessionId, {
1838
+ streamIndex: rewindStreamIndex
1839
+ });
1840
+ savePersistedAgentSession(
1841
+ this.visitorSessionId,
1842
+ persisted.sessionId,
1843
+ rewindStreamIndex,
1844
+ this.storeOptions
1845
+ );
1846
+ return true;
1847
+ }
1848
+ async regenerateTurn(message, signal, handlers) {
1849
+ await this.rewindBeforeLastTurn(signal);
1850
+ return this.sendTurn(message, signal, handlers);
1851
+ }
1804
1852
  ensureClient() {
1805
1853
  const config = resolveAgentRuntimeConfig({
1806
1854
  indexId: this.indexId,
@@ -2136,6 +2184,11 @@ function createAgentClient(options) {
2136
2184
  respondOptions.signal ?? new AbortController().signal,
2137
2185
  respondOptions.handlers
2138
2186
  ),
2187
+ regenerateTurn: (message, regenerateOptions) => session.regenerateTurn(
2188
+ message,
2189
+ regenerateOptions.signal ?? new AbortController().signal,
2190
+ regenerateOptions.handlers
2191
+ ),
2139
2192
  reset: () => session.reset(),
2140
2193
  cancelActive: () => session.cancelActive(),
2141
2194
  getActiveSessionId: () => session.getActiveSessionId()
@@ -2736,6 +2789,7 @@ function useAgentChat({
2736
2789
  const {
2737
2790
  controller,
2738
2791
  initialText = "",
2792
+ regenerate: regenerate2 = false,
2739
2793
  responses,
2740
2794
  resume,
2741
2795
  visitorText
@@ -2847,6 +2901,9 @@ function useAgentChat({
2847
2901
  initialText,
2848
2902
  message: visitorText,
2849
2903
  signal
2904
+ }) : regenerate2 ? await clientRef.current.regenerateTurn(visitorText, {
2905
+ handlers,
2906
+ signal
2850
2907
  }) : await clientRef.current.sendTurn(visitorText, {
2851
2908
  handlers,
2852
2909
  signal
@@ -3063,6 +3120,49 @@ ${outgoing}` : outgoing;
3063
3120
  visitorText: visitorTurnText(visitorMessage)
3064
3121
  });
3065
3122
  }, [runTurn, state.messages]);
3123
+ const regenerate = useCallback(async () => {
3124
+ let lastVisitorIndex = -1;
3125
+ for (let index = state.messages.length - 1; index >= 0; index -= 1) {
3126
+ if (state.messages[index]?.role === "visitor") {
3127
+ lastVisitorIndex = index;
3128
+ break;
3129
+ }
3130
+ }
3131
+ const visitorMessage = lastVisitorIndex >= 0 ? state.messages[lastVisitorIndex] : void 0;
3132
+ if (!visitorMessage) return null;
3133
+ if (runRef.current) {
3134
+ runRef.current.abort();
3135
+ clientRef.current.cancelActive();
3136
+ }
3137
+ const controller = new AbortController();
3138
+ runRef.current = controller;
3139
+ setState((prev) => ({
3140
+ ...prev,
3141
+ phase: "thinking",
3142
+ messages: prev.messages.slice(0, lastVisitorIndex + 1),
3143
+ toolSteps: [
3144
+ {
3145
+ id: "planning",
3146
+ kind: "planning",
3147
+ label: "Understanding your question",
3148
+ state: "active"
3149
+ }
3150
+ ],
3151
+ journey: null,
3152
+ followUps: [],
3153
+ streamingText: "",
3154
+ pendingOffer: null,
3155
+ pendingInputs: [],
3156
+ toolResults: [],
3157
+ error: null
3158
+ }));
3159
+ return await runTurn({
3160
+ controller,
3161
+ regenerate: true,
3162
+ resume: false,
3163
+ visitorText: visitorTurnText(visitorMessage)
3164
+ });
3165
+ }, [runTurn, state.messages]);
3066
3166
  const respondToToolInput = useCallback(
3067
3167
  async (surface, values) => {
3068
3168
  await submit(`${surface.title} submitted`, {
@@ -3139,6 +3239,7 @@ ${outgoing}` : outgoing;
3139
3239
  state,
3140
3240
  reset,
3141
3241
  retry,
3242
+ regenerate,
3142
3243
  respondToInput,
3143
3244
  respondToToolInput,
3144
3245
  submit,
@@ -3244,8 +3345,629 @@ var defaultDarkAgentRailTheme = {
3244
3345
  danger: "#ff8da1"
3245
3346
  };
3246
3347
 
3348
+ // src/react/components/MessageActions/MessageActions.tsx
3349
+ import { useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useState as useState2 } from "react";
3350
+ import { createPortal } from "react-dom";
3351
+
3352
+ // src/react/lib/speech.ts
3353
+ function toSpeechText(text) {
3354
+ let out = hideToolCardFences(text);
3355
+ out = out.replace(/```[\s\S]*?```/g, " ");
3356
+ out = out.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
3357
+ out = out.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1");
3358
+ out = out.replace(/^\s{0,3}#{1,6}\s+/gm, "");
3359
+ out = out.replace(/(\*\*|__)(.*?)\1/g, "$2");
3360
+ out = out.replace(/(\*|_)(.*?)\1/g, "$2");
3361
+ out = out.replace(/~~(.*?)~~/g, "$1");
3362
+ out = out.replace(/`([^`]*)`/g, "$1");
3363
+ out = out.replace(/^\s*>\s?/gm, "");
3364
+ out = out.replace(/^\s*[-*+]\s+/gm, "");
3365
+ out = out.replace(/^\s*\d+\.\s+/gm, "");
3366
+ out = out.replace(/\|/g, " ");
3367
+ out = out.replace(/^\s*[-:]{3,}\s*$/gm, " ");
3368
+ out = out.replace(/\s*\n\s*/g, ". ");
3369
+ out = out.replace(/(?:\.\s*){2,}/g, ". ");
3370
+ return out.replace(/\s{2,}/g, " ").trim();
3371
+ }
3372
+ function isSpeechSupported() {
3373
+ return typeof window !== "undefined" && "speechSynthesis" in window && typeof window.SpeechSynthesisUtterance === "function";
3374
+ }
3375
+ function stopSpeech() {
3376
+ if (!isSpeechSupported()) return;
3377
+ window.speechSynthesis.cancel();
3378
+ }
3379
+ var speechInterruptListeners = /* @__PURE__ */ new Set();
3380
+ var pageListenersAttached = false;
3381
+ var lastPathname = "";
3382
+ var originalPushState = null;
3383
+ var originalReplaceState = null;
3384
+ var patchedPushState = null;
3385
+ var patchedReplaceState = null;
3386
+ function currentPathname() {
3387
+ return window.location.pathname;
3388
+ }
3389
+ function notifySpeechInterrupts() {
3390
+ if (speechInterruptListeners.size === 0) return;
3391
+ stopSpeech();
3392
+ for (const listener of speechInterruptListeners) {
3393
+ listener();
3394
+ }
3395
+ }
3396
+ function interruptIfPathChanged(nextPath) {
3397
+ if (nextPath === lastPathname) return;
3398
+ lastPathname = nextPath;
3399
+ notifySpeechInterrupts();
3400
+ }
3401
+ function patchHistoryMethod(original) {
3402
+ return function patched(data, unused, url) {
3403
+ const result = original.call(this, data, unused, url);
3404
+ interruptIfPathChanged(currentPathname());
3405
+ return result;
3406
+ };
3407
+ }
3408
+ function historyMethodState(name) {
3409
+ return name === "pushState" ? {
3410
+ original: originalPushState,
3411
+ patched: patchedPushState,
3412
+ set(original, patched) {
3413
+ originalPushState = original;
3414
+ patchedPushState = patched;
3415
+ }
3416
+ } : {
3417
+ original: originalReplaceState,
3418
+ patched: patchedReplaceState,
3419
+ set(original, patched) {
3420
+ originalReplaceState = original;
3421
+ patchedReplaceState = patched;
3422
+ }
3423
+ };
3424
+ }
3425
+ function patchHistoryNamed(name) {
3426
+ const state = historyMethodState(name);
3427
+ const current = history[name];
3428
+ if (state.patched && current === state.patched) return;
3429
+ const patched = patchHistoryMethod(current);
3430
+ state.set(current, patched);
3431
+ history[name] = patched;
3432
+ }
3433
+ function restoreHistoryMethod(name) {
3434
+ const state = historyMethodState(name);
3435
+ if (!state.patched || !state.original || typeof history === "undefined") {
3436
+ return false;
3437
+ }
3438
+ if (history[name] !== state.patched) return false;
3439
+ history[name] = state.original;
3440
+ state.set(null, null);
3441
+ return true;
3442
+ }
3443
+ function handlePageHide() {
3444
+ notifySpeechInterrupts();
3445
+ }
3446
+ function handlePopState() {
3447
+ interruptIfPathChanged(currentPathname());
3448
+ }
3449
+ function handleVisibilityChange() {
3450
+ if (document.visibilityState === "hidden") {
3451
+ notifySpeechInterrupts();
3452
+ }
3453
+ }
3454
+ function attachPageListeners() {
3455
+ if (pageListenersAttached || typeof window === "undefined") return;
3456
+ pageListenersAttached = true;
3457
+ window.addEventListener("pagehide", handlePageHide);
3458
+ window.addEventListener("popstate", handlePopState);
3459
+ document.addEventListener("visibilitychange", handleVisibilityChange);
3460
+ }
3461
+ function detachPageListeners() {
3462
+ if (!pageListenersAttached || typeof window === "undefined") return;
3463
+ window.removeEventListener("pagehide", handlePageHide);
3464
+ window.removeEventListener("popstate", handlePopState);
3465
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
3466
+ pageListenersAttached = false;
3467
+ }
3468
+ function ensureSpeechInterruptsPatched() {
3469
+ if (typeof window === "undefined") return;
3470
+ lastPathname = currentPathname();
3471
+ patchHistoryNamed("pushState");
3472
+ patchHistoryNamed("replaceState");
3473
+ attachPageListeners();
3474
+ }
3475
+ function teardownSpeechInterrupts() {
3476
+ detachPageListeners();
3477
+ restoreHistoryMethod("pushState");
3478
+ restoreHistoryMethod("replaceState");
3479
+ if (!patchedPushState && !patchedReplaceState) {
3480
+ lastPathname = "";
3481
+ }
3482
+ }
3483
+ function subscribeSpeechInterrupts(onInterrupt) {
3484
+ if (typeof window === "undefined") return () => {
3485
+ };
3486
+ ensureSpeechInterruptsPatched();
3487
+ speechInterruptListeners.add(onInterrupt);
3488
+ return () => {
3489
+ speechInterruptListeners.delete(onInterrupt);
3490
+ if (speechInterruptListeners.size === 0) {
3491
+ teardownSpeechInterrupts();
3492
+ }
3493
+ };
3494
+ }
3495
+
3496
+ // src/react/components/AgentRail/AgentRailOverlayContext.tsx
3497
+ import { createContext, useContext } from "react";
3498
+ var AgentRailOverlayContext = createContext(null);
3499
+ function useAgentRailPortalRoots() {
3500
+ return useContext(AgentRailOverlayContext);
3501
+ }
3502
+ function useAgentRailMenuPortalRoot() {
3503
+ return useContext(AgentRailOverlayContext)?.railRef ?? null;
3504
+ }
3505
+
3506
+ // src/react/components/MessageActions/MessageActions.tsx
3507
+ import { jsx, jsxs } from "react/jsx-runtime";
3508
+ function CopyIcon() {
3509
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3510
+ /* @__PURE__ */ jsx(
3511
+ "rect",
3512
+ {
3513
+ x: "5.75",
3514
+ y: "5.75",
3515
+ width: "7.5",
3516
+ height: "7.5",
3517
+ rx: "1.5",
3518
+ stroke: "currentColor",
3519
+ strokeWidth: "1.5"
3520
+ }
3521
+ ),
3522
+ /* @__PURE__ */ jsx(
3523
+ "path",
3524
+ {
3525
+ d: "M10.25 5.25V4.5a1.75 1.75 0 0 0-1.75-1.75h-4A1.75 1.75 0 0 0 2.75 4.5v4c0 .97.78 1.75 1.75 1.75h.75",
3526
+ stroke: "currentColor",
3527
+ strokeWidth: "1.5"
3528
+ }
3529
+ )
3530
+ ] });
3531
+ }
3532
+ function CheckIcon() {
3533
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
3534
+ "path",
3535
+ {
3536
+ d: "M3.5 8.5l3 3 6-7",
3537
+ stroke: "currentColor",
3538
+ strokeWidth: "1.6",
3539
+ strokeLinecap: "round",
3540
+ strokeLinejoin: "round"
3541
+ }
3542
+ ) });
3543
+ }
3544
+ function ThumbUpIcon() {
3545
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3546
+ /* @__PURE__ */ jsx(
3547
+ "path",
3548
+ {
3549
+ d: "M4.67 6.67v8",
3550
+ stroke: "currentColor",
3551
+ strokeWidth: "1.5",
3552
+ strokeLinecap: "round"
3553
+ }
3554
+ ),
3555
+ /* @__PURE__ */ jsx(
3556
+ "path",
3557
+ {
3558
+ d: "M10 3.92 9.33 6.67h3.89a1.33 1.33 0 0 1 1.28 1.7l-1.55 5.33a1.33 1.33 0 0 1-1.28.97H2.67a1.33 1.33 0 0 1-1.34-1.34V8a1.33 1.33 0 0 1 1.34-1.33h1.84a1.33 1.33 0 0 0 1.19-.74L8 1.33a2.09 2.09 0 0 1 2 2.59Z",
3559
+ stroke: "currentColor",
3560
+ strokeWidth: "1.5",
3561
+ strokeLinecap: "round",
3562
+ strokeLinejoin: "round"
3563
+ }
3564
+ )
3565
+ ] });
3566
+ }
3567
+ function ThumbDownIcon() {
3568
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxs("g", { transform: "rotate(180 8 8)", children: [
3569
+ /* @__PURE__ */ jsx(
3570
+ "path",
3571
+ {
3572
+ d: "M4.67 6.67v8",
3573
+ stroke: "currentColor",
3574
+ strokeWidth: "1.5",
3575
+ strokeLinecap: "round"
3576
+ }
3577
+ ),
3578
+ /* @__PURE__ */ jsx(
3579
+ "path",
3580
+ {
3581
+ d: "M10 3.92 9.33 6.67h3.89a1.33 1.33 0 0 1 1.28 1.7l-1.55 5.33a1.33 1.33 0 0 1-1.28.97H2.67a1.33 1.33 0 0 1-1.34-1.34V8a1.33 1.33 0 0 1 1.34-1.33h1.84a1.33 1.33 0 0 0 1.19-.74L8 1.33a2.09 2.09 0 0 1 2 2.59Z",
3582
+ stroke: "currentColor",
3583
+ strokeWidth: "1.5",
3584
+ strokeLinecap: "round",
3585
+ strokeLinejoin: "round"
3586
+ }
3587
+ )
3588
+ ] }) });
3589
+ }
3590
+ function RegenerateIcon() {
3591
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3592
+ /* @__PURE__ */ jsx(
3593
+ "path",
3594
+ {
3595
+ d: "M2 8a6 6 0 0 1 6-6 6.5 6.5 0 0 1 4.5 1.83L14 5.33",
3596
+ stroke: "currentColor",
3597
+ strokeWidth: "1.5",
3598
+ strokeLinecap: "round"
3599
+ }
3600
+ ),
3601
+ /* @__PURE__ */ jsx(
3602
+ "path",
3603
+ {
3604
+ d: "M14 2v3.33h-3.33",
3605
+ stroke: "currentColor",
3606
+ strokeWidth: "1.5",
3607
+ strokeLinecap: "round",
3608
+ strokeLinejoin: "round"
3609
+ }
3610
+ ),
3611
+ /* @__PURE__ */ jsx(
3612
+ "path",
3613
+ {
3614
+ d: "M14 8a6 6 0 0 1-6 6 6.5 6.5 0 0 1-4.5-1.83L2 10.67",
3615
+ stroke: "currentColor",
3616
+ strokeWidth: "1.5",
3617
+ strokeLinecap: "round"
3618
+ }
3619
+ ),
3620
+ /* @__PURE__ */ jsx(
3621
+ "path",
3622
+ {
3623
+ d: "M5.33 10.67H2V14",
3624
+ stroke: "currentColor",
3625
+ strokeWidth: "1.5",
3626
+ strokeLinecap: "round",
3627
+ strokeLinejoin: "round"
3628
+ }
3629
+ )
3630
+ ] });
3631
+ }
3632
+ function MoreIcon() {
3633
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3634
+ /* @__PURE__ */ jsx("circle", { cx: "3.5", cy: "8", r: "1.15", fill: "currentColor" }),
3635
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "1.15", fill: "currentColor" }),
3636
+ /* @__PURE__ */ jsx("circle", { cx: "12.5", cy: "8", r: "1.15", fill: "currentColor" })
3637
+ ] });
3638
+ }
3639
+ function SourcesIcon() {
3640
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3641
+ /* @__PURE__ */ jsx(
3642
+ "path",
3643
+ {
3644
+ d: "M8 4.5C6.9 3.4 5.3 3 3.5 3c-.4 0-.8 0-1.2.1-.3 0-.5.3-.5.6v8.1c0 .4.4.7.8.6.3-.1.7-.1 1.1-.1 1.6 0 3.2.4 4.3 1.3 1.1-.9 2.7-1.3 4.3-1.3.4 0 .8 0 1.1.1.4.1.8-.2.8-.6V3.7c0-.3-.2-.6-.5-.6-.4-.1-.8-.1-1.2-.1-1.8 0-3.4.4-4.5 1.5Z",
3645
+ stroke: "currentColor",
3646
+ strokeWidth: "1.4",
3647
+ strokeLinecap: "round",
3648
+ strokeLinejoin: "round"
3649
+ }
3650
+ ),
3651
+ /* @__PURE__ */ jsx(
3652
+ "path",
3653
+ {
3654
+ d: "M8 4.5v9",
3655
+ stroke: "currentColor",
3656
+ strokeWidth: "1.4",
3657
+ strokeLinecap: "round"
3658
+ }
3659
+ )
3660
+ ] });
3661
+ }
3662
+ function ReadAloudIcon() {
3663
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
3664
+ /* @__PURE__ */ jsx(
3665
+ "path",
3666
+ {
3667
+ d: "M8.5 3.8 5.8 6H3.5c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2.3l2.7 2.2c.4.3 1 0 1-.5V4.3c0-.5-.6-.8-1-.5Z",
3668
+ stroke: "currentColor",
3669
+ strokeWidth: "1.4",
3670
+ strokeLinecap: "round",
3671
+ strokeLinejoin: "round"
3672
+ }
3673
+ ),
3674
+ /* @__PURE__ */ jsx(
3675
+ "path",
3676
+ {
3677
+ d: "M11 6.2c.5.5.8 1.1.8 1.8s-.3 1.3-.8 1.8M12.8 4.5c.9.8 1.4 2 1.4 3.5s-.5 2.7-1.4 3.5",
3678
+ stroke: "currentColor",
3679
+ strokeWidth: "1.4",
3680
+ strokeLinecap: "round"
3681
+ }
3682
+ )
3683
+ ] });
3684
+ }
3685
+ function StopIcon() {
3686
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
3687
+ "rect",
3688
+ {
3689
+ x: "4",
3690
+ y: "4",
3691
+ width: "8",
3692
+ height: "8",
3693
+ rx: "1.5",
3694
+ stroke: "currentColor",
3695
+ strokeWidth: "1.5"
3696
+ }
3697
+ ) });
3698
+ }
3699
+ async function writeToClipboard(text) {
3700
+ try {
3701
+ await navigator.clipboard.writeText(text);
3702
+ } catch {
3703
+ const textarea = document.createElement("textarea");
3704
+ textarea.value = text;
3705
+ textarea.style.position = "fixed";
3706
+ textarea.style.opacity = "0";
3707
+ document.body.appendChild(textarea);
3708
+ textarea.select();
3709
+ document.execCommand("copy");
3710
+ textarea.remove();
3711
+ }
3712
+ }
3713
+ function formatAnsweredAt(answeredAt) {
3714
+ if (!answeredAt) return null;
3715
+ const date = new Date(answeredAt);
3716
+ if (Number.isNaN(date.getTime())) return null;
3717
+ return new Intl.DateTimeFormat(void 0, {
3718
+ dateStyle: "medium",
3719
+ timeStyle: "short"
3720
+ }).format(date);
3721
+ }
3722
+ function resolveMenuPosition(input) {
3723
+ const padding = 8;
3724
+ const { button, menuHeight, menuWidth, rail } = input;
3725
+ if (!rail) {
3726
+ return {
3727
+ left: button.left,
3728
+ top: button.top - menuHeight - 6
3729
+ };
3730
+ }
3731
+ let left = button.left - rail.left;
3732
+ let top = button.top - rail.top - menuHeight - 6;
3733
+ left = Math.min(
3734
+ Math.max(left, padding),
3735
+ rail.width - menuWidth - padding
3736
+ );
3737
+ if (top < padding) {
3738
+ top = button.bottom - rail.top + 6;
3739
+ }
3740
+ top = Math.min(top, rail.height - menuHeight - padding);
3741
+ return { left, top };
3742
+ }
3743
+ function MessageActions({
3744
+ answeredAt,
3745
+ copyText,
3746
+ disabled = false,
3747
+ onOpenReceipt,
3748
+ onRegenerate,
3749
+ onFeedback,
3750
+ readAloud = false,
3751
+ receiptSteps,
3752
+ speechText
3753
+ }) {
3754
+ const menuPortalRoot = useAgentRailMenuPortalRoot();
3755
+ const [copied, setCopied] = useState2(false);
3756
+ const [rating, setRating] = useState2(null);
3757
+ const [menuOpen, setMenuOpen] = useState2(false);
3758
+ const [menuPosition, setMenuPosition] = useState2(null);
3759
+ const [speaking, setSpeaking] = useState2(false);
3760
+ const [speechSupported, setSpeechSupported] = useState2(null);
3761
+ const copyTimerRef = useRef2(null);
3762
+ const menuRef = useRef2(null);
3763
+ const portaledMenuRef = useRef2(null);
3764
+ const moreButtonRef = useRef2(null);
3765
+ const answeredLabel = formatAnsweredAt(answeredAt ?? 0);
3766
+ const resolvedSpeechText = speechText ?? toSpeechText(copyText);
3767
+ const canOpenReceipt = Boolean(receiptSteps) && Boolean(onOpenReceipt);
3768
+ const readAloudEligible = Boolean(readAloud && resolvedSpeechText);
3769
+ const canReadAloud = readAloudEligible && speechSupported === true;
3770
+ const showMenu = canOpenReceipt || (speechSupported === null ? readAloudEligible : canReadAloud);
3771
+ useLayoutEffect(() => {
3772
+ setSpeechSupported(isSpeechSupported());
3773
+ }, []);
3774
+ useLayoutEffect(() => {
3775
+ if (!menuOpen || !moreButtonRef.current || !portaledMenuRef.current) {
3776
+ setMenuPosition(null);
3777
+ return;
3778
+ }
3779
+ const button = moreButtonRef.current.getBoundingClientRect();
3780
+ const menu2 = portaledMenuRef.current;
3781
+ const rail = menuPortalRoot?.current?.getBoundingClientRect() ?? null;
3782
+ setMenuPosition(
3783
+ resolveMenuPosition({
3784
+ button,
3785
+ menuHeight: menu2.offsetHeight,
3786
+ menuWidth: menu2.offsetWidth || 190,
3787
+ rail
3788
+ })
3789
+ );
3790
+ }, [menuOpen, menuPortalRoot]);
3791
+ useEffect2(() => {
3792
+ const unsubscribe = subscribeSpeechInterrupts(() => setSpeaking(false));
3793
+ return () => {
3794
+ unsubscribe();
3795
+ if (copyTimerRef.current !== null) {
3796
+ window.clearTimeout(copyTimerRef.current);
3797
+ }
3798
+ stopSpeech();
3799
+ };
3800
+ }, []);
3801
+ useEffect2(() => {
3802
+ if (!menuOpen) return;
3803
+ const handlePointerDown = (event) => {
3804
+ const target = event.target;
3805
+ if (!menuRef.current?.contains(target) && !portaledMenuRef.current?.contains(target)) {
3806
+ setMenuOpen(false);
3807
+ }
3808
+ };
3809
+ const handleKeyDown = (event) => {
3810
+ if (event.key !== "Escape") return;
3811
+ event.preventDefault();
3812
+ event.stopPropagation();
3813
+ setMenuOpen(false);
3814
+ };
3815
+ document.addEventListener("pointerdown", handlePointerDown);
3816
+ document.addEventListener("keydown", handleKeyDown);
3817
+ return () => {
3818
+ document.removeEventListener("pointerdown", handlePointerDown);
3819
+ document.removeEventListener("keydown", handleKeyDown);
3820
+ };
3821
+ }, [menuOpen]);
3822
+ function handleCopy() {
3823
+ void writeToClipboard(copyText);
3824
+ setCopied(true);
3825
+ if (copyTimerRef.current !== null) {
3826
+ window.clearTimeout(copyTimerRef.current);
3827
+ }
3828
+ copyTimerRef.current = window.setTimeout(() => setCopied(false), 1600);
3829
+ }
3830
+ function handleFeedback(next) {
3831
+ const resolved = rating === next ? null : next;
3832
+ setRating(resolved);
3833
+ if (resolved) onFeedback?.(resolved);
3834
+ }
3835
+ function handleReadAloud() {
3836
+ if (!canReadAloud) return;
3837
+ setMenuOpen(false);
3838
+ if (speaking) {
3839
+ stopSpeech();
3840
+ setSpeaking(false);
3841
+ return;
3842
+ }
3843
+ const utterance = new SpeechSynthesisUtterance(resolvedSpeechText);
3844
+ utterance.onend = () => setSpeaking(false);
3845
+ utterance.onerror = () => setSpeaking(false);
3846
+ stopSpeech();
3847
+ window.speechSynthesis.speak(utterance);
3848
+ setSpeaking(true);
3849
+ }
3850
+ const menu = menuOpen ? /* @__PURE__ */ jsxs(
3851
+ "div",
3852
+ {
3853
+ className: "agent-message-actions__menu agent-message-actions__menu--portal",
3854
+ ref: portaledMenuRef,
3855
+ role: "menu",
3856
+ style: menuPosition ? {
3857
+ left: `${menuPosition.left}px`,
3858
+ top: `${menuPosition.top}px`
3859
+ } : { visibility: "hidden" },
3860
+ children: [
3861
+ answeredLabel ? /* @__PURE__ */ jsxs("p", { className: "agent-message-actions__menu-meta", children: [
3862
+ "Answered ",
3863
+ answeredLabel
3864
+ ] }) : null,
3865
+ canOpenReceipt ? /* @__PURE__ */ jsxs(
3866
+ "button",
3867
+ {
3868
+ type: "button",
3869
+ className: "agent-message-actions__menu-item",
3870
+ role: "menuitem",
3871
+ onClick: () => {
3872
+ setMenuOpen(false);
3873
+ onOpenReceipt?.();
3874
+ },
3875
+ children: [
3876
+ /* @__PURE__ */ jsx(SourcesIcon, {}),
3877
+ "View sources"
3878
+ ]
3879
+ }
3880
+ ) : null,
3881
+ canReadAloud ? /* @__PURE__ */ jsxs(
3882
+ "button",
3883
+ {
3884
+ type: "button",
3885
+ className: "agent-message-actions__menu-item",
3886
+ role: "menuitem",
3887
+ onClick: handleReadAloud,
3888
+ children: [
3889
+ speaking ? /* @__PURE__ */ jsx(StopIcon, {}) : /* @__PURE__ */ jsx(ReadAloudIcon, {}),
3890
+ speaking ? "Stop reading" : "Read aloud"
3891
+ ]
3892
+ }
3893
+ ) : null
3894
+ ]
3895
+ }
3896
+ ) : null;
3897
+ return /* @__PURE__ */ jsxs("div", { className: "agent-message-actions", "aria-label": "Answer actions", children: [
3898
+ /* @__PURE__ */ jsx(
3899
+ "button",
3900
+ {
3901
+ type: "button",
3902
+ className: `agent-message-actions__button${copied ? " is-copied" : ""}`,
3903
+ "aria-label": copied ? "Copied" : "Copy answer",
3904
+ title: copied ? "Copied" : "Copy answer",
3905
+ disabled,
3906
+ onClick: handleCopy,
3907
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
3908
+ }
3909
+ ),
3910
+ /* @__PURE__ */ jsx(
3911
+ "button",
3912
+ {
3913
+ type: "button",
3914
+ className: `agent-message-actions__button${rating === "positive" ? " is-active" : ""}`,
3915
+ "aria-label": "Good answer",
3916
+ "aria-pressed": rating === "positive",
3917
+ title: "Good answer",
3918
+ disabled,
3919
+ onClick: () => handleFeedback("positive"),
3920
+ children: /* @__PURE__ */ jsx(ThumbUpIcon, {})
3921
+ }
3922
+ ),
3923
+ /* @__PURE__ */ jsx(
3924
+ "button",
3925
+ {
3926
+ type: "button",
3927
+ className: `agent-message-actions__button${rating === "negative" ? " is-active" : ""}`,
3928
+ "aria-label": "Bad answer",
3929
+ "aria-pressed": rating === "negative",
3930
+ title: "Bad answer",
3931
+ disabled,
3932
+ onClick: () => handleFeedback("negative"),
3933
+ children: /* @__PURE__ */ jsx(ThumbDownIcon, {})
3934
+ }
3935
+ ),
3936
+ onRegenerate ? /* @__PURE__ */ jsx(
3937
+ "button",
3938
+ {
3939
+ type: "button",
3940
+ className: "agent-message-actions__button",
3941
+ "aria-label": "Regenerate answer",
3942
+ title: "Regenerate answer",
3943
+ disabled,
3944
+ onClick: onRegenerate,
3945
+ children: /* @__PURE__ */ jsx(RegenerateIcon, {})
3946
+ }
3947
+ ) : null,
3948
+ showMenu ? /* @__PURE__ */ jsxs("div", { className: "agent-message-actions__more", ref: menuRef, children: [
3949
+ /* @__PURE__ */ jsx(
3950
+ "button",
3951
+ {
3952
+ ref: moreButtonRef,
3953
+ type: "button",
3954
+ className: `agent-message-actions__button${menuOpen ? " is-menu-open" : ""}`,
3955
+ "aria-label": "More actions",
3956
+ "aria-haspopup": "menu",
3957
+ "aria-expanded": menuOpen,
3958
+ title: "More actions",
3959
+ disabled,
3960
+ onClick: () => setMenuOpen((open) => !open),
3961
+ children: /* @__PURE__ */ jsx(MoreIcon, {})
3962
+ }
3963
+ ),
3964
+ menuPortalRoot?.current && menu ? createPortal(menu, menuPortalRoot.current) : menu
3965
+ ] }) : null
3966
+ ] });
3967
+ }
3968
+
3247
3969
  // src/react/components/AgentRail/AgentRail.tsx
3248
- import { useEffect as useEffect4, useRef as useRef4, useState as useState8 } from "react";
3970
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState9 } from "react";
3249
3971
 
3250
3972
  // src/react/hooks/useAgentColorScheme.ts
3251
3973
  import { useSyncExternalStore } from "react";
@@ -3278,8 +4000,8 @@ function resolveAgentColorScheme(colorScheme = "auto", prefersDarkMode) {
3278
4000
  }
3279
4001
 
3280
4002
  // src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
3281
- import { useState as useState2 } from "react";
3282
- import { jsx, jsxs } from "react/jsx-runtime";
4003
+ import { useState as useState3 } from "react";
4004
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3283
4005
  function joinLabels(labels) {
3284
4006
  if (labels.length <= 1) return labels[0] ?? "";
3285
4007
  if (labels.length === 2) return `${labels[0]} and ${labels[1]}`;
@@ -3329,6 +4051,60 @@ function stepDetail(step, steps) {
3329
4051
  return "Searched this site";
3330
4052
  return step.detail;
3331
4053
  }
4054
+ function AgentWorkSteps({
4055
+ brandLabel = "",
4056
+ onRetryStep,
4057
+ steps
4058
+ }) {
4059
+ const delegationCount = steps.filter(
4060
+ (step) => step.kind === "specialist"
4061
+ ).length;
4062
+ const delegated = delegationCount > 0 && steps.some((step) => step.kind === "planning");
4063
+ const visibleSteps = steps.filter(
4064
+ (step) => step.kind !== "planning" || Boolean(brandLabel)
4065
+ );
4066
+ return /* @__PURE__ */ jsx2("ol", { className: "agent-activity-bubble__steps", children: visibleSteps.map((step) => {
4067
+ const detail = stepDetail(step, steps);
4068
+ const child = delegated && step.kind === "specialist";
4069
+ return /* @__PURE__ */ jsxs2(
4070
+ "li",
4071
+ {
4072
+ className: `agent-activity-bubble__step${child ? " agent-activity-bubble__step--child" : ""}`,
4073
+ "data-kind": step.kind,
4074
+ "data-state": step.state,
4075
+ children: [
4076
+ /* @__PURE__ */ jsx2(
4077
+ "span",
4078
+ {
4079
+ className: "agent-activity-bubble__step-icon",
4080
+ "aria-hidden": "true"
4081
+ }
4082
+ ),
4083
+ /* @__PURE__ */ jsxs2("span", { className: "agent-activity-bubble__step-copy", children: [
4084
+ /* @__PURE__ */ jsx2("span", { className: "agent-activity-bubble__step-heading", children: /* @__PURE__ */ jsx2("strong", { children: stepLabel(step, brandLabel) }) }),
4085
+ detail ? /* @__PURE__ */ jsx2("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null,
4086
+ delegated && step.kind === "planning" ? /* @__PURE__ */ jsxs2("span", { className: "agent-activity-bubble__delegation", children: [
4087
+ "Delegated ",
4088
+ delegationCount,
4089
+ " ",
4090
+ delegationCount === 1 ? "task" : "tasks"
4091
+ ] }) : null,
4092
+ step.state === "error" && onRetryStep ? /* @__PURE__ */ jsx2(
4093
+ "button",
4094
+ {
4095
+ type: "button",
4096
+ className: "agent-activity-bubble__step-retry",
4097
+ onClick: () => onRetryStep(step),
4098
+ children: "Retry"
4099
+ }
4100
+ ) : null
4101
+ ] })
4102
+ ]
4103
+ },
4104
+ step.id
4105
+ );
4106
+ }) });
4107
+ }
3332
4108
  function AgentActivityBubble({
3333
4109
  brandLabel = "",
3334
4110
  failed = false,
@@ -3337,37 +4113,30 @@ function AgentActivityBubble({
3337
4113
  }) {
3338
4114
  const active = steps.some((step) => step.state === "active");
3339
4115
  const receiptId = steps.map((step) => step.id).join(":");
3340
- const [expandedReceiptId, setExpandedReceiptId] = useState2(
4116
+ const [expandedReceiptId, setExpandedReceiptId] = useState3(
3341
4117
  null
3342
4118
  );
3343
- const detailsOpen = active || expandedReceiptId === receiptId;
3344
- const delegationCount = steps.filter(
3345
- (step) => step.kind === "specialist"
3346
- ).length;
3347
- const delegated = delegationCount > 0 && steps.some((step) => step.kind === "planning");
3348
- const visibleSteps = steps.filter(
3349
- (step) => step.kind !== "planning" || Boolean(brandLabel)
3350
- );
3351
- return /* @__PURE__ */ jsxs("article", { className: "agent-activity-bubble", children: [
3352
- /* @__PURE__ */ jsxs("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
3353
- /* @__PURE__ */ jsx(
4119
+ const detailsOpen = !active && expandedReceiptId === receiptId;
4120
+ return /* @__PURE__ */ jsxs2("article", { className: "agent-activity-bubble", children: [
4121
+ /* @__PURE__ */ jsxs2("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
4122
+ /* @__PURE__ */ jsx2(
3354
4123
  "span",
3355
4124
  {
3356
4125
  className: `agent-activity-bubble__pulse${active ? " is-active" : failed ? " is-error" : ""}`,
3357
4126
  "aria-hidden": "true"
3358
4127
  }
3359
4128
  ),
3360
- workSummary(steps, failed, brandLabel)
4129
+ workSummary(steps, failed, brandLabel),
4130
+ active ? "\u2026" : ""
3361
4131
  ] }),
3362
- /* @__PURE__ */ jsxs("div", { className: "agent-activity-bubble__details", children: [
3363
- /* @__PURE__ */ jsx(
4132
+ !active ? /* @__PURE__ */ jsxs2("div", { className: "agent-activity-bubble__details", children: [
4133
+ /* @__PURE__ */ jsx2(
3364
4134
  "button",
3365
4135
  {
3366
4136
  type: "button",
3367
4137
  className: "agent-activity-bubble__summary",
3368
4138
  "aria-expanded": detailsOpen,
3369
4139
  onClick: () => {
3370
- if (active) return;
3371
4140
  setExpandedReceiptId(
3372
4141
  (current) => current === receiptId ? null : receiptId
3373
4142
  );
@@ -3375,61 +4144,138 @@ function AgentActivityBubble({
3375
4144
  children: "How this answer was made"
3376
4145
  }
3377
4146
  ),
3378
- detailsOpen ? /* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: visibleSteps.map((step) => {
3379
- const detail = stepDetail(step, steps);
3380
- const child = delegated && step.kind === "specialist";
3381
- return /* @__PURE__ */ jsxs(
3382
- "li",
3383
- {
3384
- className: `agent-activity-bubble__step${child ? " agent-activity-bubble__step--child" : ""}`,
3385
- "data-kind": step.kind,
3386
- "data-state": step.state,
3387
- children: [
3388
- /* @__PURE__ */ jsx(
3389
- "span",
3390
- {
3391
- className: "agent-activity-bubble__step-icon",
3392
- "aria-hidden": "true"
3393
- }
3394
- ),
3395
- /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
3396
- /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-heading", children: /* @__PURE__ */ jsx("strong", { children: stepLabel(step, brandLabel) }) }),
3397
- detail ? /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null,
3398
- delegated && step.kind === "planning" ? /* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__delegation", children: [
3399
- "Delegated ",
3400
- delegationCount,
3401
- " ",
3402
- delegationCount === 1 ? "task" : "tasks"
3403
- ] }) : null,
3404
- step.state === "error" && onRetryStep ? /* @__PURE__ */ jsx(
3405
- "button",
3406
- {
3407
- type: "button",
3408
- className: "agent-activity-bubble__step-retry",
3409
- onClick: () => onRetryStep(step),
3410
- children: "Retry"
3411
- }
3412
- ) : null
3413
- ] })
3414
- ]
3415
- },
3416
- step.id
3417
- );
3418
- }) }) : null
3419
- ] })
4147
+ detailsOpen ? /* @__PURE__ */ jsx2(
4148
+ AgentWorkSteps,
4149
+ {
4150
+ brandLabel,
4151
+ onRetryStep,
4152
+ steps
4153
+ }
4154
+ ) : null
4155
+ ] }) : null
4156
+ ] });
4157
+ }
4158
+
4159
+ // src/react/components/AnswerReceiptDialog/AnswerReceiptDialog.tsx
4160
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
4161
+ import { createPortal as createPortal2 } from "react-dom";
4162
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
4163
+ var FOCUSABLE_SELECTOR = 'button:not(:disabled), a[href], textarea:not(:disabled), input:not(:disabled), [tabindex]:not([tabindex="-1"])';
4164
+ function CloseIcon() {
4165
+ return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
4166
+ "path",
4167
+ {
4168
+ d: "M4 4l8 8M12 4l-8 8",
4169
+ stroke: "currentColor",
4170
+ strokeWidth: "1.5",
4171
+ strokeLinecap: "round"
4172
+ }
4173
+ ) });
4174
+ }
4175
+ function AnswerReceiptDialog({
4176
+ brandLabel = "",
4177
+ onClose,
4178
+ steps
4179
+ }) {
4180
+ const portalRoots = useAgentRailPortalRoots();
4181
+ const overlayRoot = portalRoots?.overlayRef ?? null;
4182
+ const cardRef = useRef3(null);
4183
+ const closeButtonRef = useRef3(null);
4184
+ const previouslyFocusedRef = useRef3(null);
4185
+ useEffect3(() => {
4186
+ previouslyFocusedRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4187
+ closeButtonRef.current?.focus({ preventScroll: true });
4188
+ const handleKeyDown = (event) => {
4189
+ if (event.key === "Escape") {
4190
+ event.preventDefault();
4191
+ event.stopPropagation();
4192
+ onClose();
4193
+ return;
4194
+ }
4195
+ if (event.key !== "Tab" || !cardRef.current) return;
4196
+ const focusable = cardRef.current.querySelectorAll(
4197
+ FOCUSABLE_SELECTOR
4198
+ );
4199
+ if (focusable.length === 0) return;
4200
+ const first = focusable.item(0);
4201
+ const last = focusable.item(focusable.length - 1);
4202
+ if (event.shiftKey && document.activeElement === first) {
4203
+ event.preventDefault();
4204
+ last.focus({ preventScroll: true });
4205
+ } else if (!event.shiftKey && document.activeElement === last) {
4206
+ event.preventDefault();
4207
+ first.focus({ preventScroll: true });
4208
+ }
4209
+ };
4210
+ document.addEventListener("keydown", handleKeyDown);
4211
+ return () => {
4212
+ document.removeEventListener("keydown", handleKeyDown);
4213
+ previouslyFocusedRef.current?.focus({ preventScroll: true });
4214
+ };
4215
+ }, [onClose]);
4216
+ const content = /* @__PURE__ */ jsxs3("div", { className: "agent-receipt-dialog", children: [
4217
+ /* @__PURE__ */ jsx3(
4218
+ "button",
4219
+ {
4220
+ type: "button",
4221
+ className: "agent-receipt-dialog__backdrop",
4222
+ "aria-label": "Close",
4223
+ tabIndex: -1,
4224
+ onClick: onClose
4225
+ }
4226
+ ),
4227
+ /* @__PURE__ */ jsxs3(
4228
+ "div",
4229
+ {
4230
+ ref: cardRef,
4231
+ className: "agent-receipt-dialog__card",
4232
+ role: "dialog",
4233
+ "aria-modal": "true",
4234
+ "aria-labelledby": "agent-receipt-dialog-title",
4235
+ children: [
4236
+ /* @__PURE__ */ jsxs3("div", { className: "agent-receipt-dialog__header", children: [
4237
+ /* @__PURE__ */ jsx3(
4238
+ "p",
4239
+ {
4240
+ className: "agent-receipt-dialog__title",
4241
+ id: "agent-receipt-dialog-title",
4242
+ children: "How this answer was made"
4243
+ }
4244
+ ),
4245
+ /* @__PURE__ */ jsx3(
4246
+ "button",
4247
+ {
4248
+ ref: closeButtonRef,
4249
+ type: "button",
4250
+ className: "agent-receipt-dialog__close",
4251
+ "aria-label": "Close",
4252
+ onClick: onClose,
4253
+ children: /* @__PURE__ */ jsx3(CloseIcon, {})
4254
+ }
4255
+ )
4256
+ ] }),
4257
+ /* @__PURE__ */ jsx3("p", { className: "agent-receipt-dialog__summary", children: workSummary(steps, false, brandLabel) }),
4258
+ /* @__PURE__ */ jsx3("div", { className: "agent-receipt-dialog__body", children: /* @__PURE__ */ jsx3(AgentWorkSteps, { brandLabel, steps }) })
4259
+ ]
4260
+ }
4261
+ )
3420
4262
  ] });
4263
+ if (overlayRoot?.current) {
4264
+ return createPortal2(content, overlayRoot.current);
4265
+ }
4266
+ return content;
3421
4267
  }
3422
4268
 
3423
4269
  // src/react/components/Composer/Composer.tsx
3424
4270
  import {
3425
- useEffect as useEffect2,
4271
+ useEffect as useEffect4,
3426
4272
  useId,
3427
- useRef as useRef2,
3428
- useState as useState3
4273
+ useRef as useRef4,
4274
+ useState as useState4
3429
4275
  } from "react";
3430
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
4276
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3431
4277
  function SendIcon() {
3432
- return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
4278
+ return /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
3433
4279
  "path",
3434
4280
  {
3435
4281
  d: "M8 12V4M8 4l-3 3M8 4l3 3",
@@ -3452,21 +4298,21 @@ function Composer({
3452
4298
  form = null,
3453
4299
  onSubmit
3454
4300
  }) {
3455
- const [value, setValue] = useState3("");
3456
- const [values, setValues] = useState3(
4301
+ const [value, setValue] = useState4("");
4302
+ const [values, setValues] = useState4(
3457
4303
  () => emptyValues(form)
3458
4304
  );
3459
- const [blurred, setBlurred] = useState3({});
3460
- const inputRef = useRef2(null);
3461
- const firstFieldRef = useRef2(null);
4305
+ const [blurred, setBlurred] = useState4({});
4306
+ const inputRef = useRef4(null);
4307
+ const firstFieldRef = useRef4(null);
3462
4308
  const formId = useId();
3463
4309
  const activeForm = form;
3464
4310
  const canSendForm = activeForm ? isComposerFormComplete(activeForm, values) : Boolean(value.trim());
3465
- useEffect2(() => {
4311
+ useEffect4(() => {
3466
4312
  setValues(emptyValues(form));
3467
4313
  setBlurred({});
3468
4314
  }, [form?.id]);
3469
- useEffect2(() => {
4315
+ useEffect4(() => {
3470
4316
  if (activeForm) firstFieldRef.current?.focus();
3471
4317
  }, [activeForm?.id]);
3472
4318
  function submitChat() {
@@ -3501,7 +4347,7 @@ function Composer({
3501
4347
  submitForm();
3502
4348
  }
3503
4349
  }
3504
- return /* @__PURE__ */ jsx2(
4350
+ return /* @__PURE__ */ jsx4(
3505
4351
  "form",
3506
4352
  {
3507
4353
  className: [
@@ -3510,7 +4356,7 @@ function Composer({
3510
4356
  activeForm ? "composer--form" : ""
3511
4357
  ].filter(Boolean).join(" "),
3512
4358
  onSubmit: handleSubmit,
3513
- children: activeForm ? /* @__PURE__ */ jsxs2("div", { className: "composer__sheet", role: "group", "aria-label": "Required details", children: [
4359
+ children: activeForm ? /* @__PURE__ */ jsxs4("div", { className: "composer__sheet", role: "group", "aria-label": "Required details", children: [
3514
4360
  activeForm.fields.map((field, index) => {
3515
4361
  const fieldId = `${formId}-${field.id}`;
3516
4362
  const invalid = Boolean(blurred[field.id]) && !isValidComposerFieldValue(field, values[field.id] ?? "");
@@ -3535,7 +4381,7 @@ function Composer({
3535
4381
  },
3536
4382
  onKeyDown: handleFormKeyDown
3537
4383
  };
3538
- return /* @__PURE__ */ jsxs2(
4384
+ return /* @__PURE__ */ jsxs4(
3539
4385
  "div",
3540
4386
  {
3541
4387
  className: [
@@ -3543,9 +4389,9 @@ function Composer({
3543
4389
  field.kind === "textarea" ? "composer__row--grow" : ""
3544
4390
  ].filter(Boolean).join(" "),
3545
4391
  children: [
3546
- /* @__PURE__ */ jsxs2("label", { className: "composer__label", htmlFor: fieldId, children: [
3547
- /* @__PURE__ */ jsx2("span", { className: "composer__sr-only", children: field.label }),
3548
- field.kind === "textarea" ? /* @__PURE__ */ jsx2(
4392
+ /* @__PURE__ */ jsxs4("label", { className: "composer__label", htmlFor: fieldId, children: [
4393
+ /* @__PURE__ */ jsx4("span", { className: "composer__sr-only", children: field.label }),
4394
+ field.kind === "textarea" ? /* @__PURE__ */ jsx4(
3549
4395
  "textarea",
3550
4396
  {
3551
4397
  ...controlProps,
@@ -3555,7 +4401,7 @@ function Composer({
3555
4401
  className: "composer__control composer__control--area",
3556
4402
  rows: 3
3557
4403
  }
3558
- ) : /* @__PURE__ */ jsx2(
4404
+ ) : /* @__PURE__ */ jsx4(
3559
4405
  "input",
3560
4406
  {
3561
4407
  ...controlProps,
@@ -3568,24 +4414,24 @@ function Composer({
3568
4414
  }
3569
4415
  )
3570
4416
  ] }),
3571
- invalid ? /* @__PURE__ */ jsx2("p", { className: "composer__error", id: `${fieldId}-error`, children: field.kind === "email" ? "Enter a valid email to continue." : `Add your ${field.label.toLowerCase()} to continue.` }) : null
4417
+ invalid ? /* @__PURE__ */ jsx4("p", { className: "composer__error", id: `${fieldId}-error`, children: field.kind === "email" ? "Enter a valid email to continue." : `Add your ${field.label.toLowerCase()} to continue.` }) : null
3572
4418
  ]
3573
4419
  },
3574
4420
  field.id
3575
4421
  );
3576
4422
  }),
3577
- /* @__PURE__ */ jsx2("div", { className: "composer__toolbar", children: /* @__PURE__ */ jsx2(
4423
+ /* @__PURE__ */ jsx4("div", { className: "composer__toolbar", children: /* @__PURE__ */ jsx4(
3578
4424
  "button",
3579
4425
  {
3580
4426
  type: "submit",
3581
4427
  className: "composer__send",
3582
4428
  disabled: disabled || !canSendForm,
3583
4429
  "aria-label": "Send details",
3584
- children: /* @__PURE__ */ jsx2(SendIcon, {})
4430
+ children: /* @__PURE__ */ jsx4(SendIcon, {})
3585
4431
  }
3586
4432
  ) })
3587
- ] }) : /* @__PURE__ */ jsxs2("div", { className: "composer__field", children: [
3588
- /* @__PURE__ */ jsx2(
4433
+ ] }) : /* @__PURE__ */ jsxs4("div", { className: "composer__field", children: [
4434
+ /* @__PURE__ */ jsx4(
3589
4435
  "textarea",
3590
4436
  {
3591
4437
  ref: inputRef,
@@ -3600,14 +4446,14 @@ function Composer({
3600
4446
  onKeyDown: handleChatKeyDown
3601
4447
  }
3602
4448
  ),
3603
- /* @__PURE__ */ jsx2(
4449
+ /* @__PURE__ */ jsx4(
3604
4450
  "button",
3605
4451
  {
3606
4452
  type: "submit",
3607
4453
  className: "composer__send",
3608
4454
  disabled: disabled || !value.trim(),
3609
4455
  "aria-label": "Send message",
3610
- children: /* @__PURE__ */ jsx2(SendIcon, {})
4456
+ children: /* @__PURE__ */ jsx4(SendIcon, {})
3611
4457
  }
3612
4458
  )
3613
4459
  ] })
@@ -3616,7 +4462,7 @@ function Composer({
3616
4462
  }
3617
4463
 
3618
4464
  // src/react/components/FollowUpChips/FollowUpChips.tsx
3619
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
4465
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
3620
4466
  function FollowUpChips({
3621
4467
  suggestions,
3622
4468
  disabled = false,
@@ -3626,7 +4472,7 @@ function FollowUpChips({
3626
4472
  }) {
3627
4473
  if (suggestions.length === 0) return null;
3628
4474
  if (variant === "dock") {
3629
- return /* @__PURE__ */ jsx3("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx3("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx3(
4475
+ return /* @__PURE__ */ jsx5("div", { className: "followups followups--dock", children: /* @__PURE__ */ jsx5("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx5(
3630
4476
  "button",
3631
4477
  {
3632
4478
  type: "button",
@@ -3638,9 +4484,9 @@ function FollowUpChips({
3638
4484
  suggestion.id
3639
4485
  )) }) });
3640
4486
  }
3641
- return /* @__PURE__ */ jsxs3("div", { className: "followups", children: [
3642
- /* @__PURE__ */ jsx3("span", { className: "followups__label", children: label }),
3643
- /* @__PURE__ */ jsx3("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx3(
4487
+ return /* @__PURE__ */ jsxs5("div", { className: "followups", children: [
4488
+ /* @__PURE__ */ jsx5("span", { className: "followups__label", children: label }),
4489
+ /* @__PURE__ */ jsx5("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx5(
3644
4490
  "button",
3645
4491
  {
3646
4492
  type: "button",
@@ -3655,17 +4501,17 @@ function FollowUpChips({
3655
4501
  }
3656
4502
 
3657
4503
  // src/react/components/MessageBubble/MessageBubble.tsx
3658
- import { useState as useState5 } from "react";
4504
+ import { useState as useState6 } from "react";
3659
4505
 
3660
4506
  // src/react/components/BookingCard/BookingCard.tsx
3661
4507
  import {
3662
- useEffect as useEffect3,
4508
+ useEffect as useEffect5,
3663
4509
  useId as useId2,
3664
4510
  useMemo as useMemo2,
3665
- useRef as useRef3,
3666
- useState as useState4
4511
+ useRef as useRef5,
4512
+ useState as useState5
3667
4513
  } from "react";
3668
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4514
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
3669
4515
  var BOOKING_STEPS = [
3670
4516
  { id: "date", label: "Date" },
3671
4517
  { id: "time", label: "Time" },
@@ -3696,7 +4542,7 @@ function calendarCells(year, month) {
3696
4542
  return cells;
3697
4543
  }
3698
4544
  function BookingCardLoader() {
3699
- return /* @__PURE__ */ jsx4("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsx4("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) });
4545
+ return /* @__PURE__ */ jsx6("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsx6("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) });
3700
4546
  }
3701
4547
  function BookingCard({
3702
4548
  disabled = false,
@@ -3705,16 +4551,16 @@ function BookingCard({
3705
4551
  }) {
3706
4552
  const fieldId = useId2();
3707
4553
  const defaultType = offer.eventTypes[0]?.uri ?? offer.slots[0]?.eventTypeUri ?? "";
3708
- const [step, setStep] = useState4("date");
3709
- const [eventTypeUri, setEventTypeUri] = useState4(defaultType);
3710
- const [selectedDate, setSelectedDate] = useState4("");
3711
- const [startTime, setStartTime] = useState4("");
3712
- const [name, setName] = useState4("");
3713
- const [email, setEmail] = useState4("");
3714
- const activeStepRef = useRef3(null);
3715
- const previousStepRef = useRef3(step);
4554
+ const [step, setStep] = useState5("date");
4555
+ const [eventTypeUri, setEventTypeUri] = useState5(defaultType);
4556
+ const [selectedDate, setSelectedDate] = useState5("");
4557
+ const [startTime, setStartTime] = useState5("");
4558
+ const [name, setName] = useState5("");
4559
+ const [email, setEmail] = useState5("");
4560
+ const activeStepRef = useRef5(null);
4561
+ const previousStepRef = useRef5(step);
3716
4562
  const stepIndex = BOOKING_STEPS.findIndex((item) => item.id === step);
3717
- useEffect3(() => {
4563
+ useEffect5(() => {
3718
4564
  if (previousStepRef.current === step) return;
3719
4565
  previousStepRef.current = step;
3720
4566
  activeStepRef.current?.scrollIntoView({ block: "nearest" });
@@ -3731,7 +4577,7 @@ function BookingCard({
3731
4577
  }
3732
4578
  return next;
3733
4579
  }, [slots]);
3734
- const [visibleMonth, setVisibleMonth] = useState4(
4580
+ const [visibleMonth, setVisibleMonth] = useState5(
3735
4581
  () => firstAvailableBookingMonth(slots)
3736
4582
  );
3737
4583
  function selectEventType(nextType) {
@@ -3795,14 +4641,14 @@ function BookingCard({
3795
4641
  })
3796
4642
  });
3797
4643
  }
3798
- return /* @__PURE__ */ jsx4(
4644
+ return /* @__PURE__ */ jsx6(
3799
4645
  "section",
3800
4646
  {
3801
4647
  className: "booking-card",
3802
4648
  "aria-busy": disabled || void 0,
3803
4649
  "aria-label": "Book a meeting",
3804
- children: /* @__PURE__ */ jsxs4("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3805
- /* @__PURE__ */ jsx4("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ jsxs4(
4650
+ children: /* @__PURE__ */ jsxs6("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
4651
+ /* @__PURE__ */ jsx6("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ jsxs6(
3806
4652
  "li",
3807
4653
  {
3808
4654
  className: [
@@ -3812,40 +4658,40 @@ function BookingCard({
3812
4658
  ].filter(Boolean).join(" "),
3813
4659
  "aria-current": index === stepIndex ? "step" : void 0,
3814
4660
  children: [
3815
- /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: index + 1 }),
3816
- /* @__PURE__ */ jsx4("span", { children: item.label })
4661
+ /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: index + 1 }),
4662
+ /* @__PURE__ */ jsx6("span", { children: item.label })
3817
4663
  ]
3818
4664
  },
3819
4665
  item.id
3820
4666
  )) }),
3821
- step === "date" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3822
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3823
- timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
4667
+ step === "date" ? /* @__PURE__ */ jsxs6("div", { className: "booking-card__step", ref: activeStepRef, children: [
4668
+ /* @__PURE__ */ jsx6("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
4669
+ timeZone ? /* @__PURE__ */ jsxs6("p", { className: "booking-card__tz", children: [
3824
4670
  "Times in ",
3825
4671
  timeZone
3826
4672
  ] }) : null,
3827
- offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs4(
4673
+ offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs6(
3828
4674
  "label",
3829
4675
  {
3830
4676
  className: "booking-card__field",
3831
4677
  htmlFor: `${fieldId}-type`,
3832
4678
  children: [
3833
- /* @__PURE__ */ jsx4("span", { children: "Meeting" }),
3834
- /* @__PURE__ */ jsx4(
4679
+ /* @__PURE__ */ jsx6("span", { children: "Meeting" }),
4680
+ /* @__PURE__ */ jsx6(
3835
4681
  "select",
3836
4682
  {
3837
4683
  id: `${fieldId}-type`,
3838
4684
  value: eventTypeUri,
3839
4685
  disabled,
3840
4686
  onChange: (event) => selectEventType(event.target.value),
3841
- children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx4("option", { value: item.uri, children: item.name }, item.uri))
4687
+ children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx6("option", { value: item.uri, children: item.name }, item.uri))
3842
4688
  }
3843
4689
  )
3844
4690
  ]
3845
4691
  }
3846
4692
  ) : null,
3847
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__month", children: [
3848
- /* @__PURE__ */ jsx4(
4693
+ /* @__PURE__ */ jsxs6("div", { className: "booking-card__month", children: [
4694
+ /* @__PURE__ */ jsx6(
3849
4695
  "button",
3850
4696
  {
3851
4697
  type: "button",
@@ -3856,8 +4702,8 @@ function BookingCard({
3856
4702
  children: "\u2039"
3857
4703
  }
3858
4704
  ),
3859
- /* @__PURE__ */ jsx4("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3860
- /* @__PURE__ */ jsx4(
4705
+ /* @__PURE__ */ jsx6("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
4706
+ /* @__PURE__ */ jsx6(
3861
4707
  "button",
3862
4708
  {
3863
4709
  type: "button",
@@ -3869,9 +4715,9 @@ function BookingCard({
3869
4715
  }
3870
4716
  )
3871
4717
  ] }),
3872
- /* @__PURE__ */ jsx4("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx4("span", { children: label }, label)) }),
3873
- offer.slots.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3874
- /* @__PURE__ */ jsx4(
4718
+ /* @__PURE__ */ jsx6("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx6("span", { children: label }, label)) }),
4719
+ offer.slots.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
4720
+ /* @__PURE__ */ jsx6(
3875
4721
  "div",
3876
4722
  {
3877
4723
  className: "booking-card__calendar",
@@ -3879,7 +4725,7 @@ function BookingCard({
3879
4725
  "aria-label": "Available dates",
3880
4726
  children: cells.map((cell, index) => {
3881
4727
  if (!cell) {
3882
- return /* @__PURE__ */ jsx4(
4728
+ return /* @__PURE__ */ jsx6(
3883
4729
  "span",
3884
4730
  {
3885
4731
  className: "booking-card__day"
@@ -3889,7 +4735,7 @@ function BookingCard({
3889
4735
  }
3890
4736
  const available = availableByDate.has(cell.key);
3891
4737
  const selected = cell.key === selectedDate;
3892
- return /* @__PURE__ */ jsx4(
4738
+ return /* @__PURE__ */ jsx6(
3893
4739
  "button",
3894
4740
  {
3895
4741
  type: "button",
@@ -3909,9 +4755,9 @@ function BookingCard({
3909
4755
  }
3910
4756
  )
3911
4757
  ] }, "date") : null,
3912
- step === "time" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3913
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3914
- /* @__PURE__ */ jsx4(
4758
+ step === "time" ? /* @__PURE__ */ jsxs6("div", { className: "booking-card__step", ref: activeStepRef, children: [
4759
+ /* @__PURE__ */ jsxs6("div", { className: "booking-card__step-bar", children: [
4760
+ /* @__PURE__ */ jsx6(
3915
4761
  "button",
3916
4762
  {
3917
4763
  type: "button",
@@ -3922,15 +4768,15 @@ function BookingCard({
3922
4768
  children: "\u2039"
3923
4769
  }
3924
4770
  ),
3925
- /* @__PURE__ */ jsxs4("div", { children: [
3926
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3927
- timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
4771
+ /* @__PURE__ */ jsxs6("div", { children: [
4772
+ /* @__PURE__ */ jsx6("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
4773
+ timeZone ? /* @__PURE__ */ jsxs6("p", { className: "booking-card__tz", children: [
3928
4774
  "Times in ",
3929
4775
  timeZone
3930
4776
  ] }) : null
3931
4777
  ] })
3932
4778
  ] }),
3933
- /* @__PURE__ */ jsx4("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
4779
+ /* @__PURE__ */ jsx6("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx6(
3934
4780
  "button",
3935
4781
  {
3936
4782
  type: "button",
@@ -3942,9 +4788,9 @@ function BookingCard({
3942
4788
  slot.startTime
3943
4789
  )) })
3944
4790
  ] }, "time") : null,
3945
- step === "details" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3946
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3947
- /* @__PURE__ */ jsx4(
4791
+ step === "details" ? /* @__PURE__ */ jsxs6("div", { className: "booking-card__step", ref: activeStepRef, children: [
4792
+ /* @__PURE__ */ jsxs6("div", { className: "booking-card__step-bar", children: [
4793
+ /* @__PURE__ */ jsx6(
3948
4794
  "button",
3949
4795
  {
3950
4796
  type: "button",
@@ -3955,21 +4801,21 @@ function BookingCard({
3955
4801
  children: "\u2039"
3956
4802
  }
3957
4803
  ),
3958
- /* @__PURE__ */ jsxs4("div", { children: [
3959
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: "Enter details" }),
3960
- /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
3961
- selectedType?.location ? /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: selectedType.location }) : null
4804
+ /* @__PURE__ */ jsxs6("div", { children: [
4805
+ /* @__PURE__ */ jsx6("p", { className: "booking-card__title", children: "Enter details" }),
4806
+ /* @__PURE__ */ jsx6("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4807
+ selectedType?.location ? /* @__PURE__ */ jsx6("p", { className: "booking-card__tz", children: selectedType.location }) : null
3962
4808
  ] })
3963
4809
  ] }),
3964
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__identity", children: [
3965
- /* @__PURE__ */ jsxs4(
4810
+ /* @__PURE__ */ jsxs6("div", { className: "booking-card__identity", children: [
4811
+ /* @__PURE__ */ jsxs6(
3966
4812
  "label",
3967
4813
  {
3968
4814
  className: "booking-card__field",
3969
4815
  htmlFor: `${fieldId}-name`,
3970
4816
  children: [
3971
- /* @__PURE__ */ jsx4("span", { children: "Name" }),
3972
- /* @__PURE__ */ jsx4(
4817
+ /* @__PURE__ */ jsx6("span", { children: "Name" }),
4818
+ /* @__PURE__ */ jsx6(
3973
4819
  "input",
3974
4820
  {
3975
4821
  id: `${fieldId}-name`,
@@ -3983,14 +4829,14 @@ function BookingCard({
3983
4829
  ]
3984
4830
  }
3985
4831
  ),
3986
- /* @__PURE__ */ jsxs4(
4832
+ /* @__PURE__ */ jsxs6(
3987
4833
  "label",
3988
4834
  {
3989
4835
  className: "booking-card__field",
3990
4836
  htmlFor: `${fieldId}-email`,
3991
4837
  children: [
3992
- /* @__PURE__ */ jsx4("span", { children: "Email" }),
3993
- /* @__PURE__ */ jsx4(
4838
+ /* @__PURE__ */ jsx6("span", { children: "Email" }),
4839
+ /* @__PURE__ */ jsx6(
3994
4840
  "input",
3995
4841
  {
3996
4842
  id: `${fieldId}-email`,
@@ -4006,7 +4852,7 @@ function BookingCard({
4006
4852
  }
4007
4853
  )
4008
4854
  ] }),
4009
- /* @__PURE__ */ jsx4(
4855
+ /* @__PURE__ */ jsx6(
4010
4856
  "button",
4011
4857
  {
4012
4858
  type: "submit",
@@ -4024,7 +4870,7 @@ function BookingCard({
4024
4870
  // src/react/components/MessageBubble/MessageBubble.tsx
4025
4871
  import { Streamdown } from "streamdown";
4026
4872
  import "streamdown/styles.css";
4027
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4873
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
4028
4874
  function normalizeDedupeText(text) {
4029
4875
  return text.trim().replace(/\s+/g, " ").toLowerCase();
4030
4876
  }
@@ -4068,7 +4914,7 @@ function MessageBubble({
4068
4914
  onBook
4069
4915
  }) {
4070
4916
  const resolvedLogoUrl = brandLogoUrl?.trim();
4071
- const [failedLogoUrl, setFailedLogoUrl] = useState5(null);
4917
+ const [failedLogoUrl, setFailedLogoUrl] = useState6(null);
4072
4918
  const showBrandLogo = Boolean(resolvedLogoUrl) && failedLogoUrl !== resolvedLogoUrl;
4073
4919
  const cards = message.role === "agent" ? extractToolCards(message.text) : [];
4074
4920
  const extractedOffers = cards.filter(
@@ -4081,11 +4927,11 @@ function MessageBubble({
4081
4927
  offers.length > 0 ? sanitizeBookingOfferCopy(visibleText) : looksLikeBookingAvailabilityDump(visibleText) ? sanitizeBookingOfferCopy(visibleText) : visibleText || (isStreaming ? "" : message.text)
4082
4928
  );
4083
4929
  if (message.role === "visitor") {
4084
- return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx5("p", { className: "message-bubble__text", children: message.text }) });
4930
+ return /* @__PURE__ */ jsx7("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx7("p", { className: "message-bubble__text", children: message.text }) });
4085
4931
  }
4086
4932
  const citations = message.citations ?? [];
4087
- const agentText = /* @__PURE__ */ jsxs5("div", { className: "message-bubble__text", children: [
4088
- /* @__PURE__ */ jsx5(
4933
+ const agentText = /* @__PURE__ */ jsxs7("div", { className: "message-bubble__text", children: [
4934
+ /* @__PURE__ */ jsx7(
4089
4935
  Streamdown,
4090
4936
  {
4091
4937
  animated: isStreaming,
@@ -4099,8 +4945,8 @@ function MessageBubble({
4099
4945
  children: displayText
4100
4946
  }
4101
4947
  ),
4102
- citations.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs5("a", { href: citation.url, target: "_blank", rel: "noreferrer", children: [
4103
- /* @__PURE__ */ jsx5(
4948
+ citations.length > 0 ? /* @__PURE__ */ jsx7("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsxs7("a", { href: citation.url, target: "_blank", rel: "noreferrer", children: [
4949
+ /* @__PURE__ */ jsx7(
4104
4950
  "span",
4105
4951
  {
4106
4952
  className: "message-bubble__source-icon",
@@ -4108,12 +4954,12 @@ function MessageBubble({
4108
4954
  children: "\u25A6"
4109
4955
  }
4110
4956
  ),
4111
- /* @__PURE__ */ jsx5("span", { children: citation.label })
4957
+ /* @__PURE__ */ jsx7("span", { children: citation.label })
4112
4958
  ] }) }, citation.id)) }) : null
4113
4959
  ] });
4114
- return /* @__PURE__ */ jsxs5("article", { className: "message-bubble message-bubble--agent", children: [
4115
- displayText ? showBrandLogo ? /* @__PURE__ */ jsxs5("div", { className: "message-bubble__agent-row", children: [
4116
- /* @__PURE__ */ jsx5("span", { className: "message-bubble__agent-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
4960
+ return /* @__PURE__ */ jsxs7("article", { className: "message-bubble message-bubble--agent", children: [
4961
+ displayText ? showBrandLogo ? /* @__PURE__ */ jsxs7("div", { className: "message-bubble__agent-row", children: [
4962
+ /* @__PURE__ */ jsx7("span", { className: "message-bubble__agent-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
4117
4963
  "img",
4118
4964
  {
4119
4965
  src: resolvedLogoUrl,
@@ -4125,7 +4971,7 @@ function MessageBubble({
4125
4971
  ) }),
4126
4972
  agentText
4127
4973
  ] }) : agentText : null,
4128
- offers.map((nextOffer, index) => /* @__PURE__ */ jsx5(
4974
+ offers.map((nextOffer, index) => /* @__PURE__ */ jsx7(
4129
4975
  BookingCard,
4130
4976
  {
4131
4977
  disabled: bookingDisabled,
@@ -4138,10 +4984,10 @@ function MessageBubble({
4138
4984
  }
4139
4985
 
4140
4986
  // src/react/components/HumanInputCard/HumanInputCard.tsx
4141
- import { useState as useState7 } from "react";
4987
+ import { useState as useState8 } from "react";
4142
4988
 
4143
4989
  // src/react/components/ConfirmationCard/ConfirmationCard.tsx
4144
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
4990
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4145
4991
  function ConfirmationCard({
4146
4992
  disabled = false,
4147
4993
  request,
@@ -4150,17 +4996,17 @@ function ConfirmationCard({
4150
4996
  const options = request.options ?? [];
4151
4997
  const heading = request.kind === "tool-approval" ? "Confirm this action" : request.prompt;
4152
4998
  const prompt = request.kind === "tool-approval" ? request.prompt : void 0;
4153
- return /* @__PURE__ */ jsxs6(
4999
+ return /* @__PURE__ */ jsxs8(
4154
5000
  "section",
4155
5001
  {
4156
5002
  className: "confirmation-card",
4157
5003
  "aria-labelledby": `confirmation-${request.requestId}`,
4158
5004
  children: [
4159
- /* @__PURE__ */ jsxs6("div", { className: "confirmation-card__heading", children: [
4160
- /* @__PURE__ */ jsx6("strong", { id: `confirmation-${request.requestId}`, children: heading }),
4161
- prompt ? /* @__PURE__ */ jsx6("p", { children: prompt }) : null
5005
+ /* @__PURE__ */ jsxs8("div", { className: "confirmation-card__heading", children: [
5006
+ /* @__PURE__ */ jsx8("strong", { id: `confirmation-${request.requestId}`, children: heading }),
5007
+ prompt ? /* @__PURE__ */ jsx8("p", { children: prompt }) : null
4162
5008
  ] }),
4163
- /* @__PURE__ */ jsx6("div", { className: "confirmation-card__actions", children: options.map((option) => /* @__PURE__ */ jsx6(
5009
+ /* @__PURE__ */ jsx8("div", { className: "confirmation-card__actions", children: options.map((option) => /* @__PURE__ */ jsx8(
4164
5010
  "button",
4165
5011
  {
4166
5012
  type: "button",
@@ -4180,8 +5026,8 @@ function ConfirmationCard({
4180
5026
  }
4181
5027
 
4182
5028
  // src/react/components/ToolInputCard/ToolInputCard.tsx
4183
- import { useState as useState6 } from "react";
4184
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
5029
+ import { useState as useState7 } from "react";
5030
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
4185
5031
  function isRecord5(value) {
4186
5032
  return value !== null && typeof value === "object" && !Array.isArray(value);
4187
5033
  }
@@ -4305,7 +5151,7 @@ function FieldDescription({
4305
5151
  field,
4306
5152
  id
4307
5153
  }) {
4308
- return field.description ? /* @__PURE__ */ jsx7("span", { id, className: "tool-input-card__description", children: field.description }) : null;
5154
+ return field.description ? /* @__PURE__ */ jsx9("span", { id, className: "tool-input-card__description", children: field.description }) : null;
4309
5155
  }
4310
5156
  function ChoiceField({
4311
5157
  field,
@@ -4324,7 +5170,7 @@ function ChoiceField({
4324
5170
  const selectedIndex = options.findIndex(
4325
5171
  (option) => valuesMatch(option.value, value)
4326
5172
  );
4327
- return /* @__PURE__ */ jsxs7(
5173
+ return /* @__PURE__ */ jsxs9(
4328
5174
  "select",
4329
5175
  {
4330
5176
  id,
@@ -4339,13 +5185,13 @@ function ChoiceField({
4339
5185
  if (option) onChange(option.value);
4340
5186
  },
4341
5187
  children: [
4342
- /* @__PURE__ */ jsx7("option", { value: "", disabled: field.required, children: "Choose an option" }),
4343
- options.map((option, index) => /* @__PURE__ */ jsx7("option", { value: index, children: option.label }, optionKey(option)))
5188
+ /* @__PURE__ */ jsx9("option", { value: "", disabled: field.required, children: "Choose an option" }),
5189
+ options.map((option, index) => /* @__PURE__ */ jsx9("option", { value: index, children: option.label }, optionKey(option)))
4344
5190
  ]
4345
5191
  }
4346
5192
  );
4347
5193
  }
4348
- return /* @__PURE__ */ jsx7(
5194
+ return /* @__PURE__ */ jsx9(
4349
5195
  "div",
4350
5196
  {
4351
5197
  className: "tool-input-card__choices",
@@ -4356,8 +5202,8 @@ function ChoiceField({
4356
5202
  "aria-required": field.required,
4357
5203
  children: options.map((option, index) => {
4358
5204
  const checked = multiple ? selected.some((item) => valuesMatch(item, option.value)) : valuesMatch(value, option.value);
4359
- return /* @__PURE__ */ jsxs7("label", { className: "tool-input-card__choice", children: [
4360
- /* @__PURE__ */ jsx7(
5205
+ return /* @__PURE__ */ jsxs9("label", { className: "tool-input-card__choice", children: [
5206
+ /* @__PURE__ */ jsx9(
4361
5207
  "input",
4362
5208
  {
4363
5209
  type: multiple ? "checkbox" : "radio",
@@ -4379,7 +5225,7 @@ function ChoiceField({
4379
5225
  }
4380
5226
  }
4381
5227
  ),
4382
- /* @__PURE__ */ jsx7("span", { children: option.label })
5228
+ /* @__PURE__ */ jsx9("span", { children: option.label })
4383
5229
  ] }, optionKey(option));
4384
5230
  })
4385
5231
  }
@@ -4399,9 +5245,9 @@ function ToolField({
4399
5245
  error ? `${id}-error` : ""
4400
5246
  ].filter(Boolean).join(" ");
4401
5247
  if (field.kind === "checkbox" || field.kind === "confirmation") {
4402
- return /* @__PURE__ */ jsxs7("div", { className: "tool-input-card__field", children: [
4403
- /* @__PURE__ */ jsxs7("label", { className: "tool-input-card__check", htmlFor: id, children: [
4404
- /* @__PURE__ */ jsx7(
5248
+ return /* @__PURE__ */ jsxs9("div", { className: "tool-input-card__field", children: [
5249
+ /* @__PURE__ */ jsxs9("label", { className: "tool-input-card__check", htmlFor: id, children: [
5250
+ /* @__PURE__ */ jsx9(
4405
5251
  "input",
4406
5252
  {
4407
5253
  id,
@@ -4414,17 +5260,17 @@ function ToolField({
4414
5260
  onChange: (event) => onChange(event.target.checked)
4415
5261
  }
4416
5262
  ),
4417
- /* @__PURE__ */ jsxs7("span", { children: [
4418
- /* @__PURE__ */ jsx7("strong", { children: field.label }),
4419
- field.description ? /* @__PURE__ */ jsx7("span", { id: `${id}-description`, children: field.description }) : null
5263
+ /* @__PURE__ */ jsxs9("span", { children: [
5264
+ /* @__PURE__ */ jsx9("strong", { children: field.label }),
5265
+ field.description ? /* @__PURE__ */ jsx9("span", { id: `${id}-description`, children: field.description }) : null
4420
5266
  ] })
4421
5267
  ] }),
4422
- error ? /* @__PURE__ */ jsx7("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
5268
+ error ? /* @__PURE__ */ jsx9("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
4423
5269
  ] });
4424
5270
  }
4425
- const label = /* @__PURE__ */ jsxs7("label", { id: `${id}-label`, htmlFor: id, children: [
5271
+ const label = /* @__PURE__ */ jsxs9("label", { id: `${id}-label`, htmlFor: id, children: [
4426
5272
  field.label,
4427
- field.required ? /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: " *" }) : null
5273
+ field.required ? /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: " *" }) : null
4428
5274
  ] });
4429
5275
  const common = {
4430
5276
  id,
@@ -4436,7 +5282,7 @@ function ToolField({
4436
5282
  };
4437
5283
  let control;
4438
5284
  if (field.kind === "select" || field.kind === "radio" || field.kind === "multi-select") {
4439
- control = /* @__PURE__ */ jsx7(
5285
+ control = /* @__PURE__ */ jsx9(
4440
5286
  ChoiceField,
4441
5287
  {
4442
5288
  field,
@@ -4450,7 +5296,7 @@ function ToolField({
4450
5296
  }
4451
5297
  );
4452
5298
  } else if (field.kind === "textarea" || field.kind === "json") {
4453
- control = /* @__PURE__ */ jsx7(
5299
+ control = /* @__PURE__ */ jsx9(
4454
5300
  "textarea",
4455
5301
  {
4456
5302
  ...common,
@@ -4464,8 +5310,8 @@ function ToolField({
4464
5310
  );
4465
5311
  } else if (field.kind === "range") {
4466
5312
  const numericValue = typeof value === "number" ? value : field.min ?? 0;
4467
- control = /* @__PURE__ */ jsxs7("div", { className: "tool-input-card__range", children: [
4468
- /* @__PURE__ */ jsx7(
5313
+ control = /* @__PURE__ */ jsxs9("div", { className: "tool-input-card__range", children: [
5314
+ /* @__PURE__ */ jsx9(
4469
5315
  "input",
4470
5316
  {
4471
5317
  ...common,
@@ -4477,11 +5323,11 @@ function ToolField({
4477
5323
  onChange: (event) => onChange(Number(event.target.value))
4478
5324
  }
4479
5325
  ),
4480
- /* @__PURE__ */ jsx7("output", { htmlFor: id, children: numericValue })
5326
+ /* @__PURE__ */ jsx9("output", { htmlFor: id, children: numericValue })
4481
5327
  ] });
4482
5328
  } else {
4483
5329
  const type = field.kind === "date-time" ? "datetime-local" : field.kind === "calendar" ? "date" : field.kind;
4484
- control = /* @__PURE__ */ jsx7(
5330
+ control = /* @__PURE__ */ jsx9(
4485
5331
  "input",
4486
5332
  {
4487
5333
  ...common,
@@ -4499,11 +5345,11 @@ function ToolField({
4499
5345
  }
4500
5346
  );
4501
5347
  }
4502
- return /* @__PURE__ */ jsxs7("div", { className: "tool-input-card__field", children: [
5348
+ return /* @__PURE__ */ jsxs9("div", { className: "tool-input-card__field", children: [
4503
5349
  label,
4504
- /* @__PURE__ */ jsx7(FieldDescription, { field, id: `${id}-description` }),
5350
+ /* @__PURE__ */ jsx9(FieldDescription, { field, id: `${id}-description` }),
4505
5351
  control,
4506
- error ? /* @__PURE__ */ jsx7("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
5352
+ error ? /* @__PURE__ */ jsx9("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
4507
5353
  ] });
4508
5354
  }
4509
5355
  function ToolInputCard({
@@ -4511,11 +5357,11 @@ function ToolInputCard({
4511
5357
  surface,
4512
5358
  onSubmit
4513
5359
  }) {
4514
- const [values, setValues] = useState6(
5360
+ const [values, setValues] = useState7(
4515
5361
  () => initialValues(surface)
4516
5362
  );
4517
- const [touched, setTouched] = useState6(() => /* @__PURE__ */ new Set());
4518
- const [submitted, setSubmitted] = useState6(false);
5363
+ const [touched, setTouched] = useState7(() => /* @__PURE__ */ new Set());
5364
+ const [submitted, setSubmitted] = useState7(false);
4519
5365
  const errors = Object.fromEntries(
4520
5366
  surface.fields.map((field) => [
4521
5367
  field.path,
@@ -4540,14 +5386,14 @@ function ToolInputCard({
4540
5386
  onSubmit?.(surface, result);
4541
5387
  }
4542
5388
  if (submitted) {
4543
- return /* @__PURE__ */ jsxs7(
5389
+ return /* @__PURE__ */ jsxs9(
4544
5390
  "section",
4545
5391
  {
4546
5392
  className: "tool-input-card tool-input-card--submitted",
4547
5393
  role: "status",
4548
5394
  children: [
4549
- /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u2713" }),
4550
- /* @__PURE__ */ jsxs7("strong", { children: [
5395
+ /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: "\u2713" }),
5396
+ /* @__PURE__ */ jsxs9("strong", { children: [
4551
5397
  surface.title,
4552
5398
  " submitted"
4553
5399
  ] })
@@ -4555,18 +5401,18 @@ function ToolInputCard({
4555
5401
  }
4556
5402
  );
4557
5403
  }
4558
- return /* @__PURE__ */ jsxs7(
5404
+ return /* @__PURE__ */ jsxs9(
4559
5405
  "section",
4560
5406
  {
4561
5407
  className: "tool-input-card",
4562
5408
  "aria-labelledby": `tool-input-${surface.id}`,
4563
5409
  children: [
4564
- /* @__PURE__ */ jsxs7("div", { className: "tool-input-card__heading", children: [
4565
- /* @__PURE__ */ jsx7("strong", { id: `tool-input-${surface.id}`, children: surface.title }),
4566
- surface.description ? /* @__PURE__ */ jsx7("p", { children: surface.description }) : null
5410
+ /* @__PURE__ */ jsxs9("div", { className: "tool-input-card__heading", children: [
5411
+ /* @__PURE__ */ jsx9("strong", { id: `tool-input-${surface.id}`, children: surface.title }),
5412
+ surface.description ? /* @__PURE__ */ jsx9("p", { children: surface.description }) : null
4567
5413
  ] }),
4568
- /* @__PURE__ */ jsxs7("form", { noValidate: true, onSubmit: submit, children: [
4569
- /* @__PURE__ */ jsx7("div", { className: "tool-input-card__fields", children: surface.fields.map((field, index) => /* @__PURE__ */ jsx7(
5414
+ /* @__PURE__ */ jsxs9("form", { noValidate: true, onSubmit: submit, children: [
5415
+ /* @__PURE__ */ jsx9("div", { className: "tool-input-card__fields", children: surface.fields.map((field, index) => /* @__PURE__ */ jsx9(
4570
5416
  ToolField,
4571
5417
  {
4572
5418
  disabled,
@@ -4579,8 +5425,8 @@ function ToolInputCard({
4579
5425
  },
4580
5426
  field.path
4581
5427
  )) }),
4582
- /* @__PURE__ */ jsxs7("div", { className: "tool-input-card__actions", children: [
4583
- surface.actions?.some((action) => action.id === "reset") ? /* @__PURE__ */ jsx7(
5428
+ /* @__PURE__ */ jsxs9("div", { className: "tool-input-card__actions", children: [
5429
+ surface.actions?.some((action) => action.id === "reset") ? /* @__PURE__ */ jsx9(
4584
5430
  "button",
4585
5431
  {
4586
5432
  type: "button",
@@ -4593,7 +5439,7 @@ function ToolInputCard({
4593
5439
  children: surface.actions.find((action) => action.id === "reset")?.label ?? "Clear"
4594
5440
  }
4595
5441
  ) : null,
4596
- /* @__PURE__ */ jsx7("button", { type: "submit", disabled, children: surface.submitLabel ?? surface.actions?.find((action) => action.id === "submit")?.label ?? "Continue" })
5442
+ /* @__PURE__ */ jsx9("button", { type: "submit", disabled, children: surface.submitLabel ?? surface.actions?.find((action) => action.id === "submit")?.label ?? "Continue" })
4597
5443
  ] })
4598
5444
  ] })
4599
5445
  ]
@@ -4602,17 +5448,17 @@ function ToolInputCard({
4602
5448
  }
4603
5449
 
4604
5450
  // src/react/components/HumanInputCard/HumanInputCard.tsx
4605
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
5451
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
4606
5452
  function HumanInputCard({
4607
5453
  disabled = false,
4608
5454
  request,
4609
5455
  onRespond
4610
5456
  }) {
4611
- const [text, setText] = useState7("");
5457
+ const [text, setText] = useState8("");
4612
5458
  const options = request.options ?? [];
4613
5459
  const showText = request.display === "text" || request.allowFreeform && options.length === 0;
4614
5460
  if (request.ui) {
4615
- return /* @__PURE__ */ jsx8(
5461
+ return /* @__PURE__ */ jsx10(
4616
5462
  ToolInputCard,
4617
5463
  {
4618
5464
  disabled,
@@ -4622,7 +5468,7 @@ function HumanInputCard({
4622
5468
  );
4623
5469
  }
4624
5470
  if (options.length > 0) {
4625
- return /* @__PURE__ */ jsx8(
5471
+ return /* @__PURE__ */ jsx10(
4626
5472
  ConfirmationCard,
4627
5473
  {
4628
5474
  disabled,
@@ -4637,17 +5483,17 @@ function HumanInputCard({
4637
5483
  if (!value || disabled) return;
4638
5484
  onRespond?.({ requestId: request.requestId, text: value });
4639
5485
  }
4640
- return /* @__PURE__ */ jsxs8(
5486
+ return /* @__PURE__ */ jsxs10(
4641
5487
  "section",
4642
5488
  {
4643
5489
  className: "human-input-card",
4644
5490
  "aria-labelledby": `human-input-${request.requestId}`,
4645
5491
  children: [
4646
- /* @__PURE__ */ jsx8("div", { className: "human-input-card__heading", children: /* @__PURE__ */ jsx8("strong", { id: `human-input-${request.requestId}`, children: request.prompt }) }),
4647
- showText ? /* @__PURE__ */ jsxs8("form", { onSubmit: submitText, children: [
4648
- /* @__PURE__ */ jsx8("label", { htmlFor: `human-input-text-${request.requestId}`, children: "Response" }),
4649
- /* @__PURE__ */ jsxs8("div", { children: [
4650
- /* @__PURE__ */ jsx8(
5492
+ /* @__PURE__ */ jsx10("div", { className: "human-input-card__heading", children: /* @__PURE__ */ jsx10("strong", { id: `human-input-${request.requestId}`, children: request.prompt }) }),
5493
+ showText ? /* @__PURE__ */ jsxs10("form", { onSubmit: submitText, children: [
5494
+ /* @__PURE__ */ jsx10("label", { htmlFor: `human-input-text-${request.requestId}`, children: "Response" }),
5495
+ /* @__PURE__ */ jsxs10("div", { children: [
5496
+ /* @__PURE__ */ jsx10(
4651
5497
  "input",
4652
5498
  {
4653
5499
  id: `human-input-text-${request.requestId}`,
@@ -4656,39 +5502,39 @@ function HumanInputCard({
4656
5502
  onChange: (event) => setText(event.target.value)
4657
5503
  }
4658
5504
  ),
4659
- /* @__PURE__ */ jsx8("button", { type: "submit", disabled: disabled || !text.trim(), children: "Send" })
5505
+ /* @__PURE__ */ jsx10("button", { type: "submit", disabled: disabled || !text.trim(), children: "Send" })
4660
5506
  ] })
4661
5507
  ] }) : null,
4662
- !showText && options.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "human-input-card__unavailable", role: "status", children: "This request can\u2019t be answered here." }) : null
5508
+ !showText && options.length === 0 ? /* @__PURE__ */ jsx10("p", { className: "human-input-card__unavailable", role: "status", children: "This request can\u2019t be answered here." }) : null
4663
5509
  ]
4664
5510
  }
4665
5511
  );
4666
5512
  }
4667
5513
 
4668
5514
  // src/react/components/CollectionResultCard/CollectionResultCard.tsx
4669
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
5515
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
4670
5516
  function CollectionResultCard({
4671
5517
  result
4672
5518
  }) {
4673
5519
  const empty = result.items.length === 0;
4674
- return /* @__PURE__ */ jsxs9(
5520
+ return /* @__PURE__ */ jsxs11(
4675
5521
  "section",
4676
5522
  {
4677
5523
  className: `collection-result-card tool-result-card tool-result-card--${result.status}`,
4678
5524
  "aria-label": result.title,
4679
5525
  children: [
4680
- /* @__PURE__ */ jsxs9("div", { className: "tool-result-card__heading", children: [
4681
- /* @__PURE__ */ jsx9("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4682
- /* @__PURE__ */ jsx9("strong", { children: result.title })
5526
+ /* @__PURE__ */ jsxs11("div", { className: "tool-result-card__heading", children: [
5527
+ /* @__PURE__ */ jsx11("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5528
+ /* @__PURE__ */ jsx11("strong", { children: result.title })
4683
5529
  ] }),
4684
- empty ? /* @__PURE__ */ jsx9("p", { className: "collection-result-card__empty", children: "No matching record for the email you shared." }) : /* @__PURE__ */ jsx9("ul", { className: "collection-result-card__list", children: result.items.map((item) => /* @__PURE__ */ jsxs9("li", { children: [
4685
- /* @__PURE__ */ jsx9("div", { className: "collection-result-card__item-title", children: item.title }),
4686
- item.description ? /* @__PURE__ */ jsx9("p", { children: item.description }) : null,
4687
- item.details?.length ? /* @__PURE__ */ jsx9("dl", { children: item.details.map((detail) => /* @__PURE__ */ jsxs9("div", { children: [
4688
- /* @__PURE__ */ jsx9("dt", { children: detail.label }),
4689
- /* @__PURE__ */ jsx9("dd", { children: detail.value })
5530
+ empty ? /* @__PURE__ */ jsx11("p", { className: "collection-result-card__empty", children: "No matching record for the email you shared." }) : /* @__PURE__ */ jsx11("ul", { className: "collection-result-card__list", children: result.items.map((item) => /* @__PURE__ */ jsxs11("li", { children: [
5531
+ /* @__PURE__ */ jsx11("div", { className: "collection-result-card__item-title", children: item.title }),
5532
+ item.description ? /* @__PURE__ */ jsx11("p", { children: item.description }) : null,
5533
+ item.details?.length ? /* @__PURE__ */ jsx11("dl", { children: item.details.map((detail) => /* @__PURE__ */ jsxs11("div", { children: [
5534
+ /* @__PURE__ */ jsx11("dt", { children: detail.label }),
5535
+ /* @__PURE__ */ jsx11("dd", { children: detail.value })
4690
5536
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4691
- item.href ? /* @__PURE__ */ jsx9("a", { href: item.href, target: "_blank", rel: "noreferrer", children: "Open record" }) : null
5537
+ item.href ? /* @__PURE__ */ jsx11("a", { href: item.href, target: "_blank", rel: "noreferrer", children: "Open record" }) : null
4692
5538
  ] }, item.title)) })
4693
5539
  ]
4694
5540
  }
@@ -4696,26 +5542,26 @@ function CollectionResultCard({
4696
5542
  }
4697
5543
 
4698
5544
  // src/react/components/EntityResultCard/EntityResultCard.tsx
4699
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
5545
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
4700
5546
  function EntityResultCard({
4701
5547
  result
4702
5548
  }) {
4703
- return /* @__PURE__ */ jsxs10(
5549
+ return /* @__PURE__ */ jsxs12(
4704
5550
  "section",
4705
5551
  {
4706
5552
  className: `entity-result-card tool-result-card tool-result-card--${result.status}`,
4707
5553
  "aria-label": result.title,
4708
5554
  children: [
4709
- /* @__PURE__ */ jsxs10("div", { className: "tool-result-card__heading", children: [
4710
- /* @__PURE__ */ jsx10("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4711
- /* @__PURE__ */ jsx10("strong", { children: result.title })
5555
+ /* @__PURE__ */ jsxs12("div", { className: "tool-result-card__heading", children: [
5556
+ /* @__PURE__ */ jsx12("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5557
+ /* @__PURE__ */ jsx12("strong", { children: result.title })
4712
5558
  ] }),
4713
- result.description ? /* @__PURE__ */ jsx10("p", { children: result.description }) : null,
4714
- result.details?.length ? /* @__PURE__ */ jsx10("dl", { children: result.details.map((detail) => /* @__PURE__ */ jsxs10("div", { children: [
4715
- /* @__PURE__ */ jsx10("dt", { children: detail.label }),
4716
- /* @__PURE__ */ jsx10("dd", { children: detail.value })
5559
+ result.description ? /* @__PURE__ */ jsx12("p", { children: result.description }) : null,
5560
+ result.details?.length ? /* @__PURE__ */ jsx12("dl", { children: result.details.map((detail) => /* @__PURE__ */ jsxs12("div", { children: [
5561
+ /* @__PURE__ */ jsx12("dt", { children: detail.label }),
5562
+ /* @__PURE__ */ jsx12("dd", { children: detail.value })
4717
5563
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4718
- result.links?.length ? /* @__PURE__ */ jsx10("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ jsx10(
5564
+ result.links?.length ? /* @__PURE__ */ jsx12("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ jsx12(
4719
5565
  "a",
4720
5566
  {
4721
5567
  href: link.href,
@@ -4731,24 +5577,24 @@ function EntityResultCard({
4731
5577
  }
4732
5578
 
4733
5579
  // src/react/components/SignatureResultCard/SignatureResultCard.tsx
4734
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
5580
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
4735
5581
  function SignatureResultCard({
4736
5582
  result
4737
5583
  }) {
4738
5584
  const primaryLink = result.links?.[0];
4739
- return /* @__PURE__ */ jsxs11(
5585
+ return /* @__PURE__ */ jsxs13(
4740
5586
  "section",
4741
5587
  {
4742
5588
  className: `signature-result-card tool-result-card tool-result-card--${result.status}`,
4743
5589
  "aria-label": result.title,
4744
5590
  children: [
4745
- /* @__PURE__ */ jsxs11("div", { className: "tool-result-card__heading", children: [
4746
- /* @__PURE__ */ jsx11("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4747
- /* @__PURE__ */ jsx11("strong", { children: result.title })
5591
+ /* @__PURE__ */ jsxs13("div", { className: "tool-result-card__heading", children: [
5592
+ /* @__PURE__ */ jsx13("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5593
+ /* @__PURE__ */ jsx13("strong", { children: result.title })
4748
5594
  ] }),
4749
- result.statusLabel ? /* @__PURE__ */ jsx11("span", { className: "signature-result-card__badge", children: result.statusLabel }) : null,
4750
- result.description ? /* @__PURE__ */ jsx11("p", { children: result.description }) : null,
4751
- primaryLink ? /* @__PURE__ */ jsx11(
5595
+ result.statusLabel ? /* @__PURE__ */ jsx13("span", { className: "signature-result-card__badge", children: result.statusLabel }) : null,
5596
+ result.description ? /* @__PURE__ */ jsx13("p", { children: result.description }) : null,
5597
+ primaryLink ? /* @__PURE__ */ jsx13(
4752
5598
  "a",
4753
5599
  {
4754
5600
  className: "signature-result-card__cta",
@@ -4764,26 +5610,26 @@ function SignatureResultCard({
4764
5610
  }
4765
5611
 
4766
5612
  // src/react/components/ToolResultCard/ToolResultCard.tsx
4767
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
5613
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
4768
5614
  function ToolResultCard({
4769
5615
  result
4770
5616
  }) {
4771
- return /* @__PURE__ */ jsxs12(
5617
+ return /* @__PURE__ */ jsxs14(
4772
5618
  "section",
4773
5619
  {
4774
5620
  className: `tool-result-card tool-result-card--${result.status}`,
4775
5621
  "aria-label": result.title,
4776
5622
  children: [
4777
- /* @__PURE__ */ jsxs12("div", { className: "tool-result-card__heading", children: [
4778
- /* @__PURE__ */ jsx12("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4779
- /* @__PURE__ */ jsx12("strong", { children: result.title })
5623
+ /* @__PURE__ */ jsxs14("div", { className: "tool-result-card__heading", children: [
5624
+ /* @__PURE__ */ jsx14("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5625
+ /* @__PURE__ */ jsx14("strong", { children: result.title })
4780
5626
  ] }),
4781
- result.description ? /* @__PURE__ */ jsx12("p", { children: result.description }) : null,
4782
- result.details?.length ? /* @__PURE__ */ jsx12("dl", { children: result.details.map((detail) => /* @__PURE__ */ jsxs12("div", { children: [
4783
- /* @__PURE__ */ jsx12("dt", { children: detail.label }),
4784
- /* @__PURE__ */ jsx12("dd", { children: detail.value })
5627
+ result.description ? /* @__PURE__ */ jsx14("p", { children: result.description }) : null,
5628
+ result.details?.length ? /* @__PURE__ */ jsx14("dl", { children: result.details.map((detail) => /* @__PURE__ */ jsxs14("div", { children: [
5629
+ /* @__PURE__ */ jsx14("dt", { children: detail.label }),
5630
+ /* @__PURE__ */ jsx14("dd", { children: detail.value })
4785
5631
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4786
- result.links?.length ? /* @__PURE__ */ jsx12("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ jsx12(
5632
+ result.links?.length ? /* @__PURE__ */ jsx14("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ jsx14(
4787
5633
  "a",
4788
5634
  {
4789
5635
  href: link.href,
@@ -4799,14 +5645,14 @@ function ToolResultCard({
4799
5645
  }
4800
5646
 
4801
5647
  // src/react/components/VisitorToolResultView/VisitorToolResultView.tsx
4802
- import { jsx as jsx13 } from "react/jsx-runtime";
5648
+ import { jsx as jsx15 } from "react/jsx-runtime";
4803
5649
  function VisitorToolResultView({
4804
5650
  disabled = false,
4805
5651
  onToolInput,
4806
5652
  result
4807
5653
  }) {
4808
5654
  if (result.kind === "input") {
4809
- return /* @__PURE__ */ jsx13(
5655
+ return /* @__PURE__ */ jsx15(
4810
5656
  ToolInputCard,
4811
5657
  {
4812
5658
  disabled,
@@ -4816,16 +5662,16 @@ function VisitorToolResultView({
4816
5662
  );
4817
5663
  }
4818
5664
  if (result.kind === "entity") {
4819
- return /* @__PURE__ */ jsx13(EntityResultCard, { result });
5665
+ return /* @__PURE__ */ jsx15(EntityResultCard, { result });
4820
5666
  }
4821
5667
  if (result.kind === "collection") {
4822
- return /* @__PURE__ */ jsx13(CollectionResultCard, { result });
5668
+ return /* @__PURE__ */ jsx15(CollectionResultCard, { result });
4823
5669
  }
4824
5670
  if (result.kind === "signature") {
4825
- return /* @__PURE__ */ jsx13(SignatureResultCard, { result });
5671
+ return /* @__PURE__ */ jsx15(SignatureResultCard, { result });
4826
5672
  }
4827
5673
  if (result.kind === "summary") {
4828
- return /* @__PURE__ */ jsx13(ToolResultCard, { result });
5674
+ return /* @__PURE__ */ jsx15(ToolResultCard, { result });
4829
5675
  }
4830
5676
  return null;
4831
5677
  }
@@ -4834,9 +5680,9 @@ function isRenderableVisitorToolResult(result) {
4834
5680
  }
4835
5681
 
4836
5682
  // src/react/components/AgentRail/AgentRail.tsx
4837
- import { Fragment, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
5683
+ import { Fragment, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
4838
5684
  function MinimizeIcon() {
4839
- return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5685
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
4840
5686
  "path",
4841
5687
  {
4842
5688
  d: "M3.5 8h9",
@@ -4846,8 +5692,8 @@ function MinimizeIcon() {
4846
5692
  }
4847
5693
  ) });
4848
5694
  }
4849
- function CloseIcon() {
4850
- return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5695
+ function CloseIcon2() {
5696
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
4851
5697
  "path",
4852
5698
  {
4853
5699
  d: "M4 4l8 8M12 4l-8 8",
@@ -4858,7 +5704,7 @@ function CloseIcon() {
4858
5704
  ) });
4859
5705
  }
4860
5706
  function NewChatIcon() {
4861
- return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5707
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
4862
5708
  "path",
4863
5709
  {
4864
5710
  d: "M9.5 3.5h3v3M12.25 3.75 8 8M7 4H4.5A1.5 1.5 0 0 0 3 5.5v6A1.5 1.5 0 0 0 4.5 13h6a1.5 1.5 0 0 0 1.5-1.5V9",
@@ -4870,7 +5716,7 @@ function NewChatIcon() {
4870
5716
  ) });
4871
5717
  }
4872
5718
  function ExpandIcon() {
4873
- return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5719
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
4874
5720
  "path",
4875
5721
  {
4876
5722
  d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
@@ -4882,7 +5728,7 @@ function ExpandIcon() {
4882
5728
  ) });
4883
5729
  }
4884
5730
  function RestoreIcon() {
4885
- return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5731
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
4886
5732
  "path",
4887
5733
  {
4888
5734
  d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
@@ -4893,13 +5739,30 @@ function RestoreIcon() {
4893
5739
  }
4894
5740
  ) });
4895
5741
  }
5742
+ function ChevronDownIcon() {
5743
+ return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
5744
+ "path",
5745
+ {
5746
+ d: "M4 6.5l4 4 4-4",
5747
+ stroke: "currentColor",
5748
+ strokeWidth: "1.6",
5749
+ strokeLinecap: "round",
5750
+ strokeLinejoin: "round"
5751
+ }
5752
+ ) });
5753
+ }
5754
+ var DEFAULT_DISCLAIMER_LABEL = "Agent can make mistakes. Check important info.";
4896
5755
  function AgentRail({
4897
5756
  state,
4898
5757
  theme,
4899
5758
  colorScheme = "auto",
4900
5759
  brandLabel = "",
4901
5760
  brandLogoUrl,
4902
- poweredByLabel = "Powered by Webless",
5761
+ poweredByLabel,
5762
+ disclaimerLabel,
5763
+ disclaimerLink,
5764
+ answerReceipt = false,
5765
+ readAloud = false,
4903
5766
  composerPlaceholder = "Ask anything\u2026",
4904
5767
  mobileFullscreen = false,
4905
5768
  expanded = false,
@@ -4908,16 +5771,26 @@ function AgentRail({
4908
5771
  onExpandToggle,
4909
5772
  onReset,
4910
5773
  onRetry,
5774
+ onRegenerate,
5775
+ onFeedback,
4911
5776
  onSubmit,
4912
5777
  onFollowUpSelect,
4913
5778
  onBook,
4914
5779
  onInputResponse,
4915
5780
  onToolInput
4916
5781
  }) {
4917
- const transcriptRef = useRef4(null);
5782
+ const railRef = useRef6(null);
5783
+ const overlayRef = useRef6(null);
5784
+ const transcriptRef = useRef6(null);
5785
+ const pinnedToBottomRef = useRef6(true);
5786
+ const smoothScrollToLatestRef = useRef6(false);
5787
+ const lockedTranscriptScrollTopRef = useRef6(null);
5788
+ const [showJumpToLatest, setShowJumpToLatest] = useState9(false);
5789
+ const [receiptOpen, setReceiptOpen] = useState9(false);
4918
5790
  const resolvedBrandLabel = brandLabel.trim();
4919
5791
  const resolvedBrandLogoUrl = brandLogoUrl?.trim();
4920
- const [failedLogoUrl, setFailedLogoUrl] = useState8(null);
5792
+ const resolvedDisclaimerLabel = disclaimerLabel === void 0 ? DEFAULT_DISCLAIMER_LABEL : disclaimerLabel;
5793
+ const [failedLogoUrl, setFailedLogoUrl] = useState9(null);
4921
5794
  const showBrandLogo = Boolean(resolvedBrandLogoUrl) && failedLogoUrl !== resolvedBrandLogoUrl;
4922
5795
  const resolvedColorScheme = useAgentColorScheme(colorScheme);
4923
5796
  const brandedTheme = { ...defaultAgentRailTheme, ...theme };
@@ -4968,10 +5841,15 @@ function AgentRail({
4968
5841
  );
4969
5842
  const activeVisitorToolInput = [...visitorToolResults].reverse().find((result) => result.kind === "input");
4970
5843
  const visibleVisitorToolResults = activeVisitorToolInput ? [activeVisitorToolInput] : visitorToolResults;
4971
- const showActivity = state.toolSteps.length > 0 && visibleVisitorToolResults.length === 0 && pendingInputRequests.length === 0 && !state.pendingOffer;
5844
+ const activityActive = state.toolSteps.some((step) => step.state === "active");
5845
+ const showActivity = state.toolSteps.length > 0 && visibleVisitorToolResults.length === 0 && pendingInputRequests.length === 0 && !state.pendingOffer && activityActive;
4972
5846
  const hasVisitorMessages2 = state.messages.some(
4973
5847
  (message) => message.role === "visitor"
4974
5848
  );
5849
+ const hasAgentResponseAfterVisitor = state.messages.some(
5850
+ (message) => message.role === "agent" && message.id !== "greeting"
5851
+ );
5852
+ const showDisclaimerLabel = Boolean(resolvedDisclaimerLabel) && hasVisitorMessages2 && (hasAgentResponseAfterVisitor || state.phase === "streaming" && Boolean(state.streamingText));
4975
5853
  const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
4976
5854
  const greeting = state.messages.find(
4977
5855
  (message) => message.role === "agent" && message.id === "greeting"
@@ -4993,6 +5871,7 @@ function AgentRail({
4993
5871
  }
4994
5872
  }
4995
5873
  const lastIsAgent = lastMessage?.role === "agent";
5874
+ const showMessageActions = state.phase === "complete" && lastIsAgent && hasVisitorMessages2;
4996
5875
  const streamingMessage = state.phase === "streaming" && state.streamingText && !lastIsAgent ? {
4997
5876
  createdAt: 0,
4998
5877
  id: "streaming-response",
@@ -5019,10 +5898,36 @@ function AgentRail({
5019
5898
  hasPendingConfirmation,
5020
5899
  enabled: lastIsAgent && !isBusy
5021
5900
  });
5022
- useEffect4(() => {
5901
+ const receiptSteps = answerReceipt && state.toolSteps.length > 0 ? state.toolSteps : void 0;
5902
+ useEffect6(() => {
5903
+ if (state.phase !== "complete") {
5904
+ setReceiptOpen(false);
5905
+ }
5906
+ }, [state.phase]);
5907
+ function handleSubmit(message) {
5908
+ setReceiptOpen(false);
5909
+ onSubmit?.(message);
5910
+ }
5911
+ function handleRegenerate() {
5912
+ setReceiptOpen(false);
5913
+ onRegenerate?.();
5914
+ }
5915
+ function handleReset() {
5916
+ setReceiptOpen(false);
5917
+ onReset?.();
5918
+ }
5919
+ function handleFollowUpSelect(label) {
5920
+ setReceiptOpen(false);
5921
+ onFollowUpSelect?.(label);
5922
+ }
5923
+ useEffect6(() => {
5023
5924
  const node = transcriptRef.current;
5024
5925
  if (!node) return;
5025
- node.scrollTop = node.scrollHeight;
5926
+ const lastMessage2 = state.messages.at(-1);
5927
+ const visitorJustSent = lastMessage2?.role === "visitor";
5928
+ if (pinnedToBottomRef.current || visitorJustSent) {
5929
+ node.scrollTop = node.scrollHeight;
5930
+ }
5026
5931
  }, [
5027
5932
  state.messages,
5028
5933
  state.toolSteps,
@@ -5030,10 +5935,75 @@ function AgentRail({
5030
5935
  state.followUps,
5031
5936
  state.journey
5032
5937
  ]);
5033
- return /* @__PURE__ */ jsxs13(
5938
+ useEffect6(() => {
5939
+ const node = transcriptRef.current;
5940
+ if (!node) return;
5941
+ const handleScroll = () => {
5942
+ if (node.clientHeight === 0) return;
5943
+ const distanceFromBottom = node.scrollHeight - node.scrollTop - node.clientHeight;
5944
+ const pinned = distanceFromBottom < 48 || smoothScrollToLatestRef.current;
5945
+ pinnedToBottomRef.current = pinned;
5946
+ setShowJumpToLatest(!pinned);
5947
+ };
5948
+ node.addEventListener("scroll", handleScroll, { passive: true });
5949
+ handleScroll();
5950
+ return () => node.removeEventListener("scroll", handleScroll);
5951
+ }, []);
5952
+ useEffect6(() => {
5953
+ const node = transcriptRef.current;
5954
+ if (!node) return;
5955
+ const observer = new ResizeObserver(() => {
5956
+ if (node.clientHeight === 0) return;
5957
+ if (pinnedToBottomRef.current) {
5958
+ node.scrollTo({ top: node.scrollHeight, behavior: "instant" });
5959
+ }
5960
+ });
5961
+ observer.observe(node);
5962
+ return () => observer.disconnect();
5963
+ }, []);
5964
+ useEffect6(() => {
5965
+ if (!receiptOpen) {
5966
+ lockedTranscriptScrollTopRef.current = null;
5967
+ return;
5968
+ }
5969
+ const node = transcriptRef.current;
5970
+ if (!node || lockedTranscriptScrollTopRef.current === null) return;
5971
+ node.scrollTop = lockedTranscriptScrollTopRef.current;
5972
+ }, [receiptOpen]);
5973
+ function openReceipt() {
5974
+ const node = transcriptRef.current;
5975
+ lockedTranscriptScrollTopRef.current = node?.scrollTop ?? null;
5976
+ setReceiptOpen(true);
5977
+ }
5978
+ function scrollToLatest() {
5979
+ const node = transcriptRef.current;
5980
+ if (!node) return;
5981
+ pinnedToBottomRef.current = true;
5982
+ setShowJumpToLatest(false);
5983
+ const reduceMotion = window.matchMedia(
5984
+ "(prefers-reduced-motion: reduce)"
5985
+ ).matches;
5986
+ if (reduceMotion) {
5987
+ node.scrollTo({ top: node.scrollHeight, behavior: "instant" });
5988
+ return;
5989
+ }
5990
+ smoothScrollToLatestRef.current = true;
5991
+ const settle = () => {
5992
+ smoothScrollToLatestRef.current = false;
5993
+ const distanceFromBottom = node.scrollHeight - node.scrollTop - node.clientHeight;
5994
+ const pinned = distanceFromBottom < 48;
5995
+ pinnedToBottomRef.current = pinned;
5996
+ setShowJumpToLatest(!pinned);
5997
+ };
5998
+ node.addEventListener("scrollend", settle, { once: true });
5999
+ window.setTimeout(settle, 900);
6000
+ node.scrollTo({ top: node.scrollHeight, behavior: "smooth" });
6001
+ }
6002
+ return /* @__PURE__ */ jsx16(
5034
6003
  "aside",
5035
6004
  {
5036
- className: `agent-rail not-typeset${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
6005
+ ref: railRef,
6006
+ className: `agent-rail not-typeset${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}${receiptOpen ? " agent-rail--receipt-open" : ""}`,
5037
6007
  "data-not-typeset": "",
5038
6008
  "data-color-scheme": resolvedColorScheme,
5039
6009
  spellCheck: false,
@@ -5043,196 +6013,242 @@ function AgentRail({
5043
6013
  autoFocus: mobileFullscreen || expanded,
5044
6014
  role: mobileFullscreen || expanded ? "dialog" : void 0,
5045
6015
  tabIndex: mobileFullscreen || expanded ? -1 : void 0,
5046
- children: [
5047
- /* @__PURE__ */ jsx14("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs13("div", { className: "agent-rail__brand-row", children: [
5048
- onCollapse ? /* @__PURE__ */ jsx14(
5049
- "button",
5050
- {
5051
- type: "button",
5052
- className: "agent-rail__collapse",
5053
- "aria-label": "Collapse assist",
5054
- onClick: onCollapse,
5055
- children: /* @__PURE__ */ jsx14(MinimizeIcon, {})
5056
- }
5057
- ) : onClose ? /* @__PURE__ */ jsx14(
5058
- "button",
5059
- {
5060
- type: "button",
5061
- className: "agent-rail__close",
5062
- "aria-label": "Close agent",
5063
- onClick: onClose,
5064
- children: /* @__PURE__ */ jsx14(CloseIcon, {})
5065
- }
5066
- ) : /* @__PURE__ */ jsx14("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
5067
- resolvedBrandLabel || showBrandLogo ? /* @__PURE__ */ jsxs13("span", { className: "agent-rail__identity", children: [
5068
- showBrandLogo ? /* @__PURE__ */ jsx14("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx14(
5069
- "img",
5070
- {
5071
- className: "agent-rail__brand-logo",
5072
- src: resolvedBrandLogoUrl,
5073
- alt: "",
5074
- onError: () => {
5075
- setFailedLogoUrl(resolvedBrandLogoUrl ?? null);
6016
+ children: /* @__PURE__ */ jsxs15(
6017
+ AgentRailOverlayContext.Provider,
6018
+ {
6019
+ value: { railRef, overlayRef },
6020
+ children: [
6021
+ /* @__PURE__ */ jsxs15("div", { className: "agent-rail__surface", inert: receiptOpen || void 0, children: [
6022
+ /* @__PURE__ */ jsx16("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs15("div", { className: "agent-rail__brand-row", children: [
6023
+ onCollapse ? /* @__PURE__ */ jsx16(
6024
+ "button",
6025
+ {
6026
+ type: "button",
6027
+ className: "agent-rail__collapse",
6028
+ "aria-label": "Collapse assist",
6029
+ onClick: onCollapse,
6030
+ children: /* @__PURE__ */ jsx16(MinimizeIcon, {})
6031
+ }
6032
+ ) : onClose ? /* @__PURE__ */ jsx16(
6033
+ "button",
6034
+ {
6035
+ type: "button",
6036
+ className: "agent-rail__close",
6037
+ "aria-label": "Close agent",
6038
+ onClick: onClose,
6039
+ children: /* @__PURE__ */ jsx16(CloseIcon2, {})
6040
+ }
6041
+ ) : /* @__PURE__ */ jsx16("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
6042
+ resolvedBrandLabel || showBrandLogo ? /* @__PURE__ */ jsxs15("span", { className: "agent-rail__identity", children: [
6043
+ showBrandLogo ? /* @__PURE__ */ jsx16("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
6044
+ "img",
6045
+ {
6046
+ className: "agent-rail__brand-logo",
6047
+ src: resolvedBrandLogoUrl,
6048
+ alt: "",
6049
+ onError: () => {
6050
+ setFailedLogoUrl(resolvedBrandLogoUrl ?? null);
6051
+ }
6052
+ }
6053
+ ) }) : null,
6054
+ resolvedBrandLabel ? /* @__PURE__ */ jsx16("span", { className: "agent-rail__brand-label", children: resolvedBrandLabel }) : null
6055
+ ] }) : null,
6056
+ /* @__PURE__ */ jsxs15("span", { className: "agent-rail__actions", children: [
6057
+ onReset ? /* @__PURE__ */ jsx16(
6058
+ "button",
6059
+ {
6060
+ type: "button",
6061
+ className: "agent-rail__new-chat",
6062
+ "aria-label": "Start a new conversation",
6063
+ disabled: !hasVisitorMessages2,
6064
+ onClick: handleReset,
6065
+ children: /* @__PURE__ */ jsx16(NewChatIcon, {})
6066
+ }
6067
+ ) : null,
6068
+ onExpandToggle ? /* @__PURE__ */ jsx16(
6069
+ "button",
6070
+ {
6071
+ type: "button",
6072
+ className: "agent-rail__expand",
6073
+ "aria-label": expanded ? "Exit full screen" : "Open full screen",
6074
+ onClick: onExpandToggle,
6075
+ children: expanded ? /* @__PURE__ */ jsx16(RestoreIcon, {}) : /* @__PURE__ */ jsx16(ExpandIcon, {})
6076
+ }
6077
+ ) : null
6078
+ ] })
6079
+ ] }) }),
6080
+ /* @__PURE__ */ jsx16("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ jsxs15("div", { className: "agent-rail__thread", children: [
6081
+ !hasVisitorMessages2 ? /* @__PURE__ */ jsxs15("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
6082
+ greeting?.role === "agent" ? /* @__PURE__ */ jsx16(
6083
+ MessageBubble,
6084
+ {
6085
+ message: greeting,
6086
+ bookingDisabled: isBusy,
6087
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6088
+ onBook
6089
+ }
6090
+ ) : null,
6091
+ showIdleFollowUps ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx16(
6092
+ FollowUpChips,
6093
+ {
6094
+ suggestions: state.followUps,
6095
+ disabled: isBusy,
6096
+ label: "Start here",
6097
+ onSelect: (suggestion) => handleFollowUpSelect(suggestion.label)
6098
+ }
6099
+ ) }) : null,
6100
+ showActivity ? /* @__PURE__ */ jsx16(
6101
+ AgentActivityBubble,
6102
+ {
6103
+ brandLabel: resolvedBrandLabel,
6104
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6105
+ failed: state.phase === "error",
6106
+ steps: state.toolSteps
6107
+ }
6108
+ ) : null,
6109
+ visibleVisitorToolResults.map((result) => /* @__PURE__ */ jsx16(
6110
+ VisitorToolResultView,
6111
+ {
6112
+ result,
6113
+ disabled: semanticSurfaceDisabled,
6114
+ onToolInput
6115
+ },
6116
+ result.id
6117
+ )),
6118
+ pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ jsx16(
6119
+ HumanInputCard,
6120
+ {
6121
+ request,
6122
+ onRespond: onInputResponse
6123
+ },
6124
+ request.requestId
6125
+ ))
6126
+ ] }) : null,
6127
+ visibleMessages.map((message, index) => /* @__PURE__ */ jsxs15("div", { className: "agent-rail__turn-block", children: [
6128
+ /* @__PURE__ */ jsx16(
6129
+ MessageBubble,
6130
+ {
6131
+ message,
6132
+ bookingDisabled: isBusy,
6133
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6134
+ offer: index === lastAgentIndex ? state.pendingOffer : void 0,
6135
+ onBook
6136
+ }
6137
+ ),
6138
+ index === lastAgentIndex && showMessageActions && message.role === "agent" ? /* @__PURE__ */ jsx16(
6139
+ MessageActions,
6140
+ {
6141
+ answeredAt: message.createdAt,
6142
+ copyText: hideToolCardFences(message.text).trim() || message.text,
6143
+ readAloud,
6144
+ receiptSteps,
6145
+ onOpenReceipt: receiptSteps ? openReceipt : void 0,
6146
+ onRegenerate: onRegenerate ? handleRegenerate : void 0,
6147
+ onFeedback: onFeedback ? (rating) => onFeedback(rating, message) : void 0
6148
+ }
6149
+ ) : null,
6150
+ index === lastVisitorIndex ? /* @__PURE__ */ jsxs15(Fragment, { children: [
6151
+ showActivity ? /* @__PURE__ */ jsx16(
6152
+ AgentActivityBubble,
6153
+ {
6154
+ brandLabel: resolvedBrandLabel,
6155
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6156
+ failed: state.phase === "error",
6157
+ steps: state.toolSteps
6158
+ }
6159
+ ) : null,
6160
+ visibleVisitorToolResults.map((result) => /* @__PURE__ */ jsx16(
6161
+ VisitorToolResultView,
6162
+ {
6163
+ result,
6164
+ disabled: semanticSurfaceDisabled,
6165
+ onToolInput
6166
+ },
6167
+ result.id
6168
+ )),
6169
+ pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ jsx16(
6170
+ HumanInputCard,
6171
+ {
6172
+ request,
6173
+ onRespond: onInputResponse
6174
+ },
6175
+ request.requestId
6176
+ ))
6177
+ ] }) : null
6178
+ ] }, message.id)),
6179
+ streamingMessage ? /* @__PURE__ */ jsx16(
6180
+ MessageBubble,
6181
+ {
6182
+ message: streamingMessage,
6183
+ bookingDisabled: isBusy,
6184
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6185
+ offer: state.pendingOffer,
6186
+ onBook
6187
+ }
6188
+ ) : null,
6189
+ waitingForBooking ? /* @__PURE__ */ jsx16(BookingCardLoader, {}) : null,
6190
+ state.error ? /* @__PURE__ */ jsxs15("section", { className: "agent-rail__error", role: "alert", children: [
6191
+ /* @__PURE__ */ jsxs15("div", { children: [
6192
+ /* @__PURE__ */ jsx16("strong", { children: "Something went wrong" }),
6193
+ /* @__PURE__ */ jsx16("p", { children: state.error })
6194
+ ] }),
6195
+ onRetry ? /* @__PURE__ */ jsx16("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
6196
+ ] }) : null
6197
+ ] }) }),
6198
+ showDisclaimerLabel ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__disclaimer", children: /* @__PURE__ */ jsx16("p", { children: disclaimerLink ? /* @__PURE__ */ jsx16(
6199
+ "a",
6200
+ {
6201
+ href: disclaimerLink,
6202
+ rel: "noopener noreferrer",
6203
+ target: "_blank",
6204
+ children: resolvedDisclaimerLabel
5076
6205
  }
5077
- }
5078
- ) }) : null,
5079
- resolvedBrandLabel ? /* @__PURE__ */ jsx14("span", { className: "agent-rail__brand-label", children: resolvedBrandLabel }) : null
5080
- ] }) : null,
5081
- /* @__PURE__ */ jsxs13("span", { className: "agent-rail__actions", children: [
5082
- onReset ? /* @__PURE__ */ jsx14(
5083
- "button",
5084
- {
5085
- type: "button",
5086
- className: "agent-rail__new-chat",
5087
- "aria-label": "Start a new conversation",
5088
- disabled: !hasVisitorMessages2,
5089
- onClick: onReset,
5090
- children: /* @__PURE__ */ jsx14(NewChatIcon, {})
5091
- }
5092
- ) : null,
5093
- onExpandToggle ? /* @__PURE__ */ jsx14(
5094
- "button",
5095
- {
5096
- type: "button",
5097
- className: "agent-rail__expand",
5098
- "aria-label": expanded ? "Exit full screen" : "Open full screen",
5099
- onClick: onExpandToggle,
5100
- children: expanded ? /* @__PURE__ */ jsx14(RestoreIcon, {}) : /* @__PURE__ */ jsx14(ExpandIcon, {})
5101
- }
5102
- ) : null
5103
- ] })
5104
- ] }) }),
5105
- /* @__PURE__ */ jsx14("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ jsxs13("div", { className: "agent-rail__thread", children: [
5106
- !hasVisitorMessages2 ? /* @__PURE__ */ jsxs13("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
5107
- greeting?.role === "agent" ? /* @__PURE__ */ jsx14(
5108
- MessageBubble,
5109
- {
5110
- message: greeting,
5111
- bookingDisabled: isBusy,
5112
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5113
- onBook
5114
- }
5115
- ) : null,
5116
- showIdleFollowUps ? /* @__PURE__ */ jsx14("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx14(
5117
- FollowUpChips,
5118
- {
5119
- suggestions: state.followUps,
5120
- disabled: isBusy,
5121
- label: "Start here",
5122
- onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
5123
- }
5124
- ) }) : null,
5125
- showActivity ? /* @__PURE__ */ jsx14(
5126
- AgentActivityBubble,
6206
+ ) : resolvedDisclaimerLabel }) }) : null,
6207
+ /* @__PURE__ */ jsxs15("div", { className: "agent-rail__composer-wrap", children: [
6208
+ showJumpToLatest ? /* @__PURE__ */ jsx16(
6209
+ "button",
6210
+ {
6211
+ type: "button",
6212
+ className: "agent-rail__jump-to-latest",
6213
+ "aria-label": "Jump to the latest message",
6214
+ title: "Jump to the latest message",
6215
+ onClick: scrollToLatest,
6216
+ children: /* @__PURE__ */ jsx16(ChevronDownIcon, {})
6217
+ }
6218
+ ) : null,
6219
+ /* @__PURE__ */ jsx16(
6220
+ Composer,
6221
+ {
6222
+ variant: expanded || mobileFullscreen ? "dock" : "default",
6223
+ disabled: isBusy,
6224
+ form: composerForm,
6225
+ placeholder: composerPlaceholder,
6226
+ onSubmit: handleSubmit
6227
+ }
6228
+ ),
6229
+ poweredByLabel ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsx16("p", { children: /* @__PURE__ */ jsx16("span", { children: poweredByLabel }) }) }) : null
6230
+ ] })
6231
+ ] }),
6232
+ /* @__PURE__ */ jsx16("div", { ref: overlayRef, className: "agent-rail__overlay" }),
6233
+ receiptOpen && receiptSteps ? /* @__PURE__ */ jsx16(
6234
+ AnswerReceiptDialog,
5127
6235
  {
5128
6236
  brandLabel: resolvedBrandLabel,
5129
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5130
- failed: state.phase === "error",
5131
- steps: state.toolSteps
5132
- }
5133
- ) : null,
5134
- visibleVisitorToolResults.map((result) => /* @__PURE__ */ jsx14(
5135
- VisitorToolResultView,
5136
- {
5137
- result,
5138
- disabled: semanticSurfaceDisabled,
5139
- onToolInput
5140
- },
5141
- result.id
5142
- )),
5143
- pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ jsx14(
5144
- HumanInputCard,
5145
- {
5146
- request,
5147
- onRespond: onInputResponse
5148
- },
5149
- request.requestId
5150
- ))
5151
- ] }) : null,
5152
- visibleMessages.map((message, index) => /* @__PURE__ */ jsxs13("div", { className: "agent-rail__turn-block", children: [
5153
- /* @__PURE__ */ jsx14(
5154
- MessageBubble,
5155
- {
5156
- message,
5157
- bookingDisabled: isBusy,
5158
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5159
- offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5160
- onBook
6237
+ onClose: () => setReceiptOpen(false),
6238
+ steps: receiptSteps
5161
6239
  }
5162
- ),
5163
- index === lastVisitorIndex ? /* @__PURE__ */ jsxs13(Fragment, { children: [
5164
- showActivity ? /* @__PURE__ */ jsx14(
5165
- AgentActivityBubble,
5166
- {
5167
- brandLabel: resolvedBrandLabel,
5168
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5169
- failed: state.phase === "error",
5170
- steps: state.toolSteps
5171
- }
5172
- ) : null,
5173
- visibleVisitorToolResults.map((result) => /* @__PURE__ */ jsx14(
5174
- VisitorToolResultView,
5175
- {
5176
- result,
5177
- disabled: semanticSurfaceDisabled,
5178
- onToolInput
5179
- },
5180
- result.id
5181
- )),
5182
- pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ jsx14(
5183
- HumanInputCard,
5184
- {
5185
- request,
5186
- onRespond: onInputResponse
5187
- },
5188
- request.requestId
5189
- ))
5190
- ] }) : null
5191
- ] }, message.id)),
5192
- streamingMessage ? /* @__PURE__ */ jsx14(
5193
- MessageBubble,
5194
- {
5195
- message: streamingMessage,
5196
- bookingDisabled: isBusy,
5197
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5198
- offer: state.pendingOffer,
5199
- onBook
5200
- }
5201
- ) : null,
5202
- waitingForBooking ? /* @__PURE__ */ jsx14(BookingCardLoader, {}) : null,
5203
- state.error ? /* @__PURE__ */ jsxs13("section", { className: "agent-rail__error", role: "alert", children: [
5204
- /* @__PURE__ */ jsxs13("div", { children: [
5205
- /* @__PURE__ */ jsx14("strong", { children: "Something went wrong" }),
5206
- /* @__PURE__ */ jsx14("p", { children: state.error })
5207
- ] }),
5208
- onRetry ? /* @__PURE__ */ jsx14("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
5209
- ] }) : null
5210
- ] }) }),
5211
- /* @__PURE__ */ jsxs13("div", { className: "agent-rail__composer-wrap", children: [
5212
- /* @__PURE__ */ jsx14(
5213
- Composer,
5214
- {
5215
- variant: expanded || mobileFullscreen ? "dock" : "default",
5216
- disabled: isBusy,
5217
- form: composerForm,
5218
- placeholder: composerPlaceholder,
5219
- onSubmit
5220
- }
5221
- ),
5222
- /* @__PURE__ */ jsx14("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsxs13("p", { children: [
5223
- /* @__PURE__ */ jsx14("span", { children: "AI can make mistakes. Check important info." }),
5224
- /* @__PURE__ */ jsx14("span", { children: poweredByLabel })
5225
- ] }) })
5226
- ] })
5227
- ]
6240
+ ) : null
6241
+ ]
6242
+ }
6243
+ )
5228
6244
  }
5229
6245
  );
5230
6246
  }
5231
6247
 
5232
6248
  // src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
5233
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
6249
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
5234
6250
  function SparklesIcon() {
5235
- return /* @__PURE__ */ jsxs14(
6251
+ return /* @__PURE__ */ jsxs16(
5236
6252
  "svg",
5237
6253
  {
5238
6254
  className: "assist-edge-tab__sparkles",
@@ -5240,21 +6256,21 @@ function SparklesIcon() {
5240
6256
  fill: "none",
5241
6257
  "aria-hidden": "true",
5242
6258
  children: [
5243
- /* @__PURE__ */ jsx15(
6259
+ /* @__PURE__ */ jsx17(
5244
6260
  "path",
5245
6261
  {
5246
6262
  d: "M8 1.2l.95 2.7 2.85.05-2.25 1.75.8 2.75L8 6.7 5.65 8.45l.8-2.75L4.2 3.95l2.85-.05L8 1.2z",
5247
6263
  fill: "currentColor"
5248
6264
  }
5249
6265
  ),
5250
- /* @__PURE__ */ jsx15(
6266
+ /* @__PURE__ */ jsx17(
5251
6267
  "path",
5252
6268
  {
5253
6269
  d: "M14.2 6.4l.55 1.55 1.65.03-1.3 1 .46 1.58-1.36-1-1.36 1 .46-1.58-1.3-1 1.65-.03.55-1.55z",
5254
6270
  fill: "currentColor"
5255
6271
  }
5256
6272
  ),
5257
- /* @__PURE__ */ jsx15(
6273
+ /* @__PURE__ */ jsx17(
5258
6274
  "path",
5259
6275
  {
5260
6276
  d: "M3.1 9.1l.4 1.15 1.22.02-.96.74.34 1.17-1-.74-1 .74.34-1.17-.96-.74 1.22-.02.4-1.15z",
@@ -5268,7 +6284,7 @@ function SparklesIcon() {
5268
6284
  function TabMarkIcon({ customIconUrl }) {
5269
6285
  const url = customIconUrl?.trim();
5270
6286
  if (url) {
5271
- return /* @__PURE__ */ jsx15(
6287
+ return /* @__PURE__ */ jsx17(
5272
6288
  "img",
5273
6289
  {
5274
6290
  alt: "",
@@ -5278,10 +6294,10 @@ function TabMarkIcon({ customIconUrl }) {
5278
6294
  }
5279
6295
  );
5280
6296
  }
5281
- return /* @__PURE__ */ jsx15(SparklesIcon, {});
6297
+ return /* @__PURE__ */ jsx17(SparklesIcon, {});
5282
6298
  }
5283
6299
  function ChevronLeftIcon() {
5284
- return /* @__PURE__ */ jsx15("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx15(
6300
+ return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(
5285
6301
  "path",
5286
6302
  {
5287
6303
  d: "M10 4L6 8l4 4",
@@ -5292,8 +6308,8 @@ function ChevronLeftIcon() {
5292
6308
  }
5293
6309
  ) });
5294
6310
  }
5295
- function ChevronDownIcon() {
5296
- return /* @__PURE__ */ jsx15("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx15(
6311
+ function ChevronDownIcon2() {
6312
+ return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(
5297
6313
  "path",
5298
6314
  {
5299
6315
  d: "M4 6l4 4 4-4",
@@ -5305,7 +6321,7 @@ function ChevronDownIcon() {
5305
6321
  ) });
5306
6322
  }
5307
6323
  function DragDots() {
5308
- return /* @__PURE__ */ jsx15("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx15("i", {}, index)) });
6324
+ return /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx17("i", {}, index)) });
5309
6325
  }
5310
6326
  var VARIANT_COPY = {
5311
6327
  outline: { label: "Ask anything", aria: "Ask anything" },
@@ -5351,7 +6367,7 @@ function AssistEdgeTab({
5351
6367
  ...resolvedTextColor ? { "--as-text": resolvedTextColor } : {},
5352
6368
  colorScheme: resolvedColorScheme
5353
6369
  };
5354
- return /* @__PURE__ */ jsxs14(
6370
+ return /* @__PURE__ */ jsxs16(
5355
6371
  "button",
5356
6372
  {
5357
6373
  type: "button",
@@ -5363,15 +6379,15 @@ function AssistEdgeTab({
5363
6379
  tabIndex: visible ? 0 : -1,
5364
6380
  onClick: onOpen,
5365
6381
  children: [
5366
- mobile ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
5367
- /* @__PURE__ */ jsxs14(
6382
+ mobile ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6383
+ /* @__PURE__ */ jsxs16(
5368
6384
  "span",
5369
6385
  {
5370
6386
  className: "assist-edge-tab__mark assist-edge-tab__mark--mobile",
5371
6387
  "aria-hidden": "true",
5372
6388
  children: [
5373
- /* @__PURE__ */ jsx15(TabMarkIcon, { customIconUrl }),
5374
- showLogo ? /* @__PURE__ */ jsx15(
6389
+ /* @__PURE__ */ jsx17(TabMarkIcon, { customIconUrl }),
6390
+ showLogo ? /* @__PURE__ */ jsx17(
5375
6391
  "img",
5376
6392
  {
5377
6393
  className: "assist-edge-tab__logo",
@@ -5385,11 +6401,11 @@ function AssistEdgeTab({
5385
6401
  ]
5386
6402
  }
5387
6403
  ),
5388
- /* @__PURE__ */ jsx15("span", { className: "assist-edge-tab__label", children: visibleLabel })
5389
- ] }) : variant === "outline" ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
5390
- /* @__PURE__ */ jsxs14("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
5391
- /* @__PURE__ */ jsx15(TabMarkIcon, { customIconUrl }),
5392
- showLogo ? /* @__PURE__ */ jsx15(
6404
+ /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel })
6405
+ ] }) : variant === "outline" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6406
+ /* @__PURE__ */ jsxs16("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6407
+ /* @__PURE__ */ jsx17(TabMarkIcon, { customIconUrl }),
6408
+ showLogo ? /* @__PURE__ */ jsx17(
5393
6409
  "img",
5394
6410
  {
5395
6411
  className: "assist-edge-tab__logo",
@@ -5401,18 +6417,18 @@ function AssistEdgeTab({
5401
6417
  }
5402
6418
  ) : null
5403
6419
  ] }),
5404
- /* @__PURE__ */ jsx15("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5405
- /* @__PURE__ */ jsx15(ChevronDownIcon, {})
6420
+ /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6421
+ /* @__PURE__ */ jsx17(ChevronDownIcon2, {})
5406
6422
  ] }) : null,
5407
- variant === "ask" ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
5408
- /* @__PURE__ */ jsx15(ChevronLeftIcon, {}),
5409
- /* @__PURE__ */ jsx15("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5410
- /* @__PURE__ */ jsx15(DragDots, {})
6423
+ variant === "ask" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6424
+ /* @__PURE__ */ jsx17(ChevronLeftIcon, {}),
6425
+ /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6426
+ /* @__PURE__ */ jsx17(DragDots, {})
5411
6427
  ] }) : null,
5412
- variant === "fill" ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
5413
- /* @__PURE__ */ jsxs14("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
5414
- /* @__PURE__ */ jsx15(TabMarkIcon, { customIconUrl }),
5415
- showLogo ? /* @__PURE__ */ jsx15(
6428
+ variant === "fill" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6429
+ /* @__PURE__ */ jsxs16("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6430
+ /* @__PURE__ */ jsx17(TabMarkIcon, { customIconUrl }),
6431
+ showLogo ? /* @__PURE__ */ jsx17(
5416
6432
  "img",
5417
6433
  {
5418
6434
  className: "assist-edge-tab__logo",
@@ -5424,19 +6440,75 @@ function AssistEdgeTab({
5424
6440
  }
5425
6441
  ) : null
5426
6442
  ] }),
5427
- /* @__PURE__ */ jsx15("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5428
- /* @__PURE__ */ jsx15(ChevronLeftIcon, {})
6443
+ /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6444
+ /* @__PURE__ */ jsx17(ChevronLeftIcon, {})
5429
6445
  ] }) : null
5430
6446
  ]
5431
6447
  }
5432
6448
  );
5433
6449
  }
5434
6450
 
6451
+ // src/react/lib/agent-feedback.ts
6452
+ var AGENT_ANSWER_FEEDBACK_EVENT_TYPE = "agent_answer_feedback";
6453
+ function findPrecedingVisitorText(messages, agentMessageId) {
6454
+ const agentIndex = messages.findIndex(
6455
+ (message) => message.id === agentMessageId && message.role === "agent"
6456
+ );
6457
+ if (agentIndex < 0) return void 0;
6458
+ for (let index = agentIndex - 1; index >= 0; index -= 1) {
6459
+ const message = messages[index];
6460
+ if (message?.role === "visitor") {
6461
+ return message.text.trim() || void 0;
6462
+ }
6463
+ }
6464
+ return void 0;
6465
+ }
6466
+ function normalizeAgentFeedbackAnswerText(text) {
6467
+ const normalized = text.replace(/\s+/g, " ").trim();
6468
+ if (!normalized) return void 0;
6469
+ return normalized.length > 4e3 ? `${normalized.slice(0, 3997)}...` : normalized;
6470
+ }
6471
+ function buildAgentAnswerFeedbackEvent(input) {
6472
+ const positive = input.rating === "positive";
6473
+ const answer = input.answer ? normalizeAgentFeedbackAnswerText(input.answer) : void 0;
6474
+ return {
6475
+ event_type: AGENT_ANSWER_FEEDBACK_EVENT_TYPE,
6476
+ company: input.analytics.companyIndex,
6477
+ session_id: input.visitorSessionId,
6478
+ page: input.page,
6479
+ timestamp: Date.now(),
6480
+ tracking_consent: input.analytics.trackingConsent,
6481
+ feedback_value: positive ? 1 : -1,
6482
+ // Aggregate-safe rating enum, kept even for anonymous (no-consent) events.
6483
+ feedback_rating: positive ? "helpful" : "not_helpful",
6484
+ surface: "agent_panel",
6485
+ index_id: input.indexId,
6486
+ index_version: input.version,
6487
+ message_id: input.messageId,
6488
+ ...input.agentSessionId ? { agent_session_id: input.agentSessionId } : {},
6489
+ ...input.analytics.trackingConsent && input.query ? { query: input.query } : {},
6490
+ ...input.analytics.trackingConsent && answer ? { answer } : {}
6491
+ };
6492
+ }
6493
+ function sendAgentAnswerFeedback(eventUrl, event) {
6494
+ try {
6495
+ void fetch(eventUrl, {
6496
+ body: JSON.stringify(event),
6497
+ credentials: "omit",
6498
+ headers: { "Content-Type": "application/json" },
6499
+ keepalive: true,
6500
+ method: "POST"
6501
+ }).catch(() => {
6502
+ });
6503
+ } catch {
6504
+ }
6505
+ }
6506
+
5435
6507
  // src/react/components/AgentWidget/AgentWidget.tsx
5436
- import { useEffect as useEffect7, useRef as useRef5, useState as useState10 } from "react";
6508
+ import { useEffect as useEffect9, useRef as useRef7, useState as useState11 } from "react";
5437
6509
 
5438
6510
  // src/react/page-shift.ts
5439
- import { useEffect as useEffect5 } from "react";
6511
+ import { useEffect as useEffect7 } from "react";
5440
6512
  var PAGE_SHIFT_CLASS = "webless-agent-page-shift";
5441
6513
  var DEFAULT_RAIL_WIDTH_PX = 450;
5442
6514
  function shouldApplyPageShift(input) {
@@ -5488,7 +6560,7 @@ function clearPageMargin() {
5488
6560
  }
5489
6561
  function usePageShift(input) {
5490
6562
  const { active, railSlotRef } = input;
5491
- useEffect5(() => {
6563
+ useEffect7(() => {
5492
6564
  if (typeof document === "undefined") {
5493
6565
  return;
5494
6566
  }
@@ -5516,12 +6588,12 @@ function usePageShift(input) {
5516
6588
  }
5517
6589
 
5518
6590
  // src/react/hooks/useIsMobile.ts
5519
- import { useEffect as useEffect6, useState as useState9 } from "react";
6591
+ import { useEffect as useEffect8, useState as useState10 } from "react";
5520
6592
  function useIsMobile(breakpoint = 767) {
5521
- const [isMobile, setIsMobile] = useState9(
6593
+ const [isMobile, setIsMobile] = useState10(
5522
6594
  () => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
5523
6595
  );
5524
- useEffect6(() => {
6596
+ useEffect8(() => {
5525
6597
  const media = window.matchMedia(`(max-width: ${breakpoint}px)`);
5526
6598
  const onChange = () => setIsMobile(media.matches);
5527
6599
  onChange();
@@ -5532,7 +6604,7 @@ function useIsMobile(breakpoint = 767) {
5532
6604
  }
5533
6605
 
5534
6606
  // src/react/components/AgentWidget/AgentWidget.tsx
5535
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
6607
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
5536
6608
  function AgentWidget({
5537
6609
  indexId,
5538
6610
  customerId,
@@ -5546,13 +6618,14 @@ function AgentWidget({
5546
6618
  registerPanelController = false,
5547
6619
  colorScheme = "auto",
5548
6620
  branding,
6621
+ analytics,
5549
6622
  toolResultRegistry
5550
6623
  }) {
5551
6624
  const isMobile = useIsMobile();
5552
6625
  const placement = normalizeAgentPlacement(placementInput);
5553
- const railSlotRef = useRef5(null);
5554
- const [railCollapsed, setRailCollapsed] = useState10(defaultCollapsed);
5555
- const [railExpanded, setRailExpanded] = useState10(false);
6626
+ const railSlotRef = useRef7(null);
6627
+ const [railCollapsed, setRailCollapsed] = useState11(defaultCollapsed);
6628
+ const [railExpanded, setRailExpanded] = useState11(false);
5556
6629
  const pageShiftActive = shouldApplyPageShift({
5557
6630
  pageShift,
5558
6631
  isMobile,
@@ -5563,7 +6636,17 @@ function AgentWidget({
5563
6636
  active: pageShiftActive,
5564
6637
  railSlotRef
5565
6638
  });
5566
- const { state, reset, retry, respondToInput, respondToToolInput, submit } = useAgentChat({
6639
+ const {
6640
+ state,
6641
+ reset,
6642
+ retry,
6643
+ regenerate,
6644
+ respondToInput,
6645
+ respondToToolInput,
6646
+ submit,
6647
+ visitorSessionId,
6648
+ sessionId
6649
+ } = useAgentChat({
5567
6650
  customerId,
5568
6651
  getUnpublishedPreviewGrant,
5569
6652
  indexId,
@@ -5595,7 +6678,7 @@ function AgentWidget({
5595
6678
  } : {},
5596
6679
  ...branding?.colors?.border ? { border: branding.colors.border } : {}
5597
6680
  };
5598
- useEffect7(() => {
6681
+ useEffect9(() => {
5599
6682
  if (!registerPanelController) return;
5600
6683
  registerAgentPanelController(customerId, {
5601
6684
  open: () => setRailCollapsed(false),
@@ -5612,7 +6695,25 @@ function AgentWidget({
5612
6695
  if (isMobile) setRailCollapsed(false);
5613
6696
  await submit(message);
5614
6697
  }
5615
- useEffect7(() => {
6698
+ function handleFeedback(rating, message) {
6699
+ if (!analytics) return;
6700
+ sendAgentAnswerFeedback(
6701
+ analytics.eventUrl,
6702
+ buildAgentAnswerFeedbackEvent({
6703
+ agentSessionId: sessionId,
6704
+ analytics,
6705
+ indexId,
6706
+ messageId: message.id,
6707
+ page: window.location.href,
6708
+ query: findPrecedingVisitorText(state.messages, message.id),
6709
+ answer: message.text,
6710
+ rating,
6711
+ version: version ?? "published",
6712
+ visitorSessionId
6713
+ })
6714
+ );
6715
+ }
6716
+ useEffect9(() => {
5616
6717
  if (railCollapsed) return;
5617
6718
  const handleKeyDown = (event) => {
5618
6719
  if (event.key === "Tab" && (isMobile || railExpanded)) {
@@ -5646,19 +6747,19 @@ function AgentWidget({
5646
6747
  window.addEventListener("keydown", handleKeyDown);
5647
6748
  return () => window.removeEventListener("keydown", handleKeyDown);
5648
6749
  }, [isMobile, railCollapsed, railExpanded]);
5649
- return /* @__PURE__ */ jsxs15("div", { className: "webless-agent-root", children: [
5650
- /* @__PURE__ */ jsx16(
6750
+ return /* @__PURE__ */ jsxs17("div", { className: "webless-agent-root", children: [
6751
+ /* @__PURE__ */ jsx18(
5651
6752
  "div",
5652
6753
  {
5653
6754
  className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
5654
- children: /* @__PURE__ */ jsx16(
6755
+ children: /* @__PURE__ */ jsx18(
5655
6756
  "div",
5656
6757
  {
5657
6758
  ref: railSlotRef,
5658
6759
  className: "webless-agent-root__rail-slot",
5659
6760
  inert: railCollapsed || void 0,
5660
6761
  "aria-hidden": railCollapsed,
5661
- children: /* @__PURE__ */ jsx16(
6762
+ children: /* @__PURE__ */ jsx18(
5662
6763
  AgentRail,
5663
6764
  {
5664
6765
  theme,
@@ -5666,7 +6767,11 @@ function AgentWidget({
5666
6767
  brandLabel: agentName,
5667
6768
  brandLogoUrl: branding?.logoUrl,
5668
6769
  composerPlaceholder: branding?.composerPlaceholder ?? "Ask a question\u2026",
5669
- poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
6770
+ poweredByLabel: branding?.poweredByLabel,
6771
+ disclaimerLabel: branding?.disclaimer,
6772
+ disclaimerLink: branding?.disclaimerLink,
6773
+ answerReceipt: branding?.answerReceipt,
6774
+ readAloud: branding?.readAloud,
5670
6775
  state,
5671
6776
  mobileFullscreen: isMobile && !railCollapsed,
5672
6777
  expanded: railExpanded,
@@ -5676,6 +6781,8 @@ function AgentWidget({
5676
6781
  onSubmit: handleSubmit,
5677
6782
  onReset: reset,
5678
6783
  onRetry: () => void retry(),
6784
+ onRegenerate: () => void regenerate(),
6785
+ onFeedback: analytics ? handleFeedback : void 0,
5679
6786
  onInputResponse: (response) => void respondToInput(response),
5680
6787
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5681
6788
  onFollowUpSelect: (label) => void handleSubmit(label),
@@ -5689,7 +6796,7 @@ function AgentWidget({
5689
6796
  )
5690
6797
  }
5691
6798
  ),
5692
- railCollapsed ? /* @__PURE__ */ jsx16(
6799
+ railCollapsed ? /* @__PURE__ */ jsx18(
5693
6800
  AssistEdgeTab,
5694
6801
  {
5695
6802
  variant: placement.variant,
@@ -5734,8 +6841,13 @@ export {
5734
6841
  submitAgentPanel,
5735
6842
  defaultAgentRailTheme,
5736
6843
  defaultDarkAgentRailTheme,
6844
+ MessageActions,
5737
6845
  AgentRail,
5738
6846
  AssistEdgeTab,
6847
+ AGENT_ANSWER_FEEDBACK_EVENT_TYPE,
6848
+ findPrecedingVisitorText,
6849
+ buildAgentAnswerFeedbackEvent,
6850
+ sendAgentAnswerFeedback,
5739
6851
  AgentWidget
5740
6852
  };
5741
- //# sourceMappingURL=chunk-YNF2UPGJ.js.map
6853
+ //# sourceMappingURL=chunk-HZUPH5Z7.js.map