Skip to content

fix(tui): persist provider switches to config#2718

Closed
xyuai wants to merge 1 commit into
Hmbown:mainfrom
xyuai:fix-2663-provider-persist-config
Closed

fix(tui): persist provider switches to config#2718
xyuai wants to merge 1 commit into
Hmbown:mainfrom
xyuai:fix-2663-provider-persist-config

Conversation

@xyuai
Copy link
Copy Markdown
Contributor

@xyuai xyuai commented Jun 3, 2026

Summary

Fixes #2663.

Greptile Summary

This PR fixes a stale-restart bug (#2663) where switching providers via /provider in the TUI was not written back to config.toml, so the next launch would revert to the previously configured provider. The fix wraps both persist_root_string_key (config.toml write) and Settings::load/save in a single closure; on any error the switch still takes effect in memory but a visible warning is appended to the chat and status bar.

  • ui.rs: switch_provider now always calls commands::persist_root_string_key to update config.toml and separately updates Settings, surfacing a non-fatal warning instead of silently ignoring persistence failures.
  • tests.rs: New regression test provider_switch_persists_provider_to_config_for_restart covers the Arcee → XiaomiMimo split-state path from provider switching: settings/config split can mix MiMo model with Arcee base URL #2663, asserting both the in-memory config and the file reloaded from disk agree on the new provider.

Confidence Score: 4/5

Safe to merge — the persistence logic is correct and failures are surfaced as a user-visible warning rather than crashing or silently dropping the switch.

The core fix is straightforward and well-tested: the new regression test verifies the on-disk config, in-memory state, and settings all agree after a switch. The only findings are cosmetic — non-idiomatic newline literals and an arrow character that diverges from the style used by adjacent messages.

No files require special attention; the two style issues are both confined to the new lines in ui.rs.

Important Files Changed

Filename Overview
crates/tui/src/tui/ui.rs Adds config.toml persistence to switch_provider via persist_root_string_key; logic is correct but uses non-idiomatic char::from(10) for newlines and ASCII -> instead of the Unicode → used by adjacent messages.
crates/tui/src/tui/ui/tests.rs New regression test covers the Arcee → XiaomiMimo split-state path, asserting in-memory config, on-disk config, and settings all agree on the switched provider; test structure and assertions look correct.

Sequence Diagram

sequenceDiagram
    participant User
    participant TUI as TUI (switch_provider)
    participant Engine
    participant ConfigTOML as config.toml
    participant Settings as settings.json

    User->>TUI: /provider xiaomi-mimo
    TUI->>TUI: "Update in-memory Config & App state"
    TUI->>Engine: Op::Shutdown
    TUI->>Engine: spawn_engine (new provider)
    TUI->>Engine: Op::SyncSession / Op::SetCompaction

    note over TUI,Settings: Persistence closure (errors become a warning, never block the switch)
    TUI->>ConfigTOML: persist_root_string_key("provider", "xiaomi-mimo")
    alt write succeeds
        ConfigTOML-->>TUI: Ok(path)
        TUI->>Settings: Settings::load()
        Settings-->>TUI: settings
        TUI->>TUI: "settings.default_provider = "xiaomi-mimo""
        TUI->>Settings: settings.save()
        TUI->>User: "Provider switched: Arcee → XiaomiMimo" (no warning)
    else any step fails
        TUI->>User: "Provider switched … (not fully persisted)"
    end
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Reviews (1): Last reviewed commit: "fix(tui): persist provider switches to c..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Thanks @xyuai for taking the time to contribute.

This repository is currently observing a maintainer-managed contribution gate in dry-run mode, so this pull request is staying open. When enforcement is enabled, pull requests from contributors who are not listed in .github/APPROVED_CONTRIBUTORS will be closed automatically.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant PR access by commenting /lgtm on a pull request.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the provider switching logic in the TUI to persist the selected provider to the configuration file, handling potential errors and displaying a warning if persistence fails. It also adds a corresponding integration test to verify this behavior. The review feedback suggests simplifying the construction of the switch_summary string by using a single format! macro call and using the idiomatic '\n' character instead of char::from(10).

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/tui/src/tui/ui.rs
Comment on lines +5381 to +5391
let mut switch_summary = format!(
"Provider switched: {} -> {}",
previous_provider.as_str(),
target.as_str(),
);
switch_summary.push(char::from(10));
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
if let Some(ref warning) = persist_warning {
switch_summary.push(char::from(10));
switch_summary.push_str(warning);
}
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.

medium

The string construction for switch_summary can be simplified and made more idiomatic. Instead of manually pushing newlines via char::from(10) and allocating a temporary string with format! for the model transition, you can combine the initial message and the model transition into a single format! call. Additionally, using '\n' is the standard, idiomatic way to append a newline character in Rust.

    let mut switch_summary = format!(
        "Provider switched: {} -> {}\nModel: {} -> {}",
        previous_provider.as_str(),
        target.as_str(),
        previous_model,
        new_model
    );
    if let Some(ref warning) = persist_warning {
        switch_summary.push('\n');
        switch_summary.push_str(warning);
    }

Comment thread crates/tui/src/tui/ui.rs
Comment on lines +5386 to +5389
switch_summary.push(char::from(10));
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
if let Some(ref warning) = persist_warning {
switch_summary.push(char::from(10));
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.

P2 char::from(10) is a non-idiomatic way to express a newline in Rust and makes the intent harder to read at a glance. The idiomatic form is the ' ' literal, which the rest of the codebase already uses in format strings.

Suggested change
switch_summary.push(char::from(10));
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
if let Some(ref warning) = persist_warning {
switch_summary.push(char::from(10));
switch_summary.push('\n');
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
if let Some(ref warning) = persist_warning {
switch_summary.push('\n');

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code Fix in Cursor

Comment thread crates/tui/src/tui/ui.rs
Comment on lines +5381 to +5387
let mut switch_summary = format!(
"Provider switched: {} -> {}",
previous_provider.as_str(),
target.as_str(),
);
switch_summary.push(char::from(10));
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
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.

P2 The adjacent model/thinking change messages (lines 5215–5257) consistently use the Unicode right arrow , but the new provider-switch message uses the ASCII two-character sequence ->. The inconsistency is visible to users who see both types of messages in the same session.

Suggested change
let mut switch_summary = format!(
"Provider switched: {} -> {}",
previous_provider.as_str(),
target.as_str(),
);
switch_summary.push(char::from(10));
switch_summary.push_str(&format!("Model: {} -> {}", previous_model, new_model));
let mut switch_summary = format!(
"Provider switched: {} {}",
previous_provider.as_str(),
target.as_str(),
);
switch_summary.push('\n');
switch_summary.push_str(&format!("Model: {} {}", previous_model, new_model));

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code Fix in Cursor

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented Jun 3, 2026

Cherry-picked to codex/v0.8.53 in dba332e with endpoint display merged.

@Hmbown Hmbown closed this Jun 3, 2026
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.

provider switching: settings/config split can mix MiMo model with Arcee base URL

2 participants