@webless/agent 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-SVWXFDV3.js → chunk-E4JSTYPX.js} +881 -212
- package/dist/chunk-E4JSTYPX.js.map +1 -0
- package/dist/embed.cjs +891 -226
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.css +244 -64
- package/dist/embed.css.map +1 -1
- package/dist/embed.d.cts +2 -2
- package/dist/embed.d.ts +2 -2
- package/dist/embed.js +5 -2
- package/dist/embed.js.map +1 -1
- package/dist/index.cjs +39 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +39 -2
- package/dist/index.js.map +1 -1
- package/dist/{manifest-C8l7WUf6.d.cts → manifest-Zln88OPl.d.cts} +4 -1
- package/dist/{manifest-C8l7WUf6.d.ts → manifest-Zln88OPl.d.ts} +4 -1
- package/dist/react.cjs +883 -214
- package/dist/react.cjs.map +1 -1
- package/dist/react.css +244 -64
- package/dist/react.css.map +1 -1
- package/dist/react.d.cts +37 -4
- package/dist/react.d.ts +37 -4
- package/dist/react.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-SVWXFDV3.js.map +0 -1
|
@@ -188,6 +188,9 @@ function runtimeSessionIdKey(visitorSessionId, prefix) {
|
|
|
188
188
|
function runtimeStreamIndexKey(visitorSessionId, prefix) {
|
|
189
189
|
return `${prefix}:eve:${visitorSessionId}:streamIndex`;
|
|
190
190
|
}
|
|
191
|
+
function runtimeLastMessageKey(visitorSessionId, prefix) {
|
|
192
|
+
return `${prefix}:eve:${visitorSessionId}:lastMessage`;
|
|
193
|
+
}
|
|
191
194
|
function loadPersistedAgentSession(visitorSessionId, options) {
|
|
192
195
|
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return null;
|
|
193
196
|
const prefix = resolvePrefix(options);
|
|
@@ -195,9 +198,11 @@ function loadPersistedAgentSession(visitorSessionId, options) {
|
|
|
195
198
|
if (!sessionId) return null;
|
|
196
199
|
const rawIndex = sessionStorage.getItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
197
200
|
const streamIndex = rawIndex ? Number.parseInt(rawIndex, 10) : 0;
|
|
201
|
+
const lastMessage = sessionStorage.getItem(runtimeLastMessageKey(visitorSessionId, prefix))?.trim();
|
|
198
202
|
return {
|
|
199
203
|
sessionId,
|
|
200
|
-
streamIndex: Number.isFinite(streamIndex) && streamIndex >= 0 ? streamIndex : 0
|
|
204
|
+
streamIndex: Number.isFinite(streamIndex) && streamIndex >= 0 ? streamIndex : 0,
|
|
205
|
+
...lastMessage ? { lastMessage } : {}
|
|
201
206
|
};
|
|
202
207
|
}
|
|
203
208
|
function savePersistedAgentSession(visitorSessionId, sessionId, streamIndex, options) {
|
|
@@ -211,11 +216,19 @@ function savePersistedAgentSession(visitorSessionId, sessionId, streamIndex, opt
|
|
|
211
216
|
String(Math.max(0, streamIndex))
|
|
212
217
|
);
|
|
213
218
|
}
|
|
219
|
+
function savePersistedAgentTurnMessage(visitorSessionId, message, options) {
|
|
220
|
+
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim() || !message) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const prefix = resolvePrefix(options);
|
|
224
|
+
sessionStorage.setItem(runtimeLastMessageKey(visitorSessionId, prefix), message);
|
|
225
|
+
}
|
|
214
226
|
function clearPersistedAgentSession(visitorSessionId, options) {
|
|
215
227
|
if (typeof sessionStorage === "undefined" || !visitorSessionId.trim()) return;
|
|
216
228
|
const prefix = resolvePrefix(options);
|
|
217
229
|
sessionStorage.removeItem(runtimeSessionIdKey(visitorSessionId, prefix));
|
|
218
230
|
sessionStorage.removeItem(runtimeStreamIndexKey(visitorSessionId, prefix));
|
|
231
|
+
sessionStorage.removeItem(runtimeLastMessageKey(visitorSessionId, prefix));
|
|
219
232
|
}
|
|
220
233
|
|
|
221
234
|
// src/runtime/client.ts
|
|
@@ -230,6 +243,12 @@ function applyMessageEvent(event, rendered, handlers, workItems) {
|
|
|
230
243
|
if (event.type === "message.completed") {
|
|
231
244
|
handlers.onComplete?.();
|
|
232
245
|
}
|
|
246
|
+
if (event.type === "action.result") {
|
|
247
|
+
const result = event.data.result;
|
|
248
|
+
if (result && typeof result === "object" && "output" in result) {
|
|
249
|
+
handlers.onActionResult?.(result.output);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
233
252
|
if (event.type !== "message.appended") return rendered;
|
|
234
253
|
const { messageDelta, messageSoFar } = event.data;
|
|
235
254
|
let delta = messageDelta;
|
|
@@ -243,6 +262,12 @@ function applyMessageEvent(event, rendered, handlers, workItems) {
|
|
|
243
262
|
if (delta) handlers.onDelta(delta);
|
|
244
263
|
return next;
|
|
245
264
|
}
|
|
265
|
+
function isResumeTurnMessage(received, candidate) {
|
|
266
|
+
if (received === candidate) return true;
|
|
267
|
+
return Boolean(candidate) && received.endsWith(`
|
|
268
|
+
|
|
269
|
+
${candidate}`);
|
|
270
|
+
}
|
|
246
271
|
function latestTurnEvents(events) {
|
|
247
272
|
let startIndex = -1;
|
|
248
273
|
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
@@ -474,6 +499,11 @@ var AgentSession = class {
|
|
|
474
499
|
this.session = session;
|
|
475
500
|
try {
|
|
476
501
|
const activeSession = session;
|
|
502
|
+
savePersistedAgentTurnMessage(
|
|
503
|
+
this.visitorSessionId,
|
|
504
|
+
message,
|
|
505
|
+
this.storeOptions
|
|
506
|
+
);
|
|
477
507
|
response = await withCapabilityRefresh(
|
|
478
508
|
this.capability,
|
|
479
509
|
() => activeSession.send(message, { signal })
|
|
@@ -489,6 +519,11 @@ var AgentSession = class {
|
|
|
489
519
|
}
|
|
490
520
|
}
|
|
491
521
|
if (!response) {
|
|
522
|
+
savePersistedAgentTurnMessage(
|
|
523
|
+
this.visitorSessionId,
|
|
524
|
+
message,
|
|
525
|
+
this.storeOptions
|
|
526
|
+
);
|
|
492
527
|
const created = await withCapabilityRefresh(
|
|
493
528
|
this.capability,
|
|
494
529
|
() => client.sessions.create({ message, signal })
|
|
@@ -543,7 +578,9 @@ var AgentSession = class {
|
|
|
543
578
|
);
|
|
544
579
|
const turnEvents = latestTurnEvents(snapshot.events);
|
|
545
580
|
const received = turnEvents[0];
|
|
546
|
-
|
|
581
|
+
const lastSent = persisted.lastMessage;
|
|
582
|
+
const inFlight = !turnEvents.some((event) => isTurnBoundary(event));
|
|
583
|
+
if (received?.type !== "message.received" || !(isResumeTurnMessage(received.data.message, message) || inFlight && lastSent !== void 0 && received.data.message === lastSent)) {
|
|
547
584
|
return null;
|
|
548
585
|
}
|
|
549
586
|
let rendered = renderTurn(turnEvents);
|
|
@@ -707,6 +744,246 @@ function formatAgentError(error) {
|
|
|
707
744
|
return TRANSIENT_AGENT_ERROR_MESSAGE;
|
|
708
745
|
}
|
|
709
746
|
|
|
747
|
+
// src/react/lib/tool-card.ts
|
|
748
|
+
function bookingOfferIdentityKey(offer) {
|
|
749
|
+
const eventTypes = offer.eventTypes.map(
|
|
750
|
+
(item) => `${item.uri}:${item.duration ?? ""}:${item.locationKind ?? ""}:${item.location ?? ""}`
|
|
751
|
+
).join("|");
|
|
752
|
+
const slots = offer.slots.map((slot) => `${slot.eventTypeUri ?? ""}:${slot.startTime}`).join("|");
|
|
753
|
+
return `${eventTypes}::${slots}` || "offer";
|
|
754
|
+
}
|
|
755
|
+
var FENCE_PATTERN = /```(?:webless-tool-card|json)\s*([\s\S]*?)```/gi;
|
|
756
|
+
function asRecord(value) {
|
|
757
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
758
|
+
}
|
|
759
|
+
function asString(value) {
|
|
760
|
+
return typeof value === "string" ? value.trim() : "";
|
|
761
|
+
}
|
|
762
|
+
function isEventUri(value) {
|
|
763
|
+
return /^https:\/\/api\.calendly\.com\/scheduled_events\/[^/]+$/i.test(value);
|
|
764
|
+
}
|
|
765
|
+
function isEventTypeUri(value) {
|
|
766
|
+
return /^https:\/\/api\.calendly\.com\/event_types\/[^/]+$/i.test(value);
|
|
767
|
+
}
|
|
768
|
+
function parseToolCard(value) {
|
|
769
|
+
const record = asRecord(value);
|
|
770
|
+
if (!record) return null;
|
|
771
|
+
if (record.booking_offer && asString(record.type) !== "booking_offer") {
|
|
772
|
+
const nested = parseToolCard(record.booking_offer);
|
|
773
|
+
if (nested) return nested;
|
|
774
|
+
}
|
|
775
|
+
const type = asString(record.type);
|
|
776
|
+
if (type === "booking_offer") {
|
|
777
|
+
const eventTypes = Array.isArray(record.eventTypes) ? record.eventTypes.flatMap((item) => {
|
|
778
|
+
const entry = asRecord(item);
|
|
779
|
+
const uri = asString(entry?.uri);
|
|
780
|
+
if (!entry || !isEventTypeUri(uri)) return [];
|
|
781
|
+
const duration = entry.duration;
|
|
782
|
+
const locationKind = asString(entry.locationKind);
|
|
783
|
+
const location = asString(entry.location);
|
|
784
|
+
return [
|
|
785
|
+
{
|
|
786
|
+
name: asString(entry.name) || "Meeting",
|
|
787
|
+
uri,
|
|
788
|
+
...typeof duration === "number" ? { duration } : {},
|
|
789
|
+
...locationKind ? { locationKind } : {},
|
|
790
|
+
...location ? { location } : {}
|
|
791
|
+
}
|
|
792
|
+
];
|
|
793
|
+
}) : [];
|
|
794
|
+
const slots = Array.isArray(record.slots) ? record.slots.flatMap((item) => {
|
|
795
|
+
const entry = asRecord(item);
|
|
796
|
+
const startTime = asString(entry?.startTime);
|
|
797
|
+
if (!entry || !startTime) return [];
|
|
798
|
+
const eventTypeUri = asString(entry.eventTypeUri);
|
|
799
|
+
return [
|
|
800
|
+
{
|
|
801
|
+
startTime,
|
|
802
|
+
...isEventTypeUri(eventTypeUri) ? { eventTypeUri } : {}
|
|
803
|
+
}
|
|
804
|
+
];
|
|
805
|
+
}) : [];
|
|
806
|
+
if (slots.length === 0) return null;
|
|
807
|
+
return { type: "booking_offer", eventTypes, slots };
|
|
808
|
+
}
|
|
809
|
+
if (type === "booking_confirmed") {
|
|
810
|
+
const eventUri = asString(record.eventUri);
|
|
811
|
+
if (!isEventUri(eventUri)) return null;
|
|
812
|
+
const inviteeUri = asString(record.inviteeUri);
|
|
813
|
+
const inviteeEmail = asString(record.inviteeEmail);
|
|
814
|
+
const startTime = asString(record.startTime);
|
|
815
|
+
return {
|
|
816
|
+
type: "booking_confirmed",
|
|
817
|
+
eventUri,
|
|
818
|
+
...inviteeUri ? { inviteeUri } : {},
|
|
819
|
+
...inviteeEmail ? { inviteeEmail } : {},
|
|
820
|
+
...startTime ? { startTime } : {}
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
if (type === "booking_canceled") {
|
|
824
|
+
const eventUri = asString(record.eventUri);
|
|
825
|
+
if (!isEventUri(eventUri)) return null;
|
|
826
|
+
return { type: "booking_canceled", eventUri };
|
|
827
|
+
}
|
|
828
|
+
return null;
|
|
829
|
+
}
|
|
830
|
+
function formatBookingOfferFence(offer) {
|
|
831
|
+
return [
|
|
832
|
+
"```webless-tool-card",
|
|
833
|
+
JSON.stringify({
|
|
834
|
+
type: "booking_offer",
|
|
835
|
+
eventTypes: offer.eventTypes,
|
|
836
|
+
slots: offer.slots
|
|
837
|
+
}),
|
|
838
|
+
"```"
|
|
839
|
+
].join("\n");
|
|
840
|
+
}
|
|
841
|
+
function bookingOfferFromActionOutput(output) {
|
|
842
|
+
const record = asRecord(output);
|
|
843
|
+
const data = asRecord(record?.data) ?? record;
|
|
844
|
+
const card = parseToolCard(data);
|
|
845
|
+
return card?.type === "booking_offer" ? card : null;
|
|
846
|
+
}
|
|
847
|
+
function ensureBookingOfferText(text, offer) {
|
|
848
|
+
if (!offer) return text;
|
|
849
|
+
if (extractToolCards(text).some((card) => card.type === "booking_offer")) {
|
|
850
|
+
return text;
|
|
851
|
+
}
|
|
852
|
+
const visible = stripToolCards(text).trim() || text.trim();
|
|
853
|
+
return `${visible}
|
|
854
|
+
|
|
855
|
+
${formatBookingOfferFence(offer)}`;
|
|
856
|
+
}
|
|
857
|
+
function hideToolCardFences(text) {
|
|
858
|
+
return text.replace(/```(?:webless-tool-card|json)\s*[\s\S]*?```/gi, "").replace(/```(?:webless-tool-card|json)[\s\S]*$/i, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
859
|
+
}
|
|
860
|
+
function visitorTimeZone() {
|
|
861
|
+
try {
|
|
862
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
863
|
+
} catch {
|
|
864
|
+
return "UTC";
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function extractToolCards(text) {
|
|
868
|
+
const cards = [];
|
|
869
|
+
for (const match of text.matchAll(FENCE_PATTERN)) {
|
|
870
|
+
try {
|
|
871
|
+
const card = parseToolCard(JSON.parse(match[1] ?? ""));
|
|
872
|
+
if (card) cards.push(card);
|
|
873
|
+
} catch {
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return cards;
|
|
877
|
+
}
|
|
878
|
+
function stripToolCards(text) {
|
|
879
|
+
return text.replace(FENCE_PATTERN, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
880
|
+
}
|
|
881
|
+
function localDateKey(date) {
|
|
882
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
883
|
+
return [
|
|
884
|
+
date.getFullYear(),
|
|
885
|
+
String(date.getMonth() + 1).padStart(2, "0"),
|
|
886
|
+
String(date.getDate()).padStart(2, "0")
|
|
887
|
+
].join("-");
|
|
888
|
+
}
|
|
889
|
+
function slotDateKey(startTime) {
|
|
890
|
+
return localDateKey(new Date(startTime)) || startTime;
|
|
891
|
+
}
|
|
892
|
+
function bookingSlotsForEventType(slots, eventTypeUri) {
|
|
893
|
+
return slots.filter(
|
|
894
|
+
(slot) => !eventTypeUri || !slot.eventTypeUri || slot.eventTypeUri === eventTypeUri
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
function firstAvailableBookingMonth(slots) {
|
|
898
|
+
let earliest;
|
|
899
|
+
for (const slot of slots) {
|
|
900
|
+
const key = slotDateKey(slot.startTime);
|
|
901
|
+
if (!earliest || key < earliest) earliest = key;
|
|
902
|
+
}
|
|
903
|
+
const [year, month] = (earliest ?? slotDateKey((/* @__PURE__ */ new Date()).toISOString())).split("-").map(Number);
|
|
904
|
+
if (!year || !month) {
|
|
905
|
+
const now = /* @__PURE__ */ new Date();
|
|
906
|
+
return { year: now.getFullYear(), month: now.getMonth() };
|
|
907
|
+
}
|
|
908
|
+
return { year, month: month - 1 };
|
|
909
|
+
}
|
|
910
|
+
function formatMonthTitle(year, month) {
|
|
911
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
912
|
+
month: "long",
|
|
913
|
+
year: "numeric"
|
|
914
|
+
}).format(new Date(year, month, 1));
|
|
915
|
+
}
|
|
916
|
+
function formatLongDate(startTime) {
|
|
917
|
+
const date = new Date(startTime);
|
|
918
|
+
if (Number.isNaN(date.getTime())) return startTime;
|
|
919
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
920
|
+
weekday: "long",
|
|
921
|
+
month: "long",
|
|
922
|
+
day: "numeric"
|
|
923
|
+
}).format(date);
|
|
924
|
+
}
|
|
925
|
+
function weekdayLabels() {
|
|
926
|
+
return Array.from(
|
|
927
|
+
{ length: 7 },
|
|
928
|
+
(_, index) => new Intl.DateTimeFormat(void 0, { weekday: "short" }).format(
|
|
929
|
+
new Date(2026, 7, 3 + index)
|
|
930
|
+
)
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
function formatTimeChip(startTime) {
|
|
934
|
+
const date = new Date(startTime);
|
|
935
|
+
if (Number.isNaN(date.getTime())) return startTime;
|
|
936
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
937
|
+
hour: "numeric",
|
|
938
|
+
minute: "2-digit"
|
|
939
|
+
}).format(date);
|
|
940
|
+
}
|
|
941
|
+
function formatSlotTimeZone(startTime) {
|
|
942
|
+
const date = new Date(startTime);
|
|
943
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
944
|
+
return new Intl.DateTimeFormat(void 0, { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value ?? "";
|
|
945
|
+
}
|
|
946
|
+
function formatSlotLabel(startTime) {
|
|
947
|
+
const date = new Date(startTime);
|
|
948
|
+
if (Number.isNaN(date.getTime())) return startTime;
|
|
949
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
950
|
+
weekday: "short",
|
|
951
|
+
month: "short",
|
|
952
|
+
day: "numeric",
|
|
953
|
+
hour: "numeric",
|
|
954
|
+
minute: "2-digit",
|
|
955
|
+
timeZoneName: "short"
|
|
956
|
+
}).format(date);
|
|
957
|
+
}
|
|
958
|
+
function formatBookingRequest(input) {
|
|
959
|
+
return [
|
|
960
|
+
"Book this meeting now with CALENDLY_POST_INVITEE.",
|
|
961
|
+
"Do not open a Calendly URL and do not list other scheduled events.",
|
|
962
|
+
"Do not invent a location kind. Use only the location fields below.",
|
|
963
|
+
`event_type: ${input.eventTypeUri}`,
|
|
964
|
+
`start_time: ${input.startTime}`,
|
|
965
|
+
`invitee.name: ${input.inviteeName}`,
|
|
966
|
+
`invitee.email: ${input.inviteeEmail}`,
|
|
967
|
+
`invitee.timezone: ${input.timezone}`,
|
|
968
|
+
...input.locationKind ? [
|
|
969
|
+
`location.kind: ${input.locationKind}`,
|
|
970
|
+
...input.location ? [`location.location: ${input.location}`] : []
|
|
971
|
+
] : ["Do not send a location field."],
|
|
972
|
+
"After it succeeds, reply with one short confirmation and a webless-tool-card booking_confirmed block using visitor_booking."
|
|
973
|
+
].join("\n");
|
|
974
|
+
}
|
|
975
|
+
function visitorBookingPrefix(booking) {
|
|
976
|
+
return [
|
|
977
|
+
"This visitor already booked a meeting. Use only this meeting:",
|
|
978
|
+
`- scheduled event URI: ${booking.eventUri}`,
|
|
979
|
+
...booking.inviteeUri ? [`- invitee URI: ${booking.inviteeUri}`] : [],
|
|
980
|
+
...booking.inviteeEmail ? [`- invitee email: ${booking.inviteeEmail}`] : [],
|
|
981
|
+
"For details call CALENDLY_GET_EVENT or CALENDLY_GET_EVENT_INVITEE with those URIs.",
|
|
982
|
+
"If you must list events, pass this invitee_email. Never describe any other scheduled event.",
|
|
983
|
+
"start_time values from Calendly are UTC."
|
|
984
|
+
].join("\n");
|
|
985
|
+
}
|
|
986
|
+
|
|
710
987
|
// src/react/persisted-conversation.ts
|
|
711
988
|
var CONVERSATION_VERSION = 1;
|
|
712
989
|
function conversationKey(storageKeyPrefix, visitorSessionId) {
|
|
@@ -718,13 +995,25 @@ function parseMessage(value) {
|
|
|
718
995
|
if (typeof record.id !== "string" || record.role !== "agent" && record.role !== "visitor" || typeof record.text !== "string" || typeof record.createdAt !== "number" || !Number.isFinite(record.createdAt)) {
|
|
719
996
|
return null;
|
|
720
997
|
}
|
|
998
|
+
if (record.role === "visitor") {
|
|
999
|
+
return {
|
|
1000
|
+
id: record.id,
|
|
1001
|
+
role: "visitor",
|
|
1002
|
+
text: record.text,
|
|
1003
|
+
createdAt: record.createdAt,
|
|
1004
|
+
...typeof record.runtimeText === "string" && record.runtimeText ? { runtimeText: record.runtimeText } : {}
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
721
1007
|
return {
|
|
722
1008
|
id: record.id,
|
|
723
|
-
role:
|
|
1009
|
+
role: "agent",
|
|
724
1010
|
text: record.text,
|
|
725
1011
|
createdAt: record.createdAt
|
|
726
1012
|
};
|
|
727
1013
|
}
|
|
1014
|
+
function visitorTurnText(message) {
|
|
1015
|
+
return message.role === "visitor" && message.runtimeText ? message.runtimeText : message.text;
|
|
1016
|
+
}
|
|
728
1017
|
function loadPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
729
1018
|
if (typeof sessionStorage === "undefined") return null;
|
|
730
1019
|
const raw = sessionStorage.getItem(conversationKey(storageKeyPrefix, visitorSessionId));
|
|
@@ -757,6 +1046,42 @@ function savePersistedAgentConversation(storageKeyPrefix, visitorSessionId, conv
|
|
|
757
1046
|
function clearPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
758
1047
|
if (typeof sessionStorage === "undefined") return;
|
|
759
1048
|
sessionStorage.removeItem(conversationKey(storageKeyPrefix, visitorSessionId));
|
|
1049
|
+
clearPendingWidgetBooking(storageKeyPrefix, visitorSessionId);
|
|
1050
|
+
}
|
|
1051
|
+
function pendingBookingKey(storageKeyPrefix, visitorSessionId) {
|
|
1052
|
+
return `${storageKeyPrefix}:pending-booking:${visitorSessionId}`;
|
|
1053
|
+
}
|
|
1054
|
+
function loadPendingWidgetBooking(storageKeyPrefix, visitorSessionId) {
|
|
1055
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
1056
|
+
const raw = sessionStorage.getItem(
|
|
1057
|
+
pendingBookingKey(storageKeyPrefix, visitorSessionId)
|
|
1058
|
+
);
|
|
1059
|
+
if (!raw) return null;
|
|
1060
|
+
try {
|
|
1061
|
+
const value = JSON.parse(raw);
|
|
1062
|
+
if (typeof value !== "object" || value === null) return null;
|
|
1063
|
+
const record = value;
|
|
1064
|
+
if (typeof record.eventUri !== "string" || !record.eventUri) return null;
|
|
1065
|
+
return {
|
|
1066
|
+
eventUri: record.eventUri,
|
|
1067
|
+
...typeof record.inviteeUri === "string" && record.inviteeUri ? { inviteeUri: record.inviteeUri } : {},
|
|
1068
|
+
...typeof record.inviteeEmail === "string" && record.inviteeEmail ? { inviteeEmail: record.inviteeEmail } : {},
|
|
1069
|
+
...typeof record.startTime === "string" && record.startTime ? { startTime: record.startTime } : {}
|
|
1070
|
+
};
|
|
1071
|
+
} catch {
|
|
1072
|
+
return null;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
function savePendingWidgetBooking(storageKeyPrefix, visitorSessionId, booking) {
|
|
1076
|
+
if (typeof sessionStorage === "undefined") return;
|
|
1077
|
+
sessionStorage.setItem(
|
|
1078
|
+
pendingBookingKey(storageKeyPrefix, visitorSessionId),
|
|
1079
|
+
JSON.stringify(booking)
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
function clearPendingWidgetBooking(storageKeyPrefix, visitorSessionId) {
|
|
1083
|
+
if (typeof sessionStorage === "undefined") return;
|
|
1084
|
+
sessionStorage.removeItem(pendingBookingKey(storageKeyPrefix, visitorSessionId));
|
|
760
1085
|
}
|
|
761
1086
|
|
|
762
1087
|
// src/react/hooks/useAgentChat.ts
|
|
@@ -776,6 +1101,7 @@ function createInitialState(greeting = DEFAULT_GREETING) {
|
|
|
776
1101
|
journey: null,
|
|
777
1102
|
followUps: [],
|
|
778
1103
|
streamingText: "",
|
|
1104
|
+
pendingOffer: null,
|
|
779
1105
|
error: null
|
|
780
1106
|
};
|
|
781
1107
|
}
|
|
@@ -858,6 +1184,9 @@ function useAgentChat({
|
|
|
858
1184
|
initialState
|
|
859
1185
|
)
|
|
860
1186
|
);
|
|
1187
|
+
const pendingBookingRef = useRef(
|
|
1188
|
+
loadPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId)
|
|
1189
|
+
);
|
|
861
1190
|
const runRef = useRef(null);
|
|
862
1191
|
const clientRef = useRef(
|
|
863
1192
|
createAgentClient({
|
|
@@ -890,6 +1219,10 @@ function useAgentChat({
|
|
|
890
1219
|
visitorSessionId: visitorId,
|
|
891
1220
|
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
892
1221
|
});
|
|
1222
|
+
pendingBookingRef.current = loadPendingWidgetBooking(
|
|
1223
|
+
resolvedStorageKeyPrefix,
|
|
1224
|
+
visitorId
|
|
1225
|
+
);
|
|
893
1226
|
setState(
|
|
894
1227
|
stateFromConversation(
|
|
895
1228
|
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
|
|
@@ -925,6 +1258,7 @@ function useAgentChat({
|
|
|
925
1258
|
runRef.current?.abort();
|
|
926
1259
|
runRef.current = null;
|
|
927
1260
|
clientRef.current.reset();
|
|
1261
|
+
pendingBookingRef.current = null;
|
|
928
1262
|
clearPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId);
|
|
929
1263
|
setState(initialState);
|
|
930
1264
|
}, [initialState, resolvedStorageKeyPrefix, visitorId]);
|
|
@@ -936,6 +1270,7 @@ function useAgentChat({
|
|
|
936
1270
|
try {
|
|
937
1271
|
let streamStarted = Boolean(initialText);
|
|
938
1272
|
let streamed = initialText;
|
|
1273
|
+
const capturedOffers = [];
|
|
939
1274
|
const handlers = {
|
|
940
1275
|
onWork: (item) => {
|
|
941
1276
|
if (!isActiveRun()) return;
|
|
@@ -945,6 +1280,12 @@ function useAgentChat({
|
|
|
945
1280
|
toolSteps: upsertToolStep(prev.toolSteps, item)
|
|
946
1281
|
}));
|
|
947
1282
|
},
|
|
1283
|
+
onActionResult: (output) => {
|
|
1284
|
+
const offer = bookingOfferFromActionOutput(output);
|
|
1285
|
+
if (!offer) return;
|
|
1286
|
+
capturedOffers.push(offer);
|
|
1287
|
+
setState((prev) => ({ ...prev, pendingOffer: offer }));
|
|
1288
|
+
},
|
|
948
1289
|
onDelta: (delta) => {
|
|
949
1290
|
if (!isActiveRun()) return;
|
|
950
1291
|
if (!streamStarted) {
|
|
@@ -960,7 +1301,8 @@ function useAgentChat({
|
|
|
960
1301
|
setState((prev) => ({
|
|
961
1302
|
...prev,
|
|
962
1303
|
phase: "streaming",
|
|
963
|
-
streamingText: streamed
|
|
1304
|
+
streamingText: hideToolCardFences(streamed),
|
|
1305
|
+
pendingOffer: prev.pendingOffer ?? capturedOffers.at(-1) ?? null
|
|
964
1306
|
}));
|
|
965
1307
|
},
|
|
966
1308
|
onComplete: () => {
|
|
@@ -981,18 +1323,34 @@ function useAgentChat({
|
|
|
981
1323
|
});
|
|
982
1324
|
}
|
|
983
1325
|
if (!isActiveRun() || finalText === null) return;
|
|
1326
|
+
const displayText = ensureBookingOfferText(
|
|
1327
|
+
finalText,
|
|
1328
|
+
capturedOffers.at(-1) ?? null
|
|
1329
|
+
);
|
|
984
1330
|
const agentMessage = {
|
|
985
1331
|
id: `agent-${Date.now()}`,
|
|
986
1332
|
role: "agent",
|
|
987
|
-
text:
|
|
1333
|
+
text: displayText,
|
|
988
1334
|
createdAt: Date.now()
|
|
989
1335
|
};
|
|
1336
|
+
const parsedCards = extractToolCards(displayText);
|
|
1337
|
+
for (const card of parsedCards) {
|
|
1338
|
+
if (card.type === "booking_confirmed") {
|
|
1339
|
+
pendingBookingRef.current = card;
|
|
1340
|
+
savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
|
|
1341
|
+
}
|
|
1342
|
+
if (card.type === "booking_canceled" && pendingBookingRef.current?.eventUri === card.eventUri) {
|
|
1343
|
+
pendingBookingRef.current = null;
|
|
1344
|
+
clearPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
990
1347
|
setState((prev) => ({
|
|
991
1348
|
...prev,
|
|
992
1349
|
phase: "complete",
|
|
993
1350
|
messages: [...prev.messages, agentMessage],
|
|
994
1351
|
toolSteps: completeActivePlanning(prev.toolSteps),
|
|
995
1352
|
streamingText: "",
|
|
1353
|
+
pendingOffer: null,
|
|
996
1354
|
followUps: [],
|
|
997
1355
|
journey: null
|
|
998
1356
|
}));
|
|
@@ -1014,26 +1372,54 @@ function useAgentChat({
|
|
|
1014
1372
|
} : step
|
|
1015
1373
|
),
|
|
1016
1374
|
streamingText: "",
|
|
1375
|
+
pendingOffer: null,
|
|
1017
1376
|
error: message
|
|
1018
1377
|
}));
|
|
1019
1378
|
runRef.current = null;
|
|
1020
1379
|
}
|
|
1021
1380
|
},
|
|
1022
|
-
[]
|
|
1381
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1382
|
+
);
|
|
1383
|
+
const rememberBooking = useCallback(
|
|
1384
|
+
(booking) => {
|
|
1385
|
+
const current = pendingBookingRef.current;
|
|
1386
|
+
if (current?.eventUri === booking.eventUri && current.inviteeEmail === booking.inviteeEmail && current.inviteeUri === booking.inviteeUri) {
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
pendingBookingRef.current = booking;
|
|
1390
|
+
savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, booking);
|
|
1391
|
+
},
|
|
1392
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1393
|
+
);
|
|
1394
|
+
const forgetBooking = useCallback(
|
|
1395
|
+
(eventUri) => {
|
|
1396
|
+
const current = pendingBookingRef.current;
|
|
1397
|
+
if (!current) return;
|
|
1398
|
+
if (eventUri && current.eventUri !== eventUri) return;
|
|
1399
|
+
pendingBookingRef.current = null;
|
|
1400
|
+
clearPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId);
|
|
1401
|
+
},
|
|
1402
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1023
1403
|
);
|
|
1024
1404
|
const submit = useCallback(
|
|
1025
|
-
async (visitorText) => {
|
|
1405
|
+
async (visitorText, options) => {
|
|
1026
1406
|
if (runRef.current) {
|
|
1027
1407
|
runRef.current.abort();
|
|
1028
1408
|
clientRef.current.cancelActive();
|
|
1029
1409
|
}
|
|
1030
1410
|
const controller = new AbortController();
|
|
1031
1411
|
runRef.current = controller;
|
|
1412
|
+
const booking = pendingBookingRef.current;
|
|
1413
|
+
const outgoing = options?.runtimeText ?? visitorText;
|
|
1414
|
+
const runtimeText = booking ? `${visitorBookingPrefix(booking)}
|
|
1415
|
+
|
|
1416
|
+
${outgoing}` : outgoing;
|
|
1032
1417
|
const visitorMessage = {
|
|
1033
1418
|
id: `visitor-${Date.now()}`,
|
|
1034
1419
|
role: "visitor",
|
|
1035
1420
|
text: visitorText,
|
|
1036
|
-
createdAt: Date.now()
|
|
1421
|
+
createdAt: Date.now(),
|
|
1422
|
+
...runtimeText !== visitorText ? { runtimeText } : {}
|
|
1037
1423
|
};
|
|
1038
1424
|
setState((prev) => ({
|
|
1039
1425
|
...prev,
|
|
@@ -1050,9 +1436,10 @@ function useAgentChat({
|
|
|
1050
1436
|
journey: null,
|
|
1051
1437
|
followUps: [],
|
|
1052
1438
|
streamingText: "",
|
|
1439
|
+
pendingOffer: null,
|
|
1053
1440
|
error: null
|
|
1054
1441
|
}));
|
|
1055
|
-
await runTurn({ controller, resume: false, visitorText });
|
|
1442
|
+
await runTurn({ controller, resume: false, visitorText: runtimeText });
|
|
1056
1443
|
},
|
|
1057
1444
|
[runTurn]
|
|
1058
1445
|
);
|
|
@@ -1079,12 +1466,13 @@ function useAgentChat({
|
|
|
1079
1466
|
journey: null,
|
|
1080
1467
|
followUps: [],
|
|
1081
1468
|
streamingText: "",
|
|
1469
|
+
pendingOffer: null,
|
|
1082
1470
|
error: null
|
|
1083
1471
|
}));
|
|
1084
1472
|
await runTurn({
|
|
1085
1473
|
controller,
|
|
1086
1474
|
resume: false,
|
|
1087
|
-
visitorText: visitorMessage
|
|
1475
|
+
visitorText: visitorTurnText(visitorMessage)
|
|
1088
1476
|
});
|
|
1089
1477
|
}, [runTurn, state.messages]);
|
|
1090
1478
|
useEffect(() => {
|
|
@@ -1101,7 +1489,7 @@ function useAgentChat({
|
|
|
1101
1489
|
controller,
|
|
1102
1490
|
initialText: conversation.streamingText,
|
|
1103
1491
|
resume: true,
|
|
1104
|
-
visitorText: visitorMessage
|
|
1492
|
+
visitorText: visitorTurnText(visitorMessage)
|
|
1105
1493
|
});
|
|
1106
1494
|
return () => {
|
|
1107
1495
|
if (runRef.current === controller) {
|
|
@@ -1121,6 +1509,8 @@ function useAgentChat({
|
|
|
1121
1509
|
reset,
|
|
1122
1510
|
retry,
|
|
1123
1511
|
submit,
|
|
1512
|
+
rememberBooking,
|
|
1513
|
+
forgetBooking,
|
|
1124
1514
|
visitorSessionId: visitorId,
|
|
1125
1515
|
sessionId: clientRef.current.getActiveSessionId()
|
|
1126
1516
|
};
|
|
@@ -1177,7 +1567,7 @@ var defaultAgentRailTheme = {
|
|
|
1177
1567
|
};
|
|
1178
1568
|
|
|
1179
1569
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1180
|
-
import { useEffect as useEffect2,
|
|
1570
|
+
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
1181
1571
|
|
|
1182
1572
|
// src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
|
|
1183
1573
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1197,10 +1587,9 @@ function workSummary(steps, failed, brandLabel) {
|
|
|
1197
1587
|
);
|
|
1198
1588
|
if (hasError) return "Answered with available information";
|
|
1199
1589
|
if (specialists.length > 1)
|
|
1200
|
-
return `
|
|
1201
|
-
if (specialists.length === 1)
|
|
1202
|
-
|
|
1203
|
-
if (searched) return "Answer prepared from this site";
|
|
1590
|
+
return `Consulted ${specialists.length} specialists`;
|
|
1591
|
+
if (specialists.length === 1) return `Consulted ${specialists[0]?.label}`;
|
|
1592
|
+
if (searched) return "Searched this site";
|
|
1204
1593
|
return "Answer ready";
|
|
1205
1594
|
}
|
|
1206
1595
|
function stepLabel(step, brandLabel) {
|
|
@@ -1250,7 +1639,6 @@ function AgentActivityBubble({
|
|
|
1250
1639
|
steps
|
|
1251
1640
|
}) {
|
|
1252
1641
|
const active = steps.some((step) => step.state === "active");
|
|
1253
|
-
const delegated = steps.some((step) => step.kind === "specialist");
|
|
1254
1642
|
return /* @__PURE__ */ jsxs("article", { className: "agent-activity-bubble", children: [
|
|
1255
1643
|
/* @__PURE__ */ jsxs("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
|
|
1256
1644
|
/* @__PURE__ */ jsx(
|
|
@@ -1262,57 +1650,50 @@ function AgentActivityBubble({
|
|
|
1262
1650
|
),
|
|
1263
1651
|
workSummary(steps, failed, brandLabel)
|
|
1264
1652
|
] }),
|
|
1265
|
-
/* @__PURE__ */ jsxs(
|
|
1266
|
-
"details",
|
|
1267
|
-
{
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
},
|
|
1310
|
-
step.id
|
|
1311
|
-
);
|
|
1312
|
-
}) })
|
|
1313
|
-
]
|
|
1314
|
-
}
|
|
1315
|
-
)
|
|
1653
|
+
/* @__PURE__ */ jsxs("details", { className: "agent-activity-bubble__details", open: active, children: [
|
|
1654
|
+
/* @__PURE__ */ jsx("summary", { children: "Work details" }),
|
|
1655
|
+
/* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => {
|
|
1656
|
+
const detail = stepDetail(step, steps);
|
|
1657
|
+
return /* @__PURE__ */ jsxs(
|
|
1658
|
+
"li",
|
|
1659
|
+
{
|
|
1660
|
+
className: "agent-activity-bubble__step",
|
|
1661
|
+
"data-kind": step.kind,
|
|
1662
|
+
"data-state": step.state,
|
|
1663
|
+
children: [
|
|
1664
|
+
/* @__PURE__ */ jsx(
|
|
1665
|
+
"span",
|
|
1666
|
+
{
|
|
1667
|
+
className: "agent-activity-bubble__step-icon",
|
|
1668
|
+
"aria-hidden": "true",
|
|
1669
|
+
children: step.kind === "planning" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1670
|
+
/* @__PURE__ */ jsx(PlanningIcon, {}),
|
|
1671
|
+
brandLogoUrl ? /* @__PURE__ */ jsx(
|
|
1672
|
+
"img",
|
|
1673
|
+
{
|
|
1674
|
+
src: brandLogoUrl,
|
|
1675
|
+
alt: "",
|
|
1676
|
+
onError: (event) => {
|
|
1677
|
+
event.currentTarget.hidden = true;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
) : null
|
|
1681
|
+
] }) : step.kind === "search" ? /* @__PURE__ */ jsx(SearchIcon, {}) : step.label.slice(0, 1).toUpperCase()
|
|
1682
|
+
}
|
|
1683
|
+
),
|
|
1684
|
+
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
|
|
1685
|
+
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-heading", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx("strong", { children: stepLabel(step, brandLabel) }),
|
|
1687
|
+
/* @__PURE__ */ jsx("small", { children: step.kind === "specialist" ? "Specialist" : step.kind === "search" ? "Built-in capability" : "Supervisor" })
|
|
1688
|
+
] }),
|
|
1689
|
+
detail ? /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null
|
|
1690
|
+
] })
|
|
1691
|
+
]
|
|
1692
|
+
},
|
|
1693
|
+
step.id
|
|
1694
|
+
);
|
|
1695
|
+
}) })
|
|
1696
|
+
] })
|
|
1316
1697
|
] });
|
|
1317
1698
|
}
|
|
1318
1699
|
|
|
@@ -1414,34 +1795,318 @@ function FollowUpChips({
|
|
|
1414
1795
|
] });
|
|
1415
1796
|
}
|
|
1416
1797
|
|
|
1798
|
+
// src/react/components/BookingCard/BookingCard.tsx
|
|
1799
|
+
import { useId, useMemo as useMemo2, useState as useState3 } from "react";
|
|
1800
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1801
|
+
function monthFromKey(key) {
|
|
1802
|
+
const [year, month] = key.split("-").map(Number);
|
|
1803
|
+
if (!year || !month) return { year: (/* @__PURE__ */ new Date()).getFullYear(), month: (/* @__PURE__ */ new Date()).getMonth() };
|
|
1804
|
+
return { year, month: month - 1 };
|
|
1805
|
+
}
|
|
1806
|
+
function dateKeyFromParts(year, month, day) {
|
|
1807
|
+
return [
|
|
1808
|
+
year,
|
|
1809
|
+
String(month + 1).padStart(2, "0"),
|
|
1810
|
+
String(day).padStart(2, "0")
|
|
1811
|
+
].join("-");
|
|
1812
|
+
}
|
|
1813
|
+
function calendarCells(year, month) {
|
|
1814
|
+
const firstWeekday = (new Date(year, month, 1).getDay() + 6) % 7;
|
|
1815
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1816
|
+
const cells = [];
|
|
1817
|
+
for (let index = 0; index < firstWeekday; index += 1) cells.push(null);
|
|
1818
|
+
for (let day = 1; day <= daysInMonth; day += 1) {
|
|
1819
|
+
cells.push({ day, key: dateKeyFromParts(year, month, day) });
|
|
1820
|
+
}
|
|
1821
|
+
while (cells.length < 42) cells.push(null);
|
|
1822
|
+
return cells;
|
|
1823
|
+
}
|
|
1824
|
+
function BookingCard({
|
|
1825
|
+
offer,
|
|
1826
|
+
onBook
|
|
1827
|
+
}) {
|
|
1828
|
+
const fieldId = useId();
|
|
1829
|
+
const defaultType = offer.eventTypes[0]?.uri ?? offer.slots[0]?.eventTypeUri ?? "";
|
|
1830
|
+
const [step, setStep] = useState3("date");
|
|
1831
|
+
const [eventTypeUri, setEventTypeUri] = useState3(defaultType);
|
|
1832
|
+
const [selectedDate, setSelectedDate] = useState3("");
|
|
1833
|
+
const [startTime, setStartTime] = useState3("");
|
|
1834
|
+
const [name, setName] = useState3("");
|
|
1835
|
+
const [email, setEmail] = useState3("");
|
|
1836
|
+
const slots = useMemo2(
|
|
1837
|
+
() => bookingSlotsForEventType(offer.slots, eventTypeUri),
|
|
1838
|
+
[eventTypeUri, offer.slots]
|
|
1839
|
+
);
|
|
1840
|
+
const availableByDate = useMemo2(() => {
|
|
1841
|
+
const next = /* @__PURE__ */ new Map();
|
|
1842
|
+
for (const slot of slots) {
|
|
1843
|
+
const key = slotDateKey(slot.startTime);
|
|
1844
|
+
if (!next.has(key)) next.set(key, slot.startTime);
|
|
1845
|
+
}
|
|
1846
|
+
return next;
|
|
1847
|
+
}, [slots]);
|
|
1848
|
+
const [visibleMonth, setVisibleMonth] = useState3(
|
|
1849
|
+
() => firstAvailableBookingMonth(slots)
|
|
1850
|
+
);
|
|
1851
|
+
function selectEventType(nextType) {
|
|
1852
|
+
setEventTypeUri(nextType);
|
|
1853
|
+
setSelectedDate("");
|
|
1854
|
+
setStartTime("");
|
|
1855
|
+
setVisibleMonth(
|
|
1856
|
+
firstAvailableBookingMonth(bookingSlotsForEventType(offer.slots, nextType))
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
const daySlots = useMemo2(
|
|
1860
|
+
() => slots.filter((slot) => slotDateKey(slot.startTime) === selectedDate),
|
|
1861
|
+
[selectedDate, slots]
|
|
1862
|
+
);
|
|
1863
|
+
const selectedType = offer.eventTypes.find((item) => item.uri === eventTypeUri);
|
|
1864
|
+
const selectedSample = availableByDate.get(selectedDate) ?? startTime;
|
|
1865
|
+
const timeZone = formatSlotTimeZone(slots[0]?.startTime ?? selectedSample);
|
|
1866
|
+
const weekdays = useMemo2(() => weekdayLabels(), []);
|
|
1867
|
+
const cells = calendarCells(visibleMonth.year, visibleMonth.month);
|
|
1868
|
+
const canPrevMonth = [...availableByDate.keys()].some((key) => {
|
|
1869
|
+
const month = monthFromKey(key);
|
|
1870
|
+
return month.year < visibleMonth.year || month.year === visibleMonth.year && month.month < visibleMonth.month;
|
|
1871
|
+
});
|
|
1872
|
+
const canNextMonth = [...availableByDate.keys()].some((key) => {
|
|
1873
|
+
const month = monthFromKey(key);
|
|
1874
|
+
return month.year > visibleMonth.year || month.year === visibleMonth.year && month.month > visibleMonth.month;
|
|
1875
|
+
});
|
|
1876
|
+
function goToMonth(offset) {
|
|
1877
|
+
setVisibleMonth((current) => {
|
|
1878
|
+
const next = new Date(current.year, current.month + offset, 1);
|
|
1879
|
+
return { year: next.getFullYear(), month: next.getMonth() };
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
function selectDate(key) {
|
|
1883
|
+
if (!availableByDate.has(key)) return;
|
|
1884
|
+
setSelectedDate(key);
|
|
1885
|
+
setStartTime("");
|
|
1886
|
+
setStep("time");
|
|
1887
|
+
}
|
|
1888
|
+
function selectTime(value) {
|
|
1889
|
+
setStartTime(value);
|
|
1890
|
+
setStep("details");
|
|
1891
|
+
}
|
|
1892
|
+
function handleSubmit(event) {
|
|
1893
|
+
event.preventDefault();
|
|
1894
|
+
if (!eventTypeUri || !startTime || !name.trim() || !email.trim()) return;
|
|
1895
|
+
onBook?.({
|
|
1896
|
+
displayText: `Book the ${formatSlotLabel(startTime)} demo`,
|
|
1897
|
+
runtimeText: formatBookingRequest({
|
|
1898
|
+
eventTypeUri,
|
|
1899
|
+
inviteeEmail: email.trim(),
|
|
1900
|
+
inviteeName: name.trim(),
|
|
1901
|
+
startTime,
|
|
1902
|
+
timezone: visitorTimeZone(),
|
|
1903
|
+
locationKind: selectedType?.locationKind,
|
|
1904
|
+
location: selectedType?.location
|
|
1905
|
+
})
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
return /* @__PURE__ */ jsx4("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsxs4("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
|
|
1909
|
+
step === "date" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
1910
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
|
|
1911
|
+
timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
|
|
1912
|
+
"Times in ",
|
|
1913
|
+
timeZone
|
|
1914
|
+
] }) : null,
|
|
1915
|
+
offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-type`, children: [
|
|
1916
|
+
/* @__PURE__ */ jsx4("span", { children: "Meeting" }),
|
|
1917
|
+
/* @__PURE__ */ jsx4(
|
|
1918
|
+
"select",
|
|
1919
|
+
{
|
|
1920
|
+
id: `${fieldId}-type`,
|
|
1921
|
+
value: eventTypeUri,
|
|
1922
|
+
onChange: (event) => selectEventType(event.target.value),
|
|
1923
|
+
children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx4("option", { value: item.uri, children: item.name }, item.uri))
|
|
1924
|
+
}
|
|
1925
|
+
)
|
|
1926
|
+
] }) : null,
|
|
1927
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__month", children: [
|
|
1928
|
+
/* @__PURE__ */ jsx4(
|
|
1929
|
+
"button",
|
|
1930
|
+
{
|
|
1931
|
+
type: "button",
|
|
1932
|
+
className: "booking-card__nav",
|
|
1933
|
+
"aria-label": "Previous month",
|
|
1934
|
+
disabled: !canPrevMonth,
|
|
1935
|
+
onClick: () => goToMonth(-1),
|
|
1936
|
+
children: "\u2039"
|
|
1937
|
+
}
|
|
1938
|
+
),
|
|
1939
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
|
|
1940
|
+
/* @__PURE__ */ jsx4(
|
|
1941
|
+
"button",
|
|
1942
|
+
{
|
|
1943
|
+
type: "button",
|
|
1944
|
+
className: "booking-card__nav",
|
|
1945
|
+
"aria-label": "Next month",
|
|
1946
|
+
disabled: !canNextMonth,
|
|
1947
|
+
onClick: () => goToMonth(1),
|
|
1948
|
+
children: "\u203A"
|
|
1949
|
+
}
|
|
1950
|
+
)
|
|
1951
|
+
] }),
|
|
1952
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx4("span", { children: label }, label)) }),
|
|
1953
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__calendar", role: "grid", "aria-label": "Available dates", children: cells.map((cell, index) => {
|
|
1954
|
+
if (!cell) {
|
|
1955
|
+
return /* @__PURE__ */ jsx4("span", { className: "booking-card__day" }, `empty-${index}`);
|
|
1956
|
+
}
|
|
1957
|
+
const available = availableByDate.has(cell.key);
|
|
1958
|
+
const selected = cell.key === selectedDate;
|
|
1959
|
+
return /* @__PURE__ */ jsx4(
|
|
1960
|
+
"button",
|
|
1961
|
+
{
|
|
1962
|
+
type: "button",
|
|
1963
|
+
className: [
|
|
1964
|
+
"booking-card__day",
|
|
1965
|
+
available ? "booking-card__day--available" : "",
|
|
1966
|
+
selected ? "booking-card__day--selected" : ""
|
|
1967
|
+
].filter(Boolean).join(" "),
|
|
1968
|
+
disabled: !available,
|
|
1969
|
+
"aria-pressed": selected,
|
|
1970
|
+
onClick: () => selectDate(cell.key),
|
|
1971
|
+
children: cell.day
|
|
1972
|
+
},
|
|
1973
|
+
cell.key
|
|
1974
|
+
);
|
|
1975
|
+
}) })
|
|
1976
|
+
] }, "date") : null,
|
|
1977
|
+
step === "time" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
1978
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
|
|
1979
|
+
/* @__PURE__ */ jsx4(
|
|
1980
|
+
"button",
|
|
1981
|
+
{
|
|
1982
|
+
type: "button",
|
|
1983
|
+
className: "booking-card__nav",
|
|
1984
|
+
"aria-label": "Back to dates",
|
|
1985
|
+
onClick: () => setStep("date"),
|
|
1986
|
+
children: "\u2039"
|
|
1987
|
+
}
|
|
1988
|
+
),
|
|
1989
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1990
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
|
|
1991
|
+
timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
|
|
1992
|
+
"Times in ",
|
|
1993
|
+
timeZone
|
|
1994
|
+
] }) : null
|
|
1995
|
+
] })
|
|
1996
|
+
] }),
|
|
1997
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
|
|
1998
|
+
"button",
|
|
1999
|
+
{
|
|
2000
|
+
type: "button",
|
|
2001
|
+
className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
|
|
2002
|
+
onClick: () => selectTime(slot.startTime),
|
|
2003
|
+
children: formatTimeChip(slot.startTime)
|
|
2004
|
+
},
|
|
2005
|
+
slot.startTime
|
|
2006
|
+
)) })
|
|
2007
|
+
] }, "time") : null,
|
|
2008
|
+
step === "details" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
2009
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
|
|
2010
|
+
/* @__PURE__ */ jsx4(
|
|
2011
|
+
"button",
|
|
2012
|
+
{
|
|
2013
|
+
type: "button",
|
|
2014
|
+
className: "booking-card__nav",
|
|
2015
|
+
"aria-label": "Back to times",
|
|
2016
|
+
onClick: () => setStep("time"),
|
|
2017
|
+
children: "\u2039"
|
|
2018
|
+
}
|
|
2019
|
+
),
|
|
2020
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
2021
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: "Enter details" }),
|
|
2022
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
|
|
2023
|
+
selectedType?.location ? /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: selectedType.location }) : null
|
|
2024
|
+
] })
|
|
2025
|
+
] }),
|
|
2026
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__identity", children: [
|
|
2027
|
+
/* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-name`, children: [
|
|
2028
|
+
/* @__PURE__ */ jsx4("span", { children: "Name" }),
|
|
2029
|
+
/* @__PURE__ */ jsx4(
|
|
2030
|
+
"input",
|
|
2031
|
+
{
|
|
2032
|
+
id: `${fieldId}-name`,
|
|
2033
|
+
autoComplete: "name",
|
|
2034
|
+
value: name,
|
|
2035
|
+
onChange: (event) => setName(event.target.value),
|
|
2036
|
+
required: true
|
|
2037
|
+
}
|
|
2038
|
+
)
|
|
2039
|
+
] }),
|
|
2040
|
+
/* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-email`, children: [
|
|
2041
|
+
/* @__PURE__ */ jsx4("span", { children: "Email" }),
|
|
2042
|
+
/* @__PURE__ */ jsx4(
|
|
2043
|
+
"input",
|
|
2044
|
+
{
|
|
2045
|
+
id: `${fieldId}-email`,
|
|
2046
|
+
type: "email",
|
|
2047
|
+
autoComplete: "email",
|
|
2048
|
+
value: email,
|
|
2049
|
+
onChange: (event) => setEmail(event.target.value),
|
|
2050
|
+
required: true
|
|
2051
|
+
}
|
|
2052
|
+
)
|
|
2053
|
+
] })
|
|
2054
|
+
] }),
|
|
2055
|
+
/* @__PURE__ */ jsx4("button", { type: "submit", className: "booking-card__submit", children: "Book this time" })
|
|
2056
|
+
] }, "details") : null
|
|
2057
|
+
] }) });
|
|
2058
|
+
}
|
|
2059
|
+
|
|
1417
2060
|
// src/react/components/MessageBubble/MessageBubble.tsx
|
|
1418
2061
|
import { Streamdown } from "streamdown";
|
|
1419
2062
|
import "streamdown/styles.css";
|
|
1420
|
-
import { jsx as
|
|
1421
|
-
function MessageBubble({
|
|
2063
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2064
|
+
function MessageBubble({
|
|
2065
|
+
message,
|
|
2066
|
+
offer,
|
|
2067
|
+
onBook
|
|
2068
|
+
}) {
|
|
2069
|
+
const cards = message.role === "agent" ? extractToolCards(message.text) : [];
|
|
2070
|
+
const extractedOffers = cards.filter(
|
|
2071
|
+
(card) => card.type === "booking_offer"
|
|
2072
|
+
);
|
|
2073
|
+
const offers = offer ? [offer] : extractedOffers;
|
|
2074
|
+
const visibleText = hideToolCardFences(message.text);
|
|
2075
|
+
const isStreaming = message.role === "agent" && Boolean(message.streaming);
|
|
2076
|
+
const displayText = offers.length > 0 ? visibleText || "Pick a date and time that works for you." : visibleText || (isStreaming ? "" : message.text);
|
|
1422
2077
|
if (message.role === "visitor") {
|
|
1423
|
-
return /* @__PURE__ */
|
|
2078
|
+
return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx5("p", { className: "message-bubble__text", children: message.text }) });
|
|
1424
2079
|
}
|
|
1425
|
-
return /* @__PURE__ */
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
2080
|
+
return /* @__PURE__ */ jsxs5("article", { className: "message-bubble message-bubble--agent", children: [
|
|
2081
|
+
displayText ? /* @__PURE__ */ jsx5("div", { className: "message-bubble__text", children: /* @__PURE__ */ jsx5(
|
|
2082
|
+
Streamdown,
|
|
2083
|
+
{
|
|
2084
|
+
animated: true,
|
|
2085
|
+
caret: "circle",
|
|
2086
|
+
className: "message-bubble__markdown",
|
|
2087
|
+
controls: false,
|
|
2088
|
+
isAnimating: isStreaming,
|
|
2089
|
+
linkSafety: { enabled: false },
|
|
2090
|
+
mode: isStreaming ? "streaming" : "static",
|
|
2091
|
+
skipHtml: true,
|
|
2092
|
+
children: displayText
|
|
2093
|
+
}
|
|
2094
|
+
) }) : null,
|
|
2095
|
+
offers.map((nextOffer, index) => /* @__PURE__ */ jsx5(
|
|
2096
|
+
BookingCard,
|
|
2097
|
+
{
|
|
2098
|
+
offer: nextOffer,
|
|
2099
|
+
onBook
|
|
2100
|
+
},
|
|
2101
|
+
`${bookingOfferIdentityKey(nextOffer)}-${index}`
|
|
2102
|
+
))
|
|
2103
|
+
] });
|
|
1439
2104
|
}
|
|
1440
2105
|
|
|
1441
2106
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1442
|
-
import { jsx as
|
|
2107
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1443
2108
|
function MinimizeIcon() {
|
|
1444
|
-
return /* @__PURE__ */
|
|
2109
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1445
2110
|
"path",
|
|
1446
2111
|
{
|
|
1447
2112
|
d: "M3.5 8h9",
|
|
@@ -1452,7 +2117,7 @@ function MinimizeIcon() {
|
|
|
1452
2117
|
) });
|
|
1453
2118
|
}
|
|
1454
2119
|
function CloseIcon() {
|
|
1455
|
-
return /* @__PURE__ */
|
|
2120
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1456
2121
|
"path",
|
|
1457
2122
|
{
|
|
1458
2123
|
d: "M4 4l8 8M12 4l-8 8",
|
|
@@ -1463,7 +2128,7 @@ function CloseIcon() {
|
|
|
1463
2128
|
) });
|
|
1464
2129
|
}
|
|
1465
2130
|
function NewChatIcon() {
|
|
1466
|
-
return /* @__PURE__ */
|
|
2131
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1467
2132
|
"path",
|
|
1468
2133
|
{
|
|
1469
2134
|
d: "M9.5 3.5h3v3M12.25 3.75 8 8M7 4H4.5A1.5 1.5 0 0 0 3 5.5v6A1.5 1.5 0 0 0 4.5 13h6a1.5 1.5 0 0 0 1.5-1.5V9",
|
|
@@ -1475,7 +2140,7 @@ function NewChatIcon() {
|
|
|
1475
2140
|
) });
|
|
1476
2141
|
}
|
|
1477
2142
|
function ExpandIcon() {
|
|
1478
|
-
return /* @__PURE__ */
|
|
2143
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1479
2144
|
"path",
|
|
1480
2145
|
{
|
|
1481
2146
|
d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
|
|
@@ -1487,7 +2152,7 @@ function ExpandIcon() {
|
|
|
1487
2152
|
) });
|
|
1488
2153
|
}
|
|
1489
2154
|
function RestoreIcon() {
|
|
1490
|
-
return /* @__PURE__ */
|
|
2155
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1491
2156
|
"path",
|
|
1492
2157
|
{
|
|
1493
2158
|
d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
|
|
@@ -1513,10 +2178,10 @@ function AgentRail({
|
|
|
1513
2178
|
onReset,
|
|
1514
2179
|
onRetry,
|
|
1515
2180
|
onSubmit,
|
|
1516
|
-
onFollowUpSelect
|
|
2181
|
+
onFollowUpSelect,
|
|
2182
|
+
onBook
|
|
1517
2183
|
}) {
|
|
1518
2184
|
const transcriptRef = useRef3(null);
|
|
1519
|
-
const welcomeTitleId = useId();
|
|
1520
2185
|
const resolvedTheme = { ...defaultAgentRailTheme, ...theme };
|
|
1521
2186
|
const railStyle = {
|
|
1522
2187
|
"--rail-width": resolvedTheme.railMaxWidth,
|
|
@@ -1556,6 +2221,12 @@ function AgentRail({
|
|
|
1556
2221
|
role: "agent",
|
|
1557
2222
|
streaming: true,
|
|
1558
2223
|
text: state.streamingText
|
|
2224
|
+
} : state.pendingOffer ? {
|
|
2225
|
+
createdAt: 0,
|
|
2226
|
+
id: "pending-booking",
|
|
2227
|
+
role: "agent",
|
|
2228
|
+
streaming: false,
|
|
2229
|
+
text: "Pick a date and time that works for you."
|
|
1559
2230
|
} : null;
|
|
1560
2231
|
useEffect2(() => {
|
|
1561
2232
|
const node = transcriptRef.current;
|
|
@@ -1568,7 +2239,7 @@ function AgentRail({
|
|
|
1568
2239
|
state.followUps,
|
|
1569
2240
|
state.journey
|
|
1570
2241
|
]);
|
|
1571
|
-
return /* @__PURE__ */
|
|
2242
|
+
return /* @__PURE__ */ jsxs6(
|
|
1572
2243
|
"aside",
|
|
1573
2244
|
{
|
|
1574
2245
|
className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
|
|
@@ -1579,30 +2250,30 @@ function AgentRail({
|
|
|
1579
2250
|
role: mobileFullscreen || expanded ? "dialog" : void 0,
|
|
1580
2251
|
tabIndex: mobileFullscreen || expanded ? -1 : void 0,
|
|
1581
2252
|
children: [
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
onCollapse ? /* @__PURE__ */
|
|
2253
|
+
/* @__PURE__ */ jsx6("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs6("div", { className: "agent-rail__brand-row", children: [
|
|
2254
|
+
onCollapse ? /* @__PURE__ */ jsx6(
|
|
1584
2255
|
"button",
|
|
1585
2256
|
{
|
|
1586
2257
|
type: "button",
|
|
1587
2258
|
className: "agent-rail__collapse",
|
|
1588
2259
|
"aria-label": "Collapse assist",
|
|
1589
2260
|
onClick: onCollapse,
|
|
1590
|
-
children: /* @__PURE__ */
|
|
2261
|
+
children: /* @__PURE__ */ jsx6(MinimizeIcon, {})
|
|
1591
2262
|
}
|
|
1592
|
-
) : onClose ? /* @__PURE__ */
|
|
2263
|
+
) : onClose ? /* @__PURE__ */ jsx6(
|
|
1593
2264
|
"button",
|
|
1594
2265
|
{
|
|
1595
2266
|
type: "button",
|
|
1596
2267
|
className: "agent-rail__close",
|
|
1597
2268
|
"aria-label": "Close agent",
|
|
1598
2269
|
onClick: onClose,
|
|
1599
|
-
children: /* @__PURE__ */
|
|
2270
|
+
children: /* @__PURE__ */ jsx6(CloseIcon, {})
|
|
1600
2271
|
}
|
|
1601
|
-
) : /* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
2272
|
+
) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
|
|
2273
|
+
/* @__PURE__ */ jsxs6("span", { className: "agent-rail__identity", children: [
|
|
2274
|
+
/* @__PURE__ */ jsxs6("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: [
|
|
1604
2275
|
brandLabel.slice(0, 1).toUpperCase(),
|
|
1605
|
-
brandLogoUrl ? /* @__PURE__ */
|
|
2276
|
+
brandLogoUrl ? /* @__PURE__ */ jsx6(
|
|
1606
2277
|
"img",
|
|
1607
2278
|
{
|
|
1608
2279
|
className: "agent-rail__brand-logo",
|
|
@@ -1614,10 +2285,10 @@ function AgentRail({
|
|
|
1614
2285
|
}
|
|
1615
2286
|
) : null
|
|
1616
2287
|
] }),
|
|
1617
|
-
/* @__PURE__ */
|
|
2288
|
+
/* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-label", children: brandLabel })
|
|
1618
2289
|
] }),
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
onReset ? /* @__PURE__ */
|
|
2290
|
+
/* @__PURE__ */ jsxs6("span", { className: "agent-rail__actions", children: [
|
|
2291
|
+
onReset ? /* @__PURE__ */ jsx6(
|
|
1621
2292
|
"button",
|
|
1622
2293
|
{
|
|
1623
2294
|
type: "button",
|
|
@@ -1625,60 +2296,37 @@ function AgentRail({
|
|
|
1625
2296
|
"aria-label": "Start a new conversation",
|
|
1626
2297
|
disabled: !hasVisitorMessages2,
|
|
1627
2298
|
onClick: onReset,
|
|
1628
|
-
children: /* @__PURE__ */
|
|
2299
|
+
children: /* @__PURE__ */ jsx6(NewChatIcon, {})
|
|
1629
2300
|
}
|
|
1630
2301
|
) : null,
|
|
1631
|
-
onExpandToggle ? /* @__PURE__ */
|
|
2302
|
+
onExpandToggle ? /* @__PURE__ */ jsx6(
|
|
1632
2303
|
"button",
|
|
1633
2304
|
{
|
|
1634
2305
|
type: "button",
|
|
1635
2306
|
className: "agent-rail__expand",
|
|
1636
2307
|
"aria-label": expanded ? "Exit focus view" : "Open focus view",
|
|
1637
2308
|
onClick: onExpandToggle,
|
|
1638
|
-
children: expanded ? /* @__PURE__ */
|
|
2309
|
+
children: expanded ? /* @__PURE__ */ jsx6(RestoreIcon, {}) : /* @__PURE__ */ jsx6(ExpandIcon, {})
|
|
1639
2310
|
}
|
|
1640
2311
|
) : null
|
|
1641
2312
|
] })
|
|
1642
2313
|
] }) }),
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
!hasVisitorMessages2 ? /* @__PURE__ */
|
|
1645
|
-
"
|
|
1646
|
-
{
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
event.currentTarget.hidden = true;
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
) : null
|
|
1663
|
-
] }),
|
|
1664
|
-
/* @__PURE__ */ jsxs4("div", { className: "agent-rail__welcome-copy", children: [
|
|
1665
|
-
/* @__PURE__ */ jsx5("h2", { id: welcomeTitleId, children: "What can I help you find?" }),
|
|
1666
|
-
greeting?.role === "agent" ? /* @__PURE__ */ jsx5("p", { children: greeting.text }) : null
|
|
1667
|
-
] }),
|
|
1668
|
-
showIdleFollowUps ? /* @__PURE__ */ jsx5("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx5(
|
|
1669
|
-
FollowUpChips,
|
|
1670
|
-
{
|
|
1671
|
-
suggestions: state.followUps,
|
|
1672
|
-
disabled: isBusy,
|
|
1673
|
-
label: "Start here",
|
|
1674
|
-
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
1675
|
-
}
|
|
1676
|
-
) }) : null
|
|
1677
|
-
]
|
|
1678
|
-
}
|
|
1679
|
-
) : null,
|
|
1680
|
-
transcriptMessages.map((message) => /* @__PURE__ */ jsx5(MessageBubble, { message }, message.id)),
|
|
1681
|
-
showActivity ? /* @__PURE__ */ jsx5(
|
|
2314
|
+
/* @__PURE__ */ jsx6("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ jsxs6("div", { className: "agent-rail__thread", children: [
|
|
2315
|
+
!hasVisitorMessages2 ? /* @__PURE__ */ jsxs6("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
|
|
2316
|
+
greeting?.role === "agent" ? /* @__PURE__ */ jsx6(MessageBubble, { message: greeting, onBook }) : null,
|
|
2317
|
+
showIdleFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
2318
|
+
FollowUpChips,
|
|
2319
|
+
{
|
|
2320
|
+
suggestions: state.followUps,
|
|
2321
|
+
disabled: isBusy,
|
|
2322
|
+
label: "Start here",
|
|
2323
|
+
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
2324
|
+
}
|
|
2325
|
+
) }) : null
|
|
2326
|
+
] }) : null,
|
|
2327
|
+
transcriptMessages.map((message) => /* @__PURE__ */ jsx6(MessageBubble, { message, onBook }, message.id)),
|
|
2328
|
+
completedAnswer ? /* @__PURE__ */ jsx6(MessageBubble, { message: completedAnswer, onBook }) : null,
|
|
2329
|
+
showActivity ? /* @__PURE__ */ jsx6(
|
|
1682
2330
|
AgentActivityBubble,
|
|
1683
2331
|
{
|
|
1684
2332
|
brandLabel,
|
|
@@ -1687,18 +2335,24 @@ function AgentRail({
|
|
|
1687
2335
|
steps: state.toolSteps
|
|
1688
2336
|
}
|
|
1689
2337
|
) : null,
|
|
1690
|
-
streamingMessage ? /* @__PURE__ */
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
2338
|
+
streamingMessage ? /* @__PURE__ */ jsx6(
|
|
2339
|
+
MessageBubble,
|
|
2340
|
+
{
|
|
2341
|
+
message: streamingMessage,
|
|
2342
|
+
offer: state.pendingOffer,
|
|
2343
|
+
onBook
|
|
2344
|
+
}
|
|
2345
|
+
) : null,
|
|
2346
|
+
state.error ? /* @__PURE__ */ jsxs6("section", { className: "agent-rail__error", role: "alert", children: [
|
|
2347
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
2348
|
+
/* @__PURE__ */ jsx6("strong", { children: "Something went wrong" }),
|
|
2349
|
+
/* @__PURE__ */ jsx6("p", { children: state.error })
|
|
1696
2350
|
] }),
|
|
1697
|
-
onRetry ? /* @__PURE__ */
|
|
2351
|
+
onRetry ? /* @__PURE__ */ jsx6("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
|
|
1698
2352
|
] }) : null
|
|
1699
2353
|
] }) }),
|
|
1700
|
-
/* @__PURE__ */
|
|
1701
|
-
/* @__PURE__ */
|
|
2354
|
+
/* @__PURE__ */ jsxs6("div", { className: "agent-rail__composer-wrap", children: [
|
|
2355
|
+
/* @__PURE__ */ jsx6(
|
|
1702
2356
|
Composer,
|
|
1703
2357
|
{
|
|
1704
2358
|
variant: expanded || mobileFullscreen ? "dock" : "default",
|
|
@@ -1707,10 +2361,9 @@ function AgentRail({
|
|
|
1707
2361
|
onSubmit
|
|
1708
2362
|
}
|
|
1709
2363
|
),
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */ jsx5("span", { children: poweredByLabel })
|
|
2364
|
+
/* @__PURE__ */ jsx6("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsxs6("p", { children: [
|
|
2365
|
+
/* @__PURE__ */ jsx6("span", { children: "AI can make mistakes. Check important info." }),
|
|
2366
|
+
/* @__PURE__ */ jsx6("span", { children: poweredByLabel })
|
|
1714
2367
|
] }) })
|
|
1715
2368
|
] })
|
|
1716
2369
|
]
|
|
@@ -1719,9 +2372,9 @@ function AgentRail({
|
|
|
1719
2372
|
}
|
|
1720
2373
|
|
|
1721
2374
|
// src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
|
|
1722
|
-
import { Fragment as Fragment2, jsx as
|
|
2375
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1723
2376
|
function SparklesIcon() {
|
|
1724
|
-
return /* @__PURE__ */
|
|
2377
|
+
return /* @__PURE__ */ jsxs7(
|
|
1725
2378
|
"svg",
|
|
1726
2379
|
{
|
|
1727
2380
|
className: "assist-edge-tab__sparkles",
|
|
@@ -1729,21 +2382,21 @@ function SparklesIcon() {
|
|
|
1729
2382
|
fill: "none",
|
|
1730
2383
|
"aria-hidden": "true",
|
|
1731
2384
|
children: [
|
|
1732
|
-
/* @__PURE__ */
|
|
2385
|
+
/* @__PURE__ */ jsx7(
|
|
1733
2386
|
"path",
|
|
1734
2387
|
{
|
|
1735
2388
|
d: "M8 1.2l.95 2.7 2.85.05-2.25 1.75.8 2.75L8 6.7 5.65 8.45l.8-2.75L4.2 3.95l2.85-.05L8 1.2z",
|
|
1736
2389
|
fill: "currentColor"
|
|
1737
2390
|
}
|
|
1738
2391
|
),
|
|
1739
|
-
/* @__PURE__ */
|
|
2392
|
+
/* @__PURE__ */ jsx7(
|
|
1740
2393
|
"path",
|
|
1741
2394
|
{
|
|
1742
2395
|
d: "M14.2 6.4l.55 1.55 1.65.03-1.3 1 .46 1.58-1.36-1-1.36 1 .46-1.58-1.3-1 1.65-.03.55-1.55z",
|
|
1743
2396
|
fill: "currentColor"
|
|
1744
2397
|
}
|
|
1745
2398
|
),
|
|
1746
|
-
/* @__PURE__ */
|
|
2399
|
+
/* @__PURE__ */ jsx7(
|
|
1747
2400
|
"path",
|
|
1748
2401
|
{
|
|
1749
2402
|
d: "M3.1 9.1l.4 1.15 1.22.02-.96.74.34 1.17-1-.74-1 .74.34-1.17-.96-.74 1.22-.02.4-1.15z",
|
|
@@ -1754,8 +2407,23 @@ function SparklesIcon() {
|
|
|
1754
2407
|
}
|
|
1755
2408
|
);
|
|
1756
2409
|
}
|
|
2410
|
+
function TabMarkIcon({ customIconUrl }) {
|
|
2411
|
+
const url = customIconUrl?.trim();
|
|
2412
|
+
if (url) {
|
|
2413
|
+
return /* @__PURE__ */ jsx7(
|
|
2414
|
+
"img",
|
|
2415
|
+
{
|
|
2416
|
+
alt: "",
|
|
2417
|
+
"aria-hidden": true,
|
|
2418
|
+
className: "assist-edge-tab__custom-icon",
|
|
2419
|
+
src: url
|
|
2420
|
+
}
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
return /* @__PURE__ */ jsx7(SparklesIcon, {});
|
|
2424
|
+
}
|
|
1757
2425
|
function ChevronLeftIcon() {
|
|
1758
|
-
return /* @__PURE__ */
|
|
2426
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
1759
2427
|
"path",
|
|
1760
2428
|
{
|
|
1761
2429
|
d: "M10 4L6 8l4 4",
|
|
@@ -1767,7 +2435,7 @@ function ChevronLeftIcon() {
|
|
|
1767
2435
|
) });
|
|
1768
2436
|
}
|
|
1769
2437
|
function ChevronDownIcon() {
|
|
1770
|
-
return /* @__PURE__ */
|
|
2438
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
1771
2439
|
"path",
|
|
1772
2440
|
{
|
|
1773
2441
|
d: "M4 6l4 4 4-4",
|
|
@@ -1779,7 +2447,7 @@ function ChevronDownIcon() {
|
|
|
1779
2447
|
) });
|
|
1780
2448
|
}
|
|
1781
2449
|
function DragDots() {
|
|
1782
|
-
return /* @__PURE__ */
|
|
2450
|
+
return /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx7("i", {}, index)) });
|
|
1783
2451
|
}
|
|
1784
2452
|
var VARIANT_COPY = {
|
|
1785
2453
|
outline: { label: "Assist", aria: "Open Assist" },
|
|
@@ -1793,6 +2461,7 @@ function AssistEdgeTab({
|
|
|
1793
2461
|
inset,
|
|
1794
2462
|
visible,
|
|
1795
2463
|
label,
|
|
2464
|
+
customIconUrl,
|
|
1796
2465
|
logoUrl,
|
|
1797
2466
|
brandColor,
|
|
1798
2467
|
brandForeground,
|
|
@@ -1805,6 +2474,7 @@ function AssistEdgeTab({
|
|
|
1805
2474
|
}) {
|
|
1806
2475
|
const copy = VARIANT_COPY[variant];
|
|
1807
2476
|
const visibleLabel = label?.trim() || copy.label;
|
|
2477
|
+
const showLogo = Boolean(logoUrl?.trim()) && !customIconUrl?.trim();
|
|
1808
2478
|
const style = {
|
|
1809
2479
|
"--tab-along": `${along}%`,
|
|
1810
2480
|
"--tab-inset": `${inset}px`,
|
|
@@ -1815,7 +2485,7 @@ function AssistEdgeTab({
|
|
|
1815
2485
|
...surfaceColor ? { "--as-surface": surfaceColor } : {},
|
|
1816
2486
|
...textColor ? { "--as-text": textColor } : {}
|
|
1817
2487
|
};
|
|
1818
|
-
return /* @__PURE__ */
|
|
2488
|
+
return /* @__PURE__ */ jsxs7(
|
|
1819
2489
|
"button",
|
|
1820
2490
|
{
|
|
1821
2491
|
type: "button",
|
|
@@ -1826,15 +2496,15 @@ function AssistEdgeTab({
|
|
|
1826
2496
|
tabIndex: visible ? 0 : -1,
|
|
1827
2497
|
onClick: onOpen,
|
|
1828
2498
|
children: [
|
|
1829
|
-
mobile ? /* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
2499
|
+
mobile ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2500
|
+
/* @__PURE__ */ jsxs7(
|
|
1831
2501
|
"span",
|
|
1832
2502
|
{
|
|
1833
2503
|
className: "assist-edge-tab__mark assist-edge-tab__mark--mobile",
|
|
1834
2504
|
"aria-hidden": "true",
|
|
1835
2505
|
children: [
|
|
1836
|
-
visibleLabel.slice(0, 1).toUpperCase(),
|
|
1837
|
-
|
|
2506
|
+
customIconUrl?.trim() ? /* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }) : visibleLabel.slice(0, 1).toUpperCase(),
|
|
2507
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1838
2508
|
"img",
|
|
1839
2509
|
{
|
|
1840
2510
|
className: "assist-edge-tab__logo",
|
|
@@ -1848,14 +2518,14 @@ function AssistEdgeTab({
|
|
|
1848
2518
|
]
|
|
1849
2519
|
}
|
|
1850
2520
|
),
|
|
1851
|
-
/* @__PURE__ */
|
|
2521
|
+
/* @__PURE__ */ jsxs7("span", { className: "assist-edge-tab__label", children: [
|
|
1852
2522
|
"Ask ",
|
|
1853
2523
|
visibleLabel
|
|
1854
2524
|
] })
|
|
1855
|
-
] }) : variant === "outline" ? /* @__PURE__ */
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
|
|
2525
|
+
] }) : variant === "outline" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2526
|
+
/* @__PURE__ */ jsxs7("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
2527
|
+
/* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }),
|
|
2528
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1859
2529
|
"img",
|
|
1860
2530
|
{
|
|
1861
2531
|
className: "assist-edge-tab__logo",
|
|
@@ -1867,18 +2537,18 @@ function AssistEdgeTab({
|
|
|
1867
2537
|
}
|
|
1868
2538
|
) : null
|
|
1869
2539
|
] }),
|
|
1870
|
-
/* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
2540
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2541
|
+
/* @__PURE__ */ jsx7(ChevronDownIcon, {})
|
|
1872
2542
|
] }) : null,
|
|
1873
|
-
variant === "ask" ? /* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
/* @__PURE__ */
|
|
2543
|
+
variant === "ask" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2544
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {}),
|
|
2545
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2546
|
+
/* @__PURE__ */ jsx7(DragDots, {})
|
|
1877
2547
|
] }) : null,
|
|
1878
|
-
variant === "fill" ? /* @__PURE__ */
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
|
|
2548
|
+
variant === "fill" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2549
|
+
/* @__PURE__ */ jsxs7("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
2550
|
+
/* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }),
|
|
2551
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1882
2552
|
"img",
|
|
1883
2553
|
{
|
|
1884
2554
|
className: "assist-edge-tab__logo",
|
|
@@ -1890,8 +2560,8 @@ function AssistEdgeTab({
|
|
|
1890
2560
|
}
|
|
1891
2561
|
) : null
|
|
1892
2562
|
] }),
|
|
1893
|
-
/* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
2563
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2564
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {})
|
|
1895
2565
|
] }) : null
|
|
1896
2566
|
]
|
|
1897
2567
|
}
|
|
@@ -1899,7 +2569,7 @@ function AssistEdgeTab({
|
|
|
1899
2569
|
}
|
|
1900
2570
|
|
|
1901
2571
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
1902
|
-
import { useEffect as useEffect5, useRef as useRef4, useState as
|
|
2572
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
|
|
1903
2573
|
|
|
1904
2574
|
// src/react/page-shift.ts
|
|
1905
2575
|
import { useEffect as useEffect3 } from "react";
|
|
@@ -1982,9 +2652,9 @@ function usePageShift(input) {
|
|
|
1982
2652
|
}
|
|
1983
2653
|
|
|
1984
2654
|
// src/react/hooks/useIsMobile.ts
|
|
1985
|
-
import { useEffect as useEffect4, useState as
|
|
2655
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
1986
2656
|
function useIsMobile(breakpoint = 767) {
|
|
1987
|
-
const [isMobile, setIsMobile] =
|
|
2657
|
+
const [isMobile, setIsMobile] = useState4(
|
|
1988
2658
|
() => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1989
2659
|
);
|
|
1990
2660
|
useEffect4(() => {
|
|
@@ -2013,7 +2683,7 @@ function closeAgentPanel(customerId) {
|
|
|
2013
2683
|
}
|
|
2014
2684
|
|
|
2015
2685
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
2016
|
-
import { jsx as
|
|
2686
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2017
2687
|
function AgentWidget({
|
|
2018
2688
|
indexId,
|
|
2019
2689
|
customerId,
|
|
@@ -2030,8 +2700,8 @@ function AgentWidget({
|
|
|
2030
2700
|
const isMobile = useIsMobile();
|
|
2031
2701
|
const placement = normalizeAgentPlacement(placementInput);
|
|
2032
2702
|
const railSlotRef = useRef4(null);
|
|
2033
|
-
const [railCollapsed, setRailCollapsed] =
|
|
2034
|
-
const [railExpanded, setRailExpanded] =
|
|
2703
|
+
const [railCollapsed, setRailCollapsed] = useState5(defaultCollapsed);
|
|
2704
|
+
const [railExpanded, setRailExpanded] = useState5(false);
|
|
2035
2705
|
const pageShiftActive = shouldApplyPageShift({
|
|
2036
2706
|
pageShift,
|
|
2037
2707
|
isMobile,
|
|
@@ -2052,6 +2722,7 @@ function AgentWidget({
|
|
|
2052
2722
|
greeting: branding?.greeting
|
|
2053
2723
|
});
|
|
2054
2724
|
const agentName = branding?.agentName ?? "Webless Guide";
|
|
2725
|
+
const tabLabel = branding?.tabLabel ?? agentName;
|
|
2055
2726
|
const theme = {
|
|
2056
2727
|
...branding?.fontFamily ? { fontBody: branding.fontFamily, fontDisplay: branding.fontFamily } : {},
|
|
2057
2728
|
...branding?.colors?.primary ? {
|
|
@@ -2069,7 +2740,6 @@ function AgentWidget({
|
|
|
2069
2740
|
} : {},
|
|
2070
2741
|
...branding?.colors?.border ? { border: branding.colors.border } : {}
|
|
2071
2742
|
};
|
|
2072
|
-
const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
|
|
2073
2743
|
useEffect5(() => {
|
|
2074
2744
|
if (!registerPanelController) return;
|
|
2075
2745
|
registerAgentPanelController(customerId, {
|
|
@@ -2119,31 +2789,28 @@ function AgentWidget({
|
|
|
2119
2789
|
window.addEventListener("keydown", handleKeyDown);
|
|
2120
2790
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2121
2791
|
}, [isMobile, railCollapsed, railExpanded]);
|
|
2122
|
-
return /* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2792
|
+
return /* @__PURE__ */ jsxs8("div", { className: "webless-agent-root", children: [
|
|
2793
|
+
/* @__PURE__ */ jsxs8(
|
|
2124
2794
|
"div",
|
|
2125
2795
|
{
|
|
2126
2796
|
className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
|
|
2127
2797
|
children: [
|
|
2128
|
-
/* @__PURE__ */
|
|
2798
|
+
/* @__PURE__ */ jsx8(
|
|
2129
2799
|
"div",
|
|
2130
2800
|
{
|
|
2131
2801
|
ref: railSlotRef,
|
|
2132
2802
|
className: "webless-agent-root__rail-slot",
|
|
2133
2803
|
inert: railCollapsed || void 0,
|
|
2134
2804
|
"aria-hidden": railCollapsed,
|
|
2135
|
-
children: /* @__PURE__ */
|
|
2805
|
+
children: /* @__PURE__ */ jsx8(
|
|
2136
2806
|
AgentRail,
|
|
2137
2807
|
{
|
|
2138
2808
|
theme,
|
|
2139
2809
|
brandLabel: agentName,
|
|
2140
2810
|
brandLogoUrl: branding?.logoUrl,
|
|
2141
|
-
composerPlaceholder: branding?.composerPlaceholder ??
|
|
2811
|
+
composerPlaceholder: branding?.composerPlaceholder ?? "Ask as a visitor\u2026",
|
|
2142
2812
|
poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
|
|
2143
|
-
state
|
|
2144
|
-
...state,
|
|
2145
|
-
followUps: createIdleSuggestions()
|
|
2146
|
-
} : state,
|
|
2813
|
+
state,
|
|
2147
2814
|
mobileFullscreen: isMobile && !railCollapsed,
|
|
2148
2815
|
expanded: railExpanded,
|
|
2149
2816
|
onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
|
|
@@ -2152,12 +2819,13 @@ function AgentWidget({
|
|
|
2152
2819
|
onSubmit: handleSubmit,
|
|
2153
2820
|
onReset: reset,
|
|
2154
2821
|
onRetry: () => void retry(),
|
|
2155
|
-
onFollowUpSelect: (label) => void handleSubmit(label)
|
|
2822
|
+
onFollowUpSelect: (label) => void handleSubmit(label),
|
|
2823
|
+
onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
|
|
2156
2824
|
}
|
|
2157
2825
|
)
|
|
2158
2826
|
}
|
|
2159
2827
|
),
|
|
2160
|
-
!railCollapsed && isMobile || !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */
|
|
2828
|
+
!railCollapsed && isMobile || !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx8(
|
|
2161
2829
|
"button",
|
|
2162
2830
|
{
|
|
2163
2831
|
type: "button",
|
|
@@ -2176,7 +2844,7 @@ function AgentWidget({
|
|
|
2176
2844
|
]
|
|
2177
2845
|
}
|
|
2178
2846
|
),
|
|
2179
|
-
railCollapsed ? /* @__PURE__ */
|
|
2847
|
+
railCollapsed ? /* @__PURE__ */ jsx8(
|
|
2180
2848
|
AssistEdgeTab,
|
|
2181
2849
|
{
|
|
2182
2850
|
variant: placement.variant,
|
|
@@ -2184,7 +2852,8 @@ function AgentWidget({
|
|
|
2184
2852
|
along: placement.along,
|
|
2185
2853
|
inset: placement.inset,
|
|
2186
2854
|
visible: true,
|
|
2187
|
-
label:
|
|
2855
|
+
label: tabLabel,
|
|
2856
|
+
customIconUrl: branding?.tabIconUrl,
|
|
2188
2857
|
logoUrl: branding?.logoUrl,
|
|
2189
2858
|
brandColor: branding?.colors?.primary,
|
|
2190
2859
|
brandForeground: branding?.colors?.primaryForeground,
|
|
@@ -2215,4 +2884,4 @@ export {
|
|
|
2215
2884
|
AssistEdgeTab,
|
|
2216
2885
|
AgentWidget
|
|
2217
2886
|
};
|
|
2218
|
-
//# sourceMappingURL=chunk-
|
|
2887
|
+
//# sourceMappingURL=chunk-E4JSTYPX.js.map
|