@webless/agent 0.6.10 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/embed.cjs CHANGED
@@ -64,7 +64,7 @@ function submitAgentPanel(customerId, message, options) {
64
64
  }
65
65
 
66
66
  // src/react/components/AgentWidget/AgentWidget.tsx
67
- var import_react12 = require("react");
67
+ var import_react15 = require("react");
68
68
 
69
69
  // src/react/page-shift.ts
70
70
  var import_react = require("react");
@@ -920,6 +920,20 @@ function latestTurnEvents(events) {
920
920
  }
921
921
  return startIndex >= 0 ? events.slice(startIndex) : [];
922
922
  }
923
+ function streamIndexBeforeLastTurn(input) {
924
+ let turnStart = -1;
925
+ for (let index = input.events.length - 1; index >= 0; index -= 1) {
926
+ if (input.events[index]?.type === "message.received") {
927
+ turnStart = index;
928
+ break;
929
+ }
930
+ }
931
+ if (turnStart < 0) return null;
932
+ return Math.max(
933
+ 0,
934
+ input.currentStreamIndex - (input.events.length - turnStart)
935
+ );
936
+ }
923
937
  function renderTurn(events) {
924
938
  let rendered = "";
925
939
  for (const event of events) {
@@ -1104,6 +1118,40 @@ var AgentSession = class {
1104
1118
  this.storeOptions
1105
1119
  );
1106
1120
  }
1121
+ async rewindBeforeLastTurn(signal) {
1122
+ const persisted = loadPersistedAgentSession(
1123
+ this.visitorSessionId,
1124
+ this.storeOptions
1125
+ );
1126
+ if (!persisted?.sessionId) return false;
1127
+ const client = this.ensureClient();
1128
+ const attached = client.sessions.attach(persisted.sessionId, {
1129
+ streamIndex: persisted.streamIndex
1130
+ });
1131
+ const snapshot = await withCapabilityRefresh(
1132
+ this.capability,
1133
+ () => attached.snapshot({ signal })
1134
+ );
1135
+ const rewindStreamIndex = streamIndexBeforeLastTurn({
1136
+ currentStreamIndex: snapshot.session.streamIndex,
1137
+ events: snapshot.events
1138
+ });
1139
+ if (rewindStreamIndex === null) return false;
1140
+ this.session = client.sessions.attach(persisted.sessionId, {
1141
+ streamIndex: rewindStreamIndex
1142
+ });
1143
+ savePersistedAgentSession(
1144
+ this.visitorSessionId,
1145
+ persisted.sessionId,
1146
+ rewindStreamIndex,
1147
+ this.storeOptions
1148
+ );
1149
+ return true;
1150
+ }
1151
+ async regenerateTurn(message, signal, handlers) {
1152
+ await this.rewindBeforeLastTurn(signal);
1153
+ return this.sendTurn(message, signal, handlers);
1154
+ }
1107
1155
  ensureClient() {
1108
1156
  const config = resolveAgentRuntimeConfig({
1109
1157
  indexId: this.indexId,
@@ -1439,6 +1487,11 @@ function createAgentClient(options) {
1439
1487
  respondOptions.signal ?? new AbortController().signal,
1440
1488
  respondOptions.handlers
1441
1489
  ),
1490
+ regenerateTurn: (message, regenerateOptions) => session.regenerateTurn(
1491
+ message,
1492
+ regenerateOptions.signal ?? new AbortController().signal,
1493
+ regenerateOptions.handlers
1494
+ ),
1442
1495
  reset: () => session.reset(),
1443
1496
  cancelActive: () => session.cancelActive(),
1444
1497
  getActiveSessionId: () => session.getActiveSessionId()
@@ -2302,6 +2355,30 @@ function bookingPresenter(kind) {
2302
2355
  }
2303
2356
  };
2304
2357
  }
2358
+ function providerErrorPresenter() {
2359
+ return {
2360
+ kind: "provider_error",
2361
+ present: ({ envelope }) => {
2362
+ const output = asRecord3(envelope.output);
2363
+ const providerError = asRecord3(output?.providerError);
2364
+ const message = safeText(providerError?.message);
2365
+ const action = safeText(providerError?.action);
2366
+ if (!message || !action) return null;
2367
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2368
+ return {
2369
+ kind: "summary",
2370
+ status: "failed",
2371
+ title: message,
2372
+ description: action,
2373
+ ...resourceLabels.length ? {
2374
+ details: [
2375
+ { label: "Affected", value: resourceLabels.join(", ") }
2376
+ ]
2377
+ } : {}
2378
+ };
2379
+ }
2380
+ };
2381
+ }
2305
2382
  function asRecord3(value) {
2306
2383
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2307
2384
  }
@@ -2419,6 +2496,7 @@ function fallbackTitleFromKind(kind) {
2419
2496
  return "Saved";
2420
2497
  }
2421
2498
  var builtInVisitorToolResultRegistry = [
2499
+ providerErrorPresenter(),
2422
2500
  bookingPresenter("booking_offer"),
2423
2501
  bookingPresenter("booking_confirmed"),
2424
2502
  bookingPresenter("booking_canceled"),
@@ -2468,7 +2546,7 @@ function finalizeSummaryPresentation(result, proposed) {
2468
2546
  return {
2469
2547
  id: result.callId,
2470
2548
  toolName: result.toolName,
2471
- status: result.status,
2549
+ status: proposed.status ?? result.status,
2472
2550
  kind: "summary",
2473
2551
  title,
2474
2552
  ...description && description !== title ? { description } : {},
@@ -2477,7 +2555,7 @@ function finalizeSummaryPresentation(result, proposed) {
2477
2555
  };
2478
2556
  }
2479
2557
  function presentVisitorToolResult(result, registry = []) {
2480
- const envelope = parseAgentToolResultEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2558
+ const envelope = parseAgentToolResultEnvelope(result.output) ?? providerErrorEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2481
2559
  const proposed = envelope ? resolvePresenterOutput(result, envelope, registry) : null;
2482
2560
  if (proposed?.kind === "booking") {
2483
2561
  return {
@@ -2540,6 +2618,25 @@ function presentVisitorToolResult(result, registry = []) {
2540
2618
  }
2541
2619
  return finalizeSummaryPresentation(result, proposed);
2542
2620
  }
2621
+ function providerErrorEnvelope(output) {
2622
+ const record = asRecord3(output);
2623
+ const providerError = asRecord3(record?.providerError);
2624
+ const message = safeText(providerError?.message);
2625
+ const action = safeText(providerError?.action);
2626
+ if (!message || !action) return null;
2627
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2628
+ return {
2629
+ schemaVersion: "webless.tool-result.v1",
2630
+ output: {
2631
+ providerError: {
2632
+ action,
2633
+ message,
2634
+ ...resourceLabels.length ? { resourceLabels } : {}
2635
+ }
2636
+ },
2637
+ presentationKinds: ["provider_error"]
2638
+ };
2639
+ }
2543
2640
  function legacyBookingEnvelope(output) {
2544
2641
  const card = bookingCardFromActionOutput(output);
2545
2642
  return card ? {
@@ -2837,6 +2934,7 @@ function useAgentChat({
2837
2934
  const {
2838
2935
  controller,
2839
2936
  initialText = "",
2937
+ regenerate: regenerate2 = false,
2840
2938
  responses,
2841
2939
  resume,
2842
2940
  visitorText
@@ -2847,6 +2945,7 @@ function useAgentChat({
2847
2945
  let streamStarted = Boolean(initialText);
2848
2946
  let streamed = initialText;
2849
2947
  const capturedOffers = [];
2948
+ let bookingConfirmed = false;
2850
2949
  let capturedInputCount = 0;
2851
2950
  const handlers = {
2852
2951
  onWork: (item) => {
@@ -2871,6 +2970,7 @@ function useAgentChat({
2871
2970
  }
2872
2971
  if (!isActiveRun()) return;
2873
2972
  if (card.type === "booking_confirmed") {
2973
+ bookingConfirmed = true;
2874
2974
  pendingBookingRef.current = card;
2875
2975
  savePendingWidgetBooking(
2876
2976
  resolvedStorageKeyPrefix,
@@ -2946,7 +3046,13 @@ function useAgentChat({
2946
3046
  initialText,
2947
3047
  message: visitorText,
2948
3048
  signal
2949
- }) : await clientRef.current.sendTurn(visitorText, { handlers, signal });
3049
+ }) : regenerate2 ? await clientRef.current.regenerateTurn(visitorText, {
3050
+ handlers,
3051
+ signal
3052
+ }) : await clientRef.current.sendTurn(visitorText, {
3053
+ handlers,
3054
+ signal
3055
+ });
2950
3056
  if (resume && finalText === null) {
2951
3057
  finalText = await clientRef.current.sendTurn(visitorText, {
2952
3058
  handlers,
@@ -2965,6 +3071,7 @@ function useAgentChat({
2965
3071
  const parsedCards = extractToolCards(displayText);
2966
3072
  for (const card of parsedCards) {
2967
3073
  if (card.type === "booking_confirmed") {
3074
+ bookingConfirmed = true;
2968
3075
  pendingBookingRef.current = card;
2969
3076
  savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
2970
3077
  }
@@ -2979,7 +3086,7 @@ function useAgentChat({
2979
3086
  messages: appendAgentTurnMessage(prev.messages, displayText),
2980
3087
  toolSteps: completeActivePlanning(prev.toolSteps),
2981
3088
  streamingText: "",
2982
- pendingOffer: capturedOffers.at(-1) ?? prev.pendingOffer,
3089
+ pendingOffer: bookingConfirmed ? null : capturedOffers.at(-1) ?? prev.pendingOffer,
2983
3090
  pendingInputs: (prev.pendingInputs ?? []).filter(
2984
3091
  isChatCollectibleInputRequest
2985
3092
  ),
@@ -3005,7 +3112,6 @@ function useAgentChat({
3005
3112
  } : step
3006
3113
  ),
3007
3114
  streamingText: "",
3008
- pendingOffer: null,
3009
3115
  error: message
3010
3116
  }));
3011
3117
  runRef.current = null;
@@ -3113,7 +3219,7 @@ ${outgoing}` : outgoing;
3113
3219
  journey: null,
3114
3220
  followUps: [],
3115
3221
  streamingText: "",
3116
- pendingOffer: null,
3222
+ pendingOffer: options?.preservePendingOffer ? prev.pendingOffer : null,
3117
3223
  pendingInputs: [],
3118
3224
  toolResults: [],
3119
3225
  error: null
@@ -3149,7 +3255,6 @@ ${outgoing}` : outgoing;
3149
3255
  journey: null,
3150
3256
  followUps: [],
3151
3257
  streamingText: "",
3152
- pendingOffer: null,
3153
3258
  pendingInputs: [],
3154
3259
  toolResults: [],
3155
3260
  error: null
@@ -3160,6 +3265,49 @@ ${outgoing}` : outgoing;
3160
3265
  visitorText: visitorTurnText(visitorMessage)
3161
3266
  });
3162
3267
  }, [runTurn, state.messages]);
3268
+ const regenerate = (0, import_react2.useCallback)(async () => {
3269
+ let lastVisitorIndex = -1;
3270
+ for (let index = state.messages.length - 1; index >= 0; index -= 1) {
3271
+ if (state.messages[index]?.role === "visitor") {
3272
+ lastVisitorIndex = index;
3273
+ break;
3274
+ }
3275
+ }
3276
+ const visitorMessage = lastVisitorIndex >= 0 ? state.messages[lastVisitorIndex] : void 0;
3277
+ if (!visitorMessage) return null;
3278
+ if (runRef.current) {
3279
+ runRef.current.abort();
3280
+ clientRef.current.cancelActive();
3281
+ }
3282
+ const controller = new AbortController();
3283
+ runRef.current = controller;
3284
+ setState((prev) => ({
3285
+ ...prev,
3286
+ phase: "thinking",
3287
+ messages: prev.messages.slice(0, lastVisitorIndex + 1),
3288
+ toolSteps: [
3289
+ {
3290
+ id: "planning",
3291
+ kind: "planning",
3292
+ label: "Understanding your question",
3293
+ state: "active"
3294
+ }
3295
+ ],
3296
+ journey: null,
3297
+ followUps: [],
3298
+ streamingText: "",
3299
+ pendingOffer: null,
3300
+ pendingInputs: [],
3301
+ toolResults: [],
3302
+ error: null
3303
+ }));
3304
+ return await runTurn({
3305
+ controller,
3306
+ regenerate: true,
3307
+ resume: false,
3308
+ visitorText: visitorTurnText(visitorMessage)
3309
+ });
3310
+ }, [runTurn, state.messages]);
3163
3311
  const respondToToolInput = (0, import_react2.useCallback)(
3164
3312
  async (surface, values) => {
3165
3313
  await submit(`${surface.title} submitted`, {
@@ -3236,6 +3384,7 @@ ${outgoing}` : outgoing;
3236
3384
  state,
3237
3385
  reset,
3238
3386
  retry,
3387
+ regenerate,
3239
3388
  respondToInput,
3240
3389
  respondToToolInput,
3241
3390
  submit,
@@ -3286,7 +3435,7 @@ function normalizeAgentPlacement(placement) {
3286
3435
  }
3287
3436
 
3288
3437
  // src/react/components/AgentRail/AgentRail.tsx
3289
- var import_react11 = require("react");
3438
+ var import_react14 = require("react");
3290
3439
 
3291
3440
  // src/react/types/conversation.ts
3292
3441
  var defaultAgentRailTheme = {
@@ -3408,6 +3557,60 @@ function stepDetail(step, steps) {
3408
3557
  return "Searched this site";
3409
3558
  return step.detail;
3410
3559
  }
3560
+ function AgentWorkSteps({
3561
+ brandLabel = "",
3562
+ onRetryStep,
3563
+ steps
3564
+ }) {
3565
+ const delegationCount = steps.filter(
3566
+ (step) => step.kind === "specialist"
3567
+ ).length;
3568
+ const delegated = delegationCount > 0 && steps.some((step) => step.kind === "planning");
3569
+ const visibleSteps = steps.filter(
3570
+ (step) => step.kind !== "planning" || Boolean(brandLabel)
3571
+ );
3572
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "agent-activity-bubble__steps", children: visibleSteps.map((step) => {
3573
+ const detail = stepDetail(step, steps);
3574
+ const child = delegated && step.kind === "specialist";
3575
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3576
+ "li",
3577
+ {
3578
+ className: `agent-activity-bubble__step${child ? " agent-activity-bubble__step--child" : ""}`,
3579
+ "data-kind": step.kind,
3580
+ "data-state": step.state,
3581
+ children: [
3582
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3583
+ "span",
3584
+ {
3585
+ className: "agent-activity-bubble__step-icon",
3586
+ "aria-hidden": "true"
3587
+ }
3588
+ ),
3589
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "agent-activity-bubble__step-copy", children: [
3590
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-activity-bubble__step-heading", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: stepLabel(step, brandLabel) }) }),
3591
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null,
3592
+ delegated && step.kind === "planning" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "agent-activity-bubble__delegation", children: [
3593
+ "Delegated ",
3594
+ delegationCount,
3595
+ " ",
3596
+ delegationCount === 1 ? "task" : "tasks"
3597
+ ] }) : null,
3598
+ step.state === "error" && onRetryStep ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3599
+ "button",
3600
+ {
3601
+ type: "button",
3602
+ className: "agent-activity-bubble__step-retry",
3603
+ onClick: () => onRetryStep(step),
3604
+ children: "Retry"
3605
+ }
3606
+ ) : null
3607
+ ] })
3608
+ ]
3609
+ },
3610
+ step.id
3611
+ );
3612
+ }) });
3613
+ }
3411
3614
  function AgentActivityBubble({
3412
3615
  brandLabel = "",
3413
3616
  failed = false,
@@ -3419,14 +3622,7 @@ function AgentActivityBubble({
3419
3622
  const [expandedReceiptId, setExpandedReceiptId] = (0, import_react5.useState)(
3420
3623
  null
3421
3624
  );
3422
- const detailsOpen = active || expandedReceiptId === receiptId;
3423
- const delegationCount = steps.filter(
3424
- (step) => step.kind === "specialist"
3425
- ).length;
3426
- const delegated = delegationCount > 0 && steps.some((step) => step.kind === "planning");
3427
- const visibleSteps = steps.filter(
3428
- (step) => step.kind !== "planning" || Boolean(brandLabel)
3429
- );
3625
+ const detailsOpen = !active && expandedReceiptId === receiptId;
3430
3626
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { className: "agent-activity-bubble", children: [
3431
3627
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
3432
3628
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -3436,9 +3632,10 @@ function AgentActivityBubble({
3436
3632
  "aria-hidden": "true"
3437
3633
  }
3438
3634
  ),
3439
- workSummary(steps, failed, brandLabel)
3635
+ workSummary(steps, failed, brandLabel),
3636
+ active ? "\u2026" : ""
3440
3637
  ] }),
3441
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "agent-activity-bubble__details", children: [
3638
+ !active ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "agent-activity-bubble__details", children: [
3442
3639
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3443
3640
  "button",
3444
3641
  {
@@ -3446,7 +3643,6 @@ function AgentActivityBubble({
3446
3643
  className: "agent-activity-bubble__summary",
3447
3644
  "aria-expanded": detailsOpen,
3448
3645
  onClick: () => {
3449
- if (active) return;
3450
3646
  setExpandedReceiptId(
3451
3647
  (current) => current === receiptId ? null : receiptId
3452
3648
  );
@@ -3454,56 +3650,145 @@ function AgentActivityBubble({
3454
3650
  children: "How this answer was made"
3455
3651
  }
3456
3652
  ),
3457
- detailsOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "agent-activity-bubble__steps", children: visibleSteps.map((step) => {
3458
- const detail = stepDetail(step, steps);
3459
- const child = delegated && step.kind === "specialist";
3460
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3461
- "li",
3462
- {
3463
- className: `agent-activity-bubble__step${child ? " agent-activity-bubble__step--child" : ""}`,
3464
- "data-kind": step.kind,
3465
- "data-state": step.state,
3466
- children: [
3467
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3468
- "span",
3469
- {
3470
- className: "agent-activity-bubble__step-icon",
3471
- "aria-hidden": "true"
3472
- }
3473
- ),
3474
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "agent-activity-bubble__step-copy", children: [
3475
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-activity-bubble__step-heading", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: stepLabel(step, brandLabel) }) }),
3476
- detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null,
3477
- delegated && step.kind === "planning" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "agent-activity-bubble__delegation", children: [
3478
- "Delegated ",
3479
- delegationCount,
3480
- " ",
3481
- delegationCount === 1 ? "task" : "tasks"
3482
- ] }) : null,
3483
- step.state === "error" && onRetryStep ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3484
- "button",
3485
- {
3486
- type: "button",
3487
- className: "agent-activity-bubble__step-retry",
3488
- onClick: () => onRetryStep(step),
3489
- children: "Retry"
3490
- }
3491
- ) : null
3492
- ] })
3493
- ]
3494
- },
3495
- step.id
3496
- );
3497
- }) }) : null
3498
- ] })
3653
+ detailsOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3654
+ AgentWorkSteps,
3655
+ {
3656
+ brandLabel,
3657
+ onRetryStep,
3658
+ steps
3659
+ }
3660
+ ) : null
3661
+ ] }) : null
3499
3662
  ] });
3500
3663
  }
3501
3664
 
3502
- // src/react/components/Composer/Composer.tsx
3665
+ // src/react/components/AnswerReceiptDialog/AnswerReceiptDialog.tsx
3666
+ var import_react7 = require("react");
3667
+ var import_react_dom = require("react-dom");
3668
+
3669
+ // src/react/components/AgentRail/AgentRailOverlayContext.tsx
3503
3670
  var import_react6 = require("react");
3671
+ var AgentRailOverlayContext = (0, import_react6.createContext)(null);
3672
+ function useAgentRailPortalRoots() {
3673
+ return (0, import_react6.useContext)(AgentRailOverlayContext);
3674
+ }
3675
+ function useAgentRailMenuPortalRoot() {
3676
+ return (0, import_react6.useContext)(AgentRailOverlayContext)?.railRef ?? null;
3677
+ }
3678
+
3679
+ // src/react/components/AnswerReceiptDialog/AnswerReceiptDialog.tsx
3504
3680
  var import_jsx_runtime2 = require("react/jsx-runtime");
3505
- function SendIcon() {
3681
+ var FOCUSABLE_SELECTOR = 'button:not(:disabled), a[href], textarea:not(:disabled), input:not(:disabled), [tabindex]:not([tabindex="-1"])';
3682
+ function CloseIcon() {
3506
3683
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3684
+ "path",
3685
+ {
3686
+ d: "M4 4l8 8M12 4l-8 8",
3687
+ stroke: "currentColor",
3688
+ strokeWidth: "1.5",
3689
+ strokeLinecap: "round"
3690
+ }
3691
+ ) });
3692
+ }
3693
+ function AnswerReceiptDialog({
3694
+ brandLabel = "",
3695
+ onClose,
3696
+ steps
3697
+ }) {
3698
+ const portalRoots = useAgentRailPortalRoots();
3699
+ const overlayRoot = portalRoots?.overlayRef ?? null;
3700
+ const cardRef = (0, import_react7.useRef)(null);
3701
+ const closeButtonRef = (0, import_react7.useRef)(null);
3702
+ const previouslyFocusedRef = (0, import_react7.useRef)(null);
3703
+ (0, import_react7.useEffect)(() => {
3704
+ previouslyFocusedRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
3705
+ closeButtonRef.current?.focus({ preventScroll: true });
3706
+ const handleKeyDown = (event) => {
3707
+ if (event.key === "Escape") {
3708
+ event.preventDefault();
3709
+ event.stopPropagation();
3710
+ onClose();
3711
+ return;
3712
+ }
3713
+ if (event.key !== "Tab" || !cardRef.current) return;
3714
+ const focusable = cardRef.current.querySelectorAll(
3715
+ FOCUSABLE_SELECTOR
3716
+ );
3717
+ if (focusable.length === 0) return;
3718
+ const first = focusable.item(0);
3719
+ const last = focusable.item(focusable.length - 1);
3720
+ if (event.shiftKey && document.activeElement === first) {
3721
+ event.preventDefault();
3722
+ last.focus({ preventScroll: true });
3723
+ } else if (!event.shiftKey && document.activeElement === last) {
3724
+ event.preventDefault();
3725
+ first.focus({ preventScroll: true });
3726
+ }
3727
+ };
3728
+ document.addEventListener("keydown", handleKeyDown);
3729
+ return () => {
3730
+ document.removeEventListener("keydown", handleKeyDown);
3731
+ previouslyFocusedRef.current?.focus({ preventScroll: true });
3732
+ };
3733
+ }, [onClose]);
3734
+ const content = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "agent-receipt-dialog", children: [
3735
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3736
+ "button",
3737
+ {
3738
+ type: "button",
3739
+ className: "agent-receipt-dialog__backdrop",
3740
+ "aria-label": "Close",
3741
+ tabIndex: -1,
3742
+ onClick: onClose
3743
+ }
3744
+ ),
3745
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3746
+ "div",
3747
+ {
3748
+ ref: cardRef,
3749
+ className: "agent-receipt-dialog__card",
3750
+ role: "dialog",
3751
+ "aria-modal": "true",
3752
+ "aria-labelledby": "agent-receipt-dialog-title",
3753
+ children: [
3754
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "agent-receipt-dialog__header", children: [
3755
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3756
+ "p",
3757
+ {
3758
+ className: "agent-receipt-dialog__title",
3759
+ id: "agent-receipt-dialog-title",
3760
+ children: "How this answer was made"
3761
+ }
3762
+ ),
3763
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3764
+ "button",
3765
+ {
3766
+ ref: closeButtonRef,
3767
+ type: "button",
3768
+ className: "agent-receipt-dialog__close",
3769
+ "aria-label": "Close",
3770
+ onClick: onClose,
3771
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {})
3772
+ }
3773
+ )
3774
+ ] }),
3775
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "agent-receipt-dialog__summary", children: workSummary(steps, false, brandLabel) }),
3776
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "agent-receipt-dialog__body", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AgentWorkSteps, { brandLabel, steps }) })
3777
+ ]
3778
+ }
3779
+ )
3780
+ ] });
3781
+ if (overlayRoot?.current) {
3782
+ return (0, import_react_dom.createPortal)(content, overlayRoot.current);
3783
+ }
3784
+ return content;
3785
+ }
3786
+
3787
+ // src/react/components/Composer/Composer.tsx
3788
+ var import_react8 = require("react");
3789
+ var import_jsx_runtime3 = require("react/jsx-runtime");
3790
+ function SendIcon() {
3791
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3507
3792
  "path",
3508
3793
  {
3509
3794
  d: "M8 12V4M8 4l-3 3M8 4l3 3",
@@ -3526,21 +3811,21 @@ function Composer({
3526
3811
  form = null,
3527
3812
  onSubmit
3528
3813
  }) {
3529
- const [value, setValue] = (0, import_react6.useState)("");
3530
- const [values, setValues] = (0, import_react6.useState)(
3814
+ const [value, setValue] = (0, import_react8.useState)("");
3815
+ const [values, setValues] = (0, import_react8.useState)(
3531
3816
  () => emptyValues(form)
3532
3817
  );
3533
- const [blurred, setBlurred] = (0, import_react6.useState)({});
3534
- const inputRef = (0, import_react6.useRef)(null);
3535
- const firstFieldRef = (0, import_react6.useRef)(null);
3536
- const formId = (0, import_react6.useId)();
3818
+ const [blurred, setBlurred] = (0, import_react8.useState)({});
3819
+ const inputRef = (0, import_react8.useRef)(null);
3820
+ const firstFieldRef = (0, import_react8.useRef)(null);
3821
+ const formId = (0, import_react8.useId)();
3537
3822
  const activeForm = form;
3538
3823
  const canSendForm = activeForm ? isComposerFormComplete(activeForm, values) : Boolean(value.trim());
3539
- (0, import_react6.useEffect)(() => {
3824
+ (0, import_react8.useEffect)(() => {
3540
3825
  setValues(emptyValues(form));
3541
3826
  setBlurred({});
3542
3827
  }, [form?.id]);
3543
- (0, import_react6.useEffect)(() => {
3828
+ (0, import_react8.useEffect)(() => {
3544
3829
  if (activeForm) firstFieldRef.current?.focus();
3545
3830
  }, [activeForm?.id]);
3546
3831
  function submitChat() {
@@ -3575,7 +3860,7 @@ function Composer({
3575
3860
  submitForm();
3576
3861
  }
3577
3862
  }
3578
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3863
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3579
3864
  "form",
3580
3865
  {
3581
3866
  className: [
@@ -3584,7 +3869,7 @@ function Composer({
3584
3869
  activeForm ? "composer--form" : ""
3585
3870
  ].filter(Boolean).join(" "),
3586
3871
  onSubmit: handleSubmit,
3587
- children: activeForm ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "composer__sheet", role: "group", "aria-label": "Required details", children: [
3872
+ children: activeForm ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "composer__sheet", role: "group", "aria-label": "Required details", children: [
3588
3873
  activeForm.fields.map((field, index) => {
3589
3874
  const fieldId = `${formId}-${field.id}`;
3590
3875
  const invalid = Boolean(blurred[field.id]) && !isValidComposerFieldValue(field, values[field.id] ?? "");
@@ -3609,7 +3894,7 @@ function Composer({
3609
3894
  },
3610
3895
  onKeyDown: handleFormKeyDown
3611
3896
  };
3612
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3897
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3613
3898
  "div",
3614
3899
  {
3615
3900
  className: [
@@ -3617,9 +3902,9 @@ function Composer({
3617
3902
  field.kind === "textarea" ? "composer__row--grow" : ""
3618
3903
  ].filter(Boolean).join(" "),
3619
3904
  children: [
3620
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "composer__label", htmlFor: fieldId, children: [
3621
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "composer__sr-only", children: field.label }),
3622
- field.kind === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3905
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "composer__label", htmlFor: fieldId, children: [
3906
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "composer__sr-only", children: field.label }),
3907
+ field.kind === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3623
3908
  "textarea",
3624
3909
  {
3625
3910
  ...controlProps,
@@ -3629,7 +3914,7 @@ function Composer({
3629
3914
  className: "composer__control composer__control--area",
3630
3915
  rows: 3
3631
3916
  }
3632
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3917
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3633
3918
  "input",
3634
3919
  {
3635
3920
  ...controlProps,
@@ -3642,24 +3927,24 @@ function Composer({
3642
3927
  }
3643
3928
  )
3644
3929
  ] }),
3645
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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
3930
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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
3646
3931
  ]
3647
3932
  },
3648
3933
  field.id
3649
3934
  );
3650
3935
  }),
3651
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "composer__toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3936
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "composer__toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3652
3937
  "button",
3653
3938
  {
3654
3939
  type: "submit",
3655
3940
  className: "composer__send",
3656
3941
  disabled: disabled || !canSendForm,
3657
3942
  "aria-label": "Send details",
3658
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SendIcon, {})
3943
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SendIcon, {})
3659
3944
  }
3660
3945
  ) })
3661
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "composer__field", children: [
3662
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3946
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "composer__field", children: [
3947
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3663
3948
  "textarea",
3664
3949
  {
3665
3950
  ref: inputRef,
@@ -3674,14 +3959,14 @@ function Composer({
3674
3959
  onKeyDown: handleChatKeyDown
3675
3960
  }
3676
3961
  ),
3677
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3962
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3678
3963
  "button",
3679
3964
  {
3680
3965
  type: "submit",
3681
3966
  className: "composer__send",
3682
3967
  disabled: disabled || !value.trim(),
3683
3968
  "aria-label": "Send message",
3684
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SendIcon, {})
3969
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SendIcon, {})
3685
3970
  }
3686
3971
  )
3687
3972
  ] })
@@ -3690,7 +3975,7 @@ function Composer({
3690
3975
  }
3691
3976
 
3692
3977
  // src/react/components/FollowUpChips/FollowUpChips.tsx
3693
- var import_jsx_runtime3 = require("react/jsx-runtime");
3978
+ var import_jsx_runtime4 = require("react/jsx-runtime");
3694
3979
  function FollowUpChips({
3695
3980
  suggestions,
3696
3981
  disabled = false,
@@ -3700,7 +3985,7 @@ function FollowUpChips({
3700
3985
  }) {
3701
3986
  if (suggestions.length === 0) return null;
3702
3987
  if (variant === "dock") {
3703
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups followups--dock", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3988
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "followups followups--dock", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "followups__scroll", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3704
3989
  "button",
3705
3990
  {
3706
3991
  type: "button",
@@ -3712,9 +3997,9 @@ function FollowUpChips({
3712
3997
  suggestion.id
3713
3998
  )) }) });
3714
3999
  }
3715
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "followups", children: [
3716
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "followups__label", children: label }),
3717
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4000
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "followups", children: [
4001
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "followups__label", children: label }),
4002
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "followups__list", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3718
4003
  "button",
3719
4004
  {
3720
4005
  type: "button",
@@ -3729,11 +4014,11 @@ function FollowUpChips({
3729
4014
  }
3730
4015
 
3731
4016
  // src/react/components/MessageBubble/MessageBubble.tsx
3732
- var import_react8 = require("react");
4017
+ var import_react10 = require("react");
3733
4018
 
3734
4019
  // src/react/components/BookingCard/BookingCard.tsx
3735
- var import_react7 = require("react");
3736
- var import_jsx_runtime4 = require("react/jsx-runtime");
4020
+ var import_react9 = require("react");
4021
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3737
4022
  var BOOKING_STEPS = [
3738
4023
  { id: "date", label: "Date" },
3739
4024
  { id: "time", label: "Time" },
@@ -3764,33 +4049,34 @@ function calendarCells(year, month) {
3764
4049
  return cells;
3765
4050
  }
3766
4051
  function BookingCardLoader() {
3767
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) });
4052
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) });
3768
4053
  }
3769
4054
  function BookingCard({
4055
+ disabled = false,
3770
4056
  offer,
3771
4057
  onBook
3772
4058
  }) {
3773
- const fieldId = (0, import_react7.useId)();
4059
+ const fieldId = (0, import_react9.useId)();
3774
4060
  const defaultType = offer.eventTypes[0]?.uri ?? offer.slots[0]?.eventTypeUri ?? "";
3775
- const [step, setStep] = (0, import_react7.useState)("date");
3776
- const [eventTypeUri, setEventTypeUri] = (0, import_react7.useState)(defaultType);
3777
- const [selectedDate, setSelectedDate] = (0, import_react7.useState)("");
3778
- const [startTime, setStartTime] = (0, import_react7.useState)("");
3779
- const [name, setName] = (0, import_react7.useState)("");
3780
- const [email, setEmail] = (0, import_react7.useState)("");
3781
- const activeStepRef = (0, import_react7.useRef)(null);
3782
- const previousStepRef = (0, import_react7.useRef)(step);
4061
+ const [step, setStep] = (0, import_react9.useState)("date");
4062
+ const [eventTypeUri, setEventTypeUri] = (0, import_react9.useState)(defaultType);
4063
+ const [selectedDate, setSelectedDate] = (0, import_react9.useState)("");
4064
+ const [startTime, setStartTime] = (0, import_react9.useState)("");
4065
+ const [name, setName] = (0, import_react9.useState)("");
4066
+ const [email, setEmail] = (0, import_react9.useState)("");
4067
+ const activeStepRef = (0, import_react9.useRef)(null);
4068
+ const previousStepRef = (0, import_react9.useRef)(step);
3783
4069
  const stepIndex = BOOKING_STEPS.findIndex((item) => item.id === step);
3784
- (0, import_react7.useEffect)(() => {
4070
+ (0, import_react9.useEffect)(() => {
3785
4071
  if (previousStepRef.current === step) return;
3786
4072
  previousStepRef.current = step;
3787
4073
  activeStepRef.current?.scrollIntoView({ block: "nearest" });
3788
4074
  }, [step]);
3789
- const slots = (0, import_react7.useMemo)(
4075
+ const slots = (0, import_react9.useMemo)(
3790
4076
  () => bookingSlotsForEventType(offer.slots, eventTypeUri),
3791
4077
  [eventTypeUri, offer.slots]
3792
4078
  );
3793
- const availableByDate = (0, import_react7.useMemo)(() => {
4079
+ const availableByDate = (0, import_react9.useMemo)(() => {
3794
4080
  const next = /* @__PURE__ */ new Map();
3795
4081
  for (const slot of slots) {
3796
4082
  const key = slotDateKey(slot.startTime);
@@ -3798,7 +4084,7 @@ function BookingCard({
3798
4084
  }
3799
4085
  return next;
3800
4086
  }, [slots]);
3801
- const [visibleMonth, setVisibleMonth] = (0, import_react7.useState)(
4087
+ const [visibleMonth, setVisibleMonth] = (0, import_react9.useState)(
3802
4088
  () => firstAvailableBookingMonth(slots)
3803
4089
  );
3804
4090
  function selectEventType(nextType) {
@@ -3811,7 +4097,7 @@ function BookingCard({
3811
4097
  )
3812
4098
  );
3813
4099
  }
3814
- const daySlots = (0, import_react7.useMemo)(
4100
+ const daySlots = (0, import_react9.useMemo)(
3815
4101
  () => slots.filter((slot) => slotDateKey(slot.startTime) === selectedDate),
3816
4102
  [selectedDate, slots]
3817
4103
  );
@@ -3820,7 +4106,7 @@ function BookingCard({
3820
4106
  );
3821
4107
  const selectedSample = availableByDate.get(selectedDate) ?? startTime;
3822
4108
  const timeZone = formatSlotTimeZone(slots[0]?.startTime ?? selectedSample);
3823
- const weekdays = (0, import_react7.useMemo)(() => weekdayLabels(), []);
4109
+ const weekdays = (0, import_react9.useMemo)(() => weekdayLabels(), []);
3824
4110
  const cells = calendarCells(visibleMonth.year, visibleMonth.month);
3825
4111
  const canPrevMonth = [...availableByDate.keys()].some((key) => {
3826
4112
  const month = monthFromKey(key);
@@ -3862,222 +4148,236 @@ function BookingCard({
3862
4148
  })
3863
4149
  });
3864
4150
  }
3865
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3866
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3867
- "li",
3868
- {
3869
- className: [
3870
- "booking-card__step-indicator",
3871
- index === stepIndex ? "booking-card__step-indicator--active" : "",
3872
- index < stepIndex ? "booking-card__step-indicator--complete" : ""
3873
- ].filter(Boolean).join(" "),
3874
- "aria-current": index === stepIndex ? "step" : void 0,
3875
- children: [
3876
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
3877
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label })
3878
- ]
3879
- },
3880
- item.id
3881
- )) }),
3882
- step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3883
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3884
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3885
- "Times in ",
3886
- timeZone
3887
- ] }) : null,
3888
- offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3889
- "label",
3890
- {
3891
- className: "booking-card__field",
3892
- htmlFor: `${fieldId}-type`,
3893
- children: [
3894
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Meeting" }),
3895
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3896
- "select",
3897
- {
3898
- id: `${fieldId}-type`,
3899
- value: eventTypeUri,
3900
- onChange: (event) => selectEventType(event.target.value),
3901
- children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: item.uri, children: item.name }, item.uri))
3902
- }
3903
- )
3904
- ]
3905
- }
3906
- ) : null,
3907
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__month", children: [
3908
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3909
- "button",
3910
- {
3911
- type: "button",
3912
- className: "booking-card__nav",
3913
- "aria-label": "Previous month",
3914
- disabled: !canPrevMonth,
3915
- onClick: () => goToMonth(-1),
3916
- children: "\u2039"
3917
- }
3918
- ),
3919
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3920
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3921
- "button",
4151
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4152
+ "section",
4153
+ {
4154
+ className: "booking-card",
4155
+ "aria-busy": disabled || void 0,
4156
+ "aria-label": "Book a meeting",
4157
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
4158
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4159
+ "li",
3922
4160
  {
3923
- type: "button",
3924
- className: "booking-card__nav",
3925
- "aria-label": "Next month",
3926
- disabled: !canNextMonth,
3927
- onClick: () => goToMonth(1),
3928
- children: "\u203A"
3929
- }
3930
- )
3931
- ] }),
3932
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: label }, label)) }),
3933
- offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3934
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3935
- "div",
3936
- {
3937
- className: "booking-card__calendar",
3938
- role: "grid",
3939
- "aria-label": "Available dates",
3940
- children: cells.map((cell, index) => {
3941
- if (!cell) {
3942
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3943
- "span",
3944
- {
3945
- className: "booking-card__day"
3946
- },
3947
- `empty-${index}`
3948
- );
4161
+ className: [
4162
+ "booking-card__step-indicator",
4163
+ index === stepIndex ? "booking-card__step-indicator--active" : "",
4164
+ index < stepIndex ? "booking-card__step-indicator--complete" : ""
4165
+ ].filter(Boolean).join(" "),
4166
+ "aria-current": index === stepIndex ? "step" : void 0,
4167
+ children: [
4168
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
4169
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: item.label })
4170
+ ]
4171
+ },
4172
+ item.id
4173
+ )) }),
4174
+ step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4175
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
4176
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "booking-card__tz", children: [
4177
+ "Times in ",
4178
+ timeZone
4179
+ ] }) : null,
4180
+ offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4181
+ "label",
4182
+ {
4183
+ className: "booking-card__field",
4184
+ htmlFor: `${fieldId}-type`,
4185
+ children: [
4186
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Meeting" }),
4187
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4188
+ "select",
4189
+ {
4190
+ id: `${fieldId}-type`,
4191
+ value: eventTypeUri,
4192
+ disabled,
4193
+ onChange: (event) => selectEventType(event.target.value),
4194
+ children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: item.uri, children: item.name }, item.uri))
4195
+ }
4196
+ )
4197
+ ]
3949
4198
  }
