@webless/agent 0.6.9 → 0.6.11

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.
@@ -780,6 +780,30 @@ function bookingPresenter(kind) {
780
780
  }
781
781
  };
782
782
  }
783
+ function providerErrorPresenter() {
784
+ return {
785
+ kind: "provider_error",
786
+ present: ({ envelope }) => {
787
+ const output = asRecord3(envelope.output);
788
+ const providerError = asRecord3(output?.providerError);
789
+ const message = safeText(providerError?.message);
790
+ const action = safeText(providerError?.action);
791
+ if (!message || !action) return null;
792
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
793
+ return {
794
+ kind: "summary",
795
+ status: "failed",
796
+ title: message,
797
+ description: action,
798
+ ...resourceLabels.length ? {
799
+ details: [
800
+ { label: "Affected", value: resourceLabels.join(", ") }
801
+ ]
802
+ } : {}
803
+ };
804
+ }
805
+ };
806
+ }
783
807
  function asRecord3(value) {
784
808
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
785
809
  }
@@ -897,6 +921,7 @@ function fallbackTitleFromKind(kind) {
897
921
  return "Saved";
898
922
  }
899
923
  var builtInVisitorToolResultRegistry = [
924
+ providerErrorPresenter(),
900
925
  bookingPresenter("booking_offer"),
901
926
  bookingPresenter("booking_confirmed"),
902
927
  bookingPresenter("booking_canceled"),
@@ -946,7 +971,7 @@ function finalizeSummaryPresentation(result, proposed) {
946
971
  return {
947
972
  id: result.callId,
948
973
  toolName: result.toolName,
949
- status: result.status,
974
+ status: proposed.status ?? result.status,
950
975
  kind: "summary",
951
976
  title,
952
977
  ...description && description !== title ? { description } : {},
@@ -955,7 +980,7 @@ function finalizeSummaryPresentation(result, proposed) {
955
980
  };
956
981
  }
957
982
  function presentVisitorToolResult(result, registry = []) {
958
- const envelope = parseAgentToolResultEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
983
+ const envelope = parseAgentToolResultEnvelope(result.output) ?? providerErrorEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
959
984
  const proposed = envelope ? resolvePresenterOutput(result, envelope, registry) : null;
960
985
  if (proposed?.kind === "booking") {
961
986
  return {
@@ -1018,6 +1043,25 @@ function presentVisitorToolResult(result, registry = []) {
1018
1043
  }
1019
1044
  return finalizeSummaryPresentation(result, proposed);
1020
1045
  }
1046
+ function providerErrorEnvelope(output) {
1047
+ const record = asRecord3(output);
1048
+ const providerError = asRecord3(record?.providerError);
1049
+ const message = safeText(providerError?.message);
1050
+ const action = safeText(providerError?.action);
1051
+ if (!message || !action) return null;
1052
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
1053
+ return {
1054
+ schemaVersion: "webless.tool-result.v1",
1055
+ output: {
1056
+ providerError: {
1057
+ action,
1058
+ message,
1059
+ ...resourceLabels.length ? { resourceLabels } : {}
1060
+ }
1061
+ },
1062
+ presentationKinds: ["provider_error"]
1063
+ };
1064
+ }
1021
1065
  function legacyBookingEnvelope(output) {
1022
1066
  const card = bookingCardFromActionOutput(output);
1023
1067
  return card ? {
@@ -2702,6 +2746,7 @@ function useAgentChat({
2702
2746
  let streamStarted = Boolean(initialText);
2703
2747
  let streamed = initialText;
2704
2748
  const capturedOffers = [];
2749
+ let bookingConfirmed = false;
2705
2750
  let capturedInputCount = 0;
2706
2751
  const handlers = {
2707
2752
  onWork: (item) => {
@@ -2726,6 +2771,7 @@ function useAgentChat({
2726
2771
  }
2727
2772
  if (!isActiveRun()) return;
2728
2773
  if (card.type === "booking_confirmed") {
2774
+ bookingConfirmed = true;
2729
2775
  pendingBookingRef.current = card;
2730
2776
  savePendingWidgetBooking(
2731
2777
  resolvedStorageKeyPrefix,
@@ -2801,7 +2847,10 @@ function useAgentChat({
2801
2847
  initialText,
2802
2848
  message: visitorText,
2803
2849
  signal
2804
- }) : await clientRef.current.sendTurn(visitorText, { handlers, signal });
2850
+ }) : await clientRef.current.sendTurn(visitorText, {
2851
+ handlers,
2852
+ signal
2853
+ });
2805
2854
  if (resume && finalText === null) {
2806
2855
  finalText = await clientRef.current.sendTurn(visitorText, {
2807
2856
  handlers,
@@ -2820,6 +2869,7 @@ function useAgentChat({
2820
2869
  const parsedCards = extractToolCards(displayText);
2821
2870
  for (const card of parsedCards) {
2822
2871
  if (card.type === "booking_confirmed") {
2872
+ bookingConfirmed = true;
2823
2873
  pendingBookingRef.current = card;
2824
2874
  savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
2825
2875
  }
@@ -2834,7 +2884,7 @@ function useAgentChat({
2834
2884
  messages: appendAgentTurnMessage(prev.messages, displayText),
2835
2885
  toolSteps: completeActivePlanning(prev.toolSteps),
2836
2886
  streamingText: "",
2837
- pendingOffer: capturedOffers.at(-1) ?? prev.pendingOffer,
2887
+ pendingOffer: bookingConfirmed ? null : capturedOffers.at(-1) ?? prev.pendingOffer,
2838
2888
  pendingInputs: (prev.pendingInputs ?? []).filter(
2839
2889
  isChatCollectibleInputRequest
2840
2890
  ),
@@ -2860,7 +2910,6 @@ function useAgentChat({
2860
2910
  } : step
2861
2911
  ),
2862
2912
  streamingText: "",
2863
- pendingOffer: null,
2864
2913
  error: message
2865
2914
  }));
2866
2915
  runRef.current = null;
@@ -2968,7 +3017,7 @@ ${outgoing}` : outgoing;
2968
3017
  journey: null,
2969
3018
  followUps: [],
2970
3019
  streamingText: "",
2971
- pendingOffer: null,
3020
+ pendingOffer: options?.preservePendingOffer ? prev.pendingOffer : null,
2972
3021
  pendingInputs: [],
2973
3022
  toolResults: [],
2974
3023
  error: null
@@ -3004,7 +3053,6 @@ ${outgoing}` : outgoing;
3004
3053
  journey: null,
3005
3054
  followUps: [],
3006
3055
  streamingText: "",
3007
- pendingOffer: null,
3008
3056
  pendingInputs: [],
3009
3057
  toolResults: [],
3010
3058
  error: null
@@ -3197,7 +3245,7 @@ var defaultDarkAgentRailTheme = {
3197
3245
  };
3198
3246
 
3199
3247
  // src/react/components/AgentRail/AgentRail.tsx
3200
- import { useEffect as useEffect3, useRef as useRef3, useState as useState8 } from "react";
3248
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState8 } from "react";
3201
3249
 
3202
3250
  // src/react/hooks/useAgentColorScheme.ts
3203
3251
  import { useSyncExternalStore } from "react";
@@ -3610,7 +3658,13 @@ function FollowUpChips({
3610
3658
  import { useState as useState5 } from "react";
3611
3659
 
3612
3660
  // src/react/components/BookingCard/BookingCard.tsx
3613
- import { useId as useId2, useMemo as useMemo2, useState as useState4 } from "react";
3661
+ import {
3662
+ useEffect as useEffect3,
3663
+ useId as useId2,
3664
+ useMemo as useMemo2,
3665
+ useRef as useRef3,
3666
+ useState as useState4
3667
+ } from "react";
3614
3668
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3615
3669
  var BOOKING_STEPS = [
3616
3670
  { id: "date", label: "Date" },
@@ -3645,6 +3699,7 @@ function BookingCardLoader() {
3645
3699
  return /* @__PURE__ */ jsx4("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsx4("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) });
3646
3700
  }
3647
3701
  function BookingCard({
3702
+ disabled = false,
3648
3703
  offer,
3649
3704
  onBook
3650
3705
  }) {
@@ -3656,7 +3711,14 @@ function BookingCard({
3656
3711
  const [startTime, setStartTime] = useState4("");
3657
3712
  const [name, setName] = useState4("");
3658
3713
  const [email, setEmail] = useState4("");
3714
+ const activeStepRef = useRef3(null);
3715
+ const previousStepRef = useRef3(step);
3659
3716
  const stepIndex = BOOKING_STEPS.findIndex((item) => item.id === step);
3717
+ useEffect3(() => {
3718
+ if (previousStepRef.current === step) return;
3719
+ previousStepRef.current = step;
3720
+ activeStepRef.current?.scrollIntoView({ block: "nearest" });
3721
+ }, [step]);
3660
3722
  const slots = useMemo2(
3661
3723
  () => bookingSlotsForEventType(offer.slots, eventTypeUri),
3662
3724
  [eventTypeUri, offer.slots]
@@ -3733,216 +3795,230 @@ function BookingCard({
3733
3795
  })
3734
3796
  });
3735
3797
  }
3736
- return /* @__PURE__ */ jsx4("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsxs4("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3737
- /* @__PURE__ */ jsx4("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ jsxs4(
3738
- "li",
3739
- {
3740
- className: [
3741
- "booking-card__step-indicator",
3742
- index === stepIndex ? "booking-card__step-indicator--active" : "",
3743
- index < stepIndex ? "booking-card__step-indicator--complete" : ""
3744
- ].filter(Boolean).join(" "),
3745
- "aria-current": index === stepIndex ? "step" : void 0,
3746
- children: [
3747
- /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: index + 1 }),
3748
- /* @__PURE__ */ jsx4("span", { children: item.label })
3749
- ]
3750
- },
3751
- item.id
3752
- )) }),
3753
- step === "date" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
3754
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3755
- timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
3756
- "Times in ",
3757
- timeZone
3758
- ] }) : null,
3759
- offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs4(
3760
- "label",
3761
- {
3762
- className: "booking-card__field",
3763
- htmlFor: `${fieldId}-type`,
3764
- children: [
3765
- /* @__PURE__ */ jsx4("span", { children: "Meeting" }),
3798
+ return /* @__PURE__ */ jsx4(
3799
+ "section",
3800
+ {
3801
+ className: "booking-card",
3802
+ "aria-busy": disabled || void 0,
3803
+ "aria-label": "Book a meeting",
3804
+ children: /* @__PURE__ */ jsxs4("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3805
+ /* @__PURE__ */ jsx4("ol", { className: "booking-card__steps", "aria-label": "Booking steps", children: BOOKING_STEPS.map((item, index) => /* @__PURE__ */ jsxs4(
3806
+ "li",
3807
+ {
3808
+ className: [
3809
+ "booking-card__step-indicator",
3810
+ index === stepIndex ? "booking-card__step-indicator--active" : "",
3811
+ index < stepIndex ? "booking-card__step-indicator--complete" : ""
3812
+ ].filter(Boolean).join(" "),
3813
+ "aria-current": index === stepIndex ? "step" : void 0,
3814
+ children: [
3815
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: index + 1 }),
3816
+ /* @__PURE__ */ jsx4("span", { children: item.label })
3817
+ ]
3818
+ },
3819
+ item.id
3820
+ )) }),
3821
+ step === "date" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3822
+ /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3823
+ timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
3824
+ "Times in ",
3825
+ timeZone
3826
+ ] }) : null,
3827
+ offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs4(
3828
+ "label",
3829
+ {
3830
+ className: "booking-card__field",
3831
+ htmlFor: `${fieldId}-type`,
3832
+ children: [
3833
+ /* @__PURE__ */ jsx4("span", { children: "Meeting" }),
3834
+ /* @__PURE__ */ jsx4(
3835
+ "select",
3836
+ {
3837
+ id: `${fieldId}-type`,
3838
+ value: eventTypeUri,
3839
+ disabled,
3840
+ onChange: (event) => selectEventType(event.target.value),
3841
+ children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx4("option", { value: item.uri, children: item.name }, item.uri))
3842
+ }
3843
+ )
3844
+ ]
3845
+ }
3846
+ ) : null,
3847
+ /* @__PURE__ */ jsxs4("div", { className: "booking-card__month", children: [
3848
+ /* @__PURE__ */ jsx4(
3849
+ "button",
3850
+ {
3851
+ type: "button",
3852
+ className: "booking-card__nav",
3853
+ "aria-label": "Previous month",
3854
+ disabled: disabled || !canPrevMonth,
3855
+ onClick: () => goToMonth(-1),
3856
+ children: "\u2039"
3857
+ }
3858
+ ),
3859
+ /* @__PURE__ */ jsx4("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3766
3860
  /* @__PURE__ */ jsx4(
3767
- "select",
3861
+ "button",
3768
3862
  {
3769
- id: `${fieldId}-type`,
3770
- value: eventTypeUri,
3771
- onChange: (event) => selectEventType(event.target.value),
3772
- children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx4("option", { value: item.uri, children: item.name }, item.uri))
3863
+ type: "button",
3864
+ className: "booking-card__nav",
3865
+ "aria-label": "Next month",
3866
+ disabled: disabled || !canNextMonth,
3867
+ onClick: () => goToMonth(1),
3868
+ children: "\u203A"
3773
3869
  }
3774
3870
  )
3775
- ]
3776
- }
3777
- ) : null,
3778
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__month", children: [
3779
- /* @__PURE__ */ jsx4(
3780
- "button",
3781
- {
3782
- type: "button",
3783
- className: "booking-card__nav",
3784
- "aria-label": "Previous month",
3785
- disabled: !canPrevMonth,
3786
- onClick: () => goToMonth(-1),
3787
- children: "\u2039"
3788
- }
3789
- ),
3790
- /* @__PURE__ */ jsx4("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3791
- /* @__PURE__ */ jsx4(
3792
- "button",
3793
- {
3794
- type: "button",
3795
- className: "booking-card__nav",
3796
- "aria-label": "Next month",
3797
- disabled: !canNextMonth,
3798
- onClick: () => goToMonth(1),
3799
- children: "\u203A"
3800
- }
3801
- )
3802
- ] }),
3803
- /* @__PURE__ */ jsx4("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx4("span", { children: label }, label)) }),
3804
- offer.slots.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3805
- /* @__PURE__ */ jsx4(
3806
- "div",
3807
- {
3808
- className: "booking-card__calendar",
3809
- role: "grid",
3810
- "aria-label": "Available dates",
3811
- children: cells.map((cell, index) => {
3812
- if (!cell) {
3813
- return /* @__PURE__ */ jsx4(
3814
- "span",
3815
- {
3816
- className: "booking-card__day"
3817
- },
3818
- `empty-${index}`
3819
- );
3871
+ ] }),
3872
+ /* @__PURE__ */ jsx4("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx4("span", { children: label }, label)) }),
3873
+ offer.slots.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3874
+ /* @__PURE__ */ jsx4(
3875
+ "div",
3876
+ {
3877
+ className: "booking-card__calendar",
3878
+ role: "grid",
3879
+ "aria-label": "Available dates",
3880
+ children: cells.map((cell, index) => {
3881
+ if (!cell) {
3882
+ return /* @__PURE__ */ jsx4(
3883
+ "span",
3884
+ {
3885
+ className: "booking-card__day"
3886
+ },
3887
+ `empty-${index}`
3888
+ );
3889
+ }
3890
+ const available = availableByDate.has(cell.key);
3891
+ const selected = cell.key === selectedDate;
3892
+ return /* @__PURE__ */ jsx4(
3893
+ "button",
3894
+ {
3895
+ type: "button",
3896
+ className: [
3897
+ "booking-card__day",
3898
+ available ? "booking-card__day--available" : "",
3899
+ selected ? "booking-card__day--selected" : ""
3900
+ ].filter(Boolean).join(" "),
3901
+ disabled: disabled || !available,
3902
+ "aria-pressed": selected,
3903
+ onClick: () => selectDate(cell.key),
3904
+ children: cell.day
3905
+ },
3906
+ cell.key
3907
+ );
3908
+ })
3820
3909
  }
3821
- const available = availableByDate.has(cell.key);
3822
- const selected = cell.key === selectedDate;
3823
- return /* @__PURE__ */ jsx4(
3910
+ )
3911
+ ] }, "date") : null,
3912
+ step === "time" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3913
+ /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3914
+ /* @__PURE__ */ jsx4(
3824
3915
  "button",
3825
3916
  {
3826
3917
  type: "button",
3827
- className: [
3828
- "booking-card__day",
3829
- available ? "booking-card__day--available" : "",
3830
- selected ? "booking-card__day--selected" : ""
3831
- ].filter(Boolean).join(" "),
3832
- disabled: !available,
3833
- "aria-pressed": selected,
3834
- onClick: () => selectDate(cell.key),
3835
- children: cell.day
3836
- },
3837
- cell.key
3838
- );
3839
- })
3840
- }
3841
- )
3842
- ] }, "date") : null,
3843
- step === "time" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
3844
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3845
- /* @__PURE__ */ jsx4(
3846
- "button",
3847
- {
3848
- type: "button",
3849
- className: "booking-card__nav",
3850
- "aria-label": "Back to dates",
3851
- onClick: () => setStep("date"),
3852
- children: "\u2039"
3853
- }
3854
- ),
3855
- /* @__PURE__ */ jsxs4("div", { children: [
3856
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3857
- timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
3858
- "Times in ",
3859
- timeZone
3860
- ] }) : null
3861
- ] })
3862
- ] }),
3863
- /* @__PURE__ */ jsx4("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
3864
- "button",
3865
- {
3866
- type: "button",
3867
- className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
3868
- onClick: () => selectTime(slot.startTime),
3869
- children: formatTimeChip(slot.startTime)
3870
- },
3871
- slot.startTime
3872
- )) })
3873
- ] }, "time") : null,
3874
- step === "details" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
3875
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3876
- /* @__PURE__ */ jsx4(
3877
- "button",
3878
- {
3879
- type: "button",
3880
- className: "booking-card__nav",
3881
- "aria-label": "Back to times",
3882
- onClick: () => setStep("time"),
3883
- children: "\u2039"
3884
- }
3885
- ),
3886
- /* @__PURE__ */ jsxs4("div", { children: [
3887
- /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: "Enter details" }),
3888
- /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
3889
- selectedType?.location ? /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: selectedType.location }) : null
3890
- ] })
3891
- ] }),
3892
- /* @__PURE__ */ jsxs4("div", { className: "booking-card__identity", children: [
3893
- /* @__PURE__ */ jsxs4(
3894
- "label",
3895
- {
3896
- className: "booking-card__field",
3897
- htmlFor: `${fieldId}-name`,
3898
- children: [
3899
- /* @__PURE__ */ jsx4("span", { children: "Name" }),
3900
- /* @__PURE__ */ jsx4(
3901
- "input",
3902
- {
3903
- id: `${fieldId}-name`,
3904
- autoComplete: "name",
3905
- value: name,
3906
- onChange: (event) => setName(event.target.value),
3907
- required: true
3908
- }
3909
- )
3910
- ]
3911
- }
3912
- ),
3913
- /* @__PURE__ */ jsxs4(
3914
- "label",
3915
- {
3916
- className: "booking-card__field",
3917
- htmlFor: `${fieldId}-email`,
3918
- children: [
3919
- /* @__PURE__ */ jsx4("span", { children: "Email" }),
3920
- /* @__PURE__ */ jsx4(
3921
- "input",
3922
- {
3923
- id: `${fieldId}-email`,
3924
- type: "email",
3925
- autoComplete: "email",
3926
- value: email,
3927
- onChange: (event) => setEmail(event.target.value),
3928
- required: true
3929
- }
3930
- )
3931
- ]
3932
- }
3933
- )
3934
- ] }),
3935
- /* @__PURE__ */ jsx4(
3936
- "button",
3937
- {
3938
- type: "submit",
3939
- className: "booking-card__submit",
3940
- disabled: !name.trim() || !email.trim(),
3941
- children: "Book this time"
3942
- }
3943
- )
3944
- ] }, "details") : null
3945
- ] }) });
3918
+ className: "booking-card__nav",
3919
+ "aria-label": "Back to dates",
3920
+ disabled,
3921
+ onClick: () => setStep("date"),
3922
+ children: "\u2039"
3923
+ }
3924
+ ),
3925
+ /* @__PURE__ */ jsxs4("div", { children: [
3926
+ /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3927
+ timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
3928
+ "Times in ",
3929
+ timeZone
3930
+ ] }) : null
3931
+ ] })
3932
+ ] }),
3933
+ /* @__PURE__ */ jsx4("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
3934
+ "button",
3935
+ {
3936
+ type: "button",
3937
+ className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
3938
+ disabled,
3939
+ onClick: () => selectTime(slot.startTime),
3940
+ children: formatTimeChip(slot.startTime)
3941
+ },
3942
+ slot.startTime
3943
+ )) })
3944
+ ] }, "time") : null,
3945
+ step === "details" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", ref: activeStepRef, children: [
3946
+ /* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
3947
+ /* @__PURE__ */ jsx4(
3948
+ "button",
3949
+ {
3950
+ type: "button",
3951
+ className: "booking-card__nav",
3952
+ "aria-label": "Back to times",
3953
+ disabled,
3954
+ onClick: () => setStep("time"),
3955
+ children: "\u2039"
3956
+ }
3957
+ ),
3958
+ /* @__PURE__ */ jsxs4("div", { children: [
3959
+ /* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: "Enter details" }),
3960
+ /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
3961
+ selectedType?.location ? /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: selectedType.location }) : null
3962
+ ] })
3963
+ ] }),
3964
+ /* @__PURE__ */ jsxs4("div", { className: "booking-card__identity", children: [
3965
+ /* @__PURE__ */ jsxs4(
3966
+ "label",
3967
+ {
3968
+ className: "booking-card__field",
3969
+ htmlFor: `${fieldId}-name`,
3970
+ children: [
3971
+ /* @__PURE__ */ jsx4("span", { children: "Name" }),
3972
+ /* @__PURE__ */ jsx4(
3973
+ "input",
3974
+ {
3975
+ id: `${fieldId}-name`,
3976
+ autoComplete: "name",
3977
+ disabled,
3978
+ value: name,
3979
+ onChange: (event) => setName(event.target.value),
3980
+ required: true
3981
+ }
3982
+ )
3983
+ ]
3984
+ }
3985
+ ),
3986
+ /* @__PURE__ */ jsxs4(
3987
+ "label",
3988
+ {
3989
+ className: "booking-card__field",
3990
+ htmlFor: `${fieldId}-email`,
3991
+ children: [
3992
+ /* @__PURE__ */ jsx4("span", { children: "Email" }),
3993
+ /* @__PURE__ */ jsx4(
3994
+ "input",
3995
+ {
3996
+ id: `${fieldId}-email`,
3997
+ type: "email",
3998
+ autoComplete: "email",
3999
+ disabled,
4000
+ value: email,
4001
+ onChange: (event) => setEmail(event.target.value),
4002
+ required: true
4003
+ }
4004
+ )
4005
+ ]
4006
+ }
4007
+ )
4008
+ ] }),
4009
+ /* @__PURE__ */ jsx4(
4010
+ "button",
4011
+ {
4012
+ type: "submit",
4013
+ className: "booking-card__submit",
4014
+ disabled: disabled || !name.trim() || !email.trim(),
4015
+ children: disabled ? "Booking\u2026" : "Book this time"
4016
+ }
4017
+ )
4018
+ ] }, "details") : null
4019
+ ] })
4020
+ }
4021
+ );
3946
4022
  }
