Enable conversation-scoped speed selection for Cloud turns (#61178)

## What changed

- Stage Cloud speed choices for the next new turn in the conversation, alongside pending model and effort selections. Update the displayed conversation speed after admission without changing the local default.
- Offer speed commands supported by the pending model. Clear an incompatible pending speed change with a warning when switching models.
- Carry `service_tier` through Cloud message requests, preserving omission to inherit the thread tier and explicit null to clear it. Translate `default` to null and reject tier overrides on queued requests.

## Testing

Add tests for Cloud speed toggling, model-dependent speed choices, admission-time updates, and preserving the conversation tier when selecting a model. Extend request and wire tests to cover service-tier values, explicit clearing, and queue rejection.

GitOrigin-RevId: b4daa701f1fe29593d90a938e60cc20cb980298a
This commit is contained in:
Benjamin Carlsson
2026-11-12 20:56:33 +00:00
committed by copyberry
parent 72532ecae5
commit b279cfb170
20 changed files with 583 additions and 73 deletions
+4 -5
View File
@@ -413,7 +413,7 @@ pub(crate) struct AppServerSession {
pub(crate) model_provider_override: Option<String>,
history_support: ThreadHistorySupport,
pub(crate) thread_settings_update_supported: bool,
cloud_model_selections: HashMap<ThreadId, user_message_submission::CloudModelSelection>,
cloud_turn_settings: user_message_submission::PendingCloudTurnSettings,
default_model: Option<String>,
available_models: Vec<ModelPreset>,
prefetched_model_list: Option<RemoteHandle<Result<Vec<ModelPreset>>>>,
@@ -633,7 +633,7 @@ impl AppServerSession {
model_provider_override: None,
history_support: ThreadHistorySupport::Paginated,
thread_settings_update_supported: true,
cloud_model_selections: HashMap::new(),
cloud_turn_settings: Default::default(),
default_model: None,
available_models: Vec::new(),
prefetched_model_list: None,
@@ -1865,7 +1865,7 @@ impl AppServerSession {
collaboration_mode: Option<codex_protocol::config_types::CollaborationMode>,
output_schema: Option<serde_json::Value>,
cyber_access_program: Option<codex_app_server_protocol::CyberAccessProgram>,
cloud_selection: Option<&user_message_submission::CloudModelSelection>,
cloud_selection: Option<&user_message_submission::CloudTurnSettings>,
) -> Result<TurnStartResponse> {
let mut params = TurnStartParams {
thread_id: thread_id.to_string(),
@@ -1891,8 +1891,7 @@ impl AppServerSession {
params.summary = summary;
params.collaboration_mode = collaboration_mode;
} else if let Some(selection) = cloud_selection {
params.model = Some(selection.model.clone());
params.effort.clone_from(&selection.effort);
selection.apply(&mut params);
}
let request_id = self.next_request_id();
self.request_handle