Skip to content

Commit c99bb77

Browse files
committed
fix(tui/context): persist disabled 1M mode explicitly
1 parent a2416ef commit c99bb77

5 files changed

Lines changed: 103 additions & 9 deletions

File tree

code-rs/core/src/config.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3484,6 +3484,30 @@ model = "gpt-5.4"
34843484
assert_eq!(config.model_auto_compact_token_limit, Some(942_818));
34853485
Ok(())
34863486
}
3487+
3488+
#[test]
3489+
fn context_mode_disabled_preserves_standard_limits() -> anyhow::Result<()> {
3490+
let code_home = TempDir::new()?;
3491+
let cfg = toml::from_str::<ConfigToml>(
3492+
r#"
3493+
model = "gpt-5.4"
3494+
context_mode = "disabled"
3495+
"#,
3496+
)?;
3497+
let config = Config::load_from_base_config_with_overrides(
3498+
cfg,
3499+
ConfigOverrides {
3500+
cwd: Some(code_home.path().to_path_buf()),
3501+
..Default::default()
3502+
},
3503+
code_home.path().to_path_buf(),
3504+
)?;
3505+
3506+
assert_eq!(config.context_mode, Some(ContextMode::Disabled));
3507+
assert_eq!(config.model_context_window, Some(272_000));
3508+
assert_eq!(config.model_auto_compact_token_limit, Some(244_800));
3509+
Ok(())
3510+
}
34873511
}
34883512

34893513
#[cfg(test)]

code-rs/core/src/config_types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,8 @@ pub enum ContextMode {
14551455
OneM,
14561456
#[serde(alias = "\"auto\"")]
14571457
Auto,
1458+
#[serde(alias = "\"disabled\"")]
1459+
Disabled,
14581460
}
14591461

14601462
/// Text verbosity level for OpenAI API responses.

code-rs/core/src/model_family.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ pub fn resolve_context_mode_limits(
435435
EXTENDED_CONTEXT_WINDOW_1M,
436436
)),
437437
),
438+
Some(ContextMode::Disabled) => {
439+
(family.context_window, family.auto_compact_token_limit())
440+
}
438441
_ => (family.context_window, family.auto_compact_token_limit()),
439442
}
440443
}

code-rs/tui/src/bottom_pane/model_selection_view.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -446,9 +446,9 @@ impl ModelSelectionView {
446446
}
447447
EntryKind::ContextMode => {
448448
let next_context_mode = match self.current_context_mode {
449-
None => Some(ContextMode::OneM),
449+
None | Some(ContextMode::Disabled) => Some(ContextMode::OneM),
450450
Some(ContextMode::OneM) => Some(ContextMode::Auto),
451-
Some(ContextMode::Auto) => None,
451+
Some(ContextMode::Auto) => Some(ContextMode::Disabled),
452452
};
453453
self.current_context_mode = next_context_mode;
454454
let _ = self.app_event_tx.send(AppEvent::UpdateSessionContextModeSelection {
@@ -654,7 +654,7 @@ impl ModelSelectionView {
654654
let context_status = match self.current_context_mode {
655655
Some(ContextMode::OneM) => "enabled",
656656
Some(ContextMode::Auto) => "auto",
657-
None => "disabled",
657+
Some(ContextMode::Disabled) | None => "disabled",
658658
};
659659
let context_available = self.supports_extended_context();
660660
let mut context_label_style = Style::default().fg(crate::colors::text());

code-rs/tui/src/chatwidget.rs

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22898,6 +22898,7 @@ Have we met every part of this goal and is there no further work to do?"#
2289822898
&mut self,
2289922899
context_mode: Option<ContextMode>,
2290022900
) {
22901+
let context_mode = context_mode.or(Some(ContextMode::Disabled));
2290122902
if self.config.context_mode == context_mode && !self.sync_session_context_selection_for_model() {
2290222903
return;
2290322904
}
@@ -22925,6 +22926,7 @@ Have we met every part of this goal and is there no further work to do?"#
2292522926
persisted_context_mode.map(|mode| match mode {
2292622927
ContextMode::OneM => "1m",
2292722928
ContextMode::Auto => "auto",
22929+
ContextMode::Disabled => "disabled",
2292822930
}),
2292922931
)],
2293022932
)
@@ -22939,7 +22941,7 @@ Have we met every part of this goal and is there no further work to do?"#
2293922941
let status = match self.config.context_mode {
2294022942
Some(ContextMode::OneM) => "1M context enabled.".to_string(),
2294122943
Some(ContextMode::Auto) => "Auto Context enabled.".to_string(),
22942-
None => "Context mode disabled.".to_string(),
22944+
Some(ContextMode::Disabled) | None => "Context mode disabled.".to_string(),
2294322945
};
2294422946
self.bottom_pane.flash_footer_notice(status);
2294522947
self.request_redraw();
@@ -30224,7 +30226,7 @@ impl Drop for AutoReviewStubGuard {
3022430226
use code_core::parse_command::ParsedCommand;
3022530227
use code_core::protocol::OrderMeta;
3022630228
use code_core::config::{Config, ConfigOverrides, ConfigToml};
30227-
use code_core::config_types::{McpServerConfig, McpServerTransportConfig, ServiceTier};
30229+
use code_core::config_types::{ContextMode, McpServerConfig, McpServerTransportConfig, ServiceTier};
3022830230
use code_core::protocol::{
3022930231
AskForApproval,
3023030232
AgentMessageEvent,
@@ -30599,6 +30601,46 @@ use code_core::protocol::OrderMeta;
3059930601
assert_eq!(reloaded.service_tier, None);
3060030602
}
3060130603

30604+
#[test]
30605+
fn apply_context_mode_selection_persists_disabled_override() {
30606+
let _runtime_guard = enter_test_runtime_guard();
30607+
let code_home = tempdir().expect("temp code home");
30608+
let config_path = code_home.path().join("config.toml");
30609+
let mut harness = ChatWidgetHarness::new();
30610+
harness.chat().config.code_home = code_home.path().to_path_buf();
30611+
harness.chat().config.context_mode = Some(ContextMode::Auto);
30612+
30613+
harness.chat().apply_session_context_mode_selection(None);
30614+
30615+
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(2);
30616+
loop {
30617+
let contents = std::fs::read_to_string(&config_path).unwrap_or_default();
30618+
if contents.contains("context_mode = \"disabled\"") {
30619+
break;
30620+
}
30621+
assert!(
30622+
std::time::Instant::now() < deadline,
30623+
"expected persisted disabled context mode in {config_path:?}, got: {contents:?}"
30624+
);
30625+
std::thread::sleep(std::time::Duration::from_millis(20));
30626+
}
30627+
30628+
let cfg_text = std::fs::read_to_string(&config_path).expect("read config");
30629+
let cfg = toml::from_str::<ConfigToml>(&cfg_text).expect("parse config");
30630+
let reloaded = Config::load_from_base_config_with_overrides(
30631+
cfg,
30632+
ConfigOverrides {
30633+
cwd: Some(code_home.path().to_path_buf()),
30634+
..Default::default()
30635+
},
30636+
code_home.path().to_path_buf(),
30637+
)
30638+
.expect("reload config");
30639+
30640+
assert_eq!(reloaded.context_mode, Some(ContextMode::Disabled));
30641+
assert_eq!(reloaded.model_context_window, Some(272_000));
30642+
}
30643+
3060230644
#[test]
3060330645
fn auto_review_triggers_when_enabled_and_diff_seen() {
3060430646
let _stub_lock = AUTO_STUB_LOCK.lock().unwrap();
@@ -30915,6 +30957,10 @@ use code_core::protocol::OrderMeta;
3091530957
note.contains("Background auto-review completed and reported 1 issue(s)"),
3091630958
"idle auto-review findings should be sent to core immediately"
3091730959
);
30960+
assert!(
30961+
note.contains("Auto Review: 1 issue(s) found. needs work Merge /tmp/wt to apply fixes."),
30962+
"developer follow-up should include the same concise notice shown in the UI"
30963+
);
3091830964
}
3091930965

3092030966
#[test]
@@ -36667,13 +36713,12 @@ impl ChatWidget<'_> {
3666736713
})
3666836714
}
3666936715