3950
- const available = availableByDate.has(cell.key);
3951
- const selected = cell.key === selectedDate;
3952
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4199
+ ) : null,
4200
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__month", children: [
4201
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3953
4202
  "button",
3954
4203
  {
3955
4204
  type: "button",
3956
- className: [
3957
- "booking-card__day",
3958
- available ? "booking-card__day--available" : "",
3959
- selected ? "booking-card__day--selected" : ""
3960
- ].filter(Boolean).join(" "),
3961
- disabled: !available,
3962
- "aria-pressed": selected,
3963
- onClick: () => selectDate(cell.key),
3964
- children: cell.day
3965
- },
3966
- cell.key
3967
- );
3968
- })
3969
- }
3970
- )
3971
- ] }, "date") : null,
3972
- step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3973
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
3974
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3975
- "button",
3976
- {
3977
- type: "button",
3978
- className: "booking-card__nav",
3979
- "aria-label": "Back to dates",
3980
- onClick: () => setStep("date"),
3981
- children: "\u2039"
3982
- }
3983
- ),
3984
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
3985
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3986
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3987
- "Times in ",
3988
- timeZone
3989
- ] }) : null
3990
- ] })
3991
- ] }),
3992
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3993
- "button",
3994
- {
3995
- type: "button",
3996
- className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
3997
- onClick: () => selectTime(slot.startTime),
3998
- children: formatTimeChip(slot.startTime)
3999
- },
4000
- slot.startTime
4001
- )) })
4002
- ] }, "time") : null,
4003
- step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4004
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
4005
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4006
- "button",
4007
- {
4008
- type: "button",
4009
- className: "booking-card__nav",
4010
- "aria-label": "Back to times",
4011
- onClick: () => setStep("time"),
4012
- children: "\u2039"
4013
- }
4014
- ),
4015
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4016
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4017
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4018
- selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4019
- ] })
4020
- ] }),
4021
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__identity", children: [
4022
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4023
- "label",
4024
- {
4025
- className: "booking-card__field",
4026
- htmlFor: `${fieldId}-name`,
4027
- children: [
4028
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Name" }),
4029
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4030
- "input",
4031
- {
4032
- id: `${fieldId}-name`,
4033
- autoComplete: "name",
4034
- value: name,
4035
- onChange: (event) => setName(event.target.value),
4036
- required: true
4037
- }
4038
- )
4039
- ]
4040
- }
4041
- ),
4042
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4043
- "label",
4044
- {
4045
- className: "booking-card__field",
4046
- htmlFor: `${fieldId}-email`,
4047
- children: [
4048
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Email" }),
4049
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4050
- "input",
4051
- {
4052
- id: `${fieldId}-email`,
4053
- type: "email",
4054
- autoComplete: "email",
4055
- value: email,
4056
- onChange: (event) => setEmail(event.target.value),
4057
- required: true
4205
+ className: "booking-card__nav",
4206
+ "aria-label": "Previous month",
4207
+ disabled: disabled || !canPrevMonth,
4208
+ onClick: () => goToMonth(-1),
4209
+ children: "\u2039"
4210
+ }
4211
+ ),
4212
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
4213
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4214
+ "button",
4215
+ {
4216
+ type: "button",
4217
+ className: "booking-card__nav",
4218
+ "aria-label": "Next month",
4219
+ disabled: disabled || !canNextMonth,
4220
+ onClick: () => goToMonth(1),
4221
+ children: "\u203A"
4222
+ }
4223
+ )
4224
+ ] }),
4225
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: label }, label)) }),
4226
+ offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
4227
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4228
+ "div",
4229
+ {
4230
+ className: "booking-card__calendar",
4231
+ role: "grid",
4232
+ "aria-label": "Available dates",
4233
+ children: cells.map((cell, index) => {
4234
+ if (!cell) {
4235
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4236
+ "span",
4237
+ {
4238
+ className: "booking-card__day"
4239
+ },
4240
+ `empty-${index}`
4241
+ );
4058
4242
  }
4059
- )
4060
- ]
4061
- }
4062
- )
4063
- ] }),
4064
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4065
- "button",
4066
- {
4067
- type: "submit",
4068
- className: "booking-card__submit",
4069
- disabled: !name.trim() || !email.trim(),
4070
- children: "Book this time"
4071
- }
4072
- )
4073
- ] }, "details") : null
4074
- ] }) });
4243
+ const available = availableByDate.has(cell.key);
4244
+ const selected = cell.key === selectedDate;
4245
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4246
+ "button",
4247
+ {
4248
+ type: "button",
4249
+ className: [
4250
+ "booking-card__day",
4251
+ available ? "booking-card__day--available" : "",
4252
+ selected ? "booking-card__day--selected" : ""
4253
+ ].filter(Boolean).join(" "),
4254
+ disabled: disabled || !available,
4255
+ "aria-pressed": selected,
4256
+ onClick: () => selectDate(cell.key),
4257
+ children: cell.day
4258
+ },
4259
+ cell.key
4260
+ );
4261
+ })
4262
+ }
4263
+ )
4264
+ ] }, "date") : null,
4265
+ step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4266
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__step-bar", children: [
4267
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4268
+ "button",
4269
+ {
4270
+ type: "button",
4271
+ className: "booking-card__nav",
4272
+ "aria-label": "Back to dates",
4273
+ disabled,
4274
+ onClick: () => setStep("date"),
4275
+ children: "\u2039"
4276
+ }
4277
+ ),
4278
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
4279
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
4280
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "booking-card__tz", children: [
4281
+ "Times in ",
4282
+ timeZone
4283
+ ] }) : null
4284
+ ] })
4285
+ ] }),
4286
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4287
+ "button",
4288
+ {
4289
+ type: "button",
4290
+ className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
4291
+ disabled,
4292
+ onClick: () => selectTime(slot.startTime),
4293
+ children: formatTimeChip(slot.startTime)
4294
+ },
4295
+ slot.startTime
4296
+ )) })
4297
+ ] }, "time") : null,
4298
+ step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4299
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__step-bar", children: [
4300
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4301
+ "button",
4302
+ {
4303
+ type: "button",
4304
+ className: "booking-card__nav",
4305
+ "aria-label": "Back to times",
4306
+ disabled,
4307
+ onClick: () => setStep("time"),
4308
+ children: "\u2039"
4309
+ }
4310
+ ),
4311
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
4312
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4313
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4314
+ selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4315
+ ] })
4316
+ ] }),
4317
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "booking-card__identity", children: [
4318
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4319
+ "label",
4320
+ {
4321
+ className: "booking-card__field",
4322
+ htmlFor: `${fieldId}-name`,
4323
+ children: [
4324
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Name" }),
4325
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4326
+ "input",
4327
+ {
4328
+ id: `${fieldId}-name`,
4329
+ autoComplete: "name",
4330
+ disabled,
4331
+ value: name,
4332
+ onChange: (event) => setName(event.target.value),
4333
+ required: true
4334
+ }
4335
+ )
4336
+ ]
4337
+ }
4338
+ ),
4339
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4340
+ "label",
4341
+ {
4342
+ className: "booking-card__field",
4343
+ htmlFor: `${fieldId}-email`,
4344
+ children: [
4345
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Email" }),
4346
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4347
+ "input",
4348
+ {
4349
+ id: `${fieldId}-email`,
4350
+ type: "email",
4351
+ autoComplete: "email",
4352
+ disabled,
4353
+ value: email,
4354
+ onChange: (event) => setEmail(event.target.value),
4355
+ required: true
4356
+ }
4357
+ )
4358
+ ]
4359
+ }
4360
+ )
4361
+ ] }),
4362
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4363
+ "button",
4364
+ {
4365
+ type: "submit",
4366
+ className: "booking-card__submit",
4367
+ disabled: disabled || !name.trim() || !email.trim(),
4368
+ children: disabled ? "Booking\u2026" : "Book this time"
4369
+ }
4370
+ )
4371
+ ] }, "details") : null
4372
+ ] })
4373
+ }
4374
+ );
4075
4375
  }
