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.cjs
CHANGED
|
@@ -36,7 +36,7 @@ __export(react_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(react_exports);
|
|
37
37
|
|
|
38
38
|
// src/react/SageDeskWidget.tsx
|
|
39
|
-
var import_react2 = require("react");
|
|
39
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
40
40
|
var import_react_dom = require("react-dom");
|
|
41
41
|
|
|
42
42
|
// src/react/useSageDesk.ts
|
|
@@ -295,6 +295,7 @@ function logFallbackWarning(reason) {
|
|
|
295
295
|
}
|
|
296
296
|
var initialState = {
|
|
297
297
|
messages: [],
|
|
298
|
+
userMessages: [],
|
|
298
299
|
isOpen: false,
|
|
299
300
|
isTyping: false,
|
|
300
301
|
engineStatus: "idle",
|
|
@@ -307,8 +308,11 @@ function reducer(state, action) {
|
|
|
307
308
|
return { ...state, isOpen: true };
|
|
308
309
|
case "CLOSE":
|
|
309
310
|
return { ...state, isOpen: false };
|
|
310
|
-
case "ADD_MESSAGE":
|
|
311
|
-
|
|
311
|
+
case "ADD_MESSAGE": {
|
|
312
|
+
const newMessages = [...state.messages, action.payload];
|
|
313
|
+
const newUserMessages = action.payload.role === "user" ? [...state.userMessages, action.payload] : state.userMessages;
|
|
314
|
+
return { ...state, messages: newMessages, userMessages: newUserMessages };
|
|
315
|
+
}
|
|
312
316
|
case "SET_TYPING":
|
|
313
317
|
return { ...state, isTyping: action.payload };
|
|
314
318
|
case "SET_ENGINE_STATUS":
|
|
@@ -331,6 +335,7 @@ function useSageDesk(config) {
|
|
|
331
335
|
const embedderRef = (0, import_react.useRef)(null);
|
|
332
336
|
const engineStartedRef = (0, import_react.useRef)(false);
|
|
333
337
|
const msgCounterRef = (0, import_react.useRef)(0);
|
|
338
|
+
const engineReadyCallbacksRef = (0, import_react.useRef)([]);
|
|
334
339
|
const [chips, setChips] = (0, import_react.useState)([]);
|
|
335
340
|
const makeId = () => `msg-${++msgCounterRef.current}`;
|
|
336
341
|
const addMessage = (0, import_react.useCallback)(
|
|
@@ -342,6 +347,11 @@ function useSageDesk(config) {
|
|
|
342
347
|
},
|
|
343
348
|
[]
|
|
344
349
|
);
|
|
350
|
+
const notifyEngineReady = (0, import_react.useCallback)(() => {
|
|
351
|
+
const callbacks = engineReadyCallbacksRef.current;
|
|
352
|
+
engineReadyCallbacksRef.current = [];
|
|
353
|
+
callbacks.forEach((cb) => cb());
|
|
354
|
+
}, []);
|
|
345
355
|
const startEngine = (0, import_react.useCallback)(async () => {
|
|
346
356
|
if (engineStartedRef.current) return;
|
|
347
357
|
engineStartedRef.current = true;
|
|
@@ -352,9 +362,11 @@ function useSageDesk(config) {
|
|
|
352
362
|
embedderRef.current = new EmbedderRuntime();
|
|
353
363
|
await embedderRef.current.load(config.agent.model);
|
|
354
364
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
365
|
+
notifyEngineReady();
|
|
355
366
|
} catch (err) {
|
|
356
367
|
console.warn("[sagedesk] WASM embedder failed to load - LLM mode will use fallback messages.", err);
|
|
357
368
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "error-model", error: String(err) } });
|
|
369
|
+
notifyEngineReady();
|
|
358
370
|
}
|
|
359
371
|
return;
|
|
360
372
|
}
|
|
@@ -367,6 +379,7 @@ function useSageDesk(config) {
|
|
|
367
379
|
type: "SET_ENGINE_STATUS",
|
|
368
380
|
payload: { status: "error-index", error: String(err) }
|
|
369
381
|
});
|
|
382
|
+
notifyEngineReady();
|
|
370
383
|
addMessage({
|
|
371
384
|
role: "bot",
|
|
372
385
|
text: "I'm having trouble loading right now. Please try again in a moment."
|
|
@@ -379,12 +392,14 @@ function useSageDesk(config) {
|
|
|
379
392
|
embedderRef.current = new EmbedderRuntime();
|
|
380
393
|
await embedderRef.current.load(config.agent.model);
|
|
381
394
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
395
|
+
notifyEngineReady();
|
|
382
396
|
} catch (err) {
|
|
383
397
|
console.warn("[sagedesk] WASM model failed to load, falling back to keyword search -", err);
|
|
384
398
|
embedderRef.current = new EmbedderRuntime();
|
|
385
399
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "degraded" } });
|
|
400
|
+
notifyEngineReady();
|
|
386
401
|
}
|
|
387
|
-
}, [config.mode, config.indexUrl, config.agent.model, config.agent.suggestedChips, addMessage]);
|
|
402
|
+
}, [config.mode, config.indexUrl, config.agent.model, config.agent.suggestedChips, addMessage, notifyEngineReady]);
|
|
388
403
|
const greetingShownRef = (0, import_react.useRef)(false);
|
|
389
404
|
const open = (0, import_react.useCallback)(() => {
|
|
390
405
|
dispatch({ type: "OPEN" });
|
|
@@ -401,16 +416,12 @@ function useSageDesk(config) {
|
|
|
401
416
|
dispatch({ type: "CLOSE" });
|
|
402
417
|
}, []);
|
|
403
418
|
const waitForEngine = (0, import_react.useCallback)(() => {
|
|
419
|
+
const s = engineStatusRef.current;
|
|
420
|
+
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
421
|
+
return Promise.resolve();
|
|
422
|
+
}
|
|
404
423
|
return new Promise((resolve) => {
|
|
405
|
-
|
|
406
|
-
const s = engineStatusRef.current;
|
|
407
|
-
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
408
|
-
resolve();
|
|
409
|
-
} else {
|
|
410
|
-
setTimeout(check, 100);
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
check();
|
|
424
|
+
engineReadyCallbacksRef.current.push(resolve);
|
|
414
425
|
});
|
|
415
426
|
}, []);
|
|
416
427
|
const submit = (0, import_react.useCallback)(
|
|
@@ -491,8 +502,8 @@ function useSageDesk(config) {
|
|
|
491
502
|
}
|
|
492
503
|
if (config.mode !== "llm") {
|
|
493
504
|
const elapsed = Date.now() - typingStart;
|
|
494
|
-
const delayBase = retrievalMode === "keyword" || isFallback ?
|
|
495
|
-
const minTypingMs = delayBase + Math.random() *
|
|
505
|
+
const delayBase = retrievalMode === "keyword" || isFallback ? 400 : 800;
|
|
506
|
+
const minTypingMs = delayBase + Math.random() * 400;
|
|
496
507
|
const remaining = minTypingMs - elapsed;
|
|
497
508
|
if (remaining > 0) await new Promise((r) => setTimeout(r, remaining));
|
|
498
509
|
}
|
|
@@ -510,11 +521,9 @@ function useSageDesk(config) {
|
|
|
510
521
|
return () => document.removeEventListener("keydown", handler);
|
|
511
522
|
}, [state.isOpen, close]);
|
|
512
523
|
const activeChips = (0, import_react.useMemo)(() => {
|
|
513
|
-
const askedTexts = new Set(
|
|
514
|
-
state.messages.filter((m) => m.role === "user").map((m) => m.text.toLowerCase().trim())
|
|
515
|
-
);
|
|
524
|
+
const askedTexts = new Set(state.userMessages.map((m) => m.text.toLowerCase().trim()));
|
|
516
525
|
return chips.filter((chip) => !askedTexts.has(chip.toLowerCase().trim()));
|
|
517
|
-
}, [chips, state.
|
|
526
|
+
}, [chips, state.userMessages]);
|
|
518
527
|
return { state, chips: activeChips, open, close, submit };
|
|
519
528
|
}
|
|
520
529
|
|
|
@@ -710,9 +719,9 @@ var PoweredBy = ({ dark = false }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx
|
|
|
710
719
|
}
|
|
711
720
|
)
|
|
712
721
|
] });
|
|
713
|
-
|
|
722
|
+
var ClassicMessageBubble = import_react2.default.memo(function ClassicMessageBubble2({ msg, accent }) {
|
|
714
723
|
const isBot = msg.role === "bot";
|
|
715
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
724
|
+
const renderedHtml = (0, import_react2.useMemo)(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
716
725
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: isBot ? "flex-start" : "flex-end", gap: "4px" }, children: [
|
|
717
726
|
msg.isFallback && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: "11px", fontWeight: 500, color: "#9b9aa3", margin: 0, padding: "0 4px", fontFamily: "inherit" }, children: "Not sure about that one" }),
|
|
718
727
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
@@ -737,7 +746,7 @@ function ClassicMessageBubble({ msg, accent }) {
|
|
|
737
746
|
fontFamily: "inherit"
|
|
738
747
|
}, children: "just now" })
|
|
739
748
|
] });
|
|
740
|
-
}
|
|
749
|
+
});
|
|
741
750
|
function ClassicTypingIndicator() {
|
|
742
751
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c8c8ce", display: "inline-block" };
|
|
743
752
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
@@ -755,9 +764,9 @@ function ClassicTypingIndicator() {
|
|
|
755
764
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dot, className: "sd-r-dot-3" })
|
|
756
765
|
] }) });
|
|
757
766
|
}
|
|
758
|
-
|
|
767
|
+
var LightMessageBubble = import_react2.default.memo(function LightMessageBubble2({ msg, accent, agentName }) {
|
|
759
768
|
const isBot = msg.role === "bot";
|
|
760
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
769
|
+
const renderedHtml = (0, import_react2.useMemo)(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
761
770
|
if (isBot) {
|
|
762
771
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
763
772
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
@@ -792,7 +801,7 @@ function LightMessageBubble({ msg, accent, agentName }) {
|
|
|
792
801
|
wordBreak: "break-word",
|
|
793
802
|
fontFamily: "inherit"
|
|
794
803
|
}, children: msg.text }) });
|
|
795
|
-
}
|
|
804
|
+
});
|
|
796
805
|
function LightTypingIndicator({ accent }) {
|
|
797
806
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c4c4be", display: "inline-block" };
|
|
798
807
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
@@ -820,9 +829,9 @@ function LightTypingIndicator({ accent }) {
|
|
|
820
829
|
] })
|
|
821
830
|
] });
|
|
822
831
|
}
|
|
823
|
-
|
|
832
|
+
var DarkMessageBubble = import_react2.default.memo(function DarkMessageBubble2({ msg, accent }) {
|
|
824
833
|
const isBot = msg.role === "bot";
|
|
825
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
834
|
+
const renderedHtml = (0, import_react2.useMemo)(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
826
835
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
827
836
|
maxWidth: "85%",
|
|
828
837
|
padding: "12px 14px",
|
|
@@ -840,7 +849,7 @@ function DarkMessageBubble({ msg, accent }) {
|
|
|
840
849
|
msg.isFallback && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: "rgba(255,255,255,0.5)", display: "block", marginBottom: "4px" }, children: "Not sure about that one" }),
|
|
841
850
|
isBot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { whiteSpace: "pre-wrap" }, children: msg.text })
|
|
842
851
|
] });
|
|
843
|
-
}
|
|
852
|
+
});
|
|
844
853
|
function DarkTypingIndicator() {
|
|
845
854
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "rgba(255,255,255,0.4)", display: "inline-block" };
|
|
846
855
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
@@ -859,7 +868,7 @@ function DarkTypingIndicator() {
|
|
|
859
868
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dot, className: "sd-r-dot-3" })
|
|
860
869
|
] });
|
|
861
870
|
}
|
|
862
|
-
function
|
|
871
|
+
function ClassicTheme(p) {
|
|
863
872
|
const {
|
|
864
873
|
agent,
|
|
865
874
|
state,
|
|
@@ -1048,7 +1057,7 @@ function renderClassic(p) {
|
|
|
1048
1057
|
] })
|
|
1049
1058
|
] });
|
|
1050
1059
|
}
|
|
1051
|
-
function
|
|
1060
|
+
function LightTheme(p) {
|
|
1052
1061
|
const {
|
|
1053
1062
|
agent,
|
|
1054
1063
|
state,
|
|
@@ -1236,7 +1245,7 @@ function renderLight(p) {
|
|
|
1236
1245
|
] })
|
|
1237
1246
|
] });
|
|
1238
1247
|
}
|
|
1239
|
-
function
|
|
1248
|
+
function DarkTheme(p) {
|
|
1240
1249
|
const {
|
|
1241
1250
|
agent,
|
|
1242
1251
|
state,
|
|
@@ -1473,7 +1482,10 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1473
1482
|
'[sagedesk] Required prop "endpoint" is missing for llm mode. Provide your backend route, e.g. endpoint="/api/sagedesk".'
|
|
1474
1483
|
);
|
|
1475
1484
|
}
|
|
1476
|
-
const config =
|
|
1485
|
+
const config = (0, import_react2.useMemo)(
|
|
1486
|
+
() => ({ mode: resolvedMode, indexUrl, endpoint, agent, search: search2 }),
|
|
1487
|
+
[resolvedMode, indexUrl, endpoint, agent, search2]
|
|
1488
|
+
);
|
|
1477
1489
|
const { state, chips, open, close, submit } = useSageDesk(config);
|
|
1478
1490
|
const theme = agent.theme ?? "classic";
|
|
1479
1491
|
const accent = agent.accentColor ?? "#534AB7";
|
|
@@ -1552,7 +1564,7 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1552
1564
|
open,
|
|
1553
1565
|
submit
|
|
1554
1566
|
};
|
|
1555
|
-
const content = theme === "dark" ?
|
|
1567
|
+
const content = theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DarkTheme, { ...props }) : theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LightTheme, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ClassicTheme, { ...props });
|
|
1556
1568
|
return (0, import_react_dom.createPortal)(content, document.body);
|
|
1557
1569
|
}
|
|
1558
1570
|
// Annotate the CommonJS export names for ESM import in node:
|