mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 10:36:05 -10:00
fix(tui): refuse provider switches while a turn is running (#2982 turn lock)
The #2982 turn lock (App::reject_setting_change_while_busy) refused mode, thinking, model and permission changes during a turn. Most provider switches skipped it. Only the cross-provider model picker checked (apply.rs:939); AppAction::SwitchProvider (`/provider <id>`), ProviderPickerApplied, the external-grant reuse, the custom provider, the setup and login flows (Codewhale-owned, OrcaRouter) and local Ollama adoption all called switch_provider directly. A mid-turn `/provider <id>` then replaced the engine under the running turn. That turn kept running on the retired engine, and after Ctrl+C or the stall watchdog the session said "a cancelled turn is still settling" (design evidence V7 in the #6981 review). switch_provider (provider_routes.rs) now checks the lock first. It refuses with MessageId::SettingSubjectProvider, the existing localized "{setting} is locked while a turn is running" sentence, and returns false. Every caller already handles false. One choke point covers all callers, present and future, instead of a check at each entry. The provider fallback and auth-rollback respawns do not go through switch_provider and are unchanged. Behaviour notes: - A local Ollama adoption that would happen mid-turn shows the same status. It is not retried by itself; it happens on the next catalog adoption check. Before, it switched under the turn. - The runtime API's provider-switch route is a separate server path and is unchanged. Verification (source:8867749f54plus this diff) - Real TUI in an isolated tmux socket (env -i, scratch HOME), with a local stub provider that holds each response for 25 s. During the turn ("working 3s ... Esc to interrupt"), `/provider openrouter` + Enter printed "Provider is locked while a turn is running — press Esc to interrupt first". The footer stayed "DeepSeek · probe-model" and the turn kept running. - scripts/dev-cargo.sh clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_or: clean. - scripts/dev-test.sh tui provider ollama onboarding setting_locked live_route turn_lock model_picker login: 1127 tests run: 1127 passed, 14224 skipped. - cargo fmt --check clean. sync-changelog.sh: mirrored. - npm test and check:web were last run on8867749f54(101/19/420(413+7)/7, vitest 772/772, check:web exit 0). This diff touches one Rust function and CHANGELOG. Not verified: a baseline run of the old binary in the same probe (the old path is the design review's V7 evidence), Windows. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NBKbhx19BRbZtvWK8rVKjz
This commit is contained in:
1 parent
8867749f54
commit
faaf61be64
3 files changed
+17
No files matched your search
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Switching provider is now refused while a turn is running, as model,
|
||||
thinking and permission changes already were. The refusal covers
|
||||
`/provider <id>`, the provider picker, a custom provider, setup and login
|
||||
flows, and adopting a local Ollama. The status line reads "Provider is
|
||||
locked while a turn is running — press Esc to interrupt first". Before, a
|
||||
mid-turn `/provider <id>` replaced the engine under the running turn
|
||||
(Refs #2982).
|
||||
- `/init` now asks the model to write `AGENTS.md` in the interface language
|
||||
(for example Simplified Chinese when the TUI runs in zh-Hans), headings
|
||||
included, keeping commands, file paths and code identifiers as they are.
|
||||
|
||||
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Switching provider is now refused while a turn is running, as model,
|
||||
thinking and permission changes already were. The refusal covers
|
||||
`/provider <id>`, the provider picker, a custom provider, setup and login
|
||||
flows, and adopting a local Ollama. The status line reads "Provider is
|
||||
locked while a turn is running — press Esc to interrupt first". Before, a
|
||||
mid-turn `/provider <id>` replaced the engine under the running turn
|
||||
(Refs #2982).
|
||||
- `/init` now asks the model to write `AGENTS.md` in the interface language
|
||||
(for example Simplified Chinese when the TUI runs in zh-Hans), headings
|
||||
included, keeping commands, file paths and code identifiers as they are.
|
||||
|
||||
@@ -626,6 +626,9 @@ pub(crate) async fn switch_provider(
|
||||
identity: crate::config::ProviderIdentity,
|
||||
model_override: Option<String>,
|
||||
) -> bool {
|
||||
if app.reject_setting_change_while_busy(MessageId::SettingSubjectProvider) {
|
||||
return false;
|
||||
}
|
||||
if let Err(reason) = config.verify_provider_identity(&identity) {
|
||||
app.push_status_toast(reason, StatusToastLevel::Error, Some(8_000));
|
||||
return false;
|
||||
|
||||
Reference in new issue
Block a user