Merge remote-tracking branch 'origin/main' into pakrym/turn-input-user-messages

# Conflicts:
#	codex-rs/core/src/session/turn.rs
This commit is contained in:
pakrym-oai
2026-05-18 20:37:29 -07:00
44 changed files with 1453 additions and 1507 deletions
@@ -502,37 +502,31 @@ impl TurnRequestProcessor {
})?;
}
let thread_settings = codex_protocol::protocol::ThreadSettingsOverrides {
cwd,
workspace_roots: runtime_workspace_roots,
profile_workspace_roots,
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
active_permission_profile,
windows_sandbox_level: None,
model,
effort,
summary,
service_tier,
collaboration_mode,
personality,
};
// Start the turn by submitting the user input. Return its submission id as turn_id.
let turn_op = if has_any_overrides {
Op::UserInputWithTurnContext {
items: mapped_items,
environments: environment_selections,
final_output_json_schema: params.output_schema,
responsesapi_client_metadata: params.responsesapi_client_metadata,
cwd,
workspace_roots: runtime_workspace_roots,
profile_workspace_roots,
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
active_permission_profile,
windows_sandbox_level: None,
model,
effort,
summary,
service_tier,
collaboration_mode,
personality,
}
} else {
Op::UserInput {
items: mapped_items,
environments: environment_selections,
final_output_json_schema: params.output_schema,
responsesapi_client_metadata: params.responsesapi_client_metadata,
thread_settings: Default::default(),
}
let turn_op = Op::UserInput {
items: mapped_items,
environments: environment_selections,
final_output_json_schema: params.output_schema,
responsesapi_client_metadata: params.responsesapi_client_metadata,
thread_settings,
};
let turn_id = self
.submit_core_op(&request_id, thread.as_ref(), turn_op)
+21 -14
View File
@@ -706,22 +706,29 @@ async fn run_review_on_session(
let submit_result = run_before_review_deadline(
deadline,
params.external_cancel.as_ref(),
Box::pin(review_session.codex.submit(Op::UserTurn {
environments: None,
Box::pin(review_session.codex.submit(Op::UserInput {
items: prompt_items.items,
#[allow(deprecated)]
cwd: params.parent_turn.cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy: legacy_sandbox_policy,
permission_profile: Some(guardian_permission_profile),
model: params.model.clone(),
effort: params.reasoning_effort,
summary: Some(params.reasoning_summary),
service_tier: None,
environments: None,
final_output_json_schema: Some(params.schema.clone()),
collaboration_mode: None,
personality: params.personality,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
#[allow(deprecated)]
cwd: Some(params.parent_turn.cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(legacy_sandbox_policy),
permission_profile: Some(guardian_permission_profile),
summary: Some(params.reasoning_summary),
personality: params.personality,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: params.model.clone(),
reasoning_effort: params.reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})),
)
.await;
+1 -102
View File
@@ -49,9 +49,6 @@ use codex_protocol::request_permissions::RequestPermissionsResponse;
use codex_protocol::request_user_input::RequestUserInputResponse;
use crate::context_manager::is_user_turn_boundary;
use codex_protocol::config_types::CollaborationMode;
use codex_protocol::config_types::ModeKind;
use codex_protocol::config_types::Settings;
use codex_protocol::dynamic_tools::DynamicToolResponse;
use codex_protocol::items::UserMessageItem;
use codex_protocol::mcp::RequestId as ProtocolRequestId;
@@ -114,102 +111,6 @@ pub(super) async fn user_input_or_turn_inner(
mirror_user_text_to_realtime: Option<()>,
) {
let (items, updates, responsesapi_client_metadata) = match op {
Op::UserTurn {
cwd,
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
model,
effort,
summary,
service_tier,
final_output_json_schema,
items,
collaboration_mode,
personality,
environments,
} => {
let collaboration_mode = collaboration_mode.or_else(|| {
Some(CollaborationMode {
mode: ModeKind::Default,
settings: Settings {
model: model.clone(),
reasoning_effort: effort,
developer_instructions: None,
},
})
});
(
items,
SessionSettingsUpdate {
cwd: Some(cwd),
approval_policy: Some(approval_policy),
approvals_reviewer,
sandbox_policy: Some(sandbox_policy),
workspace_roots: None,
profile_workspace_roots: None,
permission_profile,
active_permission_profile: None,
windows_sandbox_level: None,
collaboration_mode,
reasoning_summary: summary,
service_tier,
final_output_json_schema: Some(final_output_json_schema),
environments,
personality,
app_server_client_name: None,
app_server_client_version: None,
},
None,
)
}
Op::UserInputWithTurnContext {
cwd,
workspace_roots,
profile_workspace_roots,
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
active_permission_profile,
windows_sandbox_level,
model,
effort,
summary,
service_tier,
final_output_json_schema,
items,
responsesapi_client_metadata,
collaboration_mode,
personality,
environments,
} => {
let mut updates = thread_settings_update(
sess,
ThreadSettingsOverrides {
cwd,
workspace_roots,
profile_workspace_roots,
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
active_permission_profile,
windows_sandbox_level,
model,
effort,
summary,
service_tier,
collaboration_mode,
personality,
},
)
.await;
updates.final_output_json_schema = Some(final_output_json_schema);
updates.environments = environments;
(items, updates, responsesapi_client_metadata)
}
Op::UserInput {
items,
environments,
@@ -872,9 +773,7 @@ pub(super) async fn submission_loop(
.await;
false
}
Op::UserInput { .. }
| Op::UserInputWithTurnContext { .. }
| Op::UserTurn { .. } => {
Op::UserInput { .. } => {
user_input_or_turn(&sess, sub.id.clone(), sub.op).await;
false
}
+21 -39
View File
@@ -5197,7 +5197,7 @@ fn submission_dispatch_span_uses_debug_for_realtime_audio() {
}
#[test]
fn op_kind_distinguishes_turn_ops() {
fn op_kind_for_input_and_context_ops() {
assert_eq!(
Op::OverrideTurnContext {
cwd: None,
@@ -5227,31 +5227,6 @@ fn op_kind_distinguishes_turn_ops() {
.kind(),
"user_input"
);
assert_eq!(
Op::UserInputWithTurnContext {
environments: None,
items: vec![],
final_output_json_schema: None,
responsesapi_client_metadata: None,
cwd: None,
workspace_roots: None,
profile_workspace_roots: None,
approval_policy: None,
approvals_reviewer: None,
sandbox_policy: None,
permission_profile: None,
active_permission_profile: None,
windows_sandbox_level: None,
model: None,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
}
.kind(),
"user_input_with_turn_context"
);
}
#[tokio::test]
@@ -5262,24 +5237,31 @@ async fn user_turn_updates_approvals_reviewer() {
handlers::user_input_or_turn(
&session,
"sub-1".to_string(),
Op::UserTurn {
environments: None,
Op::UserInput {
items: vec![UserInput::Text {
text: "hello".to_string(),
text_elements: Vec::new(),
}],
cwd: config.cwd.to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview),
sandbox_policy: config.legacy_sandbox_policy(),
permission_profile: None,
model: turn_context.model_info.slug.clone(),
effort: config.model_reasoning_effort,
summary: config.model_reasoning_summary,
service_tier: None,
environments: None,
final_output_json_schema: None,
collaboration_mode: None,
personality: config.personality,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(config.cwd.to_path_buf()),
approval_policy: Some(config.permissions.approval_policy.value()),
approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview),
sandbox_policy: Some(config.legacy_sandbox_policy()),
summary: config.model_reasoning_summary,
personality: config.personality,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: turn_context.model_info.slug.clone(),
reasoning_effort: config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
},
)
.await;
+140 -140
View File
@@ -132,10 +132,6 @@ use tracing::warn;
/// - If the model sends only an assistant message, we record it in the
/// conversation history and consider the turn complete.
///
#[expect(
clippy::await_holding_invalid_type,
reason = "turn execution must keep active-turn state transitions atomic"
)]
pub(crate) async fn run_turn(
sess: Arc<Session>,
turn_context: Arc<TurnContext>,
@@ -170,131 +166,11 @@ pub(crate) async fn run_turn(
return None;
}
let skills_outcome = Some(turn_context.turn_skills.outcome.as_ref());
sess.record_context_updates_and_set_reference_context_item(turn_context.as_ref())
.await;
let loaded_plugins = sess
.services
.plugins_manager
.plugins_for_config(&turn_context.config.plugins_config_input())
.await;
// Structured plugin:// mentions are resolved from the current session's
// enabled plugins, then converted into turn-scoped guidance below.
let mentioned_plugins =
collect_explicit_plugin_mentions(&input, loaded_plugins.capability_summaries());
let mcp_tools = if turn_context.apps_enabled() || !mentioned_plugins.is_empty() {
// Plugin mentions need raw MCP/app inventory even when app tools
// are normally hidden so we can describe the plugin's currently
// usable capabilities for this turn.
match sess
.services
.mcp_connection_manager
.read()
.await
.list_all_tools()
.or_cancel(&cancellation_token)
.await
{
Ok(mcp_tools) => mcp_tools,
Err(_) if turn_context.apps_enabled() => return None,
Err(_) => Vec::new(),
}
} else {
Vec::new()
};
let available_connectors = if turn_context.apps_enabled() {
let connectors = codex_connectors::merge::merge_plugin_connectors_with_accessible(
loaded_plugins
.effective_apps()
.into_iter()
.map(|connector_id| connector_id.0),
connectors::accessible_connectors_from_mcp_tools(&mcp_tools),
);
connectors::with_app_enabled_state(connectors, &turn_context.config)
} else {
Vec::new()
};
let connector_slug_counts = build_connector_slug_counts(&available_connectors);
let skill_name_counts_lower = skills_outcome
.as_ref()
.map_or_else(HashMap::new, |outcome| {
build_skill_name_counts(&outcome.skills, &outcome.disabled_paths).1
});
let mentioned_skills = skills_outcome.as_ref().map_or_else(Vec::new, |outcome| {
collect_explicit_skill_mentions(
&input,
&outcome.skills,
&outcome.disabled_paths,
&connector_slug_counts,
)
});
maybe_prompt_and_install_mcp_dependencies(
sess.as_ref(),
turn_context.as_ref(),
&cancellation_token,
&mentioned_skills,
Some(sess.mcp_elicitation_reviewer()),
)
.await;
let session_telemetry = turn_context.session_telemetry.clone();
let thread_id = sess.conversation_id.to_string();
let tracking = build_track_events_context(
turn_context.model_info.slug.clone(),
thread_id,
turn_context.sub_id.clone(),
);
let SkillInjections {
items: skill_injections,
warnings: skill_warnings,
} = build_skill_injections(
&mentioned_skills,
skills_outcome,
Some(&session_telemetry),
&sess.services.analytics_events_client,
tracking.clone(),
)
.await;
for message in skill_warnings {
sess.send_event(&turn_context, EventMsg::Warning(WarningEvent { message }))
.await;
}
let skill_items: Vec<ResponseItem> = skill_injections
.iter()
.map(|skill| ContextualUserFragment::into(crate::context::SkillInstructions::from(skill)))
.collect();
let plugin_items =
build_plugin_injections(&mentioned_plugins, &mcp_tools, &available_connectors);
let mentioned_plugin_metadata = mentioned_plugins
.iter()
.filter_map(crate::plugins::PluginCapabilitySummary::telemetry_metadata)
.collect::<Vec<_>>();
let mut explicitly_enabled_connectors = collect_explicit_app_ids(&input);
explicitly_enabled_connectors.extend(collect_explicit_app_ids_from_skill_items(
&skill_items,
&available_connectors,
&skill_name_counts_lower,
));
let connector_names_by_id = available_connectors
.iter()
.map(|connector| (connector.id.as_str(), connector.name.as_str()))
.collect::<HashMap<&str, &str>>();
let mentioned_app_invocations = explicitly_enabled_connectors
.iter()
.map(|connector_id| AppInvocation {
connector_id: Some(connector_id.clone()),
app_name: connector_names_by_id
.get(connector_id.as_str())
.map(|name| (*name).to_string()),
invocation_type: Some(InvocationType::Explicit),
})
.collect::<Vec<_>>();
let (injection_items, explicitly_enabled_connectors) =
build_skills_and_plugins(&sess, turn_context.as_ref(), &input, &cancellation_token).await?;
if run_pending_session_start_hooks(&sess, &turn_context).await {
return None;
@@ -321,14 +197,6 @@ pub(crate) async fn run_turn(
.await;
}
sess.services
.analytics_events_client
.track_app_mentioned(tracking.clone(), mentioned_app_invocations);
for plugin in mentioned_plugin_metadata {
sess.services
.analytics_events_client
.track_plugin_used(tracking.clone(), plugin);
}
sess.merge_connector_selection(explicitly_enabled_connectors.clone())
.await;
if !input.is_empty() {
@@ -341,12 +209,8 @@ pub(crate) async fn run_turn(
}))
.await;
}
if !skill_items.is_empty() {
sess.record_conversation_items(&turn_context, &skill_items)
.await;
}
if !plugin_items.is_empty() {
sess.record_conversation_items(&turn_context, &plugin_items)
for response_item in injection_items {
sess.record_conversation_items(&turn_context, std::slice::from_ref(&response_item))
.await;
}
@@ -674,6 +538,142 @@ pub(crate) async fn run_turn(
last_agent_message
}
#[expect(
clippy::await_holding_invalid_type,
reason = "MCP tool listing borrows the read guard across cancellation-aware await"
)]
async fn build_skills_and_plugins(
sess: &Arc<Session>,
turn_context: &TurnContext,
input: &[UserInput],
cancellation_token: &CancellationToken,
) -> Option<(Vec<ResponseItem>, HashSet<String>)> {
let tracking = build_track_events_context(
turn_context.model_info.slug.clone(),
sess.conversation_id.to_string(),
turn_context.sub_id.clone(),
);
let loaded_plugins = sess
.services
.plugins_manager
.plugins_for_config(&turn_context.config.plugins_config_input())
.await;
// Structured plugin:// mentions are resolved from the current session's
// enabled plugins, then converted into turn-scoped guidance below.
let mentioned_plugins =
collect_explicit_plugin_mentions(input, loaded_plugins.capability_summaries());
let mcp_tools = if turn_context.apps_enabled() || !mentioned_plugins.is_empty() {
// Plugin mentions need raw MCP/app inventory even when app tools
// are normally hidden so we can describe the plugin's currently
// usable capabilities for this turn.
match sess
.services
.mcp_connection_manager
.read()
.await
.list_all_tools()
.or_cancel(cancellation_token)
.await
{
Ok(mcp_tools) => mcp_tools,
Err(_) if turn_context.apps_enabled() => return None,
Err(_) => Vec::new(),
}
} else {
Vec::new()
};
let available_connectors = if turn_context.apps_enabled() {
let connectors = codex_connectors::merge::merge_plugin_connectors_with_accessible(
loaded_plugins
.effective_apps()
.into_iter()
.map(|connector_id| connector_id.0),
connectors::accessible_connectors_from_mcp_tools(&mcp_tools),
);
connectors::with_app_enabled_state(connectors, &turn_context.config)
} else {
Vec::new()
};
let skills_outcome = turn_context.turn_skills.outcome.as_ref();
let connector_slug_counts = build_connector_slug_counts(&available_connectors);
let skill_name_counts_lower =
build_skill_name_counts(&skills_outcome.skills, &skills_outcome.disabled_paths).1;
let mentioned_skills = collect_explicit_skill_mentions(
input,
&skills_outcome.skills,
&skills_outcome.disabled_paths,
&connector_slug_counts,
);
maybe_prompt_and_install_mcp_dependencies(
sess,
turn_context,
cancellation_token,
&mentioned_skills,
Some(sess.mcp_elicitation_reviewer()),
)
.await;
let SkillInjections {
items: skill_injections,
warnings: skill_warnings,
} = build_skill_injections(
&mentioned_skills,
Some(skills_outcome),
Some(&turn_context.session_telemetry),
&sess.services.analytics_events_client,
tracking.clone(),
)
.await;
for message in skill_warnings {
sess.send_event(turn_context, EventMsg::Warning(WarningEvent { message }))
.await;
}
let skill_items: Vec<ResponseItem> = skill_injections
.iter()
.map(|skill| ContextualUserFragment::into(crate::context::SkillInstructions::from(skill)))
.collect();
let skill_connector_ids = collect_explicit_app_ids_from_skill_items(
&skill_items,
&available_connectors,
&skill_name_counts_lower,
);
let plugin_items =
build_plugin_injections(&mentioned_plugins, &mcp_tools, &available_connectors);
let mut explicitly_enabled_connectors = collect_explicit_app_ids(input);
explicitly_enabled_connectors.extend(skill_connector_ids);
let connector_names_by_id = available_connectors
.iter()
.map(|connector| (connector.id.as_str(), connector.name.as_str()))
.collect::<HashMap<&str, &str>>();
let mentioned_app_invocations = explicitly_enabled_connectors
.iter()
.map(|connector_id| AppInvocation {
connector_id: Some(connector_id.clone()),
app_name: connector_names_by_id
.get(connector_id.as_str())
.map(|name| (*name).to_string()),
invocation_type: Some(InvocationType::Explicit),
})
.collect::<Vec<_>>();
sess.services
.analytics_events_client
.track_app_mentioned(tracking.clone(), mentioned_app_invocations);
for plugin in mentioned_plugins
.iter()
.filter_map(crate::plugins::PluginCapabilitySummary::telemetry_metadata)
{
sess.services
.analytics_events_client
.track_plugin_used(tracking.clone(), plugin);
}
let mut injection_items = skill_items;
injection_items.extend(plugin_items);
Some((injection_items, explicitly_enabled_connectors))
}
async fn track_turn_resolved_config_analytics(
sess: &Session,
turn_context: &TurnContext,
+27 -15
View File
@@ -190,8 +190,14 @@ pub enum ApplyPatchModelOutput {
ShellCommandViaHeredoc,
}
/// Returns the permission fields required by `Op::UserTurn` for tests that
/// construct the op directly.
/// A collection of different ways the model can output an apply_patch call
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ShellModelOutput {
ShellCommand,
// UnifiedExec has its own set of tests
}
/// Returns the permission fields required by test thread-settings overrides.
pub fn turn_permission_fields(
permission_profile: PermissionProfile,
cwd: &Path,
@@ -754,24 +760,30 @@ impl TestCodex {
turn_permission_fields(permission_profile, self.config.cwd.as_path());
let session_model = self.session_configured.model.clone();
self.codex
.submit(Op::UserTurn {
environments,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments,
final_output_json_schema: None,
cwd: self.config.cwd.to_path_buf(),
approval_policy,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(self.config.cwd.to_path_buf()),
approval_policy: Some(approval_policy),
sandbox_policy: Some(sandbox_policy),
permission_profile,
service_tier,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -83,24 +83,29 @@ async fn submit_without_wait_with_turn_permissions(
let test = harness.test();
let session_model = test.session_configured.model.clone();
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: harness.cwd().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(harness.cwd().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
Ok(())
+37 -26
View File
@@ -644,24 +644,29 @@ async fn submit_turn(
let session_model = test.session_configured.model.clone();
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy,
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy,
permission_profile: None,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(approval_policy),
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy: Some(sandbox_policy),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2578,24 +2583,30 @@ async fn matched_prefix_rule_runs_unsandboxed_under_zsh_fork() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, test.cwd.path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run allowed touch under zsh fork".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy,
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(approval_policy),
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+34 -36
View File
@@ -1758,12 +1758,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
)
.await;
let TestCodex {
codex,
config,
session_configured,
..
} = test_codex().with_model("gpt-5.4").build(&server).await?;
let TestCodex { codex, config, .. } = test_codex().with_model("gpt-5.4").build(&server).await?;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Default,
@@ -1775,28 +1770,26 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
};
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
cwd: config.cwd.to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
permission_profile: None,
model: session_configured.model.clone(),
effort: Some(ReasoningEffort::Low),
summary: Some(
config
.model_reasoning_summary
.unwrap_or(ReasoningSummary::Auto),
),
service_tier: None,
collaboration_mode: Some(collaboration_mode),
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(config.cwd.to_path_buf()),
approval_policy: Some(config.permissions.approval_policy.value()),
sandbox_policy: Some(config.legacy_sandbox_policy()),
summary: Some(
config
.model_reasoning_summary
.unwrap_or(ReasoningSummary::Auto),
),
collaboration_mode: Some(collaboration_mode),
..Default::default()
},
})
.await?;
@@ -1898,24 +1891,29 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
.await?;
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
cwd: config.cwd.to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
permission_profile: None,
model: session_configured.model,
effort: None,
summary: Some(ReasoningSummary::Concise),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(config.cwd.to_path_buf()),
approval_policy: Some(config.permissions.approval_policy.value()),
sandbox_policy: Some(config.legacy_sandbox_policy()),
summary: Some(ReasoningSummary::Concise),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_configured.model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await
.unwrap();
+18 -13
View File
@@ -2584,24 +2584,29 @@ text(
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "use exec to inspect and call hidden tools".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -178,28 +178,26 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
let collaboration_mode = collab_mode_with_instructions(Some(collab_text));
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
cwd: test.config.cwd.to_path_buf(),
approval_policy: test.config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: test.config.legacy_sandbox_policy(),
permission_profile: None,
model: test.session_configured.model.clone(),
effort: None,
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
service_tier: None,
collaboration_mode: Some(collaboration_mode),
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
collaboration_mode: Some(collaboration_mode),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
@@ -230,28 +228,26 @@ async fn collaboration_instructions_omitted_when_disabled() -> Result<()> {
let collaboration_mode = collab_mode_with_instructions(Some("turn instructions"));
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
cwd: test.config.cwd.to_path_buf(),
approval_policy: test.config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: test.config.legacy_sandbox_policy(),
permission_profile: None,
model: test.session_configured.model.clone(),
effort: None,
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
service_tier: None,
collaboration_mode: Some(collaboration_mode),
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
collaboration_mode: Some(collaboration_mode),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
@@ -355,28 +351,26 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
.await?;
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
cwd: test.config.cwd.to_path_buf(),
approval_policy: test.config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: test.config.legacy_sandbox_policy(),
permission_profile: None,
model: test.session_configured.model.clone(),
effort: None,
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
service_tier: None,
collaboration_mode: Some(turn_mode),
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
summary: Some(
test.config
.model_reasoning_summary
.unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto),
),
collaboration_mode: Some(turn_mode),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
+18 -13
View File
@@ -88,24 +88,29 @@ fn ev_shell_command_call(call_id: &str, command: &str) -> serde_json::Value {
fn disabled_permission_user_turn(text: impl Into<String>, cwd: PathBuf, model: String) -> Op {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
Op::UserTurn {
environments: None,
Op::UserInput {
items: vec![UserInput::Text {
text: text.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
+38 -26
View File
@@ -46,24 +46,31 @@ async fn submit_user_turn(
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(approval_policy),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: collaboration_mode.or({
Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
})
}),
..Default::default()
},
})
.await?;
Ok(())
@@ -126,24 +133,29 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run shell command".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+36 -26
View File
@@ -113,8 +113,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![
UserInput::LocalImage {
path: abs_path.clone(),
@@ -125,18 +124,24 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu
text_elements: Vec::new(),
},
],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -204,8 +209,7 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()>
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![
UserInput::Image {
image_url: image_url.clone(),
@@ -216,18 +220,24 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()>
text_elements: Vec::new(),
},
],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+12 -14
View File
@@ -44,30 +44,28 @@ use std::path::PathBuf;
fn disabled_plan_turn(
text: &str,
model: String,
_model: String,
collaboration_mode: CollaborationMode,
) -> anyhow::Result<Op> {
let cwd = std::env::current_dir()?;
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
Ok(Op::UserTurn {
environments: None,
Ok(Op::UserInput {
items: vec![UserInput::Text {
text: text.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: Some(collaboration_mode),
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(collaboration_mode),
..Default::default()
},
})
}
+18 -13
View File
@@ -75,24 +75,29 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> {
// 1) Normal user input – should hit server once.
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello world".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: Some(serde_json::from_str(SCHEMA)?),
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+21 -13
View File
@@ -64,27 +64,35 @@ async fn submit_user_turn(
approval_policy: AskForApproval,
collaboration_mode: Option<CollaborationMode>,
) -> Result<()> {
let session_model = test.session_configured.model.clone();
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.cwd.path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: text.to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(approval_policy),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: collaboration_mode.or({
Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
})
}),
..Default::default()
},
})
.await?;
Ok(())
+18 -13
View File
@@ -42,21 +42,26 @@ use wiremock::MockServer;
fn read_only_user_turn(test: &TestCodex, items: Vec<UserInput>, model: String) -> Op {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::read_only(), test.cwd_path());
Op::UserTurn {
environments: None,
Op::UserInput {
items,
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
@@ -117,24 +117,29 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
turn_permission_fields(PermissionProfile::read_only(), first_turn_cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "first turn".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: first_turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy: first_sandbox_policy,
permission_profile: first_permission_profile,
model: test.session_configured.model.clone(),
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(first_turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(first_sandbox_policy),
permission_profile: first_permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |event| {
@@ -147,24 +152,30 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
preturn_context_diff_cwd.as_path(),
);
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "second turn with context updates".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: preturn_context_diff_cwd,
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: None,
sandbox_policy: second_sandbox_policy,
permission_profile: second_permission_profile,
model: test.session_configured.model.clone(),
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: Some(Personality::Friendly),
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(preturn_context_diff_cwd),
approval_policy: Some(AskForApproval::OnRequest),
sandbox_policy: Some(second_sandbox_policy),
permission_profile: second_permission_profile,
personality: Some(Personality::Friendly),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |event| {
@@ -230,24 +241,29 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
turn_permission_fields(PermissionProfile::read_only(), cwd_one.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "first turn in agents_one".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_one.clone(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy: first_sandbox_policy,
permission_profile: first_permission_profile,
model: test.session_configured.model.clone(),
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_one.clone()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(first_sandbox_policy),
permission_profile: first_permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |event| {
@@ -258,24 +274,29 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
let (second_sandbox_policy, second_permission_profile) =
turn_permission_fields(PermissionProfile::read_only(), cwd_two.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "second turn in agents_two".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_two,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy: second_sandbox_policy,
permission_profile: second_permission_profile,
model: test.session_configured.model.clone(),
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_two),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(second_sandbox_policy),
permission_profile: second_permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |event| {
@@ -377,24 +398,30 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
);
resumed
.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "resume and change personality".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: resume_override_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: resumed.session_configured.model.clone(),
effort: resumed.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: Some(Personality::Friendly),
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(resume_override_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
personality: Some(Personality::Friendly),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: resumed.session_configured.model.clone(),
reasoning_effort: resumed.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&resumed.codex, |event| {
+18 -13
View File
@@ -92,24 +92,29 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> {
turn_permission_fields(PermissionProfile::Disabled, test.cwd_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hi".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy: codex_protocol::protocol::AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(codex_protocol::protocol::AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -104,24 +104,29 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch
.await;
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please run a tool".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -113,24 +113,29 @@ async fn submit_danger_full_access_user_turn(test: &TestCodex, text: &str) {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: text.to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.config.cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await
.unwrap_or_else(|err| panic!("submit user turn: {err}"));
+19 -13
View File
@@ -60,24 +60,30 @@ fn read_only_text_turn_with_personality(
) -> Op {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::read_only(), test.cwd_path());
Op::UserTurn {
environments: None,
Op::UserInput {
items: vec![UserInput::Text {
text: text.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(approval_policy),
sandbox_policy: Some(sandbox_policy),
permission_profile,
personality,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
+87 -66
View File
@@ -714,7 +714,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
// Second turn using per-turn overrides via UserTurn
// Second turn using per-turn thread-settings overrides.
let new_cwd = TempDir::new().unwrap();
let writable = TempDir::new().unwrap();
let permission_profile = PermissionProfile::workspace_write_with(
@@ -726,24 +726,24 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, new_cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello 2".into(),
text_elements: Vec::new(),
}],
cwd: new_cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: "o3".to_string(),
effort: Some(ReasoningEffort::High),
summary: Some(ReasoningSummary::Detailed),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(new_cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
model: Some("o3".to_string()),
effort: Some(Some(ReasoningEffort::High)),
summary: Some(ReasoningSummary::Detailed),
..Default::default()
},
})
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
@@ -840,47 +840,57 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
let default_summary = config.model_reasoning_summary;
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello 1".into(),
text_elements: Vec::new(),
}],
cwd: default_cwd.to_path_buf(),
approval_policy: default_approval_policy,
approvals_reviewer: None,
sandbox_policy: default_sandbox_policy.clone(),
permission_profile: None,
model: default_model.clone(),
effort: default_effort,
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(default_cwd.to_path_buf()),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: default_model.clone(),
reasoning_effort: default_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello 2".into(),
text_elements: Vec::new(),
}],
cwd: default_cwd.to_path_buf(),
approval_policy: default_approval_policy,
approvals_reviewer: None,
sandbox_policy: default_sandbox_policy.clone(),
permission_profile: None,
model: default_model.clone(),
effort: default_effort,
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(default_cwd.to_path_buf()),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: default_model.clone(),
reasoning_effort: default_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
@@ -969,24 +979,29 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
let default_summary = config.model_reasoning_summary;
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello 1".into(),
text_elements: Vec::new(),
}],
cwd: default_cwd.to_path_buf(),
approval_policy: default_approval_policy,
approvals_reviewer: None,
sandbox_policy: default_sandbox_policy.clone(),
permission_profile: None,
model: default_model,
effort: default_effort,
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(default_cwd.to_path_buf()),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: default_model,
reasoning_effort: default_effort,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
@@ -994,24 +1009,30 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, default_cwd.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello 2".into(),
text_elements: Vec::new(),
}],
cwd: default_cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: "o3".to_string(),
effort: Some(ReasoningEffort::High),
summary: Some(ReasoningSummary::Detailed),
service_tier: None,
collaboration_mode: None,
environments: None,
final_output_json_schema: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(default_cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
summary: Some(ReasoningSummary::Detailed),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: "o3".to_string(),
reasoning_effort: Some(ReasoningEffort::High),
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
+18 -13
View File
@@ -67,24 +67,29 @@ async fn submit_turn_with_approval_and_environments(
environments: Vec<TurnEnvironmentSelection>,
) -> Result<()> {
test.codex
.submit(Op::UserTurn {
environments: Some(environments),
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: Some(environments),
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy: SandboxPolicy::new_read_only_policy(),
permission_profile: None,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::OnRequest),
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy: Some(SandboxPolicy::new_read_only_policy()),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+47 -110
View File
@@ -142,9 +142,7 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind
)
.await;
let TestCodex {
codex, cwd, config, ..
} = test_codex()
let TestCodex { codex, .. } = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some(requested_model.to_string());
@@ -154,24 +152,15 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind
.await?;
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "check context window".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
model: requested_model.to_string(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
permission_profile: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: Default::default(),
})
.await?;
@@ -220,9 +209,7 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re
)
.await;
let TestCodex {
codex, cwd, config, ..
} = test_codex()
let TestCodex { codex, .. } = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some(requested_model.to_string());
@@ -232,24 +219,15 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re
.await?;
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "check context window".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
model: requested_model.to_string(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
permission_profile: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: Default::default(),
})
.await?;
@@ -298,9 +276,7 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re
)
.await;
let TestCodex {
codex, cwd, config, ..
} = test_codex()
let TestCodex { codex, .. } = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some(requested_model.to_string());
@@ -309,24 +285,15 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re
.await?;
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "check context window".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
model: requested_model.to_string(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
permission_profile: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: Default::default(),
})
.await?;
@@ -388,9 +355,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<(
)
.await;
let TestCodex {
codex, cwd, config, ..
} = test_codex()
let TestCodex { codex, .. } = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some(requested_model.to_string());
@@ -399,24 +364,15 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<(
.await?;
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "check model slug".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
permission_profile: None,
model: requested_model.to_string(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: Default::default(),
})
.await?;
@@ -452,36 +408,21 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning()
)
.await;
let TestCodex {
codex, cwd, config, ..
} = test_codex()
let TestCodex { codex, .. } = test_codex()
.with_model(requested_model)
.build(&server)
.await?;
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "check namespaced model metadata".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: config.permissions.approval_policy.value(),
approvals_reviewer: None,
sandbox_policy: config.legacy_sandbox_policy(),
permission_profile: None,
model: requested_model.to_string(),
effort: None,
summary: Some(
config
.model_reasoning_summary
.unwrap_or(ReasoningSummary::Auto),
),
service_tier: None,
collaboration_mode: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: Default::default(),
})
.await?;
@@ -633,24 +574,22 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run call".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: REMOTE_MODEL_SLUG.to_string(),
effort: None,
summary: Some(ReasoningSummary::Auto),
service_tier: None,
collaboration_mode: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
summary: Some(ReasoningSummary::Auto),
..Default::default()
},
})
.await?;
@@ -865,24 +804,22 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello remote".into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: model.to_string(),
effort: None,
summary: Some(ReasoningSummary::Auto),
service_tier: None,
collaboration_mode: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
summary: Some(ReasoningSummary::Auto),
..Default::default()
},
})
.await?;
@@ -190,24 +190,30 @@ async fn submit_turn(
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, test.cwd.path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy,
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(approval_policy),
approvals_reviewer: Some(ApprovalsReviewer::User),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
Ok(())
@@ -142,24 +142,30 @@ async fn submit_turn(
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy,
approvals_reviewer,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(approval_policy),
approvals_reviewer,
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
Ok(())
+47 -54
View File
@@ -132,36 +132,33 @@ async fn request_user_input_round_trip_for_mode(mode: ModeKind) -> anyhow::Resul
]);
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please confirm".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: Some(CollaborationMode {
mode,
settings: Settings {
model: session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(CollaborationMode {
mode,
settings: Settings {
model: session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -282,31 +279,29 @@ async fn request_user_input_interrupt_emits_deferred_token_count() -> anyhow::Re
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please confirm".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Plan,
settings: Settings {
model: session_configured.model,
reasoning_effort: None,
developer_instructions: None,
},
}),
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Plan,
settings: Settings {
model: session_configured.model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -388,24 +383,22 @@ where
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please confirm".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: Some(collaboration_mode),
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(collaboration_mode),
..Default::default()
},
})
.await?;
@@ -130,24 +130,29 @@ async fn submit_turn_with_timeout(test: &TestCodex, prompt: &str) -> Result<()>
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::workspace_write(), cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::OnRequest),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -105,24 +105,29 @@ fn read_only_user_turn_with_model(
let cwd = fixture.cwd.path().to_path_buf();
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::read_only(), cwd.as_path());
Op::UserTurn {
Op::UserInput {
items: vec![UserInput::Text {
text: text.into(),
text_elements: Vec::new(),
}],
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
environments: None,
final_output_json_schema: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
@@ -37,24 +37,29 @@ const CYBER_POLICY_MESSAGE: &str =
fn disabled_text_turn(test: &TestCodex, text: &str) -> Op {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.cwd_path());
Op::UserTurn {
environments: None,
Op::UserInput {
items: vec![UserInput::Text {
text: text.to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: REQUESTED_MODEL.to_string(),
effort: test.config.model_reasoning_effort,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: REQUESTED_MODEL.to_string(),
reasoning_effort: test.config.model_reasoning_effort,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
+72 -52
View File
@@ -159,24 +159,29 @@ async fn run_snapshot_command_with_options(
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run unified exec with shell snapshot".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -254,24 +259,29 @@ async fn run_shell_command_snapshot_with_options(
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run shell_command with shell snapshot".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -329,24 +339,29 @@ async fn run_tool_turn_on_harness(
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -567,24 +582,29 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, cwd.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "apply patch via shell_command with snapshot".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd.clone(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.clone()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -46,24 +46,29 @@ async fn submit_turn_with_policies(
let (sandbox_policy, permission_profile) =
turn_permission_fields(permission_profile, test.cwd_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd_path().to_path_buf(),
approval_policy,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd_path().to_path_buf()),
approval_policy: Some(approval_policy),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
Ok(())
+18 -13
View File
@@ -74,8 +74,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![
UserInput::Text {
text: "please use $demo".to_string(),
@@ -86,18 +85,24 @@ async fn user_turn_includes_skill_instructions() -> Result<()> {
path: skill_path.clone(),
},
],
environments: None,
final_output_json_schema: None,
cwd: test.config.cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -405,24 +405,29 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result<
turn_permission_fields(PermissionProfile::read_only(), cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "call the rmcp echo tool".to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: test.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: test.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
wait_for_event(&test.codex, |event| {
+90 -65
View File
@@ -102,24 +102,29 @@ async fn shell_command_tool_executes_command_and_streams_output() -> anyhow::Res
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please run the shell command".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -178,24 +183,29 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> {
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please update the plan".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -264,24 +274,29 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> {
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please update the plan".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -360,24 +375,29 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<()
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please apply a patch".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -493,24 +513,29 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> {
turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "please apply a patch".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd_path,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd_path),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+36 -26
View File
@@ -37,24 +37,29 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> {
turn_permission_fields(PermissionProfile::Disabled, test.cwd.path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -358,24 +363,29 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.cwd.path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "stream delayed completion".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -515,24 +515,29 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> {
fixture
.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "call the rmcp image tool".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: fixture.cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile: Some(permission_profile),
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(fixture.cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile: Some(permission_profile),
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+126 -92
View File
@@ -192,24 +192,29 @@ async fn submit_unified_exec_turn(
turn_permission_fields(permission_profile, test.config.cwd.as_path());
test.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: prompt.into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: test.config.cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -278,24 +283,29 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> {
turn_permission_fields(PermissionProfile::Disabled, &cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "apply patch via unified exec".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2120,24 +2130,29 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()>
turn_permission_fields(PermissionProfile::Disabled, &turn_cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "keep unified exec process after turn end".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2218,24 +2233,29 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> {
turn_permission_fields(PermissionProfile::Disabled, &turn_cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "interrupt long-running unified exec".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2685,25 +2705,29 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> {
turn_permission_fields(PermissionProfile::read_only(), &turn_cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "summarize large output".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
// Important!
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2803,24 +2827,29 @@ async fn unified_exec_enforces_glob_deny_read_policy() -> Result<()> {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::read_only(), &turn_cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "read the fixture files".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
@@ -2936,24 +2965,29 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> {
turn_permission_fields(PermissionProfile::read_only(), &turn_cwd);
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "start python under seatbelt".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: turn_cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(turn_cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -174,24 +174,29 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()>
fixture
.codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "run model shell command".to_string(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd,
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: fixture.session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: fixture.session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
+18 -13
View File
@@ -72,21 +72,26 @@ const VIEW_IMAGE_TURN_COMPLETE_TIMEOUT: Duration = Duration::from_secs(30);
fn disabled_user_turn(test: &TestCodex, items: Vec<UserInput>, model: String) -> Op {
let (sandbox_policy, permission_profile) =
turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path());
Op::UserTurn {
environments: None,
Op::UserInput {
items,
environments: None,
final_output_json_schema: None,
cwd: test.config.cwd.to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(test.config.cwd.to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
}
}
+18 -13
View File
@@ -152,24 +152,29 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result
turn_permission_fields(PermissionProfile::Disabled, cwd.path());
codex
.submit(Op::UserTurn {
environments: None,
.submit(Op::UserInput {
items: vec![UserInput::Text {
text: "hello".into(),
text_elements: Vec::new(),
}],
environments: None,
final_output_json_schema: None,
cwd: cwd.path().to_path_buf(),
approval_policy: AskForApproval::Never,
approvals_reviewer: None,
sandbox_policy,
permission_profile,
model: session_configured.model.clone(),
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: None,
responsesapi_client_metadata: None,
thread_settings: codex_protocol::protocol::ThreadSettingsOverrides {
cwd: Some(cwd.path().to_path_buf()),
approval_policy: Some(AskForApproval::Never),
sandbox_policy: Some(sandbox_policy),
permission_profile,
collaboration_mode: Some(codex_protocol::config_types::CollaborationMode {
mode: codex_protocol::config_types::ModeKind::Default,
settings: codex_protocol::config_types::Settings {
model: session_configured.model.clone(),
reasoning_effort: None,
developer_instructions: None,
},
}),
..Default::default()
},
})
.await?;
-159
View File
@@ -518,163 +518,6 @@ pub enum Op {
thread_settings: ThreadSettingsOverrides,
},
/// Similar to [`Op::UserInput`], but first applies persistent thread-settings
/// overrides in the same queued operation. This preserves submission order
/// and prevents the input from starting if the overrides are rejected.
UserInputWithTurnContext {
/// User input items, see `InputItem`
items: Vec<UserInput>,
/// Optional turn-scoped environment selections.
#[serde(default, skip_serializing_if = "Option::is_none")]
environments: Option<Vec<TurnEnvironmentSelection>>,
/// Optional JSON Schema used to constrain the final assistant message for this turn.
#[serde(skip_serializing_if = "Option::is_none")]
final_output_json_schema: Option<Value>,
/// Optional turn-scoped Responses API `client_metadata`.
#[serde(default, skip_serializing_if = "Option::is_none")]
responsesapi_client_metadata: Option<HashMap<String, String>>,
/// Updated `cwd` for sandbox/tool calls.
#[serde(skip_serializing_if = "Option::is_none")]
cwd: Option<PathBuf>,
/// Updated runtime workspace roots used to materialize symbolic
/// `:workspace_roots` filesystem permissions.
#[serde(skip_serializing_if = "Option::is_none")]
workspace_roots: Option<Vec<AbsolutePathBuf>>,
/// Updated profile-defined workspace roots for status summaries and
/// per-turn config reconstruction.
#[serde(skip_serializing_if = "Option::is_none")]
profile_workspace_roots: Option<Vec<AbsolutePathBuf>>,
/// Updated command approval policy.
#[serde(skip_serializing_if = "Option::is_none")]
approval_policy: Option<AskForApproval>,
/// Updated approval reviewer for future approval prompts.
#[serde(skip_serializing_if = "Option::is_none")]
approvals_reviewer: Option<ApprovalsReviewer>,
/// Updated sandbox policy for tool calls.
#[serde(skip_serializing_if = "Option::is_none")]
sandbox_policy: Option<SandboxPolicy>,
/// Updated permissions profile for tool calls.
#[serde(skip_serializing_if = "Option::is_none")]
permission_profile: Option<PermissionProfile>,
/// Named or built-in profile that produced `permission_profile`, if
/// the update selected a profile rather than supplying raw
/// permissions.
#[serde(skip_serializing_if = "Option::is_none")]
active_permission_profile: Option<ActivePermissionProfile>,
/// Updated Windows sandbox mode for tool execution.
#[serde(skip_serializing_if = "Option::is_none")]
windows_sandbox_level: Option<WindowsSandboxLevel>,
/// Updated model slug. When set, the model info is derived
/// automatically.
#[serde(skip_serializing_if = "Option::is_none")]
model: Option<String>,
/// Updated reasoning effort (honored only for reasoning-capable models).
///
/// Use `Some(Some(_))` to set a specific effort, `Some(None)` to clear
/// the effort, or `None` to leave the existing value unchanged.
#[serde(skip_serializing_if = "Option::is_none")]
effort: Option<Option<ReasoningEffortConfig>>,
/// Updated reasoning summary preference (honored only for reasoning-capable models).
#[serde(skip_serializing_if = "Option::is_none")]
summary: Option<ReasoningSummaryConfig>,
/// Updated service tier preference for future turns.
///
/// Use `Some(Some(_))` to set a specific tier, `Some(None)` to clear the
/// preference, or `None` to leave the existing value unchanged.
#[serde(skip_serializing_if = "Option::is_none")]
service_tier: Option<Option<String>>,
/// EXPERIMENTAL - set a pre-set collaboration mode.
/// Takes precedence over model, effort, and developer instructions if set.
#[serde(skip_serializing_if = "Option::is_none")]
collaboration_mode: Option<CollaborationMode>,
/// Updated personality preference.
#[serde(skip_serializing_if = "Option::is_none")]
personality: Option<Personality>,
},
/// Similar to [`Op::UserInput`], but contains additional context required
/// for a turn of a [`crate::codex_thread::CodexThread`].
UserTurn {
/// User input items, see `InputItem`
items: Vec<UserInput>,
/// `cwd` to use with the [`SandboxPolicy`] and potentially tool calls
/// such as `local_shell`.
cwd: PathBuf,
/// Policy to use for command approval.
approval_policy: AskForApproval,
/// Reviewer to use for approval requests raised during this turn.
///
/// When omitted, the session keeps the current setting
approvals_reviewer: Option<ApprovalsReviewer>,
/// Policy to use for tool calls such as `local_shell`.
sandbox_policy: SandboxPolicy,
/// Full permissions profile to use for tool calls such as `local_shell`.
///
/// When omitted, `sandbox_policy` is used as a legacy compatibility
/// projection.
#[serde(default, skip_serializing_if = "Option::is_none")]
permission_profile: Option<PermissionProfile>,
/// Must be a valid model slug for the configured client session
/// associated with this conversation.
model: String,
/// Will only be honored if the model is configured to use reasoning.
#[serde(skip_serializing_if = "Option::is_none")]
effort: Option<ReasoningEffortConfig>,
/// Will only be honored if the model is configured to use reasoning.
///
/// When omitted, the session keeps the current setting (which allows core to
/// fall back to the selected model's default on new sessions).
#[serde(default, skip_serializing_if = "Option::is_none")]
summary: Option<ReasoningSummaryConfig>,
/// Optional service tier override for this turn.
///
/// Use `Some(Some(_))` to set a specific tier for this turn, `Some(None)` to
/// explicitly clear the tier for this turn, or `None` to keep the existing
/// session preference.
#[serde(default, skip_serializing_if = "Option::is_none")]
service_tier: Option<Option<String>>,
// The JSON schema to use for the final assistant message
final_output_json_schema: Option<Value>,
/// EXPERIMENTAL - set a pre-set collaboration mode.
/// Takes precedence over model, effort, and developer instructions if set.
#[serde(skip_serializing_if = "Option::is_none")]
collaboration_mode: Option<CollaborationMode>,
/// Optional personality override for this turn.
#[serde(skip_serializing_if = "Option::is_none")]
personality: Option<Personality>,
/// Optional turn-scoped environments.
#[serde(default, skip_serializing_if = "Option::is_none")]
environments: Option<Vec<TurnEnvironmentSelection>>,
},
/// Inter-agent communication that should be recorded as assistant history
/// while still using the normal thread submission lifecycle.
InterAgentCommunication {
@@ -932,8 +775,6 @@ impl Op {
Self::RealtimeConversationClose => "realtime_conversation_close",
Self::RealtimeConversationListVoices => "realtime_conversation_list_voices",
Self::UserInput { .. } => "user_input",
Self::UserInputWithTurnContext { .. } => "user_input_with_turn_context",
Self::UserTurn { .. } => "user_turn",
Self::InterAgentCommunication { .. } => "inter_agent_communication",
Self::OverrideTurnContext { .. } => "override_turn_context",
Self::ExecApproval { .. } => "exec_approval",