Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@iscekic
Copy link
Collaborator

@iscekic iscekic commented Jan 20, 2026

Context

This PR adds the ability to set a Kilo Code gateway model override per mode (e.g. different models for code, architect, etc.).

The goal is to make mode-switching more powerful for users who want different performance/cost/behavior characteristics depending on what they’re doing, while keeping the default model behavior unchanged unless an override is explicitly set.

Implementation

  • Introduced a new persisted setting (modeModelOverrides) that stores a mapping of modeSlug -> modelId.
  • Added a per-mode model picker in the Modes UI that:
    • Is only enabled when the active provider is Kilo Code and the gateway model list is available.
    • Allows selecting a specific gateway model or choosing Use default (clears the override).
  • Wired a new webview message (setModeModelOverride) to:
    • Update modeModelOverrides in global state.
    • Immediately apply the selected model when the override is set for the currently active mode (so users don’t need to switch modes to see it take effect).
  • Updated mode switching behavior so that when the user switches modes, if an override exists for the target mode, the extension applies the overridden model to the active provider configuration.
  • Added a safety gate around application of overrides:
    • Overrides are only applied when the extension knows Kilo Code gateway models are available (tracked from router model fetch results), preventing setting a model that can’t be resolved when the gateway model list is unavailable.
  • Added/updated test coverage for:
    • Persisting overrides via webview messages.
    • Applying overrides on mode switch (and not applying when models are unavailable).
    • UI behavior: enabled/disabled states and correct postMessage payloads.

Screenshots

https://www.loom.com/share/c9e2a007b3aa491697d336fb814371c7

- persist per-mode model selections via new `modeModelOverrides` global setting
- add webview message to set/clear overrides and update extension state
- apply override on mode switch only when Kilo Code gateway models are available
- add Modes UI model selector backed by routerModels plus coverage updates
Extract per-mode Kilo Code model override UI into a dedicated component
with searchable combobox, provider-aware enable/disable behavior, and
updated tests for helper text and selection actions
When updating the override for the active mode, immediately update the
active Kilo Code model (only when gateway models are available) so users
don’t need to switch modes to see the change. Expose a provider getter
and add coverage for the new behavior.
@iscekic iscekic self-assigned this Jan 20, 2026
@changeset-bot
Copy link

changeset-bot bot commented Jan 20, 2026

🦋 Changeset detected

Latest commit: 53c1655

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

This PR includes changesets to release 1 package
Name Type
kilo-code Minor

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

Ensure per-mode Kilo Code model overrides take precedence when restoring
tasks from history, even if the activated provider profile specifies a
different model. Skip applying when gateway models are unavailable and
log failures to avoid breaking restore flow.
Ensure custom modes schema validation failures surface an error message for
all files, with fallbacks when i18n or VS Code APIs are unavailable, to
avoid silent failures and reduce test flakiness.

Update YAML edge case tests to use hoist-safe vscode mocks, mock i18n, and
dynamically import CustomModesManager for deterministic assertions.
Ensure Kilo Code per-mode overrides are only applied when the Kilo
Code provider is active and gateway models are available (with a
best-effort refresh to avoid stale availability state). Re-apply the
override when activating/switching provider profiles and validate the
setModeModelOverride payload via a shared Zod schema. Also localize the
mode model picker UI strings.
@iscekic iscekic marked this pull request as ready for review January 20, 2026 20:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements per-mode model overrides for Kilo Code gateway models, allowing users to configure different models for different modes (e.g., code, architect) while maintaining the default model behavior when no override is set.

