diff --git a/src/web/routes/custom-model-routes.ts b/src/web/routes/custom-model-routes.ts index 25e5d8af..28fb70e2 100644 --- a/src/web/routes/custom-model-routes.ts +++ b/src/web/routes/custom-model-routes.ts @@ -21,7 +21,7 @@ import { isMultiUserMode } from '../../config/multiuser.js'; import { getDataDir } from '../../config/instance.js'; import { isBlockedWebviewUrl } from '../webview-egress-policy.js'; import { egressBlockedReason, webviewFetch } from '../webview-egress.js'; -import { CustomModelHostSchema } from '../schemas.js'; +import { CustomModelHostSchema, MAX_DISCOVERED_CONTEXT_TOKENS } from '../schemas.js'; import { readCustomModelHosts, writeCustomModelHosts, type CustomModelHost } from '../../custom-model-hosts.js'; import type { CliEntry } from '../../config/cli-registry/types.js'; @@ -187,13 +187,6 @@ function parseSizeGB(description: unknown): number | undefined { return Number.isFinite(size) && size > 0 ? size : undefined; } -/** - * Ceiling shared with `schemas.ts`'s `CustomModelHostSchema` bound on context lengths: - * anything above it reads as nonsense and is ignored, because a bogus figure here - * overflows the smaller server, which is the exact failure this field exists to prevent. - */ -const MAX_DISCOVERED_CONTEXT_TOKENS = 100_000_000; - /** * Best-effort: reads a context length (tokens) stated by a model's OWN entry in * `GET /v1/models`. OpenRouter-style servers call the field `context_length`; current diff --git a/src/web/schemas.ts b/src/web/schemas.ts index bf97b7b4..6760a5d9 100644 --- a/src/web/schemas.ts +++ b/src/web/schemas.ts @@ -2352,6 +2352,14 @@ export const WebviewUpdateSchema = WebviewBaseSchema.partial(); /** POST /api/webviews/probe: reachability + framing check for the editor's Test button. */ export const WebviewProbeSchema = z.object({ url: webviewUrlSchema }); +/** + * Ceiling on a stated context length (tokens), shared between the bounds below and + * discovery (`custom-model-routes.ts`): anything above it reads as nonsense and is + * ignored, because a bogus figure here overflows the smaller server, which is the exact + * failure the discovery field exists to prevent. + */ +export const MAX_DISCOVERED_CONTEXT_TOKENS = 100_000_000; + // Custom Model Endpoint Profiles (docs/custom-model-endpoints-plan.md) — a // user-configured custom OpenAI-compatible endpoint, local (llama.cpp) or cloud // (Azure AI Foundry, etc.). Lives below `webviewUrlSchema` because `baseUrl` IS that @@ -2375,14 +2383,16 @@ export const CustomModelHostSchema = z.object({ defaultModelId: z.string().max(200).optional(), // Server-populated by discovery (custom-model-routes.ts); accepted here only so a client // round-tripping the GET response back through PUT (edit-save) doesn't drop it. - modelContextLengths: z.record(z.string().max(200), z.number().int().positive().max(100_000_000)).optional(), + modelContextLengths: z + .record(z.string().max(200), z.number().int().positive().max(MAX_DISCOVERED_CONTEXT_TOKENS)) + .optional(), // Same reasoning as modelContextLengths above. modelSlotCounts: z.record(z.string().max(200), z.number().int().positive().max(4096)).optional(), // Same reasoning as modelContextLengths above. modelSizesGB: z.record(z.string().max(200), z.number().positive().max(100_000)).optional(), // User-set fallback for models discovery has no context length for (session-routes.ts); // discovery never writes it. Same bound as the modelContextLengths values above. - defaultContextLength: z.number().int().positive().max(100_000_000).optional(), + defaultContextLength: z.number().int().positive().max(MAX_DISCOVERED_CONTEXT_TOKENS).optional(), }); /**