sagedesk 1.0.0 → 2.0.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 +277 -35
- package/dist/next/{SageDeskWidget-P3H2VJR5.js → SageDeskWidget-R3XJ5OUY.js} +149 -25
- package/dist/next/SageDeskWidget-R3XJ5OUY.js.map +1 -0
- package/dist/next/index.cjs +164 -27
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +10 -3
- package/dist/next/index.d.ts +10 -3
- package/dist/next/index.js +10 -4
- package/dist/next/index.js.map +1 -1
- package/dist/react/index.cjs +148 -24
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +14 -5
- package/dist/react/index.d.ts +14 -5
- package/dist/react/index.js +148 -24
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +348 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +62 -0
- package/dist/server/index.d.ts +62 -0
- package/dist/server/index.js +312 -0
- package/dist/server/index.js.map +1 -0
- package/dist/vanilla/index.cjs +6 -2
- package/dist/vanilla/index.cjs.map +1 -1
- package/dist/vanilla/index.d.cts +4 -2
- package/dist/vanilla/index.d.ts +4 -2
- package/dist/vanilla/index.js +6 -2
- package/dist/vanilla/index.js.map +1 -1
- package/package.json +10 -3
- package/dist/next/SageDeskWidget-P3H2VJR5.js.map +0 -1
package/dist/react/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
type SageDeskModel = 'all-MiniLM-L6-v2' | 'bge-small-en-v1-5' | 'paraphrase-multilingual-MiniLM-L12-v2' | 'all-mpnet-base-v2';
|
|
4
4
|
type Theme = 'classic' | 'light' | 'dark';
|
|
5
|
+
type SageDeskMode = 'local' | 'llm';
|
|
5
6
|
interface AgentConfig {
|
|
6
7
|
name: string;
|
|
7
8
|
model?: SageDeskModel;
|
|
@@ -13,7 +14,6 @@ interface AgentConfig {
|
|
|
13
14
|
position?: 'bottom-right' | 'bottom-left';
|
|
14
15
|
avatarUrl?: string;
|
|
15
16
|
contactUrl?: string;
|
|
16
|
-
poweredBy?: boolean;
|
|
17
17
|
suggestedChips?: string[];
|
|
18
18
|
}
|
|
19
19
|
interface SearchConfig {
|
|
@@ -21,25 +21,34 @@ interface SearchConfig {
|
|
|
21
21
|
topK?: number;
|
|
22
22
|
}
|
|
23
23
|
interface SageDeskConfig {
|
|
24
|
-
|
|
24
|
+
mode?: SageDeskMode;
|
|
25
|
+
indexUrl?: string;
|
|
26
|
+
endpoint?: string;
|
|
25
27
|
agent: AgentConfig;
|
|
26
28
|
search?: SearchConfig;
|
|
27
29
|
}
|
|
30
|
+
type FallbackReason = 'auth-error' | 'quota-exceeded' | 'timeout' | 'api-error' | 'malformed-response';
|
|
28
31
|
interface ChatMessage {
|
|
29
32
|
id: string;
|
|
30
33
|
role: 'user' | 'bot';
|
|
31
34
|
text: string;
|
|
32
35
|
isFallback?: boolean;
|
|
36
|
+
fallbackReason?: FallbackReason;
|
|
33
37
|
timestamp: Date;
|
|
34
38
|
}
|
|
35
39
|
type EngineStatus = 'idle' | 'loading-index' | 'loading-model' | 'ready' | 'error-index' | 'error-model' | 'degraded';
|
|
36
40
|
|
|
37
41
|
interface SageDeskWidgetProps {
|
|
38
|
-
|
|
42
|
+
/** Operating mode. 'local' (default) runs entirely in the browser via WASM. 'llm' posts to the consumer's own backend. */
|
|
43
|
+
mode?: SageDeskMode;
|
|
44
|
+
/** URL to the pre-built vector index. Required in local mode. */
|
|
45
|
+
indexUrl?: string;
|
|
46
|
+
/** Consumer's backend endpoint that accepts POST { query }. Required in llm mode. */
|
|
47
|
+
endpoint?: string;
|
|
39
48
|
agent: SageDeskConfig['agent'];
|
|
40
49
|
search?: SageDeskConfig['search'];
|
|
41
50
|
}
|
|
42
|
-
declare function SageDeskWidget({ indexUrl, agent, search }: SageDeskWidgetProps): React.ReactPortal | null;
|
|
51
|
+
declare function SageDeskWidget({ mode, indexUrl, endpoint, agent, search }: SageDeskWidgetProps): React.ReactPortal | null;
|
|
43
52
|
|
|
44
53
|
interface State {
|
|
45
54
|
messages: ChatMessage[];
|
|
@@ -58,4 +67,4 @@ interface UseSageDeskReturn {
|
|
|
58
67
|
}
|
|
59
68
|
declare function useSageDesk(config: SageDeskConfig): UseSageDeskReturn;
|
|
60
69
|
|
|
61
|
-
export { type AgentConfig, type ChatMessage, type SageDeskConfig, SageDeskWidget, type SageDeskWidgetProps, type SearchConfig, type UseSageDeskReturn, useSageDesk };
|
|
70
|
+
export { type AgentConfig, type ChatMessage, type SageDeskConfig, type SageDeskMode, SageDeskWidget, type SageDeskWidgetProps, type SearchConfig, type UseSageDeskReturn, useSageDesk };
|
package/dist/react/index.js
CHANGED
|
@@ -226,6 +226,17 @@ function getFallback(config) {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// src/react/useSageDesk.ts
|
|
229
|
+
function logFallbackWarning(reason) {
|
|
230
|
+
if (!reason) return;
|
|
231
|
+
const messages = {
|
|
232
|
+
"auth-error": "[sagedesk] Support service authentication failed. Showing relevant knowledge instead.",
|
|
233
|
+
"quota-exceeded": "[sagedesk] Support service quota exhausted. Showing relevant knowledge instead.",
|
|
234
|
+
"timeout": "[sagedesk] Support service took too long to respond. Showing relevant knowledge instead.",
|
|
235
|
+
"api-error": "[sagedesk] Support service error. Showing relevant knowledge instead.",
|
|
236
|
+
"malformed-response": "[sagedesk] Support service returned invalid response. Showing relevant knowledge instead."
|
|
237
|
+
};
|
|
238
|
+
console.warn(messages[reason] || "[sagedesk] Support service unavailable. Showing relevant knowledge instead.");
|
|
239
|
+
}
|
|
229
240
|
var initialState = {
|
|
230
241
|
messages: [],
|
|
231
242
|
isOpen: false,
|
|
@@ -278,6 +289,11 @@ function useSageDesk(config) {
|
|
|
278
289
|
const startEngine = useCallback(async () => {
|
|
279
290
|
if (engineStartedRef.current) return;
|
|
280
291
|
engineStartedRef.current = true;
|
|
292
|
+
if (config.mode === "llm") {
|
|
293
|
+
setChips(config.agent.suggestedChips ?? []);
|
|
294
|
+
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
281
297
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "loading-index" } });
|
|
282
298
|
try {
|
|
283
299
|
indexRef.current = await fetchIndex(config.indexUrl);
|
|
@@ -304,7 +320,7 @@ function useSageDesk(config) {
|
|
|
304
320
|
embedderRef.current = new EmbedderRuntime();
|
|
305
321
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "degraded" } });
|
|
306
322
|
}
|
|
307
|
-
}, [config.indexUrl, config.agent.suggestedChips, addMessage]);
|
|
323
|
+
}, [config.mode, config.indexUrl, config.agent.suggestedChips, addMessage]);
|
|
308
324
|
const greetingShownRef = useRef(false);
|
|
309
325
|
const open = useCallback(() => {
|
|
310
326
|
dispatch({ type: "OPEN" });
|
|
@@ -347,8 +363,37 @@ function useSageDesk(config) {
|
|
|
347
363
|
}
|
|
348
364
|
let botText;
|
|
349
365
|
let isFallback = false;
|
|
350
|
-
let
|
|
351
|
-
|
|
366
|
+
let fallbackReason;
|
|
367
|
+
let retrievalMode = "keyword";
|
|
368
|
+
if (config.mode === "llm") {
|
|
369
|
+
if (!config.endpoint) {
|
|
370
|
+
console.warn('[sagedesk] LLM mode requires an "endpoint" prop.');
|
|
371
|
+
botText = getFallback(config.agent);
|
|
372
|
+
isFallback = true;
|
|
373
|
+
} else {
|
|
374
|
+
try {
|
|
375
|
+
const res = await fetch(config.endpoint, {
|
|
376
|
+
method: "POST",
|
|
377
|
+
headers: { "Content-Type": "application/json" },
|
|
378
|
+
body: JSON.stringify({ query: trimmed })
|
|
379
|
+
});
|
|
380
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
381
|
+
const data = await res.json();
|
|
382
|
+
if (data.isFallback || !data.answer) {
|
|
383
|
+
fallbackReason = data.fallbackReason;
|
|
384
|
+
logFallbackWarning(fallbackReason);
|
|
385
|
+
botText = getFallback(config.agent);
|
|
386
|
+
isFallback = true;
|
|
387
|
+
} else {
|
|
388
|
+
botText = data.answer;
|
|
389
|
+
}
|
|
390
|
+
} catch (err) {
|
|
391
|
+
console.warn("[sagedesk] Support service unavailable. Using cached knowledge instead.");
|
|
392
|
+
botText = getFallback(config.agent);
|
|
393
|
+
isFallback = true;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
} else if (!indexRef.current) {
|
|
352
397
|
botText = getFallback(config.agent);
|
|
353
398
|
isFallback = true;
|
|
354
399
|
} else {
|
|
@@ -359,7 +404,7 @@ function useSageDesk(config) {
|
|
|
359
404
|
embedderRef.current,
|
|
360
405
|
config.search
|
|
361
406
|
);
|
|
362
|
-
|
|
407
|
+
retrievalMode = res.mode;
|
|
363
408
|
if (res.results.length > 0) {
|
|
364
409
|
botText = buildAnswer(res.results);
|
|
365
410
|
} else {
|
|
@@ -372,11 +417,13 @@ function useSageDesk(config) {
|
|
|
372
417
|
isFallback = true;
|
|
373
418
|
}
|
|
374
419
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
420
|
+
if (config.mode !== "llm") {
|
|
421
|
+
const elapsed = Date.now() - typingStart;
|
|
422
|
+
const delayBase = retrievalMode === "keyword" || isFallback ? 800 : 3e3;
|
|
423
|
+
const minTypingMs = delayBase + Math.random() * 2e3;
|
|
424
|
+
const remaining = minTypingMs - elapsed;
|
|
425
|
+
if (remaining > 0) await new Promise((r) => setTimeout(r, remaining));
|
|
426
|
+
}
|
|
380
427
|
dispatch({ type: "SET_TYPING", payload: false });
|
|
381
428
|
addMessage({ role: "bot", text: botText, isFallback });
|
|
382
429
|
},
|
|
@@ -399,6 +446,54 @@ function useSageDesk(config) {
|
|
|
399
446
|
return { state, chips: activeChips, open, close, submit };
|
|
400
447
|
}
|
|
401
448
|
|
|
449
|
+
// src/react/markdownUtils.ts
|
|
450
|
+
import { marked } from "marked";
|
|
451
|
+
import DOMPurify from "dompurify";
|
|
452
|
+
marked.setOptions({
|
|
453
|
+
breaks: true,
|
|
454
|
+
gfm: true,
|
|
455
|
+
pedantic: false
|
|
456
|
+
});
|
|
457
|
+
var PURIFY_CONFIG = {
|
|
458
|
+
ALLOWED_TAGS: [
|
|
459
|
+
"p",
|
|
460
|
+
"br",
|
|
461
|
+
"strong",
|
|
462
|
+
"em",
|
|
463
|
+
"u",
|
|
464
|
+
"h1",
|
|
465
|
+
"h2",
|
|
466
|
+
"h3",
|
|
467
|
+
"h4",
|
|
468
|
+
"h5",
|
|
469
|
+
"h6",
|
|
470
|
+
"ul",
|
|
471
|
+
"ol",
|
|
472
|
+
"li",
|
|
473
|
+
"blockquote",
|
|
474
|
+
"code",
|
|
475
|
+
"pre",
|
|
476
|
+
"a",
|
|
477
|
+
"hr"
|
|
478
|
+
],
|
|
479
|
+
ALLOWED_ATTR: ["href", "title", "target", "rel"],
|
|
480
|
+
ALLOW_DATA_ATTR: false
|
|
481
|
+
};
|
|
482
|
+
var HOOK_ALLOWLIST = ["a"];
|
|
483
|
+
DOMPurify.addHook("afterSanitizeAttributes", (node) => {
|
|
484
|
+
if (HOOK_ALLOWLIST.includes(node.tagName.toLowerCase())) {
|
|
485
|
+
if (node.tagName.toLowerCase() === "a") {
|
|
486
|
+
node.setAttribute("target", "_blank");
|
|
487
|
+
node.setAttribute("rel", "noopener noreferrer");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
function parseMarkdown(markdown) {
|
|
492
|
+
const html = marked.parse(markdown);
|
|
493
|
+
const sanitized = DOMPurify.sanitize(html, PURIFY_CONFIG);
|
|
494
|
+
return sanitized;
|
|
495
|
+
}
|
|
496
|
+
|
|
402
497
|
// src/react/SageDeskWidget.tsx
|
|
403
498
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
404
499
|
var STYLE_ID = "sagedesk-widget-styles";
|
|
@@ -428,6 +523,28 @@ var SHARED = `
|
|
|
428
523
|
}
|
|
429
524
|
.sd-r-scrollable::-webkit-scrollbar { display: none !important; }
|
|
430
525
|
.sd-r-scrollable > * { flex-shrink: 0 !important; }
|
|
526
|
+
.sd-r-markdown h1, .sd-r-markdown h2, .sd-r-markdown h3, .sd-r-markdown h4, .sd-r-markdown h5, .sd-r-markdown h6 {
|
|
527
|
+
margin: 12px 0 8px 0 !important; font-weight: 600 !important; line-height: 1.3 !important;
|
|
528
|
+
}
|
|
529
|
+
.sd-r-markdown h1 { font-size: 1.3em !important; }
|
|
530
|
+
.sd-r-markdown h2 { font-size: 1.2em !important; }
|
|
531
|
+
.sd-r-markdown h3 { font-size: 1.1em !important; }
|
|
532
|
+
.sd-r-markdown h4, .sd-r-markdown h5, .sd-r-markdown h6 { font-size: 1em !important; }
|
|
533
|
+
.sd-r-markdown strong { font-weight: 600 !important; }
|
|
534
|
+
.sd-r-markdown em { font-style: italic !important; }
|
|
535
|
+
.sd-r-markdown u { text-decoration: underline !important; }
|
|
536
|
+
.sd-r-markdown ul, .sd-r-markdown ol { margin: 8px 0 !important; padding-left: 20px !important; }
|
|
537
|
+
.sd-r-markdown li { margin: 4px 0 !important; }
|
|
538
|
+
.sd-r-markdown blockquote { margin: 8px 0 !important; padding-left: 12px !important; border-left: 3px solid currentColor !important; opacity: 0.8 !important; }
|
|
539
|
+
.sd-r-markdown code { font-family: 'Monaco', 'Courier New', monospace !important; font-size: 0.9em !important; padding: 2px 4px !important; background: rgba(0,0,0,0.05) !important; border-radius: 3px !important; }
|
|
540
|
+
.sd-r-markdown pre { background: rgba(0,0,0,0.05) !important; padding: 8px 10px !important; border-radius: 6px !important; overflow-x: auto !important; margin: 8px 0 !important; }
|
|
541
|
+
.sd-r-markdown pre code { background: none !important; padding: 0 !important; }
|
|
542
|
+
.sd-r-markdown hr { border: none !important; border-top: 1px solid currentColor !important; opacity: 0.3 !important; margin: 10px 0 !important; }
|
|
543
|
+
.sd-r-markdown a { text-decoration: underline !important; opacity: 0.9 !important; }
|
|
544
|
+
.sd-r-markdown a:hover { opacity: 1 !important; }
|
|
545
|
+
.sd-r-markdown p { margin: 6px 0 !important; }
|
|
546
|
+
.sd-r-markdown > *:first-child { margin-top: 0 !important; }
|
|
547
|
+
.sd-r-markdown > *:last-child { margin-bottom: 0 !important; }
|
|
431
548
|
@media (max-width: 420px) {
|
|
432
549
|
.sd-r-panel {
|
|
433
550
|
bottom: 0 !important; right: 0 !important; left: 0 !important;
|
|
@@ -514,7 +631,7 @@ var PoweredBy = ({ dark = false }) => /* @__PURE__ */ jsxs("div", { style: {
|
|
|
514
631
|
{
|
|
515
632
|
href: "https://github.com/mzeeshanwahid/sagedesk",
|
|
516
633
|
target: "_blank",
|
|
517
|
-
rel: "noopener
|
|
634
|
+
rel: "noopener",
|
|
518
635
|
style: {
|
|
519
636
|
color: dark ? "rgba(255,255,255,0.7)" : "#5a5a64",
|
|
520
637
|
fontWeight: 500,
|
|
@@ -526,6 +643,7 @@ var PoweredBy = ({ dark = false }) => /* @__PURE__ */ jsxs("div", { style: {
|
|
|
526
643
|
] });
|
|
527
644
|
function ClassicMessageBubble({ msg, accent }) {
|
|
528
645
|
const isBot = msg.role === "bot";
|
|
646
|
+
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
529
647
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: isBot ? "flex-start" : "flex-end", gap: "4px" }, children: [
|
|
530
648
|
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" }),
|
|
531
649
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -538,10 +656,9 @@ function ClassicMessageBubble({ msg, accent }) {
|
|
|
538
656
|
color: isBot ? "#1a1a2e" : "#fff",
|
|
539
657
|
border: isBot ? "1px solid rgba(20,20,40,0.06)" : "none",
|
|
540
658
|
boxShadow: isBot ? "0 1px 2px rgba(20,20,40,0.04)" : `0 6px 16px -6px color-mix(in oklab, ${accent} 60%, transparent)`,
|
|
541
|
-
whiteSpace: "pre-wrap",
|
|
542
659
|
wordBreak: "break-word",
|
|
543
660
|
fontFamily: "inherit"
|
|
544
|
-
}, children: msg.text }),
|
|
661
|
+
}, className: "sd-r-markdown", children: isBot ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx("div", { style: { whiteSpace: "pre-wrap" }, children: msg.text }) }),
|
|
545
662
|
/* @__PURE__ */ jsx("span", { style: {
|
|
546
663
|
fontSize: "11px",
|
|
547
664
|
color: "#a8a8b0",
|
|
@@ -571,6 +688,7 @@ function ClassicTypingIndicator() {
|
|
|
571
688
|
}
|
|
572
689
|
function LightMessageBubble({ msg, accent, agentName }) {
|
|
573
690
|
const isBot = msg.role === "bot";
|
|
691
|
+
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
574
692
|
if (isBot) {
|
|
575
693
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
576
694
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -587,7 +705,7 @@ function LightMessageBubble({ msg, accent, agentName }) {
|
|
|
587
705
|
/* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#a8a89e", fontVariantNumeric: "tabular-nums", fontFamily: "inherit" }, children: "just now" })
|
|
588
706
|
] }),
|
|
589
707
|
msg.isFallback && /* @__PURE__ */ jsx("p", { style: { fontSize: "11px", color: "#9b9aa3", margin: "0 0 4px", fontFamily: "inherit" }, children: "Not sure about that one" }),
|
|
590
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: "14px", lineHeight: 1.55, color: "#2a2a36", fontFamily: "inherit",
|
|
708
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: "14px", lineHeight: 1.55, color: "#2a2a36", fontFamily: "inherit", wordBreak: "break-word" }, className: "sd-r-markdown", children: /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) })
|
|
591
709
|
] })
|
|
592
710
|
] });
|
|
593
711
|
}
|
|
@@ -635,6 +753,7 @@ function LightTypingIndicator({ accent }) {
|
|
|
635
753
|
}
|
|
636
754
|
function DarkMessageBubble({ msg, accent }) {
|
|
637
755
|
const isBot = msg.role === "bot";
|
|
756
|
+
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
638
757
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
639
758
|
maxWidth: "85%",
|
|
640
759
|
padding: "12px 14px",
|
|
@@ -646,12 +765,11 @@ function DarkMessageBubble({ msg, accent }) {
|
|
|
646
765
|
color: isBot ? "rgba(255,255,255,0.92)" : "#fff",
|
|
647
766
|
alignSelf: isBot ? "flex-start" : "flex-end",
|
|
648
767
|
boxShadow: isBot ? "none" : `0 8px 20px -8px color-mix(in oklab, ${accent} 70%, transparent)`,
|
|
649
|
-
whiteSpace: "pre-wrap",
|
|
650
768
|
wordBreak: "break-word",
|
|
651
769
|
fontFamily: "inherit"
|
|
652
|
-
}, children: [
|
|
770
|
+
}, className: isBot ? "sd-r-markdown" : "", children: [
|
|
653
771
|
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" }),
|
|
654
|
-
msg.text
|
|
772
|
+
isBot ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx("div", { style: { whiteSpace: "pre-wrap" }, children: msg.text })
|
|
655
773
|
] });
|
|
656
774
|
}
|
|
657
775
|
function DarkTypingIndicator() {
|
|
@@ -1271,16 +1389,22 @@ function renderDark(p) {
|
|
|
1271
1389
|
] })
|
|
1272
1390
|
] });
|
|
1273
1391
|
}
|
|
1274
|
-
function SageDeskWidget({ indexUrl, agent, search: search2 }) {
|
|
1275
|
-
|
|
1392
|
+
function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
1393
|
+
const resolvedMode = mode ?? "local";
|
|
1394
|
+
if (!agent?.name) {
|
|
1395
|
+
throw new Error('[sagedesk] Required prop "agent.name" is missing.');
|
|
1396
|
+
}
|
|
1397
|
+
if (resolvedMode === "local" && !indexUrl) {
|
|
1276
1398
|
throw new Error(
|
|
1277
|
-
'[sagedesk] Required prop "indexUrl" is missing. Run `npx sagedesk build` and pass the output path, e.g. indexUrl="/support-index.json".'
|
|
1399
|
+
'[sagedesk] Required prop "indexUrl" is missing for local mode. Run `npx sagedesk build` and pass the output path, e.g. indexUrl="/support-index.json".'
|
|
1278
1400
|
);
|
|
1279
1401
|
}
|
|
1280
|
-
if (!
|
|
1281
|
-
throw new Error(
|
|
1402
|
+
if (resolvedMode === "llm" && !endpoint) {
|
|
1403
|
+
throw new Error(
|
|
1404
|
+
'[sagedesk] Required prop "endpoint" is missing for llm mode. Provide your backend route, e.g. endpoint="/api/sagedesk".'
|
|
1405
|
+
);
|
|
1282
1406
|
}
|
|
1283
|
-
const config = { indexUrl, agent, search: search2 };
|
|
1407
|
+
const config = { mode: resolvedMode, indexUrl, endpoint, agent, search: search2 };
|
|
1284
1408
|
const { state, chips, open, close, submit } = useSageDesk(config);
|
|
1285
1409
|
const theme = agent.theme ?? "classic";
|
|
1286
1410
|
const accent = agent.accentColor ?? "#534AB7";
|
|
@@ -1293,7 +1417,7 @@ function SageDeskWidget({ indexUrl, agent, search: search2 }) {
|
|
|
1293
1417
|
const triggerRef = useRef2(null);
|
|
1294
1418
|
const [mounted, setMounted] = useState2(false);
|
|
1295
1419
|
useEffect2(() => {
|
|
1296
|
-
if (!indexUrl.startsWith("/") && !indexUrl.startsWith("http")) {
|
|
1420
|
+
if (resolvedMode === "local" && indexUrl && !indexUrl.startsWith("/") && !indexUrl.startsWith("http")) {
|
|
1297
1421
|
console.warn(
|
|
1298
1422
|
`[sagedesk] indexUrl "${indexUrl}" looks like a relative path. It should start with "/" so it resolves correctly from any page.`
|
|
1299
1423
|
);
|
|
@@ -1335,7 +1459,7 @@ function SageDeskWidget({ indexUrl, agent, search: search2 }) {
|
|
|
1335
1459
|
[handleSubmit]
|
|
1336
1460
|
);
|
|
1337
1461
|
if (!mounted || typeof document === "undefined") return null;
|
|
1338
|
-
const showPoweredBy =
|
|
1462
|
+
const showPoweredBy = true;
|
|
1339
1463
|
const showChips = chips.length > 0;
|
|
1340
1464
|
const panelClass = isClosing ? "sd-r-closing" : state.isOpen ? "sd-r-opening" : "";
|
|
1341
1465
|
const props = {
|