@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.
Files changed (45) hide show
  1. package/dist/{aiProviderStore-XN7GCBHJ.mjs → aiProviderStore-JMA5RWX7.mjs} +2 -2
  2. package/dist/{chat-5QJNWB7I.mjs → chat-JMWPOSQ4.mjs} +5 -5
  3. package/dist/chat-provider.js +421 -20
  4. package/dist/chat-provider.js.map +1 -1
  5. package/dist/chat-provider.mjs +4 -4
  6. package/dist/{chunk-WO5KFNNW.mjs → chunk-26QQ4CLA.mjs} +62 -24
  7. package/dist/chunk-26QQ4CLA.mjs.map +1 -0
  8. package/dist/{chunk-CDQYBO3Q.mjs → chunk-2ZCR2TDY.mjs} +27 -5
  9. package/dist/chunk-2ZCR2TDY.mjs.map +1 -0
  10. package/dist/{chunk-ECRNIAG6.mjs → chunk-6ELNWXKC.mjs} +4 -4
  11. package/dist/{chunk-EOKIE5HZ.mjs → chunk-75W5VWPV.mjs} +3 -3
  12. package/dist/{chunk-JRCDANLN.mjs → chunk-7KEBNVCO.mjs} +67 -9
  13. package/dist/{chunk-JRCDANLN.mjs.map → chunk-7KEBNVCO.mjs.map} +1 -1
  14. package/dist/{chunk-3A2527TE.mjs → chunk-D3AGKOM6.mjs} +3 -3
  15. package/dist/{chunk-QU5S5QQP.mjs → chunk-QJYPWWA5.mjs} +379 -18
  16. package/dist/chunk-QJYPWWA5.mjs.map +1 -0
  17. package/dist/{chunk-QYH2T4L5.mjs → chunk-VIYBZO5W.mjs} +3 -3
  18. package/dist/{cli/cli.js → cli.js} +423 -10
  19. package/dist/cli.js.map +1 -0
  20. package/dist/{gateway-B0LJ3-jT.d.ts → gateway-5yt_3QDP.d.mts} +4 -4
  21. package/dist/{gateway-B0LJ3-jT.d.mts → gateway-5yt_3QDP.d.ts} +4 -4
  22. package/dist/index.d.mts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +598 -101
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +8 -8
  27. package/dist/management/management.js +596 -99
  28. package/dist/management/management.js.map +1 -1
  29. package/dist/management/management.mjs +6 -6
  30. package/dist/modals/chat-modal/chat-modal.js +430 -29
  31. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  32. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  33. package/dist/public-types.d.mts +1 -1
  34. package/dist/public-types.d.ts +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-CDQYBO3Q.mjs.map +0 -1
  37. package/dist/chunk-QU5S5QQP.mjs.map +0 -1
  38. package/dist/chunk-WO5KFNNW.mjs.map +0 -1
  39. package/dist/cli/cli.js.map +0 -1
  40. /package/dist/{aiProviderStore-XN7GCBHJ.mjs.map → aiProviderStore-JMA5RWX7.mjs.map} +0 -0
  41. /package/dist/{chat-5QJNWB7I.mjs.map → chat-JMWPOSQ4.mjs.map} +0 -0
  42. /package/dist/{chunk-ECRNIAG6.mjs.map → chunk-6ELNWXKC.mjs.map} +0 -0
  43. /package/dist/{chunk-EOKIE5HZ.mjs.map → chunk-75W5VWPV.mjs.map} +0 -0
  44. /package/dist/{chunk-3A2527TE.mjs.map → chunk-D3AGKOM6.mjs.map} +0 -0
  45. /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, from7, except, desc) => {
16
- if (from7 && typeof from7 === "object" || typeof from7 === "function") {
17
- for (let key of __getOwnPropNames(from7))
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: () => from7[key], enumerable: !(desc = __getOwnPropDesc(from7, key)) || desc.enumerable });
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: request.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
- debugLogger.debug(`Gateway generate request to ${url} with provider: ${request.provider || "default"}`);
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((base64Image) => {
2519
+ request.images.forEach((imageRef) => {
2390
2520
  contentArray.push({
2391
2521
  type: "image_url",
2392
2522
  image_url: {
2393
- url: base64Image.startsWith("data:") ? base64Image : `data:image/jpeg;base64,${base64Image}`,
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 import_rxjs10 = require("rxjs");
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 import_rxjs11 = require("rxjs");
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 import_rxjs12 = require("rxjs");
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 import_rxjs13 = require("rxjs");
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, import_rxjs13.map)((d) => d.response.trim()));
4655
- const summary = await (0, import_rxjs13.lastValueFrom)(summary$);
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 import_rxjs14 = require("rxjs");
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: images ?? updatedHistory[updatedHistory.length - 1].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 import_rxjs16 = require("rxjs");
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 import_rxjs15 = require("rxjs");
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 import_rxjs16.BehaviorSubject("IDLE" /* IDLE */);
10822
- progressSubject = new import_rxjs16.Subject();
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 import_rxjs16.Observable((subscriber) => {
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 import_rxjs17 = require("rxjs");
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 import_rxjs17.Subscription());
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 import_rxjs18 = require("rxjs");
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 import_rxjs18.Subscription());
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);