3947
4023
 
3948
4024
  // src/react/components/MessageBubble/MessageBubble.tsx
@@ -3959,9 +4035,7 @@ function paragraphsAreNearDuplicates(first, second) {
3959
4035
  if (left === right) return true;
3960
4036
  const shorter = left.length <= right.length ? left : right;
3961
4037
  const longer = left.length <= right.length ? right : left;
3962
- return longer.startsWith(
3963
- shorter.slice(0, Math.floor(shorter.length * 0.85))
3964
- );
4038
+ return longer.startsWith(shorter.slice(0, Math.floor(shorter.length * 0.85)));
3965
4039
  }
3966
4040
  function paragraphsShareOpening(first, second) {
3967
4041
  const opening = first.split("\n")[0]?.trim();
@@ -3989,6 +4063,7 @@ function collapseRepeatedText(text) {
3989
4063
  function MessageBubble({
3990
4064
  message,
3991
4065
  brandLogoUrl,
4066
+ bookingDisabled = false,
3992
4067
  offer,
3993
4068
  onBook
3994
4069
  }) {
@@ -4024,18 +4099,17 @@ function MessageBubble({
4024
4099
  children: displayText
4025
4100
  }
4026
4101
  ),
4027
- citations.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs5(
4028
- "a",
4029
- {
4030
- href: citation.url,
4031
- target: "_blank",
4032
- rel: "noreferrer",
4033
- children: [
4034
- /* @__PURE__ */ jsx5("span", { className: "message-bubble__source-icon", "aria-hidden": "true", children: "\u25A6" }),
4035
- /* @__PURE__ */ jsx5("span", { children: citation.label })
4036
- ]
4037
- }
4038
- ) }, citation.id)) }) : null
4102
+ citations.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "message-bubble__sources", "aria-label": "Sources", children: citations.map((citation) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs5("a", { href: citation.url, target: "_blank", rel: "noreferrer", children: [
4103
+ /* @__PURE__ */ jsx5(
4104
+ "span",
4105
+ {
4106
+ className: "message-bubble__source-icon",
4107
+ "aria-hidden": "true",
4108
+ children: "\u25A6"
4109
+ }
4110
+ ),
4111
+ /* @__PURE__ */ jsx5("span", { children: citation.label })
4112
+ ] }) }, citation.id)) }) : null
4039
4113
  ] });
