@tonyclaw/llm-inspector 1.14.1 → 1.14.2

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.
@@ -9,7 +9,7 @@ import { randomUUID } from "crypto";
9
9
  import { exec } from "node:child_process";
10
10
  import { promisify } from "node:util";
11
11
  import { M as McpServer, W as WebStandardStreamableHTTPServerTransport } from "../_libs/modelcontextprotocol__server.mjs";
12
- import { d as object, _ as _enum, b as string, u as union, a as array, c as boolean, n as number, g as discriminatedUnion, l as literal, r as record, h as _null, k as lazy, e as unknown } from "../_libs/zod.mjs";
12
+ import { d as object, _ as _enum, b as string, a as array, u as union, c as boolean, r as record, n as number, g as discriminatedUnion, l as literal, h as _null, k as lazy, e as unknown } from "../_libs/zod.mjs";
13
13
  import "../_libs/tiny-warning.mjs";
14
14
  import "../_libs/tanstack__router-core.mjs";
15
15
  import "../_libs/cookie-es.mjs";
@@ -45,8 +45,8 @@ import "../_libs/debounce-fn.mjs";
45
45
  import "../_libs/mimic-function.mjs";
46
46
  import "../_libs/semver.mjs";
47
47
  import "../_libs/uint8array-extras.mjs";
