@burtson-labs/bandit-engine 2.0.158 → 2.0.160
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 -0
- package/dist/{aiProviderStore-ZQ5VVVKQ.mjs → aiProviderStore-BNZGM6QU.mjs} +2 -2
- package/dist/chat-4BOIV4VP.mjs +16 -0
- package/dist/chat-provider.js +3 -3
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +6 -6
- package/dist/{chunk-GWQRTUKF.mjs → chunk-B3HAQC6F.mjs} +2 -2
- package/dist/chunk-B3HAQC6F.mjs.map +1 -0
- package/dist/{chunk-7HC6ONWM.mjs → chunk-IABD4L6K.mjs} +43 -44
- package/dist/chunk-IABD4L6K.mjs.map +1 -0
- package/dist/{chunk-R45DM35B.mjs → chunk-LFQH6M6B.mjs} +3 -3
- package/dist/chunk-LFQH6M6B.mjs.map +1 -0
- package/dist/{chunk-IS2LWSBZ.mjs → chunk-LNGF2XAZ.mjs} +3 -3
- package/dist/chunk-LNGF2XAZ.mjs.map +1 -0
- package/dist/{chunk-GZDJNVAS.mjs → chunk-LTWMMHFT.mjs} +11 -9
- package/dist/chunk-LTWMMHFT.mjs.map +1 -0
- package/dist/{chunk-F5JS4W2K.mjs → chunk-MHF76C2F.mjs} +246 -127
- package/dist/chunk-MHF76C2F.mjs.map +1 -0
- package/dist/{chunk-B2TJZM4Z.mjs → chunk-P6SLB5RC.mjs} +3 -3
- package/dist/{chunk-ZW3YNAD7.mjs → chunk-PDQT564P.mjs} +5 -5
- package/dist/{chunk-ZW3YNAD7.mjs.map → chunk-PDQT564P.mjs.map} +1 -1
- package/dist/{chunk-VJVGSAKI.mjs → chunk-PXCIDXRP.mjs} +7 -7
- package/dist/{chunk-VJVGSAKI.mjs.map → chunk-PXCIDXRP.mjs.map} +1 -1
- package/dist/{chunk-2X3ZTDUW.mjs → chunk-TKSOJGHX.mjs} +5 -5
- package/dist/{chunk-ZOCXFQID.mjs → chunk-XTB6ZLUI.mjs} +2 -2
- package/dist/{chunk-ZOCXFQID.mjs.map → chunk-XTB6ZLUI.mjs.map} +1 -1
- package/dist/index.js +299 -164
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -11
- package/dist/management/management.js +292 -157
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +9 -9
- package/dist/modals/chat-modal/chat-modal.js +9 -7
- package/dist/modals/chat-modal/chat-modal.js.map +1 -1
- package/dist/modals/chat-modal/chat-modal.mjs +5 -5
- package/dist/{modelStore-KBUW3XAV.mjs → modelStore-NMCRL3FR.mjs} +2 -2
- package/package.json +6 -4
- package/dist/chat-HM563VOV.mjs +0 -16
- package/dist/chunk-7HC6ONWM.mjs.map +0 -1
- package/dist/chunk-F5JS4W2K.mjs.map +0 -1
- package/dist/chunk-GWQRTUKF.mjs.map +0 -1
- package/dist/chunk-GZDJNVAS.mjs.map +0 -1
- package/dist/chunk-IS2LWSBZ.mjs.map +0 -1
- package/dist/chunk-R45DM35B.mjs.map +0 -1
- /package/dist/{aiProviderStore-ZQ5VVVKQ.mjs.map → aiProviderStore-BNZGM6QU.mjs.map} +0 -0
- /package/dist/{chat-HM563VOV.mjs.map → chat-4BOIV4VP.mjs.map} +0 -0
- /package/dist/{chunk-B2TJZM4Z.mjs.map → chunk-P6SLB5RC.mjs.map} +0 -0
- /package/dist/{chunk-2X3ZTDUW.mjs.map → chunk-TKSOJGHX.mjs.map} +0 -0
- /package/dist/{modelStore-KBUW3XAV.mjs.map → modelStore-NMCRL3FR.mjs.map} +0 -0
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
StreamingMarkdown_default,
|
|
6
6
|
isNativeShell,
|
|
7
7
|
isStandalonePwa
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LFQH6M6B.mjs";
|
|
9
9
|
import {
|
|
10
10
|
useMCPToolsStore
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LNGF2XAZ.mjs";
|
|
12
12
|
import {
|
|
13
13
|
AddIcon,
|
|
14
14
|
ArrowDownwardIcon,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
useNotificationService,
|
|
39
39
|
useTTS,
|
|
40
40
|
useVoiceStore
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-LTWMMHFT.mjs";
|
|
42
42
|
import {
|
|
43
43
|
brandingService_default,
|
|
44
44
|
detectMessageMood,
|
|
@@ -61,19 +61,19 @@ import {
|
|
|
61
61
|
useMemoryStore,
|
|
62
62
|
useProjectStore,
|
|
63
63
|
useVectorStore
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-PDQT564P.mjs";
|
|
65
65
|
import {
|
|
66
66
|
indexedDBService_default,
|
|
67
67
|
useModelStore,
|
|
68
68
|
usePackageSettingsStore,
|
|
69
69
|
usePreferencesStore
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-XTB6ZLUI.mjs";
|
|
71
71
|
import {
|
|
72
|
-
authenticationService
|
|
72
|
+
authenticationService,
|
|
73
73
|
readPersistedToken,
|
|
74
74
|
useAIProviderStore,
|
|
75
75
|
useAuthenticationStore
|
|
76
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-B3HAQC6F.mjs";
|
|
77
77
|
import {
|
|
78
78
|
debugLogger
|
|
79
79
|
} from "./chunk-KCI46M23.mjs";
|
|
@@ -928,7 +928,7 @@ var useEngineStore = create((set, get) => ({
|
|
|
928
928
|
}
|
|
929
929
|
try {
|
|
930
930
|
const headers = { "Content-Type": "application/json" };
|
|
931
|
-
const token =
|
|
931
|
+
const token = authenticationService.getToken();
|
|
932
932
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
933
933
|
const res = await fetch(`${base}/models`, { headers });
|
|
934
934
|
const data = await res.json();
|
|
@@ -1217,7 +1217,7 @@ var STTClient = class {
|
|
|
1217
1217
|
filename,
|
|
1218
1218
|
url: `${gatewayUrl}/stt/transcribe`
|
|
1219
1219
|
});
|
|
1220
|
-
const token =
|
|
1220
|
+
const token = authenticationService.getToken();
|
|
1221
1221
|
const response = await fetch(`${gatewayUrl}/stt/transcribe`, {
|
|
1222
1222
|
method: "POST",
|
|
1223
1223
|
headers: {
|
|
@@ -1324,6 +1324,97 @@ var Transcriber = ({ onTranscriptionCompleted }) => {
|
|
|
1324
1324
|
};
|
|
1325
1325
|
var transcriber_default = Transcriber;
|
|
1326
1326
|
|
|
1327
|
+
// src/chat/composer-submission.ts
|
|
1328
|
+
var isPromiseLike = (value) => !!value && typeof value.then === "function";
|
|
1329
|
+
var awaitAcceptance = async (ack) => {
|
|
1330
|
+
if (ack === false) return false;
|
|
1331
|
+
if (!isPromiseLike(ack)) return true;
|
|
1332
|
+
try {
|
|
1333
|
+
return await ack !== false;
|
|
1334
|
+
} catch {
|
|
1335
|
+
return false;
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
var buildSubmission = (text, images, documents) => {
|
|
1339
|
+
const typed = text.trim();
|
|
1340
|
+
const base = typed || (images.length === 1 ? "[\u{1F4F7} You attached an image]" : images.length > 1 ? `[\u{1F4F7} You attached ${images.length} images]` : "");
|
|
1341
|
+
const fileSummary = documents.length > 0 ? `[\u{1F4CE} Attached ${documents.length} file${documents.length > 1 ? "s" : ""}: ${documents.map((d) => d.fileName).join(", ")}]` : "";
|
|
1342
|
+
const displayQuestion = [base || (fileSummary ? "[\u{1F4E4} You submitted content without text]" : ""), fileSummary].filter(Boolean).join("\n\n");
|
|
1343
|
+
const prompt = [text, ...documents.map((d) => d.block)].filter(Boolean).join("\n\n");
|
|
1344
|
+
return { prompt, images: [...images], displayQuestion };
|
|
1345
|
+
};
|
|
1346
|
+
var isImeComposing = (event) => event.nativeEvent?.isComposing === true || event.keyCode === 229;
|
|
1347
|
+
|
|
1348
|
+
// src/chat/document-import.ts
|
|
1349
|
+
var CODE_EXTENSIONS = [".js", ".ts", ".tsx", ".json", ".py", ".java", ".c", ".cpp", ".cs"];
|
|
1350
|
+
var TEXT_EXTENSIONS = [".md", ".txt", ...CODE_EXTENSIONS];
|
|
1351
|
+
var isCodeFileName = (name) => {
|
|
1352
|
+
const lower = name.toLowerCase();
|
|
1353
|
+
return CODE_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
1354
|
+
};
|
|
1355
|
+
var isPlainTextFile = (name, mimeType = "") => mimeType.startsWith("text/") || TEXT_EXTENSIONS.some((ext) => name.toLowerCase().endsWith(ext));
|
|
1356
|
+
var CONTROL_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g;
|
|
1357
|
+
var INVISIBLE_FORMATTING = /[\u202A-\u202E\u2066-\u2069\u200B\u2060\uFEFF]/g;
|
|
1358
|
+
var stripInvisible = (text) => text.normalize("NFC").replace(CONTROL_CHARS, "").replace(INVISIBLE_FORMATTING, "");
|
|
1359
|
+
var neutralizeRoleMarkers = (text) => text.replace(/<\s*\/?\s*script\b[^>]*>/gi, "").replace(/(^|\n)([ \t]*)\/?(system|assistant|user)\s*:/gi, "$1$2[removed-role]");
|
|
1360
|
+
var prepareDocumentText = (text, fileName) => {
|
|
1361
|
+
const visible = stripInvisible(text);
|
|
1362
|
+
return (isCodeFileName(fileName) ? visible : neutralizeRoleMarkers(visible)).trim();
|
|
1363
|
+
};
|
|
1364
|
+
var formatDocumentBlock = (fileName, text) => `\u{1F4C4} ${fileName}
|
|
1365
|
+
${prepareDocumentText(text, fileName)}`;
|
|
1366
|
+
var readText = (file) => typeof file.text === "function" ? file.text() : new Promise((resolve, reject) => {
|
|
1367
|
+
const reader = new FileReader();
|
|
1368
|
+
reader.onload = () => resolve(String(reader.result ?? ""));
|
|
1369
|
+
reader.onerror = () => reject(reader.error ?? new Error("It couldn't be read."));
|
|
1370
|
+
reader.readAsText(file);
|
|
1371
|
+
});
|
|
1372
|
+
var readPdfText = async (file, maxPages = 10) => {
|
|
1373
|
+
const pdfjsLib = await import("pdfjs-dist/legacy/build/pdf.mjs");
|
|
1374
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.burtson.ai/scripts/pdf.worker.js";
|
|
1375
|
+
const pdf = await pdfjsLib.getDocument({ data: await file.arrayBuffer() }).promise;
|
|
1376
|
+
const pages = await Promise.all(
|
|
1377
|
+
Array.from({ length: Math.min(pdf.numPages, maxPages) }, async (_, i) => {
|
|
1378
|
+
try {
|
|
1379
|
+
const page = await pdf.getPage(i + 1);
|
|
1380
|
+
const content = await page.getTextContent();
|
|
1381
|
+
return content.items.map((item) => typeof item?.str === "string" ? item.str : "").join(" ");
|
|
1382
|
+
} catch {
|
|
1383
|
+
return "";
|
|
1384
|
+
}
|
|
1385
|
+
})
|
|
1386
|
+
);
|
|
1387
|
+
return pages.join("\n\n");
|
|
1388
|
+
};
|
|
1389
|
+
var readDocument = async (file) => {
|
|
1390
|
+
const name = file.name.toLowerCase();
|
|
1391
|
+
try {
|
|
1392
|
+
let text;
|
|
1393
|
+
if (isPlainTextFile(name, file.type)) {
|
|
1394
|
+
text = await readText(file);
|
|
1395
|
+
} else if (name.endsWith(".docx")) {
|
|
1396
|
+
const mammoth = await import("mammoth");
|
|
1397
|
+
text = (await mammoth.extractRawText({ arrayBuffer: await file.arrayBuffer() })).value;
|
|
1398
|
+
} else if (name.endsWith(".pdf")) {
|
|
1399
|
+
text = await readPdfText(file);
|
|
1400
|
+
} else {
|
|
1401
|
+
return { ok: false, fileName: file.name, reason: "This file type can't be read yet." };
|
|
1402
|
+
}
|
|
1403
|
+
const block = formatDocumentBlock(file.name, text);
|
|
1404
|
+
if (block === `\u{1F4C4} ${file.name}
|
|
1405
|
+
`) {
|
|
1406
|
+
return { ok: false, fileName: file.name, reason: "No readable text was found in it." };
|
|
1407
|
+
}
|
|
1408
|
+
return { ok: true, fileName: file.name, block };
|
|
1409
|
+
} catch (error) {
|
|
1410
|
+
return {
|
|
1411
|
+
ok: false,
|
|
1412
|
+
fileName: file.name,
|
|
1413
|
+
reason: error instanceof Error && error.message ? error.message : "It couldn't be read."
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1327
1418
|
// src/chat/chat-input.tsx
|
|
1328
1419
|
import { useTheme as useTheme6, alpha as alpha3 } from "@mui/material/styles";
|
|
1329
1420
|
|
|
@@ -1524,102 +1615,60 @@ var ChatInput = (props) => {
|
|
|
1524
1615
|
const removeImage = (index) => {
|
|
1525
1616
|
setPastedImages((prev) => prev.filter((_, i) => i !== index));
|
|
1526
1617
|
};
|
|
1618
|
+
const latestDraftRef = useRef2({ text: inputValue, images: pastedImages, files: fileInputs });
|
|
1619
|
+
latestDraftRef.current = { text: inputValue, images: pastedImages, files: fileInputs };
|
|
1620
|
+
const submittingRef = useRef2(false);
|
|
1621
|
+
const [sendError, setSendError] = useState6(null);
|
|
1527
1622
|
const handleSubmit = async () => {
|
|
1528
|
-
if (
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
Array.from({ length: maxPages }, async (_, i) => {
|
|
1567
|
-
try {
|
|
1568
|
-
const page = await pdf.getPage(i + 1);
|
|
1569
|
-
const content = await page.getTextContent();
|
|
1570
|
-
return content.items.map((item) => {
|
|
1571
|
-
if (item && typeof item === "object" && "str" in item && typeof item.str === "string") {
|
|
1572
|
-
return item.str;
|
|
1573
|
-
}
|
|
1574
|
-
return "";
|
|
1575
|
-
}).join(" ");
|
|
1576
|
-
} catch (err) {
|
|
1577
|
-
debugLogger.error(`Failed to read page ${i + 1}`, { error: err });
|
|
1578
|
-
return "";
|
|
1579
|
-
}
|
|
1580
|
-
})
|
|
1581
|
-
);
|
|
1582
|
-
const joined = pages.join("\n\n");
|
|
1583
|
-
debugLogger.info("Extracted PDF content", { contentPreview: joined.slice(0, 500) });
|
|
1584
|
-
return `\u{1F4C4} ${file.name}
|
|
1585
|
-
${sanitize(
|
|
1586
|
-
escapePromptInjection(joined),
|
|
1587
|
-
file.name
|
|
1588
|
-
)}`;
|
|
1589
|
-
} catch (error) {
|
|
1590
|
-
debugLogger.error("PDF load failed", {
|
|
1591
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1592
|
-
fileName: file.name
|
|
1593
|
-
});
|
|
1594
|
-
return "";
|
|
1595
|
-
}
|
|
1623
|
+
if (submittingRef.current) return;
|
|
1624
|
+
if (inputValue.trim() === "" && pastedImages.length === 0 && fileInputs.length === 0) return;
|
|
1625
|
+
submittingRef.current = true;
|
|
1626
|
+
const draft = { text: inputValue, images: [...pastedImages], files: [...fileInputs] };
|
|
1627
|
+
try {
|
|
1628
|
+
const reads = await Promise.all(draft.files.map(readDocument));
|
|
1629
|
+
const failed = reads.filter((r) => !r.ok);
|
|
1630
|
+
if (failed.length > 0) {
|
|
1631
|
+
setSendError(
|
|
1632
|
+
failed.map((f) => `Couldn't attach ${f.fileName}: ${f.reason}`).join(" ")
|
|
1633
|
+
);
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
const documents = reads.filter((r) => r.ok);
|
|
1637
|
+
const submission = buildSubmission(draft.text, draft.images, documents);
|
|
1638
|
+
debugLogger.debug("Composer submission", {
|
|
1639
|
+
documents: documents.map((d) => d.fileName),
|
|
1640
|
+
promptLength: submission.prompt.length
|
|
1641
|
+
});
|
|
1642
|
+
setSendError(null);
|
|
1643
|
+
setInputValue("");
|
|
1644
|
+
setPastedImages([]);
|
|
1645
|
+
setFileInputs([]);
|
|
1646
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
1647
|
+
inputRef.current?.blur();
|
|
1648
|
+
const accepted = await awaitAcceptance(
|
|
1649
|
+
onSend(submission.prompt, submission.images, submission.displayQuestion)
|
|
1650
|
+
);
|
|
1651
|
+
if (!accepted) {
|
|
1652
|
+
const now = latestDraftRef.current;
|
|
1653
|
+
const untouched = now.text.trim() === "" && now.images.length === 0 && now.files.length === 0;
|
|
1654
|
+
if (untouched) {
|
|
1655
|
+
setInputValue(draft.text);
|
|
1656
|
+
setPastedImages(draft.images);
|
|
1657
|
+
setFileInputs(draft.files);
|
|
1658
|
+
setSendError("Your message wasn't sent. It's back in the box so you can try again.");
|
|
1659
|
+
} else {
|
|
1660
|
+
setSendError("Your last message wasn't sent.");
|
|
1596
1661
|
}
|
|
1597
|
-
return "";
|
|
1598
|
-
} catch {
|
|
1599
|
-
return "";
|
|
1600
1662
|
}
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
const fileContent = fileTexts.filter(Boolean).join("\n\n");
|
|
1605
|
-
const tempQuestionBase = inputValue.trim() || (tempImages.length === 1 ? "[\u{1F4F7} You attached an image]" : tempImages.length > 1 ? `[\u{1F4F7} You attached ${tempImages.length} images]` : "");
|
|
1606
|
-
const fileDisplaySummary = fileInputs.length > 0 ? `[\u{1F4CE} Attached ${fileInputs.length} file${fileInputs.length > 1 ? "s" : ""}: ${fileInputs.map((f) => f.name).join(", ")}]` : "";
|
|
1607
|
-
const displayQuestion = [
|
|
1608
|
-
tempQuestionBase || (fileDisplaySummary ? "[\u{1F4E4} You submitted content without text]" : ""),
|
|
1609
|
-
fileDisplaySummary
|
|
1610
|
-
].filter(Boolean).join("\n\n");
|
|
1611
|
-
const fullPrompt = [inputValue, fileContent].filter(Boolean).join("\n\n");
|
|
1612
|
-
setInputValue("");
|
|
1613
|
-
setPastedImages([]);
|
|
1614
|
-
setFileInputs([]);
|
|
1615
|
-
onSend(fullPrompt, tempImages, displayQuestion);
|
|
1616
|
-
inputRef.current?.blur();
|
|
1617
|
-
fileInputRef.current.value = "";
|
|
1663
|
+
} finally {
|
|
1664
|
+
submittingRef.current = false;
|
|
1665
|
+
}
|
|
1618
1666
|
};
|
|
1619
1667
|
const handleKeyPress = (e) => {
|
|
1668
|
+
if (isImeComposing(e)) return;
|
|
1620
1669
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
1621
1670
|
e.preventDefault();
|
|
1622
|
-
handleSubmit();
|
|
1671
|
+
void handleSubmit();
|
|
1623
1672
|
}
|
|
1624
1673
|
};
|
|
1625
1674
|
const handleTranscriptionCompleted = (transcribed) => {
|
|
@@ -1737,6 +1786,15 @@ ${sanitize(
|
|
|
1737
1786
|
gap: isMobile ? compactMobile ? 0.75 : 1 : 0.5
|
|
1738
1787
|
},
|
|
1739
1788
|
children: [
|
|
1789
|
+
sendError && /* @__PURE__ */ jsx9(
|
|
1790
|
+
Typography3,
|
|
1791
|
+
{
|
|
1792
|
+
role: "alert",
|
|
1793
|
+
variant: "caption",
|
|
1794
|
+
sx: { color: theme.palette.error.main, px: 0.5, pt: isMobile ? 0 : 0.5 },
|
|
1795
|
+
children: sendError
|
|
1796
|
+
}
|
|
1797
|
+
),
|
|
1740
1798
|
/* @__PURE__ */ jsxs6(
|
|
1741
1799
|
Box6,
|
|
1742
1800
|
{
|
|
@@ -1782,7 +1840,10 @@ ${sanitize(
|
|
|
1782
1840
|
IconButton5,
|
|
1783
1841
|
{
|
|
1784
1842
|
size: "small",
|
|
1785
|
-
onClick: () =>
|
|
1843
|
+
onClick: () => {
|
|
1844
|
+
setSendError(null);
|
|
1845
|
+
setFileInputs((prev) => prev.filter((_, i) => i !== idx));
|
|
1846
|
+
},
|
|
1786
1847
|
sx: { ml: 0.5, color: theme.palette.mode === "dark" ? "#aaa" : "#444" },
|
|
1787
1848
|
children: /* @__PURE__ */ jsx9(CloseIcon, { sx: { fontSize: 14 } })
|
|
1788
1849
|
}
|
|
@@ -2760,7 +2821,7 @@ function syncTelemetry() {
|
|
|
2760
2821
|
const settings = usePackageSettingsStore.getState().settings;
|
|
2761
2822
|
const cfg = resolveTelemetryConfig({
|
|
2762
2823
|
telemetry: settings?.telemetry,
|
|
2763
|
-
banditApiKey:
|
|
2824
|
+
banditApiKey: authenticationService.getToken() ?? void 0
|
|
2764
2825
|
});
|
|
2765
2826
|
active = cfg ? new TelemetryExporter(cfg) : null;
|
|
2766
2827
|
} catch {
|
|
@@ -3369,7 +3430,7 @@ var executeMCPTool = async (toolCall) => {
|
|
|
3369
3430
|
}
|
|
3370
3431
|
if (tool.mcpServerId) {
|
|
3371
3432
|
const base2 = settings.gatewayApiUrl.replace(/\/$/, "");
|
|
3372
|
-
const token2 =
|
|
3433
|
+
const token2 = authenticationService.getToken();
|
|
3373
3434
|
const controller2 = new AbortController();
|
|
3374
3435
|
const timeoutId2 = setTimeout(() => controller2.abort(), 3e4);
|
|
3375
3436
|
try {
|
|
@@ -3416,7 +3477,7 @@ var executeMCPTool = async (toolCall) => {
|
|
|
3416
3477
|
"Content-Type": "application/json"
|
|
3417
3478
|
}
|
|
3418
3479
|
};
|
|
3419
|
-
const token =
|
|
3480
|
+
const token = authenticationService.getToken();
|
|
3420
3481
|
if (token) {
|
|
3421
3482
|
requestOptions.headers = {
|
|
3422
3483
|
...requestOptions.headers,
|
|
@@ -3785,8 +3846,11 @@ var useAIProvider = ({
|
|
|
3785
3846
|
history,
|
|
3786
3847
|
addHistory,
|
|
3787
3848
|
inputRef,
|
|
3788
|
-
onError
|
|
3849
|
+
onError,
|
|
3850
|
+
onTurnOutcome
|
|
3789
3851
|
}) => {
|
|
3852
|
+
const onTurnOutcomeRef = useRef4(onTurnOutcome);
|
|
3853
|
+
onTurnOutcomeRef.current = onTurnOutcome;
|
|
3790
3854
|
const currentSubRef = useRef4(null);
|
|
3791
3855
|
const lastPartialRef = useRef4({
|
|
3792
3856
|
text: "",
|
|
@@ -3832,10 +3896,14 @@ var useAIProvider = ({
|
|
|
3832
3896
|
};
|
|
3833
3897
|
const runAIProvider = useCallback(
|
|
3834
3898
|
async (systemPrompt, question, images) => {
|
|
3899
|
+
let turnHadOutput = false;
|
|
3900
|
+
const reportOutcome = (outcome) => onTurnOutcomeRef.current?.(outcome);
|
|
3835
3901
|
if (!provider) {
|
|
3836
3902
|
debugLogger.error("No AI provider configured");
|
|
3837
3903
|
overrideComponentStatus("Error");
|
|
3838
|
-
|
|
3904
|
+
const error = new Error("No AI provider configured");
|
|
3905
|
+
if (onError) onError(error);
|
|
3906
|
+
reportOutcome({ kind: "failed", hadOutput: false, error });
|
|
3839
3907
|
return;
|
|
3840
3908
|
}
|
|
3841
3909
|
const userPreferences = preferences;
|
|
@@ -3989,7 +4057,7 @@ Use this information to personalize your responses whenever relevant.` : "";
|
|
|
3989
4057
|
s3Url: resolvedId,
|
|
3990
4058
|
isUserContent: result.isUserContent,
|
|
3991
4059
|
isTeamContent: result.isTeamContent,
|
|
3992
|
-
contentSource: result.contentSource,
|
|
4060
|
+
contentSource: result.contentSource === "user" || result.contentSource === "team" ? result.contentSource : void 0,
|
|
3993
4061
|
originalFileName: result.originalFileName || result.filename || result.name,
|
|
3994
4062
|
// Preserve original data for downstream checks (e.g. vector modal detection)
|
|
3995
4063
|
_vectorResult: result
|
|
@@ -4344,6 +4412,10 @@ ${protocol}`;
|
|
|
4344
4412
|
const sub = stream.subscribe({
|
|
4345
4413
|
next: (data) => {
|
|
4346
4414
|
if (!data?.message?.content && !data?.message?.tool_calls) return;
|
|
4415
|
+
if (!turnHadOutput) {
|
|
4416
|
+
turnHadOutput = true;
|
|
4417
|
+
reportOutcome({ kind: "output" });
|
|
4418
|
+
}
|
|
4347
4419
|
if (Array.isArray(data.message.tool_calls) && data.message.tool_calls.length > 0) {
|
|
4348
4420
|
nativeToolCalls.push(...data.message.tool_calls);
|
|
4349
4421
|
sawToolBlock = true;
|
|
@@ -4378,13 +4450,14 @@ ${protocol}`;
|
|
|
4378
4450
|
},
|
|
4379
4451
|
error: (err) => {
|
|
4380
4452
|
debugLogger.error("Stream error:", err);
|
|
4453
|
+
reportOutcome({ kind: "failed", hadOutput: turnHadOutput, error: err });
|
|
4381
4454
|
stopWorking();
|
|
4382
4455
|
overrideComponentStatus("Idle");
|
|
4383
4456
|
setIsSubmitting(false);
|
|
4384
4457
|
setIsStreaming(false);
|
|
4385
4458
|
if (/lifetime validation|token.*(expired|invalid)|unauthorized|\b401\b/i.test(err.message || "")) {
|
|
4386
|
-
const { replaceLastAnswer:
|
|
4387
|
-
|
|
4459
|
+
const { replaceLastAnswer: replaceLastAnswer3 } = useConversationStore.getState();
|
|
4460
|
+
replaceLastAnswer3(
|
|
4388
4461
|
"_Your session ended \u2014 sign back in to continue._",
|
|
4389
4462
|
lastPartialRef.current.images,
|
|
4390
4463
|
false,
|
|
@@ -4411,8 +4484,8 @@ ${protocol}`;
|
|
|
4411
4484
|
scope: rateLimit.scope,
|
|
4412
4485
|
frontier: rateLimit.frontier
|
|
4413
4486
|
});
|
|
4414
|
-
const { replaceLastAnswer:
|
|
4415
|
-
|
|
4487
|
+
const { replaceLastAnswer: replaceLastAnswer3 } = useConversationStore.getState();
|
|
4488
|
+
replaceLastAnswer3(
|
|
4416
4489
|
rateLimit.scope === "weekly" ? "_You've reached your weekly limit. Upgrade to keep chatting._" : "_You've hit your session limit. It resets soon \u2014 or upgrade for higher limits._",
|
|
4417
4490
|
lastPartialRef.current.images,
|
|
4418
4491
|
false,
|
|
@@ -4433,10 +4506,16 @@ ${protocol}`;
|
|
|
4433
4506
|
if (partial && !partial.trim().endsWith("\u2026") && !partial.trim().endsWith("...")) {
|
|
4434
4507
|
partial = partial.trimEnd() + " \u2026";
|
|
4435
4508
|
}
|
|
4509
|
+
const { replaceLastAnswer: replaceLastAnswer2 } = useConversationStore.getState();
|
|
4436
4510
|
if (partial) {
|
|
4437
|
-
const { replaceLastAnswer: replaceLastAnswer2 } = useConversationStore.getState();
|
|
4438
4511
|
replaceLastAnswer2(partial, lastPartialRef.current.images, false, lastPartialRef.current.usedDocs, true);
|
|
4439
4512
|
setResponse(partial);
|
|
4513
|
+
} else {
|
|
4514
|
+
const { conversations: convs, currentId: convId } = useConversationStore.getState();
|
|
4515
|
+
const last = convs.find((c) => c.id === convId)?.history.at(-1);
|
|
4516
|
+
if (last?.answer === "...") {
|
|
4517
|
+
replaceLastAnswer2("_No response came back. Try sending again._", lastPartialRef.current.images, false, lastPartialRef.current.usedDocs, true);
|
|
4518
|
+
}
|
|
4440
4519
|
}
|
|
4441
4520
|
setStreamBuffer("");
|
|
4442
4521
|
setIsThinking?.(false);
|
|
@@ -4448,6 +4527,7 @@ ${protocol}`;
|
|
|
4448
4527
|
}
|
|
4449
4528
|
},
|
|
4450
4529
|
complete: async () => {
|
|
4530
|
+
reportOutcome({ kind: "completed" });
|
|
4451
4531
|
try {
|
|
4452
4532
|
setIsThinking?.(false);
|
|
4453
4533
|
telemetryEvent("tool_loop:llm_response", { responseLength: fullMessage.length });
|
|
@@ -4714,7 +4794,7 @@ _This link is temporary and expires in about ${mins} minutes._`;
|
|
|
4714
4794
|
}
|
|
4715
4795
|
} else {
|
|
4716
4796
|
const data = result.data ?? {};
|
|
4717
|
-
const informative = [data.message, data.details, data.error, result.error].map((value) => typeof value === "string" ? value.trim() :
|
|
4797
|
+
const informative = [data.message, data.details, data.error, result.error].map((value) => typeof value === "string" ? value.trim() : "").filter((value) => value.length > 0 && value.toLowerCase() !== "n/a");
|
|
4718
4798
|
resultText = informative.length ? informative.join(" \u2014 ") : `I couldn't complete that request: ${result.error || "Unknown error"}.`;
|
|
4719
4799
|
}
|
|
4720
4800
|
enhancedMessage = enhancedMessage.replace(placeholderToken, resultText);
|
|
@@ -5061,6 +5141,7 @@ ${inlineImageBlocks.join("\n\n")}` : "");
|
|
|
5061
5141
|
} catch {
|
|
5062
5142
|
}
|
|
5063
5143
|
currentSubRef.current = null;
|
|
5144
|
+
onTurnOutcomeRef.current?.({ kind: "cancelled" });
|
|
5064
5145
|
let partial = lastPartialRef.current.text;
|
|
5065
5146
|
if (partial && !partial.trim().endsWith("\u2026") && !partial.trim().endsWith("...")) {
|
|
5066
5147
|
partial = partial.trimEnd() + " \u2026";
|
|
@@ -5267,7 +5348,7 @@ var useNetworkStatus = () => {
|
|
|
5267
5348
|
if (connection) {
|
|
5268
5349
|
const updateConnectionInfo = () => {
|
|
5269
5350
|
const slowConnections = ["slow-2g", "2g"];
|
|
5270
|
-
const isSlowConnection = slowConnections.includes(connection.effectiveType);
|
|
5351
|
+
const isSlowConnection = slowConnections.includes(connection.effectiveType ?? "");
|
|
5271
5352
|
setNetworkStatus((prev) => ({
|
|
5272
5353
|
...prev,
|
|
5273
5354
|
isSlowConnection,
|
|
@@ -7746,7 +7827,7 @@ var ConversationDrawer = ({ open, onClose }) => {
|
|
|
7746
7827
|
title: "Sign out",
|
|
7747
7828
|
onClick: (event) => {
|
|
7748
7829
|
event.stopPropagation();
|
|
7749
|
-
|
|
7830
|
+
authenticationService.clearToken();
|
|
7750
7831
|
window.location.href = "/login";
|
|
7751
7832
|
},
|
|
7752
7833
|
sx: {
|
|
@@ -8873,7 +8954,7 @@ var EnhancedMobileConversationsModal = ({
|
|
|
8873
8954
|
title: "Sign out",
|
|
8874
8955
|
onClick: (event) => {
|
|
8875
8956
|
event.stopPropagation();
|
|
8876
|
-
|
|
8957
|
+
authenticationService.clearToken();
|
|
8877
8958
|
window.location.href = "/login";
|
|
8878
8959
|
},
|
|
8879
8960
|
sx: {
|
|
@@ -9649,7 +9730,8 @@ var QuerySuggestionPicker = ({
|
|
|
9649
9730
|
}
|
|
9650
9731
|
},
|
|
9651
9732
|
onClick: () => {
|
|
9652
|
-
onSend(prompt, [])
|
|
9733
|
+
void Promise.resolve(onSend(prompt, [])).catch(() => {
|
|
9734
|
+
});
|
|
9653
9735
|
setHasSentPrompt(true);
|
|
9654
9736
|
},
|
|
9655
9737
|
children: /* @__PURE__ */ jsx19(
|
|
@@ -9703,7 +9785,7 @@ var UnderReview = () => {
|
|
|
9703
9785
|
const theme = useTheme17();
|
|
9704
9786
|
const navigate = useNavigate4();
|
|
9705
9787
|
const handleResetSession = () => {
|
|
9706
|
-
|
|
9788
|
+
authenticationService.clearToken();
|
|
9707
9789
|
navigate("/login");
|
|
9708
9790
|
};
|
|
9709
9791
|
return /* @__PURE__ */ jsxs16(
|
|
@@ -10304,8 +10386,8 @@ var ChatContent = () => {
|
|
|
10304
10386
|
const notificationService = useNotificationService();
|
|
10305
10387
|
const [selectedTheme, setSelectedTheme] = useState19(null);
|
|
10306
10388
|
const [themeLoading, setThemeLoading] = useState19(true);
|
|
10307
|
-
const token =
|
|
10308
|
-
const claims = token ?
|
|
10389
|
+
const token = authenticationService.getToken();
|
|
10390
|
+
const claims = token ? authenticationService.parseJwtClaims(token) : null;
|
|
10309
10391
|
const baseTheme = themeMap_default[selectedTheme ?? "bandit-dark"] || banditDarkTheme;
|
|
10310
10392
|
const banditTheme = useMemo4(() => {
|
|
10311
10393
|
return createTheme(baseTheme, {
|
|
@@ -10378,7 +10460,7 @@ var ChatContent = () => {
|
|
|
10378
10460
|
} = useTTS();
|
|
10379
10461
|
useEffect17(() => {
|
|
10380
10462
|
const timer = setTimeout(() => {
|
|
10381
|
-
const isAuthenticated =
|
|
10463
|
+
const isAuthenticated = authenticationService.isAuthenticated();
|
|
10382
10464
|
if (!initialized || availableVoices.length === 0) {
|
|
10383
10465
|
if (token && isAuthenticated) {
|
|
10384
10466
|
debugLogger.debug("Chat: Voices not initialized or unavailable, attempting to load from API");
|
|
@@ -10391,7 +10473,7 @@ var ChatContent = () => {
|
|
|
10391
10473
|
return () => clearTimeout(timer);
|
|
10392
10474
|
}, [initialized, availableVoices.length, loadVoicesFromAPI, token]);
|
|
10393
10475
|
useEffect17(() => {
|
|
10394
|
-
const isAuthenticated =
|
|
10476
|
+
const isAuthenticated = authenticationService.isAuthenticated();
|
|
10395
10477
|
if (packageSettings?.gatewayApiUrl && availableVoices.length === 0 && !initialized) {
|
|
10396
10478
|
if (token && isAuthenticated) {
|
|
10397
10479
|
debugLogger.debug("Chat: Gateway URL available and no voices loaded, attempting to load from API");
|
|
@@ -11006,7 +11088,16 @@ var ChatContent = () => {
|
|
|
11006
11088
|
if (rafId) cancelAnimationFrame(rafId);
|
|
11007
11089
|
};
|
|
11008
11090
|
}, [_hasHydrated, chatContainerEl, getScrollState, history.length]);
|
|
11091
|
+
const sendAckRef = useRef16(null);
|
|
11092
|
+
const settleSendAck = useCallback6((outcome) => {
|
|
11093
|
+
const ack = sendAckRef.current;
|
|
11094
|
+
if (!ack) return;
|
|
11095
|
+
sendAckRef.current = null;
|
|
11096
|
+
if (outcome.kind === "failed" && !outcome.hadOutput) ack.reject(outcome.error);
|
|
11097
|
+
else ack.resolve();
|
|
11098
|
+
}, []);
|
|
11009
11099
|
const aiProvider = useAIProvider({
|
|
11100
|
+
onTurnOutcome: settleSendAck,
|
|
11010
11101
|
overrideComponentStatus: setComponentStatus,
|
|
11011
11102
|
setIsSubmitting,
|
|
11012
11103
|
setIsStreaming,
|
|
@@ -11057,6 +11148,26 @@ var ChatContent = () => {
|
|
|
11057
11148
|
}, [ttsStop, isStreaming, handleStop]);
|
|
11058
11149
|
const handleSend = useCallback6(
|
|
11059
11150
|
(question, images, displayQuestion) => {
|
|
11151
|
+
sendAckRef.current?.resolve();
|
|
11152
|
+
const acknowledged = new Promise((resolve, reject) => {
|
|
11153
|
+
sendAckRef.current = { resolve, reject };
|
|
11154
|
+
});
|
|
11155
|
+
const runProvider = (systemPrompt2, providerImages2) => {
|
|
11156
|
+
aiProvider(systemPrompt2, question, providerImages2).catch((error) => {
|
|
11157
|
+
debugLogger.error("AI provider failed before streaming", {
|
|
11158
|
+
error: error instanceof Error ? error.message : String(error)
|
|
11159
|
+
});
|
|
11160
|
+
setIsStreaming(false);
|
|
11161
|
+
setResponseStarted(false);
|
|
11162
|
+
setIsSubmitting(false);
|
|
11163
|
+
setPendingMessage(null);
|
|
11164
|
+
const { conversations: convs, currentId: convId, replaceLastAnswer } = useConversationStore.getState();
|
|
11165
|
+
if (convs.find((c) => c.id === convId)?.history.at(-1)?.answer === "...") {
|
|
11166
|
+
replaceLastAnswer("_No response came back. Try sending again._", void 0, false, void 0, true);
|
|
11167
|
+
}
|
|
11168
|
+
settleSendAck({ kind: "failed", hadOutput: false, error });
|
|
11169
|
+
});
|
|
11170
|
+
};
|
|
11060
11171
|
const requestStartTime = trackRequestStart();
|
|
11061
11172
|
const questionForDisplay = displayQuestion || question;
|
|
11062
11173
|
const pendingImages = images.length > 0 ? [...images] : void 0;
|
|
@@ -11095,10 +11206,15 @@ var ChatContent = () => {
|
|
|
11095
11206
|
rawQuestion: question
|
|
11096
11207
|
});
|
|
11097
11208
|
const providerImages2 = pendingImages ? [...pendingImages] : [];
|
|
11098
|
-
|
|
11209
|
+
runProvider(systemPrompt, providerImages2);
|
|
11099
11210
|
}, 0);
|
|
11211
|
+
}).catch((error) => {
|
|
11212
|
+
debugLogger.error("Starting a new conversation failed", {
|
|
11213
|
+
error: error instanceof Error ? error.message : String(error)
|
|
11214
|
+
});
|
|
11215
|
+
settleSendAck({ kind: "failed", hadOutput: false, error });
|
|
11100
11216
|
});
|
|
11101
|
-
return;
|
|
11217
|
+
return acknowledged;
|
|
11102
11218
|
}
|
|
11103
11219
|
if (existing.name === "New Conversation") {
|
|
11104
11220
|
generateName(question).then((newName) => {
|
|
@@ -11146,10 +11262,12 @@ var ChatContent = () => {
|
|
|
11146
11262
|
}
|
|
11147
11263
|
setResponse("");
|
|
11148
11264
|
const providerImages = pendingImages ? [...pendingImages] : [];
|
|
11149
|
-
|
|
11265
|
+
runProvider(systemPrompt, providerImages);
|
|
11266
|
+
return acknowledged;
|
|
11150
11267
|
},
|
|
11151
11268
|
[
|
|
11152
11269
|
aiProvider,
|
|
11270
|
+
settleSendAck,
|
|
11153
11271
|
chatContainerRef,
|
|
11154
11272
|
generateName,
|
|
11155
11273
|
getScrollState,
|
|
@@ -11173,7 +11291,8 @@ var ChatContent = () => {
|
|
|
11173
11291
|
}
|
|
11174
11292
|
setInputValue("");
|
|
11175
11293
|
setPastedImages([]);
|
|
11176
|
-
handleSend(cleaned, [], cleaned)
|
|
11294
|
+
handleSend(cleaned, [], cleaned).catch(() => {
|
|
11295
|
+
});
|
|
11177
11296
|
},
|
|
11178
11297
|
[handleSend, setInputValue, setPastedImages]
|
|
11179
11298
|
);
|
|
@@ -11751,12 +11870,12 @@ var Chat = () => {
|
|
|
11751
11870
|
ossConfigured,
|
|
11752
11871
|
isOSSMode: isOSSMode(),
|
|
11753
11872
|
tier: featureFlag.getEvaluation()?.tier,
|
|
11754
|
-
hasToken:
|
|
11873
|
+
hasToken: authenticationService.isAuthenticated(),
|
|
11755
11874
|
playgroundBypassAuth,
|
|
11756
11875
|
isPlaygroundRoute,
|
|
11757
11876
|
bypassAuth
|
|
11758
11877
|
});
|
|
11759
|
-
if (!allowUnauthenticated && !bypassAuth && !
|
|
11878
|
+
if (!allowUnauthenticated && !bypassAuth && !authenticationService.isAuthenticated()) {
|
|
11760
11879
|
debugLogger.debug("User is not authenticated, redirecting to login");
|
|
11761
11880
|
return /* @__PURE__ */ jsx23(Navigate, { to: "/login", replace: true });
|
|
11762
11881
|
}
|
|
@@ -11767,4 +11886,4 @@ var chat_default = Chat;
|
|
|
11767
11886
|
export {
|
|
11768
11887
|
chat_default
|
|
11769
11888
|
};
|
|
11770
|
-
//# sourceMappingURL=chunk-
|
|
11889
|
+
//# sourceMappingURL=chunk-MHF76C2F.mjs.map
|