@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
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-ONQMRE2G.mjs";
|
|
4
4
|
import {
|
|
5
5
|
aiProviderInitService
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-75W5VWPV.mjs";
|
|
7
7
|
import {
|
|
8
8
|
useMCPToolsStore
|
|
9
9
|
} from "./chunk-RTQDQ6TC.mjs";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
useKnowledgeStore2,
|
|
21
21
|
useMemoryStore,
|
|
22
22
|
useProjectStore
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-2ZCR2TDY.mjs";
|
|
24
24
|
import {
|
|
25
25
|
indexedDBService_default,
|
|
26
26
|
useModelStore,
|
|
@@ -157,4 +157,4 @@ export {
|
|
|
157
157
|
ChatProvider,
|
|
158
158
|
chat_provider_default
|
|
159
159
|
};
|
|
160
|
-
//# sourceMappingURL=chunk-
|
|
160
|
+
//# sourceMappingURL=chunk-D3AGKOM6.mjs.map
|
|
@@ -1015,7 +1015,7 @@ var AnthropicProvider = class {
|
|
|
1015
1015
|
};
|
|
1016
1016
|
|
|
1017
1017
|
// src/services/ai-provider/providers/gateway.provider.ts
|
|
1018
|
-
import { map as
|
|
1018
|
+
import { map as map12 } from "rxjs";
|
|
1019
1019
|
|
|
1020
1020
|
// src/services/gateway/gateway.service.ts
|
|
1021
1021
|
import axios, { AxiosHeaders } from "axios";
|
|
@@ -1164,13 +1164,17 @@ var GatewayService = class {
|
|
|
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
1166
|
const url = `${this._baseUrl}${endpoint}`;
|
|
1167
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1168
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1169
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1170
|
+
})() : request.model;
|
|
1167
1171
|
debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1168
|
-
model:
|
|
1172
|
+
model: normalizedModel,
|
|
1169
1173
|
messageCount: request.messages.length,
|
|
1170
1174
|
hasImages: !!(request.images && request.images.length > 0),
|
|
1171
1175
|
imageCount: request.images?.length || 0
|
|
1172
1176
|
});
|
|
1173
|
-
const requestBody = { ...request, stream: request.stream !== false };
|
|
1177
|
+
const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
|
|
1174
1178
|
return new Observable6((observer) => {
|
|
1175
1179
|
const controller = new AbortController();
|
|
1176
1180
|
const task = fetch(url, {
|
|
@@ -1310,12 +1314,18 @@ var GatewayService = class {
|
|
|
1310
1314
|
generate(request) {
|
|
1311
1315
|
const endpoint = request.provider ? `/api/${request.provider}/generate` : "/api/generate";
|
|
1312
1316
|
const url = `${this._baseUrl}${endpoint}`;
|
|
1313
|
-
|
|
1317
|
+
const normalizedModel = request.provider === "bandit" ? (() => {
|
|
1318
|
+
const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
|
|
1319
|
+
return trimmed !== "" ? trimmed : "bandit-core-1";
|
|
1320
|
+
})() : request.model;
|
|
1321
|
+
debugLogger.debug(`Gateway generate request to ${url} with provider: ${request.provider || "default"}`, {
|
|
1322
|
+
model: normalizedModel
|
|
1323
|
+
});
|
|
1314
1324
|
return new Observable6((observer) => {
|
|
1315
1325
|
const task = fetch(url, {
|
|
1316
1326
|
method: "POST",
|
|
1317
1327
|
headers: this._getHeaders(),
|
|
1318
|
-
body: JSON.stringify({ ...request, stream: request.stream !== false })
|
|
1328
|
+
body: JSON.stringify({ ...request, model: normalizedModel, stream: request.stream !== false })
|
|
1319
1329
|
});
|
|
1320
1330
|
task.then(async (response) => {
|
|
1321
1331
|
if (!response.ok) {
|
|
@@ -1879,6 +1889,104 @@ var OllamaGatewayService = class {
|
|
|
1879
1889
|
}
|
|
1880
1890
|
};
|
|
1881
1891
|
|
|
1892
|
+
// src/services/gateway/bandit-gateway.service.ts
|
|
1893
|
+
import { map as map11 } from "rxjs/operators";
|
|
1894
|
+
var normalizeBanditModel = (model) => {
|
|
1895
|
+
if (typeof model !== "string" || model.trim() === "") {
|
|
1896
|
+
return "bandit-core-1";
|
|
1897
|
+
}
|
|
1898
|
+
const normalized = model.replace(/^bandit:/, "").trim();
|
|
1899
|
+
return normalized === "" ? "bandit-core-1" : normalized;
|
|
1900
|
+
};
|
|
1901
|
+
var isGatewayMessageContent = (value) => {
|
|
1902
|
+
if (!value || typeof value !== "object") return false;
|
|
1903
|
+
const candidate = value;
|
|
1904
|
+
if (candidate.type !== "text" && candidate.type !== "image_url") {
|
|
1905
|
+
return false;
|
|
1906
|
+
}
|
|
1907
|
+
if (candidate.type === "text") {
|
|
1908
|
+
return typeof candidate.text === "string";
|
|
1909
|
+
}
|
|
1910
|
+
if (candidate.type === "image_url") {
|
|
1911
|
+
return !!candidate.image_url && typeof candidate.image_url.url === "string";
|
|
1912
|
+
}
|
|
1913
|
+
return false;
|
|
1914
|
+
};
|
|
1915
|
+
var normalizeBanditMessages = (messages) => messages.map((message) => {
|
|
1916
|
+
const content = message.content;
|
|
1917
|
+
if (typeof content === "string") {
|
|
1918
|
+
return { role: message.role, content };
|
|
1919
|
+
}
|
|
1920
|
+
if (Array.isArray(content)) {
|
|
1921
|
+
const filtered = content.filter(isGatewayMessageContent);
|
|
1922
|
+
if (filtered.length === 0) {
|
|
1923
|
+
return { role: message.role, content: JSON.stringify(content) };
|
|
1924
|
+
}
|
|
1925
|
+
return {
|
|
1926
|
+
role: message.role,
|
|
1927
|
+
content: filtered
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
return { role: message.role, content: content != null ? String(content) : "" };
|
|
1931
|
+
});
|
|
1932
|
+
var BanditAIGatewayService = class {
|
|
1933
|
+
_gatewayService;
|
|
1934
|
+
constructor(gatewayUrl, tokenFactory) {
|
|
1935
|
+
this._gatewayService = new GatewayService(gatewayUrl, tokenFactory);
|
|
1936
|
+
debugLogger.info("BanditAIGatewayService initialized", { gatewayUrl });
|
|
1937
|
+
}
|
|
1938
|
+
async validateServiceAvailability(args) {
|
|
1939
|
+
return this._gatewayService.validateServiceAvailability(args);
|
|
1940
|
+
}
|
|
1941
|
+
chat(request) {
|
|
1942
|
+
const model = normalizeBanditModel(request.model);
|
|
1943
|
+
const messages = normalizeBanditMessages(request.messages);
|
|
1944
|
+
const gatewayRequest = {
|
|
1945
|
+
...request,
|
|
1946
|
+
messages,
|
|
1947
|
+
model,
|
|
1948
|
+
provider: "bandit",
|
|
1949
|
+
stream: request.stream
|
|
1950
|
+
};
|
|
1951
|
+
debugLogger.debug("Bandit Gateway chat request", {
|
|
1952
|
+
model,
|
|
1953
|
+
messageCount: request.messages.length,
|
|
1954
|
+
stream: request.stream
|
|
1955
|
+
});
|
|
1956
|
+
return this._gatewayService.chat(gatewayRequest);
|
|
1957
|
+
}
|
|
1958
|
+
complete(prompt, options) {
|
|
1959
|
+
const model = normalizeBanditModel(options.model);
|
|
1960
|
+
const gatewayRequest = {
|
|
1961
|
+
model,
|
|
1962
|
+
prompt,
|
|
1963
|
+
temperature: options.temperature,
|
|
1964
|
+
max_tokens: options.max_tokens,
|
|
1965
|
+
stream: options.stream,
|
|
1966
|
+
stop: options.stop,
|
|
1967
|
+
provider: "bandit"
|
|
1968
|
+
};
|
|
1969
|
+
debugLogger.debug("Bandit Gateway generate request", {
|
|
1970
|
+
model,
|
|
1971
|
+
promptLength: prompt.length,
|
|
1972
|
+
stream: options.stream
|
|
1973
|
+
});
|
|
1974
|
+
return this._gatewayService.generate(gatewayRequest);
|
|
1975
|
+
}
|
|
1976
|
+
listModels() {
|
|
1977
|
+
debugLogger.debug("Fetching Bandit models through gateway");
|
|
1978
|
+
return this._gatewayService.listModelsByProvider("bandit");
|
|
1979
|
+
}
|
|
1980
|
+
getHealth() {
|
|
1981
|
+
return this._gatewayService.getHealth().pipe(
|
|
1982
|
+
map11((health) => ({
|
|
1983
|
+
...health,
|
|
1984
|
+
bandit_status: health.providers.find((p) => p.name === "bandit")?.status || "unavailable"
|
|
1985
|
+
}))
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
|
|
1882
1990
|
// src/services/ai-provider/providers/gateway.provider.ts
|
|
1883
1991
|
var GatewayProvider = class {
|
|
1884
1992
|
config;
|
|
@@ -1921,6 +2029,9 @@ var GatewayProvider = class {
|
|
|
1921
2029
|
case "anthropic":
|
|
1922
2030
|
this.providerSpecificService = new AnthropicGatewayService(gatewayUrl, tokenFactory);
|
|
1923
2031
|
break;
|
|
2032
|
+
case "bandit":
|
|
2033
|
+
this.providerSpecificService = new BanditAIGatewayService(gatewayUrl, tokenFactory);
|
|
2034
|
+
break;
|
|
1924
2035
|
case "ollama":
|
|
1925
2036
|
this.providerSpecificService = new OllamaGatewayService(gatewayUrl, tokenFactory);
|
|
1926
2037
|
break;
|
|
@@ -1935,6 +2046,16 @@ var GatewayProvider = class {
|
|
|
1935
2046
|
role: msg.role,
|
|
1936
2047
|
content: msg.content
|
|
1937
2048
|
}));
|
|
2049
|
+
const normalizeImageUrl2 = (value) => {
|
|
2050
|
+
if (!value) {
|
|
2051
|
+
return value;
|
|
2052
|
+
}
|
|
2053
|
+
const trimmed = value.trim();
|
|
2054
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
2055
|
+
return trimmed;
|
|
2056
|
+
}
|
|
2057
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
2058
|
+
};
|
|
1938
2059
|
if (request.images && request.images.length > 0) {
|
|
1939
2060
|
const lastUserMessageIndex = messages.map((m) => m.role).lastIndexOf("user");
|
|
1940
2061
|
if (this.config.provider === "ollama") {
|
|
@@ -1944,7 +2065,7 @@ var GatewayProvider = class {
|
|
|
1944
2065
|
images: request.images
|
|
1945
2066
|
};
|
|
1946
2067
|
}
|
|
1947
|
-
} else if (["openai", "azure-openai", "anthropic"].includes(this.config.provider || "")) {
|
|
2068
|
+
} else if (["openai", "azure-openai", "anthropic", "bandit"].includes(this.config.provider || "")) {
|
|
1948
2069
|
if (lastUserMessageIndex !== -1) {
|
|
1949
2070
|
const currentMessage = messages[lastUserMessageIndex];
|
|
1950
2071
|
const contentArray = [
|
|
@@ -1953,11 +2074,11 @@ var GatewayProvider = class {
|
|
|
1953
2074
|
text: currentMessage.content
|
|
1954
2075
|
}
|
|
1955
2076
|
];
|
|
1956
|
-
request.images.forEach((
|
|
2077
|
+
request.images.forEach((imageRef) => {
|
|
1957
2078
|
contentArray.push({
|
|
1958
2079
|
type: "image_url",
|
|
1959
2080
|
image_url: {
|
|
1960
|
-
url:
|
|
2081
|
+
url: normalizeImageUrl2(imageRef),
|
|
1961
2082
|
detail: "auto"
|
|
1962
2083
|
}
|
|
1963
2084
|
});
|
|
@@ -1966,6 +2087,11 @@ var GatewayProvider = class {
|
|
|
1966
2087
|
...messages[lastUserMessageIndex],
|
|
1967
2088
|
content: contentArray
|
|
1968
2089
|
};
|
|
2090
|
+
debugLogger.debug("Gateway provider injected image attachments", {
|
|
2091
|
+
provider: this.config.provider,
|
|
2092
|
+
imageCount: request.images.length,
|
|
2093
|
+
messageIndex: lastUserMessageIndex
|
|
2094
|
+
});
|
|
1969
2095
|
}
|
|
1970
2096
|
}
|
|
1971
2097
|
}
|
|
@@ -1994,7 +2120,7 @@ var GatewayProvider = class {
|
|
|
1994
2120
|
}))
|
|
1995
2121
|
});
|
|
1996
2122
|
return this.gatewayService.chat(gatewayRequest).pipe(
|
|
1997
|
-
|
|
2123
|
+
map12((response) => ({
|
|
1998
2124
|
message: {
|
|
1999
2125
|
content: response.choices?.[0]?.message?.content || response.choices?.[0]?.delta?.content || "",
|
|
2000
2126
|
role: "assistant"
|
|
@@ -2017,7 +2143,7 @@ var GatewayProvider = class {
|
|
|
2017
2143
|
stream: request.stream
|
|
2018
2144
|
});
|
|
2019
2145
|
return this.gatewayService.generate(gatewayRequest).pipe(
|
|
2020
|
-
|
|
2146
|
+
map12((response) => ({
|
|
2021
2147
|
response: response.response || "",
|
|
2022
2148
|
done: response.done || false
|
|
2023
2149
|
}))
|
|
@@ -2027,7 +2153,7 @@ var GatewayProvider = class {
|
|
|
2027
2153
|
debugLogger.debug("Gateway provider listing models", { provider: this.config.provider });
|
|
2028
2154
|
if (this.config.provider) {
|
|
2029
2155
|
return this.gatewayService.listModelsByProvider(this.config.provider).pipe(
|
|
2030
|
-
|
|
2156
|
+
map12((models) => models.map((model) => ({
|
|
2031
2157
|
name: model.id || model.name,
|
|
2032
2158
|
size: model.size,
|
|
2033
2159
|
details: model.details,
|
|
@@ -2037,7 +2163,7 @@ var GatewayProvider = class {
|
|
|
2037
2163
|
);
|
|
2038
2164
|
} else {
|
|
2039
2165
|
return this.gatewayService.listModels().pipe(
|
|
2040
|
-
|
|
2166
|
+
map12((models) => models.map((model) => ({
|
|
2041
2167
|
name: model.id || model.name,
|
|
2042
2168
|
size: model.size,
|
|
2043
2169
|
details: model.details,
|
|
@@ -2068,7 +2194,7 @@ var GatewayProvider = class {
|
|
|
2068
2194
|
*/
|
|
2069
2195
|
getHealth() {
|
|
2070
2196
|
return this.gatewayService.getHealth().pipe(
|
|
2071
|
-
|
|
2197
|
+
map12((health) => ({
|
|
2072
2198
|
...health,
|
|
2073
2199
|
backend_provider: this.config.provider,
|
|
2074
2200
|
backend_provider_status: health.providers.find((p) => p.name === this.config.provider)?.status || "unavailable"
|
|
@@ -2256,7 +2382,7 @@ var PlaygroundProvider = class {
|
|
|
2256
2382
|
};
|
|
2257
2383
|
|
|
2258
2384
|
// src/services/ai-provider/providers/xai.provider.ts
|
|
2259
|
-
import { Observable as Observable9, from as from6, switchMap as switchMap5, map as
|
|
2385
|
+
import { Observable as Observable9, from as from6, switchMap as switchMap5, map as map13, throwError as throwError5 } from "rxjs";
|
|
2260
2386
|
var XAIProvider = class {
|
|
2261
2387
|
config;
|
|
2262
2388
|
baseUrl;
|
|
@@ -2287,7 +2413,7 @@ var XAIProvider = class {
|
|
|
2287
2413
|
options: request.options
|
|
2288
2414
|
};
|
|
2289
2415
|
return this.chat(chatRequest).pipe(
|
|
2290
|
-
|
|
2416
|
+
map13((response) => ({
|
|
2291
2417
|
response: response.message.content,
|
|
2292
2418
|
done: response.done
|
|
2293
2419
|
}))
|
|
@@ -2304,7 +2430,7 @@ var XAIProvider = class {
|
|
|
2304
2430
|
}
|
|
2305
2431
|
return from6(response.json());
|
|
2306
2432
|
}),
|
|
2307
|
-
|
|
2433
|
+
map13(
|
|
2308
2434
|
(data) => data.data.map((model) => ({
|
|
2309
2435
|
name: model.id,
|
|
2310
2436
|
details: {
|
|
@@ -2439,7 +2565,237 @@ var XAIProvider = class {
|
|
|
2439
2565
|
}
|
|
2440
2566
|
return from6(response.json());
|
|
2441
2567
|
}),
|
|
2442
|
-
|
|
2568
|
+
map13((data) => ({
|
|
2569
|
+
message: {
|
|
2570
|
+
content: data.choices?.[0]?.message?.content ?? "",
|
|
2571
|
+
role: "assistant"
|
|
2572
|
+
},
|
|
2573
|
+
done: true
|
|
2574
|
+
}))
|
|
2575
|
+
);
|
|
2576
|
+
}
|
|
2577
|
+
getHeaders() {
|
|
2578
|
+
const headers = {};
|
|
2579
|
+
if (this.config.apiKey) {
|
|
2580
|
+
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
2581
|
+
}
|
|
2582
|
+
return headers;
|
|
2583
|
+
}
|
|
2584
|
+
};
|
|
2585
|
+
|
|
2586
|
+
// src/services/ai-provider/providers/bandit-ai.provider.ts
|
|
2587
|
+
import { Observable as Observable10, from as from7, switchMap as switchMap6, map as map14, throwError as throwError6 } from "rxjs";
|
|
2588
|
+
var DEFAULT_BANDIT_BASE = "https://api.burtson.ai";
|
|
2589
|
+
var normalizeImageUrl = (value) => {
|
|
2590
|
+
if (!value) {
|
|
2591
|
+
return null;
|
|
2592
|
+
}
|
|
2593
|
+
const trimmed = value.trim();
|
|
2594
|
+
if (!trimmed) {
|
|
2595
|
+
return null;
|
|
2596
|
+
}
|
|
2597
|
+
if (/^data:/i.test(trimmed) || /^https?:\/\//i.test(trimmed)) {
|
|
2598
|
+
return trimmed;
|
|
2599
|
+
}
|
|
2600
|
+
return `data:image/jpeg;base64,${trimmed}`;
|
|
2601
|
+
};
|
|
2602
|
+
var injectImagesIntoMessages = (messages, images) => {
|
|
2603
|
+
const normalized = messages.map((message) => ({
|
|
2604
|
+
role: message.role,
|
|
2605
|
+
content: message.content
|
|
2606
|
+
}));
|
|
2607
|
+
if (!images || images.length === 0) {
|
|
2608
|
+
return normalized;
|
|
2609
|
+
}
|
|
2610
|
+
const normalizedImages = images.map(normalizeImageUrl).filter((url) => Boolean(url));
|
|
2611
|
+
if (normalizedImages.length === 0) {
|
|
2612
|
+
return normalized;
|
|
2613
|
+
}
|
|
2614
|
+
const lastUserIndex = normalized.map((msg) => msg.role).lastIndexOf("user");
|
|
2615
|
+
if (lastUserIndex === -1) {
|
|
2616
|
+
return normalized;
|
|
2617
|
+
}
|
|
2618
|
+
const target = normalized[lastUserIndex];
|
|
2619
|
+
const baseContent = typeof target.content === "string" && target.content.trim().length > 0 ? [
|
|
2620
|
+
{
|
|
2621
|
+
type: "text",
|
|
2622
|
+
text: target.content
|
|
2623
|
+
}
|
|
2624
|
+
] : [];
|
|
2625
|
+
const imageContent = normalizedImages.map((url) => ({
|
|
2626
|
+
type: "image_url",
|
|
2627
|
+
image_url: { url, detail: "auto" }
|
|
2628
|
+
}));
|
|
2629
|
+
normalized[lastUserIndex] = {
|
|
2630
|
+
role: target.role,
|
|
2631
|
+
content: [...baseContent, ...imageContent]
|
|
2632
|
+
};
|
|
2633
|
+
return normalized;
|
|
2634
|
+
};
|
|
2635
|
+
var BanditAIProvider = class {
|
|
2636
|
+
config;
|
|
2637
|
+
baseUrl;
|
|
2638
|
+
constructor(config) {
|
|
2639
|
+
this.config = config;
|
|
2640
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BANDIT_BASE).replace(/\/$/, "");
|
|
2641
|
+
}
|
|
2642
|
+
chat(request) {
|
|
2643
|
+
const url = `${this.baseUrl}/chat/completions`;
|
|
2644
|
+
const messages = injectImagesIntoMessages(request.messages, request.images);
|
|
2645
|
+
const payload = {
|
|
2646
|
+
model: request.model,
|
|
2647
|
+
messages,
|
|
2648
|
+
stream: Boolean(request.stream),
|
|
2649
|
+
temperature: request.temperature,
|
|
2650
|
+
max_tokens: request.maxTokens
|
|
2651
|
+
};
|
|
2652
|
+
if (request.stream) {
|
|
2653
|
+
return this.streamChatRequest(url, payload);
|
|
2654
|
+
}
|
|
2655
|
+
return this.nonStreamChatRequest(url, payload);
|
|
2656
|
+
}
|
|
2657
|
+
generate(request) {
|
|
2658
|
+
const chatRequest = {
|
|
2659
|
+
model: request.model,
|
|
2660
|
+
messages: [{ role: "user", content: request.prompt }],
|
|
2661
|
+
stream: request.stream,
|
|
2662
|
+
options: request.options
|
|
2663
|
+
};
|
|
2664
|
+
return this.chat(chatRequest).pipe(
|
|
2665
|
+
map14((response) => ({
|
|
2666
|
+
response: response.message.content,
|
|
2667
|
+
done: response.done
|
|
2668
|
+
}))
|
|
2669
|
+
);
|
|
2670
|
+
}
|
|
2671
|
+
listModels() {
|
|
2672
|
+
const url = `${this.baseUrl}/models`;
|
|
2673
|
+
return from7(fetch(url, { headers: this.getHeaders() })).pipe(
|
|
2674
|
+
switchMap6((response) => {
|
|
2675
|
+
if (!response.ok) {
|
|
2676
|
+
debugLogger.error("BanditAI listModels failed", { status: response.status, url });
|
|
2677
|
+
return throwError6(() => new Error(`Failed to list Bandit models: ${response.status}`));
|
|
2678
|
+
}
|
|
2679
|
+
return from7(response.json());
|
|
2680
|
+
}),
|
|
2681
|
+
map14(
|
|
2682
|
+
(data) => data.data.map((model) => ({
|
|
2683
|
+
name: model.id,
|
|
2684
|
+
details: {
|
|
2685
|
+
format: "bandit",
|
|
2686
|
+
family: model.object
|
|
2687
|
+
}
|
|
2688
|
+
}))
|
|
2689
|
+
)
|
|
2690
|
+
);
|
|
2691
|
+
}
|
|
2692
|
+
async validateServiceAvailability(args) {
|
|
2693
|
+
const attempt = async (url) => {
|
|
2694
|
+
try {
|
|
2695
|
+
const controller = new AbortController();
|
|
2696
|
+
const timeoutId = setTimeout(() => controller.abort(), args.timeoutMs);
|
|
2697
|
+
const response = await fetch(`${url}/models`, {
|
|
2698
|
+
headers: this.getHeaders(),
|
|
2699
|
+
signal: controller.signal
|
|
2700
|
+
});
|
|
2701
|
+
clearTimeout(timeoutId);
|
|
2702
|
+
return response.ok;
|
|
2703
|
+
} catch (error) {
|
|
2704
|
+
debugLogger.warn("BanditAI availability check failed", { url, error });
|
|
2705
|
+
return false;
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
const primary = await attempt(this.baseUrl);
|
|
2709
|
+
if (primary) {
|
|
2710
|
+
return { url: this.baseUrl, isAvailable: true };
|
|
2711
|
+
}
|
|
2712
|
+
if (args.fallbackUrl) {
|
|
2713
|
+
const fallback = args.fallbackUrl.replace(/\/$/, "");
|
|
2714
|
+
if (await attempt(fallback)) {
|
|
2715
|
+
this.baseUrl = fallback;
|
|
2716
|
+
return { url: fallback, isAvailable: true };
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
return { url: this.baseUrl, isAvailable: false };
|
|
2720
|
+
}
|
|
2721
|
+
getProviderType() {
|
|
2722
|
+
return "bandit" /* BANDIT */;
|
|
2723
|
+
}
|
|
2724
|
+
getConfig() {
|
|
2725
|
+
return this.config;
|
|
2726
|
+
}
|
|
2727
|
+
streamChatRequest(url, payload) {
|
|
2728
|
+
return new Observable10((observer) => {
|
|
2729
|
+
const task = fetch(url, {
|
|
2730
|
+
method: "POST",
|
|
2731
|
+
headers: {
|
|
2732
|
+
...this.getHeaders(),
|
|
2733
|
+
"Content-Type": "application/json"
|
|
2734
|
+
},
|
|
2735
|
+
body: JSON.stringify(payload)
|
|
2736
|
+
});
|
|
2737
|
+
task.then((response) => {
|
|
2738
|
+
if (!response.ok) {
|
|
2739
|
+
observer.error(new Error(`BanditAI request failed: ${response.status}`));
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
const reader = response.body?.getReader();
|
|
2743
|
+
const decoder = new TextDecoder();
|
|
2744
|
+
let buffer = "";
|
|
2745
|
+
const read = () => {
|
|
2746
|
+
reader?.read().then(({ done, value }) => {
|
|
2747
|
+
if (done) {
|
|
2748
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
2749
|
+
observer.complete();
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
buffer += decoder.decode(value, { stream: true });
|
|
2753
|
+
const lines = buffer.split("\n");
|
|
2754
|
+
buffer = lines.pop() ?? "";
|
|
2755
|
+
for (const rawLine of lines) {
|
|
2756
|
+
const line = rawLine.trim();
|
|
2757
|
+
if (!line.startsWith("data: ")) {
|
|
2758
|
+
continue;
|
|
2759
|
+
}
|
|
2760
|
+
const data = line.slice(6).trim();
|
|
2761
|
+
if (data === "[DONE]") {
|
|
2762
|
+
observer.next({ message: { content: "", role: "assistant" }, done: true });
|
|
2763
|
+
observer.complete();
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2766
|
+
try {
|
|
2767
|
+
const parsed = JSON.parse(data);
|
|
2768
|
+
const content = parsed.choices?.[0]?.delta?.content ?? "";
|
|
2769
|
+
if (content) {
|
|
2770
|
+
observer.next({ message: { content, role: "assistant" }, done: false });
|
|
2771
|
+
}
|
|
2772
|
+
} catch (error) {
|
|
2773
|
+
debugLogger.error("BanditAI stream chunk parse failure", { data, error });
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
read();
|
|
2777
|
+
}).catch((err) => observer.error(err));
|
|
2778
|
+
};
|
|
2779
|
+
read();
|
|
2780
|
+
}).catch((err) => observer.error(err));
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
nonStreamChatRequest(url, payload) {
|
|
2784
|
+
return from7(fetch(url, {
|
|
2785
|
+
method: "POST",
|
|
2786
|
+
headers: {
|
|
2787
|
+
...this.getHeaders(),
|
|
2788
|
+
"Content-Type": "application/json"
|
|
2789
|
+
},
|
|
2790
|
+
body: JSON.stringify(payload)
|
|
2791
|
+
})).pipe(
|
|
2792
|
+
switchMap6((response) => {
|
|
2793
|
+
if (!response.ok) {
|
|
2794
|
+
return throwError6(() => new Error(`BanditAI request failed: ${response.status}`));
|
|
2795
|
+
}
|
|
2796
|
+
return from7(response.json());
|
|
2797
|
+
}),
|
|
2798
|
+
map14((data) => ({
|
|
2443
2799
|
message: {
|
|
2444
2800
|
content: data.choices?.[0]?.message?.content ?? "",
|
|
2445
2801
|
role: "assistant"
|
|
@@ -2471,6 +2827,8 @@ var AIProviderFactory = class {
|
|
|
2471
2827
|
return new AnthropicProvider(config);
|
|
2472
2828
|
case "xai" /* XAI */:
|
|
2473
2829
|
return new XAIProvider(config);
|
|
2830
|
+
case "bandit" /* BANDIT */:
|
|
2831
|
+
return new BanditAIProvider(config);
|
|
2474
2832
|
case "gateway" /* GATEWAY */:
|
|
2475
2833
|
return new GatewayProvider(config);
|
|
2476
2834
|
case "playground" /* PLAYGROUND */:
|
|
@@ -2485,6 +2843,7 @@ var AIProviderFactory = class {
|
|
|
2485
2843
|
"openai" /* OPENAI */,
|
|
2486
2844
|
"azure-openai" /* AZURE_OPENAI */,
|
|
2487
2845
|
"xai" /* XAI */,
|
|
2846
|
+
"bandit" /* BANDIT */,
|
|
2488
2847
|
"gateway" /* GATEWAY */,
|
|
2489
2848
|
"playground" /* PLAYGROUND */
|
|
2490
2849
|
];
|
|
@@ -2502,6 +2861,8 @@ var AIProviderFactory = class {
|
|
|
2502
2861
|
return !!config.apiKey;
|
|
2503
2862
|
case "xai" /* XAI */:
|
|
2504
2863
|
return !!config.apiKey;
|
|
2864
|
+
case "bandit" /* BANDIT */:
|
|
2865
|
+
return !!config.apiKey;
|
|
2505
2866
|
case "gateway" /* GATEWAY */:
|
|
2506
2867
|
return !!(config.gatewayUrl && config.provider);
|
|
2507
2868
|
case "playground" /* PLAYGROUND */:
|
|
@@ -2543,4 +2904,4 @@ export {
|
|
|
2543
2904
|
AIProviderFactory,
|
|
2544
2905
|
useAIProviderStore
|
|
2545
2906
|
};
|
|
2546
|
-
//# sourceMappingURL=chunk-
|
|
2907
|
+
//# sourceMappingURL=chunk-QJYPWWA5.mjs.map
|