sagedesk 2.1.1 → 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 +17 -38
- package/dist/next/{SageDeskWidget-SJVE6QK3.js → SageDeskWidget-ZJJGXTTC.js} +66 -37
- package/dist/next/SageDeskWidget-ZJJGXTTC.js.map +1 -0
- package/dist/next/index.cjs +142 -114
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +1 -1
- package/dist/react/index.cjs +63 -35
- 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 +65 -36
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +21 -120
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +13 -7
- package/dist/server/index.d.ts +13 -7
- package/dist/server/index.js +21 -110
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/next/SageDeskWidget-SJVE6QK3.js.map +0 -1
package/README.md
CHANGED
|
@@ -23,7 +23,9 @@ All embedding and semantic search runs entirely in the visitor's browser via Web
|
|
|
23
23
|
|
|
24
24
|
### LLM Mode
|
|
25
25
|
|
|
26
|
-
The widget
|
|
26
|
+
The widget embeds the visitor's query in the browser (same WASM model as local mode), then posts `{ query, queryVector }` to your own backend. Your backend does retrieval against the prebuilt index and calls your LLM provider for synthesis. The API key lives in your environment variables and never touches the browser. sagedesk provides ready-made server handlers for Next.js and Express - you own your entire stack.
|
|
27
|
+
|
|
28
|
+
Because the embedder stays in the browser, the server function carries no native ONNX runtime and no model weights. It deploys cleanly on Vercel, AWS Lambda, and any other serverless platform with no special configuration - the built `sagedesk/server` bundle is under 10 KB.
|
|
27
29
|
|
|
28
30
|
| | Local Mode | LLM Mode |
|
|
29
31
|
|---|---|---|
|
|
@@ -38,6 +40,15 @@ The widget posts visitor queries to your own backend. Your backend handles embed
|
|
|
38
40
|
|
|
39
41
|
---
|
|
40
42
|
|
|
43
|
+
## Framework Support
|
|
44
|
+
|
|
45
|
+
| | Supported |
|
|
46
|
+
|---|---|
|
|
47
|
+
| **Frontend** | Vanilla HTML/JS, React, Next.js (App Router) |
|
|
48
|
+
| **Backend** (LLM Mode) | Next.js API Routes, Express, any Node.js server, Vercel, AWS Lambda |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
41
52
|
## Installation
|
|
42
53
|
|
|
43
54
|
```bash
|
|
@@ -220,7 +231,7 @@ app.use('/api/sagedesk', createSageDeskMiddleware({
|
|
|
220
231
|
}));
|
|
221
232
|
```
|
|
222
233
|
|
|
223
|
-
> **Serverless
|
|
234
|
+
> **Serverless ready.** The handler does no embedding - it only reads the prebuilt index, runs an in-memory dot-product search, and proxies one HTTP call to your LLM provider. There is no `@huggingface/transformers` import, no `onnxruntime-node`, and no native binaries on the server, so no `next.config.js` workarounds, no `outputFileTracingIncludes`, and no Vercel function-size hacks are needed. Just import and mount the handler.
|
|
224
235
|
|
|
225
236
|
### Step 3 - Configure the widget
|
|
226
237
|
|
|
@@ -307,7 +318,6 @@ createSageDeskHandler({
|
|
|
307
318
|
| `provider` | `string` | yes | Provider name (e.g., `'openai'`, `'anthropic'`) or full API base URL (e.g., `'https://api.example.com/v1'`). |
|
|
308
319
|
| `apiKey` | `string` | yes | LLM API key (server-side only). |
|
|
309
320
|
| `model` | `string` | yes | Model name passed to the provider. |
|
|
310
|
-
| `embeddingModel` | `string` | no | Must match build-time model. Defaults to `all-MiniLM-L6-v2`. |
|
|
311
321
|
| `topK` | `number` | no | Number of chunks retrieved for context. Defaults to `5`. |
|
|
312
322
|
| `minScore` | `number` | no | Minimum similarity score for a chunk. Defaults to `0.42`. |
|
|
313
323
|
| `systemPrompt` | `string` | no | Override the default system prompt sent to the LLM. |
|
|
@@ -325,41 +335,10 @@ sagedesk includes built-in resilience for LLM mode. If the LLM provider fails-wh
|
|
|
325
335
|
|
|
326
336
|
2. **Automatic Fallback** - When an LLM request fails, the server returns the best matching knowledge chunks without synthesis. Visitors still get relevant, grounded information.
|
|
327
337
|
|
|
328
|
-
3. **Developer Transparency** - The browser console logs
|
|
329
|
-
- `"[sagedesk] Support service authentication failed. Showing relevant knowledge instead."` - Invalid or expired API key
|
|
330
|
-
- `"[sagedesk] Support service quota exhausted. Showing relevant knowledge instead."` - Rate limit hit
|
|
331
|
-
- `"[sagedesk] Support service took too long to respond. Showing relevant knowledge instead."` - Timeout
|
|
332
|
-
- `"[sagedesk] Support service error. Showing relevant knowledge instead."` - Generic API error
|
|
333
|
-
- `"[sagedesk] Support service returned invalid response. Showing relevant knowledge instead."` - Malformed response
|
|
338
|
+
3. **Developer Transparency** - The browser console logs a `[sagedesk]` warning for each failure class: auth error, quota exhausted, timeout, generic API error, and malformed response. Each message describes the cause and notes that the fallback was triggered.
|
|
334
339
|
|
|
335
340
|
4. **User Experience** - Visitors always see a fallback message (configured via `agent.fallback` or `agent.fallbackPool`) alongside relevant knowledge chunks. No errors are exposed to users.
|
|
336
341
|
|
|
337
|
-
### Configuring Timeout
|
|
338
|
-
|
|
339
|
-
Adjust the LLM request timeout based on your provider's typical response time:
|
|
340
|
-
|
|
341
|
-
```ts
|
|
342
|
-
// Next.js
|
|
343
|
-
export const POST = createSageDeskHandler({
|
|
344
|
-
indexPath: './public/support-index.json',
|
|
345
|
-
provider: 'deepseek',
|
|
346
|
-
apiKey: process.env.SAGEDESK_LLM_API_KEY!,
|
|
347
|
-
model: 'deepseek-chat',
|
|
348
|
-
llmTimeoutMs: 8000, // 8 seconds
|
|
349
|
-
});
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
```ts
|
|
353
|
-
// Express
|
|
354
|
-
app.use('/api/sagedesk', createSageDeskMiddleware({
|
|
355
|
-
indexPath: './public/support-index.json',
|
|
356
|
-
provider: 'openai',
|
|
357
|
-
apiKey: process.env.SAGEDESK_LLM_API_KEY!,
|
|
358
|
-
model: 'gpt-4o-mini',
|
|
359
|
-
llmTimeoutMs: 10000, // 10 seconds
|
|
360
|
-
}));
|
|
361
|
-
```
|
|
362
|
-
|
|
363
342
|
---
|
|
364
343
|
|
|
365
344
|
## Widget Configuration (`AgentConfig`)
|
|
@@ -370,7 +349,7 @@ Applies to both modes.
|
|
|
370
349
|
|---|:---:|:---:|---|
|
|
371
350
|
| `name` | `string` | **Required** | Display name in the chat header. |
|
|
372
351
|
| `theme` | `classic`, `light`, `dark` | `classic` | Visual style of the widget. |
|
|
373
|
-
| `model` | `string` | `all-MiniLM-L6-v2` | Embedding model. Must match build-time model.
|
|
352
|
+
| `model` | `string` | `all-MiniLM-L6-v2` | Embedding model loaded by the browser. Must match the build-time model. Used by both modes - local mode embeds & searches in-browser; LLM mode embeds in-browser and posts the vector to your handler. |
|
|
374
353
|
| `accentColor` | `string` | `#534AB7` | Hex color for primary UI elements. |
|
|
375
354
|
| `greeting` | `string` | - | Initial message shown to visitors. |
|
|
376
355
|
| `fallback` | `string` | - | Message shown when no answer is found. |
|
|
@@ -423,13 +402,13 @@ sagedesk defaults to `all-MiniLM-L6-v2` (~22MB), which offers an excellent balan
|
|
|
423
402
|
| `paraphrase-multilingual-MiniLM-L12-v2` | 384 | ~45 MB | 50+ languages. |
|
|
424
403
|
| `all-mpnet-base-v2` | 768 | ~85 MB | Maximum semantic quality. |
|
|
425
404
|
|
|
426
|
-
> **Note:** The `--model` flag in `npx sagedesk build` must match the `agent.model` prop
|
|
405
|
+
> **Note:** The `--model` flag in `npx sagedesk build` must match the `agent.model` prop on the widget. Both local mode and LLM mode embed in the browser using `agent.model`, and the resulting vectors must live in the same space as the index built by the CLI.
|
|
427
406
|
|
|
428
407
|
---
|
|
429
408
|
|
|
430
409
|
## Browser Support
|
|
431
410
|
|
|
432
|
-
Requires **WebAssembly** support
|
|
411
|
+
Requires **WebAssembly** support. Both local and LLM mode embed visitor queries in-browser, so the same WASM-capable browsers are required for both. WASM is supported by all modern browsers (Chrome 57+, Firefox 52+, Safari 11+, Edge 16+).
|
|
433
412
|
|
|
434
413
|
- Chrome 90+
|
|
435
414
|
- Firefox 89+
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
// src/react/SageDeskWidget.tsx
|
|
4
|
-
import {
|
|
4
|
+
import React, {
|
|
5
5
|
useState as useState2,
|
|
6
6
|
useRef as useRef2,
|
|
7
7
|
useEffect as useEffect2,
|
|
8
|
-
useCallback as useCallback2
|
|
8
|
+
useCallback as useCallback2,
|
|
9
|
+
useMemo as useMemo2
|
|
9
10
|
} from "react";
|
|
10
11
|
import { createPortal } from "react-dom";
|
|
11
12
|
|
|
@@ -265,6 +266,7 @@ function logFallbackWarning(reason) {
|
|
|
265
266
|
}
|
|
266
267
|
var initialState = {
|
|
267
268
|
messages: [],
|
|
269
|
+
userMessages: [],
|
|
268
270
|
isOpen: false,
|
|
269
271
|
isTyping: false,
|
|
270
272
|
engineStatus: "idle",
|
|
@@ -277,8 +279,11 @@ function reducer(state, action) {
|
|
|
277
279
|
return { ...state, isOpen: true };
|
|
278
280
|
case "CLOSE":
|
|
279
281
|
return { ...state, isOpen: false };
|
|
280
|
-
case "ADD_MESSAGE":
|
|
281
|
-
|
|
282
|
+
case "ADD_MESSAGE": {
|
|
283
|
+
const newMessages = [...state.messages, action.payload];
|
|
284
|
+
const newUserMessages = action.payload.role === "user" ? [...state.userMessages, action.payload] : state.userMessages;
|
|
285
|
+
return { ...state, messages: newMessages, userMessages: newUserMessages };
|
|
286
|
+
}
|
|
282
287
|
case "SET_TYPING":
|
|
283
288
|
return { ...state, isTyping: action.payload };
|
|
284
289
|
case "SET_ENGINE_STATUS":
|
|
@@ -301,6 +306,7 @@ function useSageDesk(config) {
|
|
|
301
306
|
const embedderRef = useRef(null);
|
|
302
307
|
const engineStartedRef = useRef(false);
|
|
303
308
|
const msgCounterRef = useRef(0);
|
|
309
|
+
const engineReadyCallbacksRef = useRef([]);
|
|
304
310
|
const [chips, setChips] = useState([]);
|
|
305
311
|
const makeId = () => `msg-${++msgCounterRef.current}`;
|
|
306
312
|
const addMessage = useCallback(
|
|
@@ -312,12 +318,27 @@ function useSageDesk(config) {
|
|
|
312
318
|
},
|
|
313
319
|
[]
|
|
314
320
|
);
|
|
321
|
+
const notifyEngineReady = useCallback(() => {
|
|
322
|
+
const callbacks = engineReadyCallbacksRef.current;
|
|
323
|
+
engineReadyCallbacksRef.current = [];
|
|
324
|
+
callbacks.forEach((cb) => cb());
|
|
325
|
+
}, []);
|
|
315
326
|
const startEngine = useCallback(async () => {
|
|
316
327
|
if (engineStartedRef.current) return;
|
|
317
328
|
engineStartedRef.current = true;
|
|
318
329
|
if (config.mode === "llm") {
|
|
319
330
|
setChips(config.agent.suggestedChips ?? []);
|
|
320
|
-
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "
|
|
331
|
+
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "loading-model" } });
|
|
332
|
+
try {
|
|
333
|
+
embedderRef.current = new EmbedderRuntime();
|
|
334
|
+
await embedderRef.current.load(config.agent.model);
|
|
335
|
+
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
336
|
+
notifyEngineReady();
|
|
337
|
+
} catch (err) {
|
|
338
|
+
console.warn("[sagedesk] WASM embedder failed to load - LLM mode will use fallback messages.", err);
|
|
339
|
+
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "error-model", error: String(err) } });
|
|
340
|
+
notifyEngineReady();
|
|
341
|
+
}
|
|
321
342
|
return;
|
|
322
343
|
}
|
|
323
344
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "loading-index" } });
|
|
@@ -329,6 +350,7 @@ function useSageDesk(config) {
|
|
|
329
350
|
type: "SET_ENGINE_STATUS",
|
|
330
351
|
payload: { status: "error-index", error: String(err) }
|
|
331
352
|
});
|
|
353
|
+
notifyEngineReady();
|
|
332
354
|
addMessage({
|
|
333
355
|
role: "bot",
|
|
334
356
|
text: "I'm having trouble loading right now. Please try again in a moment."
|
|
@@ -341,12 +363,14 @@ function useSageDesk(config) {
|
|
|
341
363
|
embedderRef.current = new EmbedderRuntime();
|
|
342
364
|
await embedderRef.current.load(config.agent.model);
|
|
343
365
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "ready" } });
|
|
366
|
+
notifyEngineReady();
|
|
344
367
|
} catch (err) {
|
|
345
368
|
console.warn("[sagedesk] WASM model failed to load, falling back to keyword search -", err);
|
|
346
369
|
embedderRef.current = new EmbedderRuntime();
|
|
347
370
|
dispatch({ type: "SET_ENGINE_STATUS", payload: { status: "degraded" } });
|
|
371
|
+
notifyEngineReady();
|
|
348
372
|
}
|
|
349
|
-
}, [config.mode, config.indexUrl, config.agent.suggestedChips, addMessage]);
|
|
373
|
+
}, [config.mode, config.indexUrl, config.agent.model, config.agent.suggestedChips, addMessage, notifyEngineReady]);
|
|
350
374
|
const greetingShownRef = useRef(false);
|
|
351
375
|
const open = useCallback(() => {
|
|
352
376
|
dispatch({ type: "OPEN" });
|
|
@@ -363,16 +387,12 @@ function useSageDesk(config) {
|
|
|
363
387
|
dispatch({ type: "CLOSE" });
|
|
364
388
|
}, []);
|
|
365
389
|
const waitForEngine = useCallback(() => {
|
|
390
|
+
const s = engineStatusRef.current;
|
|
391
|
+
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
392
|
+
return Promise.resolve();
|
|
393
|
+
}
|
|
366
394
|
return new Promise((resolve) => {
|
|
367
|
-
|
|
368
|
-
const s = engineStatusRef.current;
|
|
369
|
-
if (s === "ready" || s === "degraded" || s === "error-index" || s === "error-model") {
|
|
370
|
-
resolve();
|
|
371
|
-
} else {
|
|
372
|
-
setTimeout(check, 100);
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
check();
|
|
395
|
+
engineReadyCallbacksRef.current.push(resolve);
|
|
376
396
|
});
|
|
377
397
|
}, []);
|
|
378
398
|
const submit = useCallback(
|
|
@@ -396,12 +416,20 @@ function useSageDesk(config) {
|
|
|
396
416
|
console.warn('[sagedesk] LLM mode requires an "endpoint" prop.');
|
|
397
417
|
botText = getFallback(config.agent);
|
|
398
418
|
isFallback = true;
|
|
419
|
+
} else if (!embedderRef.current?.isReady) {
|
|
420
|
+
console.warn("[sagedesk] Embedder not ready - showing fallback.");
|
|
421
|
+
botText = getFallback(config.agent);
|
|
422
|
+
isFallback = true;
|
|
399
423
|
} else {
|
|
400
424
|
try {
|
|
425
|
+
const vector = await embedderRef.current.embed(trimmed);
|
|
401
426
|
const res = await fetch(config.endpoint, {
|
|
402
427
|
method: "POST",
|
|
403
428
|
headers: { "Content-Type": "application/json" },
|
|
404
|
-
body: JSON.stringify({
|
|
429
|
+
body: JSON.stringify({
|
|
430
|
+
query: trimmed,
|
|
431
|
+
queryVector: Array.from(vector)
|
|
432
|
+
})
|
|
405
433
|
});
|
|
406
434
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
407
435
|
const data = await res.json();
|
|
@@ -445,8 +473,8 @@ function useSageDesk(config) {
|
|
|
445
473
|
}
|
|
446
474
|
if (config.mode !== "llm") {
|
|
447
475
|
const elapsed = Date.now() - typingStart;
|
|
448
|
-
const delayBase = retrievalMode === "keyword" || isFallback ?
|
|
449
|
-
const minTypingMs = delayBase + Math.random() *
|
|
476
|
+
const delayBase = retrievalMode === "keyword" || isFallback ? 400 : 800;
|
|
477
|
+
const minTypingMs = delayBase + Math.random() * 400;
|
|
450
478
|
const remaining = minTypingMs - elapsed;
|
|
451
479
|
if (remaining > 0) await new Promise((r) => setTimeout(r, remaining));
|
|
452
480
|
}
|
|
@@ -464,11 +492,9 @@ function useSageDesk(config) {
|
|
|
464
492
|
return () => document.removeEventListener("keydown", handler);
|
|
465
493
|
}, [state.isOpen, close]);
|
|
466
494
|
const activeChips = useMemo(() => {
|
|
467
|
-
const askedTexts = new Set(
|
|
468
|
-
state.messages.filter((m) => m.role === "user").map((m) => m.text.toLowerCase().trim())
|
|
469
|
-
);
|
|
495
|
+
const askedTexts = new Set(state.userMessages.map((m) => m.text.toLowerCase().trim()));
|
|
470
496
|
return chips.filter((chip) => !askedTexts.has(chip.toLowerCase().trim()));
|
|
471
|
-
}, [chips, state.
|
|
497
|
+
}, [chips, state.userMessages]);
|
|
472
498
|
return { state, chips: activeChips, open, close, submit };
|
|
473
499
|
}
|
|
474
500
|
|
|
@@ -664,9 +690,9 @@ var PoweredBy = ({ dark = false }) => /* @__PURE__ */ jsxs("div", { style: {
|
|
|
664
690
|
}
|
|
665
691
|
)
|
|
666
692
|
] });
|
|
667
|
-
|
|
693
|
+
var ClassicMessageBubble = React.memo(function ClassicMessageBubble2({ msg, accent }) {
|
|
668
694
|
const isBot = msg.role === "bot";
|
|
669
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
695
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
670
696
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: isBot ? "flex-start" : "flex-end", gap: "4px" }, children: [
|
|
671
697
|
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" }),
|
|
672
698
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -691,7 +717,7 @@ function ClassicMessageBubble({ msg, accent }) {
|
|
|
691
717
|
fontFamily: "inherit"
|
|
692
718
|
}, children: "just now" })
|
|
693
719
|
] });
|
|
694
|
-
}
|
|
720
|
+
});
|
|
695
721
|
function ClassicTypingIndicator() {
|
|
696
722
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c8c8ce", display: "inline-block" };
|
|
697
723
|
return /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "4px" }, children: /* @__PURE__ */ jsxs("div", { style: {
|
|
@@ -709,9 +735,9 @@ function ClassicTypingIndicator() {
|
|
|
709
735
|
/* @__PURE__ */ jsx("span", { style: dot, className: "sd-r-dot-3" })
|
|
710
736
|
] }) });
|
|
711
737
|
}
|
|
712
|
-
|
|
738
|
+
var LightMessageBubble = React.memo(function LightMessageBubble2({ msg, accent, agentName }) {
|
|
713
739
|
const isBot = msg.role === "bot";
|
|
714
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
740
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
715
741
|
if (isBot) {
|
|
716
742
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
717
743
|
/* @__PURE__ */ jsx("div", { style: {
|
|
@@ -746,7 +772,7 @@ function LightMessageBubble({ msg, accent, agentName }) {
|
|
|
746
772
|
wordBreak: "break-word",
|
|
747
773
|
fontFamily: "inherit"
|
|
748
774
|
}, children: msg.text }) });
|
|
749
|
-
}
|
|
775
|
+
});
|
|
750
776
|
function LightTypingIndicator({ accent }) {
|
|
751
777
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "#c4c4be", display: "inline-block" };
|
|
752
778
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
@@ -774,9 +800,9 @@ function LightTypingIndicator({ accent }) {
|
|
|
774
800
|
] })
|
|
775
801
|
] });
|
|
776
802
|
}
|
|
777
|
-
|
|
803
|
+
var DarkMessageBubble = React.memo(function DarkMessageBubble2({ msg, accent }) {
|
|
778
804
|
const isBot = msg.role === "bot";
|
|
779
|
-
const renderedHtml = isBot ? parseMarkdown(msg.text) : msg.text;
|
|
805
|
+
const renderedHtml = useMemo2(() => isBot ? parseMarkdown(msg.text) : msg.text, [isBot, msg.text]);
|
|
780
806
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
781
807
|
maxWidth: "85%",
|
|
782
808
|
padding: "12px 14px",
|
|
@@ -794,7 +820,7 @@ function DarkMessageBubble({ msg, accent }) {
|
|
|
794
820
|
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" }),
|
|
795
821
|
isBot ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx("div", { style: { whiteSpace: "pre-wrap" }, children: msg.text })
|
|
796
822
|
] });
|
|
797
|
-
}
|
|
823
|
+
});
|
|
798
824
|
function DarkTypingIndicator() {
|
|
799
825
|
const dot = { width: 6, height: 6, borderRadius: "50%", background: "rgba(255,255,255,0.4)", display: "inline-block" };
|
|
800
826
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
@@ -813,7 +839,7 @@ function DarkTypingIndicator() {
|
|
|
813
839
|
/* @__PURE__ */ jsx("span", { style: dot, className: "sd-r-dot-3" })
|
|
814
840
|
] });
|
|
815
841
|
}
|
|
816
|
-
function
|
|
842
|
+
function ClassicTheme(p) {
|
|
817
843
|
const {
|
|
818
844
|
agent,
|
|
819
845
|
state,
|
|
@@ -1002,7 +1028,7 @@ function renderClassic(p) {
|
|
|
1002
1028
|
] })
|
|
1003
1029
|
] });
|
|
1004
1030
|
}
|
|
1005
|
-
function
|
|
1031
|
+
function LightTheme(p) {
|
|
1006
1032
|
const {
|
|
1007
1033
|
agent,
|
|
1008
1034
|
state,
|
|
@@ -1190,7 +1216,7 @@ function renderLight(p) {
|
|
|
1190
1216
|
] })
|
|
1191
1217
|
] });
|
|
1192
1218
|
}
|
|
1193
|
-
function
|
|
1219
|
+
function DarkTheme(p) {
|
|
1194
1220
|
const {
|
|
1195
1221
|
agent,
|
|
1196
1222
|
state,
|
|
@@ -1427,7 +1453,10 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1427
1453
|
'[sagedesk] Required prop "endpoint" is missing for llm mode. Provide your backend route, e.g. endpoint="/api/sagedesk".'
|
|
1428
1454
|
);
|
|
1429
1455
|
}
|
|
1430
|
-
const config =
|
|
1456
|
+
const config = useMemo2(
|
|
1457
|
+
() => ({ mode: resolvedMode, indexUrl, endpoint, agent, search: search2 }),
|
|
1458
|
+
[resolvedMode, indexUrl, endpoint, agent, search2]
|
|
1459
|
+
);
|
|
1431
1460
|
const { state, chips, open, close, submit } = useSageDesk(config);
|
|
1432
1461
|
const theme = agent.theme ?? "classic";
|
|
1433
1462
|
const accent = agent.accentColor ?? "#534AB7";
|
|
@@ -1506,10 +1535,10 @@ function SageDeskWidget({ mode, indexUrl, endpoint, agent, search: search2 }) {
|
|
|
1506
1535
|
open,
|
|
1507
1536
|
submit
|
|
1508
1537
|
};
|
|
1509
|
-
const content = theme === "dark" ?
|
|
1538
|
+
const content = theme === "dark" ? /* @__PURE__ */ jsx(DarkTheme, { ...props }) : theme === "light" ? /* @__PURE__ */ jsx(LightTheme, { ...props }) : /* @__PURE__ */ jsx(ClassicTheme, { ...props });
|
|
1510
1539
|
return createPortal(content, document.body);
|
|
1511
1540
|
}
|
|
1512
1541
|
export {
|
|
1513
1542
|
SageDeskWidget
|
|
1514
1543
|
};
|
|
1515
|
-
//# sourceMappingURL=SageDeskWidget-
|
|
1544
|
+
//# sourceMappingURL=SageDeskWidget-ZJJGXTTC.js.map
|