sagedesk 2.2.0 → 2.3.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/README.md +10 -32
- package/dist/next/{SageDeskWidget-TNVTYDDX.js → SageDeskWidget-ZJJGXTTC.js} +48 -35
- package/dist/next/SageDeskWidget-ZJJGXTTC.js.map +1 -0
- package/dist/next/index.cjs +124 -112
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +1 -1
- package/dist/react/index.cjs +45 -33
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +47 -34
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +2 -4
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +2 -4
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/next/SageDeskWidget-TNVTYDDX.js.map +0 -1
package/dist/react/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/react/SageDeskWidget.tsx
|
|
2
|
-
import {
|
|
2
|
+
import React, {
|
|
3
3
|
useState as useState2,
|
|
4
4
|
useRef as useRef2,
|
|
5
5
|
useEffect as useEffect2,
|
|
6
|
-
useCallback as useCallback2
|
|
6
|
+
useCallback as useCallback2,
|
|
7
|
+
useMemo as useMemo2
|
|
7
8
|
} from "react";
|
|
8
9
|
import { createPortal } from "react-dom";
|
|
9
10
|
|
|
@@ -263,6 +264,7 @@ function logFallbackWarning(reason) {
|
|
|
263
264
|
}
|
|
264
265
|
var initialState = {
|
|
265
266
|
messages: [],
|
|
267
|
+
userMessages: [],
|
|
266
268
|
isOpen: false,
|
|
267
269
|
isTyping: false,
|
|
268
270
|
engineStatus: "idle",
|
|
@@ -275,8 +277,11 @@ function reducer(state, action) {
|
|
|
275
277
|
return { ...state, isOpen: true };
|
|
276
278
|
case "CLOSE":
|
|
277
279
|
return { ...state, isOpen: false };
|
|
278
|
-
case "ADD_MESSAGE":
|
|
279
|
-
|
|
280
|
+
case "ADD_MESSAGE": {
|
|
281
|
+
const newMessages = [...state.messages, action.payload];
|
|
282
|
+
const newUserMessages = action.payload.role === "user" ? [...state.userMessages, action.payload] : state.userMessages;
|
|
283
|
+
return { ...state, messages: newMessages, userMessages: newUserMessages };
|
|
284
|
+
}
|
|
280
285
|
case "SET_TYPING":
|
|
281
286
|
return { ...state, isTyping: action.payload };
|
|
282
287
|
case "SET_ENGINE_STATUS":
|
|
@@ -299,6 +304,7 @@ function useSageDesk(config) {
|
|
|
299
304
|
const embedderRef = useRef(null);
|
|
300
305
|
const engineStartedRef = useRef(false);
|
|
301
306
|
const msgCounterRef = useRef(0);
|
|
307
|
+
const engineReadyCallbacksRef = useRef([]);
|
|
302
308
|
const [chips, setChips] = useState([]);
|
|
303
309
|
const makeId = () => `msg-${++msgCounterRef.current}`;
|
|
304
310
|
const addMessage = useCallback(
|
|
@@ -310,6 +316,11 @@ function useSageDesk(config) {
|
|
|
310
316
|
},
|
|
311
317
|
[]
|
|
312
318
|
);
|
|
319
|
+
const notifyEngineReady = useCallback(() => {
|
|
320
|
+
const callbacks = engineReadyCallbacksRef.current;
|
|
321
|
+
engineReadyCallbacksRef.current = [];
|
|
322
|
+
callbacks.forEach((cb) => cb());
|
|
323
|
+
}, []);
|
|
313
324
|
const startEngine = useCallback(async () => {
|
|
314
325
|
if (engineStartedRef.current) return;
|
|
315
326
|
engineStartedRef.current = true;
|
|
@@ -320,9 +331,11 @@ function useSageDesk(config) {
|
|
|
320
331
|
embedderRef.current = new EmbedderRuntime();
|
|
321
332
|
await embedderRef.current.load(config.agent.model);
|
|
322
333
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
334
|
+
notifyEngineReady();
|
|
323
335
|
} catch (err) {
|
|
324
336
|
console.warn("[sagedesk] WASM embedder failed to load - LLM mode will use fallback messages.", err);
|
|
325
337
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "error-model", error: String(err) } });
|
|
338
|
+
notifyEngineReady();
|
|
326
339
|
}
|
|
327
340
|
return;
|
|
328
341
|
}
|
|
@@ -335,6 +348,7 @@ function useSageDesk(config) {
|
|
|
335
348
|
type: "SET_ENGINE_STATUS",
|
|
336
349
|
payload: { status: "error-index", error: String(err) }
|
|
337
350
|
});
|
|
351
|
+
notifyEngineReady();
|
|
338
352
|
addMessage({
|
|
339
353
|
role: "bot",
|
|
340
354
|
text: "I'm having trouble loading right now. Please try again in a moment."
|
|
@@ -347,12 +361,14 @@ function useSageDesk(config) {
|
|
|
347
361
|
embedderRef.current = new EmbedderRuntime();
|
|
348
362
|
await embedderRef.current.load(config.agent.model);
|
|
349
363
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
364
|
+
notifyEngineReady();
|
|
350
365
|
} catch (err) {
|
|
351
366
|
console.warn("[sagedesk] WASM model failed to load, falling back to keyword search -", err);
|
|
352
367
|
embedderRef.current = new EmbedderRuntime();
|
|
353
368
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "degraded" } });
|
|
369
|
+
notifyEngineReady();
|
|
354
370
|
}
|
|
355
|
-
}, [config.mode, config.indexUrl, config.agent.model, config.agent.suggestedChips, addMessage]);
|
|
371
|
+
}, [config.mode, config.indexUrl, config.agent.model, config.agent.suggestedChips, addMessage, notifyEngineReady]);
|
|
356
372
|
const greetingShownRef = useRef(false);
|
|
357
373
|
const open = useCallback(() => {
|
|
358
374
|
dispatch({ type: "OPEN" });
|
|
@@ -369,16 +385,12 @@ function useSageDesk(config) {
|
|
|
369
385
|
dispatch({ type: "CLOSE" });
|
|
370
386
|
}, []);
|
|
371
387
|
const waitForEngine = useCallback(() => {
|
|
388
|
+
const s = engineStatusRef.current;
|
|
389
|
+
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
390
|
+
return Promise.resolve();
|
|
391
|
+
}
|
|
372
392
|
return new Promise((resolve) => {
|
|
373
|
-
|
|
374
|
-
const s = engineStatusRef.current;
|
|
375
|
-
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
376
|
-
resolve();
|
|
377
|
-
} else {
|
|
378
|
-
setTimeout(check, 100);
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
check();
|
|
393
|
+
engineReadyCallbacksRef.current.push(resolve);
|
|
382
394
|
});
|
|
383
395
|
}, []);
|
|
384
396
|
const submit = useCallback(
|
|
@@ -459,8 +471,8 @@ function useSageDesk(config) {
|
|
|
459
471
|
}
|
|
460
472
|
if (config.mode !== "llm") {
|
|
461
473
|
const elapsed = Date.now() - typingStart;
|
|
462
|
-
const delayBase = retrievalMode === "keyword" || isFallback ?
|
|
463
|
-
const minTypingMs = delayBase + Math.random() *
|
|
474
|
+
const delayBase = retrievalMode === "keyword" || isFallback ? 400 : 800;
|
|
475
|
+
const minTypingMs = delayBase + Math.random() * 400;
|
|
464
476
|
const remaining = minTypingMs - elapsed;
|
|
465
477
|
if (remaining > 0) await new Promise((r) => setTimeout(r, remaining));
|
|
466
478
|
}
|
|
@@ -478,11 +490,9 @@ function useSageDesk(config) {
|
|
|
478
490
|
return () => document.removeEventListener("keydown", handler);
|
|
479
491
|
}, [state.isOpen, close]);
|
|
480
492
|
const activeChips = useMemo(() => {
|
|
481
|
-
const askedTexts = new Set(
|
|
482
|
-
state.messages.filter((m) => m.role === "user").map((m) => m.text.toLowerCase().trim())
|
|
483
|
-
);
|
|
493
|
+
const askedTexts = new Set(state.userMessages.map((m) => m.text.toLowerCase().trim()));
|
|
484
494
|
return chips.filter((chip) => !askedTexts.has(chip.toLowerCase().trim()));
|
|
485
|
-
}, [chips, state.
|
|
495
|
+
}, [chips, state.userMessages]);
|
|
486
496
|
return { state, chips: activeChips, open, close, submit };
|
|
487
497
|
}
|
|
488
498
|
|
|
@@ -678,9 +688,9 @@ var PoweredBy = ({ dark = false }) => /* @__PURE__ */ jsxs("div", { style: {
|
|
|
678
688
|
}
|
|
679
689
|
)
|
|
680
690
|
] });
|
|
681
|
-
|
|
691
|
+
var ClassicMessageBubble = React.memo(function ClassicMessageBubble2({ msg, accent }) {
|
|
682
692
|
const isBot = msg.role === "bot";
|
|
683
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
693
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
684
694
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: isBot ? "flex-start" : "flex-end", gap: "4px" }, children: [
|
|
685
695
|
msg.isFallback && /* @__PURE__ */ jsx("p", { style: { fontSize: "11px", fontWeight: 500, color: "#9b9aa3", margin: 0, padding: "0 4px", fontFamily: "inherit" }, children: "Not sure about that one" }),
|
|
686
696
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -705,7 +715,7 @@ function ClassicMessageBubble({ msg, accent }) {
|
|
|
705
715
|
fontFamily: "inherit"
|
|
706
716
|
}, children: "just now" })
|
|
707
717
|
] });
|
|
708
|
-
}
|
|
718
|
+
});
|
|
709
719
|
function ClassicTypingIndicator() {
|
|
710
720
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c8c8ce", display: "inline-block" };
|
|
711
721
|
return /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "4px" }, children: /* @__PURE__ */ jsxs("div", { style: {
|
|
@@ -723,9 +733,9 @@ function ClassicTypingIndicator() {
|
|
|
723
733
|
/* @__PURE__ */ jsx("span", { style: dot, className: "sd-r-dot-3" })
|
|
724
734
|
] }) });
|
|
725
735
|
}
|
|
726
|
-
|
|
736
|
+
var LightMessageBubble = React.memo(function LightMessageBubble2({ msg, accent, agentName }) {
|
|
727
737
|
const isBot = msg.role === "bot";
|
|
728
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
738
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
729
739
|
if (isBot) {
|
|
730
740
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
731
741
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -760,7 +770,7 @@ function LightMessageBubble({ msg, accent, agentName }) {
|
|
|
760
770
|
wordBreak: "break-word",
|
|
761
771
|
fontFamily: "inherit"
|
|
762
772
|
}, children: msg.text }) });
|
|
763
|
-
}
|
|
773
|
+
});
|
|
764
774
|
function LightTypingIndicator({ accent }) {
|
|
765
775
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c4c4be", display: "inline-block" };
|
|
766
776
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
@@ -788,9 +798,9 @@ function LightTypingIndicator({ accent }) {
|
|
|
788
798
|
] })
|
|
789
799
|
] });
|
|
790
800
|
}
|
|
791
|
-
|
|
801
|
+
var DarkMessageBubble = React.memo(function DarkMessageBubble2({ msg, accent }) {
|
|
792
802
|
const isBot = msg.role === "bot";
|
|
793
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
803
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
794
804
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
795
805
|
maxWidth: "85%",
|
|
796
806
|
padding: "12px 14px",
|
|
@@ -808,7 +818,7 @@ function DarkMessageBubble({ msg, accent }) {
|
|
|
808
818
|
msg.isFallback && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "rgba(255,255,255,0.5)", display: "block", marginBottom: "4px" }, children: "Not sure about that one" }),
|
|
809
819
|
isBot ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx("div", { style: { whiteSpace: "pre-wrap" }, children: msg.text })
|
|
810
820
|
] });
|
|
811
|
-
}
|
|
821
|
+
});
|
|
812
822
|
function DarkTypingIndicator() {
|
|
813
823
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "rgba(255,255,255,0.4)", display: "inline-block" };
|
|
814
824
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
@@ -827,7 +837,7 @@ function DarkTypingIndicator() {
|
|
|
827
837
|
/* @__PURE__ */ jsx("span", { style: dot, className: "sd-r-dot-3" })
|
|
828
838
|
] });
|
|
829
839
|
}
|
|
830
|
-
function
|
|
840
|
+
function ClassicTheme(p) {
|
|
831
841
|
const {
|
|
832
842
|
agent,
|
|
833
843
|
state,
|
|
@@ -1016,7 +1026,7 @@ function renderClassic(p) {
|
|
|
1016
1026
|
] })
|
|
1017
1027
|
] });
|
|
1018
1028
|
}
|
|
1019
|
-
function
|
|
1029
|
+
function LightTheme(p) {
|
|
1020
1030
|
const {
|
|
1021
1031
|
agent,
|
|
1022
1032
|
state,
|
|
@@ -1204,7 +1214,7 @@ function renderLight(p) {
|
|
|
1204
1214
|
] })
|
|
1205
1215
|
] });
|
|
1206
1216
|
}
|
|
1207
|
-
function
|
|
1217
|
+
function DarkTheme(p) {
|
|
1208
1218
|
const {
|
|
1209
1219
|
agent,
|
|
1210
1220
|
state,
|
|
@@ -1441,7 +1451,10 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1441
1451
|
'[sagedesk] Required prop "endpoint" is missing for llm mode. Provide your backend route, e.g. endpoint="/api/sagedesk".'
|
|
1442
1452
|
);
|
|
1443
1453
|
}
|
|
1444
|
-
const config =
|
|
1454
|
+
const config = useMemo2(
|
|
1455
|
+
() => ({ mode: resolvedMode, indexUrl, endpoint, agent, search: search2 }),
|
|
1456
|
+
[resolvedMode, indexUrl, endpoint, agent, search2]
|
|
1457
|
+
);
|
|
1445
1458
|
const { state, chips, open, close, submit } = useSageDesk(config);
|
|
1446
1459
|
const theme = agent.theme ?? "classic";
|
|
1447
1460
|
const accent = agent.accentColor ?? "#534AB7";
|
|
@@ -1520,7 +1533,7 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1520
1533
|
open,
|
|
1521
1534
|
submit
|
|
1522
1535
|
};
|
|
1523
|
-
const content = theme === "dark" ?
|
|
1536
|
+
const content = theme === "dark" ? /* @__PURE__ */ jsx(DarkTheme, { ...props }) : theme === "light" ? /* @__PURE__ */ jsx(LightTheme, { ...props }) : /* @__PURE__ */ jsx(ClassicTheme, { ...props });
|
|
1524
1537
|
return createPortal(content, document.body);
|
|
1525
1538
|
}
|
|
1526
1539
|
export {
|