@burtson-labs/bandit-engine 2.0.40 → 2.0.42

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 (43) hide show
  1. package/README.md +14 -11
  2. package/dist/{aiProviderStore-JMA5RWX7.mjs → aiProviderStore-UQI33C5E.mjs} +2 -2
  3. package/dist/{chat-JMWPOSQ4.mjs → chat-XDC4SNJF.mjs} +5 -5
  4. package/dist/chat-provider.js +156 -106
  5. package/dist/chat-provider.js.map +1 -1
  6. package/dist/chat-provider.mjs +4 -4
  7. package/dist/{chunk-7KEBNVCO.mjs → chunk-4RCAVVDN.mjs} +15 -10
  8. package/dist/{chunk-7KEBNVCO.mjs.map → chunk-4RCAVVDN.mjs.map} +1 -1
  9. package/dist/{chunk-QJYPWWA5.mjs → chunk-54ZQ3FSN.mjs} +104 -61
  10. package/dist/chunk-54ZQ3FSN.mjs.map +1 -0
  11. package/dist/{chunk-26QQ4CLA.mjs → chunk-EOEI74X4.mjs} +4 -4
  12. package/dist/{chunk-6ELNWXKC.mjs → chunk-ERV7GLY3.mjs} +4 -4
  13. package/dist/{chunk-75W5VWPV.mjs → chunk-H4PBQ5LJ.mjs} +51 -46
  14. package/dist/chunk-H4PBQ5LJ.mjs.map +1 -0
  15. package/dist/{chunk-D3AGKOM6.mjs → chunk-KBKWVG7X.mjs} +3 -3
  16. package/dist/{chunk-VIYBZO5W.mjs → chunk-SBNENBUQ.mjs} +3 -3
  17. package/dist/{chunk-2ZCR2TDY.mjs → chunk-UXE67LR7.mjs} +8 -6
  18. package/dist/{chunk-2ZCR2TDY.mjs.map → chunk-UXE67LR7.mjs.map} +1 -1
  19. package/dist/cli.js +1 -1
  20. package/dist/cli.js.map +1 -1
  21. package/dist/index.js +164 -109
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +8 -8
  24. package/dist/management/management.js +164 -109
  25. package/dist/management/management.js.map +1 -1
  26. package/dist/management/management.mjs +6 -6
  27. package/dist/modals/chat-modal/chat-modal.js +108 -63
  28. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  29. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  30. package/docs/01_quickstart.md +10 -4
  31. package/docs/02_gateway_api.md +19 -3
  32. package/docs/03_provider_integration.md +5 -4
  33. package/docs/api_reference/media/02_gateway_api.md +19 -3
  34. package/docs/api_reference/media/README.md +3 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-75W5VWPV.mjs.map +0 -1
  37. package/dist/chunk-QJYPWWA5.mjs.map +0 -1
  38. /package/dist/{aiProviderStore-JMA5RWX7.mjs.map → aiProviderStore-UQI33C5E.mjs.map} +0 -0
  39. /package/dist/{chat-JMWPOSQ4.mjs.map → chat-XDC4SNJF.mjs.map} +0 -0
  40. /package/dist/{chunk-26QQ4CLA.mjs.map → chunk-EOEI74X4.mjs.map} +0 -0
  41. /package/dist/{chunk-6ELNWXKC.mjs.map → chunk-ERV7GLY3.mjs.map} +0 -0
  42. /package/dist/{chunk-D3AGKOM6.mjs.map → chunk-KBKWVG7X.mjs.map} +0 -0
  43. /package/dist/{chunk-VIYBZO5W.mjs.map → chunk-SBNENBUQ.mjs.map} +0 -0
