@burdenoff/website-sdk 2026.922.5 → 2026.923.2
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/components/explore.d.mts +4 -180
- package/dist/components/explore.d.ts +4 -180
- package/dist/components/explore.js +1458 -927
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +1225 -694
- package/dist/components/explore.mjs.map +1 -1
- package/dist/explore-D25zoXy9.d.mts +240 -0
- package/dist/explore-I4QnY4J9.d.ts +240 -0
- package/dist/{explore-types-DvQPiL1t.d.mts → explore-types-B5sdOC5M.d.mts} +75 -2
- package/dist/{explore-types-DvQPiL1t.d.ts → explore-types-B5sdOC5M.d.ts} +75 -2
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +125 -8
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +125 -8
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +418 -26
- package/dist/index.d.ts +418 -26
- package/dist/index.js +2522 -748
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2499 -750
- package/dist/index.mjs.map +1 -1
- package/dist/{use-progressive-reveal-Ha3gYPfs.d.mts → use-progressive-reveal-Cmy8bA7L.d.mts} +54 -7
- package/dist/{use-progressive-reveal-BfU_IHip.d.ts → use-progressive-reveal-DHPGGxZu.d.ts} +54 -7
- package/dist/utils/index.d.mts +55 -1
- package/dist/utils/index.d.ts +55 -1
- package/dist/utils/index.js +17 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +14 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { D as DEFAULT_EXPLORE_EXAMPLE_PROMPTS, E as ExploreChatError, a as ExploreChatErrorKind, b as ExploreChatPhase, F as FALLBACK_EXPLORE_LIMITS, U as UseExploreChatOptions,
|
|
2
|
-
import '../explore-types-
|
|
1
|
+
export { D as DEFAULT_EXPLORE_EXAMPLE_PROMPTS, E as ExploreChatError, a as ExploreChatErrorKind, b as ExploreChatPhase, c as ExploreEscalateOutcome, d as ExploreEscalateResult, F as FALLBACK_EXPLORE_LIMITS, U as UseExploreChatOptions, e as UseExploreChatResult, f as UseSpeechOutputOptions, g as UseSpeechOutputResult, h as classifyExploreError, s as stopSpeaking, u as useExploreChat, i as useProgressiveReveal, j as useSpeechOutput } from '../use-progressive-reveal-Cmy8bA7L.mjs';
|
|
2
|
+
import '../explore-types-B5sdOC5M.mjs';
|
|
3
3
|
|
|
4
4
|
interface UseSpeechInputOptions {
|
|
5
5
|
/** Receives settled text as it is recognised. Append it to the draft. */
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { D as DEFAULT_EXPLORE_EXAMPLE_PROMPTS, E as ExploreChatError, a as ExploreChatErrorKind, b as ExploreChatPhase, F as FALLBACK_EXPLORE_LIMITS, U as UseExploreChatOptions,
|
|
2
|
-
import '../explore-types-
|
|
1
|
+
export { D as DEFAULT_EXPLORE_EXAMPLE_PROMPTS, E as ExploreChatError, a as ExploreChatErrorKind, b as ExploreChatPhase, c as ExploreEscalateOutcome, d as ExploreEscalateResult, F as FALLBACK_EXPLORE_LIMITS, U as UseExploreChatOptions, e as UseExploreChatResult, f as UseSpeechOutputOptions, g as UseSpeechOutputResult, h as classifyExploreError, s as stopSpeaking, u as useExploreChat, i as useProgressiveReveal, j as useSpeechOutput } from '../use-progressive-reveal-DHPGGxZu.js';
|
|
2
|
+
import '../explore-types-B5sdOC5M.js';
|
|
3
3
|
|
|
4
4
|
interface UseSpeechInputOptions {
|
|
5
5
|
/** Receives settled text as it is recognised. Append it to the draft. */
|
package/dist/hooks/index.js
CHANGED
|
@@ -226,6 +226,10 @@ function useWebSDK() {
|
|
|
226
226
|
}
|
|
227
227
|
return client;
|
|
228
228
|
}
|
|
229
|
+
function useWebSDKConfig() {
|
|
230
|
+
const client = useWebSDK();
|
|
231
|
+
return client.getConfig();
|
|
232
|
+
}
|
|
229
233
|
|
|
230
234
|
// src/components/explore-types.ts
|
|
231
235
|
var EXPLORE_MESSAGE_FIELDS = (
|
|
@@ -385,6 +389,22 @@ var SUBMIT_EXPLORE_FEEDBACK_MUTATION = (
|
|
|
385
389
|
}
|
|
386
390
|
`
|
|
387
391
|
);
|
|
392
|
+
var ESCALATE_EXPLORE_CONVERSATION_MUTATION = (
|
|
393
|
+
/* GraphQL */
|
|
394
|
+
`
|
|
395
|
+
mutation EscalateExploreConversation(
|
|
396
|
+
$input: EscalateExploreConversationInput!
|
|
397
|
+
) {
|
|
398
|
+
escalateExploreConversation(input: $input) {
|
|
399
|
+
created
|
|
400
|
+
escalation {
|
|
401
|
+
email
|
|
402
|
+
createdAt
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
`
|
|
407
|
+
);
|
|
388
408
|
var CREATE_EXPLORE_SHARE_LINK_MUTATION = (
|
|
389
409
|
/* GraphQL */
|
|
390
410
|
`
|
|
@@ -751,6 +771,25 @@ var VALIDATION_CODES = /* @__PURE__ */ new Set([
|
|
|
751
771
|
"CONVERSATION_LIMIT",
|
|
752
772
|
"INVALID_INPUT"
|
|
753
773
|
]);
|
|
774
|
+
function escalateOutcomeForCode(code) {
|
|
775
|
+
switch (code) {
|
|
776
|
+
case "INVALID_EMAIL":
|
|
777
|
+
return "invalid-email";
|
|
778
|
+
case "RATE_LIMITED":
|
|
779
|
+
case "HTTP_429":
|
|
780
|
+
return "rate-limited";
|
|
781
|
+
case "CAPTCHA_REQUIRED":
|
|
782
|
+
case "CAPTCHA_FAILED":
|
|
783
|
+
return "captcha";
|
|
784
|
+
// The token owns nothing, or owns a different conversation. The server answers NOT_FOUND
|
|
785
|
+
// rather than FORBIDDEN so the endpoint is not an oracle for whether a thread exists;
|
|
786
|
+
// either way there is nothing this visitor can do about it, so it reads as a failure.
|
|
787
|
+
case "NOT_FOUND":
|
|
788
|
+
return "failed";
|
|
789
|
+
default:
|
|
790
|
+
return "failed";
|
|
791
|
+
}
|
|
792
|
+
}
|
|
754
793
|
function classifyExploreError(code, serverMessage) {
|
|
755
794
|
const c = code ?? "UNKNOWN";
|
|
756
795
|
if (RATE_LIMIT_CODES.has(c)) {
|
|
@@ -917,6 +956,7 @@ function useExploreChat(options = {}) {
|
|
|
917
956
|
onSend
|
|
918
957
|
} = options;
|
|
919
958
|
const client = useWebSDK();
|
|
959
|
+
const { productId } = useWebSDKConfig();
|
|
920
960
|
const promptKey = JSON.stringify(examplePrompts ?? []);
|
|
921
961
|
const welcomeKey = JSON.stringify(fallbackWelcome ?? null);
|
|
922
962
|
const fallbackCatalog = react.useMemo(
|
|
@@ -940,6 +980,7 @@ function useExploreChat(options = {}) {
|
|
|
940
980
|
const pollGenerationRef = react.useRef(0);
|
|
941
981
|
const pollTimerRef = react.useRef(null);
|
|
942
982
|
const conversationTokenRef = react.useRef(null);
|
|
983
|
+
const [hasConversation, setHasConversation] = react.useState(false);
|
|
943
984
|
const shareTokenRef = react.useRef(void 0);
|
|
944
985
|
if (shareTokenRef.current === void 0) {
|
|
945
986
|
shareTokenRef.current = readShareToken();
|
|
@@ -954,6 +995,10 @@ function useExploreChat(options = {}) {
|
|
|
954
995
|
);
|
|
955
996
|
const inFlightRef = react.useRef(false);
|
|
956
997
|
catalogRef.current = catalog;
|
|
998
|
+
const rememberConversationToken = react.useCallback((token) => {
|
|
999
|
+
conversationTokenRef.current = token;
|
|
1000
|
+
setHasConversation(token !== null);
|
|
1001
|
+
}, []);
|
|
957
1002
|
const clearPollTimer = react.useCallback(() => {
|
|
958
1003
|
if (pollTimerRef.current !== null) {
|
|
959
1004
|
clearTimeout(pollTimerRef.current);
|
|
@@ -1020,7 +1065,7 @@ function useExploreChat(options = {}) {
|
|
|
1020
1065
|
setArchive(readArchive(storageKey));
|
|
1021
1066
|
const stored = readPersisted(storageKey);
|
|
1022
1067
|
if (stored) {
|
|
1023
|
-
|
|
1068
|
+
rememberConversationToken(stored.conversationToken);
|
|
1024
1069
|
focusProductRef.current = stored.focusProduct;
|
|
1025
1070
|
const settled = stored.messages.flatMap((m) => {
|
|
1026
1071
|
if (m.role !== "ASSISTANT") return [m];
|
|
@@ -1036,7 +1081,7 @@ function useExploreChat(options = {}) {
|
|
|
1036
1081
|
setTurnCount(turns);
|
|
1037
1082
|
}
|
|
1038
1083
|
setHydrated(true);
|
|
1039
|
-
}, [persist, storageKey]);
|
|
1084
|
+
}, [persist, rememberConversationToken, storageKey]);
|
|
1040
1085
|
react.useEffect(() => {
|
|
1041
1086
|
if (!persist || !hydrated || typeof window === "undefined") return;
|
|
1042
1087
|
try {
|
|
@@ -1229,7 +1274,7 @@ function useExploreChat(options = {}) {
|
|
|
1229
1274
|
setPhase(classified.kind === "rate-limit" ? "limited" : "error");
|
|
1230
1275
|
return;
|
|
1231
1276
|
}
|
|
1232
|
-
|
|
1277
|
+
rememberConversationToken(result.conversation.token);
|
|
1233
1278
|
turnCountRef.current = result.conversation.turnCount;
|
|
1234
1279
|
setTurnCount(result.conversation.turnCount);
|
|
1235
1280
|
setRemainingToday(result.remainingToday ?? null);
|
|
@@ -1255,7 +1300,14 @@ function useExploreChat(options = {}) {
|
|
|
1255
1300
|
setPhase("streaming");
|
|
1256
1301
|
startPolling(result.conversation.token, assistantMessage.id);
|
|
1257
1302
|
},
|
|
1258
|
-
[
|
|
1303
|
+
[
|
|
1304
|
+
client,
|
|
1305
|
+
locale,
|
|
1306
|
+
pageUrl,
|
|
1307
|
+
productSlug,
|
|
1308
|
+
rememberConversationToken,
|
|
1309
|
+
startPolling
|
|
1310
|
+
]
|
|
1259
1311
|
);
|
|
1260
1312
|
const send = react.useCallback(
|
|
1261
1313
|
async (message, attachments = []) => {
|
|
@@ -1372,7 +1424,7 @@ function useExploreChat(options = {}) {
|
|
|
1372
1424
|
);
|
|
1373
1425
|
cancelPolling();
|
|
1374
1426
|
inFlightRef.current = false;
|
|
1375
|
-
|
|
1427
|
+
rememberConversationToken(null);
|
|
1376
1428
|
lastSentTextRef.current = null;
|
|
1377
1429
|
lastSentAttachmentsRef.current = [];
|
|
1378
1430
|
turnCountRef.current = 0;
|
|
@@ -1387,7 +1439,7 @@ function useExploreChat(options = {}) {
|
|
|
1387
1439
|
} catch {
|
|
1388
1440
|
}
|
|
1389
1441
|
}
|
|
1390
|
-
}, [cancelPolling, storageKey]);
|
|
1442
|
+
}, [cancelPolling, rememberConversationToken, storageKey]);
|
|
1391
1443
|
const openConversation = react.useCallback(
|
|
1392
1444
|
(token) => {
|
|
1393
1445
|
const entry = readArchive(storageKey).find((e) => e.token === token);
|
|
@@ -1399,7 +1451,7 @@ function useExploreChat(options = {}) {
|
|
|
1399
1451
|
});
|
|
1400
1452
|
cancelPolling();
|
|
1401
1453
|
inFlightRef.current = false;
|
|
1402
|
-
|
|
1454
|
+
rememberConversationToken(entry.token);
|
|
1403
1455
|
turnCountRef.current = entry.messages.filter(
|
|
1404
1456
|
(m) => m.role === "USER"
|
|
1405
1457
|
).length;
|
|
@@ -1411,7 +1463,7 @@ function useExploreChat(options = {}) {
|
|
|
1411
1463
|
setPhase(catalogRef.current.enabled ? "ready" : "disabled");
|
|
1412
1464
|
setArchive(readArchive(storageKey));
|
|
1413
1465
|
},
|
|
1414
|
-
[cancelPolling, storageKey]
|
|
1466
|
+
[cancelPolling, rememberConversationToken, storageKey]
|
|
1415
1467
|
);
|
|
1416
1468
|
const deleteConversation = react.useCallback(
|
|
1417
1469
|
(token) => {
|
|
@@ -1500,6 +1552,69 @@ function useExploreChat(options = {}) {
|
|
|
1500
1552
|
},
|
|
1501
1553
|
[client]
|
|
1502
1554
|
);
|
|
1555
|
+
const escalate = react.useCallback(
|
|
1556
|
+
async (email, note) => {
|
|
1557
|
+
const token = conversationTokenRef.current;
|
|
1558
|
+
if (!token) {
|
|
1559
|
+
return { outcome: "no-conversation", email: null, createdAt: null };
|
|
1560
|
+
}
|
|
1561
|
+
const attempt = async (captchaAttempt) => {
|
|
1562
|
+
const activeCatalog = catalogRef.current;
|
|
1563
|
+
let recaptchaToken;
|
|
1564
|
+
if (activeCatalog.captchaRequired && activeCatalog.recaptchaSiteKey) {
|
|
1565
|
+
try {
|
|
1566
|
+
recaptchaToken = await getRecaptchaV3Token(
|
|
1567
|
+
activeCatalog.recaptchaSiteKey
|
|
1568
|
+
);
|
|
1569
|
+
} catch (err) {
|
|
1570
|
+
console.warn(
|
|
1571
|
+
"[WebSDK] reCAPTCHA v3 token could not be minted",
|
|
1572
|
+
err
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
const input = {
|
|
1577
|
+
conversationToken: token,
|
|
1578
|
+
email: email.trim(),
|
|
1579
|
+
note: note?.trim() ? note.trim() : null,
|
|
1580
|
+
...recaptchaToken ? { recaptchaToken } : {},
|
|
1581
|
+
...productId ? { productId } : {}
|
|
1582
|
+
};
|
|
1583
|
+
try {
|
|
1584
|
+
const res = await client.mutate(
|
|
1585
|
+
ESCALATE_EXPLORE_CONVERSATION_MUTATION,
|
|
1586
|
+
{ input }
|
|
1587
|
+
);
|
|
1588
|
+
const first = res?.errors?.[0];
|
|
1589
|
+
const result = res?.data?.escalateExploreConversation;
|
|
1590
|
+
if (first || !result) {
|
|
1591
|
+
const code = typeof first?.extensions?.code === "string" ? first.extensions.code : "ESCALATION_FAILED";
|
|
1592
|
+
if (code === "CAPTCHA_FAILED" && captchaAttempt === 0) {
|
|
1593
|
+
return attempt(1);
|
|
1594
|
+
}
|
|
1595
|
+
return {
|
|
1596
|
+
outcome: escalateOutcomeForCode(code),
|
|
1597
|
+
email: null,
|
|
1598
|
+
createdAt: null
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
return {
|
|
1602
|
+
// `created: false` is the double-click, the retry, the reload. The handover
|
|
1603
|
+
// exists, so this is a success — and the address comes from the SERVER, because
|
|
1604
|
+
// on a repeat submit the reply goes to whatever the FIRST handover used.
|
|
1605
|
+
outcome: result.created ? "sent" : "already-handed-over",
|
|
1606
|
+
email: result.escalation?.email ?? null,
|
|
1607
|
+
createdAt: result.escalation?.createdAt ?? null
|
|
1608
|
+
};
|
|
1609
|
+
} catch {
|
|
1610
|
+
return { outcome: "failed", email: null, createdAt: null };
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
return attempt(0);
|
|
1614
|
+
},
|
|
1615
|
+
[client, productId]
|
|
1616
|
+
);
|
|
1617
|
+
const canEscalate = hasConversation && !isSharedView;
|
|
1503
1618
|
return {
|
|
1504
1619
|
phase,
|
|
1505
1620
|
catalog,
|
|
@@ -1520,6 +1635,8 @@ function useExploreChat(options = {}) {
|
|
|
1520
1635
|
clearHistory,
|
|
1521
1636
|
recordClick,
|
|
1522
1637
|
submitFeedback,
|
|
1638
|
+
escalate,
|
|
1639
|
+
canEscalate,
|
|
1523
1640
|
createShareLink,
|
|
1524
1641
|
isSharedView
|
|
1525
1642
|
};
|