@webless/agent 0.6.10 → 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/react.cjs CHANGED
@@ -2278,6 +2278,30 @@ function bookingPresenter(kind) {
2278
2278
  }
2279
2279
  };
2280
2280
  }
2281
+ function providerErrorPresenter() {
2282
+ return {
2283
+ kind: "provider_error",
2284
+ present: ({ envelope }) => {
2285
+ const output = asRecord3(envelope.output);
2286
+ const providerError = asRecord3(output?.providerError);
2287
+ const message = safeText(providerError?.message);
2288
+ const action = safeText(providerError?.action);
2289
+ if (!message || !action) return null;
2290
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2291
+ return {
2292
+ kind: "summary",
2293
+ status: "failed",
2294
+ title: message,
2295
+ description: action,
2296
+ ...resourceLabels.length ? {
2297
+ details: [
2298
+ { label: "Affected", value: resourceLabels.join(", ") }
2299
+ ]
2300
+ } : {}
2301
+ };
2302
+ }
2303
+ };
2304
+ }
2281
2305
  function asRecord3(value) {
2282
2306
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2283
2307
  }
@@ -2395,6 +2419,7 @@ function fallbackTitleFromKind(kind) {
2395
2419
  return "Saved";
2396
2420
  }
2397
2421
  var builtInVisitorToolResultRegistry = [
2422
+ providerErrorPresenter(),
2398
2423
  bookingPresenter("booking_offer"),
2399
2424
  bookingPresenter("booking_confirmed"),
2400
2425
  bookingPresenter("booking_canceled"),
@@ -2444,7 +2469,7 @@ function finalizeSummaryPresentation(result, proposed) {
2444
2469
  return {
2445
2470
  id: result.callId,
2446
2471
  toolName: result.toolName,
2447
- status: result.status,
2472
+ status: proposed.status ?? result.status,
2448
2473
  kind: "summary",
2449
2474
  title,
2450
2475
  ...description && description !== title ? { description } : {},
@@ -2453,7 +2478,7 @@ function finalizeSummaryPresentation(result, proposed) {
2453
2478
  };
2454
2479
  }
2455
2480
  function presentVisitorToolResult(result, registry = []) {
2456
- const envelope = parseAgentToolResultEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2481
+ const envelope = parseAgentToolResultEnvelope(result.output) ?? providerErrorEnvelope(result.output) ?? legacyBookingEnvelope(result.output);
2457
2482
  const proposed = envelope ? resolvePresenterOutput(result, envelope, registry) : null;
2458
2483
  if (proposed?.kind === "booking") {
2459
2484
  return {
@@ -2516,6 +2541,25 @@ function presentVisitorToolResult(result, registry = []) {
2516
2541
  }
2517
2542
  return finalizeSummaryPresentation(result, proposed);
2518
2543
  }
2544
+ function providerErrorEnvelope(output) {
2545
+ const record = asRecord3(output);
2546
+ const providerError = asRecord3(record?.providerError);
2547
+ const message = safeText(providerError?.message);
2548
+ const action = safeText(providerError?.action);
2549
+ if (!message || !action) return null;
2550
+ const resourceLabels = Array.isArray(providerError?.resourceLabels) ? providerError.resourceLabels.map(safeText).filter(Boolean).slice(0, MAX_DETAILS) : [];
2551
+ return {
2552
+ schemaVersion: "webless.tool-result.v1",
2553
+ output: {
2554
+ providerError: {
2555
+ action,
2556
+ message,
2557
+ ...resourceLabels.length ? { resourceLabels } : {}
2558
+ }
2559
+ },
2560
+ presentationKinds: ["provider_error"]
2561
+ };
2562
+ }
2519
2563
  function legacyBookingEnvelope(output) {
2520
2564
  const card = bookingCardFromActionOutput(output);
2521
2565
  return card ? {
@@ -2823,6 +2867,7 @@ function useAgentChat({
2823
2867
  let streamStarted = Boolean(initialText);
2824
2868
  let streamed = initialText;
2825
2869
  const capturedOffers = [];
2870
+ let bookingConfirmed = false;
2826
2871
  let capturedInputCount = 0;
2827
2872
  const handlers = {
2828
2873
  onWork: (item) => {
@@ -2847,6 +2892,7 @@ function useAgentChat({
2847
2892
  }
2848
2893
  if (!isActiveRun()) return;
2849
2894
  if (card.type === "booking_confirmed") {
2895
+ bookingConfirmed = true;
2850
2896
  pendingBookingRef.current = card;
2851
2897
  savePendingWidgetBooking(
2852
2898
  resolvedStorageKeyPrefix,
@@ -2922,7 +2968,10 @@ function useAgentChat({
2922
2968
  initialText,
2923
2969
  message: visitorText,
2924
2970
  signal
2925
- }) : await clientRef.current.sendTurn(visitorText, { handlers, signal });
2971
+ }) : await clientRef.current.sendTurn(visitorText, {
2972
+ handlers,
2973
+ signal
2974
+ });
2926
2975
  if (resume && finalText === null) {
2927
2976
  finalText = await clientRef.current.sendTurn(visitorText, {
2928
2977
  handlers,
@@ -2941,6 +2990,7 @@ function useAgentChat({
2941
2990
  const parsedCards = extractToolCards(displayText);
2942
2991
  for (const card of parsedCards) {
2943
2992
  if (card.type === "booking_confirmed") {
2993
+ bookingConfirmed = true;
2944
2994
  pendingBookingRef.current = card;
2945
2995
  savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
2946
2996
  }
@@ -2955,7 +3005,7 @@ function useAgentChat({
2955
3005
  messages: appendAgentTurnMessage(prev.messages, displayText),
2956
3006
  toolSteps: completeActivePlanning(prev.toolSteps),
2957
3007
  streamingText: "",
2958
- pendingOffer: capturedOffers.at(-1) ?? prev.pendingOffer,
3008
+ pendingOffer: bookingConfirmed ? null : capturedOffers.at(-1) ?? prev.pendingOffer,
2959
3009
  pendingInputs: (prev.pendingInputs ?? []).filter(
2960
3010
  isChatCollectibleInputRequest
2961
3011
  ),
@@ -2981,7 +3031,6 @@ function useAgentChat({
2981
3031
  } : step
2982
3032
  ),
2983
3033
  streamingText: "",
2984
- pendingOffer: null,
2985
3034
  error: message
2986
3035
  }));
2987
3036
  runRef.current = null;
@@ -3089,7 +3138,7 @@ ${outgoing}` : outgoing;
3089
3138
  journey: null,
3090
3139
  followUps: [],
3091
3140
  streamingText: "",
3092
- pendingOffer: null,
3141
+ pendingOffer: options?.preservePendingOffer ? prev.pendingOffer : null,
3093
3142
  pendingInputs: [],
3094
3143
  toolResults: [],
3095
3144
  error: null
@@ -3125,7 +3174,6 @@ ${outgoing}` : outgoing;
3125
3174
  journey: null,
3126
3175
  followUps: [],
3127
3176
  streamingText: "",
3128
- pendingOffer: null,
3129
3177
  pendingInputs: [],
3130
3178
  toolResults: [],
3131
3179
  error: null
@@ -3759,6 +3807,7 @@ function BookingCardLoader() {
3759
3807
  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" }) });
3760
3808
  }
3761
3809
  function BookingCard({
3810
+ disabled = false,
3762
3811
  offer,
3763
3812
  onBook
3764
3813
  }) {
@@ -3854,216 +3903,230 @@ function BookingCard({
3854
3903
  })
3855
3904
  });
3856
3905
  }
3857
- 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: [
3858
- /* @__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)(
3859
- "li",
3860
- {
3861
- className: [
3862
- "booking-card__step-indicator",
3863
- index === stepIndex ? "booking-card__step-indicator--active" : "",
3864
- index < stepIndex ? "booking-card__step-indicator--complete" : ""
3865
- ].filter(Boolean).join(" "),
3866
- "aria-current": index === stepIndex ? "step" : void 0,
3867
- children: [
3868
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
3869
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label })
3870
- ]
3871
- },
3872
- item.id
3873
- )) }),
3874
- step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3875
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3876
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3877
- "Times in ",
3878
- timeZone
3879
- ] }) : null,
3880
- offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3881
- "label",
3882
- {
3883
- className: "booking-card__field",
3884
- htmlFor: `${fieldId}-type`,
3885
- children: [
3886
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Meeting" }),
3906
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3907
+ "section",
3908
+ {
3909
+ className: "booking-card",
3910
+ "aria-busy": disabled || void 0,
3911
+ "aria-label": "Book a meeting",
3912
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
3913
+ /* @__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)(
3914
+ "li",
3915
+ {
3916
+ className: [
3917
+ "booking-card__step-indicator",
3918
+ index === stepIndex ? "booking-card__step-indicator--active" : "",
3919
+ index < stepIndex ? "booking-card__step-indicator--complete" : ""
3920
+ ].filter(Boolean).join(" "),
3921
+ "aria-current": index === stepIndex ? "step" : void 0,
3922
+ children: [
3923
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: index + 1 }),
3924
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label })
3925
+ ]
3926
+ },
3927
+ item.id
3928
+ )) }),
3929
+ step === "date" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3930
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
3931
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3932
+ "Times in ",
3933
+ timeZone
3934
+ ] }) : null,
3935
+ offer.eventTypes.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3936
+ "label",
3937
+ {
3938
+ className: "booking-card__field",
3939
+ htmlFor: `${fieldId}-type`,
3940
+ children: [
3941
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Meeting" }),
3942
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3943
+ "select",
3944
+ {
3945
+ id: `${fieldId}-type`,
3946
+ value: eventTypeUri,
3947
+ disabled,
3948
+ onChange: (event) => selectEventType(event.target.value),
3949
+ children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: item.uri, children: item.name }, item.uri))
3950
+ }
3951
+ )
3952
+ ]
3953
+ }
3954
+ ) : null,
3955
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__month", children: [
3887
3956
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3888
- "select",
3957
+ "button",
3889
3958
  {
3890
- id: `${fieldId}-type`,
3891
- value: eventTypeUri,
3892
- onChange: (event) => selectEventType(event.target.value),
3893
- children: offer.eventTypes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: item.uri, children: item.name }, item.uri))
3959
+ type: "button",
3960
+ className: "booking-card__nav",
3961
+ "aria-label": "Previous month",
3962
+ disabled: disabled || !canPrevMonth,
3963
+ onClick: () => goToMonth(-1),
3964
+ children: "\u2039"
3965
+ }
3966
+ ),
3967
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3968
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3969
+ "button",
3970
+ {
3971
+ type: "button",
3972
+ className: "booking-card__nav",
3973
+ "aria-label": "Next month",
3974
+ disabled: disabled || !canNextMonth,
3975
+ onClick: () => goToMonth(1),
3976
+ children: "\u203A"
3894
3977
  }
3895
3978
  )
3896
- ]
3897
- }
3898
- ) : null,
3899
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__month", children: [
3900
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3901
- "button",
3902
- {
3903
- type: "button",
3904
- className: "booking-card__nav",
3905
- "aria-label": "Previous month",
3906
- disabled: !canPrevMonth,
3907
- onClick: () => goToMonth(-1),
3908
- children: "\u2039"
3909
- }
3910
- ),
3911
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
3912
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3913
- "button",
3914
- {
3915
- type: "button",
3916
- className: "booking-card__nav",
3917
- "aria-label": "Next month",
3918
- disabled: !canNextMonth,
3919
- onClick: () => goToMonth(1),
3920
- children: "\u203A"
3921
- }
3922
- )
3923
- ] }),
3924
- /* @__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)) }),
3925
- offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3926
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3927
- "div",
3928
- {
3929
- className: "booking-card__calendar",
3930
- role: "grid",
3931
- "aria-label": "Available dates",
3932
- children: cells.map((cell, index) => {
3933
- if (!cell) {
3934
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3935
- "span",
3936
- {
3937
- className: "booking-card__day"
3938
- },
3939
- `empty-${index}`
3940
- );
3979
+ ] }),
3980
+ /* @__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)) }),
3981
+ offer.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__loading", role: "status", children: "Finding available times\u2026" }) : null,
3982
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3983
+ "div",
3984
+ {
3985
+ className: "booking-card__calendar",
3986
+ role: "grid",
3987
+ "aria-label": "Available dates",
3988
+ children: cells.map((cell, index) => {
3989
+ if (!cell) {
3990
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3991
+ "span",
3992
+ {
3993
+ className: "booking-card__day"
3994
+ },
3995
+ `empty-${index}`
3996
+ );
3997
+ }
3998
+ const available = availableByDate.has(cell.key);
3999
+ const selected = cell.key === selectedDate;
4000
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4001
+ "button",
4002
+ {
4003
+ type: "button",
4004
+ className: [
4005
+ "booking-card__day",
4006
+ available ? "booking-card__day--available" : "",
4007
+ selected ? "booking-card__day--selected" : ""
4008
+ ].filter(Boolean).join(" "),
4009
+ disabled: disabled || !available,
4010
+ "aria-pressed": selected,
4011
+ onClick: () => selectDate(cell.key),
4012
+ children: cell.day
4013
+ },
4014
+ cell.key
4015
+ );
4016
+ })
3941
4017
  }
3942
- const available = availableByDate.has(cell.key);
3943
- const selected = cell.key === selectedDate;
3944
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4018
+ )
4019
+ ] }, "date") : null,
4020
+ step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4021
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
4022
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3945
4023
  "button",
3946
4024
  {
3947
4025
  type: "button",
3948
- className: [
3949
- "booking-card__day",
3950
- available ? "booking-card__day--available" : "",
3951
- selected ? "booking-card__day--selected" : ""
3952
- ].filter(Boolean).join(" "),
3953
- disabled: !available,
3954
- "aria-pressed": selected,
3955
- onClick: () => selectDate(cell.key),
3956
- children: cell.day
3957
- },
3958
- cell.key
3959
- );
3960
- })
3961
- }
3962
- )
3963
- ] }, "date") : null,
3964
- step === "time" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3965
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
3966
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3967
- "button",
3968
- {
3969
- type: "button",
3970
- className: "booking-card__nav",
3971
- "aria-label": "Back to dates",
3972
- onClick: () => setStep("date"),
3973
- children: "\u2039"
3974
- }
3975
- ),
3976
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
3977
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
3978
- timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
3979
- "Times in ",
3980
- timeZone
3981
- ] }) : null
3982
- ] })
3983
- ] }),
3984
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3985
- "button",
3986
- {
3987
- type: "button",
3988
- className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
3989
- onClick: () => selectTime(slot.startTime),
3990
- children: formatTimeChip(slot.startTime)
3991
- },
3992
- slot.startTime
3993
- )) })
3994
- ] }, "time") : null,
3995
- step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
3996
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
3997
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3998
- "button",
3999
- {
4000
- type: "button",
4001
- className: "booking-card__nav",
4002
- "aria-label": "Back to times",
4003
- onClick: () => setStep("time"),
4004
- children: "\u2039"
4005
- }
4006
- ),
4007
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4008
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4009
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4010
- selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4011
- ] })
4012
- ] }),
4013
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__identity", children: [
4014
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4015
- "label",
4016
- {
4017
- className: "booking-card__field",
4018
- htmlFor: `${fieldId}-name`,
4019
- children: [
4020
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Name" }),
4021
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4022
- "input",
4023
- {
4024
- id: `${fieldId}-name`,
4025
- autoComplete: "name",
4026
- value: name,
4027
- onChange: (event) => setName(event.target.value),
4028
- required: true
4029
- }
4030
- )
4031
- ]
4032
- }
4033
- ),
4034
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4035
- "label",
4036
- {
4037
- className: "booking-card__field",
4038
- htmlFor: `${fieldId}-email`,
4039
- children: [
4040
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Email" }),
4041
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4042
- "input",
4043
- {
4044
- id: `${fieldId}-email`,
4045
- type: "email",
4046
- autoComplete: "email",
4047
- value: email,
4048
- onChange: (event) => setEmail(event.target.value),
4049
- required: true
4050
- }
4051
- )
4052
- ]
4053
- }
4054
- )
4055
- ] }),
4056
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4057
- "button",
4058
- {
4059
- type: "submit",
4060
- className: "booking-card__submit",
4061
- disabled: !name.trim() || !email.trim(),
4062
- children: "Book this time"
4063
- }
4064
- )
4065
- ] }, "details") : null
4066
- ] }) });
4026
+ className: "booking-card__nav",
4027
+ "aria-label": "Back to dates",
4028
+ disabled,
4029
+ onClick: () => setStep("date"),
4030
+ children: "\u2039"
4031
+ }
4032
+ ),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4034
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
4035
+ timeZone ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "booking-card__tz", children: [
4036
+ "Times in ",
4037
+ timeZone
4038
+ ] }) : null
4039
+ ] })
4040
+ ] }),
4041
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4042
+ "button",
4043
+ {
4044
+ type: "button",
4045
+ className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
4046
+ disabled,
4047
+ onClick: () => selectTime(slot.startTime),
4048
+ children: formatTimeChip(slot.startTime)
4049
+ },
4050
+ slot.startTime
4051
+ )) })
4052
+ ] }, "time") : null,
4053
+ step === "details" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step", ref: activeStepRef, children: [
4054
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__step-bar", children: [
4055
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4056
+ "button",
4057
+ {
4058
+ type: "button",
4059
+ className: "booking-card__nav",
4060
+ "aria-label": "Back to times",
4061
+ disabled,
4062
+ onClick: () => setStep("time"),
4063
+ children: "\u2039"
4064
+ }
4065
+ ),
4066
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4067
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__title", children: "Enter details" }),
4068
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
4069
+ selectedType?.location ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "booking-card__tz", children: selectedType.location }) : null
4070
+ ] })
4071
+ ] }),
4072
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "booking-card__identity", children: [
4073
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4074
+ "label",
4075
+ {
4076
+ className: "booking-card__field",
4077
+ htmlFor: `${fieldId}-name`,
4078
+ children: [
4079
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Name" }),
4080
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4081
+ "input",
4082
+ {
4083
+ id: `${fieldId}-name`,
4084
+ autoComplete: "name",
4085
+ disabled,
4086
+ value: name,
4087
+ onChange: (event) => setName(event.target.value),
4088
+ required: true
4089
+ }
4090
+ )
4091
+ ]
4092
+ }
4093
+ ),
4094
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4095
+ "label",
4096
+ {
4097
+ className: "booking-card__field",
4098
+ htmlFor: `${fieldId}-email`,
4099
+ children: [
4100
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Email" }),
4101
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4102
+ "input",
4103
+ {
4104
+ id: `${fieldId}-email`,
4105
+ type: "email",
4106
+ autoComplete: "email",
4107
+ disabled,
4108
+ value: email,
4109
+ onChange: (event) => setEmail(event.target.value),
4110
+ required: true
4111
+ }
4112
+ )
4113
+ ]
4114
+ }
4115
+ )
4116
+ ] }),
4117
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4118
+ "button",
4119
+ {
4120
+ type: "submit",
4121
+ className: "booking-card__submit",
4122
+ disabled: disabled || !name.trim() || !email.trim(),
4123
+ children: disabled ? "Booking\u2026" : "Book this time"
4124
+ }
4125
+ )
4126
+ ] }, "details") : null
4127
+ ] })
4128
+ }
4129
+ );
4067
4130
  }
4068
4131
 
4069
4132
  // src/react/components/MessageBubble/MessageBubble.tsx
@@ -4080,9 +4143,7 @@ function paragraphsAreNearDuplicates(first, second) {
4080
4143
  if (left === right) return true;
4081
4144
  const shorter = left.length <= right.length ? left : right;
4082
4145
  const longer = left.length <= right.length ? right : left;
4083
- return longer.startsWith(
4084
- shorter.slice(0, Math.floor(shorter.length * 0.85))
4085
- );
4146
+ return longer.startsWith(shorter.slice(0, Math.floor(shorter.length * 0.85)));
4086
4147
  }
4087
4148
  function paragraphsShareOpening(first, second) {
4088
4149
  const opening = first.split("\n")[0]?.trim();
@@ -4110,6 +4171,7 @@ function collapseRepeatedText(text) {
4110
4171
  function MessageBubble({
4111
4172
  message,
4112
4173
  brandLogoUrl,
4174
+ bookingDisabled = false,
4113
4175
  offer,
4114
4176
  onBook
4115
4177
  }) {
@@ -4145,18 +4207,17 @@ function MessageBubble({
4145
4207
  children: displayText
4146
4208
  }
4147
4209
  ),
4148
- 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)(
4149
- "a",
4150
- {
4151
- href: citation.url,
4152
- target: "_blank",
4153
- rel: "noreferrer",
4154
- children: [
4155
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "message-bubble__source-icon", "aria-hidden": "true", children: "\u25A6" }),
4156
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: citation.label })
4157
- ]
4158
- }
4159
- ) }, citation.id)) }) : null
4210
+ 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: [
4211
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4212
+ "span",
4213
+ {
4214
+ className: "message-bubble__source-icon",
4215
+ "aria-hidden": "true",
4216
+ children: "\u25A6"
4217
+ }
4218
+ ),
4219
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: citation.label })
4220
+ ] }) }, citation.id)) }) : null
4160
4221
  ] });
4161
4222
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("article", { className: "message-bubble message-bubble--agent", children: [
4162
4223
  displayText ? showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "message-bubble__agent-row", children: [
@@ -4175,6 +4236,7 @@ function MessageBubble({
4175
4236
  offers.map((nextOffer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4176
4237
  BookingCard,
4177
4238
  {
4239
+ disabled: bookingDisabled,
4178
4240
  offer: nextOffer,
4179
4241
  onBook
4180
4242
  },
@@ -5154,6 +5216,7 @@ function AgentRail({
5154
5216
  MessageBubble,
5155
5217
  {
5156
5218
  message: greeting,
5219
+ bookingDisabled: isBusy,
5157
5220
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5158
5221
  onBook
5159
5222
  }
@@ -5199,6 +5262,7 @@ function AgentRail({
5199
5262
  MessageBubble,
5200
5263
  {
5201
5264
  message,
5265
+ bookingDisabled: isBusy,
5202
5266
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5203
5267
  offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5204
5268
  onBook
@@ -5237,6 +5301,7 @@ function AgentRail({
5237
5301
  MessageBubble,
5238
5302
  {
5239
5303
  message: streamingMessage,
5304
+ bookingDisabled: isBusy,
5240
5305
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5241
5306
  offer: state.pendingOffer,
5242
5307
  onBook
@@ -5623,7 +5688,10 @@ function AgentWidget({
5623
5688
  onInputResponse: (response) => void respondToInput(response),
5624
5689
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5625
5690
  onFollowUpSelect: (label) => void handleSubmit(label),
5626
- onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
5691
+ onBook: (input) => void submit(input.displayText, {
5692
+ preservePendingOffer: true,
5693
+ runtimeText: input.runtimeText
5694
+ })
5627
5695
  }
5628
5696
  )
5629
5697
  }