@tonyclaw/llm-inspector 1.7.3 → 1.7.4
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/.output/cli.js +22 -1
- package/.output/nitro.json +1 -1
- package/.output/server/_ssr/{index-D0iGQ1Zd.mjs → index-BauwiGgk.mjs} +1 -1
- package/.output/server/_ssr/index.mjs +1 -1
- package/.output/server/_ssr/{router-BWDeDWmr.mjs → router-DPnnefGg.mjs} +51 -51
- package/.output/server/index.mjs +18 -18
- package/package.json +1 -1
- package/src/cli.ts +24 -1
- package/src/proxy/providers.ts +66 -63
package/.output/cli.js
CHANGED
|
@@ -12,6 +12,8 @@ var portDefault = envPort !== void 0 ? Number(envPort) : DEFAULT_PORT;
|
|
|
12
12
|
var args = process.argv.slice(2);
|
|
13
13
|
var port = portDefault;
|
|
14
14
|
var open = true;
|
|
15
|
+
var configDir;
|
|
16
|
+
var providersJson;
|
|
15
17
|
for (let i = 0; i < args.length; i++) {
|
|
16
18
|
const arg = args[i] ?? "";
|
|
17
19
|
switch (arg) {
|
|
@@ -26,6 +28,14 @@ for (let i = 0; i < args.length; i++) {
|
|
|
26
28
|
case "--open":
|
|
27
29
|
open = true;
|
|
28
30
|
break;
|
|
31
|
+
case "--config-dir":
|
|
32
|
+
configDir = args[i + 1];
|
|
33
|
+
i++;
|
|
34
|
+
break;
|
|
35
|
+
case "--providers":
|
|
36
|
+
providersJson = args[i + 1];
|
|
37
|
+
i++;
|
|
38
|
+
break;
|
|
29
39
|
default:
|
|
30
40
|
break;
|
|
31
41
|
}
|
|
@@ -124,9 +134,20 @@ if (open) {
|
|
|
124
134
|
}
|
|
125
135
|
var outputDir = __dirname;
|
|
126
136
|
var serverPath = join(outputDir, "../.output/server/index.mjs");
|
|
137
|
+
var serverEnv = { ...process.env };
|
|
138
|
+
if (configDir !== void 0) {
|
|
139
|
+
let resolvedPath = join(configDir, "config.json");
|
|
140
|
+
if (resolvedPath.startsWith("\\c\\")) {
|
|
141
|
+
resolvedPath = "C:" + resolvedPath;
|
|
142
|
+
}
|
|
143
|
+
serverEnv["LLM_INSPECTOR_CONFIG_PATH"] = resolvedPath;
|
|
144
|
+
}
|
|
145
|
+
if (providersJson !== void 0) {
|
|
146
|
+
serverEnv["LLM_INSPECTOR_PROVIDERS_JSON"] = providersJson;
|
|
147
|
+
}
|
|
127
148
|
var serverProcess = spawn(process.execPath, [serverPath], {
|
|
128
149
|
stdio: ["ignore", "inherit", "inherit"],
|
|
129
150
|
detached: true,
|
|
130
|
-
env:
|
|
151
|
+
env: serverEnv
|
|
131
152
|
});
|
|
132
153
|
serverProcess.unref();
|
package/.output/nitro.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema, a as parseRequest, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-
|
|
2
|
+
import { C as CapturedLogSchema, a as parseRequest, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-DPnnefGg.mjs";
|
|
3
3
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
@@ -766,7 +766,7 @@ let entriesPromise;
|
|
|
766
766
|
let baseManifestPromise;
|
|
767
767
|
let cachedFinalManifestPromise;
|
|
768
768
|
async function loadEntries() {
|
|
769
|
-
const routerEntry = await import("./router-
|
|
769
|
+
const routerEntry = await import("./router-DPnnefGg.mjs").then((n) => n.r);
|
|
770
770
|
const startEntry = await import("./start-HYkvq4Ni.mjs");
|
|
771
771
|
return { startEntry, routerEntry };
|
|
772
772
|
}
|
|
@@ -65,7 +65,7 @@ function RootDocument({ children }) {
|
|
|
65
65
|
] })
|
|
66
66
|
] });
|
|
67
67
|
}
|
|
68
|
-
const $$splitComponentImporter = () => import("./index-
|
|
68
|
+
const $$splitComponentImporter = () => import("./index-BauwiGgk.mjs");
|
|
69
69
|
const Route$d = createFileRoute("/")({
|
|
70
70
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
71
71
|
});
|
|
@@ -1396,68 +1396,68 @@ const ProviderConfigSchema = object({
|
|
|
1396
1396
|
object({
|
|
1397
1397
|
providers: array(ProviderConfigSchema)
|
|
1398
1398
|
});
|
|
1399
|
+
const configPath = process.env["LLM_INSPECTOR_CONFIG_PATH"];
|
|
1399
1400
|
const store = new Conf({
|
|
1400
1401
|
projectName: "llm-inspector",
|
|
1401
1402
|
defaults: {
|
|
1402
1403
|
providers: []
|
|
1404
|
+
},
|
|
1405
|
+
...configPath !== void 0 ? { path: configPath } : {}
|
|
1406
|
+
});
|
|
1407
|
+
function migrateProvider(p) {
|
|
1408
|
+
const currentAnthropicUrl = p.anthropicBaseUrl ?? "";
|
|
1409
|
+
const currentOpenaiUrl = p.openaiBaseUrl ?? "";
|
|
1410
|
+
if (currentAnthropicUrl !== "" || currentOpenaiUrl !== "") {
|
|
1411
|
+
return p;
|
|
1412
|
+
}
|
|
1413
|
+
let format;
|
|
1414
|
+
let baseUrl;
|
|
1415
|
+
if (currentAnthropicUrl !== "" && currentOpenaiUrl !== "") {
|
|
1416
|
+
format = p.format ?? "anthropic";
|
|
1417
|
+
baseUrl = p.baseUrl !== void 0 && p.baseUrl !== "" ? p.baseUrl : currentAnthropicUrl;
|
|
1418
|
+
} else if (currentOpenaiUrl !== "") {
|
|
1419
|
+
format = "openai";
|
|
1420
|
+
baseUrl = currentOpenaiUrl;
|
|
1421
|
+
} else if (currentAnthropicUrl !== "") {
|
|
1422
|
+
format = "anthropic";
|
|
1423
|
+
baseUrl = currentAnthropicUrl;
|
|
1424
|
+
} else if (p.format !== void 0 && p.baseUrl !== void 0 && p.baseUrl !== "") {
|
|
1425
|
+
format = p.format;
|
|
1426
|
+
baseUrl = p.baseUrl;
|
|
1427
|
+
if (format === "openai") {
|
|
1428
|
+
return { ...p, format, baseUrl, anthropicBaseUrl: "", openaiBaseUrl: p.baseUrl };
|
|
1429
|
+
} else {
|
|
1430
|
+
return { ...p, format, baseUrl, anthropicBaseUrl: p.baseUrl, openaiBaseUrl: "" };
|
|
1431
|
+
}
|
|
1403
1432
|
}
|
|
1404
|
-
|
|
1433
|
+
return {
|
|
1434
|
+
...p,
|
|
1435
|
+
format,
|
|
1436
|
+
baseUrl,
|
|
1437
|
+
anthropicBaseUrl: currentAnthropicUrl,
|
|
1438
|
+
openaiBaseUrl: currentOpenaiUrl
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1405
1441
|
function migrateProviders() {
|
|
1406
1442
|
const providers = store.get("providers", []);
|
|
1407
|
-
|
|
1408
|
-
const
|
|
1409
|
-
function getOldUrl(obj, key) {
|
|
1410
|
-
if (obj !== null && typeof obj === "object") {
|
|
1411
|
-
const desc = Object.getOwnPropertyDescriptor(obj, key);
|
|
1412
|
-
if (desc !== void 0 && typeof desc.value === "string") {
|
|
1413
|
-
return desc.value;
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
return "";
|
|
1417
|
-
}
|
|
1418
|
-
const oldAnthropicBaseUrl = getOldUrl(p, "anthropicBaseUrl");
|
|
1419
|
-
const oldOpenaiBaseUrl = getOldUrl(p, "openaiBaseUrl");
|
|
1420
|
-
const currentAnthropicUrl = p.anthropicBaseUrl ?? "";
|
|
1421
|
-
const currentOpenaiUrl = p.openaiBaseUrl ?? "";
|
|
1422
|
-
if (p.format !== void 0 && (currentAnthropicUrl !== "" || currentOpenaiUrl !== "")) {
|
|
1423
|
-
return p;
|
|
1424
|
-
}
|
|
1425
|
-
const newAnthropicUrl = oldAnthropicBaseUrl !== "" ? oldAnthropicBaseUrl : currentAnthropicUrl;
|
|
1426
|
-
const newOpenaiUrl = oldOpenaiBaseUrl !== "" ? oldOpenaiBaseUrl : currentOpenaiUrl;
|
|
1427
|
-
let format;
|
|
1428
|
-
let baseUrl;
|
|
1429
|
-
if (newAnthropicUrl !== "" && newOpenaiUrl !== "") {
|
|
1430
|
-
format = p.format ?? "anthropic";
|
|
1431
|
-
baseUrl = p.baseUrl !== void 0 && p.baseUrl !== "" ? p.baseUrl : newAnthropicUrl;
|
|
1432
|
-
} else if (newOpenaiUrl !== "") {
|
|
1433
|
-
format = "openai";
|
|
1434
|
-
baseUrl = newOpenaiUrl;
|
|
1435
|
-
} else if (newAnthropicUrl !== "") {
|
|
1436
|
-
format = "anthropic";
|
|
1437
|
-
baseUrl = newAnthropicUrl;
|
|
1438
|
-
} else if (p.format !== void 0 && p.baseUrl !== void 0 && p.baseUrl !== "") {
|
|
1439
|
-
format = p.format;
|
|
1440
|
-
baseUrl = p.baseUrl;
|
|
1441
|
-
if (format === "openai") {
|
|
1442
|
-
return { ...p, format, baseUrl, anthropicBaseUrl: "", openaiBaseUrl: p.baseUrl };
|
|
1443
|
-
} else {
|
|
1444
|
-
return { ...p, format, baseUrl, anthropicBaseUrl: p.baseUrl, openaiBaseUrl: "" };
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
migrated = true;
|
|
1448
|
-
return {
|
|
1449
|
-
...p,
|
|
1450
|
-
format,
|
|
1451
|
-
baseUrl,
|
|
1452
|
-
anthropicBaseUrl: newAnthropicUrl,
|
|
1453
|
-
openaiBaseUrl: newOpenaiUrl
|
|
1454
|
-
};
|
|
1455
|
-
});
|
|
1443
|
+
const updated = providers.map(migrateProvider);
|
|
1444
|
+
const migrated = updated.some((p, i) => JSON.stringify(p) !== JSON.stringify(providers[i]));
|
|
1456
1445
|
if (migrated) {
|
|
1457
1446
|
store.set("providers", updated);
|
|
1458
1447
|
}
|
|
1459
1448
|
}
|
|
1460
1449
|
migrateProviders();
|
|
1450
|
+
const providersJson = process.env["LLM_INSPECTOR_PROVIDERS_JSON"];
|
|
1451
|
+
if (providersJson !== void 0) {
|
|
1452
|
+
try {
|
|
1453
|
+
const parsed = ProviderConfigSchema.array().safeParse(JSON.parse(providersJson));
|
|
1454
|
+
if (parsed.success) {
|
|
1455
|
+
const migrated = parsed.data.map(migrateProvider);
|
|
1456
|
+
store.set("providers", migrated);
|
|
1457
|
+
}
|
|
1458
|
+
} catch {
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
1461
|
function getProviders() {
|
|
1462
1462
|
return store.get("providers", []);
|
|
1463
1463
|
}
|
package/.output/server/index.mjs
CHANGED
|
@@ -100,49 +100,49 @@ const assets = {
|
|
|
100
100
|
"/assets/alibaba-TTwafVwX.svg": {
|
|
101
101
|
"type": "image/svg+xml",
|
|
102
102
|
"etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
|
|
103
|
-
"mtime": "2026-06-
|
|
103
|
+
"mtime": "2026-06-03T10:13:16.267Z",
|
|
104
104
|
"size": 5915,
|
|
105
105
|
"path": "../public/assets/alibaba-TTwafVwX.svg"
|
|
106
106
|
},
|
|
107
107
|
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
108
108
|
"type": "image/jpeg",
|
|
109
109
|
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
110
|
-
"mtime": "2026-06-
|
|
110
|
+
"mtime": "2026-06-03T10:13:16.267Z",
|
|
111
111
|
"size": 6918,
|
|
112
112
|
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
113
113
|
},
|
|
114
|
-
"/assets/index-B3RwBPLW.css": {
|
|
115
|
-
"type": "text/css; charset=utf-8",
|
|
116
|
-
"etag": '"10c74-aXacU4DRFVsUwcC5jHnjoPRSlTA"',
|
|
117
|
-
"mtime": "2026-06-03T09:45:53.063Z",
|
|
118
|
-
"size": 68724,
|
|
119
|
-
"path": "../public/assets/index-B3RwBPLW.css"
|
|
120
|
-
},
|
|
121
114
|
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
122
115
|
"type": "image/svg+xml",
|
|
123
116
|
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
124
|
-
"mtime": "2026-06-
|
|
117
|
+
"mtime": "2026-06-03T10:13:16.267Z",
|
|
125
118
|
"size": 11256,
|
|
126
119
|
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
127
120
|
},
|
|
121
|
+
"/assets/main-CpIX1ZHy.js": {
|
|
122
|
+
"type": "text/javascript; charset=utf-8",
|
|
123
|
+
"etag": '"4db57-PIyiLXQGvlFJuizUFXRhGOYXJwY"',
|
|
124
|
+
"mtime": "2026-06-03T10:13:16.269Z",
|
|
125
|
+
"size": 318295,
|
|
126
|
+
"path": "../public/assets/main-CpIX1ZHy.js"
|
|
127
|
+
},
|
|
128
128
|
"/assets/qwen-CONDcHqt.png": {
|
|
129
129
|
"type": "image/png",
|
|
130
130
|
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
131
|
-
"mtime": "2026-06-
|
|
131
|
+
"mtime": "2026-06-03T10:13:16.269Z",
|
|
132
132
|
"size": 357059,
|
|
133
133
|
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
134
134
|
},
|
|
135
|
-
"/assets/
|
|
136
|
-
"type": "text/
|
|
137
|
-
"etag": '"
|
|
138
|
-
"mtime": "2026-06-
|
|
139
|
-
"size":
|
|
140
|
-
"path": "../public/assets/
|
|
135
|
+
"/assets/index-B3RwBPLW.css": {
|
|
136
|
+
"type": "text/css; charset=utf-8",
|
|
137
|
+
"etag": '"10c74-aXacU4DRFVsUwcC5jHnjoPRSlTA"',
|
|
138
|
+
"mtime": "2026-06-03T10:13:16.269Z",
|
|
139
|
+
"size": 68724,
|
|
140
|
+
"path": "../public/assets/index-B3RwBPLW.css"
|
|
141
141
|
},
|
|
142
142
|
"/assets/index-Bf_WGooQ.js": {
|
|
143
143
|
"type": "text/javascript; charset=utf-8",
|
|
144
144
|
"etag": '"831df-gmdpd1CCnM4IdaxHIs9uyMgWFaY"',
|
|
145
|
-
"mtime": "2026-06-
|
|
145
|
+
"mtime": "2026-06-03T10:13:16.269Z",
|
|
146
146
|
"size": 537055,
|
|
147
147
|
"path": "../public/assets/index-Bf_WGooQ.js"
|
|
148
148
|
}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -16,6 +16,8 @@ const portDefault = envPort !== undefined ? Number(envPort) : DEFAULT_PORT;
|
|
|
16
16
|
const args = process.argv.slice(2);
|
|
17
17
|
let port = portDefault;
|
|
18
18
|
let open = true;
|
|
19
|
+
let configDir: string | undefined;
|
|
20
|
+
let providersJson: string | undefined;
|
|
19
21
|
|
|
20
22
|
for (let i = 0; i < args.length; i++) {
|
|
21
23
|
const arg = args[i] ?? "";
|
|
@@ -31,6 +33,14 @@ for (let i = 0; i < args.length; i++) {
|
|
|
31
33
|
case "--open":
|
|
32
34
|
open = true;
|
|
33
35
|
break;
|
|
36
|
+
case "--config-dir":
|
|
37
|
+
configDir = args[i + 1];
|
|
38
|
+
i++;
|
|
39
|
+
break;
|
|
40
|
+
case "--providers":
|
|
41
|
+
providersJson = args[i + 1];
|
|
42
|
+
i++;
|
|
43
|
+
break;
|
|
34
44
|
default:
|
|
35
45
|
break;
|
|
36
46
|
}
|
|
@@ -157,10 +167,23 @@ const outputDir = __dirname;
|
|
|
157
167
|
const serverPath = join(outputDir, "../.output/server/index.mjs");
|
|
158
168
|
|
|
159
169
|
// Start server with node
|
|
170
|
+
const serverEnv = { ...process.env };
|
|
171
|
+
if (configDir !== undefined) {
|
|
172
|
+
// Convert MSYS/Git Bash path like /c/Users/... to Windows absolute path
|
|
173
|
+
let resolvedPath = join(configDir, "config.json");
|
|
174
|
+
// Convert /c/... to C:\... format
|
|
175
|
+
if (resolvedPath.startsWith("\\c\\")) {
|
|
176
|
+
resolvedPath = "C:" + resolvedPath;
|
|
177
|
+
}
|
|
178
|
+
serverEnv["LLM_INSPECTOR_CONFIG_PATH"] = resolvedPath;
|
|
179
|
+
}
|
|
180
|
+
if (providersJson !== undefined) {
|
|
181
|
+
serverEnv["LLM_INSPECTOR_PROVIDERS_JSON"] = providersJson;
|
|
182
|
+
}
|
|
160
183
|
const serverProcess = spawn(process.execPath, [serverPath], {
|
|
161
184
|
stdio: ["ignore", "inherit", "inherit"],
|
|
162
185
|
detached: true,
|
|
163
|
-
env:
|
|
186
|
+
env: serverEnv,
|
|
164
187
|
});
|
|
165
188
|
|
|
166
189
|
serverProcess.unref();
|
package/src/proxy/providers.ts
CHANGED
|
@@ -31,82 +31,70 @@ type ProvidersStore = z.infer<typeof ProvidersStoreSchema>;
|
|
|
31
31
|
|
|
32
32
|
// Using conf for storage - works in any Node.js environment without Electron
|
|
33
33
|
// Note: conf stores data in plain JSON. For production, consider additional encryption.
|
|
34
|
+
const configPath = process.env["LLM_INSPECTOR_CONFIG_PATH"];
|
|
34
35
|
export const store = new Conf<ProvidersStore>({
|
|
35
36
|
projectName: "llm-inspector",
|
|
36
37
|
defaults: {
|
|
37
38
|
providers: [],
|
|
38
39
|
},
|
|
40
|
+
...(configPath !== undefined ? { path: configPath } : {}),
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
/**
|
|
42
|
-
* Migrates
|
|
43
|
-
* Old configs had anthropicBaseUrl/openaiBaseUrl, we now keep both.
|
|
44
|
+
* Migrates a single provider config to preserve both Anthropic and OpenAI URLs.
|
|
44
45
|
*/
|
|
45
|
-
function
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (desc !== undefined && typeof desc.value === "string") {
|
|
55
|
-
return desc.value;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return "";
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const oldAnthropicBaseUrl = getOldUrl(p, "anthropicBaseUrl");
|
|
62
|
-
const oldOpenaiBaseUrl = getOldUrl(p, "openaiBaseUrl");
|
|
63
|
-
const currentAnthropicUrl = p.anthropicBaseUrl ?? "";
|
|
64
|
-
const currentOpenaiUrl = p.openaiBaseUrl ?? "";
|
|
65
|
-
|
|
66
|
-
// If already migrated (has format field and at least one URL), skip
|
|
67
|
-
if (p.format !== undefined && (currentAnthropicUrl !== "" || currentOpenaiUrl !== "")) {
|
|
68
|
-
return p;
|
|
69
|
-
}
|
|
46
|
+
export function migrateProvider(p: ProviderConfig): ProviderConfig {
|
|
47
|
+
const currentAnthropicUrl = p.anthropicBaseUrl ?? "";
|
|
48
|
+
const currentOpenaiUrl = p.openaiBaseUrl ?? "";
|
|
49
|
+
|
|
50
|
+
// If already migrated (has at least one URL set), skip
|
|
51
|
+
// format may be undefined but if URL is set, it's already migrated
|
|
52
|
+
if (currentAnthropicUrl !== "" || currentOpenaiUrl !== "") {
|
|
53
|
+
return p;
|
|
54
|
+
}
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
baseUrl
|
|
93
|
-
if (format === "openai") {
|
|
94
|
-
return { ...p, format, baseUrl, anthropicBaseUrl: "", openaiBaseUrl: p.baseUrl };
|
|
95
|
-
} else {
|
|
96
|
-
return { ...p, format, baseUrl, anthropicBaseUrl: p.baseUrl, openaiBaseUrl: "" };
|
|
97
|
-
}
|
|
56
|
+
// Determine primary format based on which URL is set
|
|
57
|
+
let format: "anthropic" | "openai" | undefined;
|
|
58
|
+
let baseUrl: string | undefined;
|
|
59
|
+
|
|
60
|
+
if (currentAnthropicUrl !== "" && currentOpenaiUrl !== "") {
|
|
61
|
+
// Both URLs set - prefer anthropic as default, use baseUrl for backward compat
|
|
62
|
+
format = p.format ?? "anthropic";
|
|
63
|
+
baseUrl = p.baseUrl !== undefined && p.baseUrl !== "" ? p.baseUrl : currentAnthropicUrl;
|
|
64
|
+
} else if (currentOpenaiUrl !== "") {
|
|
65
|
+
format = "openai";
|
|
66
|
+
baseUrl = currentOpenaiUrl;
|
|
67
|
+
} else if (currentAnthropicUrl !== "") {
|
|
68
|
+
format = "anthropic";
|
|
69
|
+
baseUrl = currentAnthropicUrl;
|
|
70
|
+
} else if (p.format !== undefined && p.baseUrl !== undefined && p.baseUrl !== "") {
|
|
71
|
+
// Only baseUrl is set (legacy config) - migrate based on format
|
|
72
|
+
format = p.format;
|
|
73
|
+
baseUrl = p.baseUrl;
|
|
74
|
+
if (format === "openai") {
|
|
75
|
+
return { ...p, format, baseUrl, anthropicBaseUrl: "", openaiBaseUrl: p.baseUrl };
|
|
76
|
+
} else {
|
|
77
|
+
return { ...p, format, baseUrl, anthropicBaseUrl: p.baseUrl, openaiBaseUrl: "" };
|
|
98
78
|
}
|
|
79
|
+
}
|
|
99
80
|
|
|
100
|
-
|
|
81
|
+
return {
|
|
82
|
+
...p,
|
|
83
|
+
format,
|
|
84
|
+
baseUrl,
|
|
85
|
+
anthropicBaseUrl: currentAnthropicUrl,
|
|
86
|
+
openaiBaseUrl: currentOpenaiUrl,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
101
89
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Migrates existing provider configs to preserve both Anthropic and OpenAI URLs.
|
|
92
|
+
* Old configs had anthropicBaseUrl/openaiBaseUrl, we now keep both.
|
|
93
|
+
*/
|
|
94
|
+
function migrateProviders(): void {
|
|
95
|
+
const providers = store.get("providers", []);
|
|
96
|
+
const updated = providers.map(migrateProvider);
|
|
97
|
+
const migrated = updated.some((p, i) => JSON.stringify(p) !== JSON.stringify(providers[i]));
|
|
110
98
|
|
|
111
99
|
if (migrated) {
|
|
112
100
|
store.set("providers", updated);
|
|
@@ -116,6 +104,21 @@ function migrateProviders(): void {
|
|
|
116
104
|
// Run migration on module load
|
|
117
105
|
migrateProviders();
|
|
118
106
|
|
|
107
|
+
// Override with JSON env var if provided (for testing)
|
|
108
|
+
const providersJson = process.env["LLM_INSPECTOR_PROVIDERS_JSON"];
|
|
109
|
+
if (providersJson !== undefined) {
|
|
110
|
+
try {
|
|
111
|
+
const parsed = ProviderConfigSchema.array().safeParse(JSON.parse(providersJson));
|
|
112
|
+
if (parsed.success) {
|
|
113
|
+
// Apply migration to JSON providers (e.g., convert baseUrl to openaiBaseUrl/anthropicBaseUrl)
|
|
114
|
+
const migrated = parsed.data.map(migrateProvider);
|
|
115
|
+
store.set("providers", migrated);
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// Ignore invalid JSON
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
119
122
|
export function getProviders(): ProviderConfig[] {
|
|
120
123
|
return store.get("providers", []);
|
|
121
124
|
}
|