@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/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
  }) {
@@ -3862,216 +3911,230 @@ function BookingCard({
3862
3911
  })
3863
3912
  });
3864
3913
  }
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" }),
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: [
3895
3964
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3896
- "select",
3965
+ "button",
3897
3966
  {
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))
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"
3902
3985
  }
3903
3986
  )
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",
3922
- {
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
- );
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
+ })
3949
4025
  }
3950
- const available = availableByDate.has(cell.key);
3951
- const selected = cell.key === selectedDate;
3952
- 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)(
3953
4031
  "button",
3954
4032
  {
3955
4033
  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
4058
- }
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
- ] }) });
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
+ );
4075
4138
  }
4076
4139
 
4077
4140
  // src/react/components/MessageBubble/MessageBubble.tsx
@@ -4088,9 +4151,7 @@ function paragraphsAreNearDuplicates(first, second) {
4088
4151
  if (left === right) return true;
4089
4152
  const shorter = left.length <= right.length ? left : right;
4090
4153
  const longer = left.length <= right.length ? right : left;
4091
- return longer.startsWith(
4092
- shorter.slice(0, Math.floor(shorter.length * 0.85))
4093
- );
4154
+ return longer.startsWith(shorter.slice(0, Math.floor(shorter.length * 0.85)));
4094
4155
  }
4095
4156
  function paragraphsShareOpening(first, second) {
4096
4157
  const opening = first.split("\n")[0]?.trim();
@@ -4118,6 +4179,7 @@ function collapseRepeatedText(text) {
4118
4179
  function MessageBubble({
4119
4180
  message,
4120
4181
  brandLogoUrl,
4182
+ bookingDisabled = false,
4121
4183
  offer,
4122
4184
  onBook
4123
4185
  }) {
@@ -4153,18 +4215,17 @@ function MessageBubble({
4153
4215
  children: displayText
4154
4216
  }
4155
4217
  ),
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
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
4168
4229
  ] });
4169
4230
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("article", { className: "message-bubble message-bubble--agent", children: [
4170
4231
  displayText ? showBrandLogo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "message-bubble__agent-row", children: [
@@ -4183,6 +4244,7 @@ function MessageBubble({
4183
4244
  offers.map((nextOffer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4184
4245
  BookingCard,
4185
4246
  {
4247
+ disabled: bookingDisabled,
4186
4248
  offer: nextOffer,
4187
4249
  onBook
4188
4250
  },
@@ -5162,6 +5224,7 @@ function AgentRail({
5162
5224
  MessageBubble,
5163
5225
  {
5164
5226
  message: greeting,
5227
+ bookingDisabled: isBusy,
5165
5228
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5166
5229
  onBook
5167
5230
  }
@@ -5207,6 +5270,7 @@ function AgentRail({
5207
5270
  MessageBubble,
5208
5271
  {
5209
5272
  message,
5273
+ bookingDisabled: isBusy,
5210
5274
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5211
5275
  offer: index === lastAgentIndex ? state.pendingOffer : void 0,
5212
5276
  onBook
@@ -5245,6 +5309,7 @@ function AgentRail({
5245
5309
  MessageBubble,
5246
5310
  {
5247
5311
  message: streamingMessage,
5312
+ bookingDisabled: isBusy,
5248
5313
  brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
5249
5314
  offer: state.pendingOffer,
5250
5315
  onBook
@@ -5631,7 +5696,10 @@ function AgentWidget({
5631
5696
  onInputResponse: (response) => void respondToInput(response),
5632
5697
  onToolInput: (surface, values) => void respondToToolInput(surface, values),
5633
5698
  onFollowUpSelect: (label) => void handleSubmit(label),
5634
- onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
5699
+ onBook: (input) => void submit(input.displayText, {
5700
+ preservePendingOffer: true,
5701
+ runtimeText: input.runtimeText
5702
+ })
5635
5703
  }
5636
5704
  )
5637
5705
  }