core: enable remote compaction v2 by default (#27573)

## Why

Remote compaction v2 is ready to become the default for providers that
already support remote compaction. Leaving it behind an
under-development opt-in keeps eligible sessions on the legacy
remote-compaction path.

This does not broaden provider eligibility: OpenAI and Azure move to v2,
while Bedrock and OSS providers retain their existing local-compaction
behavior.

## What changed

- Mark `remote_compaction_v2` stable and enable it by default.
- Make tests that intentionally cover legacy remote compaction
explicitly disable v2.
- Update parity coverage so v2 exercises the production default and only
legacy mode opts out.

## Verification

- `just test -p codex-core
auto_compact_runs_after_resume_when_token_usage_is_over_limit
auto_compact_counts_encrypted_reasoning_before_last_user
auto_compact_runs_when_reasoning_header_clears_between_turns
responses_lite_compact_request_uses_lite_transport_contract`
This commit is contained in:
jif
2026-06-11 11:07:19 +01:00
committed by GitHub
Unverified
parent 6754e77792
commit 273a4aa4f2
8 changed files with 55 additions and 58 deletions
@@ -29,6 +29,7 @@ use codex_app_server_protocol::TurnStartParams;
use codex_app_server_protocol::TurnStartResponse;
use codex_app_server_protocol::UserInput as V2UserInput;
use codex_config::types::AuthCredentialsStoreMode;
use codex_features::Feature;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use core_test_support::responses;
@@ -150,7 +151,7 @@ async fn auto_compaction_remote_emits_started_and_completed_items() -> Result<()
write_mock_responses_config_toml(
codex_home.path(),
&server.uri(),
&BTreeMap::default(),
&BTreeMap::from([(Feature::RemoteCompactionV2, false)]),
REMOTE_AUTO_COMPACT_LIMIT,
Some(true),
"mock_provider",
+4
View File
@@ -2015,6 +2015,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() {
let mut builder = test_codex().with_config(move |config| {
set_test_compact_prompt(config);
config.model_auto_compact_token_limit = Some(limit);
let _ = config.features.disable(Feature::RemoteCompactionV2);
});
let initial = builder.build(&server).await.unwrap();
let home = initial.home.clone();
@@ -2043,6 +2044,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() {
let mut resume_builder = test_codex().with_config(move |config| {
set_test_compact_prompt(config);
config.model_auto_compact_token_limit = Some(limit);
let _ = config.features.disable(Feature::RemoteCompactionV2);
});
let resumed = resume_builder
.resume(&server, home, rollout_path)
@@ -4023,6 +4025,7 @@ async fn auto_compact_counts_encrypted_reasoning_before_last_user() {
config.chatgpt_base_url = chatgpt_base_url;
set_test_compact_prompt(config);
config.model_auto_compact_token_limit = Some(300);
let _ = config.features.disable(Feature::RemoteCompactionV2);
})
.build(&server)
.await
@@ -4145,6 +4148,7 @@ async fn auto_compact_runs_when_reasoning_header_clears_between_turns() {
.with_config(|config| {
set_test_compact_prompt(config);
config.model_auto_compact_token_limit = Some(300);
let _ = config.features.disable(Feature::RemoteCompactionV2);
})
.build(&server)
.await
+7 -1
View File
@@ -36,7 +36,7 @@ use core_test_support::responses::start_websocket_server;
use core_test_support::skip_if_no_network;
use core_test_support::test_codex::TestCodexBuilder;
use core_test_support::test_codex::TestCodexHarness;
use core_test_support::test_codex::test_codex;
use core_test_support::test_codex::test_codex as base_test_codex;
use core_test_support::test_path_buf;
use core_test_support::wait_for_event;
use core_test_support::wait_for_event_match;
@@ -160,6 +160,12 @@ fn compacted_summary_only_output(summary: &str) -> Vec<ResponseItem> {
}]
}
fn test_codex() -> TestCodexBuilder {
base_test_codex().with_config(|config| {
let _ = config.features.disable(Feature::RemoteCompactionV2);
})
}
fn remote_realtime_test_codex_builder(
realtime_server: &responses::WebSocketTestServer,
) -> TestCodexBuilder {
@@ -529,8 +529,8 @@ async fn build_harness_inner(
if hooks {
trust_discovered_hooks(config);
}
if mode == Mode::V2 {
let _ = config.features.enable(Feature::RemoteCompactionV2);
if mode == Mode::Legacy {
let _ = config.features.disable(Feature::RemoteCompactionV2);
}
}))
.await
+30 -38
View File
@@ -34,7 +34,6 @@ use core_test_support::responses::ev_function_call;
use core_test_support::responses::ev_message_item_added;
use core_test_support::responses::ev_output_text_delta;
use core_test_support::responses::ev_response_created;
use core_test_support::responses::mount_compact_json_once;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::mount_sse_sequence;
use core_test_support::responses::sse;
@@ -1441,21 +1440,32 @@ async fn resumed_thread_runs_resume_then_compact_session_start_hooks() -> Result
let remote_summary = "remote compact summary";
let resume_context = "remember the resumed reef";
let compact_context = "remember the compacted reef";
let compacted_history = vec![
ResponseItem::Message {
id: None,
role: "assistant".to_string(),
content: vec![ContentItem::OutputText {
text: remote_summary.to_string(),
}],
phase: None,
},
ResponseItem::Compaction {
encrypted_content: "encrypted compact summary".to_string(),
},
];
let compact_mock =
mount_compact_json_once(&server, serde_json::json!({ "output": compacted_history })).await;
let responses_mock = mount_sse_sequence(
&server,
vec![
sse(vec![
ev_response_created("resp-1"),
ev_assistant_message("msg-1", "hello before resume"),
ev_completed_with_tokens("resp-1", over_limit_tokens),
]),
sse(vec![
serde_json::json!({
"type": "response.output_item.done",
"item": {
"type": "compaction",
"encrypted_content": remote_summary,
}
}),
ev_completed("resp-compact"),
]),
sse(vec![
ev_response_created("resp-2"),
ev_assistant_message("msg-2", "hello after resume"),
ev_completed("resp-2"),
]),
],
)
.await;
let mut builder = test_codex()
.with_pre_build_hook(move |home| {
@@ -1479,37 +1489,19 @@ async fn resumed_thread_runs_resume_then_compact_session_start_hooks() -> Result
.clone()
.context("rollout path")?;
mount_sse_once(
&server,
sse(vec![
ev_response_created("resp-1"),
ev_assistant_message("msg-1", "hello before resume"),
ev_completed_with_tokens("resp-1", over_limit_tokens),
]),
)
.await;
initial.submit_turn("hello before resume").await?;
assert!(compact_mock.requests().is_empty());
assert_eq!(responses_mock.requests().len(), 1);
let mut resume_builder = test_codex().with_config(move |config| {
config.model_auto_compact_token_limit = Some(limit);
trust_discovered_hooks(config);
});
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
let follow_up = mount_sse_once(
&server,
sse(vec![
ev_response_created("resp-2"),
ev_assistant_message("msg-2", "hello after resume"),
ev_completed("resp-2"),
]),
)
.await;
resumed.submit_turn("hello after resume").await?;
assert_eq!(compact_mock.requests().len(), 1);
let developer_messages = follow_up.single_request().message_input_texts("developer");
let requests = responses_mock.requests();
assert_eq!(requests.len(), 3);
let developer_messages = requests[2].message_input_texts("developer");
assert!(
developer_messages
.iter()
+8 -4
View File
@@ -177,10 +177,14 @@ async fn responses_lite_compact_request_uses_lite_transport_contract() -> Result
let compact_mock =
responses::mount_compact_json_once(&server, serde_json::json!({ "output": [] })).await;
let mut builder = test_codex().with_model_info_override("gpt-5.4", |model_info| {
model_info.use_responses_lite = true;
model_info.supports_parallel_tool_calls = true;
});
let mut builder = test_codex()
.with_model_info_override("gpt-5.4", |model_info| {
model_info.use_responses_lite = true;
model_info.supports_parallel_tool_calls = true;
})
.with_config(|config| {
let _ = config.features.disable(Feature::RemoteCompactionV2);
});
let test = builder.build(&server).await?;
test.submit_turn("Compact this conversation").await?;
+2 -2
View File
@@ -1249,8 +1249,8 @@ pub const FEATURES: &[FeatureSpec] = &[
FeatureSpec {
id: Feature::RemoteCompactionV2,
key: "remote_compaction_v2",
stage: Stage::UnderDevelopment,
default_enabled: false,
stage: Stage::Stable,
default_enabled: true,
},
FeatureSpec {
id: Feature::WorkspaceDependencies,
-10
View File
@@ -150,16 +150,6 @@ fn request_permissions_tool_is_under_development() {
assert_eq!(Feature::RequestPermissionsTool.default_enabled(), false);
}
#[test]
fn remote_compaction_v2_is_under_development() {
assert_eq!(Feature::RemoteCompactionV2.stage(), Stage::UnderDevelopment);
assert_eq!(Feature::RemoteCompactionV2.default_enabled(), false);
assert_eq!(
feature_for_key("remote_compaction_v2"),
Some(Feature::RemoteCompactionV2)
);
}
#[test]
fn terminal_resize_reflow_is_experimental_and_enabled_by_default() {
assert_eq!(