Simplify queued user message admission (#38092)

## What changed

- Resolve user message admission when Core accepts the input as a new turn or a steer, without waiting for rollout persistence.
- Remove persistence- and hook-specific admission errors and task bookkeeping.
- Delete queued messages after Core accepts them for turn processing, including messages subsequently stopped by a prompt hook.

## Testing

- Update concurrent admission and queue service tests for acceptance-based admission.

GitOrigin-RevId: 7dcc311cfecd3d710733b420f2add546edb86153
This commit is contained in:
Owen Lin
2026-08-12 00:41:53 +00:00
committed by copyberry
parent 4c89139da9
commit da2803c73c
14 changed files with 41 additions and 600 deletions
-85
View File
@@ -93,8 +93,6 @@ use crate::tools::handlers::ShellCommandHandler;
use crate::tools::registry::ToolExecutor;
use crate::tools::router::ToolCallSource;
use crate::turn_diff_tracker::TurnDiffTracker;
use crate::user_message_admission::PendingUserMessageAdmissionState;
use crate::user_message_admission::UserMessageAdmissionError;
use codex_config::config_toml::ConfigToml;
use codex_config::config_toml::ProjectConfig;
use codex_config::permissions_toml::FilesystemPermissionToml;
@@ -10015,89 +10013,6 @@ async fn attach_in_memory_thread_store(
store
}
#[tokio::test]
async fn failed_user_message_persistence_stops_turn_processing() {
let (mut session, turn_context, _events) = make_session_and_context_with_rx().await;
open_thread_persistence(
Arc::get_mut(&mut session).unwrap_or_else(|| panic!("session should be uniquely owned")),
)
.await;
session
.services
.live_thread
.as_ref()
.unwrap_or_else(|| panic!("session should have a live thread"))
.shutdown()
.await
.unwrap_or_else(|error| panic!("live thread should shut down: {error}"));
let client_id = "persistence-failure".to_string();
let (_pending_admission, admission) = session.pending_user_message_admissions.register(
turn_context.sub_id.clone(),
Some(client_id.clone()),
PendingUserMessageAdmissionState::WaitingForAdmission,
);
let failed_queued_prompt = vec![UserInput::Text {
text: "message with a failed rollout flush".to_string(),
text_elements: Vec::new(),
}];
let later_steer = vec![UserInput::Text {
text: "later ordinary steer".to_string(),
text_elements: Vec::new(),
}];
let later_response = user_message("later response item");
let later_mailbox = InterAgentCommunication::new(
AgentPath::root().join("worker").expect("worker path"),
AgentPath::root(),
Vec::new(),
"later mailbox message".to_string(),
/*trigger_turn*/ false,
);
let input = [
TurnInput::UserInput {
content: failed_queued_prompt,
client_id: Some(client_id),
},
TurnInput::UserInput {
content: later_steer.clone(),
client_id: None,
},
TurnInput::ResponseItem(later_response.clone()),
TurnInput::InterAgentCommunication(later_mailbox.clone()),
];
assert!(
super::turn::run_hooks_and_record_inputs(
&session,
&turn_context,
&input,
PersistContext::Standard,
)
.await,
"a rollout flush failure should stop turn processing"
);
assert!(matches!(
admission.await,
Ok(Err(UserMessageAdmissionError::PersistenceFailed(_)))
));
assert!(turn_context.terminal_error.lock().await.is_some());
let mut expected_suffix = vec![
session.response_item_from_user_input(later_steer),
later_response,
later_mailbox.to_model_input_item(),
];
for item in &mut expected_suffix {
item.set_turn_id_if_missing(&turn_context.sub_id);
}
let history = session.clone_history().await;
let history_items = strip_response_item_ids(&raw_history_items(&history));
assert!(
history_items.ends_with(&strip_response_item_ids(&expected_suffix)),
"later steer, response, and mailbox inputs should survive the failed queued message"
);
}
#[tokio::test]
async fn hook_transcript_path_does_not_persist_non_local_thread_store() {
let (mut session, _) = make_session_and_context().await;