@webless/agent 0.4.1 → 0.6.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-Y7Z3ZIAQ.js} +1090 -281
- package/dist/chunk-Y7Z3ZIAQ.js.map +1 -0
- package/dist/embed.cjs +1100 -296
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.css +416 -205
- 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-D9V3kLCd.d.cts +183 -0
- package/dist/manifest-D9V3kLCd.d.ts +183 -0
- package/dist/react.cjs +1094 -284
- package/dist/react.cjs.map +1 -1
- package/dist/react.css +416 -205
- package/dist/react.css.map +1 -1
- package/dist/react.d.cts +14 -73
- package/dist/react.d.ts +14 -73
- package/dist/react.js +3 -1
- package/package.json +1 -1
- package/dist/chunk-SVWXFDV3.js.map +0 -1
- package/dist/manifest-C8l7WUf6.d.cts +0 -84
- package/dist/manifest-C8l7WUf6.d.ts +0 -84
|
@@ -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,8 +744,248 @@ 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
|
-
var CONVERSATION_VERSION =
|
|
988
|
+
var CONVERSATION_VERSION = 2;
|
|
712
989
|
function conversationKey(storageKeyPrefix, visitorSessionId) {
|
|
713
990
|
return `${storageKeyPrefix}:conversation:${visitorSessionId}`;
|
|
714
991
|
}
|
|
@@ -718,13 +995,39 @@ 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 parseToolStep(value) {
|
|
1015
|
+
if (typeof value !== "object" || value === null) return null;
|
|
1016
|
+
const record = value;
|
|
1017
|
+
if (typeof record.id !== "string" || record.kind !== "planning" && record.kind !== "search" && record.kind !== "specialist" || typeof record.label !== "string" || record.state !== "completed" && record.state !== "active" && record.state !== "pending" && record.state !== "error") {
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
return {
|
|
1021
|
+
id: record.id,
|
|
1022
|
+
kind: record.kind,
|
|
1023
|
+
label: record.label,
|
|
1024
|
+
state: record.state,
|
|
1025
|
+
...typeof record.detail === "string" && record.detail ? { detail: record.detail } : {}
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
function visitorTurnText(message) {
|
|
1029
|
+
return message.role === "visitor" && message.runtimeText ? message.runtimeText : message.text;
|
|
1030
|
+
}
|
|
728
1031
|
function loadPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
729
1032
|
if (typeof sessionStorage === "undefined") return null;
|
|
730
1033
|
const raw = sessionStorage.getItem(conversationKey(storageKeyPrefix, visitorSessionId));
|
|
@@ -733,15 +1036,19 @@ function loadPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
|
733
1036
|
const value = JSON.parse(raw);
|
|
734
1037
|
if (typeof value !== "object" || value === null) return null;
|
|
735
1038
|
const record = value;
|
|
736
|
-
if (record.version !== CONVERSATION_VERSION || !Array.isArray(record.messages) || typeof record.pending !== "boolean" || typeof record.streamingText !== "string") {
|
|
1039
|
+
if (record.version !== 1 && record.version !== CONVERSATION_VERSION || !Array.isArray(record.messages) || typeof record.pending !== "boolean" || typeof record.streamingText !== "string" || record.version === CONVERSATION_VERSION && !Array.isArray(record.toolSteps)) {
|
|
737
1040
|
return null;
|
|
738
1041
|
}
|
|
739
1042
|
const messages = record.messages.map(parseMessage);
|
|
740
1043
|
if (messages.some((message) => message === null)) return null;
|
|
1044
|
+
const storedToolSteps = record.version === CONVERSATION_VERSION && Array.isArray(record.toolSteps) ? record.toolSteps : [];
|
|
1045
|
+
const toolSteps = storedToolSteps.map(parseToolStep);
|
|
1046
|
+
if (toolSteps.some((step) => step === null)) return null;
|
|
741
1047
|
return {
|
|
742
1048
|
messages: messages.filter((message) => message !== null),
|
|
743
1049
|
pending: record.pending,
|
|
744
|
-
streamingText: record.streamingText
|
|
1050
|
+
streamingText: record.streamingText,
|
|
1051
|
+
toolSteps: toolSteps.filter((step) => step !== null)
|
|
745
1052
|
};
|
|
746
1053
|
} catch {
|
|
747
1054
|
return null;
|
|
@@ -757,6 +1064,42 @@ function savePersistedAgentConversation(storageKeyPrefix, visitorSessionId, conv
|
|
|
757
1064
|
function clearPersistedAgentConversation(storageKeyPrefix, visitorSessionId) {
|
|
758
1065
|
if (typeof sessionStorage === "undefined") return;
|
|
759
1066
|
sessionStorage.removeItem(conversationKey(storageKeyPrefix, visitorSessionId));
|
|
1067
|
+
clearPendingWidgetBooking(storageKeyPrefix, visitorSessionId);
|
|
1068
|
+
}
|
|
1069
|
+
function pendingBookingKey(storageKeyPrefix, visitorSessionId) {
|
|
1070
|
+
return `${storageKeyPrefix}:pending-booking:${visitorSessionId}`;
|
|
1071
|
+
}
|
|
1072
|
+
function loadPendingWidgetBooking(storageKeyPrefix, visitorSessionId) {
|
|
1073
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
1074
|
+
const raw = sessionStorage.getItem(
|
|
1075
|
+
pendingBookingKey(storageKeyPrefix, visitorSessionId)
|
|
1076
|
+
);
|
|
1077
|
+
if (!raw) return null;
|
|
1078
|
+
try {
|
|
1079
|
+
const value = JSON.parse(raw);
|
|
1080
|
+
if (typeof value !== "object" || value === null) return null;
|
|
1081
|
+
const record = value;
|
|
1082
|
+
if (typeof record.eventUri !== "string" || !record.eventUri) return null;
|
|
1083
|
+
return {
|
|
1084
|
+
eventUri: record.eventUri,
|
|
1085
|
+
...typeof record.inviteeUri === "string" && record.inviteeUri ? { inviteeUri: record.inviteeUri } : {},
|
|
1086
|
+
...typeof record.inviteeEmail === "string" && record.inviteeEmail ? { inviteeEmail: record.inviteeEmail } : {},
|
|
1087
|
+
...typeof record.startTime === "string" && record.startTime ? { startTime: record.startTime } : {}
|
|
1088
|
+
};
|
|
1089
|
+
} catch {
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function savePendingWidgetBooking(storageKeyPrefix, visitorSessionId, booking) {
|
|
1094
|
+
if (typeof sessionStorage === "undefined") return;
|
|
1095
|
+
sessionStorage.setItem(
|
|
1096
|
+
pendingBookingKey(storageKeyPrefix, visitorSessionId),
|
|
1097
|
+
JSON.stringify(booking)
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
function clearPendingWidgetBooking(storageKeyPrefix, visitorSessionId) {
|
|
1101
|
+
if (typeof sessionStorage === "undefined") return;
|
|
1102
|
+
sessionStorage.removeItem(pendingBookingKey(storageKeyPrefix, visitorSessionId));
|
|
760
1103
|
}
|
|
761
1104
|
|
|
762
1105
|
// src/react/hooks/useAgentChat.ts
|
|
@@ -776,6 +1119,7 @@ function createInitialState(greeting = DEFAULT_GREETING) {
|
|
|
776
1119
|
journey: null,
|
|
777
1120
|
followUps: [],
|
|
778
1121
|
streamingText: "",
|
|
1122
|
+
pendingOffer: null,
|
|
779
1123
|
error: null
|
|
780
1124
|
};
|
|
781
1125
|
}
|
|
@@ -785,7 +1129,8 @@ function stateFromConversation(conversation, initialState) {
|
|
|
785
1129
|
...initialState,
|
|
786
1130
|
messages: conversation.messages,
|
|
787
1131
|
phase: conversation.pending ? conversation.streamingText ? "streaming" : "thinking" : "complete",
|
|
788
|
-
streamingText: conversation.streamingText
|
|
1132
|
+
streamingText: conversation.streamingText,
|
|
1133
|
+
toolSteps: conversation.toolSteps
|
|
789
1134
|
};
|
|
790
1135
|
}
|
|
791
1136
|
function upsertToolStep(steps, item) {
|
|
@@ -858,6 +1203,9 @@ function useAgentChat({
|
|
|
858
1203
|
initialState
|
|
859
1204
|
)
|
|
860
1205
|
);
|
|
1206
|
+
const pendingBookingRef = useRef(
|
|
1207
|
+
loadPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId)
|
|
1208
|
+
);
|
|
861
1209
|
const runRef = useRef(null);
|
|
862
1210
|
const clientRef = useRef(
|
|
863
1211
|
createAgentClient({
|
|
@@ -890,6 +1238,10 @@ function useAgentChat({
|
|
|
890
1238
|
visitorSessionId: visitorId,
|
|
891
1239
|
storageKeyPrefix: resolvedStorageKeyPrefix
|
|
892
1240
|
});
|
|
1241
|
+
pendingBookingRef.current = loadPendingWidgetBooking(
|
|
1242
|
+
resolvedStorageKeyPrefix,
|
|
1243
|
+
visitorId
|
|
1244
|
+
);
|
|
893
1245
|
setState(
|
|
894
1246
|
stateFromConversation(
|
|
895
1247
|
loadPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId),
|
|
@@ -912,19 +1264,22 @@ function useAgentChat({
|
|
|
912
1264
|
savePersistedAgentConversation(resolvedStorageKeyPrefix, visitorId, {
|
|
913
1265
|
messages: state.messages,
|
|
914
1266
|
pending: isAgentBusy(state.phase),
|
|
915
|
-
streamingText: state.streamingText
|
|
1267
|
+
streamingText: state.streamingText,
|
|
1268
|
+
toolSteps: state.toolSteps
|
|
916
1269
|
});
|
|
917
1270
|
}, [
|
|
918
1271
|
resolvedStorageKeyPrefix,
|
|
919
1272
|
state.messages,
|
|
920
1273
|
state.phase,
|
|
921
1274
|
state.streamingText,
|
|
1275
|
+
state.toolSteps,
|
|
922
1276
|
visitorId
|
|
923
1277
|
]);
|
|
924
1278
|
const reset = useCallback(() => {
|
|
925
1279
|
runRef.current?.abort();
|
|
926
1280
|
runRef.current = null;
|
|
927
1281
|
clientRef.current.reset();
|
|
1282
|
+
pendingBookingRef.current = null;
|
|
928
1283
|
clearPersistedAgentConversation(resolvedStorageKeyPrefix, visitorId);
|
|
929
1284
|
setState(initialState);
|
|
930
1285
|
}, [initialState, resolvedStorageKeyPrefix, visitorId]);
|
|
@@ -936,6 +1291,7 @@ function useAgentChat({
|
|
|
936
1291
|
try {
|
|
937
1292
|
let streamStarted = Boolean(initialText);
|
|
938
1293
|
let streamed = initialText;
|
|
1294
|
+
const capturedOffers = [];
|
|
939
1295
|
const handlers = {
|
|
940
1296
|
onWork: (item) => {
|
|
941
1297
|
if (!isActiveRun()) return;
|
|
@@ -945,6 +1301,12 @@ function useAgentChat({
|
|
|
945
1301
|
toolSteps: upsertToolStep(prev.toolSteps, item)
|
|
946
1302
|
}));
|
|
947
1303
|
},
|
|
1304
|
+
onActionResult: (output) => {
|
|
1305
|
+
const offer = bookingOfferFromActionOutput(output);
|
|
1306
|
+
if (!offer) return;
|
|
1307
|
+
capturedOffers.push(offer);
|
|
1308
|
+
setState((prev) => ({ ...prev, pendingOffer: offer }));
|
|
1309
|
+
},
|
|
948
1310
|
onDelta: (delta) => {
|
|
949
1311
|
if (!isActiveRun()) return;
|
|
950
1312
|
if (!streamStarted) {
|
|
@@ -960,7 +1322,8 @@ function useAgentChat({
|
|
|
960
1322
|
setState((prev) => ({
|
|
961
1323
|
...prev,
|
|
962
1324
|
phase: "streaming",
|
|
963
|
-
streamingText: streamed
|
|
1325
|
+
streamingText: hideToolCardFences(streamed),
|
|
1326
|
+
pendingOffer: prev.pendingOffer ?? capturedOffers.at(-1) ?? null
|
|
964
1327
|
}));
|
|
965
1328
|
},
|
|
966
1329
|
onComplete: () => {
|
|
@@ -981,18 +1344,34 @@ function useAgentChat({
|
|
|
981
1344
|
});
|
|
982
1345
|
}
|
|
983
1346
|
if (!isActiveRun() || finalText === null) return;
|
|
1347
|
+
const displayText = ensureBookingOfferText(
|
|
1348
|
+
finalText,
|
|
1349
|
+
capturedOffers.at(-1) ?? null
|
|
1350
|
+
);
|
|
984
1351
|
const agentMessage = {
|
|
985
1352
|
id: `agent-${Date.now()}`,
|
|
986
1353
|
role: "agent",
|
|
987
|
-
text:
|
|
1354
|
+
text: displayText,
|
|
988
1355
|
createdAt: Date.now()
|
|
989
1356
|
};
|
|
1357
|
+
const parsedCards = extractToolCards(displayText);
|
|
1358
|
+
for (const card of parsedCards) {
|
|
1359
|
+
if (card.type === "booking_confirmed") {
|
|
1360
|
+
pendingBookingRef.current = card;
|
|
1361
|
+
savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, card);
|
|
1362
|
+
}
|
|
1363
|
+
if (card.type === "booking_canceled" && pendingBookingRef.current?.eventUri === card.eventUri) {
|
|
1364
|
+
pendingBookingRef.current = null;
|
|
1365
|
+
clearPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
990
1368
|
setState((prev) => ({
|
|
991
1369
|
...prev,
|
|
992
1370
|
phase: "complete",
|
|
993
1371
|
messages: [...prev.messages, agentMessage],
|
|
994
1372
|
toolSteps: completeActivePlanning(prev.toolSteps),
|
|
995
1373
|
streamingText: "",
|
|
1374
|
+
pendingOffer: null,
|
|
996
1375
|
followUps: [],
|
|
997
1376
|
journey: null
|
|
998
1377
|
}));
|
|
@@ -1014,26 +1393,54 @@ function useAgentChat({
|
|
|
1014
1393
|
} : step
|
|
1015
1394
|
),
|
|
1016
1395
|
streamingText: "",
|
|
1396
|
+
pendingOffer: null,
|
|
1017
1397
|
error: message
|
|
1018
1398
|
}));
|
|
1019
1399
|
runRef.current = null;
|
|
1020
1400
|
}
|
|
1021
1401
|
},
|
|
1022
|
-
[]
|
|
1402
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1403
|
+
);
|
|
1404
|
+
const rememberBooking = useCallback(
|
|
1405
|
+
(booking) => {
|
|
1406
|
+
const current = pendingBookingRef.current;
|
|
1407
|
+
if (current?.eventUri === booking.eventUri && current.inviteeEmail === booking.inviteeEmail && current.inviteeUri === booking.inviteeUri) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
pendingBookingRef.current = booking;
|
|
1411
|
+
savePendingWidgetBooking(resolvedStorageKeyPrefix, visitorId, booking);
|
|
1412
|
+
},
|
|
1413
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1414
|
+
);
|
|
1415
|
+
const forgetBooking = useCallback(
|
|
1416
|
+
(eventUri) => {
|
|
1417
|
+
const current = pendingBookingRef.current;
|
|
1418
|
+
if (!current) return;
|
|
1419
|
+
if (eventUri && current.eventUri !== eventUri) return;
|
|
1420
|
+
pendingBookingRef.current = null;
|
|
1421
|
+
clearPendingWidgetBooking(resolvedStorageKeyPrefix, visitorId);
|
|
1422
|
+
},
|
|
1423
|
+
[resolvedStorageKeyPrefix, visitorId]
|
|
1023
1424
|
);
|
|
1024
1425
|
const submit = useCallback(
|
|
1025
|
-
async (visitorText) => {
|
|
1426
|
+
async (visitorText, options) => {
|
|
1026
1427
|
if (runRef.current) {
|
|
1027
1428
|
runRef.current.abort();
|
|
1028
1429
|
clientRef.current.cancelActive();
|
|
1029
1430
|
}
|
|
1030
1431
|
const controller = new AbortController();
|
|
1031
1432
|
runRef.current = controller;
|
|
1433
|
+
const booking = pendingBookingRef.current;
|
|
1434
|
+
const outgoing = options?.runtimeText ?? visitorText;
|
|
1435
|
+
const runtimeText = booking ? `${visitorBookingPrefix(booking)}
|
|
1436
|
+
|
|
1437
|
+
${outgoing}` : outgoing;
|
|
1032
1438
|
const visitorMessage = {
|
|
1033
1439
|
id: `visitor-${Date.now()}`,
|
|
1034
1440
|
role: "visitor",
|
|
1035
1441
|
text: visitorText,
|
|
1036
|
-
createdAt: Date.now()
|
|
1442
|
+
createdAt: Date.now(),
|
|
1443
|
+
...runtimeText !== visitorText ? { runtimeText } : {}
|
|
1037
1444
|
};
|
|
1038
1445
|
setState((prev) => ({
|
|
1039
1446
|
...prev,
|
|
@@ -1050,9 +1457,10 @@ function useAgentChat({
|
|
|
1050
1457
|
journey: null,
|
|
1051
1458
|
followUps: [],
|
|
1052
1459
|
streamingText: "",
|
|
1460
|
+
pendingOffer: null,
|
|
1053
1461
|
error: null
|
|
1054
1462
|
}));
|
|
1055
|
-
await runTurn({ controller, resume: false, visitorText });
|
|
1463
|
+
await runTurn({ controller, resume: false, visitorText: runtimeText });
|
|
1056
1464
|
},
|
|
1057
1465
|
[runTurn]
|
|
1058
1466
|
);
|
|
@@ -1079,12 +1487,13 @@ function useAgentChat({
|
|
|
1079
1487
|
journey: null,
|
|
1080
1488
|
followUps: [],
|
|
1081
1489
|
streamingText: "",
|
|
1490
|
+
pendingOffer: null,
|
|
1082
1491
|
error: null
|
|
1083
1492
|
}));
|
|
1084
1493
|
await runTurn({
|
|
1085
1494
|
controller,
|
|
1086
1495
|
resume: false,
|
|
1087
|
-
visitorText: visitorMessage
|
|
1496
|
+
visitorText: visitorTurnText(visitorMessage)
|
|
1088
1497
|
});
|
|
1089
1498
|
}, [runTurn, state.messages]);
|
|
1090
1499
|
useEffect(() => {
|
|
@@ -1101,7 +1510,7 @@ function useAgentChat({
|
|
|
1101
1510
|
controller,
|
|
1102
1511
|
initialText: conversation.streamingText,
|
|
1103
1512
|
resume: true,
|
|
1104
|
-
visitorText: visitorMessage
|
|
1513
|
+
visitorText: visitorTurnText(visitorMessage)
|
|
1105
1514
|
});
|
|
1106
1515
|
return () => {
|
|
1107
1516
|
if (runRef.current === controller) {
|
|
@@ -1121,6 +1530,8 @@ function useAgentChat({
|
|
|
1121
1530
|
reset,
|
|
1122
1531
|
retry,
|
|
1123
1532
|
submit,
|
|
1533
|
+
rememberBooking,
|
|
1534
|
+
forgetBooking,
|
|
1124
1535
|
visitorSessionId: visitorId,
|
|
1125
1536
|
sessionId: clientRef.current.getActiveSessionId()
|
|
1126
1537
|
};
|
|
@@ -1175,18 +1586,65 @@ var defaultAgentRailTheme = {
|
|
|
1175
1586
|
fontBody: '"Mulish", "Avenir Next", "Segoe UI", sans-serif',
|
|
1176
1587
|
fontDisplay: '"Space Grotesk", sans-serif'
|
|
1177
1588
|
};
|
|
1589
|
+
var defaultDarkAgentRailTheme = {
|
|
1590
|
+
...defaultAgentRailTheme,
|
|
1591
|
+
brand: "#a77bff",
|
|
1592
|
+
brandSoft: "#2b2140",
|
|
1593
|
+
brandDeep: "#f5f0ff",
|
|
1594
|
+
surface: "#101218",
|
|
1595
|
+
surfaceMuted: "#1a1e27",
|
|
1596
|
+
text: "#f5f7fb",
|
|
1597
|
+
textMuted: "#b6bfce",
|
|
1598
|
+
textSubtle: "#919cad",
|
|
1599
|
+
border: "rgb(226 232 240 / 0.16)",
|
|
1600
|
+
visitorBubble: "#7c3aed",
|
|
1601
|
+
success: "#55cf91",
|
|
1602
|
+
danger: "#ff8da1"
|
|
1603
|
+
};
|
|
1178
1604
|
|
|
1179
1605
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1180
|
-
import { useEffect as useEffect2,
|
|
1606
|
+
import { useEffect as useEffect2, useRef as useRef3, useState as useState6 } from "react";
|
|
1607
|
+
|
|
1608
|
+
// src/react/hooks/useAgentColorScheme.ts
|
|
1609
|
+
import { useSyncExternalStore } from "react";
|
|
1610
|
+
var DARK_MODE_QUERY = "(prefers-color-scheme: dark)";
|
|
1611
|
+
function subscribeToDarkMode(onChange) {
|
|
1612
|
+
if (typeof window === "undefined" || !window.matchMedia) {
|
|
1613
|
+
return () => void 0;
|
|
1614
|
+
}
|
|
1615
|
+
const mediaQuery = window.matchMedia(DARK_MODE_QUERY);
|
|
1616
|
+
if (typeof mediaQuery.addEventListener === "function") {
|
|
1617
|
+
mediaQuery.addEventListener("change", onChange);
|
|
1618
|
+
return () => mediaQuery.removeEventListener("change", onChange);
|
|
1619
|
+
}
|
|
1620
|
+
mediaQuery.addListener(onChange);
|
|
1621
|
+
return () => mediaQuery.removeListener(onChange);
|
|
1622
|
+
}
|
|
1623
|
+
function getPrefersDarkMode() {
|
|
1624
|
+
return typeof window !== "undefined" && Boolean(window.matchMedia?.(DARK_MODE_QUERY).matches);
|
|
1625
|
+
}
|
|
1626
|
+
function useAgentColorScheme(colorScheme = "auto") {
|
|
1627
|
+
const prefersDarkMode = useSyncExternalStore(
|
|
1628
|
+
subscribeToDarkMode,
|
|
1629
|
+
getPrefersDarkMode,
|
|
1630
|
+
() => false
|
|
1631
|
+
);
|
|
1632
|
+
return resolveAgentColorScheme(colorScheme, prefersDarkMode);
|
|
1633
|
+
}
|
|
1634
|
+
function resolveAgentColorScheme(colorScheme = "auto", prefersDarkMode) {
|
|
1635
|
+
return colorScheme === "auto" ? prefersDarkMode ? "dark" : "light" : colorScheme;
|
|
1636
|
+
}
|
|
1181
1637
|
|
|
1182
1638
|
// src/react/components/AgentActivityBubble/AgentActivityBubble.tsx
|
|
1639
|
+
import { useState as useState2 } from "react";
|
|
1183
1640
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
1184
1641
|
function workSummary(steps, failed, brandLabel) {
|
|
1185
1642
|
const active = [...steps].reverse().find((step) => step.state === "active");
|
|
1186
1643
|
if (active?.kind === "specialist")
|
|
1187
1644
|
return `${active.label} is reviewing your question`;
|
|
1188
1645
|
if (active?.kind === "search") return "Searching this site";
|
|
1189
|
-
if (active)
|
|
1646
|
+
if (active)
|
|
1647
|
+
return brandLabel ? `${brandLabel} is choosing the best way to help` : "Choosing the best way to help";
|
|
1190
1648
|
if (failed) return "Couldn\u2019t complete this request";
|
|
1191
1649
|
const hasError = steps.some((step) => step.state === "error");
|
|
1192
1650
|
const specialists = steps.filter(
|
|
@@ -1197,23 +1655,24 @@ function workSummary(steps, failed, brandLabel) {
|
|
|
1197
1655
|
);
|
|
1198
1656
|
if (hasError) return "Answered with available information";
|
|
1199
1657
|
if (specialists.length > 1)
|
|
1200
|
-
return `
|
|
1658
|
+
return `Brought in ${specialists.length} specialists`;
|
|
1201
1659
|
if (specialists.length === 1)
|
|
1202
|
-
return `
|
|
1203
|
-
if (searched) return "
|
|
1660
|
+
return `Brought in ${specialists[0]?.label}`;
|
|
1661
|
+
if (searched) return "Searched this site";
|
|
1204
1662
|
return "Answer ready";
|
|
1205
1663
|
}
|
|
1206
1664
|
function stepLabel(step, brandLabel) {
|
|
1207
|
-
return step.kind === "planning" ? brandLabel : step.label;
|
|
1665
|
+
return step.kind === "planning" ? brandLabel || "Supervisor" : step.label;
|
|
1208
1666
|
}
|
|
1209
1667
|
function stepDetail(step, steps) {
|
|
1210
1668
|
if (step.kind !== "planning" || step.state !== "completed") {
|
|
1211
1669
|
return step.detail;
|
|
1212
1670
|
}
|
|
1213
1671
|
const specialists = steps.filter((item) => item.kind === "specialist");
|
|
1214
|
-
if (specialists.length === 1)
|
|
1672
|
+
if (specialists.length === 1)
|
|
1673
|
+
return `Routed your question to ${specialists[0]?.label}`;
|
|
1215
1674
|
if (specialists.length > 1)
|
|
1216
|
-
return `
|
|
1675
|
+
return `Routed your question to ${specialists.length} specialists`;
|
|
1217
1676
|
if (steps.some((item) => item.kind === "search"))
|
|
1218
1677
|
return "Used built-in Search & Discovery";
|
|
1219
1678
|
return step.detail;
|
|
@@ -1244,13 +1703,17 @@ function PlanningIcon() {
|
|
|
1244
1703
|
) });
|
|
1245
1704
|
}
|
|
1246
1705
|
function AgentActivityBubble({
|
|
1247
|
-
brandLabel = "
|
|
1706
|
+
brandLabel = "",
|
|
1248
1707
|
brandLogoUrl,
|
|
1249
1708
|
failed = false,
|
|
1250
1709
|
steps
|
|
1251
1710
|
}) {
|
|
1252
1711
|
const active = steps.some((step) => step.state === "active");
|
|
1253
|
-
const
|
|
1712
|
+
const receiptId = steps.map((step) => step.id).join(":");
|
|
1713
|
+
const [expandedReceiptId, setExpandedReceiptId] = useState2(
|
|
1714
|
+
null
|
|
1715
|
+
);
|
|
1716
|
+
const detailsOpen = active || expandedReceiptId === receiptId;
|
|
1254
1717
|
return /* @__PURE__ */ jsxs("article", { className: "agent-activity-bubble", children: [
|
|
1255
1718
|
/* @__PURE__ */ jsxs("p", { className: "agent-activity-bubble__status", "aria-live": "polite", children: [
|
|
1256
1719
|
/* @__PURE__ */ jsx(
|
|
@@ -1262,62 +1725,69 @@ function AgentActivityBubble({
|
|
|
1262
1725
|
),
|
|
1263
1726
|
workSummary(steps, failed, brandLabel)
|
|
1264
1727
|
] }),
|
|
1265
|
-
/* @__PURE__ */ jsxs(
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
{
|
|
1277
|
-
className: "agent-activity-bubble__step",
|
|
1278
|
-
"data-kind": step.kind,
|
|
1279
|
-
"data-state": step.state,
|
|
1280
|
-
children: [
|
|
1281
|
-
/* @__PURE__ */ jsx(
|
|
1282
|
-
"span",
|
|
1283
|
-
{
|
|
1284
|
-
className: "agent-activity-bubble__step-icon",
|
|
1285
|
-
"aria-hidden": "true",
|
|
1286
|
-
children: step.kind === "planning" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1287
|
-
/* @__PURE__ */ jsx(PlanningIcon, {}),
|
|
1288
|
-
brandLogoUrl ? /* @__PURE__ */ jsx(
|
|
1289
|
-
"img",
|
|
1290
|
-
{
|
|
1291
|
-
src: brandLogoUrl,
|
|
1292
|
-
alt: "",
|
|
1293
|
-
onError: (event) => {
|
|
1294
|
-
event.currentTarget.hidden = true;
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
) : null
|
|
1298
|
-
] }) : step.kind === "search" ? /* @__PURE__ */ jsx(SearchIcon, {}) : step.label.slice(0, 1).toUpperCase()
|
|
1299
|
-
}
|
|
1300
|
-
),
|
|
1301
|
-
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
|
|
1302
|
-
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-heading", children: [
|
|
1303
|
-
/* @__PURE__ */ jsx("strong", { children: stepLabel(step, brandLabel) }),
|
|
1304
|
-
/* @__PURE__ */ jsx("small", { children: step.kind === "specialist" ? "Specialist" : step.kind === "search" ? "Built-in capability" : "Supervisor" })
|
|
1305
|
-
] }),
|
|
1306
|
-
detail ? /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null
|
|
1307
|
-
] })
|
|
1308
|
-
]
|
|
1309
|
-
},
|
|
1310
|
-
step.id
|
|
1728
|
+
/* @__PURE__ */ jsxs("div", { className: "agent-activity-bubble__details", children: [
|
|
1729
|
+
/* @__PURE__ */ jsx(
|
|
1730
|
+
"button",
|
|
1731
|
+
{
|
|
1732
|
+
type: "button",
|
|
1733
|
+
className: "agent-activity-bubble__summary",
|
|
1734
|
+
"aria-expanded": detailsOpen,
|
|
1735
|
+
onClick: () => {
|
|
1736
|
+
if (active) return;
|
|
1737
|
+
setExpandedReceiptId(
|
|
1738
|
+
(current) => current === receiptId ? null : receiptId
|
|
1311
1739
|
);
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1740
|
+
},
|
|
1741
|
+
children: "How this answer was made"
|
|
1742
|
+
}
|
|
1743
|
+
),
|
|
1744
|
+
detailsOpen ? /* @__PURE__ */ jsx("ol", { className: "agent-activity-bubble__steps", children: steps.map((step) => {
|
|
1745
|
+
const detail = stepDetail(step, steps);
|
|
1746
|
+
return /* @__PURE__ */ jsxs(
|
|
1747
|
+
"li",
|
|
1748
|
+
{
|
|
1749
|
+
className: "agent-activity-bubble__step",
|
|
1750
|
+
"data-kind": step.kind,
|
|
1751
|
+
"data-state": step.state,
|
|
1752
|
+
children: [
|
|
1753
|
+
/* @__PURE__ */ jsx(
|
|
1754
|
+
"span",
|
|
1755
|
+
{
|
|
1756
|
+
className: "agent-activity-bubble__step-icon",
|
|
1757
|
+
"aria-hidden": "true",
|
|
1758
|
+
children: step.kind === "planning" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1759
|
+
/* @__PURE__ */ jsx(PlanningIcon, {}),
|
|
1760
|
+
brandLogoUrl ? /* @__PURE__ */ jsx(
|
|
1761
|
+
"img",
|
|
1762
|
+
{
|
|
1763
|
+
src: brandLogoUrl,
|
|
1764
|
+
alt: "",
|
|
1765
|
+
onError: (event) => {
|
|
1766
|
+
event.currentTarget.hidden = true;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
) : null
|
|
1770
|
+
] }) : step.kind === "search" ? /* @__PURE__ */ jsx(SearchIcon, {}) : step.label.slice(0, 1).toUpperCase()
|
|
1771
|
+
}
|
|
1772
|
+
),
|
|
1773
|
+
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-copy", children: [
|
|
1774
|
+
/* @__PURE__ */ jsxs("span", { className: "agent-activity-bubble__step-heading", children: [
|
|
1775
|
+
/* @__PURE__ */ jsx("strong", { children: stepLabel(step, brandLabel) }),
|
|
1776
|
+
step.kind === "planning" && !brandLabel ? null : /* @__PURE__ */ jsx("small", { children: step.kind === "specialist" ? "Specialist" : step.kind === "search" ? "Built-in capability" : "Supervisor" })
|
|
1777
|
+
] }),
|
|
1778
|
+
detail ? /* @__PURE__ */ jsx("span", { className: "agent-activity-bubble__step-detail", children: detail }) : null
|
|
1779
|
+
] })
|
|
1780
|
+
]
|
|
1781
|
+
},
|
|
1782
|
+
step.id
|
|
1783
|
+
);
|
|
1784
|
+
}) }) : null
|
|
1785
|
+
] })
|
|
1316
1786
|
] });
|
|
1317
1787
|
}
|
|
1318
1788
|
|
|
1319
1789
|
// src/react/components/Composer/Composer.tsx
|
|
1320
|
-
import { useRef as useRef2, useState as
|
|
1790
|
+
import { useRef as useRef2, useState as useState3 } from "react";
|
|
1321
1791
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1322
1792
|
function SendIcon() {
|
|
1323
1793
|
return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2("path", { d: "M8 12V4M8 4l-3 3M8 4l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
@@ -1328,7 +1798,7 @@ function Composer({
|
|
|
1328
1798
|
variant = "default",
|
|
1329
1799
|
onSubmit
|
|
1330
1800
|
}) {
|
|
1331
|
-
const [value, setValue] =
|
|
1801
|
+
const [value, setValue] = useState3("");
|
|
1332
1802
|
const inputRef = useRef2(null);
|
|
1333
1803
|
function submitCurrent() {
|
|
1334
1804
|
const trimmed = value.trim();
|
|
@@ -1414,34 +1884,338 @@ function FollowUpChips({
|
|
|
1414
1884
|
] });
|
|
1415
1885
|
}
|
|
1416
1886
|
|
|
1887
|
+
// src/react/components/MessageBubble/MessageBubble.tsx
|
|
1888
|
+
import { useState as useState5 } from "react";
|
|
1889
|
+
|
|
1890
|
+
// src/react/components/BookingCard/BookingCard.tsx
|
|
1891
|
+
import { useId, useMemo as useMemo2, useState as useState4 } from "react";
|
|
1892
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1893
|
+
function monthFromKey(key) {
|
|
1894
|
+
const [year, month] = key.split("-").map(Number);
|
|
1895
|
+
if (!year || !month) return { year: (/* @__PURE__ */ new Date()).getFullYear(), month: (/* @__PURE__ */ new Date()).getMonth() };
|
|
1896
|
+
return { year, month: month - 1 };
|
|
1897
|
+
}
|
|
1898
|
+
function dateKeyFromParts(year, month, day) {
|
|
1899
|
+
return [
|
|
1900
|
+
year,
|
|
1901
|
+
String(month + 1).padStart(2, "0"),
|
|
1902
|
+
String(day).padStart(2, "0")
|
|
1903
|
+
].join("-");
|
|
1904
|
+
}
|
|
1905
|
+
function calendarCells(year, month) {
|
|
1906
|
+
const firstWeekday = (new Date(year, month, 1).getDay() + 6) % 7;
|
|
1907
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1908
|
+
const cells = [];
|
|
1909
|
+
for (let index = 0; index < firstWeekday; index += 1) cells.push(null);
|
|
1910
|
+
for (let day = 1; day <= daysInMonth; day += 1) {
|
|
1911
|
+
cells.push({ day, key: dateKeyFromParts(year, month, day) });
|
|
1912
|
+
}
|
|
1913
|
+
while (cells.length < 42) cells.push(null);
|
|
1914
|
+
return cells;
|
|
1915
|
+
}
|
|
1916
|
+
function BookingCard({
|
|
1917
|
+
offer,
|
|
1918
|
+
onBook
|
|
1919
|
+
}) {
|
|
1920
|
+
const fieldId = useId();
|
|
1921
|
+
const defaultType = offer.eventTypes[0]?.uri ?? offer.slots[0]?.eventTypeUri ?? "";
|
|
1922
|
+
const [step, setStep] = useState4("date");
|
|
1923
|
+
const [eventTypeUri, setEventTypeUri] = useState4(defaultType);
|
|
1924
|
+
const [selectedDate, setSelectedDate] = useState4("");
|
|
1925
|
+
const [startTime, setStartTime] = useState4("");
|
|
1926
|
+
const [name, setName] = useState4("");
|
|
1927
|
+
const [email, setEmail] = useState4("");
|
|
1928
|
+
const slots = useMemo2(
|
|
1929
|
+
() => bookingSlotsForEventType(offer.slots, eventTypeUri),
|
|
1930
|
+
[eventTypeUri, offer.slots]
|
|
1931
|
+
);
|
|
1932
|
+
const availableByDate = useMemo2(() => {
|
|
1933
|
+
const next = /* @__PURE__ */ new Map();
|
|
1934
|
+
for (const slot of slots) {
|
|
1935
|
+
const key = slotDateKey(slot.startTime);
|
|
1936
|
+
if (!next.has(key)) next.set(key, slot.startTime);
|
|
1937
|
+
}
|
|
1938
|
+
return next;
|
|
1939
|
+
}, [slots]);
|
|
1940
|
+
const [visibleMonth, setVisibleMonth] = useState4(
|
|
1941
|
+
() => firstAvailableBookingMonth(slots)
|
|
1942
|
+
);
|
|
1943
|
+
function selectEventType(nextType) {
|
|
1944
|
+
setEventTypeUri(nextType);
|
|
1945
|
+
setSelectedDate("");
|
|
1946
|
+
setStartTime("");
|
|
1947
|
+
setVisibleMonth(
|
|
1948
|
+
firstAvailableBookingMonth(bookingSlotsForEventType(offer.slots, nextType))
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
const daySlots = useMemo2(
|
|
1952
|
+
() => slots.filter((slot) => slotDateKey(slot.startTime) === selectedDate),
|
|
1953
|
+
[selectedDate, slots]
|
|
1954
|
+
);
|
|
1955
|
+
const selectedType = offer.eventTypes.find((item) => item.uri === eventTypeUri);
|
|
1956
|
+
const selectedSample = availableByDate.get(selectedDate) ?? startTime;
|
|
1957
|
+
const timeZone = formatSlotTimeZone(slots[0]?.startTime ?? selectedSample);
|
|
1958
|
+
const weekdays = useMemo2(() => weekdayLabels(), []);
|
|
1959
|
+
const cells = calendarCells(visibleMonth.year, visibleMonth.month);
|
|
1960
|
+
const canPrevMonth = [...availableByDate.keys()].some((key) => {
|
|
1961
|
+
const month = monthFromKey(key);
|
|
1962
|
+
return month.year < visibleMonth.year || month.year === visibleMonth.year && month.month < visibleMonth.month;
|
|
1963
|
+
});
|
|
1964
|
+
const canNextMonth = [...availableByDate.keys()].some((key) => {
|
|
1965
|
+
const month = monthFromKey(key);
|
|
1966
|
+
return month.year > visibleMonth.year || month.year === visibleMonth.year && month.month > visibleMonth.month;
|
|
1967
|
+
});
|
|
1968
|
+
function goToMonth(offset) {
|
|
1969
|
+
setVisibleMonth((current) => {
|
|
1970
|
+
const next = new Date(current.year, current.month + offset, 1);
|
|
1971
|
+
return { year: next.getFullYear(), month: next.getMonth() };
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
function selectDate(key) {
|
|
1975
|
+
if (!availableByDate.has(key)) return;
|
|
1976
|
+
setSelectedDate(key);
|
|
1977
|
+
setStartTime("");
|
|
1978
|
+
setStep("time");
|
|
1979
|
+
}
|
|
1980
|
+
function selectTime(value) {
|
|
1981
|
+
setStartTime(value);
|
|
1982
|
+
setStep("details");
|
|
1983
|
+
}
|
|
1984
|
+
function handleSubmit(event) {
|
|
1985
|
+
event.preventDefault();
|
|
1986
|
+
if (!eventTypeUri || !startTime || !name.trim() || !email.trim()) return;
|
|
1987
|
+
onBook?.({
|
|
1988
|
+
displayText: `Book the ${formatSlotLabel(startTime)} demo`,
|
|
1989
|
+
runtimeText: formatBookingRequest({
|
|
1990
|
+
eventTypeUri,
|
|
1991
|
+
inviteeEmail: email.trim(),
|
|
1992
|
+
inviteeName: name.trim(),
|
|
1993
|
+
startTime,
|
|
1994
|
+
timezone: visitorTimeZone(),
|
|
1995
|
+
locationKind: selectedType?.locationKind,
|
|
1996
|
+
location: selectedType?.location
|
|
1997
|
+
})
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
return /* @__PURE__ */ jsx4("section", { className: "booking-card", "aria-label": "Book a meeting", children: /* @__PURE__ */ jsxs4("form", { className: "booking-card__form", onSubmit: handleSubmit, children: [
|
|
2001
|
+
step === "date" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
2002
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedType?.name || "Pick a date" }),
|
|
2003
|
+
timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
|
|
2004
|
+
"Times in ",
|
|
2005
|
+
timeZone
|
|
2006
|
+
] }) : null,
|
|
2007
|
+
offer.eventTypes.length > 1 ? /* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-type`, children: [
|
|
2008
|
+
/* @__PURE__ */ jsx4("span", { children: "Meeting" }),
|
|
2009
|
+
/* @__PURE__ */ jsx4(
|
|
2010
|
+
"select",
|
|
2011
|
+
{
|
|
2012
|
+
id: `${fieldId}-type`,
|
|
2013
|
+
value: eventTypeUri,
|
|
2014
|
+
onChange: (event) => selectEventType(event.target.value),
|
|
2015
|
+
children: offer.eventTypes.map((item) => /* @__PURE__ */ jsx4("option", { value: item.uri, children: item.name }, item.uri))
|
|
2016
|
+
}
|
|
2017
|
+
)
|
|
2018
|
+
] }) : null,
|
|
2019
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__month", children: [
|
|
2020
|
+
/* @__PURE__ */ jsx4(
|
|
2021
|
+
"button",
|
|
2022
|
+
{
|
|
2023
|
+
type: "button",
|
|
2024
|
+
className: "booking-card__nav",
|
|
2025
|
+
"aria-label": "Previous month",
|
|
2026
|
+
disabled: !canPrevMonth,
|
|
2027
|
+
onClick: () => goToMonth(-1),
|
|
2028
|
+
children: "\u2039"
|
|
2029
|
+
}
|
|
2030
|
+
),
|
|
2031
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__month-title", children: formatMonthTitle(visibleMonth.year, visibleMonth.month) }),
|
|
2032
|
+
/* @__PURE__ */ jsx4(
|
|
2033
|
+
"button",
|
|
2034
|
+
{
|
|
2035
|
+
type: "button",
|
|
2036
|
+
className: "booking-card__nav",
|
|
2037
|
+
"aria-label": "Next month",
|
|
2038
|
+
disabled: !canNextMonth,
|
|
2039
|
+
onClick: () => goToMonth(1),
|
|
2040
|
+
children: "\u203A"
|
|
2041
|
+
}
|
|
2042
|
+
)
|
|
2043
|
+
] }),
|
|
2044
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__weekdays", children: weekdays.map((label) => /* @__PURE__ */ jsx4("span", { children: label }, label)) }),
|
|
2045
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__calendar", role: "grid", "aria-label": "Available dates", children: cells.map((cell, index) => {
|
|
2046
|
+
if (!cell) {
|
|
2047
|
+
return /* @__PURE__ */ jsx4("span", { className: "booking-card__day" }, `empty-${index}`);
|
|
2048
|
+
}
|
|
2049
|
+
const available = availableByDate.has(cell.key);
|
|
2050
|
+
const selected = cell.key === selectedDate;
|
|
2051
|
+
return /* @__PURE__ */ jsx4(
|
|
2052
|
+
"button",
|
|
2053
|
+
{
|
|
2054
|
+
type: "button",
|
|
2055
|
+
className: [
|
|
2056
|
+
"booking-card__day",
|
|
2057
|
+
available ? "booking-card__day--available" : "",
|
|
2058
|
+
selected ? "booking-card__day--selected" : ""
|
|
2059
|
+
].filter(Boolean).join(" "),
|
|
2060
|
+
disabled: !available,
|
|
2061
|
+
"aria-pressed": selected,
|
|
2062
|
+
onClick: () => selectDate(cell.key),
|
|
2063
|
+
children: cell.day
|
|
2064
|
+
},
|
|
2065
|
+
cell.key
|
|
2066
|
+
);
|
|
2067
|
+
}) })
|
|
2068
|
+
] }, "date") : null,
|
|
2069
|
+
step === "time" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
2070
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
|
|
2071
|
+
/* @__PURE__ */ jsx4(
|
|
2072
|
+
"button",
|
|
2073
|
+
{
|
|
2074
|
+
type: "button",
|
|
2075
|
+
className: "booking-card__nav",
|
|
2076
|
+
"aria-label": "Back to dates",
|
|
2077
|
+
onClick: () => setStep("date"),
|
|
2078
|
+
children: "\u2039"
|
|
2079
|
+
}
|
|
2080
|
+
),
|
|
2081
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
2082
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: selectedSample ? formatLongDate(selectedSample) : "Pick a time" }),
|
|
2083
|
+
timeZone ? /* @__PURE__ */ jsxs4("p", { className: "booking-card__tz", children: [
|
|
2084
|
+
"Times in ",
|
|
2085
|
+
timeZone
|
|
2086
|
+
] }) : null
|
|
2087
|
+
] })
|
|
2088
|
+
] }),
|
|
2089
|
+
/* @__PURE__ */ jsx4("div", { className: "booking-card__times", children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
|
|
2090
|
+
"button",
|
|
2091
|
+
{
|
|
2092
|
+
type: "button",
|
|
2093
|
+
className: startTime === slot.startTime ? "booking-card__time booking-card__time--selected" : "booking-card__time",
|
|
2094
|
+
onClick: () => selectTime(slot.startTime),
|
|
2095
|
+
children: formatTimeChip(slot.startTime)
|
|
2096
|
+
},
|
|
2097
|
+
slot.startTime
|
|
2098
|
+
)) })
|
|
2099
|
+
] }, "time") : null,
|
|
2100
|
+
step === "details" ? /* @__PURE__ */ jsxs4("div", { className: "booking-card__step", children: [
|
|
2101
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__step-bar", children: [
|
|
2102
|
+
/* @__PURE__ */ jsx4(
|
|
2103
|
+
"button",
|
|
2104
|
+
{
|
|
2105
|
+
type: "button",
|
|
2106
|
+
className: "booking-card__nav",
|
|
2107
|
+
"aria-label": "Back to times",
|
|
2108
|
+
onClick: () => setStep("time"),
|
|
2109
|
+
children: "\u2039"
|
|
2110
|
+
}
|
|
2111
|
+
),
|
|
2112
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
2113
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__title", children: "Enter details" }),
|
|
2114
|
+
/* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: formatSlotLabel(startTime) }),
|
|
2115
|
+
selectedType?.location ? /* @__PURE__ */ jsx4("p", { className: "booking-card__tz", children: selectedType.location }) : null
|
|
2116
|
+
] })
|
|
2117
|
+
] }),
|
|
2118
|
+
/* @__PURE__ */ jsxs4("div", { className: "booking-card__identity", children: [
|
|
2119
|
+
/* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-name`, children: [
|
|
2120
|
+
/* @__PURE__ */ jsx4("span", { children: "Name" }),
|
|
2121
|
+
/* @__PURE__ */ jsx4(
|
|
2122
|
+
"input",
|
|
2123
|
+
{
|
|
2124
|
+
id: `${fieldId}-name`,
|
|
2125
|
+
autoComplete: "name",
|
|
2126
|
+
value: name,
|
|
2127
|
+
onChange: (event) => setName(event.target.value),
|
|
2128
|
+
required: true
|
|
2129
|
+
}
|
|
2130
|
+
)
|
|
2131
|
+
] }),
|
|
2132
|
+
/* @__PURE__ */ jsxs4("label", { className: "booking-card__field", htmlFor: `${fieldId}-email`, children: [
|
|
2133
|
+
/* @__PURE__ */ jsx4("span", { children: "Email" }),
|
|
2134
|
+
/* @__PURE__ */ jsx4(
|
|
2135
|
+
"input",
|
|
2136
|
+
{
|
|
2137
|
+
id: `${fieldId}-email`,
|
|
2138
|
+
type: "email",
|
|
2139
|
+
autoComplete: "email",
|
|
2140
|
+
value: email,
|
|
2141
|
+
onChange: (event) => setEmail(event.target.value),
|
|
2142
|
+
required: true
|
|
2143
|
+
}
|
|
2144
|
+
)
|
|
2145
|
+
] })
|
|
2146
|
+
] }),
|
|
2147
|
+
/* @__PURE__ */ jsx4("button", { type: "submit", className: "booking-card__submit", children: "Book this time" })
|
|
2148
|
+
] }, "details") : null
|
|
2149
|
+
] }) });
|
|
2150
|
+
}
|
|
2151
|
+
|
|
1417
2152
|
// src/react/components/MessageBubble/MessageBubble.tsx
|
|
1418
2153
|
import { Streamdown } from "streamdown";
|
|
1419
2154
|
import "streamdown/styles.css";
|
|
1420
|
-
import { jsx as
|
|
1421
|
-
function MessageBubble({
|
|
2155
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2156
|
+
function MessageBubble({
|
|
2157
|
+
message,
|
|
2158
|
+
brandLogoUrl,
|
|
2159
|
+
offer,
|
|
2160
|
+
onBook
|
|
2161
|
+
}) {
|
|
2162
|
+
const resolvedLogoUrl = brandLogoUrl?.trim();
|
|
2163
|
+
const [failedLogoUrl, setFailedLogoUrl] = useState5(null);
|
|
2164
|
+
const showBrandLogo = Boolean(resolvedLogoUrl) && failedLogoUrl !== resolvedLogoUrl;
|
|
2165
|
+
const cards = message.role === "agent" ? extractToolCards(message.text) : [];
|
|
2166
|
+
const extractedOffers = cards.filter(
|
|
2167
|
+
(card) => card.type === "booking_offer"
|
|
2168
|
+
);
|
|
2169
|
+
const offers = offer ? [offer] : extractedOffers;
|
|
2170
|
+
const visibleText = hideToolCardFences(message.text);
|
|
2171
|
+
const isStreaming = message.role === "agent" && Boolean(message.streaming);
|
|
2172
|
+
const displayText = offers.length > 0 ? visibleText || "Pick a date and time that works for you." : visibleText || (isStreaming ? "" : message.text);
|
|
1422
2173
|
if (message.role === "visitor") {
|
|
1423
|
-
return /* @__PURE__ */
|
|
2174
|
+
return /* @__PURE__ */ jsx5("article", { className: "message-bubble message-bubble--visitor", children: /* @__PURE__ */ jsx5("p", { className: "message-bubble__text", children: message.text }) });
|
|
1424
2175
|
}
|
|
1425
|
-
|
|
2176
|
+
const agentText = /* @__PURE__ */ jsx5("div", { className: "message-bubble__text", children: /* @__PURE__ */ jsx5(
|
|
1426
2177
|
Streamdown,
|
|
1427
2178
|
{
|
|
1428
2179
|
animated: true,
|
|
1429
2180
|
caret: "circle",
|
|
1430
2181
|
className: "message-bubble__markdown",
|
|
1431
2182
|
controls: false,
|
|
1432
|
-
isAnimating:
|
|
2183
|
+
isAnimating: isStreaming,
|
|
1433
2184
|
linkSafety: { enabled: false },
|
|
1434
|
-
mode:
|
|
2185
|
+
mode: isStreaming ? "streaming" : "static",
|
|
1435
2186
|
skipHtml: true,
|
|
1436
|
-
children:
|
|
2187
|
+
children: displayText
|
|
1437
2188
|
}
|
|
1438
|
-
) })
|
|
2189
|
+
) });
|
|
2190
|
+
return /* @__PURE__ */ jsxs5("article", { className: "message-bubble message-bubble--agent", children: [
|
|
2191
|
+
displayText ? showBrandLogo ? /* @__PURE__ */ jsxs5("div", { className: "message-bubble__agent-row", children: [
|
|
2192
|
+
/* @__PURE__ */ jsx5("span", { className: "message-bubble__agent-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(
|
|
2193
|
+
"img",
|
|
2194
|
+
{
|
|
2195
|
+
src: resolvedLogoUrl,
|
|
2196
|
+
alt: "",
|
|
2197
|
+
onError: () => {
|
|
2198
|
+
setFailedLogoUrl(resolvedLogoUrl ?? null);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
) }),
|
|
2202
|
+
agentText
|
|
2203
|
+
] }) : agentText : null,
|
|
2204
|
+
offers.map((nextOffer, index) => /* @__PURE__ */ jsx5(
|
|
2205
|
+
BookingCard,
|
|
2206
|
+
{
|
|
2207
|
+
offer: nextOffer,
|
|
2208
|
+
onBook
|
|
2209
|
+
},
|
|
2210
|
+
`${bookingOfferIdentityKey(nextOffer)}-${index}`
|
|
2211
|
+
))
|
|
2212
|
+
] });
|
|
1439
2213
|
}
|
|
1440
2214
|
|
|
1441
2215
|
// src/react/components/AgentRail/AgentRail.tsx
|
|
1442
|
-
import { jsx as
|
|
2216
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1443
2217
|
function MinimizeIcon() {
|
|
1444
|
-
return /* @__PURE__ */
|
|
2218
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1445
2219
|
"path",
|
|
1446
2220
|
{
|
|
1447
2221
|
d: "M3.5 8h9",
|
|
@@ -1452,7 +2226,7 @@ function MinimizeIcon() {
|
|
|
1452
2226
|
) });
|
|
1453
2227
|
}
|
|
1454
2228
|
function CloseIcon() {
|
|
1455
|
-
return /* @__PURE__ */
|
|
2229
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1456
2230
|
"path",
|
|
1457
2231
|
{
|
|
1458
2232
|
d: "M4 4l8 8M12 4l-8 8",
|
|
@@ -1463,7 +2237,7 @@ function CloseIcon() {
|
|
|
1463
2237
|
) });
|
|
1464
2238
|
}
|
|
1465
2239
|
function NewChatIcon() {
|
|
1466
|
-
return /* @__PURE__ */
|
|
2240
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1467
2241
|
"path",
|
|
1468
2242
|
{
|
|
1469
2243
|
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 +2249,7 @@ function NewChatIcon() {
|
|
|
1475
2249
|
) });
|
|
1476
2250
|
}
|
|
1477
2251
|
function ExpandIcon() {
|
|
1478
|
-
return /* @__PURE__ */
|
|
2252
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1479
2253
|
"path",
|
|
1480
2254
|
{
|
|
1481
2255
|
d: "M6 3.5H3.5V6M10 3.5h2.5V6M10 12.5h2.5V10M6 12.5H3.5V10",
|
|
@@ -1487,7 +2261,7 @@ function ExpandIcon() {
|
|
|
1487
2261
|
) });
|
|
1488
2262
|
}
|
|
1489
2263
|
function RestoreIcon() {
|
|
1490
|
-
return /* @__PURE__ */
|
|
2264
|
+
return /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
1491
2265
|
"path",
|
|
1492
2266
|
{
|
|
1493
2267
|
d: "M5.5 5.5H3.5V7.5M10.5 5.5h2V7.5M10.5 10.5h2V8.5M5.5 10.5H3.5V8.5",
|
|
@@ -1501,7 +2275,8 @@ function RestoreIcon() {
|
|
|
1501
2275
|
function AgentRail({
|
|
1502
2276
|
state,
|
|
1503
2277
|
theme,
|
|
1504
|
-
|
|
2278
|
+
colorScheme = "auto",
|
|
2279
|
+
brandLabel = "",
|
|
1505
2280
|
brandLogoUrl,
|
|
1506
2281
|
poweredByLabel = "Powered by Webless",
|
|
1507
2282
|
composerPlaceholder = "Ask anything\u2026",
|
|
@@ -1513,11 +2288,31 @@ function AgentRail({
|
|
|
1513
2288
|
onReset,
|
|
1514
2289
|
onRetry,
|
|
1515
2290
|
onSubmit,
|
|
1516
|
-
onFollowUpSelect
|
|
2291
|
+
onFollowUpSelect,
|
|
2292
|
+
onBook
|
|
1517
2293
|
}) {
|
|
1518
2294
|
const transcriptRef = useRef3(null);
|
|
1519
|
-
const
|
|
1520
|
-
const
|
|
2295
|
+
const resolvedBrandLabel = brandLabel.trim();
|
|
2296
|
+
const resolvedBrandLogoUrl = brandLogoUrl?.trim();
|
|
2297
|
+
const [failedLogoUrl, setFailedLogoUrl] = useState6(null);
|
|
2298
|
+
const showBrandLogo = Boolean(resolvedBrandLogoUrl) && failedLogoUrl !== resolvedBrandLogoUrl;
|
|
2299
|
+
const resolvedColorScheme = useAgentColorScheme(colorScheme);
|
|
2300
|
+
const brandedTheme = { ...defaultAgentRailTheme, ...theme };
|
|
2301
|
+
const resolvedTheme = resolvedColorScheme === "dark" ? {
|
|
2302
|
+
...brandedTheme,
|
|
2303
|
+
brand: theme?.brand ?? defaultDarkAgentRailTheme.brand,
|
|
2304
|
+
brandDeep: defaultDarkAgentRailTheme.brandDeep,
|
|
2305
|
+
brandSoft: `color-mix(in srgb, ${theme?.brand ?? defaultDarkAgentRailTheme.brand} 18%, ${defaultDarkAgentRailTheme.surface})`,
|
|
2306
|
+
border: defaultDarkAgentRailTheme.border,
|
|
2307
|
+
danger: defaultDarkAgentRailTheme.danger,
|
|
2308
|
+
success: defaultDarkAgentRailTheme.success,
|
|
2309
|
+
surface: defaultDarkAgentRailTheme.surface,
|
|
2310
|
+
surfaceMuted: defaultDarkAgentRailTheme.surfaceMuted,
|
|
2311
|
+
text: defaultDarkAgentRailTheme.text,
|
|
2312
|
+
textMuted: defaultDarkAgentRailTheme.textMuted,
|
|
2313
|
+
textSubtle: defaultDarkAgentRailTheme.textSubtle,
|
|
2314
|
+
visitorBubble: theme?.visitorBubble ?? theme?.brand ?? defaultDarkAgentRailTheme.visitorBubble
|
|
2315
|
+
} : brandedTheme;
|
|
1521
2316
|
const railStyle = {
|
|
1522
2317
|
"--rail-width": resolvedTheme.railMaxWidth,
|
|
1523
2318
|
"--as-rail-max-width": resolvedTheme.railMaxWidth,
|
|
@@ -1535,7 +2330,8 @@ function AgentRail({
|
|
|
1535
2330
|
"--as-success": resolvedTheme.success,
|
|
1536
2331
|
"--as-danger": resolvedTheme.danger,
|
|
1537
2332
|
"--as-font-body": resolvedTheme.fontBody,
|
|
1538
|
-
"--as-font-display": resolvedTheme.fontDisplay
|
|
2333
|
+
"--as-font-display": resolvedTheme.fontDisplay,
|
|
2334
|
+
colorScheme: resolvedColorScheme
|
|
1539
2335
|
};
|
|
1540
2336
|
const isBusy = state.phase === "thinking" || state.phase === "running-tools" || state.phase === "streaming";
|
|
1541
2337
|
const showActivity = state.toolSteps.length > 0;
|
|
@@ -1546,7 +2342,7 @@ function AgentRail({
|
|
|
1546
2342
|
const greeting = state.messages.find(
|
|
1547
2343
|
(message) => message.role === "agent" && message.id === "greeting"
|
|
1548
2344
|
);
|
|
1549
|
-
const visibleMessages = hasVisitorMessages2 ? state.messages
|
|
2345
|
+
const visibleMessages = hasVisitorMessages2 ? state.messages : [];
|
|
1550
2346
|
const lastMessage = visibleMessages.at(-1);
|
|
1551
2347
|
const completedAnswer = showActivity && state.phase === "complete" && lastMessage?.role === "agent" ? lastMessage : null;
|
|
1552
2348
|
const transcriptMessages = completedAnswer ? visibleMessages.slice(0, -1) : visibleMessages;
|
|
@@ -1556,6 +2352,12 @@ function AgentRail({
|
|
|
1556
2352
|
role: "agent",
|
|
1557
2353
|
streaming: true,
|
|
1558
2354
|
text: state.streamingText
|
|
2355
|
+
} : state.pendingOffer ? {
|
|
2356
|
+
createdAt: 0,
|
|
2357
|
+
id: "pending-booking",
|
|
2358
|
+
role: "agent",
|
|
2359
|
+
streaming: false,
|
|
2360
|
+
text: "Pick a date and time that works for you."
|
|
1559
2361
|
} : null;
|
|
1560
2362
|
useEffect2(() => {
|
|
1561
2363
|
const node = transcriptRef.current;
|
|
@@ -1568,10 +2370,11 @@ function AgentRail({
|
|
|
1568
2370
|
state.followUps,
|
|
1569
2371
|
state.journey
|
|
1570
2372
|
]);
|
|
1571
|
-
return /* @__PURE__ */
|
|
2373
|
+
return /* @__PURE__ */ jsxs6(
|
|
1572
2374
|
"aside",
|
|
1573
2375
|
{
|
|
1574
2376
|
className: `agent-rail${mobileFullscreen ? " agent-rail--mobile-fullscreen" : ""}${expanded ? " agent-rail--expanded" : ""}`,
|
|
2377
|
+
"data-color-scheme": resolvedColorScheme,
|
|
1575
2378
|
style: railStyle,
|
|
1576
2379
|
"aria-label": "Agent conversation",
|
|
1577
2380
|
"aria-modal": mobileFullscreen || expanded ? true : void 0,
|
|
@@ -1579,45 +2382,42 @@ function AgentRail({
|
|
|
1579
2382
|
role: mobileFullscreen || expanded ? "dialog" : void 0,
|
|
1580
2383
|
tabIndex: mobileFullscreen || expanded ? -1 : void 0,
|
|
1581
2384
|
children: [
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
onCollapse ? /* @__PURE__ */
|
|
2385
|
+
/* @__PURE__ */ jsx6("header", { className: "agent-rail__header", children: /* @__PURE__ */ jsxs6("div", { className: "agent-rail__brand-row", children: [
|
|
2386
|
+
onCollapse ? /* @__PURE__ */ jsx6(
|
|
1584
2387
|
"button",
|
|
1585
2388
|
{
|
|
1586
2389
|
type: "button",
|
|
1587
2390
|
className: "agent-rail__collapse",
|
|
1588
2391
|
"aria-label": "Collapse assist",
|
|
1589
2392
|
onClick: onCollapse,
|
|
1590
|
-
children: /* @__PURE__ */
|
|
2393
|
+
children: /* @__PURE__ */ jsx6(MinimizeIcon, {})
|
|
1591
2394
|
}
|
|
1592
|
-
) : onClose ? /* @__PURE__ */
|
|
2395
|
+
) : onClose ? /* @__PURE__ */ jsx6(
|
|
1593
2396
|
"button",
|
|
1594
2397
|
{
|
|
1595
2398
|
type: "button",
|
|
1596
2399
|
className: "agent-rail__close",
|
|
1597
2400
|
"aria-label": "Close agent",
|
|
1598
2401
|
onClick: onClose,
|
|
1599
|
-
children: /* @__PURE__ */
|
|
2402
|
+
children: /* @__PURE__ */ jsx6(CloseIcon, {})
|
|
1600
2403
|
}
|
|
1601
|
-
) : /* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
"
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
onError: (event) => {
|
|
1612
|
-
event.currentTarget.hidden = true;
|
|
1613
|
-
}
|
|
2404
|
+
) : /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-spacer", "aria-hidden": "true" }),
|
|
2405
|
+
resolvedBrandLabel || showBrandLogo ? /* @__PURE__ */ jsxs6("span", { className: "agent-rail__identity", children: [
|
|
2406
|
+
showBrandLogo ? /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
|
|
2407
|
+
"img",
|
|
2408
|
+
{
|
|
2409
|
+
className: "agent-rail__brand-logo",
|
|
2410
|
+
src: resolvedBrandLogoUrl,
|
|
2411
|
+
alt: "",
|
|
2412
|
+
onError: () => {
|
|
2413
|
+
setFailedLogoUrl(resolvedBrandLogoUrl ?? null);
|
|
1614
2414
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
/* @__PURE__ */
|
|
1618
|
-
] }),
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
onReset ? /* @__PURE__ */
|
|
2415
|
+
}
|
|
2416
|
+
) }) : null,
|
|
2417
|
+
resolvedBrandLabel ? /* @__PURE__ */ jsx6("span", { className: "agent-rail__brand-label", children: resolvedBrandLabel }) : null
|
|
2418
|
+
] }) : null,
|
|
2419
|
+
/* @__PURE__ */ jsxs6("span", { className: "agent-rail__actions", children: [
|
|
2420
|
+
onReset ? /* @__PURE__ */ jsx6(
|
|
1621
2421
|
"button",
|
|
1622
2422
|
{
|
|
1623
2423
|
type: "button",
|
|
@@ -1625,80 +2425,86 @@ function AgentRail({
|
|
|
1625
2425
|
"aria-label": "Start a new conversation",
|
|
1626
2426
|
disabled: !hasVisitorMessages2,
|
|
1627
2427
|
onClick: onReset,
|
|
1628
|
-
children: /* @__PURE__ */
|
|
2428
|
+
children: /* @__PURE__ */ jsx6(NewChatIcon, {})
|
|
1629
2429
|
}
|
|
1630
2430
|
) : null,
|
|
1631
|
-
onExpandToggle ? /* @__PURE__ */
|
|
2431
|
+
onExpandToggle ? /* @__PURE__ */ jsx6(
|
|
1632
2432
|
"button",
|
|
1633
2433
|
{
|
|
1634
2434
|
type: "button",
|
|
1635
2435
|
className: "agent-rail__expand",
|
|
1636
|
-
"aria-label": expanded ? "Exit
|
|
2436
|
+
"aria-label": expanded ? "Exit full screen" : "Open full screen",
|
|
1637
2437
|
onClick: onExpandToggle,
|
|
1638
|
-
children: expanded ? /* @__PURE__ */
|
|
2438
|
+
children: expanded ? /* @__PURE__ */ jsx6(RestoreIcon, {}) : /* @__PURE__ */ jsx6(ExpandIcon, {})
|
|
1639
2439
|
}
|
|
1640
2440
|
) : null
|
|
1641
2441
|
] })
|
|
1642
2442
|
] }) }),
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
!hasVisitorMessages2 ? /* @__PURE__ */
|
|
1645
|
-
"
|
|
2443
|
+
/* @__PURE__ */ jsx6("div", { ref: transcriptRef, className: "agent-rail__transcript", children: /* @__PURE__ */ jsxs6("div", { className: "agent-rail__thread", children: [
|
|
2444
|
+
!hasVisitorMessages2 ? /* @__PURE__ */ jsxs6("section", { className: "agent-rail__welcome", "aria-label": "Welcome", children: [
|
|
2445
|
+
greeting?.role === "agent" ? /* @__PURE__ */ jsx6(
|
|
2446
|
+
MessageBubble,
|
|
2447
|
+
{
|
|
2448
|
+
message: greeting,
|
|
2449
|
+
brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
|
|
2450
|
+
onBook
|
|
2451
|
+
}
|
|
2452
|
+
) : null,
|
|
2453
|
+
showIdleFollowUps ? /* @__PURE__ */ jsx6("div", { className: "agent-rail__followups-slot", children: /* @__PURE__ */ jsx6(
|
|
2454
|
+
FollowUpChips,
|
|
2455
|
+
{
|
|
2456
|
+
suggestions: state.followUps,
|
|
2457
|
+
disabled: isBusy,
|
|
2458
|
+
label: "Start here",
|
|
2459
|
+
onSelect: (suggestion) => onFollowUpSelect?.(suggestion.label)
|
|
2460
|
+
}
|
|
2461
|
+
) }) : null
|
|
2462
|
+
] }) : null,
|
|
2463
|
+
transcriptMessages.map((message) => /* @__PURE__ */ jsx6(
|
|
2464
|
+
MessageBubble,
|
|
1646
2465
|
{
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
{
|
|
1655
|
-
className: "agent-rail__welcome-logo",
|
|
1656
|
-
src: brandLogoUrl,
|
|
1657
|
-
alt: "",
|
|
1658
|
-
onError: (event) => {
|
|
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(
|
|
2466
|
+
message,
|
|
2467
|
+
brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
|
|
2468
|
+
onBook
|
|
2469
|
+
},
|
|
2470
|
+
message.id
|
|
2471
|
+
)),
|
|
2472
|
+
showActivity ? /* @__PURE__ */ jsx6(
|
|
1682
2473
|
AgentActivityBubble,
|
|
1683
2474
|
{
|
|
1684
|
-
brandLabel,
|
|
1685
|
-
brandLogoUrl,
|
|
2475
|
+
brandLabel: resolvedBrandLabel,
|
|
2476
|
+
brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
|
|
1686
2477
|
failed: state.phase === "error",
|
|
1687
2478
|
steps: state.toolSteps
|
|
1688
2479
|
}
|
|
1689
2480
|
) : null,
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
2481
|
+
completedAnswer ? /* @__PURE__ */ jsx6(
|
|
2482
|
+
MessageBubble,
|
|
2483
|
+
{
|
|
2484
|
+
message: completedAnswer,
|
|
2485
|
+
brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
|
|
2486
|
+
onBook
|
|
2487
|
+
}
|
|
2488
|
+
) : null,
|
|
2489
|
+
streamingMessage ? /* @__PURE__ */ jsx6(
|
|
2490
|
+
MessageBubble,
|
|
2491
|
+
{
|
|
2492
|
+
message: streamingMessage,
|
|
2493
|
+
brandLogoUrl: showBrandLogo ? resolvedBrandLogoUrl : void 0,
|
|
2494
|
+
offer: state.pendingOffer,
|
|
2495
|
+
onBook
|
|
2496
|
+
}
|
|
2497
|
+
) : null,
|
|
2498
|
+
state.error ? /* @__PURE__ */ jsxs6("section", { className: "agent-rail__error", role: "alert", children: [
|
|
2499
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
2500
|
+
/* @__PURE__ */ jsx6("strong", { children: "Something went wrong" }),
|
|
2501
|
+
/* @__PURE__ */ jsx6("p", { children: state.error })
|
|
1696
2502
|
] }),
|
|
1697
|
-
onRetry ? /* @__PURE__ */
|
|
2503
|
+
onRetry ? /* @__PURE__ */ jsx6("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
|
|
1698
2504
|
] }) : null
|
|
1699
2505
|
] }) }),
|
|
1700
|
-
/* @__PURE__ */
|
|
1701
|
-
/* @__PURE__ */
|
|
2506
|
+
/* @__PURE__ */ jsxs6("div", { className: "agent-rail__composer-wrap", children: [
|
|
2507
|
+
/* @__PURE__ */ jsx6(
|
|
1702
2508
|
Composer,
|
|
1703
2509
|
{
|
|
1704
2510
|
variant: expanded || mobileFullscreen ? "dock" : "default",
|
|
@@ -1707,10 +2513,9 @@ function AgentRail({
|
|
|
1707
2513
|
onSubmit
|
|
1708
2514
|
}
|
|
1709
2515
|
),
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */ jsx5("span", { children: poweredByLabel })
|
|
2516
|
+
/* @__PURE__ */ jsx6("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsxs6("p", { children: [
|
|
2517
|
+
/* @__PURE__ */ jsx6("span", { children: "AI can make mistakes. Check important info." }),
|
|
2518
|
+
/* @__PURE__ */ jsx6("span", { children: poweredByLabel })
|
|
1714
2519
|
] }) })
|
|
1715
2520
|
] })
|
|
1716
2521
|
]
|
|
@@ -1719,9 +2524,9 @@ function AgentRail({
|
|
|
1719
2524
|
}
|
|
1720
2525
|
|
|
1721
2526
|
// src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
|
|
1722
|
-
import { Fragment as Fragment2, jsx as
|
|
2527
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1723
2528
|
function SparklesIcon() {
|
|
1724
|
-
return /* @__PURE__ */
|
|
2529
|
+
return /* @__PURE__ */ jsxs7(
|
|
1725
2530
|
"svg",
|
|
1726
2531
|
{
|
|
1727
2532
|
className: "assist-edge-tab__sparkles",
|
|
@@ -1729,21 +2534,21 @@ function SparklesIcon() {
|
|
|
1729
2534
|
fill: "none",
|
|
1730
2535
|
"aria-hidden": "true",
|
|
1731
2536
|
children: [
|
|
1732
|
-
/* @__PURE__ */
|
|
2537
|
+
/* @__PURE__ */ jsx7(
|
|
1733
2538
|
"path",
|
|
1734
2539
|
{
|
|
1735
2540
|
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
2541
|
fill: "currentColor"
|
|
1737
2542
|
}
|
|
1738
2543
|
),
|
|
1739
|
-
/* @__PURE__ */
|
|
2544
|
+
/* @__PURE__ */ jsx7(
|
|
1740
2545
|
"path",
|
|
1741
2546
|
{
|
|
1742
2547
|
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
2548
|
fill: "currentColor"
|
|
1744
2549
|
}
|
|
1745
2550
|
),
|
|
1746
|
-
/* @__PURE__ */
|
|
2551
|
+
/* @__PURE__ */ jsx7(
|
|
1747
2552
|
"path",
|
|
1748
2553
|
{
|
|
1749
2554
|
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 +2559,23 @@ function SparklesIcon() {
|
|
|
1754
2559
|
}
|
|
1755
2560
|
);
|
|
1756
2561
|
}
|
|
2562
|
+
function TabMarkIcon({ customIconUrl }) {
|
|
2563
|
+
const url = customIconUrl?.trim();
|
|
2564
|
+
if (url) {
|
|
2565
|
+
return /* @__PURE__ */ jsx7(
|
|
2566
|
+
"img",
|
|
2567
|
+
{
|
|
2568
|
+
alt: "",
|
|
2569
|
+
"aria-hidden": true,
|
|
2570
|
+
className: "assist-edge-tab__custom-icon",
|
|
2571
|
+
src: url
|
|
2572
|
+
}
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
return /* @__PURE__ */ jsx7(SparklesIcon, {});
|
|
2576
|
+
}
|
|
1757
2577
|
function ChevronLeftIcon() {
|
|
1758
|
-
return /* @__PURE__ */
|
|
2578
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
1759
2579
|
"path",
|
|
1760
2580
|
{
|
|
1761
2581
|
d: "M10 4L6 8l4 4",
|
|
@@ -1767,7 +2587,7 @@ function ChevronLeftIcon() {
|
|
|
1767
2587
|
) });
|
|
1768
2588
|
}
|
|
1769
2589
|
function ChevronDownIcon() {
|
|
1770
|
-
return /* @__PURE__ */
|
|
2590
|
+
return /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
1771
2591
|
"path",
|
|
1772
2592
|
{
|
|
1773
2593
|
d: "M4 6l4 4 4-4",
|
|
@@ -1779,12 +2599,12 @@ function ChevronDownIcon() {
|
|
|
1779
2599
|
) });
|
|
1780
2600
|
}
|
|
1781
2601
|
function DragDots() {
|
|
1782
|
-
return /* @__PURE__ */
|
|
2602
|
+
return /* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__dots", "aria-hidden": "true", children: Array.from({ length: 12 }, (_, index) => /* @__PURE__ */ jsx7("i", {}, index)) });
|
|
1783
2603
|
}
|
|
1784
2604
|
var VARIANT_COPY = {
|
|
1785
|
-
outline: { label: "
|
|
2605
|
+
outline: { label: "Ask anything", aria: "Ask anything" },
|
|
1786
2606
|
ask: { label: "Ask anything", aria: "Ask anything" },
|
|
1787
|
-
fill: { label: "
|
|
2607
|
+
fill: { label: "Ask anything", aria: "Ask anything" }
|
|
1788
2608
|
};
|
|
1789
2609
|
function AssistEdgeTab({
|
|
1790
2610
|
variant,
|
|
@@ -1793,6 +2613,7 @@ function AssistEdgeTab({
|
|
|
1793
2613
|
inset,
|
|
1794
2614
|
visible,
|
|
1795
2615
|
label,
|
|
2616
|
+
customIconUrl,
|
|
1796
2617
|
logoUrl,
|
|
1797
2618
|
brandColor,
|
|
1798
2619
|
brandForeground,
|
|
@@ -1801,40 +2622,49 @@ function AssistEdgeTab({
|
|
|
1801
2622
|
mobile = false,
|
|
1802
2623
|
surfaceColor,
|
|
1803
2624
|
textColor,
|
|
2625
|
+
colorScheme = "auto",
|
|
1804
2626
|
onOpen
|
|
1805
2627
|
}) {
|
|
2628
|
+
const resolvedColorScheme = useAgentColorScheme(colorScheme);
|
|
1806
2629
|
const copy = VARIANT_COPY[variant];
|
|
1807
2630
|
const visibleLabel = label?.trim() || copy.label;
|
|
2631
|
+
const showLogo = Boolean(logoUrl?.trim()) && !customIconUrl?.trim();
|
|
2632
|
+
const resolvedBrandColor = brandColor ?? (resolvedColorScheme === "dark" ? defaultDarkAgentRailTheme.brand : void 0);
|
|
2633
|
+
const resolvedBorderColor = resolvedColorScheme === "dark" ? defaultDarkAgentRailTheme.border : borderColor;
|
|
2634
|
+
const resolvedSurfaceColor = resolvedColorScheme === "dark" ? defaultDarkAgentRailTheme.surface : surfaceColor;
|
|
2635
|
+
const resolvedTextColor = resolvedColorScheme === "dark" ? defaultDarkAgentRailTheme.text : textColor;
|
|
1808
2636
|
const style = {
|
|
1809
2637
|
"--tab-along": `${along}%`,
|
|
1810
2638
|
"--tab-inset": `${inset}px`,
|
|
1811
|
-
...
|
|
2639
|
+
...resolvedBrandColor ? { "--as-brand": resolvedBrandColor } : {},
|
|
1812
2640
|
...brandForeground ? { "--as-visitor-text": brandForeground } : {},
|
|
1813
|
-
...
|
|
2641
|
+
...resolvedBorderColor ? { "--as-border": resolvedBorderColor } : {},
|
|
1814
2642
|
...fontFamily ? { "--as-font-display": fontFamily } : {},
|
|
1815
|
-
...
|
|
1816
|
-
...
|
|
2643
|
+
...resolvedSurfaceColor ? { "--as-surface": resolvedSurfaceColor } : {},
|
|
2644
|
+
...resolvedTextColor ? { "--as-text": resolvedTextColor } : {},
|
|
2645
|
+
colorScheme: resolvedColorScheme
|
|
1817
2646
|
};
|
|
1818
|
-
return /* @__PURE__ */
|
|
2647
|
+
return /* @__PURE__ */ jsxs7(
|
|
1819
2648
|
"button",
|
|
1820
2649
|
{
|
|
1821
2650
|
type: "button",
|
|
1822
2651
|
className: `assist-edge-tab assist-edge-tab--${variant} assist-edge-tab--${side}${mobile ? " assist-edge-tab--mobile" : ""}${visible ? " is-visible" : ""}`,
|
|
2652
|
+
"data-color-scheme": resolvedColorScheme,
|
|
1823
2653
|
style,
|
|
1824
2654
|
"aria-label": `Open ${visibleLabel}`,
|
|
1825
2655
|
"aria-hidden": !visible,
|
|
1826
2656
|
tabIndex: visible ? 0 : -1,
|
|
1827
2657
|
onClick: onOpen,
|
|
1828
2658
|
children: [
|
|
1829
|
-
mobile ? /* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
2659
|
+
mobile ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2660
|
+
/* @__PURE__ */ jsxs7(
|
|
1831
2661
|
"span",
|
|
1832
2662
|
{
|
|
1833
2663
|
className: "assist-edge-tab__mark assist-edge-tab__mark--mobile",
|
|
1834
2664
|
"aria-hidden": "true",
|
|
1835
2665
|
children: [
|
|
1836
|
-
|
|
1837
|
-
|
|
2666
|
+
/* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }),
|
|
2667
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1838
2668
|
"img",
|
|
1839
2669
|
{
|
|
1840
2670
|
className: "assist-edge-tab__logo",
|
|
@@ -1848,14 +2678,11 @@ function AssistEdgeTab({
|
|
|
1848
2678
|
]
|
|
1849
2679
|
}
|
|
1850
2680
|
),
|
|
1851
|
-
/* @__PURE__ */
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
/* @__PURE__ */ jsxs5("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
1857
|
-
/* @__PURE__ */ jsx6(SparklesIcon, {}),
|
|
1858
|
-
logoUrl ? /* @__PURE__ */ jsx6(
|
|
2681
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel })
|
|
2682
|
+
] }) : variant === "outline" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2683
|
+
/* @__PURE__ */ jsxs7("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
2684
|
+
/* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }),
|
|
2685
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1859
2686
|
"img",
|
|
1860
2687
|
{
|
|
1861
2688
|
className: "assist-edge-tab__logo",
|
|
@@ -1867,18 +2694,18 @@ function AssistEdgeTab({
|
|
|
1867
2694
|
}
|
|
1868
2695
|
) : null
|
|
1869
2696
|
] }),
|
|
1870
|
-
/* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
2697
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2698
|
+
/* @__PURE__ */ jsx7(ChevronDownIcon, {})
|
|
1872
2699
|
] }) : null,
|
|
1873
|
-
variant === "ask" ? /* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
/* @__PURE__ */
|
|
2700
|
+
variant === "ask" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2701
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {}),
|
|
2702
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2703
|
+
/* @__PURE__ */ jsx7(DragDots, {})
|
|
1877
2704
|
] }) : null,
|
|
1878
|
-
variant === "fill" ? /* @__PURE__ */
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
|
|
2705
|
+
variant === "fill" ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
2706
|
+
/* @__PURE__ */ jsxs7("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
|
|
2707
|
+
/* @__PURE__ */ jsx7(TabMarkIcon, { customIconUrl }),
|
|
2708
|
+
showLogo ? /* @__PURE__ */ jsx7(
|
|
1882
2709
|
"img",
|
|
1883
2710
|
{
|
|
1884
2711
|
className: "assist-edge-tab__logo",
|
|
@@ -1890,8 +2717,8 @@ function AssistEdgeTab({
|
|
|
1890
2717
|
}
|
|
1891
2718
|
) : null
|
|
1892
2719
|
] }),
|
|
1893
|
-
/* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
2720
|
+
/* @__PURE__ */ jsx7("span", { className: "assist-edge-tab__label", children: visibleLabel }),
|
|
2721
|
+
/* @__PURE__ */ jsx7(ChevronLeftIcon, {})
|
|
1895
2722
|
] }) : null
|
|
1896
2723
|
]
|
|
1897
2724
|
}
|
|
@@ -1899,7 +2726,7 @@ function AssistEdgeTab({
|
|
|
1899
2726
|
}
|
|
1900
2727
|
|
|
1901
2728
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
1902
|
-
import { useEffect as useEffect5, useRef as useRef4, useState as
|
|
2729
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState8 } from "react";
|
|
1903
2730
|
|
|
1904
2731
|
// src/react/page-shift.ts
|
|
1905
2732
|
import { useEffect as useEffect3 } from "react";
|
|
@@ -1982,9 +2809,9 @@ function usePageShift(input) {
|
|
|
1982
2809
|
}
|
|
1983
2810
|
|
|
1984
2811
|
// src/react/hooks/useIsMobile.ts
|
|
1985
|
-
import { useEffect as useEffect4, useState as
|
|
2812
|
+
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
1986
2813
|
function useIsMobile(breakpoint = 767) {
|
|
1987
|
-
const [isMobile, setIsMobile] =
|
|
2814
|
+
const [isMobile, setIsMobile] = useState7(
|
|
1988
2815
|
() => typeof window !== "undefined" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1989
2816
|
);
|
|
1990
2817
|
useEffect4(() => {
|
|
@@ -2013,7 +2840,7 @@ function closeAgentPanel(customerId) {
|
|
|
2013
2840
|
}
|
|
2014
2841
|
|
|
2015
2842
|
// src/react/components/AgentWidget/AgentWidget.tsx
|
|
2016
|
-
import { jsx as
|
|
2843
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2017
2844
|
function AgentWidget({
|
|
2018
2845
|
indexId,
|
|
2019
2846
|
customerId,
|
|
@@ -2030,8 +2857,8 @@ function AgentWidget({
|
|
|
2030
2857
|
const isMobile = useIsMobile();
|
|
2031
2858
|
const placement = normalizeAgentPlacement(placementInput);
|
|
2032
2859
|
const railSlotRef = useRef4(null);
|
|
2033
|
-
const [railCollapsed, setRailCollapsed] =
|
|
2034
|
-
const [railExpanded, setRailExpanded] =
|
|
2860
|
+
const [railCollapsed, setRailCollapsed] = useState8(defaultCollapsed);
|
|
2861
|
+
const [railExpanded, setRailExpanded] = useState8(false);
|
|
2035
2862
|
const pageShiftActive = shouldApplyPageShift({
|
|
2036
2863
|
pageShift,
|
|
2037
2864
|
isMobile,
|
|
@@ -2051,7 +2878,8 @@ function AgentWidget({
|
|
|
2051
2878
|
runtimeOrigin,
|
|
2052
2879
|
greeting: branding?.greeting
|
|
2053
2880
|
});
|
|
2054
|
-
const agentName = branding?.agentName ?? "
|
|
2881
|
+
const agentName = branding?.agentName ?? "";
|
|
2882
|
+
const tabLabel = branding?.tabLabel ?? agentName;
|
|
2055
2883
|
const theme = {
|
|
2056
2884
|
...branding?.fontFamily ? { fontBody: branding.fontFamily, fontDisplay: branding.fontFamily } : {},
|
|
2057
2885
|
...branding?.colors?.primary ? {
|
|
@@ -2069,7 +2897,6 @@ function AgentWidget({
|
|
|
2069
2897
|
} : {},
|
|
2070
2898
|
...branding?.colors?.border ? { border: branding.colors.border } : {}
|
|
2071
2899
|
};
|
|
2072
|
-
const idle = state.phase === "idle" && !hasVisitorMessages(state.messages);
|
|
2073
2900
|
useEffect5(() => {
|
|
2074
2901
|
if (!registerPanelController) return;
|
|
2075
2902
|
registerAgentPanelController(customerId, {
|
|
@@ -2119,64 +2946,44 @@ function AgentWidget({
|
|
|
2119
2946
|
window.addEventListener("keydown", handleKeyDown);
|
|
2120
2947
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2121
2948
|
}, [isMobile, railCollapsed, railExpanded]);
|
|
2122
|
-
return /* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2949
|
+
return /* @__PURE__ */ jsxs8("div", { className: "webless-agent-root", children: [
|
|
2950
|
+
/* @__PURE__ */ jsx8(
|
|
2124
2951
|
"div",
|
|
2125
2952
|
{
|
|
2126
2953
|
className: `webless-agent-root__shell${railCollapsed ? " webless-agent-root__shell--collapsed" : ""}${railExpanded ? " webless-agent-root__shell--expanded" : ""}`,
|
|
2127
|
-
children:
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
onReset: reset,
|
|
2154
|
-
onRetry: () => void retry(),
|
|
2155
|
-
onFollowUpSelect: (label) => void handleSubmit(label)
|
|
2156
|
-
}
|
|
2157
|
-
)
|
|
2158
|
-
}
|
|
2159
|
-
),
|
|
2160
|
-
!railCollapsed && isMobile || !isMobile && railExpanded && !railCollapsed ? /* @__PURE__ */ jsx7(
|
|
2161
|
-
"button",
|
|
2162
|
-
{
|
|
2163
|
-
type: "button",
|
|
2164
|
-
className: `webless-agent-root__backdrop${isMobile ? " webless-agent-root__backdrop--mobile" : ""}`,
|
|
2165
|
-
tabIndex: -1,
|
|
2166
|
-
"aria-label": isMobile ? "Close agent" : "Exit focus view",
|
|
2167
|
-
onClick: () => {
|
|
2168
|
-
if (isMobile) {
|
|
2169
|
-
setRailCollapsed(true);
|
|
2170
|
-
} else {
|
|
2171
|
-
setRailExpanded(false);
|
|
2172
|
-
}
|
|
2954
|
+
children: /* @__PURE__ */ jsx8(
|
|
2955
|
+
"div",
|
|
2956
|
+
{
|
|
2957
|
+
ref: railSlotRef,
|
|
2958
|
+
className: "webless-agent-root__rail-slot",
|
|
2959
|
+
inert: railCollapsed || void 0,
|
|
2960
|
+
"aria-hidden": railCollapsed,
|
|
2961
|
+
children: /* @__PURE__ */ jsx8(
|
|
2962
|
+
AgentRail,
|
|
2963
|
+
{
|
|
2964
|
+
theme,
|
|
2965
|
+
brandLabel: agentName,
|
|
2966
|
+
brandLogoUrl: branding?.logoUrl,
|
|
2967
|
+
composerPlaceholder: branding?.composerPlaceholder ?? "Ask a question\u2026",
|
|
2968
|
+
poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
|
|
2969
|
+
state,
|
|
2970
|
+
mobileFullscreen: isMobile && !railCollapsed,
|
|
2971
|
+
expanded: railExpanded,
|
|
2972
|
+
onCollapse: !isMobile ? () => setRailCollapsed(true) : void 0,
|
|
2973
|
+
onClose: isMobile ? () => setRailCollapsed(true) : void 0,
|
|
2974
|
+
onExpandToggle: !isMobile ? () => setRailExpanded((current) => !current) : void 0,
|
|
2975
|
+
onSubmit: handleSubmit,
|
|
2976
|
+
onReset: reset,
|
|
2977
|
+
onRetry: () => void retry(),
|
|
2978
|
+
onFollowUpSelect: (label) => void handleSubmit(label),
|
|
2979
|
+
onBook: (input) => void submit(input.displayText, { runtimeText: input.runtimeText })
|
|
2173
2980
|
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2981
|
+
)
|
|
2982
|
+
}
|
|
2983
|
+
)
|
|
2177
2984
|
}
|
|
2178
2985
|
),
|
|
2179
|
-
railCollapsed ? /* @__PURE__ */
|
|
2986
|
+
railCollapsed ? /* @__PURE__ */ jsx8(
|
|
2180
2987
|
AssistEdgeTab,
|
|
2181
2988
|
{
|
|
2182
2989
|
variant: placement.variant,
|
|
@@ -2184,7 +2991,8 @@ function AgentWidget({
|
|
|
2184
2991
|
along: placement.along,
|
|
2185
2992
|
inset: placement.inset,
|
|
2186
2993
|
visible: true,
|
|
2187
|
-
label:
|
|
2994
|
+
label: tabLabel,
|
|
2995
|
+
customIconUrl: branding?.tabIconUrl,
|
|
2188
2996
|
logoUrl: branding?.logoUrl,
|
|
2189
2997
|
brandColor: branding?.colors?.primary,
|
|
2190
2998
|
brandForeground: branding?.colors?.primaryForeground,
|
|
@@ -2211,8 +3019,9 @@ export {
|
|
|
2211
3019
|
openAgentPanel,
|
|
2212
3020
|
closeAgentPanel,
|
|
2213
3021
|
defaultAgentRailTheme,
|
|
3022
|
+
defaultDarkAgentRailTheme,
|
|
2214
3023
|
AgentRail,
|
|
2215
3024
|
AssistEdgeTab,
|
|
2216
3025
|
AgentWidget
|
|
2217
3026
|
};
|
|
2218
|
-
//# sourceMappingURL=chunk-
|
|
3027
|
+
//# sourceMappingURL=chunk-Y7Z3ZIAQ.js.map
|