@burtson-labs/bandit-engine 2.0.39 → 2.0.40
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/dist/{aiProviderStore-XN7GCBHJ.mjs → aiProviderStore-JMA5RWX7.mjs} +2 -2
- package/dist/{chat-5QJNWB7I.mjs → chat-JMWPOSQ4.mjs} +5 -5
- package/dist/chat-provider.js +421 -20
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +4 -4
- package/dist/{chunk-WO5KFNNW.mjs → chunk-26QQ4CLA.mjs} +62 -24
- package/dist/chunk-26QQ4CLA.mjs.map +1 -0
- package/dist/{chunk-CDQYBO3Q.mjs → chunk-2ZCR2TDY.mjs} +27 -5
- package/dist/chunk-2ZCR2TDY.mjs.map +1 -0
- package/dist/{chunk-ECRNIAG6.mjs → chunk-6ELNWXKC.mjs} +4 -4
- package/dist/{chunk-EOKIE5HZ.mjs → chunk-75W5VWPV.mjs} +3 -3
- package/dist/{chunk-JRCDANLN.mjs → chunk-7KEBNVCO.mjs} +67 -9
- package/dist/{chunk-JRCDANLN.mjs.map → chunk-7KEBNVCO.mjs.map} +1 -1
- package/dist/{chunk-3A2527TE.mjs → chunk-D3AGKOM6.mjs} +3 -3
- package/dist/{chunk-QU5S5QQP.mjs → chunk-QJYPWWA5.mjs} +379 -18
- package/dist/chunk-QJYPWWA5.mjs.map +1 -0
- package/dist/{chunk-QYH2T4L5.mjs → chunk-VIYBZO5W.mjs} +3 -3
- 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 +598 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/management/management.js +596 -99
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +6 -6
- package/dist/modals/chat-modal/chat-modal.js +430 -29
- 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/package.json +1 -1
- package/dist/chunk-CDQYBO3Q.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-JMA5RWX7.mjs.map} +0 -0
- /package/dist/{chat-5QJNWB7I.mjs.map → chat-JMWPOSQ4.mjs.map} +0 -0
- /package/dist/{chunk-ECRNIAG6.mjs.map → chunk-6ELNWXKC.mjs.map} +0 -0
- /package/dist/{chunk-EOKIE5HZ.mjs.map → chunk-75W5VWPV.mjs.map} +0 -0
- /package/dist/{chunk-3A2527TE.mjs.map → chunk-D3AGKOM6.mjs.map} +0 -0
- /package/dist/{chunk-QYH2T4L5.mjs.map → chunk-VIYBZO5W.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
|
};
|
|
@@ -1551,13 +1551,17 @@ var init_gateway_service = __esm({
|
|
|
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
1553
|
const url = `${this._baseUrl}${endpoint}`;
|
|
1554
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1555
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1556
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1557
|
+
})() : request.model;
|
|
1554
1558
|
debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1555
|
-
model:
|
|
1559
|
+
model: normalizedModel,
|
|
1556
1560
|
messageCount: request.messages.length,
|
|
1557
1561
|
hasImages: !!(request.images && request.images.length > 0),
|
|
1558
1562
|
imageCount: request.images?.length || 0
|
|
1559
1563
|
});
|
|
1560
|
-
const requestBody = { ...request, stream: request.stream !== false };
|
|
1564
|
+
const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
|
|
1561
1565
|
return new import_rxjs6.Observable((observer) => {
|
|
1562
1566
|
const controller = new AbortController();
|
|
1563
1567
|
const task = fetch(url, {
|
|
@@ -1697,12 +1701,18 @@ var init_gateway_service = __esm({
|
|
|
1697
1701
|
generate(request) {
|
|
1698
1702
|
const endpoint = request.provider ? `/api/${request.provider}/generate` : "/api/generate";
|
|
1699
1703
|
const url = `${this._baseUrl}${endpoint}`;
|
|
1700
|
-
|
|
1704
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1705
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1706
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1707
|
+
})() : request.model;
|
|
1708
|
+
debugLogger.debug(`Gateway generate request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1709
|
+
model: normalizedModel
|
|
1710
|
+
});
|
|
1701
1711
|
return new import_rxjs6.Observable((observer) => {
|
|
1702
1712
|
const task = fetch(url, {
|
|
1703
1713
|
method: "POST",
|
|
1704
1714
|
headers: this._getHeaders(),
|
|
1705
|
-
body: JSON.stringify({ ...request, stream: request.stream !== false })
|
|
1715
|
+
body: JSON.stringify({ ...request, model: normalizedModel, stream: request.stream !== false })
|
|
1706
1716
|
});
|
|
1707
1717
|
task.then(async (response) => {
|
|
1708
1718
|
if (!response.ok) {
|
|
@@ -2300,6 +2310,112 @@ var init_ollama_gateway_service = __esm({
|
|
|
2300
2310
|
}
|
|
2301
2311
|
});
|
|
2302
2312
|
|
|
2313
|
+
// src/services/gateway/bandit-gateway.service.ts
|
|
2314
|
+
var import_operators5, normalizeBanditModel, isGatewayMessageContent, normalizeBanditMessages, BanditAIGatewayService;
|
|
2315
|
+
var init_bandit_gateway_service = __esm({
|
|
2316
|
+
"src/services/gateway/bandit-gateway.service.ts"() {
|
|
2317
|
+
"use strict";
|
|
2318
|
+
init_gateway_service();
|
|
2319
|
+
import_operators5 = require("rxjs/operators");
|
|
2320
|
+
init_debugLogger();
|
|
2321
|
+
normalizeBanditModel = (model) => {
|
|
2322
|
+
if (typeof model !== "string" || model.trim() === "") {
|
|
2323
|
+
return "bandit-core-1";
|
|
2324
|
+
}
|
|
2325
|
+
const normalized = model.replace(/^bandit:/, "").trim();
|
|
2326
|
+
return normalized === "" ? "bandit-core-1" : normalized;
|
|
2327
|
+
};
|
|
2328
|
+
isGatewayMessageContent = (value) => {
|
|
2329
|
+
if (!value || typeof value !== "object") return false;
|
|
2330
|
+
const candidate = value;
|
|
2331
|
+
if (candidate.type !== "text" && candidate.type !== "image_url") {
|
|
2332
|
+
return false;
|
|
2333
|
+
}
|
|
2334
|
+
if (candidate.type === "text") {
|
|
2335
|
+
return typeof candidate.text === "string";
|
|
2336
|
+
}
|
|
2337
|
+
if (candidate.type === "image_url") {
|
|
2338
|
+
return !!candidate.image_url && typeof candidate.image_url.url === "string";
|
|
2339
|
+
}
|
|
2340
|
+
return false;
|
|
2341
|
+
};
|
|
2342
|
+
normalizeBanditMessages = (messages) => messages.map((message) => {
|
|
2343
|
+
const content = message.content;
|
|
2344
|
+
if (typeof content === "string") {
|
|
2345
|
+
return { role: message.role, content };
|
|
2346
|
+
}
|
|
2347
|
+
if (Array.isArray(content)) {
|
|
2348
|
+
const filtered = content.filter(isGatewayMessageContent);
|
|
2349
|
+
if (filtered.length === 0) {
|
|
2350
|
+
return { role: message.role, content: JSON.stringify(content) };
|
|
2351
|
+
}
|
|
2352
|
+
return {
|
|
2353
|
+
role: message.role,
|
|
2354
|
+
content: filtered
|
|
2355
|
+
};
|
|
2356
|
+
}
|
|
2357
|
+
return { role: message.role, content: content != null ? String(content) : "" };
|
|
2358
|
+
});
|
|
2359
|
+
BanditAIGatewayService = class {
|
|
2360
|
+
_gatewayService;
|
|
2361
|
+
constructor(gatewayUrl, tokenFactory) {
|
|
2362
|
+
this._gatewayService = new GatewayService(gatewayUrl, tokenFactory);
|
|
2363
|
+
debugLogger.info("BanditAIGatewayService initialized", { gatewayUrl });
|
|
2364
|
+
}
|
|
2365
|
+
async validateServiceAvailability(args) {
|
|
2366
|
+
return this._gatewayService.validateServiceAvailability(args);
|
|
2367
|
+
}
|
|
2368
|
+
chat(request) {
|
|
2369
|
+
const model = normalizeBanditModel(request.model);
|
|
2370
|
+
const messages = normalizeBanditMessages(request.messages);
|
|
2371
|
+
const gatewayRequest = {
|
|
2372
|
+
...request,
|
|
2373
|
+
messages,
|
|
2374
|
+
model,
|
|
2375
|
+
provider: "bandit",
|
|
2376
|
+
stream: request.stream
|
|
2377
|
+
};
|
|
2378
|
+
debugLogger.debug("Bandit Gateway chat request", {
|
|
2379
|
+
model,
|
|
2380
|
+
messageCount: request.messages.length,
|
|
2381
|
+
stream: request.stream
|
|
2382
|
+
});
|
|
2383
|
+
return this._gatewayService.chat(gatewayRequest);
|
|
2384
|
+
}
|
|
2385
|
+
complete(prompt, options) {
|
|
2386
|
+
const model = normalizeBanditModel(options.model);
|
|
2387
|
+
const gatewayRequest = {
|
|
2388
|
+
model,
|
|
2389
|
+
prompt,
|
|
2390
|
+
temperature: options.temperature,
|
|
2391
|
+
max_tokens: options.max_tokens,
|
|
2392
|
+
stream: options.stream,
|
|
2393
|
+
stop: options.stop,
|
|
2394
|
+
provider: "bandit"
|
|
2395
|
+
};
|
|
2396
|
+
debugLogger.debug("Bandit Gateway generate request", {
|
|
2397
|
+
model,
|
|
2398
|
+
promptLength: prompt.length,
|
|
2399
|
+
stream: options.stream
|
|
2400
|
+
});
|
|
2401
|
+
return this._gatewayService.generate(gatewayRequest);
|
|
2402
|
+
}
|
|
2403
|
+
listModels() {
|
|
2404
|
+
debugLogger.debug("Fetching Bandit models through gateway");
|
|
2405
|
+
return this._gatewayService.listModelsByProvider("bandit");
|
|
2406
|
+
}
|
|
2407
|
+
getHealth() {
|
|
2408
|
+
return this._gatewayService.getHealth().pipe(
|
|
2409
|
+
(0, import_operators5.map)((health) => ({
|
|
2410
|
+
...health,
|
|
2411
|
+
bandit_status: health.providers.find((p) => p.name === "bandit")?.status || "unavailable"
|
|
2412
|
+
}))
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
});
|
|
2418
|
+
|
|
2303
2419
|
// src/services/ai-provider/providers/gateway.provider.ts
|
|
2304
2420
|
var import_rxjs7, GatewayProvider;
|
|
2305
2421
|
var init_gateway_provider = __esm({
|
|
@@ -2313,6 +2429,7 @@ var init_gateway_provider = __esm({
|
|
|
2313
2429
|
init_azure_openai_gateway_service();
|
|
2314
2430
|
init_anthropic_gateway_service();
|
|
2315
2431
|
init_ollama_gateway_service();
|
|
2432
|
+
init_bandit_gateway_service();
|
|
2316
2433
|
GatewayProvider = class {
|
|
2317
2434
|
config;
|
|
2318
2435
|
gatewayService;
|
|
@@ -2354,6 +2471,9 @@ var init_gateway_provider = __esm({
|
|
|
2354
2471
|
case "anthropic":
|
|
2355
2472
|
this.providerSpecificService = new AnthropicGatewayService(gatewayUrl, tokenFactory);
|
|
2356
2473
|
break;
|
|
2474
|
+
case "bandit":
|
|
2475
|
+
this.providerSpecificService = new BanditAIGatewayService(gatewayUrl, tokenFactory);
|
|
2476
|
+
break;
|
|
2357
2477
|
case "ollama":
|
|
2358
2478
|
this.providerSpecificService = new OllamaGatewayService(gatewayUrl, tokenFactory);
|
|
2359
2479
|
break;
|
|
@@ -2368,6 +2488,16 @@ var init_gateway_provider = __esm({
|
|
|
2368
2488
|
role: msg.role,
|
|
2369
2489
|
content: msg.content
|
|
2370
2490
|
}));
|
|
2491
|
+
const normalizeImageUrl2 = (value) => {
|
|
2492
|
+
if (!value) {
|
|
2493
|
+
return value;
|
|
2494
|
+
}
|
|
2495
|
+
const trimmed = value.trim();
|
|
2496
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
2497
|
+
return trimmed;
|
|
2498
|
+
}
|
|
2499
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
2500
|
+
};
|
|
2371
2501
|
if (request.images && request.images.length > 0) {
|
|
2372
2502
|
const lastUserMessageIndex = messages.map((m) => m.role).lastIndexOf("user");
|
|
2373
2503
|
if (this.config.provider === "ollama") {
|
|
@@ -2377,7 +2507,7 @@ var init_gateway_provider = __esm({
|
|
|
2377
2507
|
images: request.images
|
|
2378
2508
|
};
|
|
2379
2509
|
}
|
|
2380
|
-
} else if (["openai", "azure-openai", "anthropic"].includes(this.config.provider || "")) {
|
|
2510
|
+
} else if (["openai", "azure-openai", "anthropic", "bandit"].includes(this.config.provider || "")) {
|
|
2381
2511
|
if (lastUserMessageIndex !== -1) {
|
|
2382
2512
|
const currentMessage = messages[lastUserMessageIndex];
|
|
2383
2513
|
const contentArray = [
|
|
@@ -2386,11 +2516,11 @@ var init_gateway_provider = __esm({
|
|
|
2386
2516
|
text: currentMessage.content
|
|
2387
2517
|
}
|
|
2388
2518
|
];
|
|
2389
|
-
request.images.forEach((
|
|
2519
|
+
request.images.forEach((imageRef) => {
|
|
2390
2520
|
contentArray.push({
|
|
2391
2521
|
type: "image_url",
|
|
2392
2522
|
image_url: {
|
|
2393
|
-
url:
|
|
2523
|
+
url: normalizeImageUrl2(imageRef),
|
|
2394
2524
|
detail: "auto"
|
|
2395
2525
|
}
|
|
2396
2526
|
});
|
|
@@ -2399,6 +2529,11 @@ var init_gateway_provider = __esm({
|
|
|
2399
2529
|
...messages[lastUserMessageIndex],
|
|
2400
2530
|
content: contentArray
|
|
2401
2531
|
};
|
|
2532
|
+
debugLogger.debug("Gateway provider injected image attachments", {
|
|
2533
|
+
provider: this.config.provider,
|
|
2534
|
+
imageCount: request.images.length,
|
|
2535
|
+
messageIndex: lastUserMessageIndex
|
|
2536
|
+
});
|
|
2402
2537
|
}
|
|
2403
2538
|
}
|
|
2404
2539
|
}
|
|
@@ -2907,6 +3042,244 @@ var init_xai_provider = __esm({
|
|
|
2907
3042
|
}
|
|
2908
3043
|
});
|
|
2909
3044
|
|
|
3045
|
+
// src/services/ai-provider/providers/bandit-ai.provider.ts
|
|
3046
|
+
var import_rxjs10, DEFAULT_BANDIT_BASE, normalizeImageUrl, injectImagesIntoMessages, BanditAIProvider;
|
|
3047
|
+
var init_bandit_ai_provider = __esm({
|
|
3048
|
+
"src/services/ai-provider/providers/bandit-ai.provider.ts"() {
|
|
3049
|
+
"use strict";
|
|
3050
|
+
import_rxjs10 = require("rxjs");
|
|
3051
|
+
init_common_types();
|
|
3052
|
+
init_debugLogger();
|
|
3053
|
+
DEFAULT_BANDIT_BASE = "https://api.burtson.ai";
|
|
3054
|
+
normalizeImageUrl = (value) => {
|
|
3055
|
+
if (!value) {
|
|
3056
|
+
return null;
|
|
3057
|
+
}
|
|
3058
|
+
const trimmed = value.trim();
|
|
3059
|
+
if (!trimmed) {
|
|
3060
|
+
return null;
|
|
3061
|
+
}
|
|
3062
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
3063
|
+
return trimmed;
|
|
3064
|
+
}
|
|
3065
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
3066
|
+
};
|
|
3067
|
+
injectImagesIntoMessages = (messages, images) => {
|
|
3068
|
+
const normalized = messages.map((message) => ({
|
|
3069
|
+
role: message.role,
|
|
3070
|
+
content: message.content
|
|
3071
|
+
}));
|
|
3072
|
+
if (!images || images.length === 0) {
|
|
3073
|
+
return normalized;
|
|
3074
|
+
}
|
|
3075
|
+
const normalizedImages = images.map(normalizeImageUrl).filter((url) => Boolean(url));
|
|
3076
|
+
if (normalizedImages.length === 0) {
|
|
3077
|
+
return normalized;
|
|
3078
|
+
}
|
|
3079
|
+
const lastUserIndex = normalized.map((msg) => msg.role).lastIndexOf("user");
|
|
3080
|
+
if (lastUserIndex === -1) {
|
|
3081
|
+
return normalized;
|
|
3082
|
+
}
|
|
3083
|
+
const target = normalized[lastUserIndex];
|
|
3084
|
+
const baseContent = typeof target.content === "string" && target.content.trim().length > 0 ? [
|
|
3085
|
+
{
|
|
3086
|
+
type: "text",
|
|
3087
|
+
text: target.content
|
|
3088
|
+
}
|
|
3089
|
+
] : [];
|
|
3090
|
+
const imageContent = normalizedImages.map((url) => ({
|
|
3091
|
+
type: "image_url",
|
|
3092
|
+
image_url: { url, detail: "auto" }
|
|
3093
|
+
}));
|
|
3094
|
+
normalized[lastUserIndex] = {
|
|
3095
|
+
role: target.role,
|
|
3096
|
+
content: [...baseContent, ...imageContent]
|
|
3097
|
+
};
|
|
3098
|
+
return normalized;
|
|
3099
|
+
};
|
|
3100
|
+
BanditAIProvider = class {
|
|
3101
|
+
config;
|
|
3102
|
+
baseUrl;
|
|
3103
|
+
constructor(config) {
|
|
3104
|
+
this.config = config;
|
|
3105
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BANDIT_BASE).replace(/\/$/, "");
|
|
3106
|
+
}
|
|
3107
|
+
chat(request) {
|
|
3108
|
+
const url = `${this.baseUrl}/chat/completions`;
|
|
3109
|
+
const messages = injectImagesIntoMessages(request.messages, request.images);
|
|
3110
|
+
const payload = {
|
|
3111
|
+
model: request.model,
|
|
3112
|
+
messages,
|
|
3113
|
+
stream: Boolean(request.stream),
|
|
3114
|
+
temperature: request.temperature,
|
|
3115
|
+
max_tokens: request.maxTokens
|
|
3116
|
+
};
|
|
3117
|
+
if (request.stream) {
|
|
3118
|
+
return this.streamChatRequest(url, payload);
|
|
3119
|
+
}
|
|
3120
|
+
return this.nonStreamChatRequest(url, payload);
|
|
3121
|
+
}
|
|
3122
|
+
generate(request) {
|
|
3123
|
+
const chatRequest = {
|
|
3124
|
+
model: request.model,
|
|
3125
|
+
messages: [{ role: "user", content: request.prompt }],
|
|
3126
|
+
stream: request.stream,
|
|
3127
|
+
options: request.options
|
|
3128
|
+
};
|
|
3129
|
+
return this.chat(chatRequest).pipe(
|
|
3130
|
+
(0, import_rxjs10.map)((response) => ({
|
|
3131
|
+
response: response.message.content,
|
|
3132
|
+
done: response.done
|
|
3133
|
+
}))
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
listModels() {
|
|
3137
|
+
const url = `${this.baseUrl}/models`;
|
|
3138
|
+
return (0, import_rxjs10.from)(fetch(url, { headers: this.getHeaders() })).pipe(
|
|
3139
|
+
(0, import_rxjs10.switchMap)((response) => {
|
|
3140
|
+
if (!response.ok) {
|
|
3141
|
+
debugLogger.error("BanditAI listModels failed", { status: response.status, url });
|
|
3142
|
+
return (0, import_rxjs10.throwError)(() => new Error(`Failed to list Bandit models: ${response.status}`));
|
|
3143
|
+
}
|
|
3144
|
+
return (0, import_rxjs10.from)(response.json());
|
|
3145
|
+
}),
|
|
3146
|
+
(0, import_rxjs10.map)(
|
|
3147
|
+
(data) => data.data.map((model) => ({
|
|
3148
|
+
name: model.id,
|
|
3149
|
+
details: {
|
|
3150
|
+
format: "bandit",
|
|
3151
|
+
family: model.object
|
|
3152
|
+
}
|
|
3153
|
+
}))
|
|
3154
|
+
)
|
|
3155
|
+
);
|
|
3156
|
+
}
|
|
3157
|
+
async validateServiceAvailability(args) {
|
|
3158
|
+
const attempt = async (url) => {
|
|
3159
|
+
try {
|
|
3160
|
+
const controller = new AbortController();
|
|
3161
|
+
const timeoutId = setTimeout(() => controller.abort(), args.timeoutMs);
|
|
3162
|
+
const response = await fetch(`${url}/models`, {
|
|
3163
|
+
headers: this.getHeaders(),
|
|
3164
|
+
signal: controller.signal
|
|
3165
|
+
});
|
|
3166
|
+
clearTimeout(timeoutId);
|
|
3167
|
+
return response.ok;
|
|
3168
|
+
} catch (error) {
|
|
3169
|
+
debugLogger.warn("BanditAI availability check failed", { url, error });
|
|
3170
|
+
return false;
|
|
3171
|
+
}
|
|
3172
|
+
};
|
|
3173
|
+
const primary = await attempt(this.baseUrl);
|
|
3174
|
+
if (primary) {
|
|
3175
|
+
return { url: this.baseUrl, isAvailable: true };
|
|
3176
|
+
}
|
|
3177
|
+
if (args.fallbackUrl) {
|
|
3178
|
+
const fallback = args.fallbackUrl.replace(/\/$/, "");
|
|
3179
|
+
if (await attempt(fallback)) {
|
|
3180
|
+
this.baseUrl = fallback;
|
|
3181
|
+
return { url: fallback, isAvailable: true };
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
return { url: this.baseUrl, isAvailable: false };
|
|
3185
|
+
}
|
|
3186
|
+
getProviderType() {
|
|
3187
|
+
return "bandit" /* BANDIT */;
|
|
3188
|
+
}
|
|
3189
|
+
getConfig() {
|
|
3190
|
+
return this.config;
|
|
3191
|
+
}
|
|
3192
|
+
streamChatRequest(url, payload) {
|
|
3193
|
+
return new import_rxjs10.Observable((observer) => {
|
|
3194
|
+
const task = fetch(url, {
|
|
3195
|
+
method: "POST",
|
|
3196
|
+
headers: {
|
|
3197
|
+
...this.getHeaders(),
|
|
3198
|
+
"Content-Type": "application/json"
|
|
3199
|
+
},
|
|
3200
|
+
body: JSON.stringify(payload)
|
|
3201
|
+
});
|
|
3202
|
+
task.then((response) => {
|
|
3203
|
+
if (!response.ok) {
|
|
3204
|
+
observer.error(new Error(`BanditAI request failed: ${response.status}`));
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
const reader = response.body?.getReader();
|
|
3208
|
+
const decoder = new TextDecoder();
|
|
3209
|
+
let buffer = "";
|
|
3210
|
+
const read = () => {
|
|
3211
|
+
reader?.read().then(({ done, value }) => {
|
|
3212
|
+
if (done) {
|
|
3213
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
3214
|
+
observer.complete();
|
|
3215
|
+
return;
|
|
3216
|
+
}
|
|
3217
|
+
buffer += decoder.decode(value, { stream: true });
|
|
3218
|
+
const lines = buffer.split("\n");
|
|
3219
|
+
buffer = lines.pop() ?? "";
|
|
3220
|
+
for (const rawLine of lines) {
|
|
3221
|
+
const line = rawLine.trim();
|
|
3222
|
+
if (!line.startsWith("data: ")) {
|
|
3223
|
+
continue;
|
|
3224
|
+
}
|
|
3225
|
+
const data = line.slice(6).trim();
|
|
3226
|
+
if (data === "[DONE]") {
|
|
3227
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
3228
|
+
observer.complete();
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
try {
|
|
3232
|
+
const parsed = JSON.parse(data);
|
|
3233
|
+
const content = parsed.choices?.[0]?.delta?.content ?? "";
|
|
3234
|
+
if (content) {
|
|
3235
|
+
observer.next({ message: { content, role: "assistant" }, done: false });
|
|
3236
|
+
}
|
|
3237
|
+
} catch (error) {
|
|
3238
|
+
debugLogger.error("BanditAI stream chunk parse failure", { data, error });
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
read();
|
|
3242
|
+
}).catch((err) => observer.error(err));
|
|
3243
|
+
};
|
|
3244
|
+
read();
|
|
3245
|
+
}).catch((err) => observer.error(err));
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
nonStreamChatRequest(url, payload) {
|
|
3249
|
+
return (0, import_rxjs10.from)(fetch(url, {
|
|
3250
|
+
method: "POST",
|
|
3251
|
+
headers: {
|
|
3252
|
+
...this.getHeaders(),
|
|
3253
|
+
"Content-Type": "application/json"
|
|
3254
|
+
},
|
|
3255
|
+
body: JSON.stringify(payload)
|
|
3256
|
+
})).pipe(
|
|
3257
|
+
(0, import_rxjs10.switchMap)((response) => {
|
|
3258
|
+
if (!response.ok) {
|
|
3259
|
+
return (0, import_rxjs10.throwError)(() => new Error(`BanditAI request failed: ${response.status}`));
|
|
3260
|
+
}
|
|
3261
|
+
return (0, import_rxjs10.from)(response.json());
|
|
3262
|
+
}),
|
|
3263
|
+
(0, import_rxjs10.map)((data) => ({
|
|
3264
|
+
message: {
|
|
3265
|
+
content: data.choices?.[0]?.message?.content ?? "",
|
|
3266
|
+
role: "assistant"
|
|
3267
|
+
},
|
|
3268
|
+
done: true
|
|
3269
|
+
}))
|
|
3270
|
+
);
|
|
3271
|
+
}
|
|
3272
|
+
getHeaders() {
|
|
3273
|
+
const headers = {};
|
|
3274
|
+
if (this.config.apiKey) {
|
|
3275
|
+
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
3276
|
+
}
|
|
3277
|
+
return headers;
|
|
3278
|
+
}
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
3282
|
+
|
|
2910
3283
|
// src/services/ai-provider/ai-provider.factory.ts
|
|
2911
3284
|
var AIProviderFactory;
|
|
2912
3285
|
var init_ai_provider_factory = __esm({
|
|
@@ -2920,6 +3293,7 @@ var init_ai_provider_factory = __esm({
|
|
|
2920
3293
|
init_gateway_provider();
|
|
2921
3294
|
init_playground_provider();
|
|
2922
3295
|
init_xai_provider();
|
|
3296
|
+
init_bandit_ai_provider();
|
|
2923
3297
|
AIProviderFactory = class {
|
|
2924
3298
|
static createProvider(config) {
|
|
2925
3299
|
switch (config.type) {
|
|
@@ -2933,6 +3307,8 @@ var init_ai_provider_factory = __esm({
|
|
|
2933
3307
|
return new AnthropicProvider(config);
|
|
2934
3308
|
case "xai" /* XAI */:
|
|
2935
3309
|
return new XAIProvider(config);
|
|
3310
|
+
case "bandit" /* BANDIT */:
|
|
3311
|
+
return new BanditAIProvider(config);
|
|
2936
3312
|
case "gateway" /* GATEWAY */:
|
|
2937
3313
|
return new GatewayProvider(config);
|
|
2938
3314
|
case "playground" /* PLAYGROUND */:
|
|
@@ -2947,6 +3323,7 @@ var init_ai_provider_factory = __esm({
|
|
|
2947
3323
|
"openai" /* OPENAI */,
|
|
2948
3324
|
"azure-openai" /* AZURE_OPENAI */,
|
|
2949
3325
|
"xai" /* XAI */,
|
|
3326
|
+
"bandit" /* BANDIT */,
|
|
2950
3327
|
"gateway" /* GATEWAY */,
|
|
2951
3328
|
"playground" /* PLAYGROUND */
|
|
2952
3329
|
];
|
|
@@ -2964,6 +3341,8 @@ var init_ai_provider_factory = __esm({
|
|
|
2964
3341
|
return !!config.apiKey;
|
|
2965
3342
|
case "xai" /* XAI */:
|
|
2966
3343
|
return !!config.apiKey;
|
|
3344
|
+
case "bandit" /* BANDIT */:
|
|
3345
|
+
return !!config.apiKey;
|
|
2967
3346
|
case "gateway" /* GATEWAY */:
|
|
2968
3347
|
return !!(config.gatewayUrl && config.provider);
|
|
2969
3348
|
case "playground" /* PLAYGROUND */:
|
|
@@ -4452,7 +4831,7 @@ var import_mammoth = __toESM(require("mammoth"));
|
|
|
4452
4831
|
var pdfjsLib = __toESM(require("pdfjs-dist/legacy/build/pdf"));
|
|
4453
4832
|
|
|
4454
4833
|
// src/services/prompts/conversationStarters.ts
|
|
4455
|
-
var
|
|
4834
|
+
var import_rxjs11 = require("rxjs");
|
|
4456
4835
|
init_aiProviderStore();
|
|
4457
4836
|
init_packageSettingsStore();
|
|
4458
4837
|
|
|
@@ -4611,19 +4990,19 @@ var NotificationService = class {
|
|
|
4611
4990
|
var notificationService = new NotificationService();
|
|
4612
4991
|
|
|
4613
4992
|
// src/services/prompts/moodDetection.ts
|
|
4614
|
-
var
|
|
4993
|
+
var import_rxjs12 = require("rxjs");
|
|
4615
4994
|
init_aiProviderStore();
|
|
4616
4995
|
init_packageSettingsStore();
|
|
4617
4996
|
init_debugLogger();
|
|
4618
4997
|
|
|
4619
4998
|
// src/services/prompts/detectUserInterestAndExcitement.ts
|
|
4620
|
-
var
|
|
4999
|
+
var import_rxjs13 = require("rxjs");
|
|
4621
5000
|
init_aiProviderStore();
|
|
4622
5001
|
init_packageSettingsStore();
|
|
4623
5002
|
init_debugLogger();
|
|
4624
5003
|
|
|
4625
5004
|
// src/services/prompts/documentSummarization.ts
|
|
4626
|
-
var
|
|
5005
|
+
var import_rxjs14 = require("rxjs");
|
|
4627
5006
|
init_aiProviderStore();
|
|
4628
5007
|
init_packageSettingsStore();
|
|
4629
5008
|
init_debugLogger();
|
|
@@ -4651,8 +5030,8 @@ ${content.slice(0, 4e3)}
|
|
|
4651
5030
|
stream: false,
|
|
4652
5031
|
options: { temperature: 0.3, num_predict: 100 }
|
|
4653
5032
|
});
|
|
4654
|
-
const summary$ = data$.pipe((0,
|
|
4655
|
-
const summary = await (0,
|
|
5033
|
+
const summary$ = data$.pipe((0, import_rxjs14.map)((d) => d.response.trim()));
|
|
5034
|
+
const summary = await (0, import_rxjs14.lastValueFrom)(summary$);
|
|
4656
5035
|
debugLogger.ragDebug("summarizeDocument result", { name, summary });
|
|
4657
5036
|
return summary || `Document summary for ${name}`;
|
|
4658
5037
|
} catch (error) {
|
|
@@ -4662,7 +5041,7 @@ ${content.slice(0, 4e3)}
|
|
|
4662
5041
|
};
|
|
4663
5042
|
|
|
4664
5043
|
// src/services/prompts/documentRelevance.ts
|
|
4665
|
-
var
|
|
5044
|
+
var import_rxjs15 = require("rxjs");
|
|
4666
5045
|
init_aiProviderStore();
|
|
4667
5046
|
init_packageSettingsStore();
|
|
4668
5047
|
init_debugLogger();
|
|
@@ -6986,13 +7365,17 @@ var useConversationStore = (0, import_zustand9.create)((set, get) => ({
|
|
|
6986
7365
|
const updatedConversations = conversations.map((c) => {
|
|
6987
7366
|
if (c.id === currentId && c.history.length > 0) {
|
|
6988
7367
|
const updatedHistory = [...c.history];
|
|
7368
|
+
const existingImages = updatedHistory[updatedHistory.length - 1].images;
|
|
7369
|
+
const nextImages = Array.isArray(images) && images.length > 0 ? [...images] : Array.isArray(existingImages) && existingImages.length > 0 ? [...existingImages] : existingImages;
|
|
6989
7370
|
updatedHistory[updatedHistory.length - 1] = {
|
|
6990
7371
|
...updatedHistory[updatedHistory.length - 1],
|
|
6991
7372
|
answer,
|
|
6992
7373
|
memoryUpdated,
|
|
6993
|
-
images:
|
|
7374
|
+
images: nextImages,
|
|
6994
7375
|
sourceFiles: sourceFiles ?? updatedHistory[updatedHistory.length - 1].sourceFiles,
|
|
6995
|
-
cancelled: cancelled ?? updatedHistory[updatedHistory.length - 1].cancelled
|
|
7376
|
+
cancelled: cancelled ?? updatedHistory[updatedHistory.length - 1].cancelled,
|
|
7377
|
+
placeholder: false,
|
|
7378
|
+
rawQuestion: void 0
|
|
6996
7379
|
};
|
|
6997
7380
|
return normalizeConversation({ ...c, history: updatedHistory, updatedAt: /* @__PURE__ */ new Date() });
|
|
6998
7381
|
}
|
|
@@ -7073,6 +7456,24 @@ var useConversationStore = (0, import_zustand9.create)((set, get) => ({
|
|
|
7073
7456
|
});
|
|
7074
7457
|
continue;
|
|
7075
7458
|
}
|
|
7459
|
+
if (Array.isArray(existing.history) && Array.isArray(conversation.history)) {
|
|
7460
|
+
const mergedHistory = conversation.history.map((incomingEntry, index) => {
|
|
7461
|
+
const existingEntry = existing.history[index];
|
|
7462
|
+
if (!existingEntry) {
|
|
7463
|
+
return incomingEntry;
|
|
7464
|
+
}
|
|
7465
|
+
const mergedImagesSource = Array.isArray(incomingEntry.images) && incomingEntry.images.length > 0 ? incomingEntry.images : existingEntry.images;
|
|
7466
|
+
const mergedImages = Array.isArray(mergedImagesSource) && mergedImagesSource.length > 0 ? [...mergedImagesSource] : mergedImagesSource;
|
|
7467
|
+
return {
|
|
7468
|
+
...existingEntry,
|
|
7469
|
+
...incomingEntry,
|
|
7470
|
+
images: mergedImages,
|
|
7471
|
+
placeholder: incomingEntry.placeholder ?? existingEntry.placeholder,
|
|
7472
|
+
rawQuestion: incomingEntry.rawQuestion ?? existingEntry.rawQuestion
|
|
7473
|
+
};
|
|
7474
|
+
});
|
|
7475
|
+
conversation.history = mergedHistory;
|
|
7476
|
+
}
|
|
7076
7477
|
}
|
|
7077
7478
|
next.set(conversation.id, conversation);
|
|
7078
7479
|
toPersist.push(conversation);
|
|
@@ -10790,12 +11191,12 @@ var voiceService = VoiceService.getInstance();
|
|
|
10790
11191
|
init_debugLogger();
|
|
10791
11192
|
|
|
10792
11193
|
// src/services/tts/streaming-tts.ts
|
|
10793
|
-
var
|
|
11194
|
+
var import_rxjs17 = require("rxjs");
|
|
10794
11195
|
init_debugLogger();
|
|
10795
11196
|
init_packageSettingsStore();
|
|
10796
11197
|
|
|
10797
11198
|
// src/services/tts/tts-client.ts
|
|
10798
|
-
var
|
|
11199
|
+
var import_rxjs16 = require("rxjs");
|
|
10799
11200
|
init_packageSettingsStore();
|
|
10800
11201
|
init_debugLogger();
|
|
10801
11202
|
var getOrAppendAuthHeader = (existing = {}) => {
|
|
@@ -10818,8 +11219,8 @@ var StreamingTTSClient = class _StreamingTTSClient {
|
|
|
10818
11219
|
// Store event handler references for proper cleanup
|
|
10819
11220
|
audioHandlers = /* @__PURE__ */ new Map();
|
|
10820
11221
|
// State management
|
|
10821
|
-
stateSubject = new
|
|
10822
|
-
progressSubject = new
|
|
11222
|
+
stateSubject = new import_rxjs17.BehaviorSubject("IDLE" /* IDLE */);
|
|
11223
|
+
progressSubject = new import_rxjs17.Subject();
|
|
10823
11224
|
constructor() {
|
|
10824
11225
|
}
|
|
10825
11226
|
static getInstance() {
|
|
@@ -10850,7 +11251,7 @@ var StreamingTTSClient = class _StreamingTTSClient {
|
|
|
10850
11251
|
* Speak text with simple streaming
|
|
10851
11252
|
*/
|
|
10852
11253
|
speakStream(text, voice, options = {}) {
|
|
10853
|
-
return new
|
|
11254
|
+
return new import_rxjs17.Observable((subscriber) => {
|
|
10854
11255
|
this.performSimpleStreaming(text, voice, options, subscriber);
|
|
10855
11256
|
});
|
|
10856
11257
|
}
|
|
@@ -14275,7 +14676,7 @@ var MemoryModal = ({ open, onClose }) => {
|
|
|
14275
14676
|
var memory_modal_default = MemoryModal;
|
|
14276
14677
|
|
|
14277
14678
|
// src/modals/chat-modal/chat-drawer.tsx
|
|
14278
|
-
var
|
|
14679
|
+
var import_rxjs18 = require("rxjs");
|
|
14279
14680
|
init_debugLogger();
|
|
14280
14681
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
14281
14682
|
var AIQueriesDrawer = ({ drawerOpen, onClose, onClearComplete, onNavigateToMain }) => {
|
|
@@ -14303,7 +14704,7 @@ var AIQueriesDrawer = ({ drawerOpen, onClose, onClearComplete, onNavigateToMain
|
|
|
14303
14704
|
const [memoryModalOpen, setMemoryModalOpen] = (0, import_react15.useState)(false);
|
|
14304
14705
|
const [contextMode, setContextMode] = (0, import_react15.useState)("local");
|
|
14305
14706
|
const [expandedSections, setExpandedSections] = (0, import_react15.useState)(/* @__PURE__ */ new Set(["history", "voice"]));
|
|
14306
|
-
const [audioSub, setAudioSub] = (0, import_react15.useState)(new
|
|
14707
|
+
const [audioSub, setAudioSub] = (0, import_react15.useState)(new import_rxjs18.Subscription());
|
|
14307
14708
|
const [isContextSwitching, setIsContextSwitching] = (0, import_react15.useState)(false);
|
|
14308
14709
|
const [isDrawerLoading, setIsDrawerLoading] = (0, import_react15.useState)(false);
|
|
14309
14710
|
(0, import_react15.useEffect)(() => {
|
|
@@ -19727,7 +20128,7 @@ var predefinedThemes = {
|
|
|
19727
20128
|
var themeMap_default = themeMap;
|
|
19728
20129
|
|
|
19729
20130
|
// src/modals/chat-modal/chat-modal.tsx
|
|
19730
|
-
var
|
|
20131
|
+
var import_rxjs19 = require("rxjs");
|
|
19731
20132
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
19732
20133
|
var FULL_SCREEN_THRESHOLD = 100;
|
|
19733
20134
|
var MIN_WINDOWED_HEIGHT = 400;
|
|
@@ -19796,7 +20197,7 @@ var ChatModal = ({
|
|
|
19796
20197
|
const [modalLogo, setModalLogo] = (0, import_react22.useState)("https://cdn.burtson.ai/logos/bandit-ai-logo.png");
|
|
19797
20198
|
const [modelAnchorEl, setModelAnchorEl] = (0, import_react22.useState)(null);
|
|
19798
20199
|
const [voiceAnchorEl, setVoiceAnchorEl] = (0, import_react22.useState)(null);
|
|
19799
|
-
const [audioSub, setAudioSub] = (0, import_react22.useState)(new
|
|
20200
|
+
const [audioSub, setAudioSub] = (0, import_react22.useState)(new import_rxjs19.Subscription());
|
|
19800
20201
|
const [selectedTheme, setSelectedTheme] = (0, import_react22.useState)(null);
|
|
19801
20202
|
const [themeLoading, setThemeLoading] = (0, import_react22.useState)(true);
|
|
19802
20203
|
const [autoFullscreenTriggered, setAutoFullscreenTriggered] = (0, import_react22.useState)(false);
|