Skip to content

feat(core): strip unsupported sampling params via capability registry#18622

Draft
intojhanurag wants to merge 1 commit into
mastra-ai:mainfrom
intojhanurag:feat/temperature-capability-registry
Draft

feat(core): strip unsupported sampling params via capability registry#18622
intojhanurag wants to merge 1 commit into
mastra-ai:mainfrom
intojhanurag:feat/temperature-capability-registry

Conversation

@intojhanurag

@intojhanurag intojhanurag commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Description

Extends the model capability registry to include a temperature dimension so the model router can proactively strip unsupported sampling parameters (temperature, topP, topK) before dispatching requests. Models like claude-opus-4-7 and gpt-5-pro that report temperature: false on models.dev now have these parameters silently removed, preventing 400 errors with zero user configuration.

  • Generalized the attachment-only capability loader into a multi-dimension system (CapabilityDimension) that reads both attachment and temperature from per-provider JSON files
  • Added modelSupportsTemperature() public lookup function following the same pattern as modelSupportsAttachments()
  • Added stripUnsupportedSamplingParams() in ModelRouterLanguageModel that checks the registry before every doGenerate and doStream call
  • Extended ModelsDevGateway.fetchProviders() to collect temperature capability data from models.dev alongside attachments
  • Updated registry-generator and generate-providers script to write merged capability files with both dimensions
  • Added temperature data to anthropic.json and openai.json capability files sourced from the live models.dev API

Related Issue(s)

Fixes #16247

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Test update

Checklist

  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works
  • I have addressed all Coderabbit comments on this PR

ELI5

Some AI models only accept certain “settings” for how creative the response should be. This PR teaches the router to look up which settings each model supports and automatically remove unsupported ones (like temperature) so requests don’t fail.

Summary

  • Extended the model capability registry to support a new temperature dimension alongside existing attachment support.
  • Updated the registry generator (and provider-generation scripts) to load/merge capability data from providers into capability files containing both attachment and temperature.
  • Enhanced ModelRouterLanguageModel to strip unsupported sampling parameters (temperature, topP, and topK for streaming) before calling doGenerate/doStream, based on modelSupportsTemperature().
  • Updated ModelsDevGateway.fetchProviders() to collect temperature capability data from models.dev and write it into the generated registries.
  • Added modelSupportsTemperature() (and exported it from core) alongside the existing attachment capability lookup.
  • Refreshed anthropic.json and openai.json temperature capability lists (and adjusted attachment allowlists), and added tests to verify the router’s parameter-stripping behavior.

@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

@intojhanurag is attempting to deploy a commit to the Mastra Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 236c487

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@mastra/core Minor
mastracode Patch
@mastra/mcp-docs-server Patch
@internal/playground Patch
@mastra/client-js Patch
@mastra/opencode Patch
@mastra/longmemeval Patch
mastra Patch
@mastra/deployer-cloud Minor
@mastra/react Patch
@mastra/playground-ui Patch
@mastra/server Minor
@mastra/deployer Minor
create-mastra Patch
@mastra/express Patch
@mastra/fastify Patch
@mastra/hono Patch
@mastra/koa Patch
@mastra/nestjs Patch
@mastra/next Patch
@mastra/tanstack-start Patch
@mastra/temporal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@intojhanurag intojhanurag marked this pull request as draft June 29, 2026 13:56
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8344d494-a697-449f-ba78-72839604905a

📥 Commits

Reviewing files that changed from the base of the PR and between 7d67858 and 236c487.

📒 Files selected for processing (1)
  • .changeset/twelve-candles-love.md
✅ Files skipped from review due to trivial changes (1)
  • .changeset/twelve-candles-love.md

Walkthrough

Adds temperature capability tracking to provider registry generation and lookup, then uses it in the model router to strip unsupported temperature, topP, and topK parameters before dispatch. Static capability files, public exports, tests, and a changeset are updated accordingly.

Changes

Temperature Capability Registry and Router Stripping

Layer / File(s) Summary
TemperatureCapabilities type and models-dev collection
packages/core/src/llm/model/gateways/base.ts, packages/core/src/llm/model/gateways/models-dev.ts
Defines TemperatureCapabilities, extends ModelsDevModelInfo with temperature?: boolean, collects temperature-capable model IDs per provider in fetchProviders, and exposes getTemperatureCapabilities().
registry-generator: temperature capability propagation
packages/core/src/llm/model/registry-generator.ts
Adds temperature-capability typing and detection for gateways, merges temperature capabilities in fetchProvidersFromGateways, and writes per-provider capability JSON with attachment and temperature fields.
provider-registry: dimension-based capability lookup
packages/core/src/llm/model/provider-registry.ts
Refactors capability lookup into dimension-based caches and helpers, adds modelSupportsTemperature and _resetCapabilityCaches, and updates GatewayRegistry.syncGateways to propagate and invalidate temperature caches.
Static capability JSON files
packages/core/src/llm/model/capabilities/anthropic.json, packages/core/src/llm/model/capabilities/openai.json
Updates Anthropic and OpenAI capability allowlists for attachment and temperature support.
Router sampling param stripping
packages/core/src/llm/model/router.ts
Adds stripUnsupportedSamplingParams and applies sanitized options in both doGenerate and doStream.
Public exports, script, and changeset
packages/core/src/llm/model/index.ts, packages/core/src/llm/index.ts, packages/core/scripts/generate-providers.ts, .changeset/twelve-candles-love.md
Re-exports modelSupportsTemperature, updates generate-providers to forward and log temperature capabilities, and adds the changeset entry.
Tests
packages/core/src/llm/model/provider-registry.test.ts, packages/core/src/llm/model/router-custom-provider.test.ts
Adds modelSupportsTemperature tests with cache reset and router tests covering stripping, preservation, and streaming behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mastra-ai/mastra#18500: Both PRs modify ModelRouterLanguageModel’s doGenerate/doStream paths in packages/core/src/llm/model/router.ts.

