@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.
package/dist/embed.cjs CHANGED
@@ -2302,6 +2302,30 @@ function bookingPresenter(kind) {
2302
2302
  }
2303
2303
  };
2304
2304
  }
2305
+ function providerErrorPresenter() {
2306
+ return {
2307
+ kind: "provider_error",
2308
+ present: ({ envelope }) => {
2309
+ const output = asRecord3(envelope.output);
2310
+ const providerError = asRecord3(output?.providerError);
2311
+ const message = safeText(providerError?.message);
2312
+ const action = safeText(providerError?.action);
2313
+ if (!message || !action) return null;
2314
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2315
+ return {
2316
+ kind: "summary",
2317
+ status: "failed",
2318
+ title: message,
2319
+ description: action,
2320
+ ...resourceLabels.length ? {
2321
+ details: [
2322
+ { label: "Affected", value: resourceLabels.join(", ") }
2323
+ ]
2324
+ } : {}
2325
+ };
2326
+ }
2327
+ };
2328
+ }
2305
2329
  function asRecord3(value) {
2306
2330
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2307
2331
  }
@@ -2419,6 +2443,7 @@ function fallbackTitleFromKind(kind) {
2419
2443
  return "Saved";
2420
2444
  }
2421
2445
  var builtInVisitorToolResultRegistry = [
2446
+ providerErrorPresenter(),
2422
2447
  bookingPresenter("booking_offer"),
2423
2448
  bookingPresenter("booking_confirmed"),
2424
2449
  bookingPresenter("booking_canceled"),
@@ -2468,7 +2493,7 @@ function finalizeSummaryPresentation(result, proposed) {
2468
2493
  return {
2469
2494
  id: result.callId,
2470
2495
  toolName: result.toolName,
2471
- status: result.status,
2496
+ status: proposed.status ?? result.status,
2472
2497
  kind: "summary",
2473
2498
  title,
2474
2499
  ...description && description !== title ? { description } : {},
@@ -2477,7 +2502,7 @@ function finalizeSummaryPresentation(result, proposed) {
2477
2502
  };
2478
2503
  }
2479
2504
  function presentVisitorToolResult(result, registry = []) {
2480
- const envelope = parseAgentToolResultEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2505
+ const envelope = parseAgentToolResultEnvelope(result.output) ?? providerErrorEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2481
2506
  const proposed = envelope ? resolvePresenterOutput(result, envelope, registry) : null;
2482
2507
  if (proposed?.kind === "booking") {
2483
2508
  return {
@@ -2540,6 +2565,25 @@ function presentVisitorToolResult(result, registry = []) {
2540
2565
  }
2541
2566
  return finalizeSummaryPresentation(result, proposed);
2542
2567
  }
2568
+ function providerErrorEnvelope(output) {
2569
+ const record = asRecord3(output);
2570
+ const providerError = asRecord3(record?.providerError);
2571
+ const message = safeText(providerError?.message);
2572
+ const action = safeText(providerError?.action);
2573
+ if (!message || !action) return null;
2574
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2575
+ return {
2576
+ schemaVersion: "webless.tool-result.v1",
2577
+ output: {
2578
+ providerError: {
2579
+ action,
2580
+ message,
2581
+ ...resourceLabels.length ? { resourceLabels } : {}
2582
+ }
2583
+ },
2584
+ presentationKinds: ["provider_error"]
2585
+ };
2586
+ }
2543
2587
  function legacyBookingEnvelope(output) {
2544
2588
  const card = bookingCardFromActionOutput(output);
2545
2589
  return card ? {
@@ -2847,6 +2891,7 @@ function useAgentChat({
2847
2891
  let streamStarted = Boolean(initialText);
2848
2892
  let streamed = initialText;
2849
2893
  const capturedOffers = [];
2894
+ let bookingConfirmed = false;
2850
2895
  let capturedInputCount = 0;
2851
2896
  const handlers = {
2852
2897
  onWork: (item) => {
@@ -2871,6 +2916,7 @@ function useAgentChat({
2871
2916
  }
2872
2917
  if (!isActiveRun()) return;
2873
2918
  if (card.type === "booking_confirmed") {
2919
+ bookingConfirmed = true;
2874
2920
  pendingBookingRef.current = card;
2875
2921
  savePendingWidgetBooking(
2876
2922
  resolvedStorageKeyPrefix,
@@ -2946,7 +2992,10 @@ function useAgentChat({
2946
2992
  initialText,
2947
2993
  message: visitorText,
2948
2994
  signal
2949
- }) : await clientRef.current.sendTurn(visitorText, { handlers, signal });
2995
+ }) : await clientRef.current.sendTurn(visitorText, {
2996
+ handlers,
2997
+ signal
2998
+ });
2950
2999
  if (resume && finalText === null) {
2951
3000
  finalText = await clientRef.current.sendTurn(visitorText, {
2952
3001
  handlers,
@@ -2965,6 +3014,7 @@ function useAgentChat({
2965
3014
  const parsedCards = extractToolCards(displayText);
2966
3015
  for (const card of parsedCards) {
2967
3016
  if (card.type === "booking_confirmed") {
3017
+ bookingConfirmed = true;
2968
3018
  pendingBookingRef.current = card;
2969
3019
  savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
2970
3020
  }
@@ -2979,7 +3029,7 @@ function useAgentChat({
2979
3029
  messages: appendAgentTurnMessage(prev.messages, displayText),
2980
3030
  toolSteps: completeActivePlanning(prev.toolSteps),
2981
3031
  streamingText: "",
2982
- pendingOffer: capturedOffers.at(-1) ?? prev.pendingOffer,
3032
+ pendingOffer: bookingConfirmed ? null : capturedOffers.at(-1) ?? prev.pendingOffer,
2983
3033
  pendingInputs: (prev.pendingInputs ?? []).filter(
2984
3034
  isChatCollectibleInputRequest
2985
3035
  ),
@@ -3005,7 +3055,6 @@ function useAgentChat({
3005
3055
  } : step
3006
3056
  ),
3007
3057
  streamingText: "",
3008
- pendingOffer: null,
3009
3058
  error: message
3010
3059
  }));
3011
3060
  runRef.current = null;
@@ -3113,7 +3162,7 @@ ${outgoing}` : outgoing;
3113
3162
  journey: null,
3114
3163
  followUps: [],
3115
3164
  streamingText: "",
3116
- pendingOffer: null,
3165
+ pendingOffer: options?.preservePendingOffer ? prev.pendingOffer : null,
3117
3166
  pendingInputs: [],
3118
3167
  toolResults: [],
3119
3168
  error: null
@@ -3149,7 +3198,6 @@ ${outgoing}` : outgoing;
3149
3198
  journey: null,
3150
3199
  followUps: [],
3151
3200
  streamingText: "",
3152
- pendingOffer: null,
3153
3201
  pendingInputs: [],
3154
3202
  toolResults: [],
3155
3203
  error: null
@@ -3767,6 +3815,7 @@ function BookingCardLoader() {
3767
3815
  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" }) });
3768
3816
  }
3769
3817
  function BookingCard({
3818
+ disabled = false,
3770
3819
  offer,
3771
3820
  onBook
3772
3821
  }) {
@@ -3778,7 +3827,14 @@ function BookingCard({
3778
3827
  const [startTime, setStartTime] = (0, import_react7.useState)("");
3779
3828
  const [name, setName] = (0, import_react7.useState)("");
3780
3829
  const [email, setEmail] = (0, import_react7.useState)("");
3830
+ const activeStepRef = (0, import_react7.useRef)(null);
3831
+ const previousStepRef = (0, import_react7.useRef)(step);
3781
3832
  const stepIndex = BOOKING_STEPS.findIndex((item) => item.id === step);
3833
+ (0, import_react7.useEffect)(() => {
3834
+ if (previousStepRef.current === step) return;
3835
+ previousStepRef.current = step;
3836
+ activeStepRef.current?.scrollIntoView({ block: "nearest" });
3837
+ }, [step]);
3782
3838
  const slots = (0, import_react7.useMemo)(
3783
3839
  () => bookingSlotsForEventType(offer.slots, eventTypeUri),
3784
3840
  [eventTypeUri, offer.slots]
@@ -3855,216 +3911,230 @@ function BookingCard({
3855
3911
  })
3856
3912
  });
3857
3913
  }
3858
- 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: [
3859
- /* @__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)(
3860
- "li",
3861
- {
3862
- className: [
3863
- "booking-card__step-indicator",
3864
- index === stepIndex ? "booking-card__step-indicator--active" : "",
3865
- index < stepIndex ? "booking-card__step-indicator--complete" : ""
3866
- ].filter(Boolean).join(" "),
3867
- "aria-current": index === stepIndex ? "step" : void 0,
3868
- children: [
3869
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
3870
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label })
3871
- ]
3872
- },
3873
- item.id
3874
- )) }),
3875
- step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", children: [
3876
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3877
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3878
- "Times in ",
3879
- timeZone
3880
- ] }) : null,
3881
- offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3882
- "label",
3883
- {
3884
- className: "booking-card__field",
3885
- htmlFor: `${fieldId}-type`,
3886
- children: [
3887
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Meeting" }),
3914
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3915
+ "section",
3916
+ {
3917
+ className: "booking-card",
3918
+ "aria-busy": disabled || void 0,
3919
+ "aria-label": "Book a meeting",
3920
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3921
+ /* @__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)(
3922
+ "li",
3923
+ {
3924
+ className: [
3925
+ "booking-card__step-indicator",
3926
+ index === stepIndex ? "booking-card__step-indicator--active" : "",
3927
+ index < stepIndex ? "booking-card__step-indicator--complete" : ""
3928
+ ].filter(Boolean).join(" "),
3929
+ "aria-current": index === stepIndex ? "step" : void 0,
3930
+ children: [
3931
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
3932
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label })
3933
+ ]
3934
+ },
3935
+ item.id
3936
+ )) }),
3937
+ step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3938
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3939
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3940
+ "Times in ",
3941
+ timeZone
3942
+ ] }) : null,
3943
+ offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3944
+ "label",
3945
+ {
3946
+ className: "booking-card__field",
3947
+ htmlFor: `${fieldId}-type`,
3948
+ children: [
3949
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Meeting" }),
3950
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3951
+ "select",
3952
+ {
3953
+ id: `${fieldId}-type`,
3954
+ value: eventTypeUri,
3955
+ disabled,
3956
+ onChange: (event) => selectEventType(event.target.value),
3957
+ children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: item.uri, children: item.name }, item.uri))
3958
+ }
3959
+ )
3960
+ ]
3961
+ }
3962
+ ) : null,
3963
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__month", children: [
3888
3964
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3889
- "select",
3965
+ "button",
3890
3966
  {
3891
- id: `${fieldId}-type`,
3892
- value: eventTypeUri,
3893
- onChange: (event) => selectEventType(event.target.value),
3894
- children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: item.uri, children: item.name }, item.uri))
3967
+ type: "button",
3968
+ className: "booking-card__nav",
3969
+ "aria-label": "Previous month",
3970
+ disabled: disabled || !canPrevMonth,
3971
+ onClick: () => goToMonth(-1),
3972
+ children: "\u2039"
3973
+ }
3974
+ ),
3975
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3976
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3977
+ "button",
3978
+ {
3979
+ type: "button",
3980
+ className: "booking-card__nav",
3981
+ "aria-label": "Next month",
3982
+ disabled: disabled || !canNextMonth,
3983
+ onClick: () => goToMonth(1),
3984
+ children: "\u203A"
3895
3985
  }
3896
3986
  )
3897
- ]
3898
- }
3899
- ) : null,
3900
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__month", children: [
3901
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3902
- "button",
3903
- {
3904
- type: "button",
3905
- className: "booking-card__nav",
3906
- "aria-label": "Previous month",
3907
- disabled: !canPrevMonth,
3908
- onClick: () => goToMonth(-1),
3909
- children: "\u2039"
3910
- }
3911
- ),
3912
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3913
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3914
- "button",
3915
- {
3916
- type: "button",
3917
- className: "booking-card__nav",
3918
- "aria-label": "Next month",
3919
- disabled: !canNextMonth,
3920
- onClick: () => goToMonth(1),
3921
- children: "\u203A"
3922
- }
3923
- )
3924
- ] }),
3925
- /* @__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)) }),
3926
- offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3927
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3928
- "div",
3929
- {
3930
- className: "booking-card__calendar",
3931
- role: "grid",
3932
- "aria-label": "Available dates",
3933
- children: cells.map((cell, index) => {
3934
- if (!cell) {
3935
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3936
- "span",
3937
- {
3938
- className: "booking-card__day"
3939
- },
3940
- `empty-${index}`
3941
- );
3987
+ ] }),
3988
+ /* @__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)) }),
3989
+ offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3990
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3991
+ "div",
3992
+ {
3993
+ className: "booking-card__calendar",
3994
+ role: "grid",
3995
+ "aria-label": "Available dates",
3996
+ children: cells.map((cell, index) => {
3997
+ if (!cell) {
3998
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3999
+ "span",
4000
+ {
4001
+ className: "booking-card__day"
4002
+ },
4003
+ `empty-${index}`
4004
+ );
4005
+ }
4006
+ const available = availableByDate.has(cell.key);
4007
+ const selected = cell.key === selectedDate;
4008
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4009
+ "button",
4010
+ {
4011
+ type: "button",
4012
+ className: [
4013
+ "booking-card__day",
4014
+ available ? "booking-card__day--available" : "",
4015
+ selected ? "booking-card__day--selected" : ""
4016
+ ].filter(Boolean).join(" "),
4017
+ disabled: disabled || !available,
4018
+ "aria-pressed": selected,
4019
+ onClick: () => selectDate(cell.key),
4020
+ children: cell.day
4021
+ },
4022
+ cell.key
4023
+ );
4024
+ })
3942
4025
  }
3943
- const available = availableByDate.has(cell.key);
3944
- const selected = cell.key === selectedDate;
3945
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4026
+ )
4027
+ ] }, "date") : null,
4028
+ step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4029
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
4030
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3946
4031
  "button",
3947
4032
  {
3948
4033
  type: "button",
3949
- className: [
3950
- "booking-card__day",
3951
- available ? "booking-card__day--available" : "",
3952
- selected ? "booking-card__day--selected" : ""
3953
- ].filter(Boolean).join(" "),
3954
- disabled: !available,
3955
- "aria-pressed": selected,
3956
- onClick: () => selectDate(cell.key),
3957
- children: cell.day
3958
- },
3959
- cell.key
3960
- );
3961
- })
3962
- }
3963
- )
3964
- ] }, "date") : null,
3965
- step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", children: [
3966
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
3967
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3968
- "button",
3969
- {
3970
- type: "button",
3971
- className: "booking-card__nav",
3972
- "aria-label": "Back to dates",
3973
- onClick: () => setStep("date"),
3974
- children: "\u2039"
3975
- }
3976
- ),
3977
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
3978
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3979
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3980
- "Times in ",
3981
- timeZone
3982
- ] }) : null
3983
- ] })
3984
- ] }),
3985
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3986
- "button",
3987
- {
3988
- type: "button",
3989
- className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
3990
- onClick: () => selectTime(slot.startTime),
3991
- children: formatTimeChip(slot.startTime)
3992
- },
3993
- slot.startTime
3994
- )) })
3995
- ] }, "time") : null,
3996
- step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", children: [
3997
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
3998
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3999
- "button",
4000
- {
4001
- type: "button",
4002
- className: "booking-card__nav",
4003
- "aria-label": "Back to times",
4004
- onClick: () => setStep("time"),
4005
- children: "\u2039"
4006
- }
4007
- ),
4008
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4009
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4010
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4011
- selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4012
- ] })
4013
- ] }),
4014
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__identity", children: [
4015
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4016
- "label",
4017
- {
4018
- className: "booking-card__field",
4019
- htmlFor: `${fieldId}-name`,
4020
- children: [
4021
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Name" }),
4022
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4023
- "input",
4024
- {
4025
- id: `${fieldId}-name`,
4026
- autoComplete: "name",
4027
- value: name,
4028
- onChange: (event) => setName(event.target.value),
4029
- required: true
4030
- }
4031
- )
4032
- ]
4033
- }
4034
- ),
4035
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4036
- "label",
4037
- {
4038
- className: "booking-card__field",
4039
- htmlFor: `${fieldId}-email`,
4040
- children: [
4041
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Email" }),
4042
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4043
- "input",
4044
- {
4045
- id: `${fieldId}-email`,
4046
- type: "email",
4047
- autoComplete: "email",
4048
- value: email,
4049
- onChange: (event) => setEmail(event.target.value),
4050
- required: true
4051
- }
4052
- )
4053
- ]
4054
- }
4055
- )
4056
- ] }),
4057
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4058
- "button",
4059
- {
4060
- type: "submit",
4061
- className: "booking-card__submit",
4062
- disabled: !name.trim() || !email.trim(),
4063
- children: "Book this time"
4064
- }
4065
- )
4066
- ] }, "details") : null
4067
- ] }) });
4034
+ className: "booking-card__nav",
4035
+ "aria-label": "Back to dates",
4036
+ disabled,
4037
+ onClick: () => setStep("date"),
4038
+ children: "\u2039"
4039
+ }
4040
+ ),
4041
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4042
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
4043
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
4044
+ "Times in ",
4045
+ timeZone
4046
+ ] }) : null
4047
+ ] })
4048
+ ] }),
4049
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4050
+ "button",
4051
+ {
4052
+ type: "button",
4053
+ className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
4054
+ disabled,
4055
+ onClick: () => selectTime(slot.startTime),
4056
+ children: formatTimeChip(slot.startTime)
4057
+ },
4058
+ slot.startTime
4059
+ )) })
4060
+ ] }, "time") : null,
4061
+ step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4062
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
4063
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4064
+ "button",
4065
+ {
4066
+ type: "button",
4067
+ className: "booking-card__nav",
4068
+ "aria-label": "Back to times",
4069
+ disabled,
4070
+ onClick: () => setStep("time"),
4071
+ children: "\u2039"
4072
+ }
4073
+ ),
4074
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4075
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4076
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4077
+ selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4078
+ ] })
4079
+ ] }),
4080
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__identity", children: [
4081
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4082
+ "label",
4083
+ {
4084
+ className: "booking-card__field",
4085
+ htmlFor: `${fieldId}-name`,
4086
+ children: [
4087
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Name" }),
4088
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4089
+ "input",
4090
+ {
4091
+ id: `${fieldId}-name`,
4092
+ autoComplete: "name",
4093
+ disabled,
4094
+ value: name,
4095
+ onChange: (event) => setName(event.target.value),
4096
+ required: true
4097
+ }
4098
+ )
4099
+ ]
4100
+ }
4101
+ ),
4102
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4103
+ "label",
4104
+ {
4105
+ className: "booking-card__field",
4106
+ htmlFor: `${fieldId}-email`,
4107
+ children: [
4108
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Email" }),
4109
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4110
+ "input",
4111
+ {
4112
+ id: `${fieldId}-email`,
4113
+ type: "email",
4114
+ autoComplete: "email",
4115
+ disabled,
4116
+ value: email,
4117
+ onChange: (event) => setEmail(event.target.value),
4118
+ required: true
4119
+ }
4120
+ )
4121
+ ]
4122
+ }
4123
+ )
4124
+ ] }),
4125
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4126
+ "button",
4127
+ {
4128
+ type: "submit",
4129
+ className: "booking-card__submit",
4130
+ disabled: disabled || !name.trim() || !email.trim(),
4131
+ children: disabled ? "Booking\u2026" : "Book this time"
4132
+ }
4133
+ )
4134
+ ] }, "details") : null
4135
+ ] })
4136
+ }
4137
+ );
4068
4138
  }
4069
4139
 
4070
4140
  // src/react/components/MessageBubble/MessageBubble.tsx
@@ -4081,9 +4151,7 @@ function paragraphsAreNearDuplicates(first, second) {
4081
4151
  if (left === right) return true;
4082
4152
  const shorter = left.length <= right.length ? left : right;
4083
4153
  const longer = left.length <= right.length ? right : left;
4084
- return longer.startsWith(
4085
- shorter.slice(0, Math.floor(shorter.length * 0.85))
4086
- );
4154
+ return longer.startsWith(shorter.slice(0, Math.floor(shorter.length * 0.85)));
4087
4155
  }
4088
4156
  function paragraphsShareOpening(first, second) {
4089
4157
  const opening = first.split("\n")[0]?.trim();
@@ -4111,6 +4179,7 @@ function collapseRepeatedText(text) {
4111
4179
  function MessageBubble({
4112
4180
  message,
4113
4181
  brandLogoUrl,
4182
+ bookingDisabled = false,
4114
4183
  offer,
4115
4184
  onBook
4116
4185
  }) {
@@ -4146,18 +4215,17 @@ function MessageBubble({
4146
4215
  children: displayText
4147
4216
  }
4148
4217
  ),
4149
- 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)(
4150
- "a",
4151
- {
4152
- href: citation.url,
4153
- target: "_blank",
4154
- rel: "noreferrer",
4155
- children: [
4156
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "message-bubble__source-icon", "aria-hidden": "true", children: "\u25A6" }),
4157
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: citation.label })
4158
- ]
4159
- }
4160
- ) }, citation.id)) }) : null
4218
+ 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)("a", { href: citation.url, target: "_blank", rel: "noreferrer", children: [
4219
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4220
+ "span",
4221
+ {
4222
+ className: "message-bubble__source-icon",
4223
+ "aria-hidden": "true",
4224
+ children: "\u25A6"
4225
+ }
4226
+ ),
4227
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: citation.label })
4228
+ ] }) }, citation.id)) }) : null
4161
4229
  ] });
4162
4230
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("article", { className: "message-bubble message-bubble--agent", children: [
4163
4231
  displayText ? showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "message-bubble__agent-row", children: [
@@ -4176,6 +4244,7 @@ function MessageBubble({
4176
4244
  offers.map((nextOffer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4177
4245
  BookingCard,
4178
4246
  {
4247
+ disabled: bookingDisabled,
4179
4248
  offer: nextOffer,
4180
4249
  onBook
4181
4250
  },
@@ -5155,6 +5224,7 @@ function AgentRail({
5155
5224
  MessageBubble,
5156
5225
  {
5157
5226
  message: greeting,
5227
+ bookingDisabled: isBusy,
5158
5228
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5159
5229
  onBook
5160
5230
  }
@@ -5200,6 +5270,7 @@ function AgentRail({
5200
5270
  MessageBubble,
5201
5271
  {
5202
5272
  message,
5273
+ bookingDisabled: isBusy,
5203
5274
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5204
5275
  offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5205
5276
  onBook
@@ -5238,6 +5309,7 @@ function AgentRail({
5238
5309
  MessageBubble,
5239
5310
  {
5240
5311
  message: streamingMessage,
5312
+ bookingDisabled: isBusy,
5241
5313
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5242
5314
  offer: state.pendingOffer,
5243
5315
  onBook
@@ -5624,7 +5696,10 @@ function AgentWidget({
5624
5696
  onInputResponse: (response) => void respondToInput(response),
5625
5697
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5626
5698
  onFollowUpSelect: (label) => void handleSubmit(label),
5627
- onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
5699
+ onBook: (input) => void submit(input.displayText, {
5700
+ preservePendingOffer: true,
5701
+ runtimeText: input.runtimeText
5702
+ })
5628
5703
  }
5629
5704
  )
5630
5705
  }