@xbrain-swe/nova-chat-widget 0.3.0-dev.16 → 0.3.0-dev.17
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/index.cjs +35 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +35 -35
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -120,7 +120,7 @@ function InternalProvider({
|
|
|
120
120
|
const sendEvent = (0, import_react.useCallback)((event, properties = {}) => {
|
|
121
121
|
const { auth: a, visitorId: v, sessionId: sid } = latestRef.current;
|
|
122
122
|
if (!v) return;
|
|
123
|
-
const { conversation_id: conversationId, ...rest } = properties;
|
|
123
|
+
const { conversation_id: conversationId, occurred_at: occurredAt, ...rest } = properties;
|
|
124
124
|
fetch(`${a.apiBaseUrl}/v1/events`, {
|
|
125
125
|
method: "POST",
|
|
126
126
|
keepalive: true,
|
|
@@ -131,18 +131,20 @@ function InternalProvider({
|
|
|
131
131
|
visitor_id: v,
|
|
132
132
|
session_id: sid,
|
|
133
133
|
conversation_id: conversationId ?? null,
|
|
134
|
+
occurred_at: occurredAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
134
135
|
properties: { screen: a.screen, ...rest }
|
|
135
136
|
})
|
|
136
137
|
}).catch(() => {
|
|
137
138
|
});
|
|
138
139
|
}, []);
|
|
139
140
|
const widgetViewSentRef = (0, import_react.useRef)(false);
|
|
141
|
+
const mountedAtRef = (0, import_react.useRef)((/* @__PURE__ */ new Date()).toISOString());
|
|
140
142
|
(0, import_react.useEffect)(() => {
|
|
141
143
|
if (widgetViewSentRef.current) return;
|
|
142
144
|
const send = () => {
|
|
143
145
|
if (widgetViewSentRef.current) return;
|
|
144
146
|
widgetViewSentRef.current = true;
|
|
145
|
-
sendEvent("widget_view");
|
|
147
|
+
sendEvent("widget_view", { occurred_at: mountedAtRef.current });
|
|
146
148
|
};
|
|
147
149
|
if (sessionId) {
|
|
148
150
|
send();
|
|
@@ -1233,7 +1235,6 @@ function useXbNovaChat(options) {
|
|
|
1233
1235
|
const [resumed, setResumed] = (0, import_react8.useState)(false);
|
|
1234
1236
|
const [sentOpening, setSentOpening] = (0, import_react8.useState)(null);
|
|
1235
1237
|
const conversationIdRef = (0, import_react8.useRef)(null);
|
|
1236
|
-
const pendingOpeningRef = (0, import_react8.useRef)(null);
|
|
1237
1238
|
const messagesRef = (0, import_react8.useRef)(messages);
|
|
1238
1239
|
messagesRef.current = messages;
|
|
1239
1240
|
const [busy, setBusy] = (0, import_react8.useState)(false);
|
|
@@ -1256,7 +1257,6 @@ function useXbNovaChat(options) {
|
|
|
1256
1257
|
setFeedbackState({});
|
|
1257
1258
|
dispatchedClientActionsRef.current = /* @__PURE__ */ new Set();
|
|
1258
1259
|
conversationIdRef.current = null;
|
|
1259
|
-
pendingOpeningRef.current = null;
|
|
1260
1260
|
fetch(`${apiBaseUrl}/v1/conversations`, {
|
|
1261
1261
|
method: "POST",
|
|
1262
1262
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
@@ -1289,16 +1289,6 @@ function useXbNovaChat(options) {
|
|
|
1289
1289
|
cancelled = true;
|
|
1290
1290
|
};
|
|
1291
1291
|
}, [apiBaseUrl, apiKey, botId, userKey, threadKey]);
|
|
1292
|
-
const openingMessage = options?.openingMessage;
|
|
1293
|
-
(0, import_react8.useEffect)(() => {
|
|
1294
|
-
if (!onboarding || !nudgeNodeId || !openingMessage) return;
|
|
1295
|
-
if (messagesRef.current.length === 0) return;
|
|
1296
|
-
setMessages((prev) => [
|
|
1297
|
-
...prev,
|
|
1298
|
-
{ role: "assistant", parts: [{ kind: "text", id: `nudge:${nudgeNodeId}:${prev.length}`, text: openingMessage }] }
|
|
1299
|
-
]);
|
|
1300
|
-
pendingOpeningRef.current = openingMessage;
|
|
1301
|
-
}, [onboarding, nudgeNodeId, openingMessage]);
|
|
1302
1292
|
const appendToLastAssistant = (existingParts, newParts) => setMessages((prev) => {
|
|
1303
1293
|
const next = [...prev];
|
|
1304
1294
|
next[next.length - 1] = { ...next[next.length - 1], role: "assistant", parts: [...existingParts, ...newParts] };
|
|
@@ -1417,7 +1407,7 @@ function useXbNovaChat(options) {
|
|
|
1417
1407
|
void runClientAction(spec, part, last.parts);
|
|
1418
1408
|
}
|
|
1419
1409
|
}, [messages, clientActionHandlers, onboarding, apiBaseUrl, apiKey, botId]);
|
|
1420
|
-
async function send(text) {
|
|
1410
|
+
async function send(text, nudgeOpening) {
|
|
1421
1411
|
const trimmed = text.trim();
|
|
1422
1412
|
if (!trimmed || busy) return;
|
|
1423
1413
|
sendEvent("message_send", {
|
|
@@ -1427,8 +1417,10 @@ function useXbNovaChat(options) {
|
|
|
1427
1417
|
});
|
|
1428
1418
|
setError(null);
|
|
1429
1419
|
setBusy(true);
|
|
1420
|
+
const resumedOpening = messages.length > 0 && nudgeOpening ? nudgeOpening : null;
|
|
1430
1421
|
setMessages((prev) => [
|
|
1431
1422
|
...prev,
|
|
1423
|
+
...resumedOpening ? [{ role: "assistant", parts: [{ kind: "text", id: `nudge:${prev.length}`, text: resumedOpening }] }] : [],
|
|
1432
1424
|
{ role: "user", parts: [{ kind: "text", id: "u", text: trimmed }] },
|
|
1433
1425
|
{ role: "assistant", parts: [] }
|
|
1434
1426
|
]);
|
|
@@ -1441,14 +1433,13 @@ function useXbNovaChat(options) {
|
|
|
1441
1433
|
const notes = collectContextEntries(contextRegistry);
|
|
1442
1434
|
const screen = focused ? { region: focused.region, data: resolveFactValue(focused.data) } : {};
|
|
1443
1435
|
const context = focused || notes.length ? { ...screen, ...notes.length ? { notes } : {} } : void 0;
|
|
1444
|
-
let
|
|
1436
|
+
let openingMessage;
|
|
1445
1437
|
if (messages.length === 0) {
|
|
1446
|
-
|
|
1447
|
-
setSentOpening(
|
|
1438
|
+
openingMessage = (options?.openingMessage ?? onboarding?.greeting) || null;
|
|
1439
|
+
setSentOpening(openingMessage);
|
|
1448
1440
|
} else {
|
|
1449
|
-
|
|
1441
|
+
openingMessage = resumedOpening;
|
|
1450
1442
|
}
|
|
1451
|
-
pendingOpeningRef.current = null;
|
|
1452
1443
|
try {
|
|
1453
1444
|
await streamChat(
|
|
1454
1445
|
apiBaseUrl,
|
|
@@ -1459,7 +1450,7 @@ function useXbNovaChat(options) {
|
|
|
1459
1450
|
conversation_id: conversationIdRef.current,
|
|
1460
1451
|
context,
|
|
1461
1452
|
nudge_node_id: nudgeNodeId ?? null,
|
|
1462
|
-
opening_message:
|
|
1453
|
+
opening_message: openingMessage,
|
|
1463
1454
|
visitor_id: userKey || null,
|
|
1464
1455
|
thread_key: threadKey ?? null,
|
|
1465
1456
|
session_id: sessionId
|
|
@@ -1479,7 +1470,7 @@ function useXbNovaChat(options) {
|
|
|
1479
1470
|
setBusy(false);
|
|
1480
1471
|
}
|
|
1481
1472
|
}
|
|
1482
|
-
const opening = resumed ? null : sentOpening
|
|
1473
|
+
const opening = resumed ? null : messages.length > 0 ? sentOpening : options?.openingMessage ?? onboarding?.greeting ?? null;
|
|
1483
1474
|
return {
|
|
1484
1475
|
onboarding,
|
|
1485
1476
|
opening,
|
|
@@ -1779,6 +1770,7 @@ function XbNovaChat({
|
|
|
1779
1770
|
const [activeBotId, setActiveBotId] = (0, import_react9.useState)(void 0);
|
|
1780
1771
|
const [activeNudgeNodeId, setActiveNudgeNodeId] = (0, import_react9.useState)(void 0);
|
|
1781
1772
|
const [nudgeQuickReplies, setNudgeQuickReplies] = (0, import_react9.useState)([]);
|
|
1773
|
+
const [nudgePrompt, setNudgePrompt] = (0, import_react9.useState)(null);
|
|
1782
1774
|
const [openingLine, setOpeningLine] = (0, import_react9.useState)(null);
|
|
1783
1775
|
const [showDisclosure, setShowDisclosure] = (0, import_react9.useState)(false);
|
|
1784
1776
|
const [input, setInput] = (0, import_react9.useState)("");
|
|
@@ -1848,9 +1840,11 @@ function XbNovaChat({
|
|
|
1848
1840
|
setOpeningLine(consumed.text);
|
|
1849
1841
|
setActiveNudgeNodeId(consumed.messageNodeId);
|
|
1850
1842
|
setNudgeQuickReplies(consumed.quickReplies);
|
|
1843
|
+
setNudgePrompt(consumed.text);
|
|
1851
1844
|
sendEvent("nudge_open", { nudge_node_id: consumed.messageNodeId, bot_id: consumed.botId });
|
|
1852
1845
|
} else {
|
|
1853
1846
|
setNudgeQuickReplies([]);
|
|
1847
|
+
setNudgePrompt(null);
|
|
1854
1848
|
setActiveNudgeNodeId(void 0);
|
|
1855
1849
|
const focused = getFocusedTrackEntry(trackRegistry);
|
|
1856
1850
|
setOpeningLine(
|
|
@@ -2072,19 +2066,24 @@ function XbNovaChat({
|
|
|
2072
2066
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: bottomRef })
|
|
2073
2067
|
] }),
|
|
2074
2068
|
(() => {
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
{
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2069
|
+
const prompt = messages.length > 0 ? nudgePrompt : null;
|
|
2070
|
+
if (prompt || nudgeQuickReplies.length > 0) {
|
|
2071
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-2 border-t border-neutral-200 px-3.5 py-2.5 dark:border-neutral-700", children: [
|
|
2072
|
+
prompt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm font-medium", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AssistantMarkdown, { text: prompt }) }) : null,
|
|
2073
|
+
nudgeQuickReplies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-1.5", children: nudgeQuickReplies.map((q) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2074
|
+
"button",
|
|
2075
|
+
{
|
|
2076
|
+
onClick: () => {
|
|
2077
|
+
setNudgeQuickReplies([]);
|
|
2078
|
+
setNudgePrompt(null);
|
|
2079
|
+
send(q, prompt);
|
|
2080
|
+
},
|
|
2081
|
+
className: "xbnova-chip rounded-full border px-2.5 py-1 text-[11px] font-semibold transition",
|
|
2082
|
+
children: q
|
|
2082
2083
|
},
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
q
|
|
2087
|
-
)) });
|
|
2084
|
+
q
|
|
2085
|
+
)) }) : null
|
|
2086
|
+
] });
|
|
2088
2087
|
}
|
|
2089
2088
|
const quickReplies = onboarding?.quick_replies ?? [];
|
|
2090
2089
|
if (messages.length !== 0 || quickReplies.length === 0) return null;
|
|
@@ -2104,7 +2103,8 @@ function XbNovaChat({
|
|
|
2104
2103
|
onSubmit: (e) => {
|
|
2105
2104
|
e.preventDefault();
|
|
2106
2105
|
setNudgeQuickReplies([]);
|
|
2107
|
-
|
|
2106
|
+
setNudgePrompt(null);
|
|
2107
|
+
send(input, messages.length > 0 ? nudgePrompt : null);
|
|
2108
2108
|
setInput("");
|
|
2109
2109
|
},
|
|
2110
2110
|
className: "flex items-center gap-2 border-t border-neutral-200 px-3 py-2.5 dark:border-neutral-700",
|