4076
4376
 
4077
4377
  // src/react/components/MessageBubble/MessageBubble.tsx
4078
4378
  var import_streamdown = require("streamdown");
4079
4379
  var import_styles = require("streamdown/styles.css");
4080
- var import_jsx_runtime5 = require("react/jsx-runtime");
4380
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4081
4381
  function normalizeDedupeText(text) {
4082
4382
  return text.trim().replace(/\s+/g, " ").toLowerCase();
4083
4383
  }
@@ -4088,9 +4388,7 @@ function paragraphsAreNearDuplicates(first, second) {
4088
4388
  if (left === right) return true;
4089
4389
  const shorter = left.length <= right.length ? left : right;
4090
4390
  const longer = left.length <= right.length ? right : left;
4091
- return longer.startsWith(
4092
- shorter.slice(0, Math.floor(shorter.length * 0.85))
4093
- );
4391
+ return longer.startsWith(shorter.slice(0, Math.floor(shorter.length * 0.85)));
4094
4392
  }
4095
4393
  function paragraphsShareOpening(first, second) {
4096
4394
  const opening = first.split("\n")[0]?.trim();
@@ -4118,11 +4416,12 @@ function collapseRepeatedText(text) {
4118
4416
  function MessageBubble({
4119
4417
  message,
4120
4418
  brandLogoUrl,
4419
+ bookingDisabled = false,
4121
4420
  offer,
4122
4421
  onBook
4123
4422
  }) {
4124
4423
  const resolvedLogoUrl = brandLogoUrl?.trim();
4125
- const [failedLogoUrl, setFailedLogoUrl] = (0, import_react8.useState)(null);
4424
+ const [failedLogoUrl, setFailedLogoUrl] = (0, import_react10.useState)(null);
4126
4425
  const showBrandLogo = Boolean(resolvedLogoUrl) && failedLogoUrl !== resolvedLogoUrl;
4127
4426
  const cards = message.role === "agent" ? extractToolCards(message.text) : [];
4128
4427
  const extractedOffers = cards.filter(
@@ -4135,11 +4434,11 @@ function MessageBubble({
4135
4434
  offers.length > 0 ? sanitizeBookingOfferCopy(visibleText) : looksLikeBookingAvailabilityDump(visibleText) ? sanitizeBookingOfferCopy(visibleText) : visibleText || (isStreaming ? "" : message.text)
4136
4435
  );
4137
4436
  if (message.role === "visitor") {
4138
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "message-bubble__text", children: message.text }) });
4437
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "message-bubble__text", children: message.text }) });
4139
4438
  }
4140
4439
  const citations = message.citations ?? [];
4141
- const agentText = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "message-bubble__text", children: [
4142
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4440
+ const agentText = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "message-bubble__text", children: [
4441
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4143
4442
  import_streamdown.Streamdown,
4144
4443
  {
4145
4444
  animated: isStreaming,
@@ -4153,22 +4452,21 @@ function MessageBubble({
4153
4452
  children: displayText
4154
4453
  }
4155
4454
  ),
4156
- citations.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4157
- "a",
4158
- {
4159
- href: citation.url,
4160
- target: "_blank",
4161
- rel: "noreferrer",
4162
- children: [
4163
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "message-bubble__source-icon", "aria-hidden": "true", children: "\u25A6" }),
4164
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: citation.label })
4165
- ]
4166
- }
4167
- ) }, citation.id)) }) : null
4455
+ citations.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("a", { href: citation.url, target: "_blank", rel: "noreferrer", children: [
4456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4457
+ "span",
4458
+ {
4459
+ className: "message-bubble__source-icon",
4460
+ "aria-hidden": "true",
4461
+ children: "\u25A6"
4462
+ }
4463
+ ),
4464
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: citation.label })
4465
+ ] }) }, citation.id)) }) : null
4168
4466
  ] });