4040
4114
  return /* @__PURE__ */ jsxs5("article", { className: "message-bubble message-bubble--agent", children: [
4041
4115
  displayText ? showBrandLogo ? /* @__PURE__ */ jsxs5("div", { className: "message-bubble__agent-row", children: [
@@ -4054,6 +4128,7 @@ function MessageBubble({
4054
4128
  offers.map((nextOffer, index) => /* @__PURE__ */ jsx5(
4055
4129
  BookingCard,
4056
4130
  {
4131
+ disabled: bookingDisabled,
4057
4132
  offer: nextOffer,
4058
4133
  onBook
4059
4134
  },
@@ -4839,7 +4914,7 @@ function AgentRail({
4839
4914
  onInputResponse,
4840
4915
  onToolInput
4841
4916
  }) {
4842
- const transcriptRef = useRef3(null);
4917
+ const transcriptRef = useRef4(null);
4843
4918
  const resolvedBrandLabel = brandLabel.trim();
4844
4919
  const resolvedBrandLogoUrl = brandLogoUrl?.trim();
4845
4920
  const [failedLogoUrl, setFailedLogoUrl] = useState8(null);
@@ -4944,7 +5019,7 @@ function AgentRail({
4944
5019
  hasPendingConfirmation,
4945
5020
  enabled: lastIsAgent && !isBusy
4946
5021
  });
4947
- useEffect3(() => {
5022
+ useEffect4(() => {
4948
5023
  const node = transcriptRef.current;
4949
5024
  if (!node) return;
4950
5025
  node.scrollTop = node.scrollHeight;
@@ -5033,6 +5108,7 @@ function AgentRail({
5033
5108
  MessageBubble,
5034
5109
  {
5035
5110
  message: greeting,
5111
+ bookingDisabled: isBusy,
5036
5112
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5037
5113
  onBook
5038
5114
  }
@@ -5078,6 +5154,7 @@ function AgentRail({
5078
5154
  MessageBubble,
5079
5155
  {
5080
5156
  message,
5157
+ bookingDisabled: isBusy,
5081
5158
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5082
5159
  offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5083
5160
  onBook
@@ -5116,6 +5193,7 @@ function AgentRail({
5116
5193
  MessageBubble,
5117
5194
  {
5118
5195
  message: streamingMessage,
5196
+ bookingDisabled: isBusy,
5119
5197
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5120
5198
  offer: state.pendingOffer,
5121
5199
  onBook
@@ -5355,10 +5433,10 @@ function AssistEdgeTab({
5355
5433
  }
5356
5434
 
5357
5435
  // src/react/components/AgentWidget/AgentWidget.tsx
5358
- import { useEffect as useEffect6, useRef as useRef4, useState as useState10 } from "react";
5436
+ import { useEffect as useEffect7, useRef as useRef5, useState as useState10 } from "react";
5359
5437
 
5360
5438
  // src/react/page-shift.ts
5361
- import { useEffect as useEffect4 } from "react";
5439
+ import { useEffect as useEffect5 } from "react";
5362
5440
  var PAGE_SHIFT_CLASS = "webless-agent-page-shift";
5363
5441
  var DEFAULT_RAIL_WIDTH_PX = 450;
5364
5442
  function shouldApplyPageShift(input) {
@@ -5410,7 +5488,7 @@ function clearPageMargin() {
5410
5488
  }
5411
5489
  function usePageShift(input) {
5412
5490
  const { active, railSlotRef } = input;
5413
- useEffect4(() => {
5491
+ useEffect5(() => {
5414
5492
  if (typeof document === "undefined") {
5415
5493
  return;
5416
5494
  }
@@ -5438,12 +5516,12 @@ function usePageShift(input) {
5438
5516
  }
5439
5517
 
5440
5518
  // src/react/hooks/useIsMobile.ts
5441
- import { useEffect as useEffect5, useState as useState9 } from "react";
5519
+ import { useEffect as useEffect6, useState as useState9 } from "react";
5442
5520
  function useIsMobile(breakpoint = 767) {
5443
5521
  const [isMobile, setIsMobile] = useState9(
5444
5522
  () => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
5445
5523
  );
5446
- useEffect5(() => {
5524
+ useEffect6(() => {
5447
5525
  const media = window.matchMedia(`(max-width: ${breakpoint}px)`);
5448
5526
  const onChange = () => setIsMobile(media.matches);
5449
5527
  onChange();
@@ -5472,7 +5550,7 @@ function AgentWidget({
5472
5550
  }) {
5473
5551
  const isMobile = useIsMobile();
5474
5552
  const placement = normalizeAgentPlacement(placementInput);
5475
- const railSlotRef = useRef4(null);
5553
+ const railSlotRef = useRef5(null);
5476
5554
  const [railCollapsed, setRailCollapsed] = useState10(defaultCollapsed);
5477
5555
  const [railExpanded, setRailExpanded] = useState10(false);
5478
5556
  const pageShiftActive = shouldApplyPageShift({
@@ -5517,7 +5595,7 @@ function AgentWidget({
5517
5595
  } : {},
5518
5596
  ...branding?.colors?.border ? { border: branding.colors.border } : {}
5519
5597
  };
5520
- useEffect6(() => {
5598
+ useEffect7(() => {
5521
5599
  if (!registerPanelController) return;
5522
5600
  registerAgentPanelController(customerId, {
5523
5601
  open: () => setRailCollapsed(false),
@@ -5534,7 +5612,7 @@ function AgentWidget({
5534
5612
  if (isMobile) setRailCollapsed(false);
5535
5613
  await submit(message);
5536
5614
  }
5537
- useEffect6(() => {
5615
+ useEffect7(() => {
5538
5616
  if (railCollapsed) return;
5539
5617
  const handleKeyDown = (event) => {
5540
5618
  if (event.key === "Tab" && (isMobile || railExpanded)) {
@@ -5601,7 +5679,10 @@ function AgentWidget({
5601
5679
  onInputResponse: (response) => void respondToInput(response),
5602
5680
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5603
5681
  onFollowUpSelect: (label) => void handleSubmit(label),
5604
- onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
5682
+ onBook: (input) => void submit(input.displayText, {
5683
+ preservePendingOffer: true,
5684
+ runtimeText: input.runtimeText
5685
+ })
5605
5686
  }
5606
5687
  )
5607
5688
  }
@@ -5657,4 +5738,4 @@ export {
5657
5738
  AssistEdgeTab,
5658
5739
  AgentWidget
5659
5740
  };
5660
- //# sourceMappingURL=chunk-U2SU2CGF.js.map
5741
+ //# sourceMappingURL=chunk-YNF2UPGJ.js.map