Changes:

  • Added UI component and state management for selecting per-mode Kilo Code gateway models
  • Implemented persistence and application logic for mode-specific model overrides with safety gates
  • Added comprehensive test coverage for the new feature across UI and backend components

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
webview-ui/src/i18n/locales/*/kilocode.json Added translations for mode model picker UI in 20 locales
webview-ui/src/components/kilocode/KiloModeModelPicker.tsx New component for selecting per-mode Kilo Code gateway models
webview-ui/src/components/modes/ModesView.tsx Integrated KiloModeModelPicker into modes settings UI
webview-ui/src/components/modes/tests/ModesView.spec.tsx Added tests for mode model picker UI behavior
src/shared/WebviewMessage.ts Added setModeModelOverride message type and payload schema
src/shared/ExtensionMessage.ts Added modeModelOverrides to extension state
packages/types/src/global-settings.ts Added modeModelOverrides to global settings schema
src/core/webview/ClineProvider.ts Added gateway models availability tracking and model override application logic
src/core/webview/webviewMessageHandler.ts Implemented setModeModelOverride message handler with immediate application
src/core/webview/tests/ClineProvider.sticky-mode.spec.ts Added tests for mode override application during mode switch
src/tests/modeModelOverride-active-update.spec.ts New test file for active mode model override updates
src/core/config/CustomModesManager.ts Enhanced schema validation error handling (unrelated improvement)
src/core/config/tests/CustomModesManager.yamlEdgeCases.spec.ts Updated tests to handle improved error messaging

@kiloconnect
Copy link
Contributor

kiloconnect bot commented Jan 20, 2026

Code Review Summary

Status: 6 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 3
Issue Details (click to expand)

WARNING

File Line Issue
src/core/webview/webviewMessageHandler.ts N/A Unused import z from @roo-code/types
src/core/config/CustomModesManager.ts N/A Duplicate error message shown twice in the same code block
src/core/config/CustomModesManager.ts N/A Two separate calls to vscode.window.showErrorMessage for the same error

SUGGESTION

File Line Issue
src/core/webview/ClineProvider.ts N/A Redundant return statement without a value
src/core/webview/webviewMessageHandler.ts 1808 Type check condition on line 1795 checks typeof modelId === "string" but the schema already validates this
src/__tests__/modeModelOverride-active-update.spec.ts 2 New test file should have // kilocode_change - new file marker per AGENTS.md
Files Reviewed (42 files)
  • .changeset/true-pears-throw.md - No issues
  • AGENTS.md - Formatting changes only
  • apps/kilocode-docs/docs/providers/kilocode.md - Whitespace fix
  • apps/kilocode-docs/docusaurus.config.ts - Formatting changes only
  • apps/kilocode-docs/i18n/zh-CN/docusaurus-plugin-content-docs/current/features/checkpoints.md - Whitespace fix
  • packages/agent-runtime/src/communication/__tests__/ipc.test.ts - Formatting changes only
  • packages/agent-runtime/src/host/ExtensionHost.ts - Formatting changes only
  • packages/agent-runtime/src/process.ts - Formatting changes only
  • packages/agent-runtime/src/services/extension.ts - Formatting changes only
  • packages/types/src/global-settings.ts - Added modeModelOverrides type
  • packages/types/src/mode.ts - Added model override field
  • src/__tests__/modeModelOverride-active-update.spec.ts - New test file, 1 suggestion
  • src/core/config/CustomModesManager.ts - 2 warnings
  • src/core/webview/ClineProvider.ts - Added modeModelOverrides to state, 1 suggestion
  • src/core/webview/webviewMessageHandler.ts - Added setModeModelOverride handler, 2 issues
  • src/shared/ExtensionMessage.ts - Added modeModelOverrides type
  • src/shared/WebviewMessage.ts - Added schema for mode model override payload
  • webview-ui/src/components/kilocode/KiloModeModelPicker.tsx - New component, no issues
  • webview-ui/src/components/modes/ModesView.tsx - Integrated model picker, no issues
  • webview-ui/src/components/modes/__tests__/ModesView.spec.tsx - Added tests, no issues
  • webview-ui/src/i18n/locales/*/kilocode.json (22 files) - Added translations, no issues

Summary

This PR adds per-mode model override functionality for the Kilo Code gateway provider. The implementation is well-structured with:

  • ✅ Proper TypeScript types and Zod schema validation
  • ✅ New KiloModeModelPicker component with controlled/uncontrolled modes
  • ✅ State persistence via modeModelOverrides in global state
  • ✅ Comprehensive test coverage
  • ✅ Translations for all 22 supported languages

The existing inline comments cover the identified issues. Most are minor suggestions or warnings that don't block the merge.

Fix these issues in Kilo Cloud

Add stable data-testid attributes to KiloModeModelPicker helper text
and update ModesView tests to assert via test IDs instead of strings.
Ensure mode model overrides are applied for any non-null payload value and
explicitly return undefined for non-typical providers.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.