4169
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("article", { className: "message-bubble message-bubble--agent", children: [
4170
- displayText ? showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "message-bubble__agent-row", children: [
4171
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "message-bubble__agent-avatar", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4467
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("article", { className: "message-bubble message-bubble--agent", children: [
4468
+ displayText ? showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "message-bubble__agent-row", children: [
4469
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "message-bubble__agent-avatar", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4172
4470
  "img",
4173
4471
  {
4174
4472
  src: resolvedLogoUrl,
@@ -4180,9 +4478,10 @@ function MessageBubble({
4180
4478
  ) }),
4181
4479
  agentText
4182
4480
  ] }) : agentText : null,
4183
- offers.map((nextOffer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4481
+ offers.map((nextOffer, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4184
4482
  BookingCard,
4185
4483
  {
4484
+ disabled: bookingDisabled,
4186
4485
  offer: nextOffer,
4187
4486
  onBook
4188
4487
  },
@@ -4191,11 +4490,498 @@ function MessageBubble({
4191
4490
  ] });
4192
4491
  }
4193
4492
 
4493
+ // src/react/components/MessageActions/MessageActions.tsx
4494
+ var import_react11 = require("react");
4495
+ var import_react_dom2 = require("react-dom");
4496
+
4497
+ // src/react/lib/speech.ts
4498
+ function toSpeechText(text) {
4499
+ let out = hideToolCardFences(text);
4500
+ out = out.replace(/```[\s\S]*?```/g, " ");
4501
+ out = out.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
4502
+ out = out.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1");
4503
+ out = out.replace(/^\s{0,3}#{1,6}\s+/gm, "");
4504
+ out = out.replace(/(\*\*|__)(.*?)\1/g, "$2");
4505
+ out = out.replace(/(\*|_)(.*?)\1/g, "$2");
4506
+ out = out.replace(/~~(.*?)~~/g, "$1");
4507
+ out = out.replace(/`([^`]*)`/g, "$1");
4508
+ out = out.replace(/^\s*>\s?/gm, "");
4509
+ out = out.replace(/^\s*[-*+]\s+/gm, "");
4510
+ out = out.replace(/^\s*\d+\.\s+/gm, "");
4511
+ out = out.replace(/\|/g, " ");
4512
+ out = out.replace(/^\s*[-:]{3,}\s*$/gm, " ");
4513
+ out = out.replace(/\s*\n\s*/g, ". ");
4514
+ out = out.replace(/(?:\.\s*){2,}/g, ". ");
4515
+ return out.replace(/\s{2,}/g, " ").trim();
4516
+ }
4517
+ function isSpeechSupported() {
4518
+ return typeof window !== "undefined" && "speechSynthesis" in window && typeof window.SpeechSynthesisUtterance === "function";
4519
+ }
4520
+
4521
+ // src/react/components/MessageActions/MessageActions.tsx
4522
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4523
+ function CopyIcon() {
4524
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4525
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4526
+ "rect",
4527
+ {
4528
+ x: "5.75",
4529
+ y: "5.75",
4530
+ width: "7.5",
4531
+ height: "7.5",
4532
+ rx: "1.5",
4533
+ stroke: "currentColor",
4534
+ strokeWidth: "1.5"
4535
+ }
4536
+ ),
4537
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4538
+ "path",
4539
+ {
4540
+ 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",
4541
+ stroke: "currentColor",
4542
+ strokeWidth: "1.5"
4543
+ }
4544
+ )
4545
+ ] });
4546
+ }
4547
+ function CheckIcon() {
4548
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4549
+ "path",
4550
+ {
4551
+ d: "M3.5 8.5l3 3 6-7",
4552
+ stroke: "currentColor",
4553
+ strokeWidth: "1.6",
4554
+ strokeLinecap: "round",
4555
+ strokeLinejoin: "round"
4556
+ }
4557
+ ) });
4558
+ }
4559
+ function ThumbUpIcon() {
4560
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4561
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4562
+ "path",
4563
+ {
4564
+ d: "M4.67 6.67v8",
4565
+ stroke: "currentColor",
4566
+ strokeWidth: "1.5",
4567
+ strokeLinecap: "round"
4568
+ }
4569
+ ),
4570
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4571
+ "path",
4572
+ {
4573
+ 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",
4574
+ stroke: "currentColor",
4575
+ strokeWidth: "1.5",
4576
+ strokeLinecap: "round",
4577
+ strokeLinejoin: "round"
4578
+ }
4579
+ )
4580
+ ] });
4581
+ }
4582
+ function ThumbDownIcon() {
4583
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("g", { transform: "rotate(180 8 8)", children: [
4584
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4585
+ "path",
4586
+ {
4587
+ d: "M4.67 6.67v8",
4588
+ stroke: "currentColor",
4589
+ strokeWidth: "1.5",
4590
+ strokeLinecap: "round"
4591
+ }
4592
+ ),
4593
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4594
+ "path",
4595
+ {
4596
+ 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",
4597
+ stroke: "currentColor",
4598
+ strokeWidth: "1.5",
4599
+ strokeLinecap: "round",
4600
+ strokeLinejoin: "round"
4601
+ }
4602
+ )
4603
+ ] }) });
4604
+ }
4605
+ function RegenerateIcon() {
4606
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4607
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4608
+ "path",
4609
+ {
4610
+ d: "M2 8a6 6 0 0 1 6-6 6.5 6.5 0 0 1 4.5 1.83L14 5.33",
4611
+ stroke: "currentColor",
4612
+ strokeWidth: "1.5",
4613
+ strokeLinecap: "round"
4614
+ }
4615
+ ),
4616
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4617
+ "path",
4618
+ {
4619
+ d: "M14 2v3.33h-3.33",
4620
+ stroke: "currentColor",
4621
+ strokeWidth: "1.5",
4622
+ strokeLinecap: "round",
4623
+ strokeLinejoin: "round"
4624
+ }
4625
+ ),
4626
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4627
+ "path",
4628
+ {
4629
+ d: "M14 8a6 6 0 0 1-6 6 6.5 6.5 0 0 1-4.5-1.83L2 10.67",
4630
+ stroke: "currentColor",
4631
+ strokeWidth: "1.5",
4632
+ strokeLinecap: "round"
4633
+ }
4634
+ ),
4635
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4636
+ "path",
4637
+ {
4638
+ d: "M5.33 10.67H2V14",
4639
+ stroke: "currentColor",
4640
+ strokeWidth: "1.5",
4641
+ strokeLinecap: "round",
4642
+ strokeLinejoin: "round"
4643
+ }
4644
+ )
4645
+ ] });
4646
+ }
4647
+ function MoreIcon() {
4648
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4649
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { cx: "3.5", cy: "8", r: "1.15", fill: "currentColor" }),
4650
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { cx: "8", cy: "8", r: "1.15", fill: "currentColor" }),
4651
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { cx: "12.5", cy: "8", r: "1.15", fill: "currentColor" })
4652
+ ] });
4653
+ }
4654
+ function SourcesIcon() {
4655
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4656
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4657
+ "path",
4658
+ {
4659
+ 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",
4660
+ stroke: "currentColor",
4661
+ strokeWidth: "1.4",
4662
+ strokeLinecap: "round",
4663
+ strokeLinejoin: "round"
4664
+ }
4665
+ ),
4666
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4667
+ "path",
4668
+ {
4669
+ d: "M8 4.5v9",
4670
+ stroke: "currentColor",
4671
+ strokeWidth: "1.4",
4672
+ strokeLinecap: "round"
4673
+ }
4674
+ )
4675
+ ] });
4676
+ }
4677
+ function ReadAloudIcon() {
4678
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4679
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4680
+ "path",
4681
+ {
4682
+ 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",
4683
+ stroke: "currentColor",
4684
+ strokeWidth: "1.4",
4685
+ strokeLinecap: "round",
4686
+ strokeLinejoin: "round"
4687
+ }
4688
+ ),
4689
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4690
+ "path",
4691
+ {
4692
+ 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",
4693
+ stroke: "currentColor",
4694
+ strokeWidth: "1.4",
4695
+ strokeLinecap: "round"
4696
+ }
4697
+ )
4698
+ ] });
4699
+ }
4700
+ function StopIcon() {
4701
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4702
+ "rect",
4703
+ {
4704
+ x: "4",
4705
+ y: "4",
4706
+ width: "8",
4707
+ height: "8",
4708
+ rx: "1.5",
4709
+ stroke: "currentColor",
4710
+ strokeWidth: "1.5"
4711
+ }
4712
+ ) });
4713
+ }
4714
+ async function writeToClipboard(text) {
4715
+ try {
4716
+ await navigator.clipboard.writeText(text);
4717
+ } catch {
4718
+ const textarea = document.createElement("textarea");
4719
+ textarea.value = text;
4720
+ textarea.style.position = "fixed";
4721
+ textarea.style.opacity = "0";
4722
+ document.body.appendChild(textarea);
4723
+ textarea.select();
4724
+ document.execCommand("copy");
4725
+ textarea.remove();
4726
+ }
4727
+ }
4728
+ function formatAnsweredAt(answeredAt) {
4729
+ if (!answeredAt) return null;
4730
+ const date = new Date(answeredAt);
4731
+ if (Number.isNaN(date.getTime())) return null;
4732
+ return new Intl.DateTimeFormat(void 0, {
4733
+ dateStyle: "medium",
4734
+ timeStyle: "short"
4735
+ }).format(date);
4736
+ }
4737
+ function resolveMenuPosition(input) {
4738
+ const padding = 8;
4739
+ const { button, menuHeight, menuWidth, rail } = input;
4740
+ if (!rail) {
4741
+ return {
4742
+ left: button.left,
4743
+ top: button.top - menuHeight - 6
4744
+ };
4745
+ }
4746
+ let left = button.left - rail.left;
4747
+ let top = button.top - rail.top - menuHeight - 6;
4748
+ left = Math.min(
4749
+ Math.max(left, padding),
4750
+ rail.width - menuWidth - padding
4751
+ );
4752
+ if (top < padding) {
4753
+ top = button.bottom - rail.top + 6;
4754
+ }
4755
+ top = Math.min(top, rail.height - menuHeight - padding);
4756
+ return { left, top };
4757
+ }
4758
+ function MessageActions({
4759
+ answeredAt,
4760
+ copyText,
4761
+ disabled = false,
4762
+ onOpenReceipt,
4763
+ onRegenerate,
4764
+ onFeedback,
4765
+ readAloud = false,
4766
+ receiptSteps,
4767
+ speechText
4768
+ }) {
4769
+ const menuPortalRoot = useAgentRailMenuPortalRoot();
4770
+ const [copied, setCopied] = (0, import_react11.useState)(false);
4771
+ const [rating, setRating] = (0, import_react11.useState)(null);
4772
+ const [menuOpen, setMenuOpen] = (0, import_react11.useState)(false);
4773
+ const [menuPosition, setMenuPosition] = (0, import_react11.useState)(null);
4774
+ const [speaking, setSpeaking] = (0, import_react11.useState)(false);
4775
+ const copyTimerRef = (0, import_react11.useRef)(null);
4776
+ const menuRef = (0, import_react11.useRef)(null);
4777
+ const portaledMenuRef = (0, import_react11.useRef)(null);
4778
+ const moreButtonRef = (0, import_react11.useRef)(null);
4779
+ const answeredLabel = formatAnsweredAt(answeredAt ?? 0);
4780
+ const resolvedSpeechText = speechText ?? toSpeechText(copyText);
4781
+ const canReadAloud = readAloud && isSpeechSupported() && resolvedSpeechText;
4782
+ const showMenu = Boolean(answeredLabel) || Boolean(receiptSteps) || canReadAloud;
4783
+ const canOpenReceipt = Boolean(receiptSteps) && Boolean(onOpenReceipt);
4784
+ (0, import_react11.useLayoutEffect)(() => {
4785
+ if (!menuOpen || !moreButtonRef.current || !portaledMenuRef.current) {
4786
+ setMenuPosition(null);
4787
+ return;
4788
+ }
4789
+ const button = moreButtonRef.current.getBoundingClientRect();
4790
+ const menu2 = portaledMenuRef.current;
4791
+ const rail = menuPortalRoot?.current?.getBoundingClientRect() ?? null;
4792
+ setMenuPosition(
4793
+ resolveMenuPosition({
4794
+ button,
4795
+ menuHeight: menu2.offsetHeight,
4796
+ menuWidth: menu2.offsetWidth || 190,
4797
+ rail
4798
+ })
4799
+ );
4800
+ }, [menuOpen, menuPortalRoot]);
4801
+ (0, import_react11.useEffect)(
4802
+ () => () => {
4803
+ if (copyTimerRef.current !== null) {
4804
+ window.clearTimeout(copyTimerRef.current);
4805
+ }
4806
+ if (speaking) window.speechSynthesis.cancel();
4807
+ },
4808
+ // Cancel speech only when this answer's actions unmount.
4809
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4810
+ []
4811
+ );
4812
+ (0, import_react11.useEffect)(() => {
4813
+ if (!menuOpen) return;
4814
+ const handlePointerDown = (event) => {
4815
+ const target = event.target;
4816
+ if (!menuRef.current?.contains(target) && !portaledMenuRef.current?.contains(target)) {
4817
+ setMenuOpen(false);
4818
+ }
4819
+ };
4820
+ const handleKeyDown = (event) => {
4821
+ if (event.key !== "Escape") return;
4822
+ event.preventDefault();
4823
+ event.stopPropagation();
4824
+ setMenuOpen(false);
4825
+ };
4826
+ document.addEventListener("pointerdown", handlePointerDown);
4827
+ document.addEventListener("keydown", handleKeyDown);
4828
+ return () => {
4829
+ document.removeEventListener("pointerdown", handlePointerDown);
4830
+ document.removeEventListener("keydown", handleKeyDown);
4831
+ };
4832
+ }, [menuOpen]);
4833
+ function handleCopy() {
4834
+ void writeToClipboard(copyText);
4835
+ setCopied(true);
4836
+ if (copyTimerRef.current !== null) {
4837
+ window.clearTimeout(copyTimerRef.current);
4838
+ }
4839
+ copyTimerRef.current = window.setTimeout(() => setCopied(false), 1600);
4840
+ }
4841
+ function handleFeedback(next) {
4842
+ const resolved = rating === next ? null : next;
4843
+ setRating(resolved);
4844
+ if (resolved) onFeedback?.(resolved);
4845
+ }
4846
+ function handleReadAloud() {
4847
+ if (!canReadAloud) return;
4848
+ setMenuOpen(false);
4849
+ if (speaking) {
4850
+ window.speechSynthesis.cancel();
4851
+ setSpeaking(false);
4852
+ return;
4853
+ }
4854
+ const utterance = new SpeechSynthesisUtterance(resolvedSpeechText);
4855
+ utterance.onend = () => setSpeaking(false);
4856
+ utterance.onerror = () => setSpeaking(false);
4857
+ window.speechSynthesis.cancel();
4858
+ window.speechSynthesis.speak(utterance);
4859
+ setSpeaking(true);
4860
+ }
4861
+ const menu = menuOpen ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4862
+ "div",
4863
+ {
4864
+ className: "agent-message-actions__menu agent-message-actions__menu--portal",
4865
+ ref: portaledMenuRef,
4866
+ role: "menu",
4867
+ style: menuPosition ? {
4868
+ left: `${menuPosition.left}px`,
4869
+ top: `${menuPosition.top}px`
4870
+ } : { visibility: "hidden" },
4871
+ children: [
4872
+ answeredLabel ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "agent-message-actions__menu-meta", children: [
4873
+ "Answered ",
4874
+ answeredLabel
4875
+ ] }) : null,
4876
+ canOpenReceipt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4877
+ "button",
4878
+ {
4879
+ type: "button",
4880
+ className: "agent-message-actions__menu-item",
4881
+ role: "menuitem",
4882
+ onClick: () => {
4883
+ setMenuOpen(false);
4884
+ onOpenReceipt?.();
4885
+ },
4886
+ children: [
4887
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SourcesIcon, {}),
4888
+ "View sources"
4889
+ ]
4890
+ }
4891
+ ) : null,
4892
+ canReadAloud ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4893
+ "button",
4894
+ {
4895
+ type: "button",
4896
+ className: "agent-message-actions__menu-item",
4897
+ role: "menuitem",
4898
+ onClick: handleReadAloud,
4899
+ children: [
4900
+ speaking ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StopIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ReadAloudIcon, {}),
4901
+ speaking ? "Stop reading" : "Read aloud"
4902
+ ]
4903
+ }
4904
+ ) : null
4905
+ ]
4906
+ }
4907
+ ) : null;
4908
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "agent-message-actions", "aria-label": "Answer actions", children: [
4909
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4910
+ "button",
4911
+ {
4912
+ type: "button",
4913
+ className: `agent-message-actions__button${copied ? " is-copied" : ""}`,
4914
+ "aria-label": copied ? "Copied" : "Copy answer",
4915
+ title: copied ? "Copied" : "Copy answer",
4916
+ disabled,
4917
+ onClick: handleCopy,
4918
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CopyIcon, {})
4919
+ }
4920
+ ),
4921
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4922
+ "button",
4923
+ {
4924
+ type: "button",
4925
+ className: `agent-message-actions__button${rating === "positive" ? " is-active" : ""}`,
4926
+ "aria-label": "Good answer",
4927
+ "aria-pressed": rating === "positive",
4928
+ title: "Good answer",
4929
+ disabled,
4930
+ onClick: () => handleFeedback("positive"),
4931
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThumbUpIcon, {})
4932
+ }
4933
+ ),
4934
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4935
+ "button",
4936
+ {
4937
+ type: "button",
4938
+ className: `agent-message-actions__button${rating === "negative" ? " is-active" : ""}`,
4939
+ "aria-label": "Bad answer",
4940
+ "aria-pressed": rating === "negative",
4941
+ title: "Bad answer",
4942
+ disabled,
4943
+ onClick: () => handleFeedback("negative"),
4944
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThumbDownIcon, {})
4945
+ }
4946
+ ),
4947
+ onRegenerate ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4948
+ "button",
4949
+ {
4950
+ type: "button",
4951
+ className: "agent-message-actions__button",
4952
+ "aria-label": "Regenerate answer",
4953
+ title: "Regenerate answer",
4954
+ disabled,
4955
+ onClick: onRegenerate,
4956
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RegenerateIcon, {})
4957
+ }
4958
+ ) : null,
4959
+ showMenu ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "agent-message-actions__more", ref: menuRef, children: [
4960
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4961
+ "button",
4962
+ {
4963
+ ref: moreButtonRef,
4964
+ type: "button",
4965
+ className: `agent-message-actions__button${menuOpen ? " is-menu-open" : ""}`,
4966
+ "aria-label": "More actions",
4967
+ "aria-haspopup": "menu",
4968
+ "aria-expanded": menuOpen,
4969
+ title: "More actions",
4970
+ disabled,
4971
+ onClick: () => setMenuOpen((open) => !open),
4972
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MoreIcon, {})
4973
+ }
4974
+ ),
4975
+ menuPortalRoot?.current && menu ? (0, import_react_dom2.createPortal)(menu, menuPortalRoot.current) : menu
4976
+ ] }) : null
4977
+ ] });
4978
+ }
4979
+
4194
4980
  // src/react/components/HumanInputCard/HumanInputCard.tsx
4195
- var import_react10 = require("react");
4981
+ var import_react13 = require("react");
4196
4982
 
4197
4983
  // src/react/components/ConfirmationCard/ConfirmationCard.tsx
4198
- var import_jsx_runtime6 = require("react/jsx-runtime");
4984
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4199
4985
  function ConfirmationCard({
4200
4986
  disabled = false,
4201
4987
  request,
@@ -4204,17 +4990,17 @@ function ConfirmationCard({
4204
4990
  const options = request.options ?? [];
4205
4991
  const heading = request.kind === "tool-approval" ? "Confirm this action" : request.prompt;
4206
4992
  const prompt = request.kind === "tool-approval" ? request.prompt : void 0;
4207
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4993
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4208
4994
  "section",
4209
4995
  {
4210
4996
  className: "confirmation-card",
4211
4997
  "aria-labelledby": `confirmation-${request.requestId}`,
4212
4998
  children: [
4213
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "confirmation-card__heading", children: [
4214
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { id: `confirmation-${request.requestId}`, children: heading }),
4215
- prompt ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: prompt }) : null
4999
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "confirmation-card__heading", children: [
5000
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { id: `confirmation-${request.requestId}`, children: heading }),
5001
+ prompt ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: prompt }) : null
4216
5002
  ] }),
4217
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "confirmation-card__actions", children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5003
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "confirmation-card__actions", children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4218
5004
  "button",
4219
5005
  {
4220
5006
  type: "button",
@@ -4234,8 +5020,8 @@ function ConfirmationCard({
4234
5020
  }
4235
5021
 
4236
5022
  // src/react/components/ToolInputCard/ToolInputCard.tsx
4237
- var import_react9 = require("react");
4238
- var import_jsx_runtime7 = require("react/jsx-runtime");
5023
+ var import_react12 = require("react");
5024
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4239
5025
  function isRecord5(value) {
4240
5026
  return value !== null && typeof value === "object" && !Array.isArray(value);
4241
5027
  }
@@ -4359,7 +5145,7 @@ function FieldDescription({
4359
5145
  field,
4360
5146
  id
4361
5147
  }) {
4362
- return field.description ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id, className: "tool-input-card__description", children: field.description }) : null;
5148
+ return field.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id, className: "tool-input-card__description", children: field.description }) : null;
4363
5149
  }
4364
5150
  function ChoiceField({
4365
5151
  field,
@@ -4378,7 +5164,7 @@ function ChoiceField({
4378
5164
  const selectedIndex = options.findIndex(
4379
5165
  (option) => valuesMatch(option.value, value)
4380
5166
  );
4381
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5167
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4382
5168
  "select",
4383
5169
  {
4384
5170
  id,
@@ -4393,13 +5179,13 @@ function ChoiceField({
4393
5179
  if (option) onChange(option.value);
4394
5180
  },
4395
5181
  children: [
4396
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", disabled: field.required, children: "Choose an option" }),
4397
- options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: index, children: option.label }, optionKey(option)))
5182
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", disabled: field.required, children: "Choose an option" }),
5183
+ options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: index, children: option.label }, optionKey(option)))
4398
5184
  ]
4399
5185
  }
4400
5186
  );
4401
5187
  }
4402
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5188
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4403
5189
  "div",
4404
5190
  {
4405
5191
  className: "tool-input-card__choices",
@@ -4410,8 +5196,8 @@ function ChoiceField({
4410
5196
  "aria-required": field.required,
4411
5197
  children: options.map((option, index) => {
4412
5198
  const checked = multiple ? selected.some((item) => valuesMatch(item, option.value)) : valuesMatch(value, option.value);
4413
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "tool-input-card__choice", children: [
4414
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5199
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "tool-input-card__choice", children: [
5200
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4415
5201
  "input",
4416
5202
  {
4417
5203
  type: multiple ? "checkbox" : "radio",
@@ -4433,7 +5219,7 @@ function ChoiceField({
4433
5219
  }
4434
5220
  }
4435
5221
  ),
4436
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: option.label })
5222
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: option.label })
4437
5223
  ] }, optionKey(option));
4438
5224
  })
4439
5225
  }
@@ -4453,9 +5239,9 @@ function ToolField({
4453
5239
  error ? `${id}-error` : ""
4454
5240
  ].filter(Boolean).join(" ");
4455
5241
  if (field.kind === "checkbox" || field.kind === "confirmation") {
4456
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "tool-input-card__field", children: [
4457
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "tool-input-card__check", htmlFor: id, children: [
4458
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5242
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-input-card__field", children: [
5243
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "tool-input-card__check", htmlFor: id, children: [
5244
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4459
5245
  "input",
4460
5246
  {
4461
5247
  id,
@@ -4468,17 +5254,17 @@ function ToolField({
4468
5254
  onChange: (event) => onChange(event.target.checked)
4469
5255
  }
4470
5256
  ),
4471
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
4472
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: field.label }),
4473
- field.description ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: `${id}-description`, children: field.description }) : null
5257
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
5258
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: field.label }),
5259
+ field.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id: `${id}-description`, children: field.description }) : null
4474
5260
  ] })
4475
5261
  ] }),
4476
- error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
5262
+ error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
4477
5263
  ] });
4478
5264
  }
4479
- const label = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { id: `${id}-label`, htmlFor: id, children: [
5265
+ const label = /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { id: `${id}-label`, htmlFor: id, children: [
4480
5266
  field.label,
4481
- field.required ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
5267
+ field.required ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
4482
5268
  ] });
4483
5269
  const common = {
4484
5270
  id,
@@ -4490,7 +5276,7 @@ function ToolField({
4490
5276
  };
4491
5277
  let control;
4492
5278
  if (field.kind === "select" || field.kind === "radio" || field.kind === "multi-select") {
4493
- control = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5279
+ control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4494
5280
  ChoiceField,
4495
5281
  {
4496
5282
  field,
@@ -4504,7 +5290,7 @@ function ToolField({
4504
5290
  }
4505
5291
  );
4506
5292
  } else if (field.kind === "textarea" || field.kind === "json") {
4507
- control = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5293
+ control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4508
5294
  "textarea",
4509
5295
  {
4510
5296
  ...common,
@@ -4518,8 +5304,8 @@ function ToolField({
4518
5304
  );
4519
5305
  } else if (field.kind === "range") {
4520
5306
  const numericValue = typeof value === "number" ? value : field.min ?? 0;
4521
- control = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "tool-input-card__range", children: [
4522
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5307
+ control = /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-input-card__range", children: [
5308
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4523
5309
  "input",
4524
5310
  {
4525
5311
  ...common,
@@ -4531,11 +5317,11 @@ function ToolField({
4531
5317
  onChange: (event) => onChange(Number(event.target.value))
4532
5318
  }
4533
5319
  ),
4534
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("output", { htmlFor: id, children: numericValue })
5320
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("output", { htmlFor: id, children: numericValue })
4535
5321
  ] });
4536
5322
  } else {
4537
5323
  const type = field.kind === "date-time" ? "datetime-local" : field.kind === "calendar" ? "date" : field.kind;
4538
- control = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5324
+ control = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4539
5325
  "input",
4540
5326
  {
4541
5327
  ...common,
@@ -4553,11 +5339,11 @@ function ToolField({
4553
5339
  }
4554
5340
  );
4555
5341
  }
4556
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "tool-input-card__field", children: [
5342
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-input-card__field", children: [
4557
5343
  label,
4558
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldDescription, { field, id: `${id}-description` }),
5344
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FieldDescription, { field, id: `${id}-description` }),
4559
5345
  control,
4560
- error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
5346
+ error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id: `${id}-error`, className: "tool-input-card__error", children: error }) : null
4561
5347
  ] });
4562
5348
  }
4563
5349
  function ToolInputCard({
@@ -4565,11 +5351,11 @@ function ToolInputCard({
4565
5351
  surface,
4566
5352
  onSubmit
4567
5353
  }) {
4568
- const [values, setValues] = (0, import_react9.useState)(
5354
+ const [values, setValues] = (0, import_react12.useState)(
4569
5355
  () => initialValues(surface)
4570
5356
  );
4571
- const [touched, setTouched] = (0, import_react9.useState)(() => /* @__PURE__ */ new Set());
4572
- const [submitted, setSubmitted] = (0, import_react9.useState)(false);
5357
+ const [touched, setTouched] = (0, import_react12.useState)(() => /* @__PURE__ */ new Set());
5358
+ const [submitted, setSubmitted] = (0, import_react12.useState)(false);
4573
5359
  const errors = Object.fromEntries(
4574
5360
  surface.fields.map((field) => [
4575
5361
  field.path,
@@ -4594,14 +5380,14 @@ function ToolInputCard({
4594
5380
  onSubmit?.(surface, result);
4595
5381
  }
4596
5382
  if (submitted) {
4597
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5383
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4598
5384
  "section",
4599
5385
  {
4600
5386
  className: "tool-input-card tool-input-card--submitted",
4601
5387
  role: "status",
4602
5388
  children: [
4603
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\u2713" }),
4604
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("strong", { children: [
5389
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "aria-hidden": "true", children: "\u2713" }),
5390
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("strong", { children: [
4605
5391
  surface.title,
4606
5392
  " submitted"
4607
5393
  ] })
@@ -4609,18 +5395,18 @@ function ToolInputCard({
4609
5395
  }
4610
5396
  );
4611
5397
  }
4612
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5398
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4613
5399
  "section",
4614
5400
  {
4615
5401
  className: "tool-input-card",
4616
5402
  "aria-labelledby": `tool-input-${surface.id}`,
4617
5403
  children: [
4618
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "tool-input-card__heading", children: [
4619
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { id: `tool-input-${surface.id}`, children: surface.title }),
4620
- surface.description ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { children: surface.description }) : null
5404
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-input-card__heading", children: [
5405
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { id: `tool-input-${surface.id}`, children: surface.title }),
5406
+ surface.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: surface.description }) : null
4621
5407
  ] }),
4622
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { noValidate: true, onSubmit: submit, children: [
4623
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "tool-input-card__fields", children: surface.fields.map((field, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5408
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { noValidate: true, onSubmit: submit, children: [
5409
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "tool-input-card__fields", children: surface.fields.map((field, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4624
5410
  ToolField,
4625
5411
  {
4626
5412
  disabled,
@@ -4633,8 +5419,8 @@ function ToolInputCard({
4633
5419
  },
4634
5420
  field.path
4635
5421
  )) }),
4636
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "tool-input-card__actions", children: [
4637
- surface.actions?.some((action) => action.id === "reset") ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5422
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-input-card__actions", children: [
5423
+ surface.actions?.some((action) => action.id === "reset") ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4638
5424
  "button",
4639
5425
  {
4640
5426
  type: "button",
@@ -4647,7 +5433,7 @@ function ToolInputCard({
4647
5433
  children: surface.actions.find((action) => action.id === "reset")?.label ?? "Clear"
4648
5434
  }
4649
5435
  ) : null,
4650
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "submit", disabled, children: surface.submitLabel ?? surface.actions?.find((action) => action.id === "submit")?.label ?? "Continue" })
5436
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "submit", disabled, children: surface.submitLabel ?? surface.actions?.find((action) => action.id === "submit")?.label ?? "Continue" })
4651
5437
  ] })
4652
5438
  ] })
4653
5439
  ]
@@ -4656,17 +5442,17 @@ function ToolInputCard({
4656
5442
  }
4657
5443
 
4658
5444
  // src/react/components/HumanInputCard/HumanInputCard.tsx
4659
- var import_jsx_runtime8 = require("react/jsx-runtime");
5445
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4660
5446
  function HumanInputCard({
4661
5447
  disabled = false,
4662
5448
  request,
4663
5449
  onRespond
4664
5450
  }) {
4665
- const [text, setText] = (0, import_react10.useState)("");
5451
+ const [text, setText] = (0, import_react13.useState)("");
4666
5452
  const options = request.options ?? [];
4667
5453
  const showText = request.display === "text" || request.allowFreeform && options.length === 0;
4668
5454
  if (request.ui) {
4669
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5455
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4670
5456
  ToolInputCard,
4671
5457
  {
4672
5458
  disabled,
@@ -4676,7 +5462,7 @@ function HumanInputCard({
4676
5462
  );
4677
5463
  }
4678
5464
  if (options.length > 0) {
4679
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5465
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4680
5466
  ConfirmationCard,
4681
5467
  {
4682
5468
  disabled,
@@ -4691,17 +5477,17 @@ function HumanInputCard({
4691
5477
  if (!value || disabled) return;
4692
5478
  onRespond?.({ requestId: request.requestId, text: value });
4693
5479
  }
4694
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5480
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4695
5481
  "section",
4696
5482
  {
4697
5483
  className: "human-input-card",
4698
5484
  "aria-labelledby": `human-input-${request.requestId}`,
4699
5485
  children: [
4700
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "human-input-card__heading", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { id: `human-input-${request.requestId}`, children: request.prompt }) }),
4701
- showText ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: submitText, children: [
4702
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `human-input-text-${request.requestId}`, children: "Response" }),
4703
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
4704
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5486
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "human-input-card__heading", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { id: `human-input-${request.requestId}`, children: request.prompt }) }),
5487
+ showText ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: submitText, children: [
5488
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { htmlFor: `human-input-text-${request.requestId}`, children: "Response" }),
5489
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
5490
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4705
5491
  "input",
4706
5492
  {
4707
5493
  id: `human-input-text-${request.requestId}`,
@@ -4710,39 +5496,39 @@ function HumanInputCard({
4710
5496
  onChange: (event) => setText(event.target.value)
4711
5497
  }
4712
5498
  ),
4713
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "submit", disabled: disabled || !text.trim(), children: "Send" })
5499
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "submit", disabled: disabled || !text.trim(), children: "Send" })
4714
5500
  ] })
4715
5501
  ] }) : null,
4716
- !showText && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "human-input-card__unavailable", role: "status", children: "This request can\u2019t be answered here." }) : null
5502
+ !showText && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "human-input-card__unavailable", role: "status", children: "This request can\u2019t be answered here." }) : null
4717
5503
  ]
4718
5504
  }
4719
5505
  );
4720
5506
  }
4721
5507
 
4722
5508
  // src/react/components/CollectionResultCard/CollectionResultCard.tsx
4723
- var import_jsx_runtime9 = require("react/jsx-runtime");
5509
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4724
5510
  function CollectionResultCard({
4725
5511
  result
4726
5512
  }) {
4727
5513
  const empty = result.items.length === 0;
4728
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
5514
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
4729
5515
  "section",
4730
5516
  {
4731
5517
  className: `collection-result-card tool-result-card tool-result-card--${result.status}`,
4732
5518
  "aria-label": result.title,
4733
5519
  children: [
4734
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "tool-result-card__heading", children: [
4735
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4736
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: result.title })
5520
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "tool-result-card__heading", children: [
5521
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5522
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { children: result.title })
4737
5523
  ] }),
4738
- empty ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "collection-result-card__empty", children: "No matching record for the email you shared." }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { className: "collection-result-card__list", children: result.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("li", { children: [
4739
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "collection-result-card__item-title", children: item.title }),
4740
- item.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: item.description }) : null,
4741
- item.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dl", { children: item.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
4742
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dt", { children: detail.label }),
4743
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("dd", { children: detail.value })
5524
+ empty ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "collection-result-card__empty", children: "No matching record for the email you shared." }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "collection-result-card__list", children: result.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("li", { children: [
5525
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "collection-result-card__item-title", children: item.title }),
5526
+ item.description ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { children: item.description }) : null,
5527
+ item.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dl", { children: item.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
5528
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { children: detail.label }),
5529
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { children: detail.value })
4744
5530
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4745
- item.href ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { href: item.href, target: "_blank", rel: "noreferrer", children: "Open record" }) : null
5531
+ item.href ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: item.href, target: "_blank", rel: "noreferrer", children: "Open record" }) : null
4746
5532
  ] }, item.title)) })
4747
5533
  ]
4748
5534
  }
@@ -4750,26 +5536,26 @@ function CollectionResultCard({
4750
5536
  }
4751
5537
 
4752
5538
  // src/react/components/EntityResultCard/EntityResultCard.tsx
4753
- var import_jsx_runtime10 = require("react/jsx-runtime");
5539
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4754
5540
  function EntityResultCard({
4755
5541
  result
4756
5542
  }) {
4757
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
5543
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4758
5544
  "section",
4759
5545
  {
4760
5546
  className: `entity-result-card tool-result-card tool-result-card--${result.status}`,
4761
5547
  "aria-label": result.title,
4762
5548
  children: [
4763
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "tool-result-card__heading", children: [
4764
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4765
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: result.title })
5549
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "tool-result-card__heading", children: [
5550
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5551
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: result.title })
4766
5552
  ] }),
4767
- result.description ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: result.description }) : null,
4768
- result.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dl", { children: result.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
4769
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { children: detail.label }),
4770
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { children: detail.value })
5553
+ result.description ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { children: result.description }) : null,
5554
+ result.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dl", { children: result.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
5555
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dt", { children: detail.label }),
5556
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dd", { children: detail.value })
4771
5557
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4772
- result.links?.length ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
5558
+ result.links?.length ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4773
5559
  "a",
4774
5560
  {
4775
5561
  href: link.href,
@@ -4785,24 +5571,24 @@ function EntityResultCard({
4785
5571
  }
4786
5572
 
4787
5573
  // src/react/components/SignatureResultCard/SignatureResultCard.tsx
4788
- var import_jsx_runtime11 = require("react/jsx-runtime");
5574
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4789
5575
  function SignatureResultCard({
4790
5576
  result
4791
5577
  }) {
4792
5578
  const primaryLink = result.links?.[0];
4793
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
5579
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4794
5580
  "section",
4795
5581
  {
4796
5582
  className: `signature-result-card tool-result-card tool-result-card--${result.status}`,
4797
5583
  "aria-label": result.title,
4798
5584
  children: [
4799
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "tool-result-card__heading", children: [
4800
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4801
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { children: result.title })
5585
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "tool-result-card__heading", children: [
5586
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5587
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: result.title })
4802
5588
  ] }),
4803
- result.statusLabel ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "signature-result-card__badge", children: result.statusLabel }) : null,
4804
- result.description ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { children: result.description }) : null,
4805
- primaryLink ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5589
+ result.statusLabel ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "signature-result-card__badge", children: result.statusLabel }) : null,
5590
+ result.description ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: result.description }) : null,
5591
+ primaryLink ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4806
5592
  "a",
4807
5593
  {
4808
5594
  className: "signature-result-card__cta",
@@ -4818,26 +5604,26 @@ function SignatureResultCard({
4818
5604
  }
4819
5605
 
4820
5606
  // src/react/components/ToolResultCard/ToolResultCard.tsx
4821
- var import_jsx_runtime12 = require("react/jsx-runtime");
5607
+ var import_jsx_runtime14 = require("react/jsx-runtime");
4822
5608
  function ToolResultCard({
4823
5609
  result
4824
5610
  }) {
4825
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5611
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4826
5612
  "section",
4827
5613
  {
4828
5614
  className: `tool-result-card tool-result-card--${result.status}`,
4829
5615
  "aria-label": result.title,
4830
5616
  children: [
4831
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "tool-result-card__heading", children: [
4832
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
4833
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: result.title })
5617
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "tool-result-card__heading", children: [
5618
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "tool-result-card__status", "aria-hidden": "true" }),
5619
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: result.title })
4834
5620
  ] }),
4835
- result.description ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { children: result.description }) : null,
4836
- result.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dl", { children: result.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
4837
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dt", { children: detail.label }),
4838
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("dd", { children: detail.value })
5621
+ result.description ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: result.description }) : null,
5622
+ result.details?.length ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("dl", { children: result.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
5623
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("dt", { children: detail.label }),
5624
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("dd", { children: detail.value })
4839
5625
  ] }, `${detail.label}:${detail.value}`)) }) : null,
4840
- result.links?.length ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5626
+ result.links?.length ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "tool-result-card__links", children: result.links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4841
5627
  "a",
4842
5628
  {
4843
5629
  href: link.href,
@@ -4853,14 +5639,14 @@ function ToolResultCard({
4853
5639
  }
4854
5640
 
4855
5641
  // src/react/components/VisitorToolResultView/VisitorToolResultView.tsx
4856
- var import_jsx_runtime13 = require("react/jsx-runtime");
5642
+ var import_jsx_runtime15 = require("react/jsx-runtime");
4857
5643
  function VisitorToolResultView({
4858
5644
  disabled = false,
4859
5645
  onToolInput,
4860
5646
  result
4861
5647
  }) {
4862
5648
  if (result.kind === "input") {
4863
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5649
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4864
5650
  ToolInputCard,
4865
5651
  {
4866
5652
  disabled,
@@ -4870,16 +5656,16 @@ function VisitorToolResultView({
4870
5656
  );
4871
5657
  }
4872
5658
  if (result.kind === "entity") {
4873
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EntityResultCard, { result });
5659
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(EntityResultCard, { result });
4874
5660
  }
4875
5661
  if (result.kind === "collection") {
4876
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CollectionResultCard, { result });
5662
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CollectionResultCard, { result });
4877
5663
  }
4878
5664
  if (result.kind === "signature") {
4879
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SignatureResultCard, { result });
5665
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SignatureResultCard, { result });
4880
5666
  }
4881
5667
  if (result.kind === "summary") {
4882
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ToolResultCard, { result });
5668
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ToolResultCard, { result });
4883
5669
  }
4884
5670
  return null;
4885
5671
  }
@@ -4888,9 +5674,9 @@ function isRenderableVisitorToolResult(result) {
4888
5674
  }
4889
5675
 
4890
5676
  // src/react/components/AgentRail/AgentRail.tsx
4891
- var import_jsx_runtime14 = require("react/jsx-runtime");
5677
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4892
5678
  function MinimizeIcon() {
4893
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5679
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4894
5680
  "path",
4895
5681
  {
4896
5682
  d: "M3.5 8h9",
@@ -4900,8 +5686,8 @@ function MinimizeIcon() {
4900
5686
  }
4901
5687
  ) });
4902
5688
  }
4903
- function CloseIcon() {
4904
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5689
+ function CloseIcon2() {
5690
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4905
5691
  "path",
4906
5692
  {
4907
5693
  d: "M4 4l8 8M12 4l-8 8",
@@ -4912,7 +5698,7 @@ function CloseIcon() {
4912
5698
  ) });
4913
5699
  }
4914
5700
  function NewChatIcon() {
4915
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5701
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4916
5702
  "path",
4917
5703
  {
4918
5704
  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",
@@ -4924,7 +5710,7 @@ function NewChatIcon() {
4924
5710
  ) });
4925
5711
  }
4926
5712
  function ExpandIcon() {
4927
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5713
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4928
5714
  "path",
4929
5715
  {
4930
5716
  d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
@@ -4936,7 +5722,7 @@ function ExpandIcon() {
4936
5722
  ) });
4937
5723
  }
4938
5724
  function RestoreIcon() {
4939
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5725
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4940
5726
  "path",
4941
5727
  {
4942
5728
  d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
@@ -4947,6 +5733,19 @@ function RestoreIcon() {
4947
5733
  }
4948
5734
  ) });
4949
5735
  }
5736
+ function ChevronDownIcon() {
5737
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5738
+ "path",
5739
+ {
5740
+ d: "M4 6.5l4 4 4-4",
5741
+ stroke: "currentColor",
5742
+ strokeWidth: "1.6",
5743
+ strokeLinecap: "round",
5744
+ strokeLinejoin: "round"
5745
+ }
5746
+ ) });
5747
+ }
5748
+ var DEFAULT_DISCLAIMER_LABEL = "Agent can make mistakes. Check important info.";
4950
5749
  function AgentRail({
4951
5750
  state,
4952
5751
  theme,
@@ -4954,6 +5753,9 @@ function AgentRail({
4954
5753
  brandLabel = "",
4955
5754
  brandLogoUrl,
4956
5755
  poweredByLabel = "Powered by Webless",
5756
+ disclaimerLabel,
5757
+ answerReceipt = false,
5758
+ readAloud = false,
4957
5759
  composerPlaceholder = "Ask anything\u2026",
4958
5760
  mobileFullscreen = false,
4959
5761
  expanded = false,
@@ -4962,16 +5764,26 @@ function AgentRail({
4962
5764
  onExpandToggle,
4963
5765
  onReset,
4964
5766
  onRetry,
5767
+ onRegenerate,
5768
+ onFeedback,
4965
5769
  onSubmit,
4966
5770
  onFollowUpSelect,
4967
5771
  onBook,
4968
5772
  onInputResponse,
4969
5773
  onToolInput
4970
5774
  }) {
4971
- const transcriptRef = (0, import_react11.useRef)(null);
5775
+ const railRef = (0, import_react14.useRef)(null);
5776
+ const overlayRef = (0, import_react14.useRef)(null);
5777
+ const transcriptRef = (0, import_react14.useRef)(null);
5778
+ const pinnedToBottomRef = (0, import_react14.useRef)(true);
5779
+ const smoothScrollToLatestRef = (0, import_react14.useRef)(false);
5780
+ const lockedTranscriptScrollTopRef = (0, import_react14.useRef)(null);
5781
+ const [showJumpToLatest, setShowJumpToLatest] = (0, import_react14.useState)(false);
5782
+ const [receiptOpen, setReceiptOpen] = (0, import_react14.useState)(false);
4972
5783
  const resolvedBrandLabel = brandLabel.trim();
4973
5784
  const resolvedBrandLogoUrl = brandLogoUrl?.trim();
4974
- const [failedLogoUrl, setFailedLogoUrl] = (0, import_react11.useState)(null);
5785
+ const resolvedDisclaimerLabel = disclaimerLabel === void 0 ? DEFAULT_DISCLAIMER_LABEL : disclaimerLabel;
5786
+ const [failedLogoUrl, setFailedLogoUrl] = (0, import_react14.useState)(null);
4975
5787
  const showBrandLogo = Boolean(resolvedBrandLogoUrl) && failedLogoUrl !== resolvedBrandLogoUrl;
4976
5788
  const resolvedColorScheme = useAgentColorScheme(colorScheme);
4977
5789
  const brandedTheme = { ...defaultAgentRailTheme, ...theme };
@@ -5022,10 +5834,15 @@ function AgentRail({
5022
5834
  );
5023
5835
  const activeVisitorToolInput = [...visitorToolResults].reverse().find((result) => result.kind === "input");
5024
5836
  const visibleVisitorToolResults = activeVisitorToolInput ? [activeVisitorToolInput] : visitorToolResults;
5025
- const showActivity = state.toolSteps.length > 0 && visibleVisitorToolResults.length === 0 && pendingInputRequests.length === 0 && !state.pendingOffer;
5837
+ const activityActive = state.toolSteps.some((step) => step.state === "active");
5838
+ const showActivity = state.toolSteps.length > 0 && visibleVisitorToolResults.length === 0 && pendingInputRequests.length === 0 && !state.pendingOffer && activityActive;
5026
5839
  const hasVisitorMessages2 = state.messages.some(
5027
5840
  (message) => message.role === "visitor"
5028
5841
  );
5842
+ const hasAgentResponseAfterVisitor = state.messages.some(
5843
+ (message) => message.role === "agent" && message.id !== "greeting"
5844
+ );
5845
+ const showDisclaimerLabel = Boolean(resolvedDisclaimerLabel) && hasVisitorMessages2 && (hasAgentResponseAfterVisitor || state.phase === "streaming" && Boolean(state.streamingText));
5029
5846
  const showIdleFollowUps = !hasVisitorMessages2 && state.followUps.length > 0;
5030
5847
  const greeting = state.messages.find(
5031
5848
  (message) => message.role === "agent" && message.id === "greeting"
@@ -5047,6 +5864,7 @@ function AgentRail({
5047
5864
  }
5048
5865
  }
5049
5866
  const lastIsAgent = lastMessage?.role === "agent";
5867
+ const showMessageActions = state.phase === "complete" && lastIsAgent && hasVisitorMessages2;
5050
5868
  const streamingMessage = state.phase === "streaming" && state.streamingText && !lastIsAgent ? {
5051
5869
  createdAt: 0,
5052
5870
  id: "streaming-response",
@@ -5073,10 +5891,36 @@ function AgentRail({
5073
5891
  hasPendingConfirmation,
5074
5892
  enabled: lastIsAgent && !isBusy
5075
5893
  });
5076
- (0, import_react11.useEffect)(() => {
5894
+ const receiptSteps = answerReceipt && state.toolSteps.length > 0 ? state.toolSteps : void 0;
5895
+ (0, import_react14.useEffect)(() => {
5896
+ if (state.phase !== "complete") {
5897
+ setReceiptOpen(false);
5898
+ }
5899
+ }, [state.phase]);
5900
+ function handleSubmit(message) {
5901
+ setReceiptOpen(false);
5902
+ onSubmit?.(message);
5903
+ }
5904
+ function handleRegenerate() {
5905
+ setReceiptOpen(false);
5906
+ onRegenerate?.();
5907
+ }
5908
+ function handleReset() {
5909
+ setReceiptOpen(false);
5910
+ onReset?.();
5911
+ }
5912
+ function handleFollowUpSelect(label) {
5913
+ setReceiptOpen(false);
5914
+ onFollowUpSelect?.(label);
5915
+ }
5916
+ (0, import_react14.useEffect)(() => {
5077
5917
  const node = transcriptRef.current;
5078
5918
  if (!node) return;
5079
- node.scrollTop = node.scrollHeight;
5919
+ const lastMessage2 = state.messages.at(-1);
5920
+ const visitorJustSent = lastMessage2?.role === "visitor";
5921
+ if (pinnedToBottomRef.current || visitorJustSent) {
5922
+ node.scrollTop = node.scrollHeight;
5923
+ }
5080
5924
  }, [
5081
5925
  state.messages,
5082
5926
  state.toolSteps,
@@ -5084,10 +5928,75 @@ function AgentRail({
5084
5928
  state.followUps,
5085
5929
  state.journey
5086
5930
  ]);
5087
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5931
+ (0, import_react14.useEffect)(() => {
5932
+ const node = transcriptRef.current;
5933
+ if (!node) return;
5934
+ const handleScroll = () => {
5935
+ if (node.clientHeight === 0) return;
5936
+ const distanceFromBottom = node.scrollHeight - node.scrollTop - node.clientHeight;
5937
+ const pinned = distanceFromBottom < 48 || smoothScrollToLatestRef.current;
5938
+ pinnedToBottomRef.current = pinned;
5939
+ setShowJumpToLatest(!pinned);
5940
+ };
5941
+ node.addEventListener("scroll", handleScroll, { passive: true });
5942
+ handleScroll();
5943
+ return () => node.removeEventListener("scroll", handleScroll);
5944
+ }, []);
5945
+ (0, import_react14.useEffect)(() => {
5946
+ const node = transcriptRef.current;
5947
+ if (!node) return;
5948
+ const observer = new ResizeObserver(() => {
5949
+ if (node.clientHeight === 0) return;
5950
+ if (pinnedToBottomRef.current) {
5951
+ node.scrollTo({ top: node.scrollHeight, behavior: "instant" });
5952
+ }
5953
+ });
5954
+ observer.observe(node);
5955
+ return () => observer.disconnect();
5956
+ }, []);
5957
+ (0, import_react14.useEffect)(() => {
5958
+ if (!receiptOpen) {
5959
+ lockedTranscriptScrollTopRef.current = null;
5960
+ return;
5961
+ }
5962
+ const node = transcriptRef.current;
5963
+ if (!node || lockedTranscriptScrollTopRef.current === null) return;
5964
+ node.scrollTop = lockedTranscriptScrollTopRef.current;
5965
+ }, [receiptOpen]);
5966
+ function openReceipt() {
5967
+ const node = transcriptRef.current;
5968
+ lockedTranscriptScrollTopRef.current = node?.scrollTop ?? null;
5969
+ setReceiptOpen(true);
5970
+ }
5971
+ function scrollToLatest() {
5972
+ const node = transcriptRef.current;
5973
+ if (!node) return;
5974
+ pinnedToBottomRef.current = true;
5975
+ setShowJumpToLatest(false);
5976
+ const reduceMotion = window.matchMedia(
5977
+ "(prefers-reduced-motion: reduce)"
5978
+ ).matches;
5979
+ if (reduceMotion) {
5980
+ node.scrollTo({ top: node.scrollHeight, behavior: "instant" });
5981
+ return;
5982
+ }
5983
+ smoothScrollToLatestRef.current = true;
5984
+ const settle = () => {
5985
+ smoothScrollToLatestRef.current = false;
5986
+ const distanceFromBottom = node.scrollHeight - node.scrollTop - node.clientHeight;
5987
+ const pinned = distanceFromBottom < 48;
5988
+ pinnedToBottomRef.current = pinned;
5989
+ setShowJumpToLatest(!pinned);
5990
+ };
5991
+ node.addEventListener("scrollend", settle, { once: true });
5992
+ window.setTimeout(settle, 900);
5993
+ node.scrollTo({ top: node.scrollHeight, behavior: "smooth" });
5994
+ }
5995
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5088
5996
  "aside",
5089
5997
  {
5090
- className: `agent-rail not-typeset${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
5998
+ ref: railRef,
5999
+ className: `agent-rail not-typeset${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}${receiptOpen ? " agent-rail--receipt-open" : ""}`,
5091
6000
  "data-not-typeset": "",
5092
6001
  "data-color-scheme": resolvedColorScheme,
5093
6002
  spellCheck: false,
@@ -5097,193 +6006,234 @@ function AgentRail({
5097
6006
  autoFocus: mobileFullscreen || expanded,
5098
6007
  role: mobileFullscreen || expanded ? "dialog" : void 0,
5099
6008
  tabIndex: mobileFullscreen || expanded ? -1 : void 0,
5100
- children: [
5101
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("header", { className: "agent-rail__header", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "agent-rail__brand-row", children: [
5102
- onCollapse ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5103
- "button",
5104
- {
5105
- type: "button",
5106
- className: "agent-rail__collapse",
5107
- "aria-label": "Collapse assist",
5108
- onClick: onCollapse,
5109
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MinimizeIcon, {})
5110
- }
5111
- ) : onClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5112
- "button",
5113
- {
5114
- type: "button",
5115
- className: "agent-rail__close",
5116
- "aria-label": "Close agent",
5117
- onClick: onClose,
5118
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CloseIcon, {})
5119
- }
5120
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
5121
- resolvedBrandLabel || showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "agent-rail__identity", children: [
5122
- showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5123
- "img",
5124
- {
5125
- className: "agent-rail__brand-logo",
5126
- src: resolvedBrandLogoUrl,
5127
- alt: "",
5128
- onError: () => {
5129
- setFailedLogoUrl(resolvedBrandLogoUrl ?? null);
5130
- }
5131
- }
5132
- ) }) : null,
5133
- resolvedBrandLabel ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "agent-rail__brand-label", children: resolvedBrandLabel }) : null
5134
- ] }) : null,
5135
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "agent-rail__actions", children: [
5136
- onReset ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5137
- "button",
5138
- {
5139
- type: "button",
5140
- className: "agent-rail__new-chat",
5141
- "aria-label": "Start a new conversation",
5142
- disabled: !hasVisitorMessages2,
5143
- onClick: onReset,
5144
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NewChatIcon, {})
5145
- }
5146
- ) : null,
5147
- onExpandToggle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5148
- "button",
5149
- {
5150
- type: "button",
5151
- className: "agent-rail__expand",
5152
- "aria-label": expanded ? "Exit full screen" : "Open full screen",
5153
- onClick: onExpandToggle,
5154
- children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RestoreIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ExpandIcon, {})
5155
- }
5156
- ) : null
5157
- ] })
5158
- ] }) }),
5159
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "agent-rail__thread", children: [
5160
- !hasVisitorMessages2 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
5161
- greeting?.role === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5162
- MessageBubble,
5163
- {
5164
- message: greeting,
5165
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5166
- onBook
5167
- }
5168
- ) : null,
5169
- showIdleFollowUps ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5170
- FollowUpChips,
5171
- {
5172
- suggestions: state.followUps,
5173
- disabled: isBusy,
5174
- label: "Start here",
5175
- onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
5176
- }
5177
- ) }) : null,
5178
- showActivity ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5179
- AgentActivityBubble,
6009
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6010
+ AgentRailOverlayContext.Provider,
6011
+ {
6012
+ value: { railRef, overlayRef },
6013
+ children: [
6014
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "agent-rail__surface", inert: receiptOpen || void 0, children: [
6015
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("header", { className: "agent-rail__header", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "agent-rail__brand-row", children: [
6016
+ onCollapse ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6017
+ "button",
6018
+ {
6019
+ type: "button",
6020
+ className: "agent-rail__collapse",
6021
+ "aria-label": "Collapse assist",
6022
+ onClick: onCollapse,
6023
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MinimizeIcon, {})
6024
+ }
6025
+ ) : onClose ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6026
+ "button",
6027
+ {
6028
+ type: "button",
6029
+ className: "agent-rail__close",
6030
+ "aria-label": "Close agent",
6031
+ onClick: onClose,
6032
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CloseIcon2, {})
6033
+ }
6034
+ ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
6035
+ resolvedBrandLabel || showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "agent-rail__identity", children: [
6036
+ showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6037
+ "img",
6038
+ {
6039
+ className: "agent-rail__brand-logo",
6040
+ src: resolvedBrandLogoUrl,
6041
+ alt: "",
6042
+ onError: () => {
6043
+ setFailedLogoUrl(resolvedBrandLogoUrl ?? null);
6044
+ }
6045
+ }
6046
+ ) }) : null,
6047
+ resolvedBrandLabel ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "agent-rail__brand-label", children: resolvedBrandLabel }) : null
6048
+ ] }) : null,
6049
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "agent-rail__actions", children: [
6050
+ onReset ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6051
+ "button",
6052
+ {
6053
+ type: "button",
6054
+ className: "agent-rail__new-chat",
6055
+ "aria-label": "Start a new conversation",
6056
+ disabled: !hasVisitorMessages2,
6057
+ onClick: handleReset,
6058
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(NewChatIcon, {})
6059
+ }
6060
+ ) : null,
6061
+ onExpandToggle ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6062
+ "button",
6063
+ {
6064
+ type: "button",
6065
+ className: "agent-rail__expand",
6066
+ "aria-label": expanded ? "Exit full screen" : "Open full screen",
6067
+ onClick: onExpandToggle,
6068
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RestoreIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ExpandIcon, {})
6069
+ }
6070
+ ) : null
6071
+ ] })
6072
+ ] }) }),
6073
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "agent-rail__thread", children: [
6074
+ !hasVisitorMessages2 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
6075
+ greeting?.role === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6076
+ MessageBubble,
6077
+ {
6078
+ message: greeting,
6079
+ bookingDisabled: isBusy,
6080
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6081
+ onBook
6082
+ }
6083
+ ) : null,
6084
+ showIdleFollowUps ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6085
+ FollowUpChips,
6086
+ {
6087
+ suggestions: state.followUps,
6088
+ disabled: isBusy,
6089
+ label: "Start here",
6090
+ onSelect: (suggestion) => handleFollowUpSelect(suggestion.label)
6091
+ }
6092
+ ) }) : null,
6093
+ showActivity ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6094
+ AgentActivityBubble,
6095
+ {
6096
+ brandLabel: resolvedBrandLabel,
6097
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6098
+ failed: state.phase === "error",
6099
+ steps: state.toolSteps
6100
+ }
6101
+ ) : null,
6102
+ visibleVisitorToolResults.map((result) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6103
+ VisitorToolResultView,
6104
+ {
6105
+ result,
6106
+ disabled: semanticSurfaceDisabled,
6107
+ onToolInput
6108
+ },
6109
+ result.id
6110
+ )),
6111
+ pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6112
+ HumanInputCard,
6113
+ {
6114
+ request,
6115
+ onRespond: onInputResponse
6116
+ },
6117
+ request.requestId
6118
+ ))
6119
+ ] }) : null,
6120
+ visibleMessages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "agent-rail__turn-block", children: [
6121
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6122
+ MessageBubble,
6123
+ {
6124
+ message,
6125
+ bookingDisabled: isBusy,
6126
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6127
+ offer: index === lastAgentIndex ? state.pendingOffer : void 0,
6128
+ onBook
6129
+ }
6130
+ ),
6131
+ index === lastAgentIndex && showMessageActions && message.role === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6132
+ MessageActions,
6133
+ {
6134
+ answeredAt: message.createdAt,
6135
+ copyText: hideToolCardFences(message.text).trim() || message.text,
6136
+ readAloud,
6137
+ receiptSteps,
6138
+ onOpenReceipt: receiptSteps ? openReceipt : void 0,
6139
+ onRegenerate: onRegenerate ? handleRegenerate : void 0,
6140
+ onFeedback: onFeedback ? (rating) => onFeedback(rating, message) : void 0
6141
+ }
6142
+ ) : null,
6143
+ index === lastVisitorIndex ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
6144
+ showActivity ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6145
+ AgentActivityBubble,
6146
+ {
6147
+ brandLabel: resolvedBrandLabel,
6148
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6149
+ failed: state.phase === "error",
6150
+ steps: state.toolSteps
6151
+ }
6152
+ ) : null,
6153
+ visibleVisitorToolResults.map((result) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6154
+ VisitorToolResultView,
6155
+ {
6156
+ result,
6157
+ disabled: semanticSurfaceDisabled,
6158
+ onToolInput
6159
+ },
6160
+ result.id
6161
+ )),
6162
+ pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6163
+ HumanInputCard,
6164
+ {
6165
+ request,
6166
+ onRespond: onInputResponse
6167
+ },
6168
+ request.requestId
6169
+ ))
6170
+ ] }) : null
6171
+ ] }, message.id)),
6172
+ streamingMessage ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6173
+ MessageBubble,
6174
+ {
6175
+ message: streamingMessage,
6176
+ bookingDisabled: isBusy,
6177
+ brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
6178
+ offer: state.pendingOffer,
6179
+ onBook
6180
+ }
6181
+ ) : null,
6182
+ waitingForBooking ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BookingCardLoader, {}) : null,
6183
+ state.error ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { className: "agent-rail__error", role: "alert", children: [
6184
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
6185
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "Something went wrong" }),
6186
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: state.error })
6187
+ ] }),
6188
+ onRetry ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
6189
+ ] }) : null
6190
+ ] }) }),
6191
+ showDisclaimerLabel ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "agent-rail__disclaimer", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: resolvedDisclaimerLabel }) }) : null,
6192
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "agent-rail__composer-wrap", children: [
6193
+ showJumpToLatest ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6194
+ "button",
6195
+ {
6196
+ type: "button",
6197
+ className: "agent-rail__jump-to-latest",
6198
+ "aria-label": "Jump to the latest message",
6199
+ title: "Jump to the latest message",
6200
+ onClick: scrollToLatest,
6201
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChevronDownIcon, {})
6202
+ }
6203
+ ) : null,
6204
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6205
+ Composer,
6206
+ {
6207
+ variant: expanded || mobileFullscreen ? "dock" : "default",
6208
+ disabled: isBusy,
6209
+ form: composerForm,
6210
+ placeholder: composerPlaceholder,
6211
+ onSubmit: handleSubmit
6212
+ }
6213
+ ),
6214
+ poweredByLabel ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "agent-rail__footer", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: poweredByLabel }) }) }) : null
6215
+ ] })
6216
+ ] }),
6217
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: overlayRef, className: "agent-rail__overlay" }),
6218
+ receiptOpen && receiptSteps ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6219
+ AnswerReceiptDialog,
5180
6220
  {
5181
6221
  brandLabel: resolvedBrandLabel,
5182
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5183
- failed: state.phase === "error",
5184
- steps: state.toolSteps
6222
+ onClose: () => setReceiptOpen(false),
6223
+ steps: receiptSteps
5185
6224
  }
