Skip to content

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Nov 21, 2025

Problem

When selecting a specific provider on OpenRouter (e.g., "Anthropic" for an Anthropic model), endpoint models were missing model-level capabilities like supportsNativeTools, causing the system to incorrectly fall back to XML protocol instead of using native tool calling.

Root Cause

  • The /models/{id}/endpoints API only returns provider-specific data (pricing, max_tokens)
  • It does NOT include supported_parameters, which is used to determine tool support
  • Tool support is model-level, not provider-level (e.g., claude-sonnet-4.5 supports tools regardless of whether you use Anthropic's endpoint or Bedrock's endpoint)

Solution

Copy model-level capabilities from the parent model to each endpoint in modelEndpointCache.ts:

const parentModels = await getModels({ provider: "openrouter" })
const parentModel = parentModels[modelId]

if (parentModel) {
    for (const endpointKey of Object.keys(modelProviders)) {
        modelProviders[endpointKey].supportsNativeTools = parentModel.supportsNativeTools
        modelProviders[endpointKey].supportsReasoningEffort = parentModel.supportsReasoningEffort
        modelProviders[endpointKey].supportedParameters = parentModel.supportedParameters
    }
}

Testing

Added test coverage in openrouter.spec.ts to verify capability copying.

Performance

✅ No extra API calls - uses existing cached model data (5-minute TTL)
✅ Works correctly on every message
✅ All tests passing (4159/4159)

Fixes the issue where Anthropic models on OpenRouter would fall back to XML tools instead of using native tool calling.


Important

Fixes missing model-level capabilities in endpoint models by copying them from parent models in modelEndpointCache.ts.

  • Behavior:
    • Copies model-level capabilities (supportsNativeTools, supportsReasoningEffort, supportedParameters) from parent models to endpoint models in getModelEndpoints() in modelEndpointCache.ts.
    • Ensures capabilities are copied for all endpoints, preventing fallback to XML protocol.
  • Testing:
    • Added tests in modelEndpointCache.spec.ts to verify capability copying and ensure independent array copies.
    • Updated openrouter.spec.ts to mock and verify endpoint capabilities.
  • Performance:
    • No additional API calls; uses cached model data.
    • All tests passing (4159/4159).

This description was created by Ellipsis for 24877ad. You can customize this summary. It will automatically update as commits are pushed.

When selecting a specific provider on OpenRouter (e.g., Anthropic), endpoint
models were missing model-level capabilities like supportsNativeTools, causing
incorrect fallback to XML protocol.

The endpoints API only returns provider-specific data (pricing, max_tokens) and
does not include supported_parameters. Tool support is model-level, not
provider-level, so we copy these capabilities from the parent model.

Changes:
- modelEndpointCache: Copy supportsNativeTools, supportsReasoningEffort, and
  supportedParameters from parent model to each endpoint
- Tests: Added test coverage for capability copying
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. bug Something isn't working labels Nov 21, 2025
@roomote
Copy link
Contributor

roomote bot commented Nov 21, 2025

Rooviewer Clock   See task on Roo Cloud

All previously flagged issues have been resolved.

  • Shared mutable array reference in supportedParameters assignment (line 70 in modelEndpointCache.ts)
  • Test coverage gap - tests simulate behavior instead of testing actual implementation
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

