- Derived the mandatory low, high, and max ladder for Kimi K3 across OpenAI-compatible routes.
- Mapped generic requested tiers onto K3 wire values and defaulted the model to max.
- Added request-level regression coverage for LiteLLM-compatible models.
Fixes#5983
- Enable `moonshot-mfjs` tool schema flavor for Kimi-family ids on any host, not just native endpoints, since proxies forward schemas verbatim to Moonshot's validator.
The grammar tool-schema flavor preserves boolean additionalProperties/unevaluatedProperties rather than stripping them; the doc comment wrongly promised the Ollama-style strip.
Local grammar-constrained OpenAI-compatible servers (llama.cpp, LM Studio,
vLLM) build a GBNF grammar from tool JSON Schemas and 400 with
"Unrecognized schema: true" on a bare boolean subschema. The task tool's
open outputSchema field normalizes to boolean `true` (issue #1179), which
the converter cannot compile, breaking every tool request.
Add a "grammar" tool-schema flavor, auto-detected for local backends, that
widens bare boolean/empty subschemas into a value-accepting primitive union
while preserving closed-object `additionalProperties: false`.
Fixes#5914
- Parsed live named efforts, mandatory-thinking state, and model protocol metadata.
- Sent native Kimi named efforts and adaptive Anthropic override efforts without generic token budgets.
Fixes#5893
Added an opt-in compatibility flag for non-official Anthropic OAuth endpoints while preserving authoritative OAuth and Cloudflare credentials.
Fixes#5888
Invalidated rich-v4 rows so upgraded clients immediately refresh models with corrected per-model pricing instead of serving stale zero-cost entries until TTL expiry.
mapLiteLLMRichEntry read token limits and capabilities from LiteLLM's
rich model_info but hardcoded cost to the bundled reference or a zero
sentinel, so any model absent from the bundled catalog / models.dev
displayed as free even when LiteLLM reported real pricing.
Read input_cost_per_token / output_cost_per_token (and cache costs) via
getLiteLLMCost, converting per-token to per-million, and carry cost
through the cross-endpoint merge in fetchLiteLLMRichModels. Fall back to
the bundled reference only when LiteLLM omits cost.
Fixes#5818
Skipped recording 401 rich-endpoint failures as fallback diagnostics so the caller's auth-retry path (withAuth refresh/sibling rotation) is not pre-empted by a warning from a stale first credential.
Kept 403 and other non-retryable failures warn-worthy.
Fixes#5801
Logged one actionable warning per LiteLLM management base when rich metadata discovery fails, while keeping missing 404 routes silent.
Documented metadata-route permissions and covered forbidden versus absent endpoints.
Fixes#5801
Reinstates the catalog regeneration (glm-4.5 reasoning/effort metadata,
refreshed pricing and limits) that the previous commit wrongly rolled
back. The three failing tests were pinned to stale upstream metadata;
they now assert the durable contracts instead: K2.7-Code stays above
the 32,768 K2-family cap and tracks the bundled reference, and K3
asserts effort-mode metadata while the wire-body test remains the
binding reasoning_effort=max contract.
A stale regenerated models.json rode the previous commit from the
shared index; it contradicted the Fireworks K2.7-Code output-ceiling
and Moonshot K3 reasoning contracts (#1849, #5756). Restored the
snapshot those tests verify; a deliberate catalog refresh should
reconcile the K3/K2.7 policies first.
The 50ms budget raced external-process spawn on cold CI runners: cancel
could fire before yes produced output, so the builtin tail flushed an
empty ring buffer (0 lines instead of 5, Linux x64 modern). 750ms keeps
the post-cancel drain scenario while outlasting spawn latency.
Recorded which cached model ids had headers omitted and which header sets cannot be reconstructed from current static inputs.
Fresh/offline cache reads now restore exact static headers before returning models. Dynamic-only or dynamically-augmented header models bypass fresh-cache reuse and refetch online; offline and failure fallbacks omit them instead of returning unusable models without required transport headers.
Bumped the cache schema to v10 and added static, dynamic, offline, and raw-persistence regressions.
Fixes#5780
Replaced the incomplete credential-header denylist with a default-deny cache boundary: no model header values are persisted because custom providers may use arbitrary authentication header names.
Bumped the cache schema to v9 and enabled SQLite secure_delete so older header-bearing rows are invalidated without leaving credential bytes in free pages. Added coverage for X-Goog-Api-Key, X-Access-Token, arbitrary headers, and physical scrubbing of pre-v9 cache rows.
Fixes#5780
Native /login and /logout (plus setup-wizard sign-in and RPC login)
refreshed model discovery with the default all-provider
online-if-uncached strategy, which reused a fresh authoritative cache row
and never re-ran fetchDynamicModels with the just-persisted credential,
so newly authenticated models stayed unavailable in-session and stale
endpoint data survived a relogin. Each auth-completion path now awaits a
provider-scoped refreshProvider(providerId, "online").
Also fixed writeModelCache serializing credential-bearing request headers
(Authorization, X-Api-Key, api-key, cookie, proxy-authorization) into the
plaintext models.db; they are now stripped before persistence and
re-derived on load from AuthStorage / provider config.
Fixes#5780
- Updated models.json to set maxTokens to 65536 for Kimi K2.7-Code entries.
- Adjusted openai-compat logic to use a new 65,536 ceiling for K2.7-Code while preserving the 32,768 cap for older K2 models.
- Modified tests to verify the new token limit and ensure K2.7-Code models are excluded from the older cap.
Native Kimi K3 always reasons via reasoning_effort: "max" and is newly marked
requiresEffort. The Kimi-family disableReasoningOnForcedToolChoice rule (added
for the K2.x Moonshot 400 "tool_choice 'specified' is incompatible with
thinking enabled", #827) applies only to the binary thinking block K3 never
sends, so it wrongly stripped K3's effort on forced-tool turns — e.g. plan-mode
toolChoice: "required" — leaving mandatory reasoning off on the wire.
- Exempted native K3 from disableReasoningOnForcedToolChoice.
- Added a regression test asserting reasoning_effort=max survives a forced
tool_choice turn while no thinking block is emitted.
Fixes#5756
Native moonshot/kimi-k3 is dynamically discovered but has no bundled or
models.dev reference, so mapWithBundledReference fell through to the generic
dynamic defaults: zero token cost, null limits, text-only input, and no
reasoning. /models then labeled the paid model "Free".
- Added isKimiK3ModelId identity helper for any-namespace K3 ids.
- Stamped Moonshot's official K3 pricing ($3 input / $0.30 cache-hit / $15
output), 1,048,576-token context, 131,072 default max output, image input,
and always-on reasoning in the moonshot discovery mapper.
- Routed native K3 reasoning through OpenAI-style reasoning_effort: "max"
instead of the K2.x binary thinking: { type } block, which K3 does not use.
- Widened the 300s reasoning stream-idle floor to cover native K3.
Fixes#5756
- Repointed the Umans models.dev descriptor to published PAYG rates.
- Backfilled authoritative discovery rows and the Flash technical alias.
- Added runtime, descriptor, and bundled catalog regression coverage.
Fixes#5733
The generation-time policy pin only corrected the bundled JSON. Logged-in
Codex users hit fetchCodexModels() at runtime, and mergeDynamicModel prefers
any positive dynamic contextWindow over the bundled one, so the 272000
discovery fallback re-overwrote the 372000 bundle on every live refresh.
Made the Codex discovery context_window fallback SKU-aware: GPT-5.6
luna/sol/terra now fall back to 372000 (their upstream hard capacity) when
upstream omits the field, matching the generation-time policy.
Fixes#5705
Codex discovery falls back to DEFAULT_CONTEXT_WINDOW (272000) when upstream
omits context_window, which overwrote the previously-bundled 372000 hard
capacity for openai-codex gpt-5.6 luna/sol/terra on regen. OpenAI's Codex
model registry declares context_window = max_context_window = 372000, and a
direct Responses request with 350,317 input tokens completes, proving 272K is
not the route's hard cap.
Pinned these SKUs to 372000 in applyOpenAICatalogPolicy and refreshed the
bundled entries.
Fixes#5705
- Applied `applyOpenRouterReportedCost` in completion parsing and shared usage population so reported OpenRouter charges are now reconciled before tier adjustment.
- Scaled usage component costs by the reported-to-estimated ratio and retained an input-only fallback when estimated totals were missing.
- Added OpenRouter-specific usage tests for SSE responses and chunk parsing to assert done-message totals and component sums match reported cost.
- Updated the model catalog with new provider/model records and revised costs, limits, and metadata.
GitHub Copilot's mai-code-1-flash-picker (and other mai-* models) are
served only through the /responses endpoint; the classifier routed them
to /chat/completions, which returned 400 unsupported_api_for_model.
Added the mai- prefix to isCopilotResponsesModelId so both dynamic
discovery (inferCopilotApi) and bundled resolution
(COPILOT_API_RESOLUTION_RULES) select openai-responses, and updated the
bundled models.json entry to match.
Fixes#5612
- Added resolved sampling-parameter compatibility for OpenAI o-series and GPT-5+ models.
- Stopped Responses and Chat Completions payloads from forwarding temperature and related controls to restricted models.
- Added catalog and wire-payload regressions for GitHub Copilot GPT-5.6 Luna.
Fixes#5606
The `zai` provider descriptor mapped the models.dev `zai-coding-plan`
key, which reports all-$0 subscription rates, so 13 of 14 GLM SKUs
showed token cost as "Free" in /models. The models.dev `zai`
pay-as-you-go key carries the real per-token rates for the identical
model ids, matching how other subscription providers surface comparison
pricing.
- Point the `zai` descriptor at the `zai` models.dev key.
- Regenerate the bundled zai cost blocks from the PAYG rates.
- Add issue-5598 regression test against the descriptor + mapper.
Fixes#5598
A litellm proxy on a loopback baseUrl fronting a local llama.cpp/vLLM server
was excluded from isLocalOpenAICompatBackend (PROXY_OPENAI_COMPAT_PROVIDERS)
so replayReasoningContent stays off proxies that may forward to an unrelated
cloud upstream. That exclusion also stripped the 300s LOCAL_OPENAI_COMPAT
stream-timeout floor, so the first-event budget fell back to the 100s default.
A slow prefill on a large prompt (llama.cpp "non-consecutive token position"
KV thrash + reprocess) then exceeded 100s, aborting with "OpenAI completions
stream timed out while waiting for the first event" and retry-looping.
Decouple the stream-timeout floor from the replay gate: the floor now applies
to any loopback/RFC1918 backend (including proxies) because widening the abort
ceiling only helps a slow local upstream and never forwards an extra wire
field. Reasoning replay stays gated to first-party local providers. Applied to
both the completions and responses compat builders.
Fixes#4786
Built-in discovery skipped the OAuth refresh whenever a fresh authoritative cache existed, so an openai-codex user with an expired access token never got the model manager constructed and stale bundled models (e.g. gpt-5.4-nano) stayed selectable for the full cache TTL. Force the refresh for authoritative providers and forward the registry fetch through the Codex manager so discovery honors the configured transport.
Fixes#5364
Authoritative OpenCode model catalogs now use credential-and-endpoint-specific cache namespaces so one account cannot reuse another account's entitlements.
Fixes#4769