- Update active model when the current mode’s model override is cleared
  (null) so the UI stays in sync without a mode switch
- Ensure schema validation failures surface a single error toast with safe
  fallback behavior (keeps tests deterministic)
- Normalize kilocode marker comments
Remove defensive null checks around router/kilocode model maps and call
setKilocodeGatewayModelsAvailable directly to ensure availability is
consistently updated.
Allow custom mode definitions (YAML/JSON) to specify an optional
provider-agnostic `model` field and automatically derive persisted
`modeModelOverrides` from merged custom modes, clearing overrides when a
mode omits `model` while leaving non-custom slugs untouched.
Stop reapplying per-mode overrides when updating the current mode or
activating provider profiles. Mirror modeModelOverrides from
ExtensionContext.globalState into ContextProxy on startup so the webview
renders the latest overrides immediately.
Do not delete existing mode model overrides when custom modes omit
`mode.model`, and avoid unnecessary globalState writes during refresh.
Also mirror `modeModelOverrides` into ContextProxy so the webview updates
immediately after YAML-driven changes.
Allow KiloModeModelPicker to be controlled via selectedModelId/onSelectModelId
so create-mode flow can defer persistence until submit. Persist the selected
model override after mode creation and add test ids + coverage for the new
dialog behavior.
@iscekic
Copy link
Collaborator Author

iscekic commented Jan 22, 2026

I'm not too happy about code quality here - I'm open to ideas on how to make it better.

Use optional chaining when calling `setKilocodeGatewayModelsAvailable` to
avoid errors with partial provider mocks in unit tests.
- **恢复文件和任务** - 恢复工作区文件并删除所有后续对话消息。当您希望将代码和对话完全重置回检查点的时间点时使用。此选项需要在对话框中进行确认,因为它无法撤消。

<img src="/docs/img/checkpoints/checkpoints-9.png" alt="恢复文件和任务检查点的确认对话框" width="300" />
<img src="/docs/img/checkpoints/checkpoints-9.png" alt="恢复文件和任务检查点的确认对话框" width="300" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to extend the docs for this not anyway for the user?

this.context.globalState.get<Record<string, string>>("modeModelOverrides") ?? {}
await this.contextProxy.setValue("modeModelOverrides", overridesFromGlobalState)
} catch {
// non-fatal
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we log this or handle explicitly? UI should not stay stale here, we should inform the user about the failure.

Comment on lines +1623 to +1628
// kilocode_change start: per-mode overrides are Kilo Code-specific
// Prevent accidentally writing a Kilo Code gateway model id into another provider's model-id field.
if (provider !== "kilocode") {
return
}
// kilocode_change end: per-mode overrides are Kilo Code-specific
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nested kilocode_change markers?

Comment on lines +1761 to +1763
const { name, id, ...providerSettingsFromProfile } = await this.providerSettingsManager.activateProfile(args)
let providerSettings = providerSettingsFromProfile
// kilocode_change: do NOT re-apply per-mode override here; it should only happen during mode switches.
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should wrapp here kilocode_change properly

provider.context.globalState.get<Record<string, string>>("modeModelOverrides") ?? {}
await updateGlobalState("modeModelOverrides", overridesFromGlobalState)
} catch {
// non-fatal
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should log here.

// CustomModesManager updates `context.globalState` directly (not through ContextProxy), so we need to
// mirror `modeModelOverrides` into ContextProxy so the webview can render it immediately.
try {
const overridesFromGlobalState =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Code looks very similar to above, not sure if its possible to exact this logic out into a new file, then we just need a marker for the file and can delegate.

updated[mode] = modelId
}

await updateGlobalState("modeModelOverrides", updated)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This might not work with agent manager, but we can figure this out later. Each agent-runtime process maintains it's own state file in a tmp directory to stay ephemeral. If a mutation happens here this might be therefore fine, as we don't change it in the actively running session. So if users later have to restart the agent manager this should be fine for now.

payload: { mode: "code", modelId: null },
})
})
// kilocode_change end: per-mode model override UI behavior
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need a marker for each individual test?

} as any
}

it("does not apply the per-mode override immediately when updating the current mode (only on mode switch)", async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should it not apply it immediately?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants