@burtson-labs/bandit-engine 2.0.40 → 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-JMA5RWX7.mjs → aiProviderStore-UQI33C5E.mjs} +2 -2
- package/dist/{chat-JMWPOSQ4.mjs → chat-T5ANWWYQ.mjs} +5 -5
- package/dist/chat-provider.js +151 -103
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +4 -4
- package/dist/{chunk-D3AGKOM6.mjs → chunk-22EY3ZDC.mjs} +3 -3
- package/dist/{chunk-6ELNWXKC.mjs → chunk-3E57HLDV.mjs} +4 -4
- package/dist/{chunk-QJYPWWA5.mjs → chunk-54ZQ3FSN.mjs} +104 -61
- package/dist/chunk-54ZQ3FSN.mjs.map +1 -0
- package/dist/{chunk-7KEBNVCO.mjs → chunk-A6OBEF72.mjs} +15 -10
- package/dist/{chunk-7KEBNVCO.mjs.map → chunk-A6OBEF72.mjs.map} +1 -1
- package/dist/{chunk-2ZCR2TDY.mjs → chunk-CX3INLYJ.mjs} +3 -3
- package/dist/{chunk-VIYBZO5W.mjs → chunk-LYWVYBKU.mjs} +3 -3
- package/dist/{chunk-26QQ4CLA.mjs → chunk-QFNEHSY4.mjs} +4 -4
- package/dist/{chunk-75W5VWPV.mjs → chunk-WPWWWUD7.mjs} +51 -46
- package/dist/chunk-WPWWWUD7.mjs.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.js +159 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/management/management.js +159 -106
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +6 -6
- package/dist/modals/chat-modal/chat-modal.js +103 -60
- package/dist/modals/chat-modal/chat-modal.js.map +1 -1
- package/dist/modals/chat-modal/chat-modal.mjs +4 -4
- 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-75W5VWPV.mjs.map +0 -1
- package/dist/chunk-QJYPWWA5.mjs.map +0 -1
- /package/dist/{aiProviderStore-JMA5RWX7.mjs.map → aiProviderStore-UQI33C5E.mjs.map} +0 -0
- /package/dist/{chat-JMWPOSQ4.mjs.map → chat-T5ANWWYQ.mjs.map} +0 -0
- /package/dist/{chunk-D3AGKOM6.mjs.map → chunk-22EY3ZDC.mjs.map} +0 -0
- /package/dist/{chunk-6ELNWXKC.mjs.map → chunk-3E57HLDV.mjs.map} +0 -0
- /package/dist/{chunk-2ZCR2TDY.mjs.map → chunk-CX3INLYJ.mjs.map} +0 -0
- /package/dist/{chunk-VIYBZO5W.mjs.map → chunk-LYWVYBKU.mjs.map} +0 -0
- /package/dist/{chunk-26QQ4CLA.mjs.map → chunk-QFNEHSY4.mjs.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -4468,61 +4468,15 @@ var init_gateway_service = __esm({
|
|
|
4468
4468
|
*/
|
|
4469
4469
|
chat(request) {
|
|
4470
4470
|
const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
|
|
4471
|
-
const
|
|
4471
|
+
const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
|
|
4472
4472
|
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
4473
4473
|
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
4474
4474
|
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
4475
4475
|
})() : request.model;
|
|
4476
|
-
debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
|
|
4477
|
-
model: normalizedModel,
|
|
4478
|
-
messageCount: request.messages.length,
|
|
4479
|
-
hasImages: !!(request.images && request.images.length > 0),
|
|
4480
|
-
imageCount: request.images?.length || 0
|
|
4481
|
-
});
|
|
4482
4476
|
const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
|
|
4483
4477
|
return new import_rxjs6.Observable((observer) => {
|
|
4484
4478
|
const controller = new AbortController();
|
|
4485
|
-
const
|
|
4486
|
-
method: "POST",
|
|
4487
|
-
headers: this._getHeaders(),
|
|
4488
|
-
body: JSON.stringify(requestBody),
|
|
4489
|
-
signal: controller.signal
|
|
4490
|
-
});
|
|
4491
|
-
task.then(async (response) => {
|
|
4492
|
-
debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
|
|
4493
|
-
if (!response.ok) {
|
|
4494
|
-
let errorText = "";
|
|
4495
|
-
let errorData = null;
|
|
4496
|
-
try {
|
|
4497
|
-
errorText = await response.text();
|
|
4498
|
-
debugLogger.error("GatewayService chat error response body", {
|
|
4499
|
-
status: response.status,
|
|
4500
|
-
statusText: response.statusText,
|
|
4501
|
-
url: response.url,
|
|
4502
|
-
body: errorText
|
|
4503
|
-
});
|
|
4504
|
-
} catch (readError) {
|
|
4505
|
-
debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
|
|
4506
|
-
errorText = `Request failed with status ${response.status}`;
|
|
4507
|
-
}
|
|
4508
|
-
try {
|
|
4509
|
-
errorData = JSON.parse(errorText);
|
|
4510
|
-
debugLogger.error("GatewayService chat parsed error payload", errorData);
|
|
4511
|
-
} catch (parseError) {
|
|
4512
|
-
debugLogger.error("GatewayService chat error payload was not valid JSON");
|
|
4513
|
-
errorData = { message: errorText };
|
|
4514
|
-
}
|
|
4515
|
-
const error = this._createHttpError(
|
|
4516
|
-
`POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
|
|
4517
|
-
{
|
|
4518
|
-
status: response.status,
|
|
4519
|
-
statusText: response.statusText ?? "",
|
|
4520
|
-
data: errorData,
|
|
4521
|
-
url
|
|
4522
|
-
}
|
|
4523
|
-
);
|
|
4524
|
-
throw error;
|
|
4525
|
-
}
|
|
4479
|
+
const handleStreamingResponse = async (response) => {
|
|
4526
4480
|
const reader = response.body?.getReader();
|
|
4527
4481
|
const decoder = new TextDecoder();
|
|
4528
4482
|
let buffer = "";
|
|
@@ -4597,14 +4551,75 @@ var init_gateway_service = __esm({
|
|
|
4597
4551
|
}).catch((err) => observer.error(err));
|
|
4598
4552
|
};
|
|
4599
4553
|
read();
|
|
4600
|
-
}
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4554
|
+
};
|
|
4555
|
+
const sendRequest = (targetEndpoint, allowFallback) => {
|
|
4556
|
+
const url = `${this._baseUrl}${targetEndpoint}`;
|
|
4557
|
+
debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
|
|
4558
|
+
model: normalizedModel,
|
|
4559
|
+
messageCount: request.messages.length,
|
|
4560
|
+
hasImages: !!(request.images && request.images.length > 0),
|
|
4561
|
+
imageCount: request.images?.length || 0
|
|
4605
4562
|
});
|
|
4606
|
-
|
|
4607
|
-
|
|
4563
|
+
fetch(url, {
|
|
4564
|
+
method: "POST",
|
|
4565
|
+
headers: this._getHeaders(),
|
|
4566
|
+
body: JSON.stringify(requestBody),
|
|
4567
|
+
signal: controller.signal
|
|
4568
|
+
}).then(async (response) => {
|
|
4569
|
+
debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
|
|
4570
|
+
if (response.status === 404 && allowFallback && fallbackEndpoint) {
|
|
4571
|
+
debugLogger.warn("GatewayService chat endpoint returned 404, attempting fallback route", {
|
|
4572
|
+
provider: request.provider,
|
|
4573
|
+
attemptedEndpoint: targetEndpoint,
|
|
4574
|
+
fallbackEndpoint
|
|
4575
|
+
});
|
|
4576
|
+
sendRequest(fallbackEndpoint, false);
|
|
4577
|
+
return;
|
|
4578
|
+
}
|
|
4579
|
+
if (!response.ok) {
|
|
4580
|
+
let errorText = "";
|
|
4581
|
+
let errorData = null;
|
|
4582
|
+
try {
|
|
4583
|
+
errorText = await response.text();
|
|
4584
|
+
debugLogger.error("GatewayService chat error response body", {
|
|
4585
|
+
status: response.status,
|
|
4586
|
+
statusText: response.statusText,
|
|
4587
|
+
url: response.url,
|
|
4588
|
+
body: errorText
|
|
4589
|
+
});
|
|
4590
|
+
} catch (readError) {
|
|
4591
|
+
debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
|
|
4592
|
+
errorText = `Request failed with status ${response.status}`;
|
|
4593
|
+
}
|
|
4594
|
+
try {
|
|
4595
|
+
errorData = JSON.parse(errorText);
|
|
4596
|
+
debugLogger.error("GatewayService chat parsed error payload", errorData);
|
|
4597
|
+
} catch (parseError) {
|
|
4598
|
+
debugLogger.error("GatewayService chat error payload was not valid JSON");
|
|
4599
|
+
errorData = { message: errorText };
|
|
4600
|
+
}
|
|
4601
|
+
const error = this._createHttpError(
|
|
4602
|
+
`POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
|
|
4603
|
+
{
|
|
4604
|
+
status: response.status,
|
|
4605
|
+
statusText: response.statusText ?? "",
|
|
4606
|
+
data: errorData,
|
|
4607
|
+
url
|
|
4608
|
+
}
|
|
4609
|
+
);
|
|
4610
|
+
throw error;
|
|
4611
|
+
}
|
|
4612
|
+
await handleStreamingResponse(response);
|
|
4613
|
+
}).catch((err) => {
|
|
4614
|
+
debugLogger.error("GatewayService chat fetch error", {
|
|
4615
|
+
error: err,
|
|
4616
|
+
url,
|
|
4617
|
+
provider: request.provider
|
|
4618
|
+
});
|
|
4619
|
+
observer.error(err);
|
|
4620
|
+
});
|
|
4621
|
+
};
|
|
4622
|
+
sendRequest(endpoint, true);
|
|
4608
4623
|
return () => {
|
|
4609
4624
|
try {
|
|
4610
4625
|
controller.abort();
|
|
@@ -4737,18 +4752,46 @@ var init_gateway_service = __esm({
|
|
|
4737
4752
|
);
|
|
4738
4753
|
}
|
|
4739
4754
|
_getHeaders() {
|
|
4740
|
-
const
|
|
4755
|
+
const rawToken2 = this._tokenFactory();
|
|
4741
4756
|
const headers = {
|
|
4742
4757
|
"Content-Type": "application/json"
|
|
4743
4758
|
};
|
|
4744
|
-
if (
|
|
4745
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
4746
|
-
debugLogger.debug("Authorization header set with token");
|
|
4747
|
-
} else {
|
|
4759
|
+
if (!rawToken2) {
|
|
4748
4760
|
debugLogger.warn("GatewayService: No token found, skipping Authorization header");
|
|
4761
|
+
return headers;
|
|
4762
|
+
}
|
|
4763
|
+
const token = rawToken2.trim();
|
|
4764
|
+
if (token === "") {
|
|
4765
|
+
debugLogger.warn("GatewayService: Token factory returned empty string");
|
|
4766
|
+
return headers;
|
|
4767
|
+
}
|
|
4768
|
+
if (/^(Bearer|ApiKey)\s+/i.test(token)) {
|
|
4769
|
+
headers["Authorization"] = token;
|
|
4770
|
+
debugLogger.debug("GatewayService: Authorization header set with explicit scheme");
|
|
4771
|
+
return headers;
|
|
4772
|
+
}
|
|
4773
|
+
if (this._isLikelyBanditApiKey(token)) {
|
|
4774
|
+
headers["Authorization"] = `ApiKey ${token}`;
|
|
4775
|
+
headers["X-Burtson-Api-Key"] = token;
|
|
4776
|
+
debugLogger.debug("GatewayService: Authorization header set using API key");
|
|
4777
|
+
return headers;
|
|
4749
4778
|
}
|
|
4779
|
+
if (this._isLikelyJwt(token)) {
|
|
4780
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
4781
|
+
debugLogger.debug("GatewayService: Authorization header set using bearer token");
|
|
4782
|
+
return headers;
|
|
4783
|
+
}
|
|
4784
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
4785
|
+
debugLogger.debug("GatewayService: Authorization header defaulted to bearer scheme");
|
|
4750
4786
|
return headers;
|
|
4751
4787
|
}
|
|
4788
|
+
_isLikelyJwt(token) {
|
|
4789
|
+
const segments = token.split(".");
|
|
4790
|
+
return segments.length === 3 && segments.every((segment) => segment.length > 0);
|
|
4791
|
+
}
|
|
4792
|
+
_isLikelyBanditApiKey(value) {
|
|
4793
|
+
return /^bai_[a-z0-9]{10,}$/i.test(value);
|
|
4794
|
+
}
|
|
4752
4795
|
/**
|
|
4753
4796
|
* Submit feedback to the gateway API
|
|
4754
4797
|
*/
|
|
@@ -29268,26 +29311,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
29268
29311
|
if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
|
|
29269
29312
|
providerConfig = this.convertAnthropicConfig(providerConfig, settings?.gatewayApiUrl);
|
|
29270
29313
|
}
|
|
29271
|
-
|
|
29272
|
-
providerConfig.tokenFactory = () => {
|
|
29273
|
-
let token = authenticationService.getToken();
|
|
29274
|
-
if (!token) {
|
|
29275
|
-
token = localStorage.getItem("authToken");
|
|
29276
|
-
}
|
|
29277
|
-
if (!token) {
|
|
29278
|
-
try {
|
|
29279
|
-
const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
|
|
29280
|
-
const authStore = useAuthenticationStore2.getState();
|
|
29281
|
-
token = authStore.token;
|
|
29282
|
-
} catch (e) {
|
|
29283
|
-
}
|
|
29284
|
-
}
|
|
29285
|
-
debugLogger.info("AI Provider Init: IndexedDB config token factory", {
|
|
29286
|
-
hasToken: !!token
|
|
29287
|
-
});
|
|
29288
|
-
return token;
|
|
29289
|
-
};
|
|
29290
|
-
}
|
|
29314
|
+
providerConfig = this.ensureTokenFactory(providerConfig);
|
|
29291
29315
|
try {
|
|
29292
29316
|
const { createProvider } = useAIProviderStore.getState();
|
|
29293
29317
|
createProvider(providerConfig);
|
|
@@ -29315,27 +29339,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
29315
29339
|
if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
|
|
29316
29340
|
providerConfig = this.convertAnthropicConfig(providerConfig, settings.gatewayApiUrl);
|
|
29317
29341
|
}
|
|
29318
|
-
|
|
29319
|
-
providerConfig.tokenFactory = () => {
|
|
29320
|
-
let token = authenticationService.getToken();
|
|
29321
|
-
if (!token) {
|
|
29322
|
-
token = localStorage.getItem("authToken");
|
|
29323
|
-
}
|
|
29324
|
-
if (!token) {
|
|
29325
|
-
try {
|
|
29326
|
-
const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
|
|
29327
|
-
const authStore = useAuthenticationStore2.getState();
|
|
29328
|
-
token = authStore.token;
|
|
29329
|
-
} catch (e) {
|
|
29330
|
-
}
|
|
29331
|
-
}
|
|
29332
|
-
debugLogger.info("AIProviderInit: Explicit config tokenFactory", {
|
|
29333
|
-
hasToken: !!token,
|
|
29334
|
-
localStorage: !!localStorage.getItem("authToken")
|
|
29335
|
-
});
|
|
29336
|
-
return token;
|
|
29337
|
-
};
|
|
29338
|
-
}
|
|
29342
|
+
providerConfig = this.ensureTokenFactory(providerConfig);
|
|
29339
29343
|
debugLogger.info("Using explicit AI provider config", providerConfig);
|
|
29340
29344
|
} else {
|
|
29341
29345
|
providerConfig = {
|
|
@@ -29447,9 +29451,10 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
29447
29451
|
*/
|
|
29448
29452
|
switchProvider(config) {
|
|
29449
29453
|
try {
|
|
29454
|
+
const normalizedConfig = this.ensureTokenFactory({ ...config });
|
|
29450
29455
|
const { switchProvider } = useAIProviderStore.getState();
|
|
29451
|
-
switchProvider(
|
|
29452
|
-
debugLogger.info(`Switched to AI provider: ${
|
|
29456
|
+
switchProvider(normalizedConfig);
|
|
29457
|
+
debugLogger.info(`Switched to AI provider: ${normalizedConfig.type}`);
|
|
29453
29458
|
} catch (error) {
|
|
29454
29459
|
debugLogger.error("Failed to switch AI provider:", { error });
|
|
29455
29460
|
throw error;
|
|
@@ -29483,6 +29488,49 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
29483
29488
|
debugLogger.info("AI Provider Init: Converted direct Anthropic provider to gateway configuration");
|
|
29484
29489
|
return normalized;
|
|
29485
29490
|
}
|
|
29491
|
+
/**
|
|
29492
|
+
* Ensure providers that require auth have a token factory configured.
|
|
29493
|
+
* Handles both UI auth tokens and API key scenarios.
|
|
29494
|
+
*/
|
|
29495
|
+
ensureTokenFactory(config) {
|
|
29496
|
+
if (config.type === "ollama" /* OLLAMA */ || config.type === "gateway" /* GATEWAY */) {
|
|
29497
|
+
const existingFactory = config.tokenFactory;
|
|
29498
|
+
if (existingFactory) {
|
|
29499
|
+
return config;
|
|
29500
|
+
}
|
|
29501
|
+
if (typeof config.apiKey === "string" && config.apiKey.trim() !== "") {
|
|
29502
|
+
const key = config.apiKey.trim();
|
|
29503
|
+
config.tokenFactory = () => key;
|
|
29504
|
+
debugLogger.info("AIProviderInit: Using API key for token factory", {
|
|
29505
|
+
type: config.type,
|
|
29506
|
+
hasKey: true
|
|
29507
|
+
});
|
|
29508
|
+
return config;
|
|
29509
|
+
}
|
|
29510
|
+
config.tokenFactory = () => {
|
|
29511
|
+
let token = authenticationService.getToken();
|
|
29512
|
+
if (!token && typeof localStorage !== "undefined") {
|
|
29513
|
+
try {
|
|
29514
|
+
token = localStorage.getItem("authToken");
|
|
29515
|
+
} catch {
|
|
29516
|
+
}
|
|
29517
|
+
}
|
|
29518
|
+
if (!token) {
|
|
29519
|
+
try {
|
|
29520
|
+
const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
|
|
29521
|
+
const authStore = useAuthenticationStore2.getState();
|
|
29522
|
+
token = authStore.token;
|
|
29523
|
+
} catch {
|
|
29524
|
+
}
|
|
29525
|
+
}
|
|
29526
|
+
debugLogger.info("AIProviderInit: Token factory resolved auth token", {
|
|
29527
|
+
hasToken: !!token
|
|
29528
|
+
});
|
|
29529
|
+
return token;
|
|
29530
|
+
};
|
|
29531
|
+
}
|
|
29532
|
+
return config;
|
|
29533
|
+
}
|
|
29486
29534
|
};
|
|
29487
29535
|
var aiProviderInitService = AIProviderInitService.getInstance();
|
|
29488
29536
|
|
|
@@ -39186,11 +39234,16 @@ var ProviderTab = () => {
|
|
|
39186
39234
|
const trimmed = sanitized.defaultModel.trim();
|
|
39187
39235
|
sanitized.defaultModel = trimmed || void 0;
|
|
39188
39236
|
}
|
|
39237
|
+
if (typeof sanitized.apiKey === "string") {
|
|
39238
|
+
const trimmedKey = sanitized.apiKey.trim();
|
|
39239
|
+
sanitized.apiKey = trimmedKey || void 0;
|
|
39240
|
+
}
|
|
39189
39241
|
return sanitized;
|
|
39190
39242
|
}, []);
|
|
39191
39243
|
const [providerConfig, setProviderConfig] = (0, import_react53.useState)({
|
|
39192
|
-
type: "
|
|
39193
|
-
|
|
39244
|
+
type: "gateway",
|
|
39245
|
+
gatewayUrl: packageSettings?.gatewayApiUrl || "",
|
|
39246
|
+
provider: "bandit"
|
|
39194
39247
|
});
|
|
39195
39248
|
const [isProviderConfigOpen, setIsProviderConfigOpen] = (0, import_react53.useState)(false);
|
|
39196
39249
|
const [snackbarMessage, setSnackbarMessage] = (0, import_react53.useState)("");
|
|
@@ -39326,7 +39379,7 @@ var ProviderTab = () => {
|
|
|
39326
39379
|
setProviderConfig(applyDefaultModel({
|
|
39327
39380
|
...baseConfig,
|
|
39328
39381
|
gatewayUrl: packageSettings?.gatewayApiUrl || "",
|
|
39329
|
-
provider: "
|
|
39382
|
+
provider: "bandit"
|
|
39330
39383
|
}));
|
|
39331
39384
|
break;
|
|
39332
39385
|
case "playground" /* PLAYGROUND */:
|