5186
- ) : null,
5187
- visibleVisitorToolResults.map((result) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5188
- VisitorToolResultView,
5189
- {
5190
- result,
5191
- disabled: semanticSurfaceDisabled,
5192
- onToolInput
5193
- },
5194
- result.id
5195
- )),
5196
- pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5197
- HumanInputCard,
5198
- {
5199
- request,
5200
- onRespond: onInputResponse
5201
- },
5202
- request.requestId
5203
- ))
5204
- ] }) : null,
5205
- visibleMessages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "agent-rail__turn-block", children: [
5206
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5207
- MessageBubble,
5208
- {
5209
- message,
5210
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5211
- offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5212
- onBook
5213
- }
5214
- ),
5215
- index === lastVisitorIndex ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
5216
- showActivity ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5217
- AgentActivityBubble,
5218
- {
5219
- brandLabel: resolvedBrandLabel,
5220
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5221
- failed: state.phase === "error",
5222
- steps: state.toolSteps
5223
- }
5224
- ) : null,
5225
- visibleVisitorToolResults.map((result) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5226
- VisitorToolResultView,
5227
- {
5228
- result,
5229
- disabled: semanticSurfaceDisabled,
5230
- onToolInput
5231
- },
5232
- result.id
5233
- )),
5234
- pendingInputRequests.slice(0, 1).map((request) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5235
- HumanInputCard,
5236
- {
5237
- request,
5238
- onRespond: onInputResponse
5239
- },
5240
- request.requestId
5241
- ))
5242
- ] }) : null
5243
- ] }, message.id)),
5244
- streamingMessage ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5245
- MessageBubble,
5246
- {
5247
- message: streamingMessage,
5248
- brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5249
- offer: state.pendingOffer,
5250
- onBook
5251
- }
5252
- ) : null,
5253
- waitingForBooking ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(BookingCardLoader, {}) : null,
5254
- state.error ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { className: "agent-rail__error", role: "alert", children: [
5255
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
5256
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: "Something went wrong" }),
5257
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: state.error })
5258
- ] }),
5259
- onRetry ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
5260
- ] }) : null
5261
- ] }) }),
5262
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "agent-rail__composer-wrap", children: [
5263
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5264
- Composer,
5265
- {
5266
- variant: expanded || mobileFullscreen ? "dock" : "default",
5267
- disabled: isBusy,
5268
- form: composerForm,
5269
- placeholder: composerPlaceholder,
5270
- onSubmit
5271
- }
5272
- ),
5273
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "agent-rail__footer", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
5274
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "AI can make mistakes. Check important info." }),
5275
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: poweredByLabel })
5276
- ] }) })
5277
- ] })
5278
- ]
6225
+ ) : null
6226
+ ]
6227
+ }
6228
+ )
5279
6229
  }
