fix(provider): unify model capability resolution - #2041
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR centralizes model capability identity and request-policy resolution in the main process, propagates request-local capability snapshots through runtime generation, updates renderer controls, refreshes model metadata and registries, and adds identity, policy, wire, routing, and UI tests. ChangesModel capability identity and request policy
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Renderer
participant ModelClient
participant ProviderSettings
participant AiSdkProvider
participant AiSdkRuntime
Renderer->>ModelClient: request capability snapshot
ModelClient->>ProviderSettings: forward route override and reasoning
ProviderSettings->>AiSdkProvider: resolve capability identity
AiSdkProvider->>AiSdkRuntime: provide snapshot and runtime facts
AiSdkRuntime->>AiSdkProvider: serialize effective generation options
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 14
🧹 Nitpick comments (8)
src/main/provider/providers/aiSdkProvider.ts (1)
1281-1306: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract the duplicated embeddings/dimensions runtime-context builder.
runEmbeddingsWithDecisionand the fallback path inrunDimensionsWithDecisionnow construct byte-identicalAiSdkRuntimeContextobjects (identity resolution, headers, snapshot, trace/header callbacks). A single private helper (e.g.buildEmbeddingRuntimeContext(modelId, decision)) would keep the capability-snapshot wiring in one place as this evolves.Also applies to: 1367-1392
🤖 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 `@src/main/provider/providers/aiSdkProvider.ts` around lines 1281 - 1306, Extract the duplicated AiSdkRuntimeContext construction from runEmbeddingsWithDecision and the fallback path in runDimensionsWithDecision into one private helper, such as buildEmbeddingRuntimeContext(modelId, decision). Move identity resolution, headers, capability snapshot, trace/header callbacks, and related runtime flags into the helper, then reuse it from both call sites while preserving their existing behavior.src/main/agent/deepchat/runtime/compactionRuntimeCoordinator.ts (1)
155-181: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winReuse
providerModelFactsfor the input-capability lookup too.
compact()now resolves facts once, but the laterresolveProviderInputCapabilities(this.deps.providerSettings, state.providerId, state.modelId)call in this method omits them, so it re-runsgetModelConfig+getCapabilitySnapshot.turnCoordinatoranddeepChatLoopRunnerpass the facts through; matching that here keeps the "resolve once per turn" invariant and avoids a snapshot recomputation that could disagree with the one used above.♻️ Pass the resolved facts through
const { supportsVision, supportsAudioInput } = resolveProviderInputCapabilities( this.deps.providerSettings, state.providerId, - state.modelId + state.modelId, + providerModelFacts )🤖 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 `@src/main/agent/deepchat/runtime/compactionRuntimeCoordinator.ts` around lines 155 - 181, Update compact() to pass the already resolved providerModelFacts into its later resolveProviderInputCapabilities call. Preserve the existing capability lookup behavior while avoiding a second getModelConfig/getCapabilitySnapshot resolution and maintaining the resolve-once-per-turn invariant used by turnCoordinator and deepChatLoopRunner.src/renderer/src/components/chat/ChatStatusBar.vue (1)
1948-1952: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
topPdefaults ignore a fixed request policy whiletemperaturehonors it.Temperature prefers
temperaturePolicy.valuewhen fixed, buttopPstill resolves purely frommodelConfig.topP. When the capability snapshot fixestopP, the stored session default diverges from the value shown in the UI (topPInputValue) and from what is sent on the wire. Consider mirroring the temperature branch.♻️ Suggested symmetry
- topP: normalizeTopP(modelConfig.topP), + topP: + capabilities?.requestPolicy.topP?.mode === 'fixed' + ? capabilities.requestPolicy.topP.value + : normalizeTopP(modelConfig.topP),🤖 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 `@src/renderer/src/components/chat/ChatStatusBar.vue` around lines 1948 - 1952, Update the topP assignment in the ChatStatusBar configuration flow to honor the fixed topP request policy before falling back to modelConfig.topP, mirroring the temperature policy precedence. Reuse the existing topP policy mode/value symbols and normalize the selected value consistently with the current topP handling.src/renderer/src/components/settings/ModelConfigDialog.vue (1)
991-1003: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
queueCapabilityRefreshrefetches even when nothing changed.The
@blurhandler on the model ID input calls this on every blur, andmodelClient.getCapabilitiesbypasses its cache wheneveroptionsare passed, so each blur is an unconditional IPC round-trip plus abeginLoading()that blanks the snapshot and flips the controls into the loading skeleton. ThecurrentModelLookupIdwatcher at Line 1614 already guards withmodelCapabilities.identity.value?.requestModelId === nextModelId; consider the same short-circuit here (or only refresh on blur when the id actually changed).🤖 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 `@src/renderer/src/components/settings/ModelConfigDialog.vue` around lines 991 - 1003, Update queueCapabilityRefresh to return early when modelCapabilities.identity.value?.requestModelId already matches the current model lookup ID, reusing the same identity comparison as the currentModelLookupId watcher. Keep the existing open and loading guards, and only call beginLoading and fetchCapabilities when the model ID has changed.test/renderer/composables/useChatConfigFields.test.ts (1)
51-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert that fixed controls cannot persist updates.
This test verifies the disabled presentation but not the new
setValueguard. Invoketemperature?.setValue(...)and assert that the emit spy was not called, so future slider changes cannot overwrite a policy-fixed value.🤖 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 `@test/renderer/composables/useChatConfigFields.test.ts` around lines 51 - 60, Extend the fixed-mode test around createFields and the temperature field to invoke temperature?.setValue(...) with a different value, then assert the emit spy was not called. Keep the existing disabled, hint, and getValue assertions, and verify the setValue guard prevents policy-fixed controls from persisting updates.test/main/provider/aiSdkRuntime.test.ts (1)
2135-2150: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSnapshot is internally inconsistent: effort-mode portrait with
supportsReasoningEffort: false.The helper defaults
supportsReasoningEfforttofalse, but this override supplies aneffort-modereasoningPortrait. Real snapshots derive that flag from the portrait (seebuildResolvedCapabilitySnapshot), so this fixture can't occur in production and may mask a regression in effort handling. AddsupportsReasoningEffort: true, reasoningEffortDefault: 'max'as in the non-streaming counterpart at Line 2072.🤖 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 `@test/main/provider/aiSdkRuntime.test.ts` around lines 2135 - 2150, Update the capability snapshot fixture for the effort-mode reasoningPortrait to explicitly set supportsReasoningEffort: true and reasoningEffortDefault: 'max', matching the non-streaming counterpart and keeping the snapshot internally consistent.test/renderer/composables/useModelCapabilities.test.ts (1)
121-136: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueNit:
temperatureCapability: nullis likely not a producible value.
buildResolvedCapabilitySnapshotsetstemperatureCapabilityfrom the catalog, where "unknown" isundefined, notnull. TheRecord<string, unknown>overrides parameter hides the mismatch. Usingundefinedkeeps these fixtures faithful.Also applies to: 153-182
🤖 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 `@test/renderer/composables/useModelCapabilities.test.ts` around lines 121 - 136, Update the capability fixtures in the tests around the successful unknown-temperature case and the additionally referenced cases to use temperatureCapability: undefined instead of null, matching the catalog value produced by buildResolvedCapabilitySnapshot. Remove any type override or fixture typing that masks this mismatch while preserving the existing assertions and test behavior.src/main/provider/settings.ts (1)
601-688: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winEach capability getter re-resolves a full snapshot; consider memoizing.
getCapabilityProviderId,supportsReasoningCapability,getReasoningPortrait,getThinkingBudgetRange,supportsSearchCapability,getTemperatureCapability,supportsTemperatureControl,getSearchDefaults,supportsAudioInputCapability,supportsReasoningEffortCapability,getReasoningEffortDefault,supportsVerbosityCapability,getVerbosityDefaulteach callgetCapabilitySnapshot, which runsgetModelRouteConfig+getProviderModelRouteMetadata(store/DB read) +resolveCapabilityIdentity(catalog scans). Previously these were directmodelCapabilities.*lookups. Any caller touching several getters for the same(providerId, modelId)now pays that resolution repeatedly.The runtime paths were updated to thread a single snapshot, but these port methods stay on hot paths (e.g.
getDbProviderModelsat Line 1200 callssupportsReasoningCapabilityper model). A small keyed memo invalidated alongsideinvalidateProviderModelsCache/setModelConfigwould remove the fan-out.🤖 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 `@src/main/provider/settings.ts` around lines 601 - 688, Memoize capability snapshots keyed by the `(providerId, modelId)` pair so the listed capability getters reuse one result instead of repeatedly calling `getCapabilitySnapshot`. Add a small cache around `getCapabilitySnapshot` or the shared getter path, and clear it wherever `invalidateProviderModelsCache` and `setModelConfig` invalidate model configuration, preserving refreshed results after configuration changes.
🤖 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 `@resources/model-db/providers.json`:
- Around line 269258-269286: Add the missing cost block to the claude-opus-5
provider record, mirroring the full pricing values from the equivalent
anthropic/claude-opus-5 entry. Keep the existing capabilities and model metadata
unchanged so cost estimation uses the published rates.
- Around line 242069-242072: Update the limit.output values for the newly added
model entries in providers.json, rather than mirroring limit.context. Set each
model’s output limit to its concrete provider API max_output_tokens or
generation limit, including qwen3.5-122b-a10b, qwen3-coder-next,
gemini-3-flash-preview, claude-opus-4-6, doubao-seed-2-0-* variants, and
cc-glm-5.1.
- Around line 242492-242586: Update the reasoning defaults in the gpt-5.4-high
and gpt-5.4-low entries so each tier explicitly uses its corresponding default
effort/path: high for gpt-5.4-high and low for gpt-5.4-low. Preserve their
shared limits, costs, supported options, and other configuration.
In `@src/main/provider/aiSdk/providerOptionsMapper.ts`:
- Around line 264-275: Update the DashScope reasoning block in the provider
options mapping so `reasoningEnabled` with a supported reasoning portrait still
sets `config.enable_thinking`, while an explicit `modelConfig.thinkingBudget`
can set `config.thinking_budget` even when `reasoningPortrait` is unresolved.
Keep portrait-based default budget resolution conditional on the portrait being
available.
In `@src/main/provider/aiSdk/runtime.ts`:
- Around line 795-821: Update resolveEffectiveGenerationRequest so an undefined
requestedTemperature falls back to modelConfig.temperature before applying
requestPolicy.temperature. Preserve explicit caller-provided temperatures and
ensure the resolved value is still used to populate samplingOptions.
In `@src/main/provider/capabilityIdentity.ts`:
- Around line 111-162: Update getOwnerProviderIds so the xAI provider check also
matches the normalized “x ai” owner form alongside “xai” and “grok”, allowing
hyphen-normalized x-ai values to resolve to the xai provider.
In `@src/main/provider/providerModelHelper.ts`:
- Around line 282-285: Update the non-`new-api` branch of the `type` resolution
in `getProviderModelRouteMetadata` to use model-first precedence, matching
`applyResolvedModelConfig`: prefer the stored model’s defined type and fall back
to `config.type` only when it is absent. Keep the existing `new-api` resolution
through `resolveNewApiEffectiveModelType` unchanged.
In `@src/main/provider/routes.ts`:
- Around line 650-665: Align the capabilities response in the handler using
modelsGetCapabilitiesRoute with ModelCapabilitiesSchema: omit the snapshot’s
internal identity and requestPolicy fields before parsing, unless those fields
are intentionally part of the public contract, in which case explicitly add them
to the response schema. Preserve the existing temperatureCapability null
fallback.
In `@src/renderer/src/components/settings/ModelConfigDialog.vue`:
- Around line 1614-1629: The currentModelLookupId watcher calls
modelCapabilities.beginLoading() without guaranteeing a subsequent capability
fetch, leaving the dialog stuck loading when no blur occurs. Update this watcher
to queue or trigger the composable’s refresh/load operation after the model ID
changes, while preserving clear() for an empty ID and the existing early-return
conditions.
In `@src/shared/modelId.ts`:
- Around line 14-20: Update getDottedProviderUnqualifiedModelId so it does not
identify the model segment using the first hyphenated segment, which incorrectly
preserves hyphenated provider prefixes such as meta-llama. Use the established
known-provider prefix list or a reliable model-ID token heuristic to strip
provider prefixes while preserving the model identifier for both hyphenated and
non-hyphenated providers.
In `@test/main/provider/aiSdkReasoningWire.test.ts`:
- Around line 15-27: The captureRequestBody helper’s exact single-call assertion
is nondeterministic because retryable failures may invoke fetch multiple times.
Replace fetchMock’s toHaveBeenCalledTimes(1) assertion with a nonzero-call
assertion while continuing to inspect mock.calls[0], or configure the relevant
wire-test generateText path to use maxRetries: 0 where supported.
In `@test/renderer/components/ModelConfigDialog.test.ts`:
- Around line 62-73: Update createCapabilityResult in
test/renderer/components/ModelConfigDialog.test.ts (lines 62-73) and the
getCapabilities mock in test/renderer/components/ChatStatusBar.test.ts (lines
481-516) to distinguish an omitted temperatureCapability from one explicitly set
to undefined: use a property-presence check for both supportsTemperatureControl
and temperatureCapability, defaulting to true only when the property is absent.
In `@test/renderer/composables/useModelCapabilities.test.ts`:
- Around line 138-151: Align the fixture in the test around useModelCapabilities
with the main-process contract by using temperatureCapability: false together
with a served temperature policy of mode "omit", and assert the resolved
temperature state is hidden. Update the test description to reflect that it
verifies capability-derived omission rather than passthrough-policy handling.
In `@test/setup.renderer.ts`:
- Around line 14-38: Update createDefaultReasoningCapabilities to match the
catalog expectations for its default OpenAI gpt-5.4 identity: mark it
catalog-matched, populate catalogModelId with the resolved model ID, set
supportsSearch to true, and provide the corresponding searchDefaults. Preserve
the existing behavior for other capability fields and explicitly verify whether
non-default provider/model inputs should retain their current fallback values.
---
Nitpick comments:
In `@src/main/agent/deepchat/runtime/compactionRuntimeCoordinator.ts`:
- Around line 155-181: Update compact() to pass the already resolved
providerModelFacts into its later resolveProviderInputCapabilities call.
Preserve the existing capability lookup behavior while avoiding a second
getModelConfig/getCapabilitySnapshot resolution and maintaining the
resolve-once-per-turn invariant used by turnCoordinator and deepChatLoopRunner.
In `@src/main/provider/providers/aiSdkProvider.ts`:
- Around line 1281-1306: Extract the duplicated AiSdkRuntimeContext construction
from runEmbeddingsWithDecision and the fallback path in
runDimensionsWithDecision into one private helper, such as
buildEmbeddingRuntimeContext(modelId, decision). Move identity resolution,
headers, capability snapshot, trace/header callbacks, and related runtime flags
into the helper, then reuse it from both call sites while preserving their
existing behavior.
In `@src/main/provider/settings.ts`:
- Around line 601-688: Memoize capability snapshots keyed by the `(providerId,
modelId)` pair so the listed capability getters reuse one result instead of
repeatedly calling `getCapabilitySnapshot`. Add a small cache around
`getCapabilitySnapshot` or the shared getter path, and clear it wherever
`invalidateProviderModelsCache` and `setModelConfig` invalidate model
configuration, preserving refreshed results after configuration changes.
In `@src/renderer/src/components/chat/ChatStatusBar.vue`:
- Around line 1948-1952: Update the topP assignment in the ChatStatusBar
configuration flow to honor the fixed topP request policy before falling back to
modelConfig.topP, mirroring the temperature policy precedence. Reuse the
existing topP policy mode/value symbols and normalize the selected value
consistently with the current topP handling.
In `@src/renderer/src/components/settings/ModelConfigDialog.vue`:
- Around line 991-1003: Update queueCapabilityRefresh to return early when
modelCapabilities.identity.value?.requestModelId already matches the current
model lookup ID, reusing the same identity comparison as the
currentModelLookupId watcher. Keep the existing open and loading guards, and
only call beginLoading and fetchCapabilities when the model ID has changed.
In `@test/main/provider/aiSdkRuntime.test.ts`:
- Around line 2135-2150: Update the capability snapshot fixture for the
effort-mode reasoningPortrait to explicitly set supportsReasoningEffort: true
and reasoningEffortDefault: 'max', matching the non-streaming counterpart and
keeping the snapshot internally consistent.
In `@test/renderer/composables/useChatConfigFields.test.ts`:
- Around line 51-60: Extend the fixed-mode test around createFields and the
temperature field to invoke temperature?.setValue(...) with a different value,
then assert the emit spy was not called. Keep the existing disabled, hint, and
getValue assertions, and verify the setValue guard prevents policy-fixed
controls from persisting updates.
In `@test/renderer/composables/useModelCapabilities.test.ts`:
- Around line 121-136: Update the capability fixtures in the tests around the
successful unknown-temperature case and the additionally referenced cases to use
temperatureCapability: undefined instead of null, matching the catalog value
produced by buildResolvedCapabilitySnapshot. Remove any type override or fixture
typing that masks this mismatch while preserving the existing assertions and
test behavior.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 52c3c6c9-7ba1-4b87-a2a3-60e466945ff5
📒 Files selected for processing (115)
docs/architecture/model-capability-identity/plan.mddocs/architecture/model-capability-identity/spec.mddocs/architecture/model-capability-identity/tasks.mddocs/features/provider-runtime/spec.mdresources/acp-registry/registry.jsonresources/model-db/providers.jsonsrc/main/agent/deepchat/runtime/compactionRuntimeCoordinator.tssrc/main/agent/deepchat/runtime/deepChatLoopRunner.tssrc/main/agent/deepchat/runtime/generationSettings.tssrc/main/agent/deepchat/runtime/providerInputCapabilities.tssrc/main/agent/deepchat/runtime/providerModelRuntimeFacts.tssrc/main/agent/deepchat/runtime/sessionSettingsCoordinator.tssrc/main/agent/deepchat/runtime/turnCoordinator.tssrc/main/provider/aiSdk/providerOptionsMapper.tssrc/main/provider/aiSdk/runtime.tssrc/main/provider/baseProvider.tssrc/main/provider/capabilityIdentity.tssrc/main/provider/data/settingsTable.tssrc/main/provider/modelCapabilities.tssrc/main/provider/modelConfig.tssrc/main/provider/providerModelHelper.tssrc/main/provider/providers/aiSdkProvider.tssrc/main/provider/providers/ollamaProvider.tssrc/main/provider/routes.tssrc/main/provider/settings.tssrc/main/provider/settingsDbStores.tssrc/renderer/api/ModelClient.tssrc/renderer/src/components/ChatConfig.vuesrc/renderer/src/components/ChatConfig/ConfigSliderField.vuesrc/renderer/src/components/ChatConfig/types.tssrc/renderer/src/components/GenerationParameterLoadingSkeleton.vuesrc/renderer/src/components/chat/ChatStatusBar.vuesrc/renderer/src/components/settings/ModelConfigDialog.vuesrc/renderer/src/composables/useChatConfigFields.tssrc/renderer/src/composables/useModelCapabilities.tssrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/de-DE/chat.jsonsrc/renderer/src/i18n/de-DE/settings.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/es-ES/chat.jsonsrc/renderer/src/i18n/es-ES/settings.jsonsrc/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/chat.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/id-ID/chat.jsonsrc/renderer/src/i18n/id-ID/settings.jsonsrc/renderer/src/i18n/it-IT/chat.jsonsrc/renderer/src/i18n/it-IT/settings.jsonsrc/renderer/src/i18n/ja-JP/chat.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ms-MY/chat.jsonsrc/renderer/src/i18n/ms-MY/settings.jsonsrc/renderer/src/i18n/pl-PL/chat.jsonsrc/renderer/src/i18n/pl-PL/settings.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/tr-TR/chat.jsonsrc/renderer/src/i18n/tr-TR/settings.jsonsrc/renderer/src/i18n/vi-VN/chat.jsonsrc/renderer/src/i18n/vi-VN/settings.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/shared/contracts/domainSchemas.tssrc/shared/contracts/routes/models.routes.tssrc/shared/model.tssrc/shared/modelId.tssrc/shared/modelRequestPolicy.tssrc/shared/moonshotKimiPolicy.tssrc/shared/types/model-capabilities.tssrc/shared/types/provider.tssrc/types/i18n.d.tstest/main/agent/deepchat/harness/deepChatAgentHarness.test.tstest/main/agent/deepchat/runtime/compactionRuntimeCoordinator.test.tstest/main/agent/deepchat/runtime/generationSettings.test.tstest/main/agent/deepchat/runtime/providerInputCapabilities.test.tstest/main/agent/deepchat/runtime/sessionSettingsCoordinator.test.tstest/main/provider/aiSdkProviderOptionsMapper.test.tstest/main/provider/aiSdkReasoningWire.test.tstest/main/provider/aiSdkRuntime.test.tstest/main/provider/basicApiKeyProviders.test.tstest/main/provider/capabilityIdentity.test.tstest/main/provider/data/settingsTable.test.tstest/main/provider/data/settingsTableQuery.test.tstest/main/provider/modelCapabilities.test.tstest/main/provider/modelConfig.test.tstest/main/provider/newApiProvider.test.tstest/main/provider/ollamaProvider.test.tstest/main/provider/providerDbModelConfig.test.tstest/main/provider/providerModelCapabilityMapping.test.tstest/main/provider/providerModelHelper.test.tstest/main/provider/routes.test.tstest/main/routes/contracts.test.tstest/main/session/runtimeIntegration.test.tstest/main/shared/model.test.tstest/main/shared/modelRequestPolicy.test.tstest/main/shared/moonshotKimiPolicy.test.tstest/renderer/components/ChatConfig.test.tstest/renderer/components/ChatStatusBar.test.tstest/renderer/components/ModelConfigDialog.test.tstest/renderer/composables/useChatConfigFields.test.tstest/renderer/composables/useModelCapabilities.test.tstest/setup.renderer.ts
💤 Files with no reviewable changes (25)
- src/renderer/src/i18n/zh-TW/chat.json
- src/renderer/src/i18n/ru-RU/chat.json
- test/main/shared/moonshotKimiPolicy.test.ts
- src/renderer/src/i18n/zh-CN/chat.json
- src/renderer/src/i18n/ja-JP/chat.json
- src/renderer/src/i18n/da-DK/chat.json
- src/renderer/src/i18n/es-ES/chat.json
- src/renderer/src/i18n/tr-TR/chat.json
- src/renderer/src/i18n/fa-IR/chat.json
- src/renderer/src/i18n/vi-VN/chat.json
- src/renderer/src/i18n/id-ID/chat.json
- src/renderer/src/i18n/fr-FR/chat.json
- src/renderer/src/i18n/pl-PL/chat.json
- src/shared/moonshotKimiPolicy.ts
- src/renderer/src/i18n/he-IL/chat.json
- src/renderer/src/i18n/de-DE/chat.json
- src/renderer/src/i18n/ms-MY/chat.json
- src/renderer/src/i18n/it-IT/chat.json
- src/renderer/src/i18n/en-US/chat.json
- src/renderer/src/i18n/pt-BR/chat.json
- src/types/i18n.d.ts
- src/renderer/src/i18n/zh-HK/chat.json
- test/main/shared/model.test.ts
- src/renderer/src/i18n/ko-KR/chat.json
- src/main/provider/baseProvider.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@resources/model-db/providers.json`:
- Around line 52897-52928: Update the gpt-4o-mini-transcribe model entry’s
limit.output value from 16000 to 2000, while preserving its context limit and
all other metadata.
- Around line 58986-59017: Update both gpt-4o-transcribe entries in the model
provider definitions so their limit.output value is 2000 instead of 16000, while
preserving the 16000 context limit and all other model metadata.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 6fdb4694-d3ee-4241-a7e4-20d1410ca6f3
📒 Files selected for processing (27)
docs/architecture/model-capability-identity/plan.mddocs/architecture/model-capability-identity/spec.mddocs/architecture/model-capability-identity/tasks.mdresources/acp-registry/registry.jsonresources/model-db/providers.jsonsrc/main/agent/deepchat/runtime/compactionRuntimeCoordinator.tssrc/main/provider/aiSdk/providerOptionsMapper.tssrc/main/provider/capabilityIdentity.tssrc/main/provider/modelConfig.tssrc/main/provider/providerModelHelper.tssrc/main/provider/providers/aiSdkProvider.tssrc/renderer/src/components/chat/ChatStatusBar.vuesrc/renderer/src/components/settings/ModelConfigDialog.vuesrc/shared/modelId.tssrc/shared/types/provider.tstest/main/agent/deepchat/runtime/compactionRuntimeCoordinator.test.tstest/main/provider/aiSdkProviderOptionsMapper.test.tstest/main/provider/aiSdkReasoningWire.test.tstest/main/provider/aiSdkRuntime.test.tstest/main/provider/capabilityIdentity.test.tstest/main/provider/providerDbModelConfig.test.tstest/main/provider/providerModelHelper.test.tstest/main/shared/modelId.test.tstest/renderer/components/ChatStatusBar.test.tstest/renderer/components/ModelConfigDialog.test.tstest/renderer/composables/useChatConfigFields.test.tstest/renderer/composables/useModelCapabilities.test.ts
🚧 Files skipped from review as they are similar to previous changes (21)
- src/shared/types/provider.ts
- src/main/agent/deepchat/runtime/compactionRuntimeCoordinator.ts
- src/shared/modelId.ts
- test/main/provider/providerDbModelConfig.test.ts
- test/main/provider/aiSdkReasoningWire.test.ts
- docs/architecture/model-capability-identity/spec.md
- test/main/agent/deepchat/runtime/compactionRuntimeCoordinator.test.ts
- test/renderer/composables/useChatConfigFields.test.ts
- src/main/provider/capabilityIdentity.ts
- src/main/provider/aiSdk/providerOptionsMapper.ts
- docs/architecture/model-capability-identity/tasks.md
- src/main/provider/providerModelHelper.ts
- test/renderer/components/ChatStatusBar.test.ts
- test/main/provider/aiSdkRuntime.test.ts
- src/renderer/src/components/chat/ChatStatusBar.vue
- test/renderer/components/ModelConfigDialog.test.ts
- docs/architecture/model-capability-identity/plan.md
- test/main/provider/capabilityIdentity.test.ts
- test/renderer/composables/useModelCapabilities.test.ts
- src/renderer/src/components/settings/ModelConfigDialog.vue
- src/main/provider/providers/aiSdkProvider.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@resources/model-db/providers.json`:
- Around line 268502-268525: Update the type classification for the
qwen/qwen3.7-flash entry from imageGeneration to chat, preserving its existing
text/image/video input and text output modalities.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4526df06-abb1-4982-8153-561768055d7d
📒 Files selected for processing (45)
resources/model-db/providers.jsonsrc/main/agent/deepchat/runtime/turnCoordinator.tssrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/de-DE/chat.jsonsrc/renderer/src/i18n/de-DE/settings.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/es-ES/chat.jsonsrc/renderer/src/i18n/es-ES/settings.jsonsrc/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/chat.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/id-ID/chat.jsonsrc/renderer/src/i18n/id-ID/settings.jsonsrc/renderer/src/i18n/it-IT/chat.jsonsrc/renderer/src/i18n/it-IT/settings.jsonsrc/renderer/src/i18n/ja-JP/chat.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ms-MY/chat.jsonsrc/renderer/src/i18n/ms-MY/settings.jsonsrc/renderer/src/i18n/pl-PL/chat.jsonsrc/renderer/src/i18n/pl-PL/settings.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/tr-TR/chat.jsonsrc/renderer/src/i18n/tr-TR/settings.jsonsrc/renderer/src/i18n/vi-VN/chat.jsonsrc/renderer/src/i18n/vi-VN/settings.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/shared/contracts/domainSchemas.tssrc/types/i18n.d.tstest/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
💤 Files with no reviewable changes (21)
- src/renderer/src/i18n/de-DE/chat.json
- src/renderer/src/i18n/da-DK/chat.json
- src/renderer/src/i18n/en-US/chat.json
- src/renderer/src/i18n/he-IL/chat.json
- src/renderer/src/i18n/pl-PL/chat.json
- src/renderer/src/i18n/vi-VN/chat.json
- src/renderer/src/i18n/tr-TR/chat.json
- src/renderer/src/i18n/ms-MY/chat.json
- src/renderer/src/i18n/zh-CN/chat.json
- src/renderer/src/i18n/zh-HK/chat.json
- src/types/i18n.d.ts
- src/renderer/src/i18n/it-IT/chat.json
- src/renderer/src/i18n/es-ES/chat.json
- src/renderer/src/i18n/fr-FR/chat.json
- src/renderer/src/i18n/pt-BR/chat.json
- src/renderer/src/i18n/fa-IR/chat.json
- src/renderer/src/i18n/id-ID/chat.json
- src/renderer/src/i18n/ru-RU/chat.json
- src/renderer/src/i18n/zh-TW/chat.json
- src/renderer/src/i18n/ja-JP/chat.json
- src/renderer/src/i18n/ko-KR/chat.json
🚧 Files skipped from review as they are similar to previous changes (22)
- src/renderer/src/i18n/pt-BR/settings.json
- src/renderer/src/i18n/es-ES/settings.json
- src/renderer/src/i18n/zh-CN/settings.json
- src/renderer/src/i18n/tr-TR/settings.json
- src/renderer/src/i18n/ru-RU/settings.json
- src/renderer/src/i18n/pl-PL/settings.json
- src/renderer/src/i18n/it-IT/settings.json
- src/renderer/src/i18n/ja-JP/settings.json
- src/renderer/src/i18n/da-DK/settings.json
- src/shared/contracts/domainSchemas.ts
- src/renderer/src/i18n/he-IL/settings.json
- src/renderer/src/i18n/id-ID/settings.json
- src/renderer/src/i18n/fr-FR/settings.json
- src/renderer/src/i18n/zh-TW/settings.json
- src/renderer/src/i18n/ms-MY/settings.json
- src/renderer/src/i18n/ko-KR/settings.json
- src/renderer/src/i18n/fa-IR/settings.json
- src/renderer/src/i18n/de-DE/settings.json
- test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
- src/main/agent/deepchat/runtime/turnCoordinator.ts
- src/renderer/src/i18n/zh-HK/settings.json
- src/renderer/src/i18n/en-US/settings.json
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/shared/imageGenerationSettings.ts`:
- Line 106: Update the providerOptionsKey condition in normalizeText to accept
both openai and newapi, preserving the canonical newApi fallback after
normalization. Ensure provider factory values emitted as newApi are classified
correctly.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c8bb710f-3148-42b8-8cf0-9cfefe07f5e2
📒 Files selected for processing (7)
src/main/provider/aiSdk/providerFactory.tssrc/shared/imageGenerationSettings.tssrc/shared/videoGenerationSettings.tstest/main/provider/aiSdkProviderFactory.test.tstest/main/provider/aiSdkProviderOptionsMapper.test.tstest/main/provider/aiSdkRuntime.test.tstest/main/provider/aiSdkStreamAdapter.test.ts
💤 Files with no reviewable changes (1)
- src/shared/videoGenerationSettings.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- test/main/provider/aiSdkRuntime.test.ts
Summary
Unify model capability resolution across provider routing, runtime serialization, settings, agent defaults, and renderer controls.
This fixes Kimi K3 requests through New API while establishing a single capability identity and request-policy contract for future models and aggregators.
Root cause
New API correctly routed
kimi-k3through an OpenAI-compatible endpoint, but runtime code later treated the transport as the capability owner and attempted to resolveopenai/kimi-k3.That lost Moonshot's provider-db metadata, converted unknown temperature support into an enabled default, and sent unsupported sampling parameters. Renderer components also resolved capabilities independently, allowing UI controls to disagree with the final HTTP request.
Changes
passthrough,fixed, andomitmodes.temperature;top_p;thinking.reasoning_effortthrough the standard AI SDK option.Summary by CodeRabbit