Suggested labels

tests: green ✅

Suggested reviewers

  • abhiaiyer91
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: stripping unsupported sampling params via the capability registry.
Linked Issues check ✅ Passed The PR implements the requested capability-driven fix by auto-stripping unsupported sampling params before dispatching requests.
Out of Scope Changes check ✅ Passed The changes stay focused on capability registry updates, router sanitization, tests, and provider capability data.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@dane-ai-mastra dane-ai-mastra Bot added the complexity: medium Medium-complexity PR label Jun 29, 2026
@dane-ai-mastra

dane-ai-mastra Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR triage

Linked issue check skipped for core contributor @intojhanurag.


PR complexity score

Factor Value Score impact
Files changed 13 +26
Lines changed 437 +24
Author merged PRs 213 -20
Test files changed Yes -10
Final score 20

Applied label: complexity: medium


Changed test gate

Changed Test Gate is pending. The Changed Test Gate / changed-tests check will update the test label when it completes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
packages/core/src/llm/model/router-custom-provider.test.ts (1)

214-301: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a custom-provider pass-through case.

All new assertions use registry-backed OpenAI IDs. The router only strips when capability lookup returns false; unknown/custom providers return undefined and should keep temperature/topP/topK. A dedicated test here would lock that behavior down.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/llm/model/router-custom-provider.test.ts` around lines 214
- 301, The new temperature-stripping tests in router-custom-provider.test.ts
only cover registry-backed OpenAI IDs, but they miss the custom-provider path
where capability lookup returns undefined. Add a dedicated test around
Agent.generate and/or Agent.stream that uses a custom provider/model id and
verifies modelSettings like temperature, topP, and topK are preserved in the
spyGenerate/spyStream payload when the capability registry has no entry. Keep
the focus on the router behavior in the Agent flow and the
createOpenAICompatible/mock model setup so the pass-through case is locked down.
packages/core/src/llm/model/provider-registry.test.ts (1)

44-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover nested-model fallback in the new temperature suite.

modelSupportsTemperature() now rides on the generic capability lookup, but this suite only exercises exact model IDs. Add one variant/dated model ID that should resolve through the base temperature capability entry so regressions in the fallback path are caught here too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/llm/model/provider-registry.test.ts` around lines 44 - 64,
The new temperature tests for modelSupportsTemperature() only cover exact IDs,
so they miss the nested-model fallback path in the generic capability lookup.
Add a case in provider-registry.test.ts using a variant or dated model ID that
should resolve through the base temperature capability entry, and assert
modelSupportsTemperature() returns true to protect the fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/twelve-candles-love.md:
- Line 5: Add a brief public-facing usage example for the new `@mastra/core`
sampling-parameter stripping behavior, and rewrite the changelog entry to
emphasize the developer outcome rather than models.dev or registry internals. In
the changeset entry, reference the user-visible behavior of unsupported
temperature/topP/topK being removed automatically before dispatch, and keep the
example and description centered on how consumers benefit from the feature.

In `@packages/core/scripts/generate-providers.ts`:
- Around line 20-39: Update writeRegistryFiles so capability file generation is
triggered when either attachmentCapabilities or temperatureCapabilities has
entries, not only when attachmentCapabilities is non-empty. Use the existing
writeRegistryFiles flow in generate-providers.ts and the capability output logic
that writes under capabilities/ to ensure temperature-only runs still emit the
registry files consumed by modelSupportsTemperature().

In `@packages/core/src/llm/model/gateways/models-dev.ts`:
- Line 114: The capability maps are accumulating stale entries because
fetchProviders() rebuilds providerConfigs but does not reset
temperatureCapabilities or attachmentCapabilities before repopulating them.
Update the logic in fetchProviders(), getTemperatureCapabilities(), and
fetchProvidersFromGateways() so both maps are cleared/reset alongside
providerConfigs before new data is loaded, ensuring removed providers/models or
capability changes are not retained across syncs.