5280
6230
  );
5281
6231
  }
5282
6232
 
5283
6233
  // src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
5284
- var import_jsx_runtime15 = require("react/jsx-runtime");
6234
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5285
6235
  function SparklesIcon() {
5286
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
6236
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5287
6237
  "svg",
5288
6238
  {
5289
6239
  className: "assist-edge-tab__sparkles",
@@ -5291,21 +6241,21 @@ function SparklesIcon() {
5291
6241
  fill: "none",
5292
6242
  "aria-hidden": "true",
5293
6243
  children: [
5294
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6244
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5295
6245
  "path",
5296
6246
  {
5297
6247
  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",
5298
6248
  fill: "currentColor"
5299
6249
  }
5300
6250
  ),
5301
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6251
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5302
6252
  "path",
5303
6253
  {
5304
6254
  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",
5305
6255
  fill: "currentColor"
5306
6256
  }
5307
6257
  ),
5308
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6258
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5309
6259
  "path",
5310
6260
  {
5311
6261
  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",
@@ -5319,7 +6269,7 @@ function SparklesIcon() {
5319
6269
  function TabMarkIcon({ customIconUrl }) {
5320
6270
  const url = customIconUrl?.trim();
5321
6271
  if (url) {
5322
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6272
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5323
6273
  "img",
5324
6274
  {
5325
6275
  alt: "",
@@ -5329,10 +6279,10 @@ function TabMarkIcon({ customIconUrl }) {
5329
6279
  }
5330
6280
  );
5331
6281
  }
5332
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SparklesIcon, {});
6282
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SparklesIcon, {});
5333
6283
  }
5334
6284
  function ChevronLeftIcon() {
5335
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6285
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5336
6286
  "path",
5337
6287
  {
5338
6288
  d: "M10 4L6 8l4 4",
@@ -5343,8 +6293,8 @@ function ChevronLeftIcon() {
5343
6293
  }
5344
6294
  ) });
5345
6295
  }