@hannesrudolph hannesrudolph added the Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. label Nov 21, 2025
@daniel-lxs daniel-lxs moved this from Triage to PR [Needs Review] in Roo Code Roadmap Nov 21, 2025
@hannesrudolph hannesrudolph added PR - Needs Review and removed Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. labels Nov 21, 2025
- Clone supportedParameters array to avoid shared mutable references
- Add comprehensive test coverage for modelEndpointCache capability copying
- Tests now verify the actual implementation instead of simulating behavior
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Nov 21, 2025
@hannesrudolph hannesrudolph merged commit f6d3fdf into main Nov 21, 2025
19 of 20 checks passed
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Nov 21, 2025
@github-project-automation github-project-automation bot moved this from PR [Needs Review] to Done in Roo Code Roadmap Nov 21, 2025
@hannesrudolph hannesrudolph deleted the fix/openrouter-anthropic-native-tools branch November 21, 2025 23:05
mini2s added a commit to zgsm-ai/costrict that referenced this pull request Nov 22, 2025
* Changeset version bump (RooCodeInc#9005)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Chris Estreich <[email protected]>

* config(rooignore): remove ignored directories from exclusion list

* fix: correct OpenRouter Mistral model dimension from 3072 to 1536 (RooCodeInc#9028)

* Revert "fix: prevent UI flicker and enable resumption after task cancellation" (RooCodeInc#9032)

* chore: add changeset for v3.30.1 (RooCodeInc#9033)

* Changeset version bump (RooCodeInc#9034)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Rubens <[email protected]>

* fix: eliminate UI flicker during task cancellation (RooCodeInc#9037)

* fix: eliminate UI flicker during task cancellation

- Modify ClineProvider.createTaskWithHistoryItem() to detect when rehydrating current task
- Implement in-place task replacement to avoid empty stack state that causes UI flicker
- Add comprehensive unit tests for flicker-free cancel behavior
- Maintain backward compatibility and proper event listener cleanup

Fixes the jarring navigation to home view when cancelling tasks

* fix: ensure proper garbage collection of old task during flicker-free rehydration

- Call abortTask(true) on old task before replacement to stop processes and mark as abandoned
- This ensures proper cleanup and prevents memory leaks during task cancellation
- Add test verification for abortTask cleanup

* feat: add file path tooltips with centralized PathTooltip component (RooCodeInc#9030)

- Add PathTooltip component that wraps StandardTooltip with proper styling
- Use maxWidth='min(300px,100vw)' via inline style to override defaults
- Apply '[text-wrap:wrap]' class to override text-balance behavior
- Add formatPathTooltip helper for consistent path content formatting
- Update CodeAccordian, ChatRow, and BatchFilePermission to use PathTooltip
- Centralizes tooltip behavior and reduces duplication

Supersedes PR RooCodeInc#8797.

* fix: keep pinned models fixed at top of scrollable list (RooCodeInc#8813)

* fix: keep pinned models fixed at top of scrollable list

- Separated pinned and unpinned configs into different containers
- Pinned configs now stay fixed at the top
- Only unpinned configs are scrollable
- Added tests to verify the fixed behavior

Fixes RooCodeInc#8812

* fix: resolve sticky header visual artifact in ApiConfigSelector

- Changed sticky header background from bg-vscode-editorWidget-background to bg-vscode-dropdown-background to match popover container
- Moved separator logic into sticky container as conditional bottom border to prevent scroll artifacts
- Updated tests to match new separator structure
- All 21 tests passing

---------

Co-authored-by: Roo Code <[email protected]>
Co-authored-by: daniel-lxs <[email protected]>

* Set Claude Sonnet 4.5 as default for key providers (RooCodeInc#8922)

* fix(checkpoints): resolve incorrect commit location when GIT_DIR set in Dev Containers (RooCodeInc#8811)

* Update cerebras.ts (RooCodeInc#9024)

* fix: update Opus 4.1 max tokens from 8K to 32K (RooCodeInc#9046)

Aligns claude-opus-4-1-20250805 max token limit with claude-opus-4-20250514,
both models now supporting 32K output tokens (overridable to 8K when
enableReasoningEffort is false).

Fixes RooCodeInc#9045

Co-authored-by: Roo Code <[email protected]>

* Merge remote-tracking branch 'upstream/main' into roo-to-main

* feat(api): add mode parameter to ZgsmAiHandler and add tooltips to ChatRow buttons

* chore: simplify Google Analytics to standard implementation (RooCodeInc#9044)

Co-authored-by: Roo Code <[email protected]>

* feat: add conditional test running to pre-push hook (RooCodeInc#9055)

* Fix dynamic provider model validation to prevent cross-contamination (RooCodeInc#9054)

* Fix Bedrock user agent to report full SDK details (RooCodeInc#9043)

* feat: add Qwen3 embedding models (0.6B and 4B) to OpenRouter support (RooCodeInc#9060)

Co-authored-by: Roo Code <[email protected]>

* web: Agent Landing Page A/B testing toolkit (RooCodeInc#9018)

Co-authored-by: Roo Code <[email protected]>

* feat: Global Inference for Bedrock models (RooCodeInc#8750) (RooCodeInc#8940)

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Co-authored-by: Roo Code <[email protected]>

* Release v3.30.2 (RooCodeInc#9065)

chore: add changeset for v3.30.2

* Changeset version bump (RooCodeInc#9066)

* changeset version bump

* Revise CHANGELOG for version 3.30.2

Updated changelog for version 3.30.2 with new features and fixes.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Rubens <[email protected]>

* Merge branch 'main' of github.com:zgsm-ai/costrict into roo-to-main

* feat(error-handling): add HTTP 413 payload too large error handling

* fix(webview): correct default value for useZgsmCustomConfig and fix settings message order

* feat: add kimi-k2-thinking model to moonshot provider (RooCodeInc#9079)

* ux: Home screen visuals (