In `@packages/core/src/llm/model/provider-registry.ts`:
- Around line 436-446: The capability-file contract is out of sync with what
writeRegistryFiles() emits because ProviderCapabilityFile still requires
attachment even when only temperature is written. Update ProviderCapabilityFile
in provider-registry.ts so attachment is optional and the
parser/loadProviderCapabilityFile path can represent temperature-only files
without relying on a cast. Keep CapabilityDimension and providerCapCaches
aligned with the revised schema so the writer and reader use the same contract.

In `@packages/core/src/llm/model/registry-generator.ts`:
- Line 257: The write path in writeRegistryFiles() is still controlled only by
attachment capability data, so temperature-only inputs never trigger
regeneration of the capabilities/ directory and stale registry files can remain.
Update the gating logic around writeRegistryFiles() and the capability file
generation path so temperatureCapabilities alone is enough to write/refresh the
temperature registry entries, and ensure any removal/cleanup logic also runs
when only temperature support changes. Use the existing writeRegistryFiles() and
modelSupportsTemperature() flow to locate the affected branch.

---

Nitpick comments:
In `@packages/core/src/llm/model/provider-registry.test.ts`:
- Around line 44-64: The new temperature tests for modelSupportsTemperature()
only cover exact IDs, so they miss the nested-model fallback path in the generic
capability lookup. Add a case in provider-registry.test.ts using a variant or
dated model ID that should resolve through the base temperature capability
entry, and assert modelSupportsTemperature() returns true to protect the
fallback behavior.

In `@packages/core/src/llm/model/router-custom-provider.test.ts`:
- Around line 214-301: The new temperature-stripping tests in
router-custom-provider.test.ts only cover registry-backed OpenAI IDs, but they
miss the custom-provider path where capability lookup returns undefined. Add a
dedicated test around Agent.generate and/or Agent.stream that uses a custom
provider/model id and verifies modelSettings like temperature, topP, and topK
are preserved in the spyGenerate/spyStream payload when the capability registry
has no entry. Keep the focus on the router behavior in the Agent flow and the
createOpenAICompatible/mock model setup so the pass-through case is locked down.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f9a5958c-85b6-40f4-abf2-9164128574c3

📥 Commits

Reviewing files that changed from the base of the PR and between 848faa0 and 7d67858.

📒 Files selected for processing (13)
  • .changeset/twelve-candles-love.md
  • packages/core/scripts/generate-providers.ts
  • packages/core/src/llm/index.ts
  • packages/core/src/llm/model/capabilities/anthropic.json
  • packages/core/src/llm/model/capabilities/openai.json
  • packages/core/src/llm/model/gateways/base.ts
  • packages/core/src/llm/model/gateways/models-dev.ts
  • packages/core/src/llm/model/index.ts
  • packages/core/src/llm/model/provider-registry.test.ts
  • packages/core/src/llm/model/provider-registry.ts
  • packages/core/src/llm/model/registry-generator.ts
  • packages/core/src/llm/model/router-custom-provider.test.ts
  • packages/core/src/llm/model/router.ts

Comment thread .changeset/twelve-candles-love.md Outdated
Comment thread packages/core/scripts/generate-providers.ts
Comment thread packages/core/src/llm/model/gateways/models-dev.ts
Comment thread packages/core/src/llm/model/provider-registry.ts
Comment thread packages/core/src/llm/model/registry-generator.ts
@intojhanurag intojhanurag force-pushed the feat/temperature-capability-registry branch 2 times, most recently from 1bfa6f4 to 3bc544f Compare June 29, 2026 14:13
…gistry

Some models (claude-opus-4-7, gpt-5-pro) reject temperature/topP/topK
with a 400. The model router now checks the capability registry before
dispatching and silently strips unsupported sampling parameters.

Extends the existing attachment-only capability system to a generic
multi-dimension registry. The temperature dimension is populated from
models.dev data and auto-updated by the CI regeneration workflow.

Closes mastra-ai#16247
@intojhanurag intojhanurag force-pushed the feat/temperature-capability-registry branch from 3bc544f to 236c487 Compare June 29, 2026 14:26
@intojhanurag intojhanurag marked this pull request as ready for review June 29, 2026 14:29
@intojhanurag intojhanurag marked this pull request as draft June 29, 2026 14:29
@intojhanurag

Copy link
Copy Markdown
Contributor Author

Known limitations (out of scope for this PR)

Custom proxy aliases: If a user configures a custom model alias like my-company/fast-claude in LiteLLM that internally routes to claude-opus-4-7, the capability registry won't match it — temperature passes through. Workaround: use the real model ID instead of an alias.

Value-conditional rules: Some models reject temperature only under specific conditions (e.g., GPT-5 rejects temperature != 1, gpt-5.1 only when reasoning_effort is set). This PR strips all sampling params or none — it can't express conditional rules. No user has reported hitting this yet.

Both could be addressed later by adding a user-facing capability override API (e.g., setModelCapabilities('my-alias', { temperature: false })), built on top of the same CapabilityDimension system this PR introduces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

complexity: medium Medium-complexity PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] claude-opus-4-7 deprecates temperature — agent.stream() returns 400, no framework-level handling (parity with PrefillErrorHandler)

1 participant