5346
- function ChevronDownIcon() {
5347
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6296
+ function ChevronDownIcon2() {
6297
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5348
6298
  "path",
5349
6299
  {
5350
6300
  d: "M4 6l4 4 4-4",
@@ -5356,7 +6306,7 @@ function ChevronDownIcon() {
5356
6306
  ) });
5357
6307
  }
5358
6308
  function DragDots() {
5359
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("i", {}, index)) });
6309
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("i", {}, index)) });
5360
6310
  }
5361
6311
  var VARIANT_COPY = {
5362
6312
  outline: { label: "Ask anything", aria: "Ask anything" },
@@ -5402,7 +6352,7 @@ function AssistEdgeTab({
5402
6352
  ...resolvedTextColor ? { "--as-text": resolvedTextColor } : {},
5403
6353
  colorScheme: resolvedColorScheme
5404
6354
  };
5405
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
6355
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5406
6356
  "button",
5407
6357
  {
5408
6358
  type: "button",
@@ -5414,15 +6364,15 @@ function AssistEdgeTab({
5414
6364
  tabIndex: visible ? 0 : -1,
5415
6365
  onClick: onOpen,
5416
6366
  children: [
5417
- mobile ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
5418
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
6367
+ mobile ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
6368
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5419
6369
  "span",
5420
6370
  {
5421
6371
  className: "assist-edge-tab__mark assist-edge-tab__mark--mobile",
5422
6372
  "aria-hidden": "true",
5423
6373
  children: [
5424
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TabMarkIcon, { customIconUrl }),
5425
- showLogo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6374
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TabMarkIcon, { customIconUrl }),
6375
+ showLogo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5426
6376
  "img",
5427
6377
  {
5428
6378
  className: "assist-edge-tab__logo",
@@ -5436,11 +6386,11 @@ function AssistEdgeTab({
5436
6386
  ]
5437
6387
  }
5438
6388
  ),
5439
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel })
5440
- ] }) : variant === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
5441
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
5442
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TabMarkIcon, { customIconUrl }),
5443
- showLogo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6389
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel })
6390
+ ] }) : variant === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
6391
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6392
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TabMarkIcon, { customIconUrl }),
6393
+ showLogo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5444
6394
  "img",
