@burtson-labs/bandit-engine 2.0.37 → 2.0.38

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 (44) hide show
  1. package/dist/{aiProviderStore-UJRDUYOF.mjs → aiProviderStore-XN7GCBHJ.mjs} +2 -2
  2. package/dist/{chat-SZK3EBDO.mjs → chat-5QJNWB7I.mjs} +5 -5
  3. package/dist/chat-provider.js +29 -3
  4. package/dist/chat-provider.js.map +1 -1
  5. package/dist/chat-provider.mjs +4 -4
  6. package/dist/{chunk-2ZZA2IFL.mjs → chunk-3A2527TE.mjs} +3 -3
  7. package/dist/{chunk-FJO5ZWYU.mjs → chunk-CDQYBO3Q.mjs} +26 -8
  8. package/dist/chunk-CDQYBO3Q.mjs.map +1 -0
  9. package/dist/{chunk-PLNFTIGX.mjs → chunk-ECRNIAG6.mjs} +4 -4
  10. package/dist/{chunk-S635Q6OQ.mjs → chunk-EOKIE5HZ.mjs} +24 -3
  11. package/dist/chunk-EOKIE5HZ.mjs.map +1 -0
  12. package/dist/{chunk-G4OXOTNJ.mjs → chunk-JRCDANLN.mjs} +154 -61
  13. package/dist/{chunk-G4OXOTNJ.mjs.map → chunk-JRCDANLN.mjs.map} +1 -1
  14. package/dist/{chunk-ZNNOTDRD.mjs → chunk-QU5S5QQP.mjs} +9 -4
  15. package/dist/chunk-QU5S5QQP.mjs.map +1 -0
  16. package/dist/{chunk-ED5NNDKO.mjs → chunk-QYH2T4L5.mjs} +3 -3
  17. package/dist/{chunk-ZAVV2AT5.mjs → chunk-WO5KFNNW.mjs} +4 -4
  18. package/dist/cli/cli.js +1 -1
  19. package/dist/cli/cli.js.map +1 -1
  20. package/dist/{gateway-Ckf_KusF.d.ts → gateway-B0LJ3-jT.d.mts} +3 -0
  21. package/dist/{gateway-Ckf_KusF.d.mts → gateway-B0LJ3-jT.d.ts} +3 -0
  22. package/dist/index.d.mts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +196 -59
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +8 -8
  27. package/dist/management/management.js +196 -59
  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 +8 -3
  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-FJO5ZWYU.mjs.map +0 -1
  37. package/dist/chunk-S635Q6OQ.mjs.map +0 -1
  38. package/dist/chunk-ZNNOTDRD.mjs.map +0 -1
  39. /package/dist/{aiProviderStore-UJRDUYOF.mjs.map → aiProviderStore-XN7GCBHJ.mjs.map} +0 -0
  40. /package/dist/{chat-SZK3EBDO.mjs.map → chat-5QJNWB7I.mjs.map} +0 -0
  41. /package/dist/{chunk-2ZZA2IFL.mjs.map → chunk-3A2527TE.mjs.map} +0 -0
  42. /package/dist/{chunk-PLNFTIGX.mjs.map → chunk-ECRNIAG6.mjs.map} +0 -0
  43. /package/dist/{chunk-ED5NNDKO.mjs.map → chunk-QYH2T4L5.mjs.map} +0 -0
  44. /package/dist/{chunk-ZAVV2AT5.mjs.map → chunk-WO5KFNNW.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -1,24 +1,24 @@
1
1
  import {
2
2
  chat_default
3
- } from "./chunk-ZAVV2AT5.mjs";
3
+ } from "./chunk-WO5KFNNW.mjs";
4
4
  import {
5
5
  chat_provider_default
6
- } from "./chunk-2ZZA2IFL.mjs";
6
+ } from "./chunk-3A2527TE.mjs";
7
7
  import "./chunk-ONQMRE2G.mjs";
8
8
  import {
9
9
  management_default,
10
10
  useGatewayHealth,
11
11
  useGatewayMemory,
12
12
  useGatewayModels
13
- } from "./chunk-G4OXOTNJ.mjs";
14
- import "./chunk-S635Q6OQ.mjs";
13
+ } from "./chunk-JRCDANLN.mjs";
14
+ import "./chunk-EOKIE5HZ.mjs";
15
15
  import "./chunk-RTQDQ6TC.mjs";
