@tonyclaw/agent-inspector 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Djb4XFZS.js → CompareDrawer-BWMipEjS.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-DIAgurux.js +114 -0
  4. package/.output/public/assets/{ReplayDialog-DBPMIs2I.js → ReplayDialog-DaSzZsvM.js} +1 -1
  5. package/.output/public/assets/RequestAnatomy-BfQmPHCd.js +1 -0
  6. package/.output/public/assets/ResponseView-CblEWDMx.js +1 -0
  7. package/.output/public/assets/StreamingChunkSequence-B4atnL99.js +1 -0
  8. package/.output/public/assets/_sessionId-DUzYnZXV.js +1 -0
  9. package/.output/public/assets/index-CxhRsekH.css +1 -0
  10. package/.output/public/assets/index-jagRsQaV.js +1 -0
  11. package/.output/public/assets/{main-CwhqfJqM.js → main-DE6Y4-wV.js} +2 -2
  12. package/.output/server/{_sessionId-DzBy9gLa.mjs → _sessionId-61HO9rUI.mjs} +3 -3
  13. package/.output/server/_ssr/{CompareDrawer-C5NBvE2e.mjs → CompareDrawer-CSPqneYm.mjs} +2 -2
  14. package/.output/server/_ssr/{ProxyViewerContainer-DiZjOTQT.mjs → ProxyViewerContainer-DrSMa5O7.mjs} +159 -14
  15. package/.output/server/_ssr/{ReplayDialog-EpvTwFvp.mjs → ReplayDialog-Dn3naENv.mjs} +3 -3
  16. package/.output/server/_ssr/{RequestAnatomy-DaQjhixp.mjs → RequestAnatomy-D1X3f3AX.mjs} +336 -42
  17. package/.output/server/_ssr/{ResponseView-D8tGHCGY.mjs → ResponseView-CwXAWOoE.mjs} +2 -2
  18. package/.output/server/_ssr/{StreamingChunkSequence-DGQnb1QE.mjs → StreamingChunkSequence-DRSR2FfN.mjs} +2 -2
  19. package/.output/server/_ssr/{index-N25hqa7t.mjs → index-D4zn5CAg.mjs} +2 -2
  20. package/.output/server/_ssr/index.mjs +2 -2
  21. package/.output/server/_ssr/{router-Bf0m6F0G.mjs → router-CSRaa_tu.mjs} +531 -111
  22. package/.output/server/{_tanstack-start-manifest_v-DlAyJ5DB.mjs → _tanstack-start-manifest_v-CfvVUYYj.mjs} +1 -1
  23. package/.output/server/index.mjs +60 -60
  24. package/bin/agent-inspector.js +2 -0
  25. package/package.json +3 -2
  26. package/src/components/providers/ProviderCard.tsx +59 -5
  27. package/src/components/providers/ProviderForm.tsx +42 -0
  28. package/src/components/providers/ProvidersPanel.tsx +68 -0
  29. package/src/components/proxy-viewer/LogEntry.tsx +6 -1
  30. package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +134 -3
  31. package/src/components/proxy-viewer/anatomy/contextIntelligence.ts +298 -40
  32. package/src/lib/providerContract.ts +12 -0
  33. package/src/lib/providerModelMetadata.ts +327 -0
  34. package/src/proxy/providers.ts +112 -52
  35. package/src/routes/api/providers.$providerId.model-metadata.ts +134 -0
  36. package/src/routes/api/providers.$providerId.ts +3 -0
  37. package/src/routes/api/providers.ts +2 -0
  38. package/.output/public/assets/ProxyViewerContainer-CWdkPZsJ.js +0 -114
  39. package/.output/public/assets/RequestAnatomy-FBfRNQN7.js +0 -1
  40. package/.output/public/assets/ResponseView-Db4pJL7U.js +0 -1
  41. package/.output/public/assets/StreamingChunkSequence-BH175O6R.js +0 -1
  42. package/.output/public/assets/_sessionId-3ipVoQtW.js +0 -1
  43. package/.output/public/assets/index-Bo1dGS4R.css +0 -1
  44. package/.output/public/assets/index-CJgaCJo8.js +0 -1
@@ -49,8 +49,8 @@ import "../_libs/mimic-function.mjs";
49
49
  import "../_libs/semver.mjs";
50
50
  import "../_libs/uint8array-extras.mjs";
51
51
  const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