5445
6395
  {
5446
6396
  className: "assist-edge-tab__logo",
@@ -5452,18 +6402,18 @@ function AssistEdgeTab({
5452
6402
  }
5453
6403
  ) : null
5454
6404
  ] }),
5455
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5456
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronDownIcon, {})
6405
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6406
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ChevronDownIcon2, {})
5457
6407
  ] }) : null,
5458
- variant === "ask" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
5459
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronLeftIcon, {}),
5460
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5461
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DragDots, {})
6408
+ variant === "ask" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
6409
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ChevronLeftIcon, {}),
6410
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6411
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DragDots, {})
5462
6412
  ] }) : null,
5463
- variant === "fill" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
5464
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
5465
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TabMarkIcon, { customIconUrl }),
5466
- showLogo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6413
+ variant === "fill" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
6414
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6415
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TabMarkIcon, { customIconUrl }),
6416
+ showLogo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5467
6417
  "img",
5468
6418
  {
5469
6419
  className: "assist-edge-tab__logo",
@@ -5475,16 +6425,72 @@ function AssistEdgeTab({
5475
6425
  }
5476
6426
  ) : null
5477
6427
  ] }),
5478
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
5479
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronLeftIcon, {})
6428
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6429
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ChevronLeftIcon, {})
5480
6430
  ] }) : null
5481
6431
  ]
5482
6432
  }
5483
6433
  );
5484
6434
  }
5485
6435
 
6436
+ // src/react/lib/agent-feedback.ts
6437
+ var AGENT_ANSWER_FEEDBACK_EVENT_TYPE = "agent_answer_feedback";
6438
+ function findPrecedingVisitorText(messages, agentMessageId) {
6439
+ const agentIndex = messages.findIndex(
6440
+ (message) => message.id === agentMessageId && message.role === "agent"
6441
+ );
6442
+ if (agentIndex < 0) return void 0;
6443
+ for (let index = agentIndex - 1; index >= 0; index -= 1) {
6444
+ const message = messages[index];
6445
+ if (message?.role === "visitor") {
6446
+ return message.text.trim() || void 0;
6447
+ }
6448
+ }
6449
+ return void 0;
6450
+ }
6451
+ function normalizeAgentFeedbackAnswerText(text) {
6452
+ const normalized = text.replace(/\s+/g, " ").trim();
6453
+ if (!normalized) return void 0;
6454
+ return normalized.length > 4e3 ? `${normalized.slice(0, 3997)}...` : normalized;
6455
+ }
6456
+ function buildAgentAnswerFeedbackEvent(input) {
6457
+ const positive = input.rating === "positive";
6458
+ const answer = input.answer ? normalizeAgentFeedbackAnswerText(input.answer) : void 0;
6459
+ return {
6460
+ event_type: AGENT_ANSWER_FEEDBACK_EVENT_TYPE,
6461
+ company: input.analytics.companyIndex,
6462
+ session_id: input.visitorSessionId,
6463
+ page: input.page,
6464
+ timestamp: Date.now(),
6465
+ tracking_consent: input.analytics.trackingConsent,
6466
+ feedback_value: positive ? 1 : -1,
6467
+ // Aggregate-safe rating enum, kept even for anonymous (no-consent) events.
6468
+ feedback_rating: positive ? "helpful" : "not_helpful",
6469
+ surface: "agent_panel",
6470
+ index_id: input.indexId,
6471
+ index_version: input.version,
6472
+ message_id: input.messageId,
6473
+ ...input.agentSessionId ? { agent_session_id: input.agentSessionId } : {},
6474
+ ...input.analytics.trackingConsent && input.query ? { query: input.query } : {},
6475
+ ...input.analytics.trackingConsent && answer ? { answer } : {}
6476
+ };
6477
+ }
6478
+ function sendAgentAnswerFeedback(eventUrl, event) {
6479
+ try {
6480
+ void fetch(eventUrl, {
6481
+ body: JSON.stringify(event),
6482
+ credentials: "omit",
6483
+ headers: { "Content-Type": "application/json" },
6484
+ keepalive: true,
6485
+ method: "POST"
6486
+ }).catch(() => {
6487
+ });
6488
+ } catch {
6489
+ }
6490
+ }
6491
+
5486
6492
  // src/react/components/AgentWidget/AgentWidget.tsx
5487
- var import_jsx_runtime16 = require("react/jsx-runtime");
6493
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5488
6494
  function AgentWidget({
5489
6495
  indexId,
5490
6496
  customerId,
@@ -5498,13 +6504,14 @@ function AgentWidget({
5498
6504
  registerPanelController = false,
5499
6505
  colorScheme = "auto",
5500
6506
  branding,
6507
+ analytics,
5501
6508
  toolResultRegistry
5502
6509
  }) {
5503
6510
  const isMobile = useIsMobile();
5504
6511
  const placement = normalizeAgentPlacement(placementInput);
5505
- const railSlotRef = (0, import_react12.useRef)(null);
5506
- const [railCollapsed, setRailCollapsed] = (0, import_react12.useState)(defaultCollapsed);
5507
- const [railExpanded, setRailExpanded] = (0, import_react12.useState)(false);
6512
+ const railSlotRef = (0, import_react15.useRef)(null);
6513
+ const [railCollapsed, setRailCollapsed] = (0, import_react15.useState)(defaultCollapsed);
6514
+ const [railExpanded, setRailExpanded] = (0, import_react15.useState)(false);
5508
6515
  const pageShiftActive = shouldApplyPageShift({
5509
6516
  pageShift,
5510
6517
  isMobile,
@@ -5515,7 +6522,17 @@ function AgentWidget({
5515
6522
  active: pageShiftActive,
5516
6523
  railSlotRef
5517
6524
  });
5518
- const { state, reset, retry, respondToInput, respondToToolInput, submit } = useAgentChat({
6525
+ const {
6526
+ state,
6527
+ reset,
6528
+ retry,
6529
+ regenerate,
6530
+ respondToInput,
6531
+ respondToToolInput,
6532
+ submit,
6533
+ visitorSessionId,
6534
+ sessionId
6535
+ } = useAgentChat({
5519
6536
  customerId,
5520
6537
  getUnpublishedPreviewGrant,
5521
6538
  indexId,
@@ -5547,7 +6564,7 @@ function AgentWidget({
5547
6564
  } : {},
5548
6565
  ...branding?.colors?.border ? { border: branding.colors.border } : {}
5549
6566
  };
5550
- (0, import_react12.useEffect)(() => {
6567
+ (0, import_react15.useEffect)(() => {
5551
6568
  if (!registerPanelController) return;
5552
6569
  registerAgentPanelController(customerId, {
5553
6570
  open: () => setRailCollapsed(false),
@@ -5564,7 +6581,25 @@ function AgentWidget({
5564
6581
  if (isMobile) setRailCollapsed(false);
5565
6582
  await submit(message);
5566
6583
  }
5567
- (0, import_react12.useEffect)(() => {
6584
+ function handleFeedback(rating, message) {
6585
+ if (!analytics) return;
6586
+ sendAgentAnswerFeedback(
6587
+ analytics.eventUrl,
6588
+ buildAgentAnswerFeedbackEvent({
6589
+ agentSessionId: sessionId,
6590
+ analytics,
6591
+ indexId,
6592
+ messageId: message.id,
6593
+ page: window.location.href,
6594
+ query: findPrecedingVisitorText(state.messages, message.id),
6595
+ answer: message.text,
6596
+ rating,
6597
+ version: version ?? "published",
6598
+ visitorSessionId
6599
+ })
6600
+ );
6601
+ }
6602
+ (0, import_react15.useEffect)(() => {
5568
6603
  if (railCollapsed) return;
5569
6604
  const handleKeyDown = (event) => {
5570
6605
  if (event.key === "Tab" && (isMobile || railExpanded)) {
@@ -5598,19 +6633,19 @@ function AgentWidget({
5598
6633
  window.addEventListener("keydown", handleKeyDown);
5599
6634
  return () => window.removeEventListener("keydown", handleKeyDown);
5600
6635
  }, [isMobile, railCollapsed, railExpanded]);
5601
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "webless-agent-root", children: [
5602
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6636
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "webless-agent-root", children: [
6637
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5603
6638
  "div",
5604
6639
  {
5605
6640
  className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
5606
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6641
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5607
6642
  "div",
5608
6643
  {
5609
6644
  ref: railSlotRef,
5610
6645
  className: "webless-agent-root__rail-slot",
5611
6646
  inert: railCollapsed || void 0,
5612
6647
  "aria-hidden": railCollapsed,
5613
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6648
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5614
6649
  AgentRail,
5615
6650
  {
5616
6651
  theme,
@@ -5619,6 +6654,9 @@ function AgentWidget({
5619
6654
  brandLogoUrl: branding?.logoUrl,
5620
6655
  composerPlaceholder: branding?.composerPlaceholder ?? "Ask a question\u2026",
5621
6656
  poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
6657
+ disclaimerLabel: branding?.disclaimer,
6658
+ answerReceipt: branding?.answerReceipt,
6659
+ readAloud: branding?.readAloud,
5622
6660
  state,
5623
6661
  mobileFullscreen: isMobile && !railCollapsed,
5624
6662
  expanded: railExpanded,
@@ -5628,17 +6666,22 @@ function AgentWidget({
5628
6666
  onSubmit: handleSubmit,
5629
6667
  onReset: reset,
5630
6668
  onRetry: () => void retry(),
6669
+ onRegenerate: () => void regenerate(),
6670
+ onFeedback: analytics ? handleFeedback : void 0,
5631
6671
  onInputResponse: (response) => void respondToInput(response),
5632
6672
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5633
6673
  onFollowUpSelect: (label) => void handleSubmit(label),
5634
- onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
6674
+ onBook: (input) => void submit(input.displayText, {
6675
+ preservePendingOffer: true,
6676
+ runtimeText: input.runtimeText
6677
+ })
5635
6678
  }
5636
6679
  )
5637
6680
  }
5638
6681
  )
5639
6682
  }
5640
6683
  ),
5641
- railCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6684
+ railCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5642
6685
  AssistEdgeTab,
5643
6686
  {
5644
6687
  variant: placement.variant,
@@ -5677,12 +6720,12 @@ function readUnpublishedPreviewBuildId(href) {
5677
6720
  }
5678
6721
 
5679
6722
  // src/embed/AgentWidget.tsx
5680
- var import_jsx_runtime17 = require("react/jsx-runtime");
6723
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5681
6724
  function AgentWidget2({
5682
6725
  manifest
5683
6726
  }) {
5684
6727
  const defaultCollapsed = manifest.version !== "unpublished";
5685
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6728
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5686
6729
  AgentWidget,
5687
6730
  {
5688
6731
  indexId: manifest.indexId,
@@ -5694,6 +6737,7 @@ function AgentWidget2({
5694
6737
  pageShift: manifest.pageShift,
5695
6738
  colorScheme: manifest.colorScheme,
5696
6739
  branding: manifest.branding,
6740
+ analytics: manifest.analytics,
5697
6741
  defaultCollapsed,
5698
6742
  registerPanelController: true
5699
6743
  }
@@ -5724,6 +6768,7 @@ function normalizeAgentTagManifest(manifest) {
5724
6768
  runtimeOrigin: manifest.runtimeOrigin?.trim() || DEFAULT_RUNTIME_ORIGIN
5725
6769
  });
5726
6770
  const branding = normalizeAgentBranding(manifest.branding);
6771
+ const analytics = normalizeAgentAnalytics(manifest.analytics);
5727
6772
  return {
5728
6773
  customerId,
5729
6774
  indexId,
@@ -5736,7 +6781,27 @@ function normalizeAgentTagManifest(manifest) {
5736
6781
  placement: normalizeAgentPlacement(manifest.placement),
5737
6782
  pageShift: manifest.pageShift ?? true,
5738
6783
  colorScheme,
5739
- ...branding ? { branding } : {}
6784
+ ...branding ? { branding } : {},
6785
+ ...analytics ? { analytics } : {}
6786
+ };
6787
+ }
6788
+ function normalizeAgentAnalytics(analytics) {
6789
+ if (!analytics) return void 0;
6790
+ const companyIndex = analytics.companyIndex?.trim() ?? "";
6791
+ const eventUrl = analytics.eventUrl?.trim() ?? "";
6792
+ if (!companyIndex || !eventUrl) return void 0;
6793
+ try {
6794
+ const parsed = new URL(eventUrl);
6795
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
6796
+ return void 0;
6797
+ }
6798
+ } catch {
6799
+ return void 0;
6800
+ }
6801
+ return {
6802
+ companyIndex,
6803
+ eventUrl,
6804
+ trackingConsent: analytics.trackingConsent === true
5740
6805
  };
5741
6806
  }
5742
6807
  function normalizeOptionalValue(value) {
@@ -5759,6 +6824,9 @@ function normalizeAgentBranding(branding) {
5759
6824
  greeting: normalizeOptionalValue(branding.greeting),
5760
6825
  composerPlaceholder: normalizeOptionalValue(branding.composerPlaceholder),
5761
6826
  poweredByLabel: normalizeOptionalValue(branding.poweredByLabel),
6827
+ disclaimer: branding.disclaimer === null ? null : normalizeOptionalValue(branding.disclaimer),
6828
+ answerReceipt: branding.answerReceipt === true ? true : void 0,
6829
+ readAloud: branding.readAloud === true ? true : void 0,
5762
6830
  fontFamily: normalizeOptionalValue(branding.fontFamily),
5763
6831
  colors: colors && Object.keys(colors).length > 0 ? colors : void 0
5764
6832
  };
@@ -5766,7 +6834,7 @@ function normalizeAgentBranding(branding) {
5766
6834
  }
5767
6835
 
5768
6836
  // src/embed/mount.tsx
5769
- var import_jsx_runtime18 = require("react/jsx-runtime");
6837
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5770
6838
  var mountedHandles = /* @__PURE__ */ new Map();
5771
6839
  var latestCustomerId = null;
5772
6840
  function resolveMountHost(manifest, script) {
@@ -5796,7 +6864,7 @@ function mountAgent(input) {
5796
6864
  const host = createHost(manifest.customerId);
5797
6865
  mountTarget.append(host);
5798
6866
  const root = (0, import_client5.createRoot)(host);
5799
- root.render(/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AgentWidget2, { manifest }));
6867
+ root.render(/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AgentWidget2, { manifest }));
5800
6868
  const handle = {
5801
6869
  customerId: manifest.customerId,
5802
6870
  manifest,