@@ -1163,61 +1163,15 @@ var GatewayService = class {
1163
1163
  */
1164
1164
  chat(request) {
1165
1165
  const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
1166
- const url = `${this._baseUrl}${endpoint}`;
1166
+ const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
1167
1167
  const normalizedModel = request.provider === "bandit" ? (() => {
1168
1168
  const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
1169
1169
  return trimmed !== "" ? trimmed : "bandit-core-1";
1170
1170
  })() : request.model;
1171
- debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
1172
- model: normalizedModel,
1173
- messageCount: request.messages.length,
1174
- hasImages: !!(request.images && request.images.length > 0),
1175
- imageCount: request.images?.length || 0
1176
- });
1177
1171
  const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
1178
1172
  return new Observable6((observer) => {
1179
1173
  const controller = new AbortController();
1180
- const task = fetch(url, {
1181
- method: "POST",
1182
- headers: this._getHeaders(),
1183
- body: JSON.stringify(requestBody),
1184
- signal: controller.signal
1185
- });
1186
- task.then(async (response) => {
1187
- debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
1188
- if (!response.ok) {
1189
- let errorText = "";
1190
- let errorData = null;
1191
- try {
1192
- errorText = await response.text();
1193
- debugLogger.error("GatewayService chat error response body", {
1194
- status: response.status,
1195
- statusText: response.statusText,
1196
- url: response.url,
1197
- body: errorText
1198
- });
1199
- } catch (readError) {
1200
- debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
1201
- errorText = `Request failed with status ${response.status}`;
1202
- }
1203
- try {
1204
- errorData = JSON.parse(errorText);
1205
- debugLogger.error("GatewayService chat parsed error payload", errorData);
1206
- } catch (parseError) {
1207
- debugLogger.error("GatewayService chat error payload was not valid JSON");
1208
- errorData = { message: errorText };
1209
- }
1210
- const error = this._createHttpError(
1211
- `POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
1212
- {
1213
- status: response.status,
1214
- statusText: response.statusText ?? "",
1215
- data: errorData,
1216
- url
1217
- }
1218
- );
1219
- throw error;
1220
- }
1174
+ const handleStreamingResponse = async (response) => {
1221
1175
  const reader = response.body?.getReader();
1222
1176
  const decoder = new TextDecoder();
1223
1177
  let buffer = "";
@@ -1292,14 +1246,75 @@ var GatewayService = class {
1292
1246
  }).catch((err) => observer.error(err));
1293
1247
  };
1294
1248
  read();
1295
- }).catch((err) => {
1296
- debugLogger.error("GatewayService chat fetch error", {
1297
- error: err,
1298
- url,
1299
- provider: request.provider
1249
+ };
1250
+ const sendRequest = (targetEndpoint, allowFallback) => {
1251
+ const url = `${this._baseUrl}${targetEndpoint}`;
1252
+ debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
1253
+ model: normalizedModel,
1254
+ messageCount: request.messages.length,
1255
+ hasImages: !!(request.images && request.images.length > 0),
1256
+ imageCount: request.images?.length || 0
1300
1257
  });
1301
- observer.error(err);
1302
- });
1258
+ fetch(url, {
1259
+ method: "POST",
1260
+ headers: this._getHeaders(),
1261
+ body: JSON.stringify(requestBody),
1262
+ signal: controller.signal
1263
+ }).then(async (response) => {
1264
+ debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
1265
+ if (response.status === 404 && allowFallback && fallbackEndpoint) {
1266
+ debugLogger.warn("GatewayService chat endpoint returned 404, attempting fallback route", {
1267
+ provider: request.provider,
1268
+ attemptedEndpoint: targetEndpoint,
1269
+ fallbackEndpoint
1270
+ });
1271
+ sendRequest(fallbackEndpoint, false);
1272
+ return;
1273
+ }
1274
+ if (!response.ok) {
1275
+ let errorText = "";
1276
+ let errorData = null;
1277
+ try {
1278
+ errorText = await response.text();
1279
+ debugLogger.error("GatewayService chat error response body", {
1280
+ status: response.status,
1281
+ statusText: response.statusText,
1282
+ url: response.url,
1283
+ body: errorText
1284
+ });
1285
+ } catch (readError) {
1286
+ debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
1287
+ errorText = `Request failed with status ${response.status}`;
1288
+ }
1289
+ try {
1290
+ errorData = JSON.parse(errorText);
1291
+ debugLogger.error("GatewayService chat parsed error payload", errorData);
1292
+ } catch (parseError) {
1293
+ debugLogger.error("GatewayService chat error payload was not valid JSON");
1294
+ errorData = { message: errorText };
1295
+ }
1296
+ const error = this._createHttpError(
1297
+ `POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
1298
+ {
1299
+ status: response.status,
1300
+ statusText: response.statusText ?? "",
1301
+ data: errorData,
1302
+ url
1303
+ }
1304
+ );
1305
+ throw error;
1306
+ }
1307
+ await handleStreamingResponse(response);
1308
+ }).catch((err) => {
1309
+ debugLogger.error("GatewayService chat fetch error", {
1310
+ error: err,
1311
+ url,
1312
+ provider: request.provider
1313
+ });
1314
+ observer.error(err);
1315
+ });
1316
+ };
1317
+ sendRequest(endpoint, true);
1303
1318
  return () => {
1304
1319
  try {
1305
1320
  controller.abort();
@@ -1432,18 +1447,46 @@ var GatewayService = class {
1432
1447
  );
1433
1448
  }
1434
1449
  _getHeaders() {
1435
- const token = this._tokenFactory();
1450
+ const rawToken = this._tokenFactory();
1436
1451
  const headers = {
1437
1452
  "Content-Type": "application/json"
1438
1453
  };
1439
- if (token && token.trim() !== "") {
1440
- headers["Authorization"] = `Bearer ${token}`;
1441
- debugLogger.debug("Authorization header set with token");
1442
- } else {
1454
+ if (!rawToken) {
1443
1455
  debugLogger.warn("GatewayService: No token found, skipping Authorization header");
1456
+ return headers;
1444
1457
  }
1458
+ const token = rawToken.trim();
1459
+ if (token === "") {
1460
+ debugLogger.warn("GatewayService: Token factory returned empty string");
1461
+ return headers;
1462
+ }
1463
+ if (/^(Bearer|ApiKey)\s+/i.test(token)) {
1464
+ headers["Authorization"] = token;
1465
+ debugLogger.debug("GatewayService: Authorization header set with explicit scheme");
1466
+ return headers;
1467
+ }
1468
+ if (this._isLikelyBanditApiKey(token)) {
1469
+ headers["Authorization"] = `ApiKey ${token}`;
1470
+ headers["X-Burtson-Api-Key"] = token;
1471
+ debugLogger.debug("GatewayService: Authorization header set using API key");
1472
+ return headers;
1473
+ }
1474
+ if (this._isLikelyJwt(token)) {
1475
+ headers["Authorization"] = `Bearer ${token}`;
1476
+ debugLogger.debug("GatewayService: Authorization header set using bearer token");
1477
+ return headers;
1478
+ }
1479
+ headers["Authorization"] = `Bearer ${token}`;
1480
+ debugLogger.debug("GatewayService: Authorization header defaulted to bearer scheme");
1445
1481
  return headers;
1446
1482
  }
1483
+ _isLikelyJwt(token) {
1484
+ const segments = token.split(".");
1485
+ return segments.length === 3 && segments.every((segment) => segment.length > 0);
1486
+ }
1487
+ _isLikelyBanditApiKey(value) {
1488
+ return /^bai_[a-z0-9]{10,}$/i.test(value);
1489
+ }
1447
1490
  /**
1448
1491
  * Submit feedback to the gateway API
1449
1492
  */
@@ -2904,4 +2947,4 @@ export {
2904
2947
  AIProviderFactory,
2905
2948
  useAIProviderStore
2906
2949
  };
2907
- //# sourceMappingURL=chunk-QJYPWWA5.mjs.map
2950
+ //# sourceMappingURL=chunk-54ZQ3FSN.mjs.map