16
16
  import {
17
17
  defineCustomElement
18
18
  } from "./chunk-IXIM7BNO.mjs";
19
19
  import {
20
20
  chat_modal_default
21
- } from "./chunk-PLNFTIGX.mjs";
21
+ } from "./chunk-ECRNIAG6.mjs";
22
22
  import {
23
23
  FeedbackButton,
24
24
  FeedbackModal,
@@ -36,7 +36,7 @@ import {
36
36
  useTTS,
37
37
  useVoiceStore,
38
38
  voiceService
39
- } from "./chunk-ED5NNDKO.mjs";
39
+ } from "./chunk-QYH2T4L5.mjs";
40
40
  import {
41
41
  DEFAULT_TIER_FEATURES,
42
42
  FeatureFlagContext,
@@ -56,11 +56,11 @@ import {
56
56
  useVectorStore,
57
57
  vectorDatabaseService,
58
58
  vectorMigrationService
59
- } from "./chunk-FJO5ZWYU.mjs";
59
+ } from "./chunk-CDQYBO3Q.mjs";
60
60
  import {
61
61
  usePackageSettingsStore
62
62
  } from "./chunk-XUBYA5I7.mjs";
63
- import "./chunk-ZNNOTDRD.mjs";
63
+ import "./chunk-QU5S5QQP.mjs";
64
64
  import {
65
65
  DebugLogger,
66
66
  debugLogger
@@ -1233,10 +1233,16 @@ var init_anthropic_provider = __esm({
1233
1233
  AnthropicProvider = class {
1234
1234
  config;
1235
1235
  baseUrl;
1236
+ version;
1237
+ defaultMaxTokens;
1236
1238
  constructor(config) {
1237
1239
  deprecatedAnthropicProvider();
1238
1240
  this.config = config;
1239
1241
  this.baseUrl = config.baseUrl || "https://api.anthropic.com/v1";
1242
+ this.version = typeof config.anthropicVersion === "string" && config.anthropicVersion.trim() ? config.anthropicVersion.trim() : "2023-06-01";
1243
+ this.defaultMaxTokens = typeof config.anthropicMaxTokens === "number" && config.anthropicMaxTokens > 0 ? config.anthropicMaxTokens : 1024;
1244
+ this.config.anthropicVersion = this.version;
1245
+ this.config.anthropicMaxTokens = this.defaultMaxTokens;
1240
1246
  }
1241
1247
  chat(request) {
1242
1248
  const url = `${this.baseUrl}/messages`;
@@ -1251,7 +1257,7 @@ var init_anthropic_provider = __esm({
1251
1257
  system: systemMessage?.content,
1252
1258
  stream: Boolean(request.stream),
1253
1259
  temperature: request.temperature,
1254
- max_tokens: request.maxTokens ?? 1e3
1260
+ max_tokens: request.maxTokens ?? this.defaultMaxTokens
1255
1261
  };
1256
1262
  if (request.stream) {
1257
1263
  return this.streamChatRequest(url, payload);
@@ -1488,7 +1494,7 @@ var init_anthropic_provider = __esm({
1488
1494
  }
1489
1495
  getHeaders() {
1490
1496
  const headers = {
1491
- "anthropic-version": "2023-06-01"
1497
+ "anthropic-version": this.version
1492
1498
  };
1493
1499
  if (this.config.apiKey) {
1494
1500
  headers["x-api-key"] = this.config.apiKey;
@@ -3046,7 +3052,6 @@ var init_ai_provider_factory = __esm({
3046
3052
  "ollama" /* OLLAMA */,
3047
3053
  "openai" /* OPENAI */,
3048
3054
  "azure-openai" /* AZURE_OPENAI */,
3049
- "anthropic" /* ANTHROPIC */,
3050
3055
  "xai" /* XAI */,
3051
3056
  "gateway" /* GATEWAY */,
3052
3057
  "playground" /* PLAYGROUND */
@@ -3242,8 +3247,10 @@ Do not:
3242
3247
  - Refer to yourself or use phrases like "As an AI..."
3243
3248
  - Include greetings, explanations, or personality
3244
3249
  - Include jokes, fiction, or quotes
3250
+ - Number, bullet, or otherwise prefix the questions with extra characters
3251
+ - Repeat the same idea phrased differently \u2014 each question must explore a distinct angle or subtopic
3245
3252
 
3246
- Output only ${limit} questions \u2014 one per line.`;
3253
+ Output only ${limit} questions \u2014 one per line, with no leading numbers, bullets, or prefixes.`;
3247
3254
  return prompt.trim();
3248
3255
  };
3249
3256
  }
@@ -3464,17 +3471,33 @@ var init_conversationStarters = __esm({
3464
3471
  options: { temperature: 1.5, num_predict: 250 }
3465
3472
  });
3466
3473
  const questions$ = data$.pipe((0, import_rxjs10.map)((d) => {
3467
- const lines = d.response.split("\n").map((line) => line.trim()).filter((line) => {
3468
- return line.length > 10 && !line.toLowerCase().includes("sorry") && !line.toLowerCase().includes("i cannot") && !line.toLowerCase().includes("i can't") && !line.toLowerCase().includes("unable to") && !line.toLowerCase().startsWith("as an ai") && line.includes("?");
3474
+ const sanitizeLine = (line) => {
3475
+ const withoutNumbering = line.replace(/^[0-9]+[.)\-\s:]+/, "").replace(/^[•*+-]\s+/, "");
3476
+ const withoutQuotes = withoutNumbering.replace(/^[“"']+/, "").replace(/[”"']+$/, "");
3477
+ const withoutEmoji = withoutQuotes.replace(/\p{Extended_Pictographic}/gu, "");
3478
+ return withoutEmoji.trim().replace(/\s+/g, " ");
3479
+ };
3480
+ const sanitized = d.response.split("\n").map((line) => sanitizeLine(line.trim())).filter((line) => {
3481
+ const lower = line.toLowerCase();
3482
+ return line.length > 10 && line.includes("?") && !lower.includes("sorry") && !lower.includes("i cannot") && !lower.includes("i can't") && !lower.includes("unable to") && !lower.startsWith("as an ai");
3483
+ }).filter((line) => line.length > 0);
3484
+ const unique = [];
3485
+ const seen = /* @__PURE__ */ new Set();
3486
+ sanitized.forEach((line) => {
3487
+ const key = line.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
3488
+ if (key && !seen.has(key)) {
3489
+ seen.add(key);
3490
+ unique.push(line);
3491
+ }
3469
3492
  });
3470
- return lines;
3493
+ return unique;
3471
3494
  }));
3472
3495
  const starters = await (0, import_rxjs10.lastValueFrom)(questions$);
3473
3496
  if (starters.length === 0) {
3474
3497
  debugLogger.warn("No meaningful conversation starters generated");
3475
3498
  return [];
3476
3499
  }
3477
- return starters;
3500
+ return starters.slice(0, args.limit);
3478
3501
  } catch (err) {
3479
3502
  debugLogger.error("\u274C Failed to generate conversation starters:", { error: err });
3480
3503
  notificationService.handleHttpError(err);
@@ -37823,6 +37846,9 @@ var AIProviderInitService = class _AIProviderInitService {
37823
37846
  debugLogger.info("AI Provider Init: Found saved config in IndexedDB", { type: savedConfig.type });
37824
37847
  const { id: _id, ...configWithoutId } = savedConfig;
37825
37848
  providerConfig = { ...configWithoutId };
37849
+ if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
37850
+ providerConfig = this.convertAnthropicConfig(providerConfig, settings?.gatewayApiUrl);
37851
+ }
37826
37852
  if ((providerConfig.type === "ollama" /* OLLAMA */ || providerConfig.type === "gateway" /* GATEWAY */) && !providerConfig.tokenFactory) {
37827
37853
  providerConfig.tokenFactory = () => {
37828
37854
  let token = authenticationService.getToken();
@@ -37867,6 +37893,9 @@ var AIProviderInitService = class _AIProviderInitService {
37867
37893
  }
37868
37894
  if (settings.aiProvider) {
37869
37895
  providerConfig = { ...settings.aiProvider };
37896
+ if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
37897
+ providerConfig = this.convertAnthropicConfig(providerConfig, settings.gatewayApiUrl);
37898
+ }
37870
37899
  if (providerConfig.type === "ollama" /* OLLAMA */ && !providerConfig.tokenFactory) {
37871
37900
  providerConfig.tokenFactory = () => {
37872
37901
  let token = authenticationService.getToken();
@@ -38020,6 +38049,21 @@ var AIProviderInitService = class _AIProviderInitService {
38020
38049
  isProviderInitialized() {
38021
38050
  return useAIProviderStore.getState().provider !== null;
38022
38051
  }
38052
+ convertAnthropicConfig(config, gatewayUrl) {
38053
+ if (config.type !== "anthropic" /* ANTHROPIC */) {
38054
+ return config;
38055
+ }
38056
+ const defaultModel = typeof config.defaultModel === "string" && config.defaultModel.trim() ? config.defaultModel.trim() : "claude-3-5-sonnet-latest";
38057
+ const normalized = {
38058
+ type: "gateway" /* GATEWAY */,
38059
+ gatewayUrl: gatewayUrl || config.gatewayUrl || "",
38060
+ provider: "anthropic",
38061
+ defaultModel,
38062
+ tokenFactory: config.tokenFactory
38063
+ };
38064
+ debugLogger.info("AI Provider Init: Converted direct Anthropic provider to gateway configuration");
38065
+ return normalized;
38066
+ }
38023
38067
  };
38024
38068
  var aiProviderInitService = AIProviderInitService.getInstance();
38025
38069
 
@@ -38033,6 +38077,48 @@ var ProviderTab = () => {
38033
38077
  const { settings: packageSettings } = usePackageSettingsStore();
38034
38078
  const theme = (0, import_material25.useTheme)();
38035
38079
  const isMobile = (0, import_material25.useMediaQuery)(theme.breakpoints.down("sm"));
38080
+ const getSuggestedModel = (0, import_react33.useCallback)((type) => {
38081
+ const configuredDefault = packageSettings?.defaultModel?.trim();
38082
+ if (configuredDefault) {
38083
+ return configuredDefault;
38084
+ }
38085
+ switch (type) {
38086
+ case "openai" /* OPENAI */:
38087
+ return "gpt-4o-mini";
38088
+ case "xai" /* XAI */:
38089
+ return "grok-beta";
38090
+ default:
38091
+ return "";
38092
+ }
38093
+ }, [packageSettings?.defaultModel]);
38094
+ const applyDefaultModel = (0, import_react33.useCallback)((config) => {
38095
+ const normalized = { ...config };
38096
+ const trimmed = typeof normalized.defaultModel === "string" ? normalized.defaultModel.trim() : void 0;
38097
+ const requiresModel = normalized.type === "openai" /* OPENAI */ || normalized.type === "xai" /* XAI */;
38098
+ if (trimmed) {
38099
+ normalized.defaultModel = trimmed;
38100
+ return normalized;
38101
+ }
38102
+ if (!requiresModel) {
38103
+ delete normalized.defaultModel;
38104
+ return normalized;
38105
+ }
38106
+ const suggestion = getSuggestedModel(normalized.type);
38107
+ if (suggestion) {
38108
+ normalized.defaultModel = suggestion;
38109
+ } else {
38110
+ delete normalized.defaultModel;
38111
+ }
38112
+ return normalized;
38113
+ }, [getSuggestedModel]);
38114
+ const sanitizeConfigForSave = (0, import_react33.useCallback)((config) => {
38115
+ const sanitized = { ...config };
38116
+ if (typeof sanitized.defaultModel === "string") {
38117
+ const trimmed = sanitized.defaultModel.trim();
38118
+ sanitized.defaultModel = trimmed || void 0;
38119
+ }
38120
+ return sanitized;
38121
+ }, []);
38036
38122
  const [providerConfig, setProviderConfig] = (0, import_react33.useState)({
38037
38123
  type: "ollama",
38038
38124
  baseUrl: "http://localhost:11434"
@@ -38081,19 +38167,38 @@ var ProviderTab = () => {
38081
38167
  }
38082
38168
  return null;
38083
38169
  };
38170
+ const convertAnthropicConfig = (0, import_react33.useCallback)((config) => {
38171
+ if (!config) return null;
38172
+ if (config.type !== "anthropic" /* ANTHROPIC */) {
38173
+ return config;
38174
+ }
38175
+ const gatewayUrl = config.gatewayUrl || packageSettings?.gatewayApiUrl || "";
38176
+ const defaultModel = typeof config.defaultModel === "string" && config.defaultModel.trim() ? config.defaultModel.trim() : "claude-3-5-sonnet-latest";
38177
+ const converted = {
38178
+ type: "gateway" /* GATEWAY */,
38179
+ gatewayUrl,
38180
+ provider: "anthropic",
38181
+ defaultModel,
38182
+ tokenFactory: config.tokenFactory
38183
+ };
38184
+ return converted;
38185
+ }, [packageSettings?.gatewayApiUrl]);
38084
38186
  (0, import_react33.useEffect)(() => {
38085
38187
  const initializeProviderConfig = async () => {
38086
38188
  const savedConfig = await loadProviderConfigFromDB();
38087
38189
  if (savedConfig) {
38088
- setProviderConfig(savedConfig);
38190
+ const normalized = convertAnthropicConfig(savedConfig) || savedConfig;
38191
+ setProviderConfig(applyDefaultModel(normalized));
38089
38192
  } else if (currentProviderConfig) {
38090
- setProviderConfig(currentProviderConfig);
38193
+ const normalized = convertAnthropicConfig(currentProviderConfig) || currentProviderConfig;
38194
+ setProviderConfig(applyDefaultModel(normalized));
38091
38195
  } else if (packageSettings?.aiProvider) {
38092
- setProviderConfig(packageSettings.aiProvider);
38196
+ const normalized = convertAnthropicConfig(packageSettings.aiProvider) || packageSettings.aiProvider;
38197
+ setProviderConfig(applyDefaultModel(normalized));
38093
38198
  }
38094
38199
  };
38095
38200
  initializeProviderConfig();
38096
- }, [currentProviderConfig, packageSettings]);
38201
+ }, [applyDefaultModel, convertAnthropicConfig, currentProviderConfig, packageSettings]);
38097
38202
  const showMessage = (message, severity) => {
38098
38203
  setSnackbarMessage(message);
38099
38204
  setSnackbarSeverity(severity);
@@ -38103,74 +38208,87 @@ var ProviderTab = () => {
38103
38208
  const baseConfig = { type };
38104
38209
  switch (type) {
38105
38210
  case "ollama" /* OLLAMA */:
38106
- setProviderConfig({
38211
+ setProviderConfig(applyDefaultModel({
38107
38212
  ...baseConfig,
38108
38213
  baseUrl: "http://localhost:11434"
38109
- });
38214
+ }));
38110
38215
  break;
38111
38216
  case "openai" /* OPENAI */:
38112
- setProviderConfig({
38217
+ setProviderConfig(applyDefaultModel({
38113
38218
  ...baseConfig,
38114
38219
  baseUrl: "https://api.openai.com/v1",
38115
38220
  apiKey: ""
38116
- });
38221
+ }));
38117
38222
  break;
38118
38223
  case "azure-openai" /* AZURE_OPENAI */:
38119
- setProviderConfig({
38224
+ setProviderConfig(applyDefaultModel({
38120
38225
  ...baseConfig,
38121
38226
  baseUrl: "",
38122
38227
  apiKey: "",
38123
38228
  apiVersion: "2024-02-01",
38124
38229
  deploymentName: ""
38125
- });
38230
+ }));
38126
38231
  break;
38127
38232
  case "anthropic" /* ANTHROPIC */:
38128
- setProviderConfig({
38129
- ...baseConfig,
38130
- baseUrl: "https://api.anthropic.com",
38131
- apiKey: ""
38132
- });
38233
+ showMessage("Anthropic is only available via the Gateway provider. Please configure Gateway and choose Anthropic as the backend.", "error");
38234
+ setProviderConfig(applyDefaultModel({
38235
+ type: "gateway" /* GATEWAY */,
38236
+ gatewayUrl: packageSettings?.gatewayApiUrl || "",
38237
+ provider: "anthropic",
38238
+ defaultModel: "claude-3-5-sonnet-latest"
38239
+ }));
38133
38240
  break;
38134
38241
  case "xai" /* XAI */:
38135
- setProviderConfig({
38242
+ setProviderConfig(applyDefaultModel({
38136
38243
  ...baseConfig,
38137
38244
  baseUrl: "https://api.x.ai/v1",
38138
38245
  apiKey: ""
38139
- });
38246
+ }));
38140
38247
  break;
38141
38248
  case "gateway" /* GATEWAY */:
38142
- setProviderConfig({
38249
+ setProviderConfig(applyDefaultModel({
38143
38250
  ...baseConfig,
38144
38251
  gatewayUrl: packageSettings?.gatewayApiUrl || "",
38145
38252
  provider: "openai"
38146
- });
38253
+ }));
38147
38254
  break;
38148
38255
  case "playground" /* PLAYGROUND */:
38149
- setProviderConfig({
38256
+ setProviderConfig(applyDefaultModel({
38150
38257
  ...baseConfig
38151
- });
38258
+ }));
38152
38259
  break;
38153
38260
  }
38154
38261
  };
38155
38262
  const handleSaveProviderConfig = async () => {
38156
38263
  try {
38157
- const isValid = AIProviderFactory.validateConfig(providerConfig);
38264
+ const normalizedConfigIntermediate = sanitizeConfigForSave(providerConfig);
38265
+ const normalizedConfig = convertAnthropicConfig(normalizedConfigIntermediate) || normalizedConfigIntermediate;
38266
+ const requiresModel = normalizedConfig.type === "openai" /* OPENAI */ || normalizedConfig.type === "xai" /* XAI */;
38267
+ if (requiresModel && !normalizedConfig.defaultModel) {
38268
+ showMessage("Please provide a default model ID for the selected provider.", "error");
38269
+ return;
38270
+ }
38271
+ const isValid = AIProviderFactory.validateConfig(normalizedConfig);
38158
38272
  if (!isValid) {
38159
38273
  showMessage("Invalid provider configuration. Please check all required fields.", "error");
38160
38274
  return;
38161
38275
  }
38162
- await saveProviderConfigToDB(providerConfig);
38163
- await aiProviderInitService.switchProvider(providerConfig);
38276
+ await saveProviderConfigToDB(normalizedConfig);
38277
+ await aiProviderInitService.switchProvider(normalizedConfig);
38164
38278
  if (packageSettings) {
38165
38279
  const updatedSettings = {
38166
38280
  ...packageSettings,
38167
- aiProvider: providerConfig
38281
+ aiProvider: normalizedConfig
38168
38282
  };
38283
+ if (normalizedConfig.defaultModel) {
38284
+ updatedSettings.defaultModel = normalizedConfig.defaultModel;
38285
+ }
38169
38286
  usePackageSettingsStore.setState({ settings: updatedSettings });
38170
38287
  }
38288
+ setProviderConfig(applyDefaultModel(normalizedConfig));
38171
38289
  setIsProviderConfigOpen(false);
38172
38290
  showMessage("Provider configuration saved and switched successfully!", "success");
38173
- debugLogger.info("Provider configuration saved and switched", { type: providerConfig.type });
38291
+ debugLogger.info("Provider configuration saved and switched", { type: normalizedConfig.type });
38174
38292
  } catch (error) {
38175
38293
  debugLogger.error("Failed to save provider configuration:", { error });
38176
38294
  showMessage(`Failed to save provider configuration: ${error instanceof Error ? error.message : "Unknown error"}`, "error");
@@ -38178,8 +38296,9 @@ var ProviderTab = () => {
38178
38296
  };
38179
38297
  const handleTestProviderConnection = async () => {
38180
38298
  try {
38181
- const testConfig = { ...providerConfig };
38182
- const testProvider = AIProviderFactory.createProvider(testConfig);
38299
+ const testConfig = sanitizeConfigForSave(providerConfig);
38300
+ const normalizedTestConfig = convertAnthropicConfig(testConfig) || testConfig;
38301
+ const testProvider = AIProviderFactory.createProvider(normalizedTestConfig);
38183
38302
  const result = await testProvider.validateServiceAvailability({ timeoutMs: 1e4 });
38184
38303
  if (result.isAvailable) {
38185
38304
  showMessage("Connection successful! Provider is available.", "success");
@@ -38269,7 +38388,6 @@ var ProviderTab = () => {
38269
38388
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "ollama", children: "Ollama" }),
38270
38389
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "openai", children: "OpenAI" }),
38271
38390
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "azure-openai", children: "Azure OpenAI" }),
38272
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "anthropic", children: "Anthropic" }),
38273
38391
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "xai", children: "xAI" }),
38274
38392
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.MenuItem, { value: "playground", children: "Playground (Mock Demo)" })
38275
38393
  ]
@@ -38325,7 +38443,10 @@ var ProviderTab = () => {
38325
38443
  {
38326
38444
  label: "API Base URL",
38327
38445
  value: providerConfig.baseUrl || "",
38328
- onChange: (e) => setProviderConfig({ ...providerConfig, baseUrl: e.target.value }),
38446
+ onChange: (e) => setProviderConfig((prev) => ({
38447
+ ...prev,
38448
+ baseUrl: e.target.value
38449
+ })),
38329
38450
  fullWidth: true,
38330
38451
  sx: { mb: 2 },
38331
38452
  placeholder: "https://api.openai.com/v1"
@@ -38337,10 +38458,28 @@ var ProviderTab = () => {
38337
38458
  label: "API Key",
38338
38459
  type: "password",
38339
38460
  value: providerConfig.apiKey || "",
38340
- onChange: (e) => setProviderConfig({ ...providerConfig, apiKey: e.target.value }),
38461
+ onChange: (e) => setProviderConfig((prev) => ({
38462
+ ...prev,
38463
+ apiKey: e.target.value
38464
+ })),
38341
38465
  fullWidth: true,
38466
+ sx: { mb: 2 },
38342
38467
  placeholder: "sk-..."
38343
38468
  }
38469
+ ),
38470
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38471
+ import_material25.TextField,
38472
+ {
38473
+ label: "Default Model ID",
38474
+ value: providerConfig.defaultModel || "",
38475
+ onChange: (e) => setProviderConfig((prev) => ({
38476
+ ...prev,
38477
+ defaultModel: e.target.value
38478
+ })),
38479
+ fullWidth: true,
38480
+ placeholder: "gpt-4o-mini",
38481
+ helperText: "Example: gpt-4o-mini, gpt-4.1, gpt-3.5-turbo"
38482
+ }
38344
38483
  )
38345
38484
  ] }),
38346
38485
  providerConfig.type === "azure-openai" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Box, { children: [
@@ -38394,7 +38533,10 @@ var ProviderTab = () => {
38394
38533
  {
38395
38534
  label: "API Base URL",
38396
38535
  value: providerConfig.baseUrl || "",
38397
- onChange: (e) => setProviderConfig({ ...providerConfig, baseUrl: e.target.value }),
38536
+ onChange: (e) => setProviderConfig((prev) => ({
38537
+ ...prev,
38538
+ baseUrl: e.target.value
38539
+ })),
38398
38540
  fullWidth: true,
38399
38541
  sx: { mb: 2 },
38400
38542
  placeholder: "https://api.x.ai/v1"
@@ -38406,36 +38548,31 @@ var ProviderTab = () => {
38406
38548
  label: "API Key",
38407
38549
  type: "password",
38408
38550
  value: providerConfig.apiKey || "",
38409
- onChange: (e) => setProviderConfig({ ...providerConfig, apiKey: e.target.value }),
38410
- fullWidth: true,
38411
- placeholder: "xai-..."
38412
- }
38413
- )
38414
- ] }),
38415
- providerConfig.type === "anthropic" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Box, { children: [
38416
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38417
- import_material25.TextField,
38418
- {
38419
- label: "API Base URL",
38420
- value: providerConfig.baseUrl || "",
38421
- onChange: (e) => setProviderConfig({ ...providerConfig, baseUrl: e.target.value }),
38551
+ onChange: (e) => setProviderConfig((prev) => ({
38552
+ ...prev,
38553
+ apiKey: e.target.value
38554
+ })),
38422
38555
  fullWidth: true,
38423
38556
  sx: { mb: 2 },
38424
- placeholder: "https://api.anthropic.com"
38557
+ placeholder: "xai-..."
38425
38558
  }
38426
38559
  ),
38427
38560
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38428
38561
  import_material25.TextField,
38429
38562
  {
38430
- label: "API Key",
38431
- type: "password",
38432
- value: providerConfig.apiKey || "",
38433
- onChange: (e) => setProviderConfig({ ...providerConfig, apiKey: e.target.value }),
38563
+ label: "Default Model ID",
38564
+ value: providerConfig.defaultModel || "",
38565
+ onChange: (e) => setProviderConfig((prev) => ({
38566
+ ...prev,
38567
+ defaultModel: e.target.value
38568
+ })),
38434
38569
  fullWidth: true,
38435
- placeholder: "sk-ant-..."
38570
+ placeholder: "grok-beta",
38571
+ helperText: "Example: grok-beta, grok-2, grok-vision-beta"
38436
38572
  }
38437
38573
  )
38438
38574
  ] }),
38575
+ providerConfig.type === "anthropic" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Alert, { severity: "warning", sx: { mt: 2 }, children: "Anthropic is only supported through the Bandit Gateway provider. Please switch to Gateway and select Anthropic as the backend service." }),
38439
38576
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Box, { sx: { display: "flex", gap: 2, mt: 3 }, children: [
38440
38577
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38441
38578
  import_material25.Button,