48
- const appCss = "/assets/index-DEUddp_2.css";
49
- const Route$i = createRootRoute({
48
+ const appCss = "/assets/index-DOG5AdQ9.css";
49
+ const Route$j = createRootRoute({
50
50
  head: () => ({
51
51
  meta: [
52
52
  { charSet: "utf-8" },
@@ -69,8 +69,8 @@ function RootDocument({ children }) {
69
69
  ] })
70
70
  ] });
71
71
  }
72
- const $$splitComponentImporter = () => import("./index-Cso39vJc.mjs");
73
- const Route$h = createFileRoute("/")({
72
+ const $$splitComponentImporter = () => import("./index-DmLit8Ad.mjs");
73
+ const Route$i = createFileRoute("/")({
74
74
  component: lazyRouteComponent($$splitComponentImporter, "component")
75
75
  });
76
76
  const LOG_DIR_ENV = process.env["LOG_DIR"];
@@ -1608,6 +1608,7 @@ const ProviderConfigSchema = object({
1608
1608
  name: string(),
1609
1609
  apiKey: string(),
1610
1610
  model: string().optional(),
1611
+ models: array(string()).min(1),
1611
1612
  format: _enum(["anthropic", "openai"]).optional(),
1612
1613
  baseUrl: string().optional(),
1613
1614
  anthropicBaseUrl: string().optional(),
@@ -1675,6 +1676,62 @@ function migrateProviders() {
1675
1676
  }
1676
1677
  }
1677
1678
  migrateProviders();
1679
+ function migrateMultiModel() {
1680
+ const providers = store.get("providers", []);
1681
+ if (providers.length === 0) return;
1682
+ let changed = false;
1683
+ const promoted = providers.map((p) => {
1684
+ if (p.models !== void 0 && p.models.length > 0) return p;
1685
+ const models = p.model !== void 0 && p.model !== "" ? [p.model] : [];
1686
+ changed = true;
1687
+ return { ...p, models };
1688
+ });
1689
+ const groups = /* @__PURE__ */ new Map();
1690
+ for (const p of promoted) {
1691
+ const key = `${p.apiKey}::${p.anthropicBaseUrl ?? ""}::${p.openaiBaseUrl ?? ""}`;
1692
+ const group = groups.get(key);
1693
+ if (group !== void 0) {
1694
+ group.push(p);
1695
+ } else {
1696
+ groups.set(key, [p]);
1697
+ }
1698
+ }
1699
+ const merged = [];
1700
+ for (const group of groups.values()) {
1701
+ const first = group[0];
1702
+ if (group.length === 1 && first !== void 0) {
1703
+ merged.push(first);
1704
+ continue;
1705
+ }
1706
+ changed = true;
1707
+ const sorted = group.toSorted(
1708
+ (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
1709
+ );
1710
+ const earliest = sorted[0];
1711
+ if (earliest === void 0) continue;
1712
+ const allModels = /* @__PURE__ */ new Set();
1713
+ for (const p of sorted) {
1714
+ for (const m of p.models ?? []) {
1715
+ if (m !== "") allModels.add(m);
1716
+ }
1717
+ }
1718
+ const mergedSource = sorted.find((p) => p.source !== void 0)?.source;
1719
+ merged.push({
1720
+ ...earliest,
1721
+ models: [...allModels],
1722
+ source: mergedSource,
1723
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1724
+ });
1725
+ }
1726
+ if (changed && merged.length > 0) {
1727
+ try {
1728
+ writeFileSync(`${store.path}.bak`, readFileSync(store.path, "utf-8"));
1729
+ } catch {
1730
+ }
1731
+ store.set("providers", merged);
1732
+ }
1733
+ }
1734
+ migrateMultiModel();
1678
1735
  const providersJson = process.env["LLM_INSPECTOR_PROVIDERS_JSON"];
1679
1736
  if (providersJson !== void 0) {
1680
1737
  try {
@@ -1696,22 +1753,39 @@ function getProvider(id) {
1696
1753
  function normalizeApiKey(apiKey) {
1697
1754
  return apiKey.replace(/^Bearer\s+/i, "").trim();
1698
1755
  }
1699
- function addProvider(name, apiKey, format, baseUrl, model, authHeader, apiDocsUrl, anthropicBaseUrl, openaiBaseUrl, source) {
1756
+ function addProvider(name, apiKey, format, baseUrl, models, authHeader, apiDocsUrl, anthropicBaseUrl, openaiBaseUrl, source) {
1700
1757
  const providers = getProviders();
1758
+ const normalizedKey = normalizeApiKey(apiKey);
1759
+ const resolvedAnthropicUrl = anthropicBaseUrl ?? "";
1760
+ const resolvedOpenaiUrl = openaiBaseUrl ?? "";
1701
1761
  const now = (/* @__PURE__ */ new Date()).toISOString();
1762
+ const existing = providers.find(
1763
+ (p) => p.apiKey === normalizedKey && (p.anthropicBaseUrl ?? "") === (resolvedAnthropicUrl ?? "") && (p.openaiBaseUrl ?? "") === (resolvedOpenaiUrl ?? "")
1764
+ );
1765
+ if (existing) {
1766
+ const newModels = (models ?? []).filter((m) => m !== "");
1767
+ if (newModels.length > 0) {
1768
+ const mergedModels = new Set(existing.models ?? []);
1769
+ for (const m of newModels) mergedModels.add(m);
1770
+ existing.models = [...mergedModels];
1771
+ existing.updatedAt = now;
1772
+ store.set("providers", providers);
1773
+ }
1774
+ return existing;
1775
+ }
1702
1776
  const newProvider = {
1703
1777
  id: randomUUID(),
1704
1778
  name,
1705
- apiKey: normalizeApiKey(apiKey),
1779
+ apiKey: normalizedKey,
1706
1780
  format: format ?? (anthropicBaseUrl !== void 0 ? "anthropic" : openaiBaseUrl !== void 0 ? "openai" : void 0),
1707
1781
  baseUrl,
1708
- model,
1782
+ models: models ?? [],
1709
1783
  authHeader: authHeader ?? "bearer",
1710
1784
  apiDocsUrl,
1711
1785
  createdAt: now,
1712
1786
  updatedAt: now,
1713
- anthropicBaseUrl: anthropicBaseUrl ?? "",
1714
- openaiBaseUrl: openaiBaseUrl ?? "",
1787
+ anthropicBaseUrl: resolvedAnthropicUrl,
1788
+ openaiBaseUrl: resolvedOpenaiUrl,
1715
1789
  source
1716
1790
  };
1717
1791
  providers.push(newProvider);
@@ -1726,7 +1800,7 @@ function updateProvider(id, updates) {
1726
1800
  id: existing.id,
1727
1801
  name: updates.name ?? existing.name,
1728
1802
  apiKey: updates.apiKey !== void 0 ? normalizeApiKey(updates.apiKey) : existing.apiKey,
1729
- model: updates.model !== void 0 ? updates.model : existing.model,
1803
+ models: updates.models !== void 0 ? updates.models : existing.models,
1730
1804
  format: updates.format ?? existing.format,
1731
1805
  baseUrl: updates.baseUrl !== void 0 ? updates.baseUrl : existing.baseUrl,
1732
1806
  authHeader: updates.authHeader ?? existing.authHeader,
@@ -1836,16 +1910,21 @@ function findProviderByModel(model) {
1836
1910
  if (modelLower.startsWith(providerPrefix)) {
1837
1911
  return provider;
1838
1912
  }
1839
- if (provider.model !== void 0 && provider.model !== "" && modelNormalized === normalizeModelName(provider.model)) {
1840
- return provider;
1841
- }
1842
- if (provider.model !== void 0 && provider.model !== "") {
1843
- const modelPart = modelNormalized.replace(normalizeModelName(provider.name), "");
1844
- const concatenated = normalizeModelName(provider.name) + modelPart;
1845
- if (modelNormalized === concatenated) {
1913
+ const modelList = provider.models ?? (provider.model !== void 0 ? [provider.model] : []);
1914
+ for (const m of modelList) {
1915
+ if (m !== "" && modelNormalized === normalizeModelName(m)) {
1846
1916
  return provider;
1847
1917
  }
1848
1918
  }
1919
+ for (const m of modelList) {
1920
+ if (m !== "") {
1921
+ const modelPart = modelNormalized.replace(normalizeModelName(provider.name), "");
1922
+ const concatenated = normalizeModelName(provider.name) + modelPart;
1923
+ if (modelNormalized === concatenated) {
1924
+ return provider;
1925
+ }
1926
+ }
1927
+ }
1849
1928
  }
1850
1929
  return null;
1851
1930
  }
@@ -2475,7 +2554,7 @@ async function handleProxy(req) {
2475
2554
  }
2476
2555
  return handleStreamingResponse(upstreamRes, req, startTime, formatHandler, upstreamUrl, log);
2477
2556
  }
2478
- const Route$g = createFileRoute("/proxy/$")({
2557
+ const Route$h = createFileRoute("/proxy/$")({
2479
2558
  server: {
2480
2559
  handlers: {
2481
2560
  GET: ({ request }) => handleProxy(request),
@@ -2487,7 +2566,7 @@ const Route$g = createFileRoute("/proxy/$")({
2487
2566
  }
2488
2567
  }
2489
2568
  });
2490
- const Route$f = createFileRoute("/api/sessions")({
2569
+ const Route$g = createFileRoute("/api/sessions")({
2491
2570
  server: {
2492
2571
  handlers: {
2493
2572
  GET: () => Response.json(getSessions())
@@ -2500,12 +2579,13 @@ const ProviderInputSchema = object({
2500
2579
  format: _enum(["anthropic", "openai"]).optional(),
2501
2580
  anthropicBaseUrl: string().optional(),
2502
2581
  openaiBaseUrl: string().optional(),
2503
- model: string().min(1, "Model is required"),
2582
+ models: array(string()).min(1, "At least one model is required"),
2583
+ model: string().optional(),
2504
2584
  authHeader: _enum(["bearer", "x-api-key"]).optional().default("bearer"),
2505
2585
  apiDocsUrl: string().optional(),
2506
2586
  source: _enum(["company", "personal"]).optional()
2507
2587
  });
2508
- const Route$e = createFileRoute("/api/providers")({
2588
+ const Route$f = createFileRoute("/api/providers")({
2509
2589
  server: {
2510
2590
  handlers: {
2511
2591
  GET: () => {
@@ -2522,7 +2602,7 @@ const Route$e = createFileRoute("/api/providers")({
2522
2602
  parsed.data.format,
2523
2603
  void 0,
2524
2604
  // baseUrl (legacy) — use format-specific URLs instead
2525
- parsed.data.model,
2605
+ parsed.data.models,
2526
2606
  parsed.data.authHeader,
2527
2607
  parsed.data.apiDocsUrl,
2528
2608
  parsed.data.anthropicBaseUrl,
@@ -2534,7 +2614,7 @@ const Route$e = createFileRoute("/api/providers")({
2534
2614
  }
2535
2615
  }
2536
2616
  });
2537
- const Route$d = createFileRoute("/api/models")({
2617
+ const Route$e = createFileRoute("/api/models")({
2538
2618
  server: {
2539
2619
  handlers: {
2540
2620
  GET: () => Response.json(getModels())
@@ -3044,7 +3124,7 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
3044
3124
  ({ id }) => safeCall(() => testProviderImpl(callApi, id))
3045
3125
  );
3046
3126
  }
3047
- const Route$c = createFileRoute("/api/mcp")({
3127
+ const Route$d = createFileRoute("/api/mcp")({
3048
3128
  server: {
3049
3129
  handlers: {
3050
3130
  // The SDK may issue either POST, GET, or DELETE. TanStack Start only
@@ -3056,7 +3136,7 @@ const Route$c = createFileRoute("/api/mcp")({
3056
3136
  }
3057
3137
  }
3058
3138
  });
3059
- const Route$b = createFileRoute("/api/logs")({
3139
+ const Route$c = createFileRoute("/api/logs")({
3060
3140
  server: {
3061
3141
  handlers: {
3062
3142
  GET: ({ request }) => {
@@ -3082,7 +3162,7 @@ const Route$b = createFileRoute("/api/logs")({
3082
3162
  }
3083
3163
  });
3084
3164
  logger.debug("Health endpoint loaded");
3085
- const Route$a = createFileRoute("/api/health")({
3165
+ const Route$b = createFileRoute("/api/health")({
3086
3166
  server: {
3087
3167
  handlers: {
3088
3168
  GET: () => {
@@ -3096,7 +3176,7 @@ const RuntimeConfigPatchSchema = object({
3096
3176
  }).strict().refine((v) => Object.keys(v).length > 0, {
3097
3177
  message: "At least one field must be provided"
3098
3178
  });
3099
- const Route$9 = createFileRoute("/api/config")({
3179
+ const Route$a = createFileRoute("/api/config")({
3100
3180
  server: {
3101
3181
  handlers: {
3102
3182
  GET: () => {
@@ -3126,7 +3206,7 @@ const Route$9 = createFileRoute("/api/config")({
3126
3206
  }
3127
3207
  });
3128
3208
  union([string(), object({ providers: unknown() })]);
3129
- const Route$8 = createFileRoute("/api/providers/import")({
3209
+ const Route$9 = createFileRoute("/api/providers/import")({
3130
3210
  server: {
3131
3211
  handlers: {
3132
3212
  POST: async ({ request }) => {
@@ -3159,7 +3239,7 @@ const Route$8 = createFileRoute("/api/providers/import")({
3159
3239
  }
3160
3240
  }
3161
3241
  });
3162
- const Route$7 = createFileRoute("/api/providers/export")({
3242
+ const Route$8 = createFileRoute("/api/providers/export")({
3163
3243
  server: {
3164
3244
  handlers: {
3165
3245
  GET: ({ request }) => {
@@ -3182,14 +3262,15 @@ const ProviderUpdateSchema = object({
3182
3262
  apiKey: string().min(1, "API key is required").optional(),
3183
3263
  format: _enum(["anthropic", "openai"]).optional(),
3184
3264
  baseUrl: string().min(1, "Base URL is required").optional(),
3185
- model: string().min(1, "Model is required").optional(),
3265
+ model: string().optional(),
3266
+ models: array(string()).optional(),
3186
3267
  authHeader: _enum(["bearer", "x-api-key"]).optional(),
3187
3268
  anthropicBaseUrl: string().optional(),
3188
3269
  openaiBaseUrl: string().optional(),
3189
3270
  apiDocsUrl: string().optional(),
3190
3271
  source: _enum(["company", "personal"]).optional()
3191
3272
  });
3192
- const Route$6 = createFileRoute("/api/providers/$providerId")({
3273
+ const Route$7 = createFileRoute("/api/providers/$providerId")({
3193
3274
  server: {
3194
3275
  handlers: {
3195
3276
  GET: ({ params }) => {
@@ -3221,7 +3302,7 @@ const Route$6 = createFileRoute("/api/providers/$providerId")({
3221
3302
  }
3222
3303
  }
3223
3304
  });
3224
- const Route$5 = createFileRoute("/api/logs/stream")({
3305
+ const Route$6 = createFileRoute("/api/logs/stream")({
3225
3306
  server: {
3226
3307
  handlers: {
3227
3308
  GET: ({ request }) => {
@@ -3275,7 +3356,7 @@ const Route$5 = createFileRoute("/api/logs/stream")({
3275
3356
  }
3276
3357
  }
3277
3358
  });
3278
- const Route$4 = createFileRoute("/api/logs/$id")({
3359
+ const Route$5 = createFileRoute("/api/logs/$id")({
3279
3360
  server: {
3280
3361
  handlers: {
3281
3362
  GET: async ({ params }) => {
@@ -3292,7 +3373,7 @@ const Route$4 = createFileRoute("/api/logs/$id")({
3292
3373
  }
3293
3374
  }
3294
3375
  });
3295
- const Route$3 = createFileRoute("/api/config/paths")({
3376
+ const Route$4 = createFileRoute("/api/config/paths")({
3296
3377
  server: {
3297
3378
  handlers: {
3298
3379
  GET: () => {
@@ -3710,31 +3791,7 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
3710
3791
  return createErrorResult(err, Date.now() - startTime, true);
3711
3792
  }
3712
3793
  }
3713
- function createTestLogEntry(providerName, path2, body, upstreamUrl, result, isTest) {
3714
- return {
3715
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3716
- id: `test-${Date.now()}`,
3717
- method: "POST",
3718
- path: path2,
3719
- model: isTest ? result.model : void 0,
3720
- sessionId: null,
3721
- rawRequestBody: body,
3722
- responseStatus: result.success ? 200 : 500,
3723
- responseText: result.rawResponse ?? JSON.stringify(result),
3724
- inputTokens: result.inputTokens ?? null,
3725
- outputTokens: result.outputTokens ?? null,
3726
- elapsedMs: result.latencyMs ?? 0,
3727
- streaming: result.streaming ?? false,
3728
- userAgent: "provider-test",
3729
- origin: null,
3730
- upstreamUrl,
3731
- error: result.success ? null : result.error?.message ?? String(result.error),
3732
- isTest: true,
3733
- providerName,
3734
- headers: result.requestHeaders ?? {}
3735
- };
3736
- }
3737
- const Route$2 = createFileRoute("/api/providers/$providerId/test")({
3794
+ const Route$3 = createFileRoute("/api/providers/$providerId/test")({
3738
3795
  server: {
3739
3796
  handlers: {
3740
3797
  POST: async ({ params }) => {
@@ -3742,208 +3799,70 @@ const Route$2 = createFileRoute("/api/providers/$providerId/test")({
3742
3799
  if (!provider) {
3743
3800
  return Response.json({ error: "Provider not found" }, { status: 404 });
3744
3801
  }
3745
- if (provider.model === void 0 || provider.model.trim().length === 0) {
3802
+ const p = provider;
3803
+ const modelsToTest = (provider.models ?? []).filter((m) => m.trim() !== "");
3804
+ if (modelsToTest.length === 0) {
3746
3805
  return Response.json(
3747
- { error: "Please configure a model name in provider settings" },
3806
+ { error: "Please configure at least one model in provider settings" },
3748
3807
  { status: 400 }
3749
3808
  );
3750
3809
  }
3751
- const model = provider.model.trim();
3752
- const usageModel = getModelUsageName(model, provider.name);
3753
3810
  const results = {
3754
3811
  anthropic: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } },
3755
- openai: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } }
3812
+ openai: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } },
3813
+ models: {}
3756
3814
  };
3757
- if (provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.length > 0) {
3758
- const nonStreamingResult = await testEndpoint(
3759
- provider.anthropicBaseUrl,
3760
- provider.apiKey,
3761
- "/v1/messages",
3762
- usageModel,
3763
- false
3764
- );
3765
- results.anthropic.nonStreaming = nonStreamingResult;
3766
- const requestBody = JSON.stringify({
3767
- model: usageModel,
3768
- messages: [{ role: "user", content: "say hello and briefly introduce yourself" }],
3769
- max_tokens: 1024
3770
- });
3771
- const upstreamUrl = `${provider.anthropicBaseUrl}/v1/messages`;
3772
- await addTestLogEntry({
3773
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3774
- method: "POST",
3775
- path: "/v1/messages",
3776
- model: nonStreamingResult.model ?? model,
3777
- sessionId: null,
3778
- rawRequestBody: requestBody,
3779
- responseStatus: nonStreamingResult.success ? 200 : 500,
3780
- responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
3781
- inputTokens: nonStreamingResult.inputTokens ?? null,
3782
- outputTokens: nonStreamingResult.outputTokens ?? null,
3783
- cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
3784
- cacheReadInputTokens: nonStreamingResult.cacheReadInputTokens ?? null,
3785
- elapsedMs: nonStreamingResult.latencyMs ?? 0,
3786
- streaming: false,
3787
- userAgent: "provider-test",
3788
- origin: null,
3789
- apiFormat: "anthropic",
3790
- isTest: true,
3791
- providerName: provider.name,
3792
- headers: nonStreamingResult.requestHeaders ?? {}
3793
- });
3794
- appendLogEntry(
3795
- createTestLogEntry(
3796
- provider.name,
3797
- "/v1/messages",
3798
- requestBody,
3799
- upstreamUrl,
3800
- nonStreamingResult,
3801
- true
3802
- )
3803
- );
3804
- const streamingResult = await testStreamingEndpoint(
3805
- provider.anthropicBaseUrl,
3806
- provider.apiKey,
3807
- "/v1/messages",
3808
- usageModel,
3809
- false
3810
- );
3811
- results.anthropic.streaming = streamingResult;
3812
- const streamingRequestBody = JSON.stringify({
3813
- model: usageModel,
3814
- messages: [{ role: "user", content: "say hello" }],
3815
- max_tokens: 256,
3816
- stream: true
3817
- });
3818
- await addTestLogEntry({
3819
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3820
- method: "POST",
3821
- path: "/v1/messages",
3822
- model: streamingResult.model ?? model,
3823
- sessionId: null,
3824
- rawRequestBody: streamingRequestBody,
3825
- responseStatus: streamingResult.success ? 200 : 500,
3826
- responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
3827
- inputTokens: streamingResult.inputTokens ?? null,
3828
- outputTokens: streamingResult.outputTokens ?? null,
3829
- cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
3830
- cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
3831
- elapsedMs: streamingResult.latencyMs ?? 0,
3832
- streaming: true,
3833
- streamingChunks: streamingResult.streamingChunks,
3834
- userAgent: "provider-test",
3835
- origin: null,
3836
- apiFormat: "anthropic",
3837
- isTest: true,
3838
- providerName: provider.name,
3839
- headers: streamingResult.requestHeaders ?? {}
3840
- });
3841
- appendLogEntry(
3842
- createTestLogEntry(
3843
- provider.name,
3844
- "/v1/messages",
3845
- streamingRequestBody,
3846
- upstreamUrl,
3847
- streamingResult,
3848
- true
3849
- )
3850
- );
3815
+ const anthropicUrl = provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.length > 0 ? provider.anthropicBaseUrl : void 0;
3816
+ const openaiUrl = provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0 ? provider.openaiBaseUrl : void 0;
3817
+ async function testOneModel(displayName) {
3818
+ const usageModel = getModelUsageName(displayName, p.name);
3819
+ const notConfigured = { notConfigured: true };
3820
+ const modelResults = {
3821
+ anthropic: { nonStreaming: notConfigured, streaming: notConfigured },
3822
+ openai: { nonStreaming: notConfigured, streaming: notConfigured }
3823
+ };
3824
+ const tasks = [];
3825
+ if (anthropicUrl !== void 0) {
3826
+ tasks.push(
3827
+ testEndpoint(anthropicUrl, p.apiKey, "/v1/messages", usageModel, false).then((r) => {
3828
+ modelResults.anthropic.nonStreaming = r;
3829
+ }),
3830
+ testStreamingEndpoint(anthropicUrl, p.apiKey, "/v1/messages", usageModel, false).then(
3831
+ (r) => {
3832
+ modelResults.anthropic.streaming = r;
3833
+ }
3834
+ )
3835
+ );
3836
+ }
3837
+ if (openaiUrl !== void 0) {
3838
+ tasks.push(
3839
+ testEndpoint(openaiUrl, p.apiKey, "/v1/chat/completions", usageModel, true).then(
3840
+ (r) => {
3841
+ modelResults.openai.nonStreaming = r;
3842
+ }
3843
+ ),
3844
+ testStreamingEndpoint(
3845
+ openaiUrl,
3846
+ p.apiKey,
3847
+ "/v1/chat/completions",
3848
+ usageModel,
3849
+ true
3850
+ ).then((r) => {
3851
+ modelResults.openai.streaming = r;
3852
+ })
3853
+ );
3854
+ }
3855
+ await Promise.all(tasks);
3856
+ results.models[displayName] = modelResults;
3851
3857
  }
3852
- if (provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0) {
3853
- const nonStreamingResult = await testEndpoint(
3854
- provider.openaiBaseUrl,
3855
- provider.apiKey,
3856
- "/v1/chat/completions",
3857
- usageModel,
3858
- true
3859
- );
3860
- results.openai.nonStreaming = nonStreamingResult;
3861
- const requestBody = JSON.stringify({
3862
- model: usageModel,
3863
- messages: [{ role: "user", content: "say hello and briefly introduce yourself" }],
3864
- max_tokens: 1024
3865
- });
3866
- const upstreamUrl = `${provider.openaiBaseUrl}/v1/chat/completions`;
3867
- await addTestLogEntry({
3868
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3869
- method: "POST",
3870
- path: "/v1/chat/completions",
3871
- model: nonStreamingResult.model ?? model,
3872
- sessionId: null,
3873
- rawRequestBody: requestBody,
3874
- responseStatus: nonStreamingResult.success ? 200 : 500,
3875
- responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
3876
- inputTokens: nonStreamingResult.inputTokens ?? null,
3877
- outputTokens: nonStreamingResult.outputTokens ?? null,
3878
- cacheCreationInputTokens: null,
3879
- cacheReadInputTokens: null,
3880
- elapsedMs: nonStreamingResult.latencyMs ?? 0,
3881
- streaming: false,
3882
- userAgent: "provider-test",
3883
- origin: null,
3884
- apiFormat: "openai",
3885
- isTest: true,
3886
- providerName: provider.name,
3887
- headers: nonStreamingResult.requestHeaders ?? {}
3888
- });
3889
- appendLogEntry(
3890
- createTestLogEntry(
3891
- provider.name,
3892
- "/v1/chat/completions",
3893
- requestBody,
3894
- upstreamUrl,
3895
- nonStreamingResult,
3896
- true
3897
- )
3898
- );
3899
- const streamingResult = await testStreamingEndpoint(
3900
- provider.openaiBaseUrl,
3901
- provider.apiKey,
3902
- "/v1/chat/completions",
3903
- usageModel,
3904
- true
3905
- );
3906
- results.openai.streaming = streamingResult;
3907
- const streamingRequestBody = JSON.stringify({
3908
- model: usageModel,
3909
- messages: [{ role: "user", content: "say hello" }],
3910
- max_tokens: 256,
3911
- stream: true
3912
- });
3913
- await addTestLogEntry({
3914
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3915
- method: "POST",
3916
- path: "/v1/chat/completions",
3917
- model: streamingResult.model ?? model,
3918
- sessionId: null,
3919
- rawRequestBody: streamingRequestBody,
3920
- responseStatus: streamingResult.success ? 200 : 500,
3921
- responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
3922
- inputTokens: streamingResult.inputTokens ?? null,
3923
- outputTokens: streamingResult.outputTokens ?? null,
3924
- cacheCreationInputTokens: null,
3925
- cacheReadInputTokens: null,
3926
- elapsedMs: streamingResult.latencyMs ?? 0,
3927
- streaming: true,
3928
- streamingChunks: streamingResult.streamingChunks,
3929
- userAgent: "provider-test",
3930
- origin: null,
3931
- apiFormat: "openai",
3932
- isTest: true,
3933
- providerName: provider.name,
3934
- headers: streamingResult.requestHeaders ?? {}
3935
- });
3936
- appendLogEntry(
3937
- createTestLogEntry(
3938
- provider.name,
3939
- "/v1/chat/completions",
3940
- streamingRequestBody,
3941
- upstreamUrl,
3942
- streamingResult,
3943
- true
3944
- )
3945
- );
3858
+ await Promise.all(modelsToTest.map((displayName) => testOneModel(displayName)));
3859
+ const firstModelName = modelsToTest[0];
3860
+ const firstResults = results.models[firstModelName];
3861
+ if (firstResults !== void 0) {
3862
+ results.anthropic = firstResults.anthropic;
3863
+ results.openai = firstResults.openai;
3946
3864
  }
3865
+ results.testedAt = (/* @__PURE__ */ new Date()).toISOString();
3947
3866
  return Response.json(results);
3948
3867
  }
3949
3868
  }
@@ -3952,7 +3871,7 @@ const Route$2 = createFileRoute("/api/providers/$providerId/test")({
3952
3871
  const ReplayRequestSchema = object({
3953
3872
  modifiedBody: string()
3954
3873
  });
3955
- const Route$1 = createFileRoute("/api/logs/$id/replay")({
3874
+ const Route$2 = createFileRoute("/api/logs/$id/replay")({
3956
3875
  server: {
3957
3876
  handlers: {
3958
3877
  POST: async ({ params, request }) => {
@@ -4070,7 +3989,7 @@ const Route$1 = createFileRoute("/api/logs/$id/replay")({
4070
3989
  }
4071
3990
  }
4072
3991
  });
4073
- const Route = createFileRoute("/api/logs/$id/chunks")({
3992
+ const Route$1 = createFileRoute("/api/logs/$id/chunks")({
4074
3993
  server: {
4075
3994
  handlers: {
4076
3995
  GET: async ({ params }) => {
@@ -4096,96 +4015,422 @@ const Route = createFileRoute("/api/logs/$id/chunks")({
4096
4015
  }
4097
4016
  }
4098
4017
  });
4099
- const IndexRoute = Route$h.update({
4018
+ const ProviderTestErrorTypeSchema = _enum([
4019
+ "timeout",
4020
+ "network_unreachable",
4021
+ "connection_refused",
4022
+ "auth_failed",
4023
+ "rate_limited",
4024
+ "server_error",
4025
+ "invalid_response",
4026
+ "unknown"
4027
+ ]);
4028
+ const ProviderTestErrorSchema = object({
4029
+ message: string(),
4030
+ type: ProviderTestErrorTypeSchema,
4031
+ details: string().optional(),
4032
+ hint: string().optional()
4033
+ });
4034
+ const ProviderTestContentSchema = object({
4035
+ type: _enum(["text", "thinking"]),
4036
+ text: string().optional(),
4037
+ thinking: string().optional()
4038
+ });
4039
+ const ProviderTestResultSchema = object({
4040
+ success: boolean(),
4041
+ error: ProviderTestErrorSchema.optional(),
4042
+ model: string().optional(),
4043
+ inputTokens: number().optional(),
4044
+ outputTokens: number().optional(),
4045
+ cacheCreationInputTokens: number().optional(),
4046
+ cacheReadInputTokens: number().optional(),
4047
+ latencyMs: number().optional(),
4048
+ content: array(ProviderTestContentSchema).optional(),
4049
+ rawResponse: string().optional(),
4050
+ streaming: boolean().optional(),
4051
+ streamingChunks: object({
4052
+ chunks: array(StreamingChunkSchema$1),
4053
+ truncated: boolean().default(false)
4054
+ }).optional(),
4055
+ requestHeaders: record(string(), string()).optional()
4056
+ });
4057
+ const ProviderTestStateSchema = union([
4058
+ ProviderTestResultSchema,
4059
+ object({ notConfigured: literal(true) }),
4060
+ object({ testing: literal(true) })
4061
+ ]);
4062
+ const ProviderFormatTestResultsSchema = object({
4063
+ nonStreaming: ProviderTestStateSchema,
4064
+ streaming: ProviderTestStateSchema
4065
+ });
4066
+ const ModelTestResultsSchema = object({
4067
+ anthropic: ProviderFormatTestResultsSchema,
4068
+ openai: ProviderFormatTestResultsSchema
4069
+ });
4070
+ const ProviderTestResultsSchema = object({
4071
+ anthropic: ProviderFormatTestResultsSchema,
4072
+ openai: ProviderFormatTestResultsSchema,
4073
+ models: record(string(), ModelTestResultsSchema).optional(),
4074
+ testedAt: string().optional()
4075
+ });
4076
+ function createPendingProviderTestResults() {
4077
+ return {
4078
+ anthropic: {
4079
+ nonStreaming: { testing: true },
4080
+ streaming: { testing: true }
4081
+ },
4082
+ openai: {
4083
+ nonStreaming: { testing: true },
4084
+ streaming: { testing: true }
4085
+ }
4086
+ };
4087
+ }
4088
+ function createFailedProviderTestResults(message, type) {
4089
+ const createFormatResult = () => ({
4090
+ nonStreaming: {
4091
+ success: false,
4092
+ error: { message, type }
4093
+ },
4094
+ streaming: { notConfigured: true }
4095
+ });
4096
+ return {
4097
+ anthropic: createFormatResult(),
4098
+ openai: createFormatResult()
4099
+ };
4100
+ }
4101
+ function hasSuccessField(result) {
4102
+ return Object.prototype.hasOwnProperty.call(result, "success");
4103
+ }
4104
+ function createTestLogEntry(providerName, path2, body, upstreamUrl, result, isTest) {
4105
+ return {
4106
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4107
+ id: `test-${Date.now()}`,
4108
+ method: "POST",
4109
+ path: path2,
4110
+ model: isTest ? result.model : void 0,
4111
+ sessionId: null,
4112
+ rawRequestBody: body,
4113
+ responseStatus: result.success ? 200 : 500,
4114
+ responseText: result.rawResponse ?? JSON.stringify(result),
4115
+ inputTokens: result.inputTokens ?? null,
4116
+ outputTokens: result.outputTokens ?? null,
4117
+ elapsedMs: result.latencyMs ?? 0,
4118
+ streaming: result.streaming ?? false,
4119
+ userAgent: "provider-test",
4120
+ origin: null,
4121
+ upstreamUrl,
4122
+ error: result.success ? null : result.error?.message ?? String(result.error),
4123
+ isTest: true,
4124
+ providerName,
4125
+ headers: result.requestHeaders ?? {}
4126
+ };
4127
+ }
4128
+ async function logModelResults(displayName, providerName, anthropicUrl, openaiUrl, modelResults) {
4129
+ const usageModel = getModelUsageName(displayName, providerName);
4130
+ if (anthropicUrl !== void 0) {
4131
+ const nsResult = modelResults.anthropic.nonStreaming;
4132
+ const sResult = modelResults.anthropic.streaming;
4133
+ if (hasSuccessField(nsResult) && hasSuccessField(sResult)) {
4134
+ const nonStreamingResult = nsResult;
4135
+ const streamingResult = sResult;
4136
+ const requestBody = JSON.stringify({
4137
+ model: usageModel,
4138
+ messages: [{ role: "user", content: "say hello and briefly introduce yourself" }],
4139
+ max_tokens: 1024
4140
+ });
4141
+ const upstreamUrl = `${anthropicUrl}/v1/messages`;
4142
+ await addTestLogEntry({
4143
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4144
+ method: "POST",
4145
+ path: "/v1/messages",
4146
+ model: nonStreamingResult.model ?? displayName,
4147
+ sessionId: null,
4148
+ rawRequestBody: requestBody,
4149
+ responseStatus: nonStreamingResult.success ? 200 : 500,
4150
+ responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
4151
+ inputTokens: nonStreamingResult.inputTokens ?? null,
4152
+ outputTokens: nonStreamingResult.outputTokens ?? null,
4153
+ cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
4154
+ cacheReadInputTokens: nonStreamingResult.cacheReadInputTokens ?? null,
4155
+ elapsedMs: nonStreamingResult.latencyMs ?? 0,
4156
+ streaming: false,
4157
+ userAgent: "provider-test",
4158
+ origin: null,
4159
+ apiFormat: "anthropic",
4160
+ isTest: true,
4161
+ providerName,
4162
+ headers: nonStreamingResult.requestHeaders ?? {}
4163
+ });
4164
+ appendLogEntry(
4165
+ createTestLogEntry(
4166
+ providerName,
4167
+ "/v1/messages",
4168
+ requestBody,
4169
+ upstreamUrl,
4170
+ nonStreamingResult,
4171
+ true
4172
+ )
4173
+ );
4174
+ const streamingRequestBody = JSON.stringify({
4175
+ model: usageModel,
4176
+ messages: [{ role: "user", content: "say hello" }],
4177
+ max_tokens: 256,
4178
+ stream: true
4179
+ });
4180
+ await addTestLogEntry({
4181
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4182
+ method: "POST",
4183
+ path: "/v1/messages",
4184
+ model: streamingResult.model ?? displayName,
4185
+ sessionId: null,
4186
+ rawRequestBody: streamingRequestBody,
4187
+ responseStatus: streamingResult.success ? 200 : 500,
4188
+ responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
4189
+ inputTokens: streamingResult.inputTokens ?? null,
4190
+ outputTokens: streamingResult.outputTokens ?? null,
4191
+ cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
4192
+ cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
4193
+ elapsedMs: streamingResult.latencyMs ?? 0,
4194
+ streaming: true,
4195
+ streamingChunks: streamingResult.streamingChunks,
4196
+ userAgent: "provider-test",
4197
+ origin: null,
4198
+ apiFormat: "anthropic",
4199
+ isTest: true,
4200
+ providerName,
4201
+ headers: streamingResult.requestHeaders ?? {}
4202
+ });
4203
+ appendLogEntry(
4204
+ createTestLogEntry(
4205
+ providerName,
4206
+ "/v1/messages",
4207
+ streamingRequestBody,
4208
+ upstreamUrl,
4209
+ streamingResult,
4210
+ true
4211
+ )
4212
+ );
4213
+ }
4214
+ }
4215
+ if (openaiUrl !== void 0) {
4216
+ const nsResult = modelResults.openai.nonStreaming;
4217
+ const sResult = modelResults.openai.streaming;
4218
+ if (hasSuccessField(nsResult) && hasSuccessField(sResult)) {
4219
+ const nonStreamingResult = nsResult;
4220
+ const streamingResult = sResult;
4221
+ const requestBody = JSON.stringify({
4222
+ model: usageModel,
4223
+ messages: [{ role: "user", content: "say hello and briefly introduce yourself" }],
4224
+ max_tokens: 1024
4225
+ });
4226
+ const upstreamUrl = `${openaiUrl}/v1/chat/completions`;
4227
+ await addTestLogEntry({
4228
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4229
+ method: "POST",
4230
+ path: "/v1/chat/completions",
4231
+ model: nonStreamingResult.model ?? displayName,
4232
+ sessionId: null,
4233
+ rawRequestBody: requestBody,
4234
+ responseStatus: nonStreamingResult.success ? 200 : 500,
4235
+ responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
4236
+ inputTokens: nonStreamingResult.inputTokens ?? null,
4237
+ outputTokens: nonStreamingResult.outputTokens ?? null,
4238
+ cacheCreationInputTokens: null,
4239
+ cacheReadInputTokens: null,
4240
+ elapsedMs: nonStreamingResult.latencyMs ?? 0,
4241
+ streaming: false,
4242
+ userAgent: "provider-test",
4243
+ origin: null,
4244
+ apiFormat: "openai",
4245
+ isTest: true,
4246
+ providerName,
4247
+ headers: nonStreamingResult.requestHeaders ?? {}
4248
+ });
4249
+ appendLogEntry(
4250
+ createTestLogEntry(
4251
+ providerName,
4252
+ "/v1/chat/completions",
4253
+ requestBody,
4254
+ upstreamUrl,
4255
+ nonStreamingResult,
4256
+ true
4257
+ )
4258
+ );
4259
+ const streamingRequestBody = JSON.stringify({
4260
+ model: usageModel,
4261
+ messages: [{ role: "user", content: "say hello" }],
4262
+ max_tokens: 256,
4263
+ stream: true
4264
+ });
4265
+ await addTestLogEntry({
4266
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4267
+ method: "POST",
4268
+ path: "/v1/chat/completions",
4269
+ model: streamingResult.model ?? displayName,
4270
+ sessionId: null,
4271
+ rawRequestBody: streamingRequestBody,
4272
+ responseStatus: streamingResult.success ? 200 : 500,
4273
+ responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
4274
+ inputTokens: streamingResult.inputTokens ?? null,
4275
+ outputTokens: streamingResult.outputTokens ?? null,
4276
+ cacheCreationInputTokens: null,
4277
+ cacheReadInputTokens: null,
4278
+ elapsedMs: streamingResult.latencyMs ?? 0,
4279
+ streaming: true,
4280
+ streamingChunks: streamingResult.streamingChunks,
4281
+ userAgent: "provider-test",
4282
+ origin: null,
4283
+ apiFormat: "openai",
4284
+ isTest: true,
4285
+ providerName,
4286
+ headers: streamingResult.requestHeaders ?? {}
4287
+ });
4288
+ appendLogEntry(
4289
+ createTestLogEntry(
4290
+ providerName,
4291
+ "/v1/chat/completions",
4292
+ streamingRequestBody,
4293
+ upstreamUrl,
4294
+ streamingResult,
4295
+ true
4296
+ )
4297
+ );
4298
+ }
4299
+ }
4300
+ }
4301
+ const Route = createFileRoute("/api/providers/$providerId/test/log")({
4302
+ server: {
4303
+ handlers: {
4304
+ POST: async ({ params, request }) => {
4305
+ const provider = getProvider(params.providerId);
4306
+ if (!provider) {
4307
+ return Response.json({ error: "Provider not found" }, { status: 404 });
4308
+ }
4309
+ let body;
4310
+ try {
4311
+ body = await request.json();
4312
+ } catch {
4313
+ return Response.json({ error: "Invalid JSON body" }, { status: 400 });
4314
+ }
4315
+ const parsed = ProviderTestResultsSchema.safeParse(body);
4316
+ if (!parsed.success) {
4317
+ return Response.json(
4318
+ { error: `Invalid test results: ${parsed.error.message}` },
4319
+ { status: 400 }
4320
+ );
4321
+ }
4322
+ const results = parsed.data;
4323
+ const anthropicUrl = provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.length > 0 ? provider.anthropicBaseUrl : void 0;
4324
+ const openaiUrl = provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0 ? provider.openaiBaseUrl : void 0;
4325
+ const entries = [];
4326
+ if (results.models !== void 0) {
4327
+ for (const [modelName, modelResult] of Object.entries(results.models)) {
4328
+ entries.push(
4329
+ logModelResults(modelName, provider.name, anthropicUrl, openaiUrl, modelResult)
4330
+ );
4331
+ }
4332
+ }
4333
+ await Promise.all(entries);
4334
+ return Response.json({ logged: entries.length });
4335
+ }
4336
+ }
4337
+ }
4338
+ });
4339
+ const IndexRoute = Route$i.update({
4100
4340
  id: "/",
4101
4341
  path: "/",
4102
- getParentRoute: () => Route$i
4342
+ getParentRoute: () => Route$j
4103
4343
  });
4104
- const ProxySplatRoute = Route$g.update({
4344
+ const ProxySplatRoute = Route$h.update({
4105
4345
  id: "/proxy/$",
4106
4346
  path: "/proxy/$",
4107
- getParentRoute: () => Route$i
4347
+ getParentRoute: () => Route$j
4108
4348
  });
4109
- const ApiSessionsRoute = Route$f.update({
4349
+ const ApiSessionsRoute = Route$g.update({
4110
4350
  id: "/api/sessions",
4111
4351
  path: "/api/sessions",
4112
- getParentRoute: () => Route$i
4352
+ getParentRoute: () => Route$j
4113
4353
  });
4114
- const ApiProvidersRoute = Route$e.update({
4354
+ const ApiProvidersRoute = Route$f.update({
4115
4355
  id: "/api/providers",
4116
4356
  path: "/api/providers",
4117
- getParentRoute: () => Route$i
4357
+ getParentRoute: () => Route$j
4118
4358
  });
4119
- const ApiModelsRoute = Route$d.update({
4359
+ const ApiModelsRoute = Route$e.update({
4120
4360
  id: "/api/models",
4121
4361
  path: "/api/models",
4122
- getParentRoute: () => Route$i
4362
+ getParentRoute: () => Route$j
4123
4363
  });
4124
- const ApiMcpRoute = Route$c.update({
4364
+ const ApiMcpRoute = Route$d.update({
4125
4365
  id: "/api/mcp",
4126
4366
  path: "/api/mcp",
4127
- getParentRoute: () => Route$i
4367
+ getParentRoute: () => Route$j
4128
4368
  });
4129
- const ApiLogsRoute = Route$b.update({
4369
+ const ApiLogsRoute = Route$c.update({
4130
4370
  id: "/api/logs",
4131
4371
  path: "/api/logs",
4132
- getParentRoute: () => Route$i
4372
+ getParentRoute: () => Route$j
4133
4373
  });
4134
- const ApiHealthRoute = Route$a.update({
4374
+ const ApiHealthRoute = Route$b.update({
4135
4375
  id: "/api/health",
4136
4376
  path: "/api/health",
4137
- getParentRoute: () => Route$i
4377
+ getParentRoute: () => Route$j
4138
4378
  });
4139
- const ApiConfigRoute = Route$9.update({
4379
+ const ApiConfigRoute = Route$a.update({
4140
4380
  id: "/api/config",
4141
4381
  path: "/api/config",
4142
- getParentRoute: () => Route$i
4382
+ getParentRoute: () => Route$j
4143
4383
  });
4144
- const ApiProvidersImportRoute = Route$8.update({
4384
+ const ApiProvidersImportRoute = Route$9.update({
4145
4385
  id: "/import",
4146
4386
  path: "/import",
4147
4387
  getParentRoute: () => ApiProvidersRoute
4148
4388
  });
4149
- const ApiProvidersExportRoute = Route$7.update({
4389
+ const ApiProvidersExportRoute = Route$8.update({
4150
4390
  id: "/export",
4151
4391
  path: "/export",
4152
4392
  getParentRoute: () => ApiProvidersRoute
4153
4393
  });
4154
- const ApiProvidersProviderIdRoute = Route$6.update({
4394
+ const ApiProvidersProviderIdRoute = Route$7.update({
4155
4395
  id: "/$providerId",
4156
4396
  path: "/$providerId",
4157
4397
  getParentRoute: () => ApiProvidersRoute
4158
4398
  });
4159
- const ApiLogsStreamRoute = Route$5.update({
4399
+ const ApiLogsStreamRoute = Route$6.update({
4160
4400
  id: "/stream",
4161
4401
  path: "/stream",
4162
4402
  getParentRoute: () => ApiLogsRoute
4163
4403
  });
4164
- const ApiLogsIdRoute = Route$4.update({
4404
+ const ApiLogsIdRoute = Route$5.update({
4165
4405
  id: "/$id",
4166
4406
  path: "/$id",
4167
4407
  getParentRoute: () => ApiLogsRoute
4168
4408
  });
4169
- const ApiConfigPathsRoute = Route$3.update({
4409
+ const ApiConfigPathsRoute = Route$4.update({
4170
4410
  id: "/paths",
4171
4411
  path: "/paths",
4172
4412
  getParentRoute: () => ApiConfigRoute
4173
4413
  });
4174
- const ApiProvidersProviderIdTestRoute = Route$2.update({
4414
+ const ApiProvidersProviderIdTestRoute = Route$3.update({
4175
4415
  id: "/test",
4176
4416
  path: "/test",
4177
4417
  getParentRoute: () => ApiProvidersProviderIdRoute
4178
4418
  });
4179
- const ApiLogsIdReplayRoute = Route$1.update({
4419
+ const ApiLogsIdReplayRoute = Route$2.update({
4180
4420
  id: "/replay",
4181
4421
  path: "/replay",
4182
4422
  getParentRoute: () => ApiLogsIdRoute
4183
4423
  });
4184
- const ApiLogsIdChunksRoute = Route.update({
4424
+ const ApiLogsIdChunksRoute = Route$1.update({
4185
4425
  id: "/chunks",
4186
4426
  path: "/chunks",
4187
4427
  getParentRoute: () => ApiLogsIdRoute
4188
4428
  });
4429
+ const ApiProvidersProviderIdTestLogRoute = Route.update({
4430
+ id: "/log",
4431
+ path: "/log",
4432
+ getParentRoute: () => ApiProvidersProviderIdTestRoute
4433
+ });
4189
4434
  const ApiConfigRouteChildren = {
4190
4435
  ApiConfigPathsRoute
4191
4436
  };
@@ -4204,8 +4449,14 @@ const ApiLogsRouteChildren = {
4204
4449
  ApiLogsStreamRoute
4205
4450
  };
4206
4451
  const ApiLogsRouteWithChildren = ApiLogsRoute._addFileChildren(ApiLogsRouteChildren);
4452
+ const ApiProvidersProviderIdTestRouteChildren = {
4453
+ ApiProvidersProviderIdTestLogRoute
4454
+ };
4455
+ const ApiProvidersProviderIdTestRouteWithChildren = ApiProvidersProviderIdTestRoute._addFileChildren(
4456
+ ApiProvidersProviderIdTestRouteChildren
4457
+ );
4207
4458
  const ApiProvidersProviderIdRouteChildren = {
4208
- ApiProvidersProviderIdTestRoute
4459
+ ApiProvidersProviderIdTestRoute: ApiProvidersProviderIdTestRouteWithChildren
4209
4460
  };
4210
4461
  const ApiProvidersProviderIdRouteWithChildren = ApiProvidersProviderIdRoute._addFileChildren(
4211
4462
  ApiProvidersProviderIdRouteChildren
@@ -4229,7 +4480,7 @@ const rootRouteChildren = {
4229
4480
  ApiSessionsRoute,
4230
4481
  ProxySplatRoute
4231
4482
  };
4232
- const routeTree = Route$i._addFileChildren(rootRouteChildren)._addFileTypes();
4483
+ const routeTree = Route$j._addFileChildren(rootRouteChildren)._addFileTypes();
4233
4484
  function getRouter() {
4234
4485
  const router2 = createRouter({
4235
4486
  routeTree,
@@ -4244,10 +4495,12 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
4244
4495
  export {
4245
4496
  CapturedLogSchema as C,
4246
4497
  InspectorResponseSchema as I,
4247
- ProviderConfigSchema as P,
4498
+ ProviderTestResultsSchema as P,
4248
4499
  RuntimeConfigSchema as R,
4249
- StreamingChunkSchema$1 as S,
4250
4500
  parseRequest as a,
4501
+ createFailedProviderTestResults as b,
4502
+ createPendingProviderTestResults as c,
4503
+ ProviderConfigSchema as d,
4251
4504
  parseOpenAIResponse as p,
4252
4505
  router as r,
4253
4506
  stripClaudeCodeBillingHeader as s