@burtson-labs/bandit-engine 2.0.39 → 2.0.41
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 +14 -11
- package/dist/{aiProviderStore-XN7GCBHJ.mjs → aiProviderStore-UQI33C5E.mjs} +2 -2
- package/dist/{chat-5QJNWB7I.mjs → chat-T5ANWWYQ.mjs} +5 -5
- package/dist/chat-provider.js +571 -122
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +4 -4
- package/dist/{chunk-3A2527TE.mjs → chunk-22EY3ZDC.mjs} +3 -3
- package/dist/{chunk-ECRNIAG6.mjs → chunk-3E57HLDV.mjs} +4 -4
- package/dist/{chunk-QU5S5QQP.mjs → chunk-54ZQ3FSN.mjs} +481 -77
- package/dist/chunk-54ZQ3FSN.mjs.map +1 -0
- package/dist/{chunk-JRCDANLN.mjs → chunk-A6OBEF72.mjs} +75 -12
- package/dist/{chunk-JRCDANLN.mjs.map → chunk-A6OBEF72.mjs.map} +1 -1
- package/dist/{chunk-CDQYBO3Q.mjs → chunk-CX3INLYJ.mjs} +27 -5
- package/dist/chunk-CX3INLYJ.mjs.map +1 -0
- package/dist/{chunk-QYH2T4L5.mjs → chunk-LYWVYBKU.mjs} +3 -3
- package/dist/{chunk-WO5KFNNW.mjs → chunk-QFNEHSY4.mjs} +62 -24
- package/dist/chunk-QFNEHSY4.mjs.map +1 -0
- package/dist/{chunk-EOKIE5HZ.mjs → chunk-WPWWWUD7.mjs} +51 -46
- package/dist/chunk-WPWWWUD7.mjs.map +1 -0
- package/dist/{cli/cli.js → cli.js} +423 -10
- package/dist/cli.js.map +1 -0
- package/dist/{gateway-B0LJ3-jT.d.ts → gateway-5yt_3QDP.d.mts} +4 -4
- package/dist/{gateway-B0LJ3-jT.d.mts → gateway-5yt_3QDP.d.ts} +4 -4
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +756 -206
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/management/management.js +754 -204
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +6 -6
- package/dist/modals/chat-modal/chat-modal.js +532 -88
- package/dist/modals/chat-modal/chat-modal.js.map +1 -1
- package/dist/modals/chat-modal/chat-modal.mjs +4 -4
- package/dist/public-types.d.mts +1 -1
- package/dist/public-types.d.ts +1 -1
- package/docs/01_quickstart.md +10 -4
- package/docs/02_gateway_api.md +19 -3
- package/docs/03_provider_integration.md +5 -4
- package/docs/api_reference/media/02_gateway_api.md +19 -3
- package/docs/api_reference/media/README.md +3 -1
- package/package.json +1 -1
- package/dist/chunk-CDQYBO3Q.mjs.map +0 -1
- package/dist/chunk-EOKIE5HZ.mjs.map +0 -1
- package/dist/chunk-QU5S5QQP.mjs.map +0 -1
- package/dist/chunk-WO5KFNNW.mjs.map +0 -1
- package/dist/cli/cli.js.map +0 -1
- /package/dist/{aiProviderStore-XN7GCBHJ.mjs.map → aiProviderStore-UQI33C5E.mjs.map} +0 -0
- /package/dist/{chat-5QJNWB7I.mjs.map → chat-T5ANWWYQ.mjs.map} +0 -0
- /package/dist/{chunk-3A2527TE.mjs.map → chunk-22EY3ZDC.mjs.map} +0 -0
- /package/dist/{chunk-ECRNIAG6.mjs.map → chunk-3E57HLDV.mjs.map} +0 -0
- /package/dist/{chunk-QYH2T4L5.mjs.map → chunk-LYWVYBKU.mjs.map} +0 -0
|
@@ -12,11 +12,11 @@ var __export = (target, all) => {
|
|
|
12
12
|
for (var name in all)
|
|
13
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
14
|
};
|
|
15
|
-
var __copyProps = (to,
|
|
16
|
-
if (
|
|
17
|
-
for (let key of __getOwnPropNames(
|
|
15
|
+
var __copyProps = (to, from8, except, desc) => {
|
|
16
|
+
if (from8 && typeof from8 === "object" || typeof from8 === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from8))
|
|
18
18
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
-
__defProp(to, key, { get: () =>
|
|
19
|
+
__defProp(to, key, { get: () => from8[key], enumerable: !(desc = __getOwnPropDesc(from8, key)) || desc.enumerable });
|
|
20
20
|
}
|
|
21
21
|
return to;
|
|
22
22
|
};
|
|
@@ -1550,57 +1550,15 @@ var init_gateway_service = __esm({
|
|
|
1550
1550
|
*/
|
|
1551
1551
|
chat(request) {
|
|
1552
1552
|
const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
});
|
|
1560
|
-
const requestBody = { ...request, stream: request.stream !== false };
|
|
1553
|
+
const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
|
|
1554
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1555
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1556
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1557
|
+
})() : request.model;
|
|
1558
|
+
const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
|
|
1561
1559
|
return new import_rxjs6.Observable((observer) => {
|
|
1562
1560
|
const controller = new AbortController();
|
|
1563
|
-
const
|
|
1564
|
-
method: "POST",
|
|
1565
|
-
headers: this._getHeaders(),
|
|
1566
|
-
body: JSON.stringify(requestBody),
|
|
1567
|
-
signal: controller.signal
|
|
1568
|
-
});
|
|
1569
|
-
task.then(async (response) => {
|
|
1570
|
-
debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
|
|
1571
|
-
if (!response.ok) {
|
|
1572
|
-
let errorText = "";
|
|
1573
|
-
let errorData = null;
|
|
1574
|
-
try {
|
|
1575
|
-
errorText = await response.text();
|
|
1576
|
-
debugLogger.error("GatewayService chat error response body", {
|
|
1577
|
-
status: response.status,
|
|
1578
|
-
statusText: response.statusText,
|
|
1579
|
-
url: response.url,
|
|
1580
|
-
body: errorText
|
|
1581
|
-
});
|
|
1582
|
-
} catch (readError) {
|
|
1583
|
-
debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
|
|
1584
|
-
errorText = `Request failed with status ${response.status}`;
|
|
1585
|
-
}
|
|
1586
|
-
try {
|
|
1587
|
-
errorData = JSON.parse(errorText);
|
|
1588
|
-
debugLogger.error("GatewayService chat parsed error payload", errorData);
|
|
1589
|
-
} catch (parseError) {
|
|
1590
|
-
debugLogger.error("GatewayService chat error payload was not valid JSON");
|
|
1591
|
-
errorData = { message: errorText };
|
|
1592
|
-
}
|
|
1593
|
-
const error = this._createHttpError(
|
|
1594
|
-
`POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
|
|
1595
|
-
{
|
|
1596
|
-
status: response.status,
|
|
1597
|
-
statusText: response.statusText ?? "",
|
|
1598
|
-
data: errorData,
|
|
1599
|
-
url
|
|
1600
|
-
}
|
|
1601
|
-
);
|
|
1602
|
-
throw error;
|
|
1603
|
-
}
|
|
1561
|
+
const handleStreamingResponse = async (response) => {
|
|
1604
1562
|
const reader = response.body?.getReader();
|
|
1605
1563
|
const decoder = new TextDecoder();
|
|
1606
1564
|
let buffer = "";
|
|
@@ -1675,14 +1633,75 @@ var init_gateway_service = __esm({
|
|
|
1675
1633
|
}).catch((err) => observer.error(err));
|
|
1676
1634
|
};
|
|
1677
1635
|
read();
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1636
|
+
};
|
|
1637
|
+
const sendRequest = (targetEndpoint, allowFallback) => {
|
|
1638
|
+
const url = `${this._baseUrl}${targetEndpoint}`;
|
|
1639
|
+
debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1640
|
+
model: normalizedModel,
|
|
1641
|
+
messageCount: request.messages.length,
|
|
1642
|
+
hasImages: !!(request.images && request.images.length > 0),
|
|
1643
|
+
imageCount: request.images?.length || 0
|
|
1683
1644
|
});
|
|
1684
|
-
|
|
1685
|
-
|
|
1645
|
+
fetch(url, {
|
|
1646
|
+
method: "POST",
|
|
1647
|
+
headers: this._getHeaders(),
|
|
1648
|
+
body: JSON.stringify(requestBody),
|
|
1649
|
+
signal: controller.signal
|
|
1650
|
+
}).then(async (response) => {
|
|
1651
|
+
debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
|
|
1652
|
+
if (response.status === 404 && allowFallback && fallbackEndpoint) {
|
|
1653
|
+
debugLogger.warn("GatewayService chat endpoint returned 404, attempting fallback route", {
|
|
1654
|
+
provider: request.provider,
|
|
1655
|
+
attemptedEndpoint: targetEndpoint,
|
|
1656
|
+
fallbackEndpoint
|
|
1657
|
+
});
|
|
1658
|
+
sendRequest(fallbackEndpoint, false);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
if (!response.ok) {
|
|
1662
|
+
let errorText = "";
|
|
1663
|
+
let errorData = null;
|
|
1664
|
+
try {
|
|
1665
|
+
errorText = await response.text();
|
|
1666
|
+
debugLogger.error("GatewayService chat error response body", {
|
|
1667
|
+
status: response.status,
|
|
1668
|
+
statusText: response.statusText,
|
|
1669
|
+
url: response.url,
|
|
1670
|
+
body: errorText
|
|
1671
|
+
});
|
|
1672
|
+
} catch (readError) {
|
|
1673
|
+
debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
|
|
1674
|
+
errorText = `Request failed with status ${response.status}`;
|
|
1675
|
+
}
|
|
1676
|
+
try {
|
|
1677
|
+
errorData = JSON.parse(errorText);
|
|
1678
|
+
debugLogger.error("GatewayService chat parsed error payload", errorData);
|
|
1679
|
+
} catch (parseError) {
|
|
1680
|
+
debugLogger.error("GatewayService chat error payload was not valid JSON");
|
|
1681
|
+
errorData = { message: errorText };
|
|
1682
|
+
}
|
|
1683
|
+
const error = this._createHttpError(
|
|
1684
|
+
`POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
|
|
1685
|
+
{
|
|
1686
|
+
status: response.status,
|
|
1687
|
+
statusText: response.statusText ?? "",
|
|
1688
|
+
data: errorData,
|
|
1689
|
+
url
|
|
1690
|
+
}
|
|
1691
|
+
);
|
|
1692
|
+
throw error;
|
|
1693
|
+
}
|
|
1694
|
+
await handleStreamingResponse(response);
|
|
1695
|
+
}).catch((err) => {
|
|
1696
|
+
debugLogger.error("GatewayService chat fetch error", {
|
|
1697
|
+
error: err,
|
|
1698
|
+
url,
|
|
1699
|
+
provider: request.provider
|
|
1700
|
+
});
|
|
1701
|
+
observer.error(err);
|
|
1702
|
+
});
|
|
1703
|
+
};
|
|
1704
|
+
sendRequest(endpoint, true);
|
|
1686
1705
|
return () => {
|
|
1687
1706
|
try {
|
|
1688
1707
|
controller.abort();
|
|
@@ -1697,12 +1716,18 @@ var init_gateway_service = __esm({
|
|
|
1697
1716
|
generate(request) {
|
|
1698
1717
|
const endpoint = request.provider ? `/api/${request.provider}/generate` : "/api/generate";
|
|
1699
1718
|
const url = `${this._baseUrl}${endpoint}`;
|
|
1700
|
-
|
|
1719
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1720
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1721
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1722
|
+
})() : request.model;
|
|
1723
|
+
debugLogger.debug(`Gateway generate request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1724
|
+
model: normalizedModel
|
|
1725
|
+
});
|
|
1701
1726
|
return new import_rxjs6.Observable((observer) => {
|
|
1702
1727
|
const task = fetch(url, {
|
|
1703
1728
|
method: "POST",
|
|
1704
1729
|
headers: this._getHeaders(),
|
|
1705
|
-
body: JSON.stringify({ ...request, stream: request.stream !== false })
|
|
1730
|
+
body: JSON.stringify({ ...request, model: normalizedModel, stream: request.stream !== false })
|
|
1706
1731
|
});
|
|
1707
1732
|
task.then(async (response) => {
|
|
1708
1733
|
if (!response.ok) {
|
|
@@ -1809,18 +1834,46 @@ var init_gateway_service = __esm({
|
|
|
1809
1834
|
);
|
|
1810
1835
|
}
|
|
1811
1836
|
_getHeaders() {
|
|
1812
|
-
const
|
|
1837
|
+
const rawToken2 = this._tokenFactory();
|
|
1813
1838
|
const headers = {
|
|
1814
1839
|
"Content-Type": "application/json"
|
|
1815
1840
|
};
|
|
1816
|
-
if (
|
|
1817
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
1818
|
-
debugLogger.debug("Authorization header set with token");
|
|
1819
|
-
} else {
|
|
1841
|
+
if (!rawToken2) {
|
|
1820
1842
|
debugLogger.warn("GatewayService: No token found, skipping Authorization header");
|
|
1843
|
+
return headers;
|
|
1844
|
+
}
|
|
1845
|
+
const token = rawToken2.trim();
|
|
1846
|
+
if (token === "") {
|
|
1847
|
+
debugLogger.warn("GatewayService: Token factory returned empty string");
|
|
1848
|
+
return headers;
|
|
1821
1849
|
}
|
|
1850
|
+
if (/^(Bearer|ApiKey)\s+/i.test(token)) {
|
|
1851
|
+
headers["Authorization"] = token;
|
|
1852
|
+
debugLogger.debug("GatewayService: Authorization header set with explicit scheme");
|
|
1853
|
+
return headers;
|
|
1854
|
+
}
|
|
1855
|
+
if (this._isLikelyBanditApiKey(token)) {
|
|
1856
|
+
headers["Authorization"] = `ApiKey ${token}`;
|
|
1857
|
+
headers["X-Burtson-Api-Key"] = token;
|
|
1858
|
+
debugLogger.debug("GatewayService: Authorization header set using API key");
|
|
1859
|
+
return headers;
|
|
1860
|
+
}
|
|
1861
|
+
if (this._isLikelyJwt(token)) {
|
|
1862
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
1863
|
+
debugLogger.debug("GatewayService: Authorization header set using bearer token");
|
|
1864
|
+
return headers;
|
|
1865
|
+
}
|
|
1866
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
1867
|
+
debugLogger.debug("GatewayService: Authorization header defaulted to bearer scheme");
|
|
1822
1868
|
return headers;
|
|
1823
1869
|
}
|
|
1870
|
+
_isLikelyJwt(token) {
|
|
1871
|
+
const segments = token.split(".");
|
|
1872
|
+
return segments.length === 3 && segments.every((segment) => segment.length > 0);
|
|
1873
|
+
}
|
|
1874
|
+
_isLikelyBanditApiKey(value) {
|
|
1875
|
+
return /^bai_[a-z0-9]{10,}$/i.test(value);
|
|
1876
|
+
}
|
|
1824
1877
|
/**
|
|
1825
1878
|
* Submit feedback to the gateway API
|
|
1826
1879
|
*/
|
|
@@ -2300,6 +2353,112 @@ var init_ollama_gateway_service = __esm({
|
|
|
2300
2353
|
}
|
|
2301
2354
|
});
|
|
2302
2355
|
|
|
2356
|
+
// src/services/gateway/bandit-gateway.service.ts
|
|
2357
|
+
var import_operators5, normalizeBanditModel, isGatewayMessageContent, normalizeBanditMessages, BanditAIGatewayService;
|
|
2358
|
+
var init_bandit_gateway_service = __esm({
|
|
2359
|
+
"src/services/gateway/bandit-gateway.service.ts"() {
|
|
2360
|
+
"use strict";
|
|
2361
|
+
init_gateway_service();
|
|
2362
|
+
import_operators5 = require("rxjs/operators");
|
|
2363
|
+
init_debugLogger();
|
|
2364
|
+
normalizeBanditModel = (model) => {
|
|
2365
|
+
if (typeof model !== "string" || model.trim() === "") {
|
|
2366
|
+
return "bandit-core-1";
|
|
2367
|
+
}
|
|
2368
|
+
const normalized = model.replace(/^bandit:/, "").trim();
|
|
2369
|
+
return normalized === "" ? "bandit-core-1" : normalized;
|
|
2370
|
+
};
|
|
2371
|
+
isGatewayMessageContent = (value) => {
|
|
2372
|
+
if (!value || typeof value !== "object") return false;
|
|
2373
|
+
const candidate = value;
|
|
2374
|
+
if (candidate.type !== "text" && candidate.type !== "image_url") {
|
|
2375
|
+
return false;
|
|
2376
|
+
}
|
|
2377
|
+
if (candidate.type === "text") {
|
|
2378
|
+
return typeof candidate.text === "string";
|
|
2379
|
+
}
|
|
2380
|
+
if (candidate.type === "image_url") {
|
|
2381
|
+
return !!candidate.image_url && typeof candidate.image_url.url === "string";
|
|
2382
|
+
}
|
|
2383
|
+
return false;
|
|
2384
|
+
};
|
|
2385
|
+
normalizeBanditMessages = (messages) => messages.map((message) => {
|
|
2386
|
+
const content = message.content;
|
|
2387
|
+
if (typeof content === "string") {
|
|
2388
|
+
return { role: message.role, content };
|
|
2389
|
+
}
|
|
2390
|
+
if (Array.isArray(content)) {
|
|
2391
|
+
const filtered = content.filter(isGatewayMessageContent);
|
|
2392
|
+
if (filtered.length === 0) {
|
|
2393
|
+
return { role: message.role, content: JSON.stringify(content) };
|
|
2394
|
+
}
|
|
2395
|
+
return {
|
|
2396
|
+
role: message.role,
|
|
2397
|
+
content: filtered
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
return { role: message.role, content: content != null ? String(content) : "" };
|
|
2401
|
+
});
|
|
2402
|
+
BanditAIGatewayService = class {
|
|
2403
|
+
_gatewayService;
|
|
2404
|
+
constructor(gatewayUrl, tokenFactory) {
|
|
2405
|
+
this._gatewayService = new GatewayService(gatewayUrl, tokenFactory);
|
|
2406
|
+
debugLogger.info("BanditAIGatewayService initialized", { gatewayUrl });
|
|
2407
|
+
}
|
|
2408
|
+
async validateServiceAvailability(args) {
|
|
2409
|
+
return this._gatewayService.validateServiceAvailability(args);
|
|
2410
|
+
}
|
|
2411
|
+
chat(request) {
|
|
2412
|
+
const model = normalizeBanditModel(request.model);
|
|
2413
|
+
const messages = normalizeBanditMessages(request.messages);
|
|
2414
|
+
const gatewayRequest = {
|
|
2415
|
+
...request,
|
|
2416
|
+
messages,
|
|
2417
|
+
model,
|
|
2418
|
+
provider: "bandit",
|
|
2419
|
+
stream: request.stream
|
|
2420
|
+
};
|
|
2421
|
+
debugLogger.debug("Bandit Gateway chat request", {
|
|
2422
|
+
model,
|
|
2423
|
+
messageCount: request.messages.length,
|
|
2424
|
+
stream: request.stream
|
|
2425
|
+
});
|
|
2426
|
+
return this._gatewayService.chat(gatewayRequest);
|
|
2427
|
+
}
|
|
2428
|
+
complete(prompt, options) {
|
|
2429
|
+
const model = normalizeBanditModel(options.model);
|
|
2430
|
+
const gatewayRequest = {
|
|
2431
|
+
model,
|
|
2432
|
+
prompt,
|
|
2433
|
+
temperature: options.temperature,
|
|
2434
|
+
max_tokens: options.max_tokens,
|
|
2435
|
+
stream: options.stream,
|
|
2436
|
+
stop: options.stop,
|
|
2437
|
+
provider: "bandit"
|
|
2438
|
+
};
|
|
2439
|
+
debugLogger.debug("Bandit Gateway generate request", {
|
|
2440
|
+
model,
|
|
2441
|
+
promptLength: prompt.length,
|
|
2442
|
+
stream: options.stream
|
|
2443
|
+
});
|
|
2444
|
+
return this._gatewayService.generate(gatewayRequest);
|
|
2445
|
+
}
|
|
2446
|
+
listModels() {
|
|
2447
|
+
debugLogger.debug("Fetching Bandit models through gateway");
|
|
2448
|
+
return this._gatewayService.listModelsByProvider("bandit");
|
|
2449
|
+
}
|
|
2450
|
+
getHealth() {
|
|
2451
|
+
return this._gatewayService.getHealth().pipe(
|
|
2452
|
+
(0, import_operators5.map)((health) => ({
|
|
2453
|
+
...health,
|
|
2454
|
+
bandit_status: health.providers.find((p) => p.name === "bandit")?.status || "unavailable"
|
|
2455
|
+
}))
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
});
|
|
2461
|
+
|
|
2303
2462
|
// src/services/ai-provider/providers/gateway.provider.ts
|
|
2304
2463
|
var import_rxjs7, GatewayProvider;
|
|
2305
2464
|
var init_gateway_provider = __esm({
|
|
@@ -2313,6 +2472,7 @@ var init_gateway_provider = __esm({
|
|
|
2313
2472
|
init_azure_openai_gateway_service();
|
|
2314
2473
|
init_anthropic_gateway_service();
|
|
2315
2474
|
init_ollama_gateway_service();
|
|
2475
|
+
init_bandit_gateway_service();
|
|
2316
2476
|
GatewayProvider = class {
|
|
2317
2477
|
config;
|
|
2318
2478
|
gatewayService;
|
|
@@ -2354,6 +2514,9 @@ var init_gateway_provider = __esm({
|
|
|
2354
2514
|
case "anthropic":
|
|
2355
2515
|
this.providerSpecificService = new AnthropicGatewayService(gatewayUrl, tokenFactory);
|
|
2356
2516
|
break;
|
|
2517
|
+
case "bandit":
|
|
2518
|
+
this.providerSpecificService = new BanditAIGatewayService(gatewayUrl, tokenFactory);
|
|
2519
|
+
break;
|
|
2357
2520
|
case "ollama":
|
|
2358
2521
|
this.providerSpecificService = new OllamaGatewayService(gatewayUrl, tokenFactory);
|
|
2359
2522
|
break;
|
|
@@ -2368,6 +2531,16 @@ var init_gateway_provider = __esm({
|
|
|
2368
2531
|
role: msg.role,
|
|
2369
2532
|
content: msg.content
|
|
2370
2533
|
}));
|
|
2534
|
+
const normalizeImageUrl2 = (value) => {
|
|
2535
|
+
if (!value) {
|
|
2536
|
+
return value;
|
|
2537
|
+
}
|
|
2538
|
+
const trimmed = value.trim();
|
|
2539
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
2540
|
+
return trimmed;
|
|
2541
|
+
}
|
|
2542
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
2543
|
+
};
|
|
2371
2544
|
if (request.images && request.images.length > 0) {
|
|
2372
2545
|
const lastUserMessageIndex = messages.map((m) => m.role).lastIndexOf("user");
|
|
2373
2546
|
if (this.config.provider === "ollama") {
|
|
@@ -2377,7 +2550,7 @@ var init_gateway_provider = __esm({
|
|
|
2377
2550
|
images: request.images
|
|
2378
2551
|
};
|
|
2379
2552
|
}
|
|
2380
|
-
} else if (["openai", "azure-openai", "anthropic"].includes(this.config.provider || "")) {
|
|
2553
|
+
} else if (["openai", "azure-openai", "anthropic", "bandit"].includes(this.config.provider || "")) {
|
|
2381
2554
|
if (lastUserMessageIndex !== -1) {
|
|
2382
2555
|
const currentMessage = messages[lastUserMessageIndex];
|
|
2383
2556
|
const contentArray = [
|
|
@@ -2386,11 +2559,11 @@ var init_gateway_provider = __esm({
|
|
|
2386
2559
|
text: currentMessage.content
|
|
2387
2560
|
}
|
|
2388
2561
|
];
|
|
2389
|
-
request.images.forEach((
|
|
2562
|
+
request.images.forEach((imageRef) => {
|
|
2390
2563
|
contentArray.push({
|
|
2391
2564
|
type: "image_url",
|
|
2392
2565
|
image_url: {
|
|
2393
|
-
url:
|
|
2566
|
+
url: normalizeImageUrl2(imageRef),
|
|
2394
2567
|
detail: "auto"
|
|
2395
2568
|
}
|
|
2396
2569
|
});
|
|
@@ -2399,6 +2572,11 @@ var init_gateway_provider = __esm({
|
|
|
2399
2572
|
...messages[lastUserMessageIndex],
|
|
2400
2573
|
content: contentArray
|
|
2401
2574
|
};
|
|
2575
|
+
debugLogger.debug("Gateway provider injected image attachments", {
|
|
2576
|
+
provider: this.config.provider,
|
|
2577
|
+
imageCount: request.images.length,
|
|
2578
|
+
messageIndex: lastUserMessageIndex
|
|
2579
|
+
});
|
|
2402
2580
|
}
|
|
2403
2581
|
}
|
|
2404
2582
|
}
|
|
@@ -2907,6 +3085,244 @@ var init_xai_provider = __esm({
|
|
|
2907
3085
|
}
|
|
2908
3086
|
});
|
|
2909
3087
|
|
|
3088
|
+
// src/services/ai-provider/providers/bandit-ai.provider.ts
|
|
3089
|
+
var import_rxjs10, DEFAULT_BANDIT_BASE, normalizeImageUrl, injectImagesIntoMessages, BanditAIProvider;
|
|
3090
|
+
var init_bandit_ai_provider = __esm({
|
|
3091
|
+
"src/services/ai-provider/providers/bandit-ai.provider.ts"() {
|
|
3092
|
+
"use strict";
|
|
3093
|
+
import_rxjs10 = require("rxjs");
|
|
3094
|
+
init_common_types();
|
|
3095
|
+
init_debugLogger();
|
|
3096
|
+
DEFAULT_BANDIT_BASE = "https://api.burtson.ai";
|
|
3097
|
+
normalizeImageUrl = (value) => {
|
|
3098
|
+
if (!value) {
|
|
3099
|
+
return null;
|
|
3100
|
+
}
|
|
3101
|
+
const trimmed = value.trim();
|
|
3102
|
+
if (!trimmed) {
|
|
3103
|
+
return null;
|
|
3104
|
+
}
|
|
3105
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
3106
|
+
return trimmed;
|
|
3107
|
+
}
|
|
3108
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
3109
|
+
};
|
|
3110
|
+
injectImagesIntoMessages = (messages, images) => {
|
|
3111
|
+
const normalized = messages.map((message) => ({
|
|
3112
|
+
role: message.role,
|
|
3113
|
+
content: message.content
|
|
3114
|
+
}));
|
|
3115
|
+
if (!images || images.length === 0) {
|
|
3116
|
+
return normalized;
|
|
3117
|
+
}
|
|
3118
|
+
const normalizedImages = images.map(normalizeImageUrl).filter((url) => Boolean(url));
|
|
3119
|
+
if (normalizedImages.length === 0) {
|
|
3120
|
+
return normalized;
|
|
3121
|
+
}
|
|
3122
|
+
const lastUserIndex = normalized.map((msg) => msg.role).lastIndexOf("user");
|
|
3123
|
+
if (lastUserIndex === -1) {
|
|
3124
|
+
return normalized;
|
|
3125
|
+
}
|
|
3126
|
+
const target = normalized[lastUserIndex];
|
|
3127
|
+
const baseContent = typeof target.content === "string" && target.content.trim().length > 0 ? [
|
|
3128
|
+
{
|
|
3129
|
+
type: "text",
|
|
3130
|
+
text: target.content
|
|
3131
|
+
}
|
|
3132
|
+
] : [];
|
|
3133
|
+
const imageContent = normalizedImages.map((url) => ({
|
|
3134
|
+
type: "image_url",
|
|
3135
|
+
image_url: { url, detail: "auto" }
|
|
3136
|
+
}));
|
|
3137
|
+
normalized[lastUserIndex] = {
|
|
3138
|
+
role: target.role,
|
|
3139
|
+
content: [...baseContent, ...imageContent]
|
|
3140
|
+
};
|
|
3141
|
+
return normalized;
|
|
3142
|
+
};
|
|
3143
|
+
BanditAIProvider = class {
|
|
3144
|
+
config;
|
|
3145
|
+
baseUrl;
|
|
3146
|
+
constructor(config) {
|
|
3147
|
+
this.config = config;
|
|
3148
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BANDIT_BASE).replace(/\/$/, "");
|
|
3149
|
+
}
|
|
3150
|
+
chat(request) {
|
|
3151
|
+
const url = `${this.baseUrl}/chat/completions`;
|
|
3152
|
+
const messages = injectImagesIntoMessages(request.messages, request.images);
|
|
3153
|
+
const payload = {
|
|
3154
|
+
model: request.model,
|
|
3155
|
+
messages,
|
|
3156
|
+
stream: Boolean(request.stream),
|
|
3157
|
+
temperature: request.temperature,
|
|
3158
|
+
max_tokens: request.maxTokens
|
|
3159
|
+
};
|
|
3160
|
+
if (request.stream) {
|
|
3161
|
+
return this.streamChatRequest(url, payload);
|
|
3162
|
+
}
|
|
3163
|
+
return this.nonStreamChatRequest(url, payload);
|
|
3164
|
+
}
|
|
3165
|
+
generate(request) {
|
|
3166
|
+
const chatRequest = {
|
|
3167
|
+
model: request.model,
|
|
3168
|
+
messages: [{ role: "user", content: request.prompt }],
|
|
3169
|
+
stream: request.stream,
|
|
3170
|
+
options: request.options
|
|
3171
|
+
};
|
|
3172
|
+
return this.chat(chatRequest).pipe(
|
|
3173
|
+
(0, import_rxjs10.map)((response) => ({
|
|
3174
|
+
response: response.message.content,
|
|
3175
|
+
done: response.done
|
|
3176
|
+
}))
|
|
3177
|
+
);
|
|
3178
|
+
}
|
|
3179
|
+
listModels() {
|
|
3180
|
+
const url = `${this.baseUrl}/models`;
|
|
3181
|
+
return (0, import_rxjs10.from)(fetch(url, { headers: this.getHeaders() })).pipe(
|
|
3182
|
+
(0, import_rxjs10.switchMap)((response) => {
|
|
3183
|
+
if (!response.ok) {
|
|
3184
|
+
debugLogger.error("BanditAI listModels failed", { status: response.status, url });
|
|
3185
|
+
return (0, import_rxjs10.throwError)(() => new Error(`Failed to list Bandit models: ${response.status}`));
|
|
3186
|
+
}
|
|
3187
|
+
return (0, import_rxjs10.from)(response.json());
|
|
3188
|
+
}),
|
|
3189
|
+
(0, import_rxjs10.map)(
|
|
3190
|
+
(data) => data.data.map((model) => ({
|
|
3191
|
+
name: model.id,
|
|
3192
|
+
details: {
|
|
3193
|
+
format: "bandit",
|
|
3194
|
+
family: model.object
|
|
3195
|
+
}
|
|
3196
|
+
}))
|
|
3197
|
+
)
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
async validateServiceAvailability(args) {
|
|
3201
|
+
const attempt = async (url) => {
|
|
3202
|
+
try {
|
|
3203
|
+
const controller = new AbortController();
|
|
3204
|
+
const timeoutId = setTimeout(() => controller.abort(), args.timeoutMs);
|
|
3205
|
+
const response = await fetch(`${url}/models`, {
|
|
3206
|
+
headers: this.getHeaders(),
|
|
3207
|
+
signal: controller.signal
|
|
3208
|
+
});
|
|
3209
|
+
clearTimeout(timeoutId);
|
|
3210
|
+
return response.ok;
|
|
3211
|
+
} catch (error) {
|
|
3212
|
+
debugLogger.warn("BanditAI availability check failed", { url, error });
|
|
3213
|
+
return false;
|
|
3214
|
+
}
|
|
3215
|
+
};
|
|
3216
|
+
const primary = await attempt(this.baseUrl);
|
|
3217
|
+
if (primary) {
|
|
3218
|
+
return { url: this.baseUrl, isAvailable: true };
|
|
3219
|
+
}
|
|
3220
|
+
if (args.fallbackUrl) {
|
|
3221
|
+
const fallback = args.fallbackUrl.replace(/\/$/, "");
|
|
3222
|
+
if (await attempt(fallback)) {
|
|
3223
|
+
this.baseUrl = fallback;
|
|
3224
|
+
return { url: fallback, isAvailable: true };
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
return { url: this.baseUrl, isAvailable: false };
|
|
3228
|
+
}
|
|
3229
|
+
getProviderType() {
|
|
3230
|
+
return "bandit" /* BANDIT */;
|
|
3231
|
+
}
|
|
3232
|
+
getConfig() {
|
|
3233
|
+
return this.config;
|
|
3234
|
+
}
|
|
3235
|
+
streamChatRequest(url, payload) {
|
|
3236
|
+
return new import_rxjs10.Observable((observer) => {
|
|
3237
|
+
const task = fetch(url, {
|
|
3238
|
+
method: "POST",
|
|
3239
|
+
headers: {
|
|
3240
|
+
...this.getHeaders(),
|
|
3241
|
+
"Content-Type": "application/json"
|
|
3242
|
+
},
|
|
3243
|
+
body: JSON.stringify(payload)
|
|
3244
|
+
});
|
|
3245
|
+
task.then((response) => {
|
|
3246
|
+
if (!response.ok) {
|
|
3247
|
+
observer.error(new Error(`BanditAI request failed: ${response.status}`));
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
const reader = response.body?.getReader();
|
|
3251
|
+
const decoder = new TextDecoder();
|
|
3252
|
+
let buffer = "";
|
|
3253
|
+
const read = () => {
|
|
3254
|
+
reader?.read().then(({ done, value }) => {
|
|
3255
|
+
if (done) {
|
|
3256
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
3257
|
+
observer.complete();
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
buffer += decoder.decode(value, { stream: true });
|
|
3261
|
+
const lines = buffer.split("\n");
|
|
3262
|
+
buffer = lines.pop() ?? "";
|
|
3263
|
+
for (const rawLine of lines) {
|
|
3264
|
+
const line = rawLine.trim();
|
|
3265
|
+
if (!line.startsWith("data: ")) {
|
|
3266
|
+
continue;
|
|
3267
|
+
}
|
|
3268
|
+
const data = line.slice(6).trim();
|
|
3269
|
+
if (data === "[DONE]") {
|
|
3270
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
3271
|
+
observer.complete();
|
|
3272
|
+
return;
|
|
3273
|
+
}
|
|
3274
|
+
try {
|
|
3275
|
+
const parsed = JSON.parse(data);
|
|
3276
|
+
const content = parsed.choices?.[0]?.delta?.content ?? "";
|
|
3277
|
+
if (content) {
|
|
3278
|
+
observer.next({ message: { content, role: "assistant" }, done: false });
|
|
3279
|
+
}
|
|
3280
|
+
} catch (error) {
|
|
3281
|
+
debugLogger.error("BanditAI stream chunk parse failure", { data, error });
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
read();
|
|
3285
|
+
}).catch((err) => observer.error(err));
|
|
3286
|
+
};
|
|
3287
|
+
read();
|
|
3288
|
+
}).catch((err) => observer.error(err));
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
nonStreamChatRequest(url, payload) {
|
|
3292
|
+
return (0, import_rxjs10.from)(fetch(url, {
|
|
3293
|
+
method: "POST",
|
|
3294
|
+
headers: {
|
|
3295
|
+
...this.getHeaders(),
|
|
3296
|
+
"Content-Type": "application/json"
|
|
3297
|
+
},
|
|
3298
|
+
body: JSON.stringify(payload)
|
|
3299
|
+
})).pipe(
|
|
3300
|
+
(0, import_rxjs10.switchMap)((response) => {
|
|
3301
|
+
if (!response.ok) {
|
|
3302
|
+
return (0, import_rxjs10.throwError)(() => new Error(`BanditAI request failed: ${response.status}`));
|
|
3303
|
+
}
|
|
3304
|
+
return (0, import_rxjs10.from)(response.json());
|
|
3305
|
+
}),
|
|
3306
|
+
(0, import_rxjs10.map)((data) => ({
|
|
3307
|
+
message: {
|
|
3308
|
+
content: data.choices?.[0]?.message?.content ?? "",
|
|
3309
|
+
role: "assistant"
|
|
3310
|
+
},
|
|
3311
|
+
done: true
|
|
3312
|
+
}))
|
|
3313
|
+
);
|
|
3314
|
+
}
|
|
3315
|
+
getHeaders() {
|
|
3316
|
+
const headers = {};
|
|
3317
|
+
if (this.config.apiKey) {
|
|
3318
|
+
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
3319
|
+
}
|
|
3320
|
+
return headers;
|
|
3321
|
+
}
|
|
3322
|
+
};
|
|
3323
|
+
}
|
|
3324
|
+
});
|
|
3325
|
+
|
|
2910
3326
|
// src/services/ai-provider/ai-provider.factory.ts
|
|
2911
3327
|
var AIProviderFactory;
|
|
2912
3328
|
var init_ai_provider_factory = __esm({
|
|
@@ -2920,6 +3336,7 @@ var init_ai_provider_factory = __esm({
|
|
|
2920
3336
|
init_gateway_provider();
|
|
2921
3337
|
init_playground_provider();
|
|
2922
3338
|
init_xai_provider();
|
|
3339
|
+
init_bandit_ai_provider();
|
|
2923
3340
|
AIProviderFactory = class {
|
|
2924
3341
|
static createProvider(config) {
|
|
2925
3342
|
switch (config.type) {
|
|
@@ -2933,6 +3350,8 @@ var init_ai_provider_factory = __esm({
|
|
|
2933
3350
|
return new AnthropicProvider(config);
|
|
2934
3351
|
case "xai" /* XAI */:
|
|
2935
3352
|
return new XAIProvider(config);
|
|
3353
|
+
case "bandit" /* BANDIT */:
|
|
3354
|
+
return new BanditAIProvider(config);
|
|
2936
3355
|
case "gateway" /* GATEWAY */:
|
|
2937
3356
|
return new GatewayProvider(config);
|
|
2938
3357
|
case "playground" /* PLAYGROUND */:
|
|
@@ -2947,6 +3366,7 @@ var init_ai_provider_factory = __esm({
|
|
|
2947
3366
|
"openai" /* OPENAI */,
|
|
2948
3367
|
"azure-openai" /* AZURE_OPENAI */,
|
|
2949
3368
|
"xai" /* XAI */,
|
|
3369
|
+
"bandit" /* BANDIT */,
|
|
2950
3370
|
"gateway" /* GATEWAY */,
|
|
2951
3371
|
"playground" /* PLAYGROUND */
|
|
2952
3372
|
];
|
|
@@ -2964,6 +3384,8 @@ var init_ai_provider_factory = __esm({
|
|
|
2964
3384
|
return !!config.apiKey;
|
|
2965
3385
|
case "xai" /* XAI */:
|
|
2966
3386
|
return !!config.apiKey;
|
|
3387
|
+
case "bandit" /* BANDIT */:
|
|
3388
|
+
return !!config.apiKey;
|
|
2967
3389
|
case "gateway" /* GATEWAY */:
|
|
2968
3390
|
return !!(config.gatewayUrl && config.provider);
|
|
2969
3391
|
case "playground" /* PLAYGROUND */:
|
|
@@ -4452,7 +4874,7 @@ var import_mammoth = __toESM(require("mammoth"));
|
|
|
4452
4874
|
var pdfjsLib = __toESM(require("pdfjs-dist/legacy/build/pdf"));
|
|
4453
4875
|
|
|
4454
4876
|
// src/services/prompts/conversationStarters.ts
|
|
4455
|
-
var
|
|
4877
|
+
var import_rxjs11 = require("rxjs");
|
|
4456
4878
|
init_aiProviderStore();
|
|
4457
4879
|
init_packageSettingsStore();
|
|
4458
4880
|
|
|
@@ -4611,19 +5033,19 @@ var NotificationService = class {
|
|
|
4611
5033
|
var notificationService = new NotificationService();
|
|
4612
5034
|
|
|
4613
5035
|
// src/services/prompts/moodDetection.ts
|
|
4614
|
-
var
|
|
5036
|
+
var import_rxjs12 = require("rxjs");
|
|
4615
5037
|
init_aiProviderStore();
|
|
4616
5038
|
init_packageSettingsStore();
|
|
4617
5039
|
init_debugLogger();
|
|
4618
5040
|
|
|
4619
5041
|
// src/services/prompts/detectUserInterestAndExcitement.ts
|
|
4620
|
-
var
|
|
5042
|
+
var import_rxjs13 = require("rxjs");
|
|
4621
5043
|
init_aiProviderStore();
|
|
4622
5044
|
init_packageSettingsStore();
|
|
4623
5045
|
init_debugLogger();
|
|
4624
5046
|
|
|
4625
5047
|
// src/services/prompts/documentSummarization.ts
|
|
4626
|
-
var
|
|
5048
|
+
var import_rxjs14 = require("rxjs");
|
|
4627
5049
|
init_aiProviderStore();
|
|
4628
5050
|
init_packageSettingsStore();
|
|
4629
5051
|
init_debugLogger();
|
|
@@ -4651,8 +5073,8 @@ ${content.slice(0, 4e3)}
|
|
|
4651
5073
|
stream: false,
|
|
4652
5074
|
options: { temperature: 0.3, num_predict: 100 }
|
|
4653
5075
|
});
|
|
4654
|
-
const summary$ = data$.pipe((0,
|
|
4655
|
-
const summary = await (0,
|
|
5076
|
+
const summary$ = data$.pipe((0, import_rxjs14.map)((d) => d.response.trim()));
|
|
5077
|
+
const summary = await (0, import_rxjs14.lastValueFrom)(summary$);
|
|
4656
5078
|
debugLogger.ragDebug("summarizeDocument result", { name, summary });
|
|
4657
5079
|
return summary || `Document summary for ${name}`;
|
|
4658
5080
|
} catch (error) {
|
|
@@ -4662,7 +5084,7 @@ ${content.slice(0, 4e3)}
|
|
|
4662
5084
|
};
|
|
4663
5085
|
|
|
4664
5086
|
// src/services/prompts/documentRelevance.ts
|
|
4665
|
-
var
|
|
5087
|
+
var import_rxjs15 = require("rxjs");
|
|
4666
5088
|
init_aiProviderStore();
|
|
4667
5089
|
init_packageSettingsStore();
|
|
4668
5090
|
init_debugLogger();
|
|
@@ -6986,13 +7408,17 @@ var useConversationStore = (0, import_zustand9.create)((set, get) => ({
|
|
|
6986
7408
|
const updatedConversations = conversations.map((c) => {
|
|
6987
7409
|
if (c.id === currentId && c.history.length > 0) {
|
|
6988
7410
|
const updatedHistory = [...c.history];
|
|
7411
|
+
const existingImages = updatedHistory[updatedHistory.length - 1].images;
|
|
7412
|
+
const nextImages = Array.isArray(images) && images.length > 0 ? [...images] : Array.isArray(existingImages) && existingImages.length > 0 ? [...existingImages] : existingImages;
|
|
6989
7413
|
updatedHistory[updatedHistory.length - 1] = {
|
|
6990
7414
|
...updatedHistory[updatedHistory.length - 1],
|
|
6991
7415
|
answer,
|
|
6992
7416
|
memoryUpdated,
|
|
6993
|
-
images:
|
|
7417
|
+
images: nextImages,
|
|
6994
7418
|
sourceFiles: sourceFiles ?? updatedHistory[updatedHistory.length - 1].sourceFiles,
|
|
6995
|
-
cancelled: cancelled ?? updatedHistory[updatedHistory.length - 1].cancelled
|
|
7419
|
+
cancelled: cancelled ?? updatedHistory[updatedHistory.length - 1].cancelled,
|
|
7420
|
+
placeholder: false,
|
|
7421
|
+
rawQuestion: void 0
|
|
6996
7422
|
};
|
|
6997
7423
|
return normalizeConversation({ ...c, history: updatedHistory, updatedAt: /* @__PURE__ */ new Date() });
|
|
6998
7424
|
}
|
|
@@ -7073,6 +7499,24 @@ var useConversationStore = (0, import_zustand9.create)((set, get) => ({
|
|
|
7073
7499
|
});
|
|
7074
7500
|
continue;
|
|
7075
7501
|
}
|
|
7502
|
+
if (Array.isArray(existing.history) && Array.isArray(conversation.history)) {
|
|
7503
|
+
const mergedHistory = conversation.history.map((incomingEntry, index) => {
|
|
7504
|
+
const existingEntry = existing.history[index];
|
|
7505
|
+
if (!existingEntry) {
|
|
7506
|
+
return incomingEntry;
|
|
7507
|
+
}
|
|
7508
|
+
const mergedImagesSource = Array.isArray(incomingEntry.images) && incomingEntry.images.length > 0 ? incomingEntry.images : existingEntry.images;
|
|
7509
|
+
const mergedImages = Array.isArray(mergedImagesSource) && mergedImagesSource.length > 0 ? [...mergedImagesSource] : mergedImagesSource;
|
|
7510
|
+
return {
|
|
7511
|
+
...existingEntry,
|
|
7512
|
+
...incomingEntry,
|
|
7513
|
+
images: mergedImages,
|
|
7514
|
+
placeholder: incomingEntry.placeholder ?? existingEntry.placeholder,
|
|
7515
|
+
rawQuestion: incomingEntry.rawQuestion ?? existingEntry.rawQuestion
|
|
7516
|
+
};
|
|
7517
|
+
});
|
|
7518
|
+
conversation.history = mergedHistory;
|
|
7519
|
+
}
|
|
7076
7520
|
}
|
|
7077
7521
|
next.set(conversation.id, conversation);
|
|
7078
7522
|
toPersist.push(conversation);
|
|
@@ -10790,12 +11234,12 @@ var voiceService = VoiceService.getInstance();
|
|
|
10790
11234
|
init_debugLogger();
|
|
10791
11235
|
|
|
10792
11236
|
// src/services/tts/streaming-tts.ts
|
|
10793
|
-
var
|
|
11237
|
+
var import_rxjs17 = require("rxjs");
|
|
10794
11238
|
init_debugLogger();
|
|
10795
11239
|
init_packageSettingsStore();
|
|
10796
11240
|
|
|
10797
11241
|
// src/services/tts/tts-client.ts
|
|
10798
|
-
var
|
|
11242
|
+
var import_rxjs16 = require("rxjs");
|
|
10799
11243
|
init_packageSettingsStore();
|
|
10800
11244
|
init_debugLogger();
|
|
10801
11245
|
var getOrAppendAuthHeader = (existing = {}) => {
|
|
@@ -10818,8 +11262,8 @@ var StreamingTTSClient = class _StreamingTTSClient {
|
|
|
10818
11262
|
// Store event handler references for proper cleanup
|
|
10819
11263
|
audioHandlers = /* @__PURE__ */ new Map();
|
|
10820
11264
|
// State management
|
|
10821
|
-
stateSubject = new
|
|
10822
|
-
progressSubject = new
|
|
11265
|
+
stateSubject = new import_rxjs17.BehaviorSubject("IDLE" /* IDLE */);
|
|
11266
|
+
progressSubject = new import_rxjs17.Subject();
|
|
10823
11267
|
constructor() {
|
|
10824
11268
|
}
|
|
10825
11269
|
static getInstance() {
|
|
@@ -10850,7 +11294,7 @@ var StreamingTTSClient = class _StreamingTTSClient {
|
|
|
10850
11294
|
* Speak text with simple streaming
|
|
10851
11295
|
*/
|
|
10852
11296
|
speakStream(text, voice, options = {}) {
|
|
10853
|
-
return new
|
|
11297
|
+
return new import_rxjs17.Observable((subscriber) => {
|
|
10854
11298
|
this.performSimpleStreaming(text, voice, options, subscriber);
|
|
10855
11299
|
});
|
|
10856
11300
|
}
|
|
@@ -14275,7 +14719,7 @@ var MemoryModal = ({ open, onClose }) => {
|
|
|
14275
14719
|
var memory_modal_default = MemoryModal;
|
|
14276
14720
|
|
|
14277
14721
|
// src/modals/chat-modal/chat-drawer.tsx
|
|
14278
|
-
var
|
|
14722
|
+
var import_rxjs18 = require("rxjs");
|
|
14279
14723
|
init_debugLogger();
|
|
14280
14724
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
14281
14725
|
var AIQueriesDrawer = ({ drawerOpen, onClose, onClearComplete, onNavigateToMain }) => {
|
|
@@ -14303,7 +14747,7 @@ var AIQueriesDrawer = ({ drawerOpen, onClose, onClearComplete, onNavigateToMain
|
|
|
14303
14747
|
const [memoryModalOpen, setMemoryModalOpen] = (0, import_react15.useState)(false);
|
|
14304
14748
|
const [contextMode, setContextMode] = (0, import_react15.useState)("local");
|
|
14305
14749
|
const [expandedSections, setExpandedSections] = (0, import_react15.useState)(/* @__PURE__ */ new Set(["history", "voice"]));
|
|
14306
|
-
const [audioSub, setAudioSub] = (0, import_react15.useState)(new
|
|
14750
|
+
const [audioSub, setAudioSub] = (0, import_react15.useState)(new import_rxjs18.Subscription());
|
|
14307
14751
|
const [isContextSwitching, setIsContextSwitching] = (0, import_react15.useState)(false);
|
|
14308
14752
|
const [isDrawerLoading, setIsDrawerLoading] = (0, import_react15.useState)(false);
|
|
14309
14753
|
(0, import_react15.useEffect)(() => {
|
|
@@ -19727,7 +20171,7 @@ var predefinedThemes = {
|
|
|
19727
20171
|
var themeMap_default = themeMap;
|
|
19728
20172
|
|
|
19729
20173
|
// src/modals/chat-modal/chat-modal.tsx
|
|
19730
|
-
var
|
|
20174
|
+
var import_rxjs19 = require("rxjs");
|
|
19731
20175
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
19732
20176
|
var FULL_SCREEN_THRESHOLD = 100;
|
|
19733
20177
|
var MIN_WINDOWED_HEIGHT = 400;
|
|
@@ -19796,7 +20240,7 @@ var ChatModal = ({
|
|
|
19796
20240
|
const [modalLogo, setModalLogo] = (0, import_react22.useState)("https://cdn.burtson.ai/logos/bandit-ai-logo.png");
|
|
19797
20241
|
const [modelAnchorEl, setModelAnchorEl] = (0, import_react22.useState)(null);
|
|
19798
20242
|
const [voiceAnchorEl, setVoiceAnchorEl] = (0, import_react22.useState)(null);
|
|
19799
|
-
const [audioSub, setAudioSub] = (0, import_react22.useState)(new
|
|
20243
|
+
const [audioSub, setAudioSub] = (0, import_react22.useState)(new import_rxjs19.Subscription());
|
|
19800
20244
|
const [selectedTheme, setSelectedTheme] = (0, import_react22.useState)(null);
|
|
19801
20245
|
const [themeLoading, setThemeLoading] = (0, import_react22.useState)(true);
|
|
19802
20246
|
const [autoFullscreenTriggered, setAutoFullscreenTriggered] = (0, import_react22.useState)(false);
|