@tonyclaw/llm-inspector 1.7.7 → 1.7.9

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.
@@ -7,7 +7,7 @@ import { C as Conf } from "../_libs/conf.mjs";
7
7
  import { randomUUID } from "crypto";
8
8
  import { exec } from "node:child_process";
9
9
  import { promisify } from "node:util";
10
- import { o as object, _ as _enum, s as string, a as array, n as number, d as discriminatedUnion, l as literal, b as boolean, r as record, c as lazy, e as _null, u as union } from "../_libs/zod.mjs";
10
+ import { o as object, _ as _enum, s as string, u as union, a as array, n as number, d as discriminatedUnion, l as literal, b as boolean, r as record, c as lazy, e as _null, f as unknown } from "../_libs/zod.mjs";
11
11
  import "../_libs/tiny-warning.mjs";
12
12
  import "../_libs/tanstack__router-core.mjs";
13
13
  import "../_libs/cookie-es.mjs";
@@ -42,7 +42,7 @@ import "../_libs/mimic-function.mjs";
42
42
  import "../_libs/semver.mjs";
43
43
  import "../_libs/uint8array-extras.mjs";
44
44
  const appCss = "/assets/index-B3RwBPLW.css";
45
- const Route$e = createRootRoute({
45
+ const Route$g = createRootRoute({
46
46
  head: () => ({
47
47
  meta: [
48
48
  { charSet: "utf-8" },
@@ -65,8 +65,8 @@ function RootDocument({ children }) {
65
65
  ] })
66
66
  ] });
67
67
  }
68
- const $$splitComponentImporter = () => import("./index-DbpsE3Y4.mjs");
69
- const Route$d = createFileRoute("/")({
68
+ const $$splitComponentImporter = () => import("./index-CAIDMqNv.mjs");
69
+ const Route$f = createFileRoute("/")({
70
70
  component: lazyRouteComponent($$splitComponentImporter, "component")
71
71
  });
72
72
  const LOG_DIR_ENV = process.env["LOG_DIR"];
@@ -939,9 +939,10 @@ function extractAnthropicStream(raw, log, fallbackModel, collectChunks) {
939
939
  let streamStartMs = 0;
940
940
  const chunks = [];
941
941
  for (const line of raw.split("\n")) {
942
- if (!line.startsWith("data: ")) continue;
942
+ const trimmedLine = line.trim();
943
+ if (!trimmedLine.startsWith("data: ")) continue;
943
944
  try {
944
- const json = JSON.parse(line.slice(6));
945
+ const json = JSON.parse(trimmedLine.slice(6));
945
946
  const parsed = SseEventSchema.safeParse(json);
946
947
  if (!parsed.success) continue;
947
948
  const data = parsed.data;
@@ -1175,8 +1176,9 @@ function extractOpenAIStream(raw, log, fallbackModel, collectChunks = true) {
1175
1176
  let streamStartMs = 0;
1176
1177
  const chunks = [];
1177
1178
  for (const line of raw.split("\n")) {
1178
- if (!line.startsWith("data: ")) continue;
1179
- const dataStr = line.slice(6).trim();
1179
+ const trimmedLine = line.trim();
1180
+ if (!trimmedLine.startsWith("data: ")) continue;
1181
+ const dataStr = trimmedLine.slice(6);
1180
1182
  if (dataStr === "[DONE]") break;
1181
1183
  try {
1182
1184
  const parsed = JSON.parse(dataStr);
@@ -1518,6 +1520,74 @@ function deleteProvider(id) {
1518
1520
  store.set("providers", filtered);
1519
1521
  return true;
1520
1522
  }
1523
+ function exportProviders() {
1524
+ const providers = getProviders();
1525
+ const safeProviders = providers.map(({ apiKey, ...rest }) => ({
1526
+ ...rest,
1527
+ apiKey: maskApiKey(apiKey)
1528
+ }));
1529
+ return JSON.stringify(safeProviders, null, 2);
1530
+ }
1531
+ function exportProvidersWithKeys() {
1532
+ return JSON.stringify(getProviders(), null, 2);
1533
+ }
1534
+ function importProviders(json) {
1535
+ const errors = [];
1536
+ let imported = 0;
1537
+ try {
1538
+ const parsed = JSON.parse(json);
1539
+ const ImportSchema = union([
1540
+ array(ProviderConfigSchema),
1541
+ object({
1542
+ providers: array(ProviderConfigSchema)
1543
+ })
1544
+ ]);
1545
+ const parseResult = ImportSchema.safeParse(parsed);
1546
+ if (!parseResult.success) {
1547
+ return {
1548
+ imported: 0,
1549
+ errors: [`Invalid format: ${parseResult.error.message}`]
1550
+ };
1551
+ }
1552
+ const providerArray = Array.isArray(parseResult.data) ? parseResult.data : parseResult.data.providers;
1553
+ for (let i = 0; i < providerArray.length; i++) {
1554
+ const item = providerArray[i];
1555
+ const result = ProviderConfigSchema.safeParse(item);
1556
+ if (!result.success) {
1557
+ errors.push(`Provider ${i + 1}: ${result.error.message}`);
1558
+ continue;
1559
+ }
1560
+ const provider = result.data;
1561
+ const existing = getProviders().find(
1562
+ (p) => p.name === provider.name && p.anthropicBaseUrl === provider.anthropicBaseUrl
1563
+ );
1564
+ if (existing) {
1565
+ errors.push(`Provider "${provider.name}" already exists, skipping`);
1566
+ continue;
1567
+ }
1568
+ const newProvider = {
1569
+ ...provider,
1570
+ id: randomUUID(),
1571
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1572
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1573
+ };
1574
+ const providers = getProviders();
1575
+ providers.push(newProvider);
1576
+ store.set("providers", providers);
1577
+ imported++;
1578
+ }
1579
+ } catch (err) {
1580
+ return {
1581
+ imported: 0,
1582
+ errors: [`Failed to parse JSON: ${err instanceof Error ? err.message : String(err)}`]
1583
+ };
1584
+ }
1585
+ return { imported, errors };
1586
+ }
1587
+ function maskApiKey(apiKey) {
1588
+ if (apiKey.length <= 8) return "••••••••";
1589
+ return apiKey.slice(0, 4) + "••••••••" + apiKey.slice(-4);
1590
+ }
1521
1591
  function getModelUsageName(model, providerName) {
1522
1592
  if (providerName !== void 0 && providerName !== "" && providerName.toLowerCase().includes("minimax")) {
1523
1593
  return model.replace(/ /g, "-");
@@ -1694,6 +1764,9 @@ function parseRequestPath(req, url) {
1694
1764
  };
1695
1765
  }
1696
1766
  function buildUpstreamUrl$1(upstreamBase, normalizedPath) {
1767
+ if (upstreamBase.endsWith("/v1") && normalizedPath.startsWith("/v1/")) {
1768
+ return upstreamBase + normalizedPath.slice(3);
1769
+ }
1697
1770
  return upstreamBase + normalizedPath;
1698
1771
  }
1699
1772
  function selectUpstreamBase$1(isChatCompletions, matchedProviderConfig) {
@@ -1875,7 +1948,7 @@ function findProviderByModelFromConfig(requestBody) {
1875
1948
  if (model === null) return null;
1876
1949
  return findProviderByModel(model);
1877
1950
  }
1878
- const Route$c = createFileRoute("/proxy/$")({
1951
+ const Route$e = createFileRoute("/proxy/$")({
1879
1952
  server: {
1880
1953
  handlers: {
1881
1954
  GET: ({ request }) => handleProxy(request),
@@ -1887,7 +1960,7 @@ const Route$c = createFileRoute("/proxy/$")({
1887
1960
  }
1888
1961
  }
1889
1962
  });
1890
- const Route$b = createFileRoute("/api/sessions")({
1963
+ const Route$d = createFileRoute("/api/sessions")({
1891
1964
  server: {
1892
1965
  handlers: {
1893
1966
  GET: () => Response.json(getSessions())
@@ -1902,7 +1975,7 @@ const ProviderInputSchema = object({
1902
1975
  model: string().min(1, "Model is required"),
1903
1976
  authHeader: _enum(["bearer", "x-api-key"]).optional().default("bearer")
1904
1977
  });
1905
- const Route$a = createFileRoute("/api/providers")({
1978
+ const Route$c = createFileRoute("/api/providers")({
1906
1979
  server: {
1907
1980
  handlers: {
1908
1981
  GET: () => {
@@ -1926,14 +1999,14 @@ const Route$a = createFileRoute("/api/providers")({
1926
1999
  }
1927
2000
  }
1928
2001
  });
1929
- const Route$9 = createFileRoute("/api/models")({
2002
+ const Route$b = createFileRoute("/api/models")({
1930
2003
  server: {
1931
2004
  handlers: {
1932
2005
  GET: () => Response.json(getModels())
1933
2006
  }
1934
2007
  }
1935
2008
  });
1936
- const Route$8 = createFileRoute("/api/logs")({
2009
+ const Route$a = createFileRoute("/api/logs")({
1937
2010
  server: {
1938
2011
  handlers: {
1939
2012
  GET: ({ request }) => {
@@ -1958,7 +2031,7 @@ const Route$8 = createFileRoute("/api/logs")({
1958
2031
  }
1959
2032
  }
1960
2033
  });
1961
- const Route$7 = createFileRoute("/api/health")({
2034
+ const Route$9 = createFileRoute("/api/health")({
1962
2035
  server: {
1963
2036
  handlers: {
1964
2037
  GET: () => {
@@ -1967,6 +2040,58 @@ const Route$7 = createFileRoute("/api/health")({
1967
2040
  }
1968
2041
  }
1969
2042
  });
2043
+ union([string(), object({ providers: unknown() })]);
2044
+ const Route$8 = createFileRoute("/api/providers/import")({
2045
+ server: {
2046
+ handlers: {
2047
+ POST: async ({ request }) => {
2048
+ try {
2049
+ const rawBody = await request.text();
2050
+ let jsonContent;
2051
+ try {
2052
+ const parsedBody = JSON.parse(rawBody);
2053
+ jsonContent = typeof parsedBody === "string" ? parsedBody : JSON.stringify(parsedBody);
2054
+ } catch {
2055
+ jsonContent = rawBody;
2056
+ }
2057
+ if (!jsonContent || jsonContent.trim() === "") {
2058
+ return Response.json({ error: "No JSON content provided" }, { status: 400 });
2059
+ }
2060
+ const result = importProviders(jsonContent);
2061
+ return Response.json({
2062
+ success: result.imported > 0,
2063
+ imported: result.imported,
2064
+ errors: result.errors,
2065
+ message: result.imported > 0 ? `Successfully imported ${result.imported} provider(s)` : result.errors.length > 0 ? `Import completed with ${result.errors.length} error(s)` : "No providers imported"
2066
+ });
2067
+ } catch (err) {
2068
+ return Response.json(
2069
+ { error: `Failed to import: ${err instanceof Error ? err.message : String(err)}` },
2070
+ { status: 400 }
2071
+ );
2072
+ }
2073
+ }
2074
+ }
2075
+ }
2076
+ });
2077
+ const Route$7 = createFileRoute("/api/providers/export")({
2078
+ server: {
2079
+ handlers: {
2080
+ GET: ({ request }) => {
2081
+ const url = new URL(request.url);
2082
+ const includeKeys = url.searchParams.get("includeKeys") === "true";
2083
+ const json = includeKeys ? exportProvidersWithKeys() : exportProviders();
2084
+ const filename = includeKeys ? `llm-inspector-providers-${Date.now()}.json` : `llm-inspector-providers-safe-${Date.now()}.json`;
2085
+ return new Response(json, {
2086
+ headers: {
2087
+ "Content-Type": "application/json",
2088
+ "Content-Disposition": `attachment; filename="${filename}"`
2089
+ }
2090
+ });
2091
+ }
2092
+ }
2093
+ }
2094
+ });
1970
2095
  const ProviderUpdateSchema = object({
1971
2096
  name: string().min(1, "Name is required").optional(),
1972
2097
  apiKey: string().min(1, "API key is required").optional(),
@@ -2104,30 +2229,76 @@ const ERROR_HINTS = {
2104
2229
  const MAX_ERROR_DETAILS_LENGTH = 200;
2105
2230
  function classifyError(error, responseStatus) {
2106
2231
  const errorStr = String(error);
2232
+ const errorLower = errorStr.toLowerCase();
2107
2233
  if (error instanceof Error && error.name === "AbortError") {
2108
- return { type: "timeout", details: "Request was aborted due to timeout" };
2234
+ return { type: "timeout", details: "Request was aborted (timeout)" };
2235
+ }
2236
+ if (errorLower.includes("timeout") || errorLower.includes("timed out") || errorLower.includes("etimedout") || errorLower.includes("esockettimedout") || errorLower.includes("socket hang up") || errorLower.includes("peer terminating")) {
2237
+ return { type: "timeout", details: extractErrorDetails(errorStr) };
2238
+ }
2239
+ if (errorLower.includes("econnrefused") || errorLower.includes("connection refused") || errorLower.includes("econrefused")) {
2240
+ return { type: "connection_refused", details: extractErrorDetails(errorStr) };
2241
+ }
2242
+ if (errorLower.includes("enotfound") || errorLower.includes("getaddrinfo") || errorLower.includes("dns lookup") || errorLower.includes("name or service not known") || errorLower.includes("network is unreachable") || errorLower.includes("enetunreach") || errorLower.includes("fetch failed") || errorLower.includes("failed to fetch") || errorLower.includes("networkerror")) {
2243
+ return { type: "network_unreachable", details: extractErrorDetails(errorStr) };
2109
2244
  }
2110
- if (errorStr.includes("timeout") || errorStr.includes("timed out") || errorStr.includes("Timeout")) {
2111
- return { type: "timeout", details: truncateErrorDetails(errorStr) };
2245
+ if (errorLower.includes("econnreset") || errorLower.includes("connection reset") || errorLower.includes("ECONNRESET")) {
2246
+ return { type: "connection_refused", details: "Connection was reset by server" };
2112
2247
  }
2113
- if (errorStr.includes("ECONNREFUSED") || errorStr.includes("connection refused")) {
2114
- return { type: "connection_refused", details: truncateErrorDetails(errorStr) };
2248
+ if (errorLower.includes("tls") || errorLower.includes("ssl") || errorLower.includes("certificate") || errorLower.includes("self signed") || errorLower.includes("unable to verify") || errorLower.includes("sec_error") || errorLower.includes("securitypolicy")) {
2249
+ return { type: "network_unreachable", details: "SSL/TLS certificate error" };
2250
+ }
2251
+ if (errorLower.includes("proxy") || errorLower.includes("tunneling") || errorLower.includes("eproto")) {
2252
+ return { type: "network_unreachable", details: extractErrorDetails(errorStr) };
2253
+ }
2254
+ if (errorLower.includes("cors") || errorLower.includes("cross-origin") || errorLower.includes("access-control")) {
2255
+ return {
2256
+ type: "network_unreachable",
2257
+ details: "CORS error - check your server's CORS configuration"
2258
+ };
2115
2259
  }
2116
- if (errorStr.includes("ENOTFOUND") || errorStr.includes("getaddrinfo") || errorStr.includes("DNS") || errorStr.includes("network") || errorStr.includes("fetch failed")) {
2117
- return { type: "network_unreachable", details: truncateErrorDetails(errorStr) };
2260
+ if (errorLower.includes("invalid url") || errorLower.includes("url invalid") || errorLower.includes("etype") || errorLower.includes("err_invalid_url")) {
2261
+ return { type: "network_unreachable", details: "Invalid URL - check your provider base URL" };
2262
+ }
2263
+ if (errorLower.includes("empty response") || errorLower.includes("aborted") || errorLower.includes("premature close") || errorLower.includes("incomplete read")) {
2264
+ return { type: "invalid_response", details: "Server closed connection prematurely" };
2265
+ }
2266
+ if (errorLower.includes("bad gateway") || errorLower.includes("gateway timeout")) {
2267
+ return { type: "server_error", details: extractErrorDetails(errorStr) };
2118
2268
  }
2119
2269
  if (responseStatus !== void 0) {
2120
2270
  if (responseStatus === 401 || responseStatus === 403) {
2121
- return { type: "auth_failed", details: `HTTP ${responseStatus}` };
2271
+ return { type: "auth_failed", details: `Authentication failed (HTTP ${responseStatus})` };
2272
+ }
2273
+ if (responseStatus === 407) {
2274
+ return { type: "auth_failed", details: "Proxy authentication required (HTTP 407)" };
2122
2275
  }
2123
2276
  if (responseStatus === 429) {
2124
- return { type: "rate_limited", details: `HTTP ${responseStatus}` };
2277
+ return { type: "rate_limited", details: "Rate limited - try again later (HTTP 429)" };
2125
2278
  }
2126
2279
  if (responseStatus >= 500 && responseStatus < 600) {
2127
- return { type: "server_error", details: `HTTP ${responseStatus}` };
2280
+ return { type: "server_error", details: `Server error (HTTP ${responseStatus})` };
2281
+ }
2282
+ if (responseStatus === 400) {
2283
+ return {
2284
+ type: "invalid_response",
2285
+ details: "Bad request (HTTP 400) - check your model name and parameters"
2286
+ };
2287
+ }
2288
+ if (responseStatus === 404) {
2289
+ return {
2290
+ type: "network_unreachable",
2291
+ details: "Endpoint not found (HTTP 404) - check your base URL"
2292
+ };
2128
2293
  }
2129
2294
  }
2130
- return { type: "unknown", details: truncateErrorDetails(errorStr) };
2295
+ return { type: "unknown", details: extractErrorDetails(errorStr) };
2296
+ }
2297
+ function extractErrorDetails(errorStr) {
2298
+ let details = errorStr.replace(/^TypeError:\s*/i, "");
2299
+ details = details.replace(/^Error:\s*/i, "");
2300
+ details = details.replace(/^fetch failed:\s*/i, "");
2301
+ return truncateErrorDetails(details);
2131
2302
  }
2132
2303
  function truncateErrorDetails(details) {
2133
2304
  if (details.length <= MAX_ERROR_DETAILS_LENGTH) {
@@ -2330,11 +2501,26 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
2330
2501
  };
2331
2502
  }
2332
2503
  const decoder = new TextDecoder();
2504
+ const MAX_CHUNKS_SIZE = 10 * 1024 * 1024;
2505
+ let totalSize = 0;
2333
2506
  try {
2334
2507
  while (true) {
2335
2508
  const { done, value } = await reader.read();
2336
2509
  if (done) break;
2337
- chunks.push(decoder.decode(value, { stream: true }));
2510
+ if (totalSize >= MAX_CHUNKS_SIZE) {
2511
+ return createErrorResult(
2512
+ "Response too large (exceeded 10MB limit)",
2513
+ Date.now() - startTime,
2514
+ true
2515
+ );
2516
+ }
2517
+ const decoded = decoder.decode(value, { stream: true });
2518
+ totalSize += decoded.length;
2519
+ chunks.push(decoded);
2520
+ }
2521
+ const finalChunk = decoder.decode();
2522
+ if (finalChunk) {
2523
+ chunks.push(finalChunk);
2338
2524
  }
2339
2525
  } catch (readErr) {
2340
2526
  return createErrorResult(`Stream read error: ${readErr}`, latencyMs, true);
@@ -2851,40 +3037,50 @@ const Route = createFileRoute("/api/logs/$id/chunks")({
2851
3037
  }
2852
3038
  }
2853
3039
  });
2854
- const IndexRoute = Route$d.update({
3040
+ const IndexRoute = Route$f.update({
2855
3041
  id: "/",
2856
3042
  path: "/",
2857
- getParentRoute: () => Route$e
3043
+ getParentRoute: () => Route$g
2858
3044
  });
2859
- const ProxySplatRoute = Route$c.update({
3045
+ const ProxySplatRoute = Route$e.update({
2860
3046
  id: "/proxy/$",
2861
3047
  path: "/proxy/$",
2862
- getParentRoute: () => Route$e
3048
+ getParentRoute: () => Route$g
2863
3049
  });
2864
- const ApiSessionsRoute = Route$b.update({
3050
+ const ApiSessionsRoute = Route$d.update({
2865
3051
  id: "/api/sessions",
2866
3052
  path: "/api/sessions",
2867
- getParentRoute: () => Route$e
3053
+ getParentRoute: () => Route$g
2868
3054
  });
2869
- const ApiProvidersRoute = Route$a.update({
3055
+ const ApiProvidersRoute = Route$c.update({
2870
3056
  id: "/api/providers",
2871
3057
  path: "/api/providers",
2872
- getParentRoute: () => Route$e
3058
+ getParentRoute: () => Route$g
2873
3059
  });
2874
- const ApiModelsRoute = Route$9.update({
3060
+ const ApiModelsRoute = Route$b.update({
2875
3061
  id: "/api/models",
2876
3062
  path: "/api/models",
2877
- getParentRoute: () => Route$e
3063
+ getParentRoute: () => Route$g
2878
3064
  });
2879
- const ApiLogsRoute = Route$8.update({
3065
+ const ApiLogsRoute = Route$a.update({
2880
3066
  id: "/api/logs",
2881
3067
  path: "/api/logs",
2882
- getParentRoute: () => Route$e
3068
+ getParentRoute: () => Route$g
2883
3069
  });
2884
- const ApiHealthRoute = Route$7.update({
3070
+ const ApiHealthRoute = Route$9.update({
2885
3071
  id: "/api/health",
2886
3072
  path: "/api/health",
2887
- getParentRoute: () => Route$e
3073
+ getParentRoute: () => Route$g
3074
+ });
3075
+ const ApiProvidersImportRoute = Route$8.update({
3076
+ id: "/import",
3077
+ path: "/import",
3078
+ getParentRoute: () => ApiProvidersRoute
3079
+ });
3080
+ const ApiProvidersExportRoute = Route$7.update({
3081
+ id: "/export",
3082
+ path: "/export",
3083
+ getParentRoute: () => ApiProvidersRoute
2888
3084
  });
2889
3085
  const ApiProvidersProviderIdRoute = Route$6.update({
2890
3086
  id: "/$providerId",
@@ -2904,7 +3100,7 @@ const ApiLogsIdRoute = Route$4.update({
2904
3100
  const ApiConfigPathsRoute = Route$3.update({
2905
3101
  id: "/api/config/paths",
2906
3102
  path: "/api/config/paths",
2907
- getParentRoute: () => Route$e
3103
+ getParentRoute: () => Route$g
2908
3104
  });
2909
3105
  const ApiProvidersProviderIdTestRoute = Route$2.update({
2910
3106
  id: "/test",
@@ -2940,7 +3136,9 @@ const ApiProvidersProviderIdRouteWithChildren = ApiProvidersProviderIdRoute._add
2940
3136
  ApiProvidersProviderIdRouteChildren
2941
3137
  );
2942
3138
  const ApiProvidersRouteChildren = {
2943
- ApiProvidersProviderIdRoute: ApiProvidersProviderIdRouteWithChildren
3139
+ ApiProvidersProviderIdRoute: ApiProvidersProviderIdRouteWithChildren,
3140
+ ApiProvidersExportRoute,
3141
+ ApiProvidersImportRoute
2944
3142
  };
2945
3143
  const ApiProvidersRouteWithChildren = ApiProvidersRoute._addFileChildren(
2946
3144
  ApiProvidersRouteChildren
@@ -2955,7 +3153,7 @@ const rootRouteChildren = {
2955
3153
  ProxySplatRoute,
2956
3154
  ApiConfigPathsRoute
2957
3155
  };
2958
- const routeTree = Route$e._addFileChildren(rootRouteChildren)._addFileTypes();
3156
+ const routeTree = Route$g._addFileChildren(rootRouteChildren)._addFileTypes();
2959
3157
  function getRouter() {
2960
3158
  const router2 = createRouter({
2961
3159
  routeTree,
@@ -0,0 +1,4 @@
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/api/config/paths"], "preloads": ["/assets/main-BrU8NdGQ.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-CB8ZIeEk.js"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/models": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/proxy/$.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.paths.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.import.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.ts" } }, "clientEntry": "/assets/main-BrU8NdGQ.js" });
2
+ export {
3
+ tsrStartManifest
4
+ };
@@ -100,51 +100,51 @@ const assets = {
100
100
  "/assets/index-B3RwBPLW.css": {
101
101
  "type": "text/css; charset=utf-8",
102
102
  "etag": '"10c74-aXacU4DRFVsUwcC5jHnjoPRSlTA"',
103
- "mtime": "2026-06-03T12:05:46.053Z",
103
+ "mtime": "2026-06-04T00:12:14.535Z",
104
104
  "size": 68724,
105
105
  "path": "../public/assets/index-B3RwBPLW.css"
106
106
  },
107
107
  "/assets/alibaba-TTwafVwX.svg": {
108
108
  "type": "image/svg+xml",
109
109
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
110
- "mtime": "2026-06-03T12:05:46.051Z",
110
+ "mtime": "2026-06-04T00:12:14.535Z",
111
111
  "size": 5915,
112
112
  "path": "../public/assets/alibaba-TTwafVwX.svg"
113
113
  },
114
- "/assets/main-DYXtPYU8.js": {
115
- "type": "text/javascript; charset=utf-8",
116
- "etag": '"4db57-3IoaJ0zzvDUU7WQZuVFYW7QEzGQ"',
117
- "mtime": "2026-06-03T12:05:46.053Z",
118
- "size": 318295,
119
- "path": "../public/assets/main-DYXtPYU8.js"
120
- },
121
- "/assets/qwen-CONDcHqt.png": {
122
- "type": "image/png",
123
- "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
124
- "mtime": "2026-06-03T12:05:46.053Z",
125
- "size": 357059,
126
- "path": "../public/assets/qwen-CONDcHqt.png"
127
- },
128
114
  "/assets/minimax-BPMzvuL-.jpeg": {
129
115
  "type": "image/jpeg",
130
116
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
131
- "mtime": "2026-06-03T12:05:46.053Z",
117
+ "mtime": "2026-06-04T00:12:14.537Z",
132
118
  "size": 6918,
133
119
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
134
120
  },
121
+ "/assets/main-BrU8NdGQ.js": {
122
+ "type": "text/javascript; charset=utf-8",
123
+ "etag": '"4db57-Aw3zM46XAKLPcPLc9vLSzFsuUjI"',
124
+ "mtime": "2026-06-04T00:12:14.537Z",
125
+ "size": 318295,
126
+ "path": "../public/assets/main-BrU8NdGQ.js"
127
+ },
135
128
  "/assets/zhipuai-BPNAnxo-.svg": {
136
129
  "type": "image/svg+xml",
137
130
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
138
- "mtime": "2026-06-03T12:05:46.053Z",
131
+ "mtime": "2026-06-04T00:12:14.535Z",
139
132
  "size": 11256,
140
133
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
141
134
  },
142
- "/assets/index-Drusqil7.js": {
135
+ "/assets/qwen-CONDcHqt.png": {
136
+ "type": "image/png",
137
+ "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
138
+ "mtime": "2026-06-04T00:12:14.535Z",
139
+ "size": 357059,
140
+ "path": "../public/assets/qwen-CONDcHqt.png"
141
+ },
142
+ "/assets/index-CB8ZIeEk.js": {
143
143
  "type": "text/javascript; charset=utf-8",
144
- "etag": '"8368b-K/ZW3jyne5SeFVJGXXNOEllhQyM"',
145
- "mtime": "2026-06-03T12:05:46.054Z",
146
- "size": 538251,
147
- "path": "../public/assets/index-Drusqil7.js"
144
+ "etag": '"840e2-X78/yEmQlQ7ABa9KL5bfVykPAUY"',
145
+ "mtime": "2026-06-04T00:12:14.537Z",
146
+ "size": 540898,
147
+ "path": "../public/assets/index-CB8ZIeEk.js"
148
148
  }
149
149
  };
150
150
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/llm-inspector",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
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",