@tonyclaw/llm-inspector 1.11.2 → 1.11.3

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.
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, R as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, R as RuntimeConfigSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-e-RbjELX.mjs";
2
+ import { C as CapturedLogSchema, R as RuntimeConfigSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-CChl8Zb8.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
5
5
  import { J as JSZip } from "../_libs/jszip.mjs";
@@ -255,7 +255,7 @@ async function exportLogsAsZip(logs) {
255
255
  document.body.removeChild(anchor);
256
256
  URL.revokeObjectURL(url);
257
257
  }
258
- const version = "1.11.2";
258
+ const version = "1.11.3";
259
259
  const packageJson = {
260
260
  version
261
261
  };
@@ -2937,7 +2937,8 @@ const KNOWN_PROVIDER_PRESETS = {
2937
2937
  },
2938
2938
  minimax: {
2939
2939
  format: "anthropic",
2940
- baseUrl: "https://api.minimaxi.com/anthropic"
2940
+ baseUrl: "https://api.minimaxi.com/anthropic",
2941
+ apiDocsUrl: "https://platform.minimaxi.com/docs/api-reference/api-overview"
2941
2942
  },
2942
2943
  alibaba: {
2943
2944
  format: "openai",
@@ -2945,6 +2946,7 @@ const KNOWN_PROVIDER_PRESETS = {
2945
2946
  }
2946
2947
  };
2947
2948
  const MINIMAX_MODELS = [
2949
+ "MiniMax M3",
2948
2950
  "MiniMax M2.7",
2949
2951
  "MiniMax M2.7-highspeed",
2950
2952
  "MiniMax M2.5",
@@ -2985,6 +2987,9 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
2985
2987
  setFormat(preset.format);
2986
2988
  setBaseUrl(preset.baseUrl);
2987
2989
  }
2990
+ if (preset.apiDocsUrl !== void 0 && !apiDocsUrl) {
2991
+ setApiDocsUrl(preset.apiDocsUrl);
2992
+ }
2988
2993
  if (keyword === "minimax" && !model) {
2989
2994
  setModel(MINIMAX_MODELS[0] ?? "");
2990
2995
  }
@@ -3331,11 +3336,17 @@ function ProvidersPanel({
3331
3336
  anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : void 0,
3332
3337
  openaiBaseUrl: data.format === "openai" ? data.baseUrl : void 0
3333
3338
  };
3334
- const res = await fetch("/api/providers", {
3335
- method: "POST",
3336
- headers: { "Content-Type": "application/json" },
3337
- body: JSON.stringify(payload)
3338
- });
3339
+ let res;
3340
+ try {
3341
+ res = await fetch("/api/providers", {
3342
+ method: "POST",
3343
+ headers: { "Content-Type": "application/json" },
3344
+ body: JSON.stringify(payload)
3345
+ });
3346
+ } catch (err) {
3347
+ setError("Network error: could not reach the server. Is the proxy running?");
3348
+ return;
3349
+ }
3339
3350
  if (!res.ok) {
3340
3351
  const err = await res.json();
3341
3352
  setError(err.error ?? "Failed to add provider");
@@ -3358,11 +3369,17 @@ function ProvidersPanel({
3358
3369
  anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : void 0,
3359
3370
  openaiBaseUrl: data.format === "openai" ? data.baseUrl : void 0
3360
3371
  };
3361
- const res = await fetch(`/api/providers/${editingProvider.id}`, {
3362
- method: "PUT",
3363
- headers: { "Content-Type": "application/json" },
3364
- body: JSON.stringify(payload)
3365
- });
3372
+ let res;
3373
+ try {
3374
+ res = await fetch(`/api/providers/${editingProvider.id}`, {
3375
+ method: "PUT",
3376
+ headers: { "Content-Type": "application/json" },
3377
+ body: JSON.stringify(payload)
3378
+ });
3379
+ } catch (err) {
3380
+ setError("Network error: could not reach the server. Is the proxy running?");
3381
+ return;
3382
+ }
3366
3383
  if (!res.ok) {
3367
3384
  const err = await res.json();
3368
3385
  setError(err.error ?? "Failed to update provider");
@@ -3377,9 +3394,15 @@ function ProvidersPanel({
3377
3394
  function handleDeleteProvider(providerId) {
3378
3395
  if (!window.confirm("Are you sure you want to delete this provider?")) return;
3379
3396
  void (async () => {
3380
- const res = await fetch(`/api/providers/${providerId}`, {
3381
- method: "DELETE"
3382
- });
3397
+ let res;
3398
+ try {
3399
+ res = await fetch(`/api/providers/${providerId}`, {
3400
+ method: "DELETE"
3401
+ });
3402
+ } catch (err) {
3403
+ setError("Network error: could not reach the server. Is the proxy running?");
3404
+ return;
3405
+ }
3383
3406
  if (!res.ok) {
3384
3407
  const err = await res.json();
3385
3408
  setError(err.error ?? "Failed to delete provider");
@@ -85,7 +85,7 @@ function getResponse() {
85
85
  }
86
86
  var HEADERS = { TSS_SHELL: "X-TSS_SHELL" };
87
87
  async function getStartManifest(matchedRoutes) {
88
- const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-C5P5lsG5.mjs");
88
+ const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-Crwqisvn.mjs");
89
89
  const startManifest = tsrStartManifest();
90
90
  let routes = startManifest.routes;
91
91
  routes[rootRouteId];
@@ -1157,7 +1157,7 @@ var getBaseManifest = getProdBaseManifest;
1157
1157
  var createEarlyHintsForRequest = createEarlyHintsCollector;
1158
1158
  async function loadEntries() {
1159
1159
  const [routerEntry, startEntry, pluginAdapters] = await Promise.all([
1160
- import("./router-e-RbjELX.mjs").then((n) => n.r),
1160
+ import("./router-CChl8Zb8.mjs").then((n) => n.r),
1161
1161
  import("./start-HYkvq4Ni.mjs"),
1162
1162
  import("./empty-plugin-adapters-BFgPZ6_d.mjs")
1163
1163
  ]);
@@ -66,7 +66,7 @@ function RootDocument({ children }) {
66
66
  ] })
67
67
  ] });
68
68
  }
69
- const $$splitComponentImporter = () => import("./index-CYuV1ljD.mjs");
69
+ const $$splitComponentImporter = () => import("./index-ByYDXUrF.mjs");
70
70
  const Route$g = createFileRoute("/")({
71
71
  component: lazyRouteComponent($$splitComponentImporter, "component")
72
72
  });
@@ -2408,7 +2408,8 @@ const ProviderInputSchema = object({
2408
2408
  name: string().min(1, "Name is required"),
2409
2409
  apiKey: string().min(1, "API key is required"),
2410
2410
  format: _enum(["anthropic", "openai"]),
2411
- baseUrl: string().min(1, "Base URL is required"),
2411
+ anthropicBaseUrl: string().optional(),
2412
+ openaiBaseUrl: string().optional(),
2412
2413
  model: string().min(1, "Model is required"),
2413
2414
  authHeader: _enum(["bearer", "x-api-key"]).optional().default("bearer"),
2414
2415
  apiDocsUrl: string().optional()
@@ -2428,7 +2429,7 @@ const Route$d = createFileRoute("/api/providers")({
2428
2429
  parsed.data.name,
2429
2430
  parsed.data.apiKey,
2430
2431
  parsed.data.format,
2431
- parsed.data.baseUrl,
2432
+ parsed.data.format === "anthropic" ? parsed.data.anthropicBaseUrl : parsed.data.openaiBaseUrl,
2432
2433
  parsed.data.model,
2433
2434
  parsed.data.authHeader,
2434
2435
  parsed.data.apiDocsUrl
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ routes: { __root__: { filePath: "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", children: ["/", "/api/config", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], preloads: ["/assets/index-Chp_30CP.js"], scripts: [{ attrs: { type: "module", async: true, src: "/assets/index-Chp_30CP.js" } }] }, "/": { filePath: "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", children: void 0, preloads: ["/assets/index-DLvqlFS9.js"] } } });
1
+ const tsrStartManifest = () => ({ routes: { __root__: { filePath: "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", children: ["/", "/api/config", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], preloads: ["/assets/index-CKy7R8oW.js"], scripts: [{ attrs: { type: "module", async: true, src: "/assets/index-CKy7R8oW.js" } }] }, "/": { filePath: "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", children: void 0, preloads: ["/assets/index-CSRjLK1k.js"] } } });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -38,51 +38,51 @@ const assets = {
38
38
  "/assets/alibaba-TTwafVwX.svg": {
39
39
  "type": "image/svg+xml",
40
40
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
41
- "mtime": "2026-06-06T09:13:20.378Z",
41
+ "mtime": "2026-06-06T09:31:31.372Z",
42
42
  "size": 5915,
43
43
  "path": "../public/assets/alibaba-TTwafVwX.svg"
44
44
  },
45
+ "/assets/index-BpKPXEcb.css": {
46
+ "type": "text/css; charset=utf-8",
47
+ "etag": '"11628-5GjLelHqc7BEfGB/7qUFPt5/gyM"',
48
+ "mtime": "2026-06-06T09:31:31.372Z",
49
+ "size": 71208,
50
+ "path": "../public/assets/index-BpKPXEcb.css"
51
+ },
45
52
  "/assets/minimax-BPMzvuL-.jpeg": {
46
53
  "type": "image/jpeg",
47
54
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
48
- "mtime": "2026-06-06T09:13:20.380Z",
55
+ "mtime": "2026-06-06T09:31:31.372Z",
49
56
  "size": 6918,
50
57
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
51
58
  },
52
- "/assets/index-BpKPXEcb.css": {
53
- "type": "text/css; charset=utf-8",
54
- "etag": '"11628-5GjLelHqc7BEfGB/7qUFPt5/gyM"',
55
- "mtime": "2026-06-06T09:13:20.380Z",
56
- "size": 71208,
57
- "path": "../public/assets/index-BpKPXEcb.css"
59
+ "/assets/index-CKy7R8oW.js": {
60
+ "type": "text/javascript; charset=utf-8",
61
+ "etag": '"5103c-DuZfMWELeZa9mIZKPKG6FD5Y+uE"',
62
+ "mtime": "2026-06-06T09:31:31.372Z",
63
+ "size": 331836,
64
+ "path": "../public/assets/index-CKy7R8oW.js"
58
65
  },
59
66
  "/assets/zhipuai-BPNAnxo-.svg": {
60
67
  "type": "image/svg+xml",
61
68
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
62
- "mtime": "2026-06-06T09:13:20.378Z",
69
+ "mtime": "2026-06-06T09:31:31.370Z",
63
70
  "size": 11256,
64
71
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
65
72
  },
66
73
  "/assets/qwen-CONDcHqt.png": {
67
74
  "type": "image/png",
68
75
  "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
69
- "mtime": "2026-06-06T09:13:20.378Z",
76
+ "mtime": "2026-06-06T09:31:31.372Z",
70
77
  "size": 357059,
71
78
  "path": "../public/assets/qwen-CONDcHqt.png"
72
79
  },
73
- "/assets/index-Chp_30CP.js": {
74
- "type": "text/javascript; charset=utf-8",
75
- "etag": '"5103c-5HK4V8mRGKw17pJ5x54GVb2N5bU"',
76
- "mtime": "2026-06-06T09:13:20.380Z",
77
- "size": 331836,
78
- "path": "../public/assets/index-Chp_30CP.js"
79
- },
80
- "/assets/index-DLvqlFS9.js": {
80
+ "/assets/index-CSRjLK1k.js": {
81
81
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"8b6f3-NmcxU8MkXNUN+0T4A/2Ajs2dUI4"',
83
- "mtime": "2026-06-06T09:13:20.380Z",
84
- "size": 571123,
85
- "path": "../public/assets/index-DLvqlFS9.js"
82
+ "etag": '"8b887-aEaYFR9Qp5UrFg7NUdOU4Zrq+D4"',
83
+ "mtime": "2026-06-06T09:31:31.373Z",
84
+ "size": 571527,
85
+ "path": "../public/assets/index-CSRjLK1k.js"
86
86
  }
87
87
  };
88
88
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/llm-inspector",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "type": "module",
5
5
  "description": "LLM API proxy inspector — captures and displays requests/responses from AI coding tools in a web UI",
6
6
  "license": "MIT",
@@ -3,24 +3,28 @@ import { Button } from "../ui/button";
3
3
  import type { ProviderConfig } from "../../proxy/providers";
4
4
 
5
5
  // Known provider presets - maps provider name keywords to their API URLs
6
- const KNOWN_PROVIDER_PRESETS: Record<string, { format: "anthropic" | "openai"; baseUrl: string }> =
7
- {
8
- deepseek: {
9
- format: "openai",
10
- baseUrl: "https://api.deepseek.com",
11
- },
12
- minimax: {
13
- format: "anthropic",
14
- baseUrl: "https://api.minimaxi.com/anthropic",
15
- },
16
- alibaba: {
17
- format: "openai",
18
- baseUrl: "https://dashscope.aliyuncs.com/compatible-mode",
19
- },
20
- };
6
+ const KNOWN_PROVIDER_PRESETS: Record<
7
+ string,
8
+ { format: "anthropic" | "openai"; baseUrl: string; apiDocsUrl?: string }
9
+ > = {
10
+ deepseek: {
11
+ format: "openai",
12
+ baseUrl: "https://api.deepseek.com",
13
+ },
14
+ minimax: {
15
+ format: "anthropic",
16
+ baseUrl: "https://api.minimaxi.com/anthropic",
17
+ apiDocsUrl: "https://platform.minimaxi.com/docs/api-reference/api-overview",
18
+ },
19
+ alibaba: {
20
+ format: "openai",
21
+ baseUrl: "https://dashscope.aliyuncs.com/compatible-mode",
22
+ },
23
+ };
21
24
 
22
25
  // MiniMax model options
23
26
  const MINIMAX_MODELS = [
27
+ "MiniMax M3",
24
28
  "MiniMax M2.7",
25
29
  "MiniMax M2.7-highspeed",
26
30
  "MiniMax M2.5",
@@ -85,6 +89,9 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
85
89
  setFormat(preset.format);
86
90
  setBaseUrl(preset.baseUrl);
87
91
  }
92
+ if (preset.apiDocsUrl !== undefined && !apiDocsUrl) {
93
+ setApiDocsUrl(preset.apiDocsUrl);
94
+ }
88
95
  // For MiniMax, auto-select the first model if not already set
89
96
  if (keyword === "minimax" && !model) {
90
97
  setModel(MINIMAX_MODELS[0] ?? "");
@@ -261,11 +261,17 @@ export function ProvidersPanel({
261
261
  anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : undefined,
262
262
  openaiBaseUrl: data.format === "openai" ? data.baseUrl : undefined,
263
263
  };
264
- const res = await fetch("/api/providers", {
265
- method: "POST",
266
- headers: { "Content-Type": "application/json" },
267
- body: JSON.stringify(payload),
268
- });
264
+ let res: Response;
265
+ try {
266
+ res = await fetch("/api/providers", {
267
+ method: "POST",
268
+ headers: { "Content-Type": "application/json" },
269
+ body: JSON.stringify(payload),
270
+ });
271
+ } catch (err) {
272
+ setError("Network error: could not reach the server. Is the proxy running?");
273
+ return;
274
+ }
269
275
  if (!res.ok) {
270
276
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
271
277
  const err = (await res.json()) as { error?: string };
@@ -299,11 +305,17 @@ export function ProvidersPanel({
299
305
  anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : undefined,
300
306
  openaiBaseUrl: data.format === "openai" ? data.baseUrl : undefined,
301
307
  };
302
- const res = await fetch(`/api/providers/${editingProvider.id}`, {
303
- method: "PUT",
304
- headers: { "Content-Type": "application/json" },
305
- body: JSON.stringify(payload),
306
- });
308
+ let res: Response;
309
+ try {
310
+ res = await fetch(`/api/providers/${editingProvider.id}`, {
311
+ method: "PUT",
312
+ headers: { "Content-Type": "application/json" },
313
+ body: JSON.stringify(payload),
314
+ });
315
+ } catch (err) {
316
+ setError("Network error: could not reach the server. Is the proxy running?");
317
+ return;
318
+ }
307
319
  if (!res.ok) {
308
320
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
309
321
  const err = (await res.json()) as { error?: string };
@@ -323,9 +335,15 @@ export function ProvidersPanel({
323
335
  // eslint-disable-next-line no-alert
324
336
  if (!window.confirm("Are you sure you want to delete this provider?")) return;
325
337
  void (async () => {
326
- const res = await fetch(`/api/providers/${providerId}`, {
327
- method: "DELETE",
328
- });
338
+ let res: Response;
339
+ try {
340
+ res = await fetch(`/api/providers/${providerId}`, {
341
+ method: "DELETE",
342
+ });
343
+ } catch (err) {
344
+ setError("Network error: could not reach the server. Is the proxy running?");
345
+ return;
346
+ }
329
347
  if (!res.ok) {
330
348
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
331
349
  const err = (await res.json()) as { error?: string };
@@ -6,7 +6,8 @@ const ProviderInputSchema = z.object({
6
6
  name: z.string().min(1, "Name is required"),
7
7
  apiKey: z.string().min(1, "API key is required"),
8
8
  format: z.enum(["anthropic", "openai"]),
9
- baseUrl: z.string().min(1, "Base URL is required"),
9
+ anthropicBaseUrl: z.string().optional(),
10
+ openaiBaseUrl: z.string().optional(),
10
11
  model: z.string().min(1, "Model is required"),
11
12
  authHeader: z.enum(["bearer", "x-api-key"]).optional().default("bearer"),
12
13
  apiDocsUrl: z.string().optional(),
@@ -27,7 +28,9 @@ export const Route = createFileRoute("/api/providers")({
27
28
  parsed.data.name,
28
29
  parsed.data.apiKey,
29
30
  parsed.data.format,
30
- parsed.data.baseUrl,
31
+ parsed.data.format === "anthropic"
32
+ ? parsed.data.anthropicBaseUrl
33
+ : parsed.data.openaiBaseUrl,
31
34
  parsed.data.model,
32
35
  parsed.data.authHeader,
33
36
  parsed.data.apiDocsUrl,