52
- const appCss = "/assets/index-Bo1dGS4R.css";
53
- const Route$r = createRootRoute({
52
+ const appCss = "/assets/index-CxhRsekH.css";
53
+ const Route$s = createRootRoute({
54
54
  head: () => ({
55
55
  meta: [
56
56
  { charSet: "utf-8" },
@@ -92,8 +92,8 @@ function RootDocument({ children }) {
92
92
  ] })
93
93
  ] });
94
94
  }
95
- const $$splitComponentImporter$1 = () => import("./index-N25hqa7t.mjs");
96
- const Route$q = createFileRoute("/")({
95
+ const $$splitComponentImporter$1 = () => import("./index-D4zn5CAg.mjs");
96
+ const Route$r = createFileRoute("/")({
97
97
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
98
98
  });
99
99
  const B64URL_RE = /^[A-Za-z0-9_-]+$/;
@@ -135,8 +135,8 @@ function decodeSessionIdFromPath(encoded) {
135
135
  function getSessionPath(sessionId) {
136
136
  return `/session/${encodeSessionIdForPath(sessionId)}`;
137
137
  }
138
- const $$splitComponentImporter = () => import("../_sessionId-DzBy9gLa.mjs");
139
- const Route$p = createFileRoute("/session/$sessionId")({
138
+ const $$splitComponentImporter = () => import("../_sessionId-61HO9rUI.mjs");
139
+ const Route$q = createFileRoute("/session/$sessionId")({
140
140
  component: lazyRouteComponent($$splitComponentImporter, "component"),
141
141
  parseParams: (params) => ({
142
142
  sessionId: decodeSessionIdFromPath(params.sessionId)
@@ -2047,6 +2047,14 @@ const alibabaProvider = {
2047
2047
  }
2048
2048
  };
2049
2049
  registry.register(alibabaProvider);
2050
+ const ProviderModelMetadataSchema = object({
2051
+ model: string().min(1),
2052
+ contextWindow: number().int().positive().optional(),
2053
+ outputLimit: number().int().positive().optional(),
2054
+ source: _enum(["manual", "registry"]).optional(),
2055
+ sourceUrl: string().optional(),
2056
+ updatedAt: string().optional()
2057
+ });
2050
2058
  const ProviderConfigSchema = object({
2051
2059
  id: string(),
2052
2060
  name: string(),
@@ -2059,10 +2067,256 @@ const ProviderConfigSchema = object({
2059
2067
  openaiBaseUrl: string().optional(),
2060
2068
  authHeader: _enum(["bearer", "x-api-key"]).optional().default("bearer"),
2061
2069
  apiDocsUrl: string().optional(),
2070
+ modelMetadataUrl: string().optional(),
2071
+ modelMetadata: array(ProviderModelMetadataSchema).optional(),
2062
2072
  source: _enum(["company", "personal"]).optional(),
2063
2073
  createdAt: string(),
2064
2074
  updatedAt: string()
2065
2075
  });
2076
+ const ProviderRegistryModelSchema = object({
2077
+ id: string().min(1),
2078
+ aliases: array(string()).optional().default([]),
2079
+ contextWindow: number().int().positive().optional(),
2080
+ outputLimit: number().int().positive().optional(),
2081
+ sourceUrl: string().optional()
2082
+ });
2083
+ const ProviderRegistryProviderSchema = object({
2084
+ name: string().min(1).optional(),
2085
+ aliases: array(string()).optional().default([]),
2086
+ baseUrls: array(string()).optional().default([]),
2087
+ models: array(ProviderRegistryModelSchema).min(1)
2088
+ });
2089
+ const ProviderModelRegistrySchema = object({
2090
+ version: number().int().positive().optional(),
2091
+ updatedAt: string().optional(),
2092
+ providers: array(ProviderRegistryProviderSchema).optional().default([]),
2093
+ models: array(ProviderRegistryModelSchema).optional().default([])
2094
+ });
2095
+ const BUILTIN_MODEL_METADATA_SOURCE_URL = "agent-inspector://builtin/model-metadata";
2096
+ const BUILTIN_PROVIDER_MODEL_REGISTRY = {
2097
+ providers: [
2098
+ {
2099
+ name: "DeepSeek",
2100
+ aliases: ["deepseek"],
2101
+ baseUrls: ["https://api.deepseek.com"],
2102
+ models: [
2103
+ {
2104
+ id: "deepseek-v4-pro",
2105
+ aliases: ["DeepSeek-V4-Pro"],
2106
+ contextWindow: 1e6
2107
+ },
2108
+ {
2109
+ id: "deepseek-v4-flash",
2110
+ aliases: ["DeepSeek-V4-Flash"],
2111
+ contextWindow: 1e6
2112
+ }
2113
+ ]
2114
+ },
2115
+ {
2116
+ name: "MiniMax",
2117
+ aliases: ["minimax"],
2118
+ baseUrls: ["https://api.minimaxi.com/anthropic"],
2119
+ models: [
2120
+ {
2121
+ id: "MiniMax M3",
2122
+ aliases: ["MiniMax-M3", "minimax-m3"],
2123
+ contextWindow: 1e6
2124
+ },
2125
+ {
2126
+ id: "MiniMax M2.7",
2127
+ aliases: ["MiniMax-M2.7", "minimax-m2.7"],
2128
+ contextWindow: 204800
2129
+ },
2130
+ {
2131
+ id: "MiniMax M2.7-highspeed",
2132
+ aliases: ["MiniMax-M2.7-highspeed", "minimax-m2.7-highspeed"],
2133
+ contextWindow: 204800
2134
+ },
2135
+ {
2136
+ id: "MiniMax M2.5",
2137
+ aliases: ["MiniMax-M2.5", "minimax-m2.5"],
2138
+ contextWindow: 204800
2139
+ },
2140
+ {
2141
+ id: "MiniMax M2.5-highspeed",
2142
+ aliases: ["MiniMax-M2.5-highspeed", "minimax-m2.5-highspeed"],
2143
+ contextWindow: 204800
2144
+ },
2145
+ {
2146
+ id: "MiniMax M2.1",
2147
+ aliases: ["MiniMax-M2.1", "minimax-m2.1"],
2148
+ contextWindow: 204800
2149
+ },
2150
+ {
2151
+ id: "MiniMax M2.1-highspeed",
2152
+ aliases: ["MiniMax-M2.1-highspeed", "minimax-m2.1-highspeed"],
2153
+ contextWindow: 204800
2154
+ }
2155
+ ]
2156
+ }
2157
+ ],
2158
+ models: []
2159
+ };
2160
+ function normalizeModelName$1(value) {
2161
+ return value.trim().toLowerCase().replace(/\s+/g, "-");
2162
+ }
2163
+ function normalizeProviderName(value) {
2164
+ return value.trim().toLowerCase().replace(/\s+/g, "");
2165
+ }
2166
+ function normalizeUrl(value) {
2167
+ if (value === void 0) return null;
2168
+ const trimmed = value.trim();
2169
+ if (trimmed === "") return null;
2170
+ try {
2171
+ const parsed = new URL(trimmed);
2172
+ const path2 = parsed.pathname.replace(/\/+$/, "");
2173
+ return `${parsed.origin}${path2}`.toLowerCase();
2174
+ } catch {
2175
+ return trimmed.replace(/\/+$/, "").toLowerCase();
2176
+ }
2177
+ }
2178
+ function providerBaseUrls(provider) {
2179
+ const urls = [];
2180
+ if (provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.trim() !== "") {
2181
+ urls.push(provider.anthropicBaseUrl);
2182
+ }
2183
+ if (provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.trim() !== "") {
2184
+ urls.push(provider.openaiBaseUrl);
2185
+ }
2186
+ if (provider.baseUrl !== void 0 && provider.baseUrl.trim() !== "") {
2187
+ urls.push(provider.baseUrl);
2188
+ }
2189
+ return urls;
2190
+ }
2191
+ function providerModels(provider) {
2192
+ const models = provider.models.filter((model) => model.trim() !== "");
2193
+ if (models.length > 0) return models;
2194
+ if (provider.model !== void 0 && provider.model.trim() !== "") return [provider.model];
2195
+ return [];
2196
+ }
2197
+ function registryModelHasUsableMetadata(model) {
2198
+ return model.contextWindow !== void 0 || model.outputLimit !== void 0;
2199
+ }
2200
+ function registryModelMatches(model, registryModel) {
2201
+ const normalized = normalizeModelName$1(model);
2202
+ if (normalized === normalizeModelName$1(registryModel.id)) return true;
2203
+ return registryModel.aliases.some((alias) => normalized === normalizeModelName$1(alias));
2204
+ }
2205
+ function providerEntryMatches(provider, entry) {
2206
+ const providerName = normalizeProviderName(provider.name);
2207
+ const names = entry.name === void 0 ? [...entry.aliases] : [entry.name, ...entry.aliases];
2208
+ const nameMatches = names.some((name) => {
2209
+ const normalized = normalizeProviderName(name);
2210
+ return providerName.includes(normalized) || normalized.includes(providerName);
2211
+ });
2212
+ if (nameMatches) return true;
2213
+ const normalizedProviderUrls = providerBaseUrls(provider).map((url) => normalizeUrl(url)).filter((url) => url !== null);
2214
+ const baseUrlMatches = entry.baseUrls.some((url) => {
2215
+ const normalized = normalizeUrl(url);
2216
+ return normalized !== null && normalizedProviderUrls.includes(normalized);
2217
+ });
2218
+ if (baseUrlMatches) return true;
2219
+ return providerModels(provider).some(
2220
+ (model) => entry.models.some((registryModel) => registryModelMatches(model, registryModel))
2221
+ );
2222
+ }
2223
+ function findRegistryModel(provider, model, registry2) {
2224
+ for (const providerEntry of registry2.providers) {
2225
+ if (!providerEntryMatches(provider, providerEntry)) continue;
2226
+ const matched = providerEntry.models.find(
2227
+ (registryModel) => registryModelMatches(model, registryModel)
2228
+ );
2229
+ if (matched !== void 0 && registryModelHasUsableMetadata(matched)) return matched;
2230
+ }
2231
+ const topLevelMatched = registry2.models.find(
2232
+ (registryModel) => registryModelMatches(model, registryModel)
2233
+ );
2234
+ if (topLevelMatched !== void 0 && registryModelHasUsableMetadata(topLevelMatched)) {
2235
+ return topLevelMatched;
2236
+ }
2237
+ return null;
2238
+ }
2239
+ function findProviderModelMetadata(provider, model) {
2240
+ const normalized = normalizeModelName$1(model);
2241
+ const metadata = provider.modelMetadata ?? [];
2242
+ return metadata.find((entry) => normalizeModelName$1(entry.model) === normalized) ?? null;
2243
+ }
2244
+ function providerHasContextMetadata(provider) {
2245
+ const models = providerModels(provider);
2246
+ if (models.length === 0) return false;
2247
+ return models.every((model) => {
2248
+ const metadata = findProviderModelMetadata(provider, model);
2249
+ return metadata !== null && metadata.contextWindow !== void 0;
2250
+ });
2251
+ }
2252
+ function resolveProviderContextWindow(model, providers) {
2253
+ if (model === null) return null;
2254
+ for (const provider of providers) {
2255
+ const metadata = findProviderModelMetadata(provider, model);
2256
+ if (metadata !== null && metadata.contextWindow !== void 0) {
2257
+ return {
2258
+ providerName: provider.name,
2259
+ model: metadata.model,
2260
+ tokens: metadata.contextWindow,
2261
+ sourceUrl: metadata.sourceUrl
2262
+ };
2263
+ }
2264
+ }
2265
+ return null;
2266
+ }
2267
+ function applyProviderModelRegistry(provider, registry2, sourceUrl, updatedAt, mode = "replace") {
2268
+ const existing = /* @__PURE__ */ new Map();
2269
+ for (const metadata of provider.modelMetadata ?? []) {
2270
+ existing.set(normalizeModelName$1(metadata.model), metadata);
2271
+ }
2272
+ const matchedModels = [];
2273
+ const missingModels = [];
2274
+ for (const model of providerModels(provider)) {
2275
+ const registryModel = findRegistryModel(provider, model, registry2);
2276
+ if (registryModel === null) {
2277
+ missingModels.push(model);
2278
+ continue;
2279
+ }
2280
+ const normalized = normalizeModelName$1(model);
2281
+ const existingMetadata = existing.get(normalized);
2282
+ if (mode === "fill-missing" && existingMetadata !== void 0 && existingMetadata.contextWindow !== void 0 && (existingMetadata.outputLimit !== void 0 || registryModel.outputLimit === void 0)) {
2283
+ continue;
2284
+ }
2285
+ existing.set(normalized, {
2286
+ model,
2287
+ contextWindow: existingMetadata?.contextWindow ?? registryModel.contextWindow,
2288
+ outputLimit: existingMetadata?.outputLimit ?? registryModel.outputLimit,
2289
+ source: existingMetadata?.source ?? "registry",
2290
+ sourceUrl: existingMetadata?.sourceUrl ?? registryModel.sourceUrl ?? sourceUrl,
2291
+ updatedAt
2292
+ });
2293
+ matchedModels.push(model);
2294
+ }
2295
+ const modelMetadata = [...existing.values()].toSorted((a, b) => a.model.localeCompare(b.model));
2296
+ return {
2297
+ modelMetadata,
2298
+ imported: matchedModels.length,
2299
+ matchedModels,
2300
+ missingModels
2301
+ };
2302
+ }
2303
+ function applyBuiltinProviderModelMetadata(provider, updatedAt) {
2304
+ return applyProviderModelRegistry(
2305
+ provider,
2306
+ BUILTIN_PROVIDER_MODEL_REGISTRY,
2307
+ BUILTIN_MODEL_METADATA_SOURCE_URL,
2308
+ updatedAt,
2309
+ "fill-missing"
2310
+ );
2311
+ }
2312
+ function withBuiltinProviderModelMetadata(provider, updatedAt) {
2313
+ const result = applyBuiltinProviderModelMetadata(provider, updatedAt);
2314
+ if (result.imported === 0) return provider;
2315
+ return {
2316
+ ...provider,
2317
+ modelMetadata: result.modelMetadata
2318
+ };
2319
+ }
2066
2320
  object({
2067
2321
  providers: array(ProviderConfigSchema)
2068
2322
  });
@@ -2079,6 +2333,8 @@ const LegacyProviderConfigSchema = object({
2079
2333
  openaiBaseUrl: string().optional(),
2080
2334
  authHeader: _enum(["bearer", "x-api-key"]).optional(),
2081
2335
  apiDocsUrl: string().optional(),
2336
+ modelMetadataUrl: string().optional(),
2337
+ modelMetadata: array(ProviderModelMetadataSchema).optional(),
2082
2338
  source: _enum(["company", "personal"]).optional(),
2083
2339
  createdAt: string().optional(),
2084
2340
  updatedAt: string().optional()
@@ -2115,12 +2371,14 @@ function migrateLegacyProvider(provider, index, now) {
2115
2371
  openaiBaseUrl,
2116
2372
  authHeader: provider.authHeader ?? "bearer",
2117
2373
  apiDocsUrl: provider.apiDocsUrl,
2374
+ modelMetadataUrl: provider.modelMetadataUrl,
2375
+ modelMetadata: provider.modelMetadata,
2118
2376
  source: provider.source,
2119
2377
  createdAt: provider.createdAt ?? now,
2120
2378
  updatedAt: provider.updatedAt ?? now
2121
2379
  };
2122
2380
  const parsed = ProviderConfigSchema.safeParse(candidate);
2123
- return parsed.success ? parsed.data : null;
2381
+ return parsed.success ? withBuiltinProviderModelMetadata(parsed.data, now) : null;
2124
2382
  }
2125
2383
  function migrateFromDataDirConfig(targetStore, dataDirPath) {
2126
2384
  if (process.env["AGENT_INSPECTOR_CONFIG_PATH"] !== void 0) return;
@@ -2161,7 +2419,11 @@ function migrateFromLegacyConfLocation(targetStore) {
2161
2419
  });
2162
2420
  const legacyProviders = legacyStore.get("providers", []);
2163
2421
  if (legacyProviders.length === 0) return;
2164
- targetStore.set("providers", legacyProviders);
2422
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2423
+ targetStore.set(
2424
+ "providers",
2425
+ legacyProviders.map((provider) => withBuiltinProviderModelMetadata(provider, now))
2426
+ );
2165
2427
  logger.info(
2166
2428
  `[providers] Migrated ${legacyProviders.length} provider(s) from ${legacyStore.path} to ${targetStore.path}`
2167
2429
  );
@@ -2260,12 +2522,26 @@ function migrateMultiModel() {
2260
2522
  }
2261
2523
  }
2262
2524
  migrateMultiModel();
2525
+ function migrateBuiltinModelMetadata() {
2526
+ const providers = store.get("providers", []);
2527
+ if (providers.length === 0) return;
2528
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2529
+ const updated = providers.map((provider) => withBuiltinProviderModelMetadata(provider, now));
2530
+ const changed = updated.some(
2531
+ (provider, index) => JSON.stringify(provider) !== JSON.stringify(providers[index])
2532
+ );
2533
+ if (changed) {
2534
+ store.set("providers", updated);
2535
+ }
2536
+ }
2537
+ migrateBuiltinModelMetadata();
2263
2538
  const providersJson = process.env["AGENT_INSPECTOR_PROVIDERS_JSON"];
2264
2539
  if (providersJson !== void 0) {
2265
2540
  try {
2266
2541
  const parsed = ProviderConfigSchema.array().safeParse(JSON.parse(providersJson));
2267
2542
  if (parsed.success) {
2268
- const migrated = parsed.data.map(migrateProvider);
2543
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2544
+ const migrated = parsed.data.map(migrateProvider).map((provider) => withBuiltinProviderModelMetadata(provider, now));
2269
2545
  store.set("providers", migrated);
2270
2546
  }
2271
2547
  } catch {
@@ -2281,7 +2557,7 @@ function getProvider(id) {
2281
2557
  function normalizeApiKey(apiKey) {
2282
2558
  return apiKey.replace(/^Bearer\s+/i, "").trim();
2283
2559
  }
2284
- function addProvider(name, apiKey, format, baseUrl, models, authHeader, apiDocsUrl, anthropicBaseUrl, openaiBaseUrl, source) {
2560
+ function addProvider(name, apiKey, format, baseUrl, models, authHeader, apiDocsUrl, anthropicBaseUrl, openaiBaseUrl, source, modelMetadataUrl) {
2285
2561
  const providers = getProviders();
2286
2562
  const normalizedKey = normalizeApiKey(apiKey);
2287
2563
  const resolvedAnthropicUrl = anthropicBaseUrl ?? "";
@@ -2291,31 +2567,41 @@ function addProvider(name, apiKey, format, baseUrl, models, authHeader, apiDocsU
2291
2567
  (p) => p.apiKey === normalizedKey && (p.anthropicBaseUrl ?? "") === (resolvedAnthropicUrl ?? "") && (p.openaiBaseUrl ?? "") === (resolvedOpenaiUrl ?? "")
2292
2568
  );
2293
2569
  if (existing) {
2570
+ const existingIndex = providers.findIndex((p) => p.id === existing.id);
2294
2571
  const newModels = (models ?? []).filter((m) => m !== "");
2572
+ existing.modelMetadataUrl = modelMetadataUrl ?? existing.modelMetadataUrl;
2295
2573
  if (newModels.length > 0) {
2296
2574
  const mergedModels = new Set(existing.models ?? []);
2297
2575
  for (const m of newModels) mergedModels.add(m);
2298
2576
  existing.models = [...mergedModels];
2299
- existing.updatedAt = now;
2300
- store.set("providers", providers);
2301
2577
  }
2302
- return existing;
2578
+ existing.updatedAt = now;
2579
+ const enriched = withBuiltinProviderModelMetadata(existing, now);
2580
+ if (existingIndex >= 0) {
2581
+ providers[existingIndex] = enriched;
2582
+ }
2583
+ store.set("providers", providers);
2584
+ return enriched;
2303
2585
  }
2304
- const newProvider = {
2305
- id: randomUUID(),
2306
- name,
2307
- apiKey: normalizedKey,
2308
- format: format ?? (anthropicBaseUrl !== void 0 ? "anthropic" : openaiBaseUrl !== void 0 ? "openai" : void 0),
2309
- baseUrl,
2310
- models: models ?? [],
2311
- authHeader: authHeader ?? "bearer",
2312
- apiDocsUrl,
2313
- createdAt: now,
2314
- updatedAt: now,
2315
- anthropicBaseUrl: resolvedAnthropicUrl,
2316
- openaiBaseUrl: resolvedOpenaiUrl,
2317
- source
2318
- };
2586
+ const newProvider = withBuiltinProviderModelMetadata(
2587
+ {
2588
+ id: randomUUID(),
2589
+ name,
2590
+ apiKey: normalizedKey,
2591
+ format: format ?? (anthropicBaseUrl !== void 0 ? "anthropic" : openaiBaseUrl !== void 0 ? "openai" : void 0),
2592
+ baseUrl,
2593
+ models: models ?? [],
2594
+ authHeader: authHeader ?? "bearer",
2595
+ apiDocsUrl,
2596
+ modelMetadataUrl,
2597
+ createdAt: now,
2598
+ updatedAt: now,
2599
+ anthropicBaseUrl: resolvedAnthropicUrl,
2600
+ openaiBaseUrl: resolvedOpenaiUrl,
2601
+ source
2602
+ },
2603
+ now
2604
+ );
2319
2605
  providers.push(newProvider);
2320
2606
  store.set("providers", providers);
2321
2607
  return newProvider;
@@ -2324,22 +2610,28 @@ function updateProvider(id, updates) {
2324
2610
  const providers = getProviders();
2325
2611
  const existing = providers.find((p) => p.id === id);
2326
2612
  if (!existing) return null;
2327
- const updated = {
2328
- id: existing.id,
2329
- name: updates.name ?? existing.name,
2330
- apiKey: updates.apiKey !== void 0 ? normalizeApiKey(updates.apiKey) : existing.apiKey,
2331
- models: updates.models !== void 0 ? updates.models : existing.models,
2332
- format: updates.format ?? existing.format,
2333
- baseUrl: updates.baseUrl !== void 0 ? updates.baseUrl : existing.baseUrl,
2334
- authHeader: updates.authHeader ?? existing.authHeader,
2335
- apiDocsUrl: updates.apiDocsUrl ?? existing.apiDocsUrl,
2336
- createdAt: existing.createdAt,
2337
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2338
- // Handle format-specific URLs
2339
- anthropicBaseUrl: updates.anthropicBaseUrl !== void 0 ? updates.anthropicBaseUrl : existing.anthropicBaseUrl,
2340
- openaiBaseUrl: updates.openaiBaseUrl !== void 0 ? updates.openaiBaseUrl : existing.openaiBaseUrl,
2341
- source: updates.source !== void 0 ? updates.source : existing.source
2342
- };
2613
+ const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2614
+ const updated = withBuiltinProviderModelMetadata(
2615
+ {
2616
+ id: existing.id,
2617
+ name: updates.name ?? existing.name,
2618
+ apiKey: updates.apiKey !== void 0 ? normalizeApiKey(updates.apiKey) : existing.apiKey,
2619
+ models: updates.models !== void 0 ? updates.models : existing.models,
2620
+ format: updates.format ?? existing.format,
2621
+ baseUrl: updates.baseUrl !== void 0 ? updates.baseUrl : existing.baseUrl,
2622
+ authHeader: updates.authHeader ?? existing.authHeader,
2623
+ apiDocsUrl: updates.apiDocsUrl ?? existing.apiDocsUrl,
2624
+ modelMetadataUrl: updates.modelMetadataUrl !== void 0 ? updates.modelMetadataUrl : existing.modelMetadataUrl,
2625
+ modelMetadata: updates.modelMetadata !== void 0 ? updates.modelMetadata : existing.modelMetadata,
2626
+ createdAt: existing.createdAt,
2627
+ updatedAt,
2628
+ // Handle format-specific URLs
2629
+ anthropicBaseUrl: updates.anthropicBaseUrl !== void 0 ? updates.anthropicBaseUrl : existing.anthropicBaseUrl,
2630
+ openaiBaseUrl: updates.openaiBaseUrl !== void 0 ? updates.openaiBaseUrl : existing.openaiBaseUrl,
2631
+ source: updates.source !== void 0 ? updates.source : existing.source
2632
+ },
2633
+ updatedAt
2634
+ );
2343
2635
  const index = providers.findIndex((p) => p.id === id);
2344
2636
  providers[index] = updated;
2345
2637
  store.set("providers", providers);
@@ -2401,12 +2693,16 @@ function importProviders(json) {
2401
2693
  errors.push(`Provider "${provider.name}" already exists, skipping`);
2402
2694
  continue;
2403
2695
  }
2404
- const newProvider = {
2405
- ...provider,
2406
- id: randomUUID(),
2407
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2408
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2409
- };
2696
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2697
+ const newProvider = withBuiltinProviderModelMetadata(
2698
+ {
2699
+ ...provider,
2700
+ id: randomUUID(),
2701
+ createdAt: now,
2702
+ updatedAt: now
2703
+ },
2704
+ now
2705
+ );
2410
2706
  newProviders.push(newProvider);
2411
2707
  existingKeys.add(key);
2412
2708
  imported++;
@@ -3363,7 +3659,7 @@ async function handleProxy(req) {
3363
3659
  }
3364
3660
  return handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log);
3365
3661
  }
3366
- const Route$o = createFileRoute("/proxy/$")({
3662
+ const Route$p = createFileRoute("/proxy/$")({
3367
3663
  server: {
3368
3664
  handlers: {
3369
3665
  GET: ({ request }) => handleProxy(request),
@@ -3375,7 +3671,7 @@ const Route$o = createFileRoute("/proxy/$")({
3375
3671
  }
3376
3672
  }
3377
3673
  });
3378
- const Route$n = createFileRoute("/api/sessions")({
3674
+ const Route$o = createFileRoute("/api/sessions")({
3379
3675
  server: {
3380
3676
  handlers: {
3381
3677
  GET: ({ request }) => {
@@ -3399,9 +3695,10 @@ const ProviderInputSchema = object({
3399
3695
  model: string().optional(),
3400
3696
  authHeader: _enum(["bearer", "x-api-key"]).optional().default("bearer"),
3401
3697
  apiDocsUrl: string().optional(),
3698
+ modelMetadataUrl: string().optional(),
3402
3699
  source: _enum(["company", "personal"]).optional()
3403
3700
  });
3404
- const Route$m = createFileRoute("/api/providers")({
3701
+ const Route$n = createFileRoute("/api/providers")({
3405
3702
  server: {
3406
3703
  handlers: {
3407
3704
  GET: () => {
@@ -3423,14 +3720,15 @@ const Route$m = createFileRoute("/api/providers")({
3423
3720
  parsed.data.apiDocsUrl,
3424
3721
  parsed.data.anthropicBaseUrl,
3425
3722
  parsed.data.openaiBaseUrl,
3426
- parsed.data.source
3723
+ parsed.data.source,
3724
+ parsed.data.modelMetadataUrl
3427
3725
  );
3428
3726
  return Response.json(newProvider, { status: 201 });
3429
3727
  }
3430
3728
  }
3431
3729
  }
3432
3730
  });
3433
- const Route$l = createFileRoute("/api/models")({
3731
+ const Route$m = createFileRoute("/api/models")({
3434
3732
  server: {
3435
3733
  handlers: {
3436
3734
  GET: () => Response.json(getModels())
@@ -4042,7 +4340,7 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
4042
4340
  (args) => safeCall(() => getProjectContextImpl(callApi, args))
4043
4341
  );
4044
4342
  }
4045
- const Route$k = createFileRoute("/api/mcp")({
4343
+ const Route$l = createFileRoute("/api/mcp")({
4046
4344
  server: {
4047
4345
  handlers: {
4048
4346
  // The SDK may issue either POST, GET, or DELETE. TanStack Start only
@@ -4057,7 +4355,7 @@ const Route$k = createFileRoute("/api/mcp")({
4057
4355
  const DeleteBodySchema = object({
4058
4356
  ids: array(number().int().positive()).optional()
4059
4357
  }).optional();
4060
- const Route$j = createFileRoute("/api/logs")({
4358
+ const Route$k = createFileRoute("/api/logs")({
4061
4359
  server: {
4062
4360
  handlers: {
4063
4361
  GET: ({ request }) => {
@@ -4104,7 +4402,7 @@ const Route$j = createFileRoute("/api/logs")({
4104
4402
  }
4105
4403
  });
4106
4404
  logger.debug("Health endpoint loaded");
4107
- const Route$i = createFileRoute("/api/health")({
4405
+ const Route$j = createFileRoute("/api/health")({
4108
4406
  server: {
4109
4407
  handlers: {
4110
4408
  GET: () => {
@@ -4121,7 +4419,7 @@ const RuntimeConfigPatchSchema = object({
4121
4419
  }).strict().refine((v) => Object.keys(v).length > 0, {
4122
4420
  message: "At least one field must be provided"
4123
4421
  });
4124
- const Route$h = createFileRoute("/api/config")({
4422
+ const Route$i = createFileRoute("/api/config")({
4125
4423
  server: {
4126
4424
  handlers: {
4127
4425
  GET: () => {
@@ -4530,7 +4828,7 @@ function scanExternalProviders() {
4530
4828
  }
4531
4829
  return { providers: filteredProviders, warnings };
4532
4830
  }
4533
- const Route$g = createFileRoute("/api/providers/scan")({
4831
+ const Route$h = createFileRoute("/api/providers/scan")({
4534
4832
  server: {
4535
4833
  handlers: {
4536
4834
  GET: () => {
@@ -4551,7 +4849,7 @@ const Route$g = createFileRoute("/api/providers/scan")({
4551
4849
  }
4552
4850
  });
4553
4851
  union([string(), object({ providers: unknown() })]);
4554
- const Route$f = createFileRoute("/api/providers/import")({
4852
+ const Route$g = createFileRoute("/api/providers/import")({
4555
4853
  server: {
4556
4854
  handlers: {
4557
4855
  POST: async ({ request }) => {
@@ -4584,7 +4882,7 @@ const Route$f = createFileRoute("/api/providers/import")({
4584
4882
  }
4585
4883
  }
4586
4884
  });
4587
- const Route$e = createFileRoute("/api/providers/export")({
4885
+ const Route$f = createFileRoute("/api/providers/export")({
4588
4886
  server: {
4589
4887
  handlers: {
4590
4888
  GET: ({ request }) => {
@@ -4613,9 +4911,11 @@ const ProviderUpdateSchema = object({
4613
4911
  anthropicBaseUrl: string().optional(),
4614
4912
  openaiBaseUrl: string().optional(),
4615
4913
  apiDocsUrl: string().optional(),
4914
+ modelMetadataUrl: string().optional(),
4915
+ modelMetadata: array(ProviderModelMetadataSchema).optional(),
4616
4916
  source: _enum(["company", "personal"]).optional()
4617
4917
  });
4618
- const Route$d = createFileRoute("/api/providers/$providerId")({
4918
+ const Route$e = createFileRoute("/api/providers/$providerId")({
4619
4919
  server: {
4620
4920
  handlers: {
4621
4921
  GET: ({ params }) => {
@@ -4647,7 +4947,7 @@ const Route$d = createFileRoute("/api/providers/$providerId")({
4647
4947
  }
4648
4948
  }
4649
4949
  });
4650
- const Route$c = createFileRoute("/api/logs/stream")({
4950
+ const Route$d = createFileRoute("/api/logs/stream")({
4651
4951
  server: {
4652
4952
  handlers: {
4653
4953
  GET: ({ request }) => {
@@ -4711,7 +5011,7 @@ const Route$c = createFileRoute("/api/logs/stream")({
4711
5011
  }
4712
5012
  }
4713
5013
  });
4714
- const Route$b = createFileRoute("/api/logs/$id")({
5014
+ const Route$c = createFileRoute("/api/logs/$id")({
4715
5015
  server: {
4716
5016
  handlers: {
4717
5017
  GET: async ({ params }) => {
@@ -5248,7 +5548,7 @@ const SearchBodySchema = object({
5248
5548
  query: string().min(1),
5249
5549
  project: string().optional()
5250
5550
  });
5251
- const Route$a = createFileRoute("/api/knowledge/search")({
5551
+ const Route$b = createFileRoute("/api/knowledge/search")({
5252
5552
  server: {
5253
5553
  handlers: {
5254
5554
  GET: async ({ request }) => {
@@ -5270,7 +5570,7 @@ const Route$a = createFileRoute("/api/knowledge/search")({
5270
5570
  }
5271
5571
  }
5272
5572
  });
5273
- const Route$9 = createFileRoute("/api/knowledge/project-context")({
5573
+ const Route$a = createFileRoute("/api/knowledge/project-context")({
5274
5574
  server: {
5275
5575
  handlers: {
5276
5576
  GET: async ({ request }) => {
@@ -5352,14 +5652,14 @@ function updateCandidateDraft(id, updates) {
5352
5652
  candidates.set(id, updated);
5353
5653
  return updated;
5354
5654
  }
5355
- const Route$8 = createFileRoute("/api/knowledge/candidates")({
5655
+ const Route$9 = createFileRoute("/api/knowledge/candidates")({
5356
5656
  server: {
5357
5657
  handlers: {
5358
5658
  GET: () => Response.json({ candidates: listCandidates() })
5359
5659
  }
5360
5660
  }
5361
5661
  });
5362
- const Route$7 = createFileRoute("/api/config/paths")({
5662
+ const Route$8 = createFileRoute("/api/config/paths")({
5363
5663
  server: {
5364
5664
  handlers: {
5365
5665
  GET: () => {
@@ -5828,7 +6128,7 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
5828
6128
  return createErrorResult(err, Date.now() - startTime, true);
5829
6129
  }
5830
6130
  }
5831
- const Route$6 = createFileRoute("/api/providers/$providerId/test")({
6131
+ const Route$7 = createFileRoute("/api/providers/$providerId/test")({
5832
6132
  server: {
5833
6133
  handlers: {
5834
6134
  POST: async ({ params }) => {
@@ -5899,6 +6199,116 @@ const Route$6 = createFileRoute("/api/providers/$providerId/test")({
5899
6199
  }
5900
6200
  }
5901
6201
  });
6202
+ const RefreshModelMetadataInputSchema = object({
6203
+ url: string().optional()
6204
+ });
6205
+ function normalizeRefreshUrl(value) {
6206
+ if (value === void 0) return null;
6207
+ const trimmed = value.trim();
6208
+ return trimmed === "" ? null : trimmed;
6209
+ }
6210
+ function isHttpUrl(value) {
6211
+ try {
6212
+ const parsed = new URL(value);
6213
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
6214
+ } catch {
6215
+ return false;
6216
+ }
6217
+ }
6218
+ async function readRegistryJson(response) {
6219
+ try {
6220
+ return JSON.parse(await response.text());
6221
+ } catch {
6222
+ return null;
6223
+ }
6224
+ }
6225
+ const Route$6 = createFileRoute("/api/providers/$providerId/model-metadata")({
6226
+ server: {
6227
+ handlers: {
6228
+ POST: async ({ params, request }) => {
6229
+ const provider = getProvider(params.providerId);
6230
+ if (provider === void 0) {
6231
+ return Response.json({ error: "Provider not found" }, { status: 404 });
6232
+ }
6233
+ const parsed = RefreshModelMetadataInputSchema.safeParse(await request.json());
6234
+ if (!parsed.success) {
6235
+ return Response.json({ error: parsed.error.message }, { status: 400 });
6236
+ }
6237
+ const sourceUrl = normalizeRefreshUrl(
6238
+ parsed.data.url ?? provider.modelMetadataUrl ?? process.env["AGENT_INSPECTOR_MODEL_METADATA_URL"]
6239
+ );
6240
+ if (sourceUrl === null) {
6241
+ const result2 = applyBuiltinProviderModelMetadata(provider, (/* @__PURE__ */ new Date()).toISOString());
6242
+ const updated2 = updateProvider(provider.id, {
6243
+ modelMetadata: result2.modelMetadata
6244
+ });
6245
+ if (updated2 === null) {
6246
+ return Response.json({ error: "Provider not found" }, { status: 404 });
6247
+ }
6248
+ return Response.json({
6249
+ provider: updated2,
6250
+ imported: result2.imported,
6251
+ matchedModels: result2.matchedModels,
6252
+ missingModels: result2.missingModels,
6253
+ sourceUrl: BUILTIN_MODEL_METADATA_SOURCE_URL
6254
+ });
6255
+ }
6256
+ if (!isHttpUrl(sourceUrl)) {
6257
+ return Response.json(
6258
+ { error: "Model metadata URL must be an http(s) URL." },
6259
+ { status: 400 }
6260
+ );
6261
+ }
6262
+ let response;
6263
+ try {
6264
+ response = await fetch(sourceUrl, { headers: { Accept: "application/json" } });
6265
+ } catch (err) {
6266
+ return Response.json(
6267
+ { error: `Failed to fetch model metadata: ${String(err)}` },
6268
+ { status: 502 }
6269
+ );
6270
+ }
6271
+ if (!response.ok) {
6272
+ return Response.json(
6273
+ { error: `Model metadata fetch failed with HTTP ${String(response.status)}` },
6274
+ { status: 502 }
6275
+ );
6276
+ }
6277
+ const registryJson = await readRegistryJson(response);
6278
+ if (registryJson === null) {
6279
+ return Response.json(
6280
+ { error: "Model metadata response is not valid JSON." },
6281
+ { status: 400 }
6282
+ );
6283
+ }
6284
+ const registry2 = ProviderModelRegistrySchema.safeParse(registryJson);
6285
+ if (!registry2.success) {
6286
+ return Response.json({ error: registry2.error.message }, { status: 400 });
6287
+ }
6288
+ const result = applyProviderModelRegistry(
6289
+ provider,
6290
+ registry2.data,
6291
+ sourceUrl,
6292
+ (/* @__PURE__ */ new Date()).toISOString()
6293
+ );
6294
+ const updated = updateProvider(provider.id, {
6295
+ modelMetadata: result.modelMetadata,
6296
+ modelMetadataUrl: sourceUrl
6297
+ });
6298
+ if (updated === null) {
6299
+ return Response.json({ error: "Provider not found" }, { status: 404 });
6300
+ }
6301
+ return Response.json({
6302
+ provider: updated,
6303
+ imported: result.imported,
6304
+ matchedModels: result.matchedModels,
6305
+ missingModels: result.missingModels,
6306
+ sourceUrl
6307
+ });
6308
+ }
6309
+ }
6310
+ }
6311
+ });
5902
6312
  const ReplayRequestSchema = object({
5903
6313
  modifiedBody: string()
5904
6314
  });
@@ -6447,111 +6857,116 @@ const Route = createFileRoute("/api/knowledge/candidates/$candidateId/promote")(
6447
6857
  }
6448
6858
  }
6449
6859
  });
6450
- const IndexRoute = Route$q.update({
6860
+ const IndexRoute = Route$r.update({
6451
6861
  id: "/",
6452
6862
  path: "/",
6453
- getParentRoute: () => Route$r
6863
+ getParentRoute: () => Route$s
6454
6864
  });
6455
- const SessionSessionIdRoute = Route$p.update({
6865
+ const SessionSessionIdRoute = Route$q.update({
6456
6866
  id: "/session/$sessionId",
6457
6867
  path: "/session/$sessionId",
6458
- getParentRoute: () => Route$r
6868
+ getParentRoute: () => Route$s
6459
6869
  });
6460
- const ProxySplatRoute = Route$o.update({
6870
+ const ProxySplatRoute = Route$p.update({
6461
6871
  id: "/proxy/$",
6462
6872
  path: "/proxy/$",
6463
- getParentRoute: () => Route$r
6873
+ getParentRoute: () => Route$s
6464
6874
  });
6465
- const ApiSessionsRoute = Route$n.update({
6875
+ const ApiSessionsRoute = Route$o.update({
6466
6876
  id: "/api/sessions",
6467
6877
  path: "/api/sessions",
6468
- getParentRoute: () => Route$r
6878
+ getParentRoute: () => Route$s
6469
6879
  });
6470
- const ApiProvidersRoute = Route$m.update({
6880
+ const ApiProvidersRoute = Route$n.update({
6471
6881
  id: "/api/providers",
6472
6882
  path: "/api/providers",
6473
- getParentRoute: () => Route$r
6883
+ getParentRoute: () => Route$s
6474
6884
  });
6475
- const ApiModelsRoute = Route$l.update({
6885
+ const ApiModelsRoute = Route$m.update({
6476
6886
  id: "/api/models",
6477
6887
  path: "/api/models",
6478
- getParentRoute: () => Route$r
6888
+ getParentRoute: () => Route$s
6479
6889
  });
6480
- const ApiMcpRoute = Route$k.update({
6890
+ const ApiMcpRoute = Route$l.update({
6481
6891
  id: "/api/mcp",
6482
6892
  path: "/api/mcp",
6483
- getParentRoute: () => Route$r
6893
+ getParentRoute: () => Route$s
6484
6894
  });
6485
- const ApiLogsRoute = Route$j.update({
6895
+ const ApiLogsRoute = Route$k.update({
6486
6896
  id: "/api/logs",
6487
6897
  path: "/api/logs",
6488
- getParentRoute: () => Route$r
6898
+ getParentRoute: () => Route$s
6489
6899
  });
6490
- const ApiHealthRoute = Route$i.update({
6900
+ const ApiHealthRoute = Route$j.update({
6491
6901
  id: "/api/health",
6492
6902
  path: "/api/health",
6493
- getParentRoute: () => Route$r
6903
+ getParentRoute: () => Route$s
6494
6904
  });
6495
- const ApiConfigRoute = Route$h.update({
6905
+ const ApiConfigRoute = Route$i.update({
6496
6906
  id: "/api/config",
6497
6907
  path: "/api/config",
6498
- getParentRoute: () => Route$r
6908
+ getParentRoute: () => Route$s
6499
6909
  });
6500
- const ApiProvidersScanRoute = Route$g.update({
6910
+ const ApiProvidersScanRoute = Route$h.update({
6501
6911
  id: "/scan",
6502
6912
  path: "/scan",
6503
6913
  getParentRoute: () => ApiProvidersRoute
6504
6914
  });
6505
- const ApiProvidersImportRoute = Route$f.update({
6915
+ const ApiProvidersImportRoute = Route$g.update({
6506
6916
  id: "/import",
6507
6917
  path: "/import",
6508
6918
  getParentRoute: () => ApiProvidersRoute
6509
6919
  });
6510
- const ApiProvidersExportRoute = Route$e.update({
6920
+ const ApiProvidersExportRoute = Route$f.update({
6511
6921
  id: "/export",
6512
6922
  path: "/export",
6513
6923
  getParentRoute: () => ApiProvidersRoute
6514
6924
  });
6515
- const ApiProvidersProviderIdRoute = Route$d.update({
6925
+ const ApiProvidersProviderIdRoute = Route$e.update({
6516
6926
  id: "/$providerId",
6517
6927
  path: "/$providerId",
6518
6928
  getParentRoute: () => ApiProvidersRoute
6519
6929
  });
6520
- const ApiLogsStreamRoute = Route$c.update({
6930
+ const ApiLogsStreamRoute = Route$d.update({
6521
6931
  id: "/stream",
6522
6932
  path: "/stream",
6523
6933
  getParentRoute: () => ApiLogsRoute
6524
6934
  });
6525
- const ApiLogsIdRoute = Route$b.update({
6935
+ const ApiLogsIdRoute = Route$c.update({
6526
6936
  id: "/$id",
6527
6937
  path: "/$id",
6528
6938
  getParentRoute: () => ApiLogsRoute
6529
6939
  });
6530
- const ApiKnowledgeSearchRoute = Route$a.update({
6940
+ const ApiKnowledgeSearchRoute = Route$b.update({
6531
6941
  id: "/api/knowledge/search",
6532
6942
  path: "/api/knowledge/search",
6533
- getParentRoute: () => Route$r
6943
+ getParentRoute: () => Route$s
6534
6944
  });
6535
- const ApiKnowledgeProjectContextRoute = Route$9.update({
6945
+ const ApiKnowledgeProjectContextRoute = Route$a.update({
6536
6946
  id: "/api/knowledge/project-context",
6537
6947
  path: "/api/knowledge/project-context",
6538
- getParentRoute: () => Route$r
6948
+ getParentRoute: () => Route$s
6539
6949
  });
6540
- const ApiKnowledgeCandidatesRoute = Route$8.update({
6950
+ const ApiKnowledgeCandidatesRoute = Route$9.update({
6541
6951
  id: "/api/knowledge/candidates",
6542
6952
  path: "/api/knowledge/candidates",
6543
- getParentRoute: () => Route$r
6953
+ getParentRoute: () => Route$s
6544
6954
  });
6545
- const ApiConfigPathsRoute = Route$7.update({
6955
+ const ApiConfigPathsRoute = Route$8.update({
6546
6956
  id: "/paths",
6547
6957
  path: "/paths",
6548
6958
  getParentRoute: () => ApiConfigRoute
6549
6959
  });
6550
- const ApiProvidersProviderIdTestRoute = Route$6.update({
6960
+ const ApiProvidersProviderIdTestRoute = Route$7.update({
6551
6961
  id: "/test",
6552
6962
  path: "/test",
6553
6963
  getParentRoute: () => ApiProvidersProviderIdRoute
6554
6964
  });
6965
+ const ApiProvidersProviderIdModelMetadataRoute = Route$6.update({
6966
+ id: "/model-metadata",
6967
+ path: "/model-metadata",
6968
+ getParentRoute: () => ApiProvidersProviderIdRoute
6969
+ });
6555
6970
  const ApiLogsIdReplayRoute = Route$5.update({
6556
6971
  id: "/replay",
6557
6972
  path: "/replay",
@@ -6575,7 +6990,7 @@ const ApiProvidersProviderIdTestLogRoute = Route$2.update({
6575
6990
  const ApiKnowledgeSessionsSessionIdCandidatesRoute = Route$1.update({
6576
6991
  id: "/api/knowledge/sessions/$sessionId/candidates",
6577
6992
  path: "/api/knowledge/sessions/$sessionId/candidates",
6578
- getParentRoute: () => Route$r
6993
+ getParentRoute: () => Route$s
6579
6994
  });
6580
6995
  const ApiKnowledgeCandidatesCandidateIdPromoteRoute = Route.update({
6581
6996
  id: "/promote",
@@ -6607,6 +7022,7 @@ const ApiProvidersProviderIdTestRouteWithChildren = ApiProvidersProviderIdTestRo
6607
7022
  ApiProvidersProviderIdTestRouteChildren
6608
7023
  );
6609
7024
  const ApiProvidersProviderIdRouteChildren = {
7025
+ ApiProvidersProviderIdModelMetadataRoute,
6610
7026
  ApiProvidersProviderIdTestRoute: ApiProvidersProviderIdTestRouteWithChildren
6611
7027
  };
6612
7028
  const ApiProvidersProviderIdRouteWithChildren = ApiProvidersProviderIdRoute._addFileChildren(
@@ -6649,7 +7065,7 @@ const rootRouteChildren = {
6649
7065
  ApiKnowledgeSearchRoute,
6650
7066
  ApiKnowledgeSessionsSessionIdCandidatesRoute
6651
7067
  };
6652
- const routeTree = Route$r._addFileChildren(rootRouteChildren)._addFileTypes();
7068
+ const routeTree = Route$s._addFileChildren(rootRouteChildren)._addFileTypes();
6653
7069
  function getRouter() {
6654
7070
  const router2 = createRouter({
6655
7071
  routeTree,
@@ -6669,17 +7085,21 @@ export {
6669
7085
  MAX_SLOW_RESPONSE_THRESHOLD_SECONDS as M,
6670
7086
  OpenAIRequestSchema as O,
6671
7087
  ProviderTestResultsSchema as P,
6672
- Route$p as R,
7088
+ Route$q as R,
6673
7089
  TimeDisplayFormatSchema as T,
6674
7090
  DEFAULT_TIME_DISPLAY_FORMAT as a,
6675
7091
  RuntimeConfigSchema as b,
6676
7092
  AnthropicRequestSchema as c,
6677
7093
  stripClaudeCodeBillingHeader as d,
6678
- createPendingProviderTestResults as e,
6679
- createFailedProviderTestResults as f,
7094
+ providerHasContextMetadata as e,
7095
+ findProviderModelMetadata as f,
6680
7096
  getSessionPath as g,
6681
- ProviderConfigSchema as h,
6682
- router as i,
7097
+ createPendingProviderTestResults as h,
7098
+ createFailedProviderTestResults as i,
7099
+ ProviderConfigSchema as j,
7100
+ resolveProviderContextWindow as k,
7101
+ isPlainRecord as l,
7102
+ router as m,
6683
7103
  parseOpenAIResponse as p,
6684
7104
  requestFormatForPath as r,
6685
7105
  safeGetOwnProperty as s