36670-
fn insert_auto_review_notice(
36671-
&mut self,
36716+
fn auto_review_notice_line(
3667236717
branch: &str,
3667336718
worktree_path: &std::path::Path,
3667436719
summary: Option<&str>,
3667536720
findings: usize,
36676-
) {
36721+
) -> String {
3667736722
let path_text = format!("{}", worktree_path.display());
3667836723
let has_path = !path_text.is_empty();
3667936724

@@ -36694,6 +36739,17 @@ impl ChatWidget<'_> {
3669436739
line.push_str(&format!("Merge {path_text} to apply fixes."));
3669536740
}
3669636741
line.push_str(" [Ctrl+A] Show");
36742+
line
36743+
}
36744+
36745+
fn insert_auto_review_notice(
36746+
&mut self,
36747+
branch: &str,
36748+
worktree_path: &std::path::Path,
36749+
summary: Option<&str>,
36750+
findings: usize,
36751+
) {
36752+
let line = Self::auto_review_notice_line(branch, worktree_path, summary, findings);
3669736753

3669836754
let message_lines = vec![MessageLine {
3669936755
kind: MessageLineKind::Paragraph,
@@ -36857,6 +36913,14 @@ impl ChatWidget<'_> {
3685736913
resolved_worktree_path.display().to_string()
3685836914
};
3685936915
let errored = error.is_some();
36916+
let notice_line = has_findings.then(|| {
36917+
Self::auto_review_notice_line(
36918+
&worktree_label,
36919+
&resolved_worktree_path,
36920+
summary.as_deref(),
36921+
effective_findings,
36922+
)
36923+
});
3686036924
let (indicator_status, developer_note) = if let Some(err) = error {
3686136925
let summarized_error = Self::summarize_auto_review_error(&err);
3686236926
let classification = Self::classify_auto_review_error(&err);
@@ -36873,7 +36937,8 @@ impl ChatWidget<'_> {
3687336937
)
3687436938
} else if has_findings {
3687536939
let mut note = format!(
36876-
"[developer] Background auto-review completed and reported {effective_findings} issue(s).\n\nA separate LLM ran /review (and may have run auto-resolve) in an isolated git worktree. Any proposed fixes live only in that worktree until you merge them.\n\nNext: Decide if the findings are genuine. If yes, Merge the worktree '{worktree_label}' to apply the changes (or cherry-pick selectively). If not, do not merge.\n\nWorktree path: {worktree_path_label}\n{snapshot_note}\n{agent_note}",
36940+
"[developer] {}\n\nBackground auto-review completed and reported {effective_findings} issue(s).\n\nA separate LLM ran /review (and may have run auto-resolve) in an isolated git worktree. Any proposed fixes live only in that worktree until you merge them.\n\nNext: Decide if the findings are genuine. If yes, Merge the worktree '{worktree_label}' to apply the changes (or cherry-pick selectively). If not, do not merge.\n\nWorktree path: {worktree_path_label}\n{snapshot_note}\n{agent_note}",
36941+
notice_line.as_deref().unwrap_or("Background auto-review found issues."),
3687736942
);
3687836943
if let Some(summary_note) = summary_note {
3687936944
note.push('\n');

0 commit comments

Comments
 (0)