From 8751324dfe9935a54a5c67969e4bbf44f6def1c5 Mon Sep 17 00:00:00 2001 From: Edward Frazer Date: Mon, 15 Jun 2026 04:32:21 +0000 Subject: [PATCH] refactor: extract core user submission data --- .../src/request_processors/turn_processor.rs | 11 +- codex-rs/core-api/src/lib.rs | 1 + codex-rs/core/src/agent/control.rs | 3 +- codex-rs/core/src/agent/control_tests.rs | 43 +- codex-rs/core/src/codex_delegate.rs | 11 +- codex-rs/core/src/guardian/review_session.rs | 11 +- codex-rs/core/src/session/handlers.rs | 12 +- codex-rs/core/src/session/mod.rs | 15 +- codex-rs/core/src/session/tests.rs | 51 +- .../src/tools/handlers/multi_agents_tests.rs | 27 +- .../tools/handlers/multi_agents_v2/spawn.rs | 5 +- codex-rs/core/tests/common/test_codex.rs | 15 +- .../remote_env_windows_test.rs | 17 +- codex-rs/core/tests/suite/abort_tasks.rs | 71 +- .../core/tests/suite/additional_context.rs | 333 ++++--- codex-rs/core/tests/suite/agents_md.rs | 43 +- codex-rs/core/tests/suite/apply_patch_cli.rs | 29 +- codex-rs/core/tests/suite/approvals.rs | 57 +- codex-rs/core/tests/suite/auto_review.rs | 15 +- codex-rs/core/tests/suite/client.rs | 505 +++++----- .../core/tests/suite/client_websockets.rs | 29 +- codex-rs/core/tests/suite/code_mode.rs | 15 +- .../tests/suite/collaboration_instructions.rs | 239 ++--- codex-rs/core/tests/suite/compact.rs | 461 ++++----- codex-rs/core/tests/suite/compact_remote.rs | 915 +++++++++--------- .../core/tests/suite/compact_remote_parity.rs | 9 +- .../core/tests/suite/compact_resume_fork.rs | 15 +- codex-rs/core/tests/suite/exec_policy.rs | 29 +- .../core/tests/suite/extension_sandbox.rs | 15 +- codex-rs/core/tests/suite/fork_thread.rs | 29 +- codex-rs/core/tests/suite/guardian_review.rs | 15 +- codex-rs/core/tests/suite/hooks.rs | 29 +- codex-rs/core/tests/suite/image_rollout.rs | 53 +- codex-rs/core/tests/suite/items.rs | 135 +-- codex-rs/core/tests/suite/json_result.rs | 17 +- .../core/tests/suite/mcp_turn_metadata.rs | 15 +- .../tests/suite/model_runtime_selectors.rs | 29 +- codex-rs/core/tests/suite/model_switching.rs | 9 +- .../core/tests/suite/model_visible_layout.rs | 113 +-- codex-rs/core/tests/suite/models_cache_ttl.rs | 15 +- .../core/tests/suite/models_etag_responses.rs | 15 +- codex-rs/core/tests/suite/otel.rs | 309 +++--- codex-rs/core/tests/suite/pending_input.rs | 57 +- .../core/tests/suite/permissions_messages.rs | 211 ++-- codex-rs/core/tests/suite/personality.rs | 15 +- codex-rs/core/tests/suite/plugins.rs | 71 +- codex-rs/core/tests/suite/prompt_caching.rs | 211 ++-- codex-rs/core/tests/suite/quota_exceeded.rs | 15 +- .../core/tests/suite/realtime_conversation.rs | 29 +- codex-rs/core/tests/suite/remote_env.rs | 15 +- codex-rs/core/tests/suite/remote_models.rs | 99 +- .../core/tests/suite/request_compression.rs | 29 +- .../core/tests/suite/request_permissions.rs | 15 +- .../tests/suite/request_permissions_tool.rs | 15 +- .../core/tests/suite/request_user_input.rs | 43 +- .../suite/responses_api_proxy_headers.rs | 15 +- codex-rs/core/tests/suite/responses_lite.rs | 15 +- codex-rs/core/tests/suite/resume.rs | 99 +- codex-rs/core/tests/suite/review.rs | 15 +- codex-rs/core/tests/suite/rmcp_client.rs | 15 +- .../tests/suite/safety_check_downgrade.rs | 15 +- codex-rs/core/tests/suite/search_tool.rs | 57 +- codex-rs/core/tests/suite/shell_snapshot.rs | 57 +- codex-rs/core/tests/suite/skill_approval.rs | 15 +- codex-rs/core/tests/suite/skills.rs | 27 +- codex-rs/core/tests/suite/sqlite_state.rs | 43 +- .../suite/stream_error_allows_next_turn.rs | 29 +- .../core/tests/suite/stream_no_completed.rs | 15 +- .../tests/suite/subagent_notifications.rs | 15 +- codex-rs/core/tests/suite/tool_harness.rs | 71 +- codex-rs/core/tests/suite/tool_parallelism.rs | 29 +- codex-rs/core/tests/suite/truncation.rs | 15 +- codex-rs/core/tests/suite/unified_exec.rs | 99 +- .../suite/unified_exec_zsh_fork_approvals.rs | 15 +- .../core/tests/suite/user_notification.rs | 15 +- codex-rs/core/tests/suite/user_shell_cmd.rs | 15 +- codex-rs/core/tests/suite/view_image.rs | 9 +- .../core/tests/suite/websocket_fallback.rs | 15 +- codex-rs/core/tests/suite/window_headers.rs | 15 +- codex-rs/mcp-server/src/codex_tool_runner.rs | 33 +- codex-rs/memories/write/src/runtime.rs | 9 +- codex-rs/protocol/src/protocol.rs | 36 +- codex-rs/thread-manager-sample/src/main.rs | 15 +- 83 files changed, 2775 insertions(+), 2658 deletions(-) diff --git a/codex-rs/app-server/src/request_processors/turn_processor.rs b/codex-rs/app-server/src/request_processors/turn_processor.rs index 8d1810d87f..5767ce33c2 100644 --- a/codex-rs/app-server/src/request_processors/turn_processor.rs +++ b/codex-rs/app-server/src/request_processors/turn_processor.rs @@ -4,6 +4,7 @@ use codex_protocol::protocol::AdditionalContextKind as CoreAdditionalContextKind use codex_protocol::protocol::MultiAgentVersion; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; +use codex_protocol::protocol::UserSubmission; use codex_utils_path_uri::PathUri; const DIRECT_INPUT_TO_MULTI_AGENT_V2_SUBAGENT_ERROR: &str = @@ -471,10 +472,12 @@ impl TurnRequestProcessor { // Start the turn by submitting the user input. Return its submission id as turn_id. let turn_op = Op::UserInput { - items: mapped_items, - final_output_json_schema: params.output_schema, - responsesapi_client_metadata: params.responsesapi_client_metadata, - additional_context, + submission: UserSubmission { + items: mapped_items, + final_output_json_schema: params.output_schema, + responsesapi_client_metadata: params.responsesapi_client_metadata, + additional_context, + }, thread_settings, }; let turn_id = thread diff --git a/codex-rs/core-api/src/lib.rs b/codex-rs/core-api/src/lib.rs index df4e6ea8a6..b62c23fbb8 100644 --- a/codex-rs/core-api/src/lib.rs +++ b/codex-rs/core-api/src/lib.rs @@ -90,6 +90,7 @@ pub use codex_protocol::protocol::Op; pub use codex_protocol::protocol::SessionConfiguredEvent; pub use codex_protocol::protocol::SessionSource; pub use codex_protocol::protocol::TurnEnvironmentSelection; +pub use codex_protocol::protocol::UserSubmission; pub use codex_protocol::protocol::W3cTraceContext; pub use codex_protocol::user_input::UserInput; pub use codex_utils_absolute_path::AbsolutePathBuf; diff --git a/codex-rs/core/src/agent/control.rs b/codex-rs/core/src/agent/control.rs index 5f1246bf5b..39534de645 100644 --- a/codex-rs/core/src/agent/control.rs +++ b/codex-rs/core/src/agent/control.rs @@ -680,7 +680,8 @@ fn agent_matches_prefix(agent_path: Option<&AgentPath>, prefix: &AgentPath) -> b pub(crate) fn render_input_preview(initial_operation: &Op) -> String { match initial_operation { - Op::UserInput { items, .. } => items + Op::UserInput { submission, .. } => submission + .items .iter() .map(|item| match item { UserInput::Text { text, .. } => text.clone(), diff --git a/codex-rs/core/src/agent/control_tests.rs b/codex-rs/core/src/agent/control_tests.rs index 410e1beaf6..c9c494436c 100644 --- a/codex-rs/core/src/agent/control_tests.rs +++ b/codex-rs/core/src/agent/control_tests.rs @@ -27,6 +27,7 @@ use codex_protocol::protocol::TurnAbortReason; use codex_protocol::protocol::TurnAbortedEvent; use codex_protocol::protocol::TurnCompleteEvent; use codex_protocol::protocol::TurnStartedEvent; +use codex_protocol::protocol::UserSubmission; use codex_thread_store::ArchiveThreadParams; use codex_thread_store::LocalThreadStore; use codex_thread_store::LocalThreadStoreConfig; @@ -460,13 +461,13 @@ async fn send_input_submits_user_message() { let expected = ( thread_id, Op::UserInput { - items: vec![UserInput::Text { - text: "hello from tests".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello from tests".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }, ); @@ -798,13 +799,13 @@ async fn spawn_agent_creates_thread_and_sends_prompt() { let expected = ( thread_id, Op::UserInput { - items: vec![UserInput::Text { - text: "spawned".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "spawned".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }, ); @@ -1021,13 +1022,13 @@ async fn spawn_agent_can_fork_parent_thread_history_with_sanitized_items() { let expected = ( child_thread_id, Op::UserInput { - items: vec![UserInput::Text { - text: "child task".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "child task".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }, ); diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index d31dc138b5..97cad55769 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -18,6 +18,7 @@ use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; use codex_protocol::protocol::Submission; use codex_protocol::protocol::ThreadSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionsArgs; use codex_protocol::request_permissions::RequestPermissionsEvent; @@ -206,10 +207,12 @@ pub(crate) async fn run_codex_thread_one_shot( // Send the initial input to kick off the one-shot turn. io.submit(Op::UserInput { - items: input, - final_output_json_schema, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: input, + final_output_json_schema, + responsesapi_client_metadata: None, + additional_context: Default::default(), + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index 9d96a2d60b..636433706d 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -27,6 +27,7 @@ use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; use codex_protocol::protocol::TokenUsage; +use codex_protocol::protocol::UserSubmission; use serde_json::Value; use tokio::sync::Mutex; use tokio::sync::Semaphore; @@ -761,10 +762,12 @@ async fn run_review_on_session( deadline, params.external_cancel.as_ref(), Box::pin(review_session.codex.submit(Op::UserInput { - items: prompt_items.items, - final_output_json_schema: Some(params.schema.clone()), - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: prompt_items.items, + final_output_json_schema: Some(params.schema.clone()), + responsesapi_client_metadata: None, + additional_context: Default::default(), + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(codex_protocol::protocol::TurnEnvironmentSelections::new( parent_turn_legacy_fallback_cwd, diff --git a/codex-rs/core/src/session/handlers.rs b/codex-rs/core/src/session/handlers.rs index 4ed79d04e3..2b648a46ef 100644 --- a/codex-rs/core/src/session/handlers.rs +++ b/codex-rs/core/src/session/handlers.rs @@ -45,6 +45,7 @@ use codex_protocol::protocol::ThreadSettingsAppliedEvent; use codex_protocol::protocol::ThreadSettingsOverrides; use codex_protocol::protocol::ThreadSettingsSnapshot; use codex_protocol::protocol::TurnAbortReason; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::WarningEvent; use codex_protocol::request_permissions::RequestPermissionsResponse; use codex_protocol::request_user_input::RequestUserInputResponse; @@ -187,15 +188,18 @@ pub(super) async fn user_input_or_turn_inner( client_user_message_id: Option, ) { let Op::UserInput { - items, - final_output_json_schema, - responsesapi_client_metadata, - additional_context, + submission, thread_settings, } = op else { unreachable!(); }; + let UserSubmission { + items, + final_output_json_schema, + responsesapi_client_metadata, + additional_context, + } = submission; let emit_thread_settings_applied = thread_settings != ThreadSettingsOverrides::default(); let mut updates = if emit_thread_settings_applied { thread_settings_update(sess, thread_settings).await diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 207f7eab9e..ead2c43444 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -372,6 +372,7 @@ use codex_protocol::protocol::TokenCountEvent; use codex_protocol::protocol::TokenUsage; use codex_protocol::protocol::TokenUsageInfo; use codex_protocol::protocol::TurnModerationMetadataEvent; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::WarningEvent; use codex_protocol::user_input::UserInput; use codex_tools::ToolEnvironmentMode; @@ -1136,13 +1137,13 @@ impl Session { self, self.next_internal_sub_id(), Op::UserInput { - items: vec![UserInput::Text { - text, - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text, + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }, /*client_user_message_id*/ None, diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 5086fd63bd..a0d067d7fd 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -58,6 +58,7 @@ use codex_protocol::permissions::FileSystemSpecialPath; use codex_protocol::protocol::NonSteerableTurnKind; use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::TurnEnvironmentSelections; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_utils_path_uri::PathUri; @@ -2582,13 +2583,13 @@ async fn fork_startup_context_then_first_turn_diff_snapshot() -> anyhow::Result< initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "fork seed".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "fork seed".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2627,13 +2628,13 @@ async fn fork_startup_context_then_first_turn_diff_snapshot() -> anyhow::Result< forked .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after fork".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after fork".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: ThreadSettingsOverrides { approval_policy: Some(AskForApproval::Never), collaboration_mode: Some(collaboration_mode), @@ -6130,10 +6131,10 @@ fn submission_dispatch_span_uses_debug_for_realtime_audio() { fn op_kind_for_input_and_context_ops() { assert_eq!( Op::UserInput { - items: vec![], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![], + ..Default::default() + }, thread_settings: Default::default(), } .kind(), @@ -6157,13 +6158,13 @@ async fn user_turn_updates_approvals_reviewer() { &session, "sub-1".to_string(), Op::UserInput { - items: vec![UserInput::Text { - text: "hello".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(config.cwd.clone())), approval_policy: Some(config.permissions.approval_policy.value()), diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index 8c3ea14325..2f68ba5756 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -52,6 +52,7 @@ use codex_protocol::protocol::SubAgentSource; use codex_protocol::protocol::TurnAbortReason; use codex_protocol::protocol::TurnAbortedEvent; use codex_protocol::protocol::TurnCompleteEvent; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_state::DirectionalThreadSpawnEdgeStatus; use core_test_support::TempDirExt; @@ -2675,19 +2676,19 @@ async fn send_input_accepts_structured_items() { .expect("send_input should succeed"); let expected = Op::UserInput { - items: vec![ - UserInput::Mention { - name: "drive".to_string(), - path: "app://google_drive".to_string(), - }, - UserInput::Text { - text: "read the folder".to_string(), - text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::Mention { + name: "drive".to_string(), + path: "app://google_drive".to_string(), + }, + UserInput::Text { + text: "read the folder".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, thread_settings: Default::default(), }; let captured = manager diff --git a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs index 2186a4a6d6..e715600fdf 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs @@ -108,8 +108,9 @@ async fn handle_spawn_agent( session.services.agent_control.spawn_agent_with_metadata( config, match initial_operation { - Op::UserInput { items, .. } - if items + Op::UserInput { submission, .. } + if submission + .items .iter() .all(|item| matches!(item, UserInput::Text { .. })) => { diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index bdac7fddcb..c6233d0243 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -45,6 +45,7 @@ use codex_protocol::protocol::SessionConfiguredEvent; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::TurnEnvironmentSelection; use codex_protocol::protocol::TurnEnvironmentSelections; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_path_uri::PathUri; @@ -845,13 +846,13 @@ impl TestCodex { }); self.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: turn_environment_selections, approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/remote_env_windows/remote_env_windows_test.rs b/codex-rs/core/tests/remote_env_windows/remote_env_windows_test.rs index 24efb8e7ed..f97c7db06c 100644 --- a/codex-rs/core/tests/remote_env_windows/remote_env_windows_test.rs +++ b/codex-rs/core/tests/remote_env_windows/remote_env_windows_test.rs @@ -12,9 +12,10 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecCommandStatus; -use codex_protocol::protocol::Op; use codex_protocol::protocol::TurnEnvironmentSelection; use codex_protocol::protocol::TurnEnvironmentSelections; +use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; @@ -88,13 +89,13 @@ async fn windows_exec_server_runs_with_native_shell_and_cwd() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run the Windows smoke command".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run the Windows smoke command".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(environments), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/abort_tasks.rs b/codex-rs/core/tests/suite/abort_tasks.rs index d44b4e5a23..aefafabe30 100644 --- a/codex-rs/core/tests/suite/abort_tasks.rs +++ b/codex-rs/core/tests/suite/abort_tasks.rs @@ -4,6 +4,7 @@ use std::time::Duration; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_function_call; @@ -46,13 +47,13 @@ async fn interrupt_long_running_tool_emits_turn_aborted() { // Kick off a turn that triggers the function call. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start sleep".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start sleep".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -103,13 +104,13 @@ async fn interrupt_tool_records_history_entries() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start history recording".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start history recording".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -124,13 +125,13 @@ async fn interrupt_tool_records_history_entries() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "follow up".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "follow up".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -207,13 +208,13 @@ async fn interrupt_persists_turn_aborted_marker_in_next_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start interrupt marker".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start interrupt marker".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -228,13 +229,13 @@ async fn interrupt_persists_turn_aborted_marker_in_next_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "follow up".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "follow up".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/additional_context.rs b/codex-rs/core/tests/suite/additional_context.rs index 6812be95e4..fb3b39274d 100644 --- a/codex-rs/core/tests/suite/additional_context.rs +++ b/codex-rs/core/tests/suite/additional_context.rs @@ -5,6 +5,7 @@ use codex_protocol::protocol::AdditionalContextKind; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ItemCompletedEvent; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::context_snapshot; use core_test_support::context_snapshot::ContextSnapshotOptions; @@ -37,28 +38,30 @@ async fn additional_context_is_model_visible_but_not_a_user_message_item() -> Re test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "inspect the active tab".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "browser_info".to_string(), - AdditionalContextEntry { - value: "tab one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: "run one".to_string(), - kind: AdditionalContextKind::Application, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "inspect the active tab".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "browser_info".to_string(), + AdditionalContextEntry { + value: "tab one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: "run one".to_string(), + kind: AdditionalContextKind::Application, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; @@ -135,10 +138,12 @@ async fn external_context_like_user_text_remains_a_user_message_item() -> Result test.codex .submit(Op::UserInput { - items: vec![user_input.clone()], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::new(), + submission: UserSubmission { + items: vec![user_input.clone()], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::new(), + }, thread_settings: Default::default(), }) .await?; @@ -180,28 +185,30 @@ async fn additional_context_trust_controls_message_role() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "inspect context".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "browser_info".to_string(), - AdditionalContextEntry { - value: "tab one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: "run one".to_string(), - kind: AdditionalContextKind::Application, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "inspect context".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "browser_info".to_string(), + AdditionalContextEntry { + value: "tab one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: "run one".to_string(), + kind: AdditionalContextKind::Application, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; @@ -260,13 +267,15 @@ async fn additional_context_is_deduplicated_between_turns_while_retained() -> Re test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: additional_context.clone(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: additional_context.clone(), + }, thread_settings: Default::default(), }) .await?; @@ -277,13 +286,15 @@ async fn additional_context_is_deduplicated_between_turns_while_retained() -> Re test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "second turn".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context, + submission: UserSubmission { + items: vec![UserInput::Text { + text: "second turn".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context, + }, thread_settings: Default::default(), }) .await?; @@ -338,28 +349,30 @@ async fn additional_context_removes_one_value_while_adding_another() -> Result<( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: "run one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "browser_info".to_string(), - AdditionalContextEntry { - value: "tab one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: "run one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "browser_info".to_string(), + AdditionalContextEntry { + value: "tab one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; @@ -370,28 +383,30 @@ async fn additional_context_removes_one_value_while_adding_another() -> Result<( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "second turn".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: "run one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "terminal_info".to_string(), - AdditionalContextEntry { - value: "pty one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "second turn".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: "run one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "terminal_info".to_string(), + AdditionalContextEntry { + value: "pty one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; @@ -402,35 +417,37 @@ async fn additional_context_removes_one_value_while_adding_another() -> Result<( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "third turn".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: "run one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "browser_info".to_string(), - AdditionalContextEntry { - value: "tab one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ( - "terminal_info".to_string(), - AdditionalContextEntry { - value: "pty one".to_string(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "third turn".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: "run one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "browser_info".to_string(), + AdditionalContextEntry { + value: "tab one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ( + "terminal_info".to_string(), + AdditionalContextEntry { + value: "pty one".to_string(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; @@ -498,28 +515,30 @@ async fn additional_context_values_are_truncated_before_model_input() -> Result< test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "summarize context".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: BTreeMap::from([ - ( - "automation_info".to_string(), - AdditionalContextEntry { - value: long_automation_value.clone(), - kind: AdditionalContextKind::Application, - }, - ), - ( - "browser_info".to_string(), - AdditionalContextEntry { - value: long_browser_value.clone(), - kind: AdditionalContextKind::Untrusted, - }, - ), - ]), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "summarize context".to_string(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + responsesapi_client_metadata: None, + additional_context: BTreeMap::from([ + ( + "automation_info".to_string(), + AdditionalContextEntry { + value: long_automation_value.clone(), + kind: AdditionalContextKind::Application, + }, + ), + ( + "browser_info".to_string(), + AdditionalContextEntry { + value: long_browser_value.clone(), + kind: AdditionalContextKind::Untrusted, + }, + ), + ]), + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/agents_md.rs b/codex-rs/core/tests/suite/agents_md.rs index a4ab404065..92f8d7db02 100644 --- a/codex-rs/core/tests/suite/agents_md.rs +++ b/codex-rs/core/tests/suite/agents_md.rs @@ -11,6 +11,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::InitialHistory; use codex_protocol::protocol::Op; use codex_protocol::protocol::TurnEnvironmentSelection; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_path_uri::PathUri; @@ -103,13 +104,13 @@ fn assert_single_instruction_fragment(request: &responses::ResponsesRequest, exp async fn submit_thread_turn(thread: &Arc, prompt: &str) -> Result<()> { thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -459,13 +460,13 @@ async fn loads_user_instructions_without_a_primary_environment() -> Result<()> { no_environment_thread .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "inspect global instructions without an environment".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "inspect global instructions without an environment".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -908,13 +909,13 @@ async fn fork_replays_rendered_instructions_from_shared_history() -> Result<()> forked .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "continue fork".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "continue fork".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/apply_patch_cli.rs b/codex-rs/core/tests/suite/apply_patch_cli.rs index 2527e4cb93..3ba3485f18 100644 --- a/codex-rs/core/tests/suite/apply_patch_cli.rs +++ b/codex-rs/core/tests/suite/apply_patch_cli.rs @@ -31,6 +31,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::TurnEnvironmentSelection; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; #[cfg(target_os = "linux")] use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0; @@ -97,13 +98,13 @@ async fn submit_without_wait_with_turn_permissions( let session_model = test.session_configured.model.clone(); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { approval_policy: Some(AskForApproval::Never), sandbox_policy: Some(sandbox_policy), @@ -1646,13 +1647,13 @@ async fn apply_patch_turn_diff_tracks_local_and_remote_environment_paths() -> Re ]; test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "apply matching patches to local and remote environments".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "apply matching patches to local and remote environments".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(codex_protocol::protocol::TurnEnvironmentSelections::new( test.config.cwd.clone(), diff --git a/codex-rs/core/tests/suite/approvals.rs b/codex-rs/core/tests/suite/approvals.rs index 422fd28260..a33cf785ae 100644 --- a/codex-rs/core/tests/suite/approvals.rs +++ b/codex-rs/core/tests/suite/approvals.rs @@ -25,6 +25,7 @@ use codex_protocol::protocol::GranularApprovalConfig; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; use codex_protocol::protocol::SandboxPolicy; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::managed_network_requirements_loader; use core_test_support::responses::ev_apply_patch_custom_tool_call; @@ -655,13 +656,13 @@ async fn submit_turn( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), @@ -2615,13 +2616,13 @@ async fn env_zsh_script_spawned_by_python_can_request_escalation_under_zsh_fork( turn_permission_fields(permission_profile, test.cwd.path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run nested env zsh script through python".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run nested env zsh script through python".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), @@ -2759,13 +2760,13 @@ async fn matched_prefix_rule_runs_unsandboxed_under_zsh_fork() -> Result<()> { turn_permission_fields(permission_profile, test.cwd.path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run allowed touch under zsh fork".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run allowed touch under zsh fork".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), @@ -3350,13 +3351,13 @@ allow_local_binding = true let session_model = test.session_configured.model.clone(); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "deny-read network retry".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "deny-read network retry".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/auto_review.rs b/codex-rs/core/tests/suite/auto_review.rs index 4dd3effe49..456ba49775 100644 --- a/codex-rs/core/tests/suite/auto_review.rs +++ b/codex-rs/core/tests/suite/auto_review.rs @@ -17,6 +17,7 @@ use codex_protocol::openai_models::default_input_modalities; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionsResponse; use codex_protocol::user_input::UserInput; @@ -155,13 +156,13 @@ async fn remote_model_override_uses_catalog_model_for_strict_auto_review() -> Re turn_permission_fields(PermissionProfile::read_only(), cwd_path.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run the Guardian model override check".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run the Guardian model override check".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::OnRequest), diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index c5dfd96cf6..003b69bbce 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -48,6 +48,7 @@ use codex_protocol::protocol::RolloutLine; use codex_protocol::protocol::SessionMeta; use codex_protocol::protocol::SessionMetaLine; use codex_protocol::protocol::SessionSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::PathBufExt; use core_test_support::TestCodexResponsesRequestKind; @@ -193,13 +194,13 @@ async fn non_openai_responses_requests_omit_item_turn_metadata() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -490,13 +491,13 @@ async fn resume_includes_initial_messages_and_sends_prior_items() { // 2) Submit new input; the request body must include the prior items, then initial context, then new user input. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -865,13 +866,13 @@ async fn includes_session_id_thread_id_and_model_headers_in_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1079,13 +1080,13 @@ async fn includes_base_instructions_override_in_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1136,13 +1137,13 @@ async fn chatgpt_auth_sends_correct_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1264,13 +1265,13 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1303,13 +1304,13 @@ async fn includes_user_instructions_message_in_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1391,13 +1392,13 @@ async fn includes_apps_guidance_as_developer_message_for_chatgpt_auth() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1454,13 +1455,13 @@ async fn omits_apps_guidance_for_api_key_auth_even_when_feature_enabled() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1513,13 +1514,13 @@ async fn omits_apps_guidance_when_configured_off() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1555,13 +1556,13 @@ async fn omits_environment_context_when_configured_off() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1612,13 +1613,13 @@ async fn skills_append_to_developer_message() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1695,13 +1696,13 @@ async fn skills_use_aliases_in_developer_message_under_budget_pressure() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1756,13 +1757,13 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1798,13 +1799,13 @@ async fn includes_no_effort_in_request() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1841,13 +1842,13 @@ async fn includes_default_reasoning_effort_in_request_when_defined_by_model_info codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1892,13 +1893,13 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(config.cwd.clone())), approval_policy: Some(config.permissions.approval_policy.value()), @@ -1948,13 +1949,13 @@ async fn configured_reasoning_summary_is_sent() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2004,13 +2005,13 @@ async fn responses_lite_sets_all_turns_context_and_disables_parallel_tool_calls( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2066,13 +2067,13 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(config.cwd.clone())), approval_policy: Some(config.permissions.approval_policy.value()), @@ -2126,13 +2127,13 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2184,13 +2185,13 @@ async fn reasoning_summary_none_overrides_model_catalog_default() -> anyhow::Res codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2223,13 +2224,13 @@ async fn includes_default_verbosity_in_request() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2271,13 +2272,13 @@ async fn configured_verbosity_not_sent_for_models_without_support() -> anyhow::R codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2318,13 +2319,13 @@ async fn configured_verbosity_is_sent() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2372,13 +2373,13 @@ async fn includes_developer_instructions_message_in_request() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2675,13 +2676,13 @@ async fn token_count_includes_rate_limits_snapshot() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2816,13 +2817,13 @@ async fn usage_limit_error_emits_rate_limit_event() -> anyhow::Result<()> { let submission_id = codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2893,13 +2894,13 @@ async fn context_window_error_sets_total_tokens_to_model_window() -> anyhow::Res codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "seed turn".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "seed turn".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2908,13 +2909,13 @@ async fn context_window_error_sets_total_tokens_to_model_window() -> anyhow::Res codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "trigger context window".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "trigger context window".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2993,13 +2994,13 @@ async fn incomplete_response_emits_content_filter_error_message() -> anyhow::Res .await?; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "trigger incomplete".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "trigger incomplete".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3104,13 +3105,13 @@ async fn azure_overrides_assign_properties_used_for_responses_url() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3193,13 +3194,13 @@ async fn env_var_overrides_loaded_auth() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3250,13 +3251,13 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { // Turn 1: user sends U1; wait for completion. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "U1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "U1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3266,13 +3267,13 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { // Turn 2: user sends U2; wait for completion. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "U2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "U2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3282,13 +3283,13 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { // Turn 3: user sends U3; wait for completion. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "U3".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "U3".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/client_websockets.rs b/codex-rs/core/tests/suite/client_websockets.rs index cee54e24b3..bdd9d5cdac 100755 --- a/codex-rs/core/tests/suite/client_websockets.rs +++ b/codex-rs/core/tests/suite/client_websockets.rs @@ -29,6 +29,7 @@ use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::SessionSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::W3cTraceContext; use codex_protocol::user_input::UserInput; use codex_rollout_trace::ConversationPart; @@ -1345,13 +1346,13 @@ async fn responses_websocket_usage_limit_error_emits_rate_limit_event() { let submission_id = test .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1435,13 +1436,13 @@ async fn responses_websocket_invalid_request_error_with_status_is_forwarded() { let submission_id = test .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index e436b6fa9b..16be45db37 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -21,6 +21,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_web_search_extension::install as install_web_search_extension; use core_test_support::apps_test_server::AppsTestServer; @@ -3404,13 +3405,13 @@ text( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "use exec to inspect and call hidden tools".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "use exec to inspect and call hidden tools".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(codex_protocol::protocol::TurnEnvironmentSelections::new( cwd, diff --git a/codex-rs/core/tests/suite/collaboration_instructions.rs b/codex-rs/core/tests/suite/collaboration_instructions.rs index d9d511edbd..df434288f1 100644 --- a/codex-rs/core/tests/suite/collaboration_instructions.rs +++ b/codex-rs/core/tests/suite/collaboration_instructions.rs @@ -6,6 +6,7 @@ use codex_protocol::protocol::COLLABORATION_MODE_CLOSE_TAG; use codex_protocol::protocol::COLLABORATION_MODE_OPEN_TAG; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -73,13 +74,13 @@ async fn no_collaboration_instructions_by_default() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -127,13 +128,13 @@ async fn user_input_includes_collaboration_instructions_after_override() -> Resu test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -164,13 +165,13 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(test.config.permissions.approval_policy.value()), @@ -214,13 +215,13 @@ async fn collaboration_instructions_omitted_when_disabled() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(test.config.permissions.approval_policy.value()), @@ -273,13 +274,13 @@ async fn override_then_next_turn_uses_updated_collaboration_instructions() -> Re test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -321,13 +322,13 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(test.config.permissions.approval_policy.value()), @@ -385,13 +386,13 @@ async fn collaboration_mode_update_emits_new_instruction_message() -> Result<()> test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -408,13 +409,13 @@ async fn collaboration_mode_update_emits_new_instruction_message() -> Result<()> test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -460,13 +461,13 @@ async fn collaboration_mode_update_noop_does_not_append() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -483,13 +484,13 @@ async fn collaboration_mode_update_noop_does_not_append() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -537,13 +538,13 @@ async fn collaboration_mode_update_emits_new_instruction_message_when_mode_chang test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -563,13 +564,13 @@ async fn collaboration_mode_update_emits_new_instruction_message_when_mode_chang test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -618,13 +619,13 @@ async fn collaboration_mode_update_noop_does_not_append_when_mode_is_unchanged() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -644,13 +645,13 @@ async fn collaboration_mode_update_noop_does_not_append_when_mode_is_unchanged() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -702,13 +703,13 @@ async fn resume_replays_collaboration_instructions() -> Result<()> { initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -718,13 +719,13 @@ async fn resume_replays_collaboration_instructions() -> Result<()> { resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after resume".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after resume".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -770,13 +771,13 @@ async fn empty_collaboration_instructions_are_ignored() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index cff88f57a8..5391506a20 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -22,6 +22,7 @@ use codex_protocol::protocol::ItemStartedEvent; use codex_protocol::protocol::Op; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::WarningEvent; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; @@ -103,13 +104,13 @@ fn disabled_permission_user_turn(text: impl Into, cwd: PathBuf, model: S let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); Op::UserInput { - items: vec![UserInput::Text { - text: text.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), @@ -500,13 +501,13 @@ async fn summarize_context_three_requests_and_instructions() { // 1) Normal user input – should hit server once. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello world".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello world".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -525,13 +526,13 @@ async fn summarize_context_three_requests_and_instructions() { // 3) Next user input – third hit; history should include only the summary. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: THIRD_USER_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: THIRD_USER_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -695,13 +696,13 @@ async fn manual_pre_compact_block_decision_does_not_block_compaction() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello before blocked compact".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello before blocked compact".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -768,13 +769,13 @@ async fn compact_hooks_respect_matchers_and_post_runs_after_compaction() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello before matched compact".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello before matched compact".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -838,13 +839,13 @@ async fn manual_compact_uses_custom_prompt() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -985,13 +986,13 @@ async fn manual_compact_emits_context_compaction_items() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "manual compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "manual compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1151,13 +1152,13 @@ async fn multiple_auto_compact_per_task_runs_after_token_limit_hit() { // Start the conversation with the user message codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1623,13 +1624,13 @@ async fn auto_compact_runs_after_token_limit_hit() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: FIRST_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: FIRST_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1639,13 +1640,13 @@ async fn auto_compact_runs_after_token_limit_hit() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: SECOND_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: SECOND_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1655,13 +1656,13 @@ async fn auto_compact_runs_after_token_limit_hit() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: POST_AUTO_USER_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: POST_AUTO_USER_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1826,13 +1827,13 @@ async fn auto_compact_emits_context_compaction_items() { for user in [FIRST_AUTO_MSG, SECOND_AUTO_MSG, POST_AUTO_USER_MSG] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1907,13 +1908,13 @@ async fn auto_compact_starts_after_turn_started() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: FIRST_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: FIRST_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1922,13 +1923,13 @@ async fn auto_compact_starts_after_turn_started() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: SECOND_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: SECOND_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1937,13 +1938,13 @@ async fn auto_compact_starts_after_turn_started() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: POST_AUTO_USER_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: POST_AUTO_USER_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2926,13 +2927,13 @@ async fn auto_compact_persists_rollout_entries() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: FIRST_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: FIRST_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2941,13 +2942,13 @@ async fn auto_compact_persists_rollout_entries() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: SECOND_AUTO_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: SECOND_AUTO_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -2956,13 +2957,13 @@ async fn auto_compact_persists_rollout_entries() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: POST_AUTO_USER_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: POST_AUTO_USER_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3040,13 +3041,13 @@ async fn manual_compact_retries_after_context_window_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3144,13 +3145,13 @@ async fn manual_compact_non_context_failure_retries_then_emits_task_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3239,13 +3240,13 @@ async fn manual_compact_twice_preserves_latest_user_messages() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3257,13 +3258,13 @@ async fn manual_compact_twice_preserves_latest_user_messages() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3275,13 +3276,13 @@ async fn manual_compact_twice_preserves_latest_user_messages() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: final_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: final_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3482,13 +3483,13 @@ async fn auto_compact_allows_multiple_attempts_when_interleaved_with_other_turn_ for user in [MULTI_AUTO_MSG, follow_up_user, final_user] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -3587,13 +3588,13 @@ async fn snapshot_request_shape_mid_turn_continuation_compaction() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: FUNCTION_CALL_LIMIT_MSG.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: FUNCTION_CALL_LIMIT_MSG.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4021,13 +4022,13 @@ async fn auto_compact_counts_encrypted_reasoning_before_last_user() { { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4143,13 +4144,13 @@ async fn auto_compact_runs_when_reasoning_header_clears_between_turns() { for user in [first_user, second_user, third_user] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4205,13 +4206,13 @@ async fn snapshot_request_shape_pre_turn_compaction_including_incoming_user_mess for user in ["USER_ONE", "USER_TWO"] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4233,19 +4234,19 @@ async fn snapshot_request_shape_pre_turn_compaction_including_incoming_user_mess .to_string(); codex .submit(Op::UserInput { - items: vec![ - UserInput::Image { - image_url: image_url.clone(), - detail: None, - }, - UserInput::Text { - text: "USER_THREE".to_string(), - text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::Image { + image_url: image_url.clone(), + detail: None, + }, + UserInput::Text { + text: "USER_THREE".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4428,13 +4429,13 @@ async fn snapshot_request_shape_pre_turn_compaction_context_window_exceeded() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4443,13 +4444,13 @@ async fn snapshot_request_shape_pre_turn_compaction_context_window_exceeded() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -4516,13 +4517,13 @@ async fn snapshot_request_shape_manual_compact_without_previous_user_messages() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "AFTER_MANUAL_EMPTY_COMPACT".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "AFTER_MANUAL_EMPTY_COMPACT".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/compact_remote.rs b/codex-rs/core/tests/suite/compact_remote.rs index f9b35f686a..c5ec61f7f9 100644 --- a/codex-rs/core/tests/suite/compact_remote.rs +++ b/codex-rs/core/tests/suite/compact_remote.rs @@ -23,6 +23,7 @@ use codex_protocol::protocol::RealtimeEvent; use codex_protocol::protocol::RealtimeOutputModality; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::PathBufExt; use core_test_support::apps_test_server::configure_search_capable_model; @@ -340,13 +341,13 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -357,13 +358,13 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -603,33 +604,47 @@ async fn assert_remote_manual_compact_request_parity( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "TURN_ONE_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), - thread_settings: Default::default(), - }) - .await?; - wait_for_turn_complete(&codex).await; - - codex - .submit(Op::UserInput { - items: vec![ - UserInput::Text { - text: "TURN_TWO_PREFIX".to_string(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "TURN_ONE_USER".to_string(), text_elements: Vec::new(), - }, - UserInput::Text { - text: "TURN_TWO_SUFFIX".to_string(), + }], + ..Default::default() + }, + thread_settings: Default::default(), + }) + .await?; + wait_for_turn_complete(&codex).await; + + codex + .submit(Op::UserInput { + submission: UserSubmission { + items: vec![ + UserInput::Text { + text: "TURN_TWO_PREFIX".to_string(), + text_elements: Vec::new(), + }, + UserInput::Text { + text: "TURN_TWO_SUFFIX".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, + thread_settings: Default::default(), + }) + .await?; + wait_for_turn_complete(&codex).await; + + codex + .submit(Op::UserInput { + submission: UserSubmission { + items: vec![UserInput::Text { + text: "TURN_THREE_TOOL_USER".to_string(), text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -637,13 +652,19 @@ async fn assert_remote_manual_compact_request_parity( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "TURN_THREE_TOOL_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::Image { + image_url, + detail: None, + }, + UserInput::Text { + text: "TURN_FOUR_IMAGE_USER".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -651,33 +672,13 @@ async fn assert_remote_manual_compact_request_parity( codex .submit(Op::UserInput { - items: vec![ - UserInput::Image { - image_url, - detail: None, - }, - UserInput::Text { - text: "TURN_FOUR_IMAGE_USER".to_string(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "TURN_FIVE_USER".to_string(), text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), - thread_settings: Default::default(), - }) - .await?; - wait_for_turn_complete(&codex).await; - - codex - .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "TURN_FIVE_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -839,13 +840,13 @@ async fn remote_compact_v2_reuses_compaction_trigger_for_followups() -> Result<( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -856,13 +857,13 @@ async fn remote_compact_v2_reuses_compaction_trigger_for_followups() -> Result<( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -987,13 +988,13 @@ async fn remote_compact_v2_retries_failures_with_stream_retry_budget() -> Result codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1004,13 +1005,13 @@ async fn remote_compact_v2_retries_failures_with_stream_retry_budget() -> Result codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1090,13 +1091,13 @@ async fn remote_compact_v2_accepts_additional_output_items_before_compaction() - codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1107,13 +1108,13 @@ async fn remote_compact_v2_accepts_additional_output_items_before_compaction() - codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1196,13 +1197,13 @@ async fn remote_compact_filters_deferred_dynamic_tools() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1268,13 +1269,13 @@ async fn remote_compact_runs_automatically() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1405,13 +1406,13 @@ async fn remote_compact_trims_function_call_history_to_fit_context_window() -> R codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1419,13 +1420,13 @@ async fn remote_compact_trims_function_call_history_to_fit_context_window() -> R codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1533,13 +1534,13 @@ async fn remote_compact_rewrites_multiple_trailing_function_call_outputs() -> Re codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1547,13 +1548,13 @@ async fn remote_compact_rewrites_multiple_trailing_function_call_outputs() -> Re codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1659,13 +1660,13 @@ async fn auto_remote_compact_trims_function_call_history_to_fit_context_window() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1673,13 +1674,13 @@ async fn auto_remote_compact_trims_function_call_history_to_fit_context_window() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1693,13 +1694,13 @@ async fn auto_remote_compact_trims_function_call_history_to_fit_context_window() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "turn that triggers auto compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "turn that triggers auto compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1821,13 +1822,13 @@ async fn remote_compact_trims_tool_search_output_to_empty_tools_array() -> Resul codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Find the oversized deferred tool".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Find the oversized deferred tool".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1901,13 +1902,13 @@ async fn auto_remote_compact_failure_stops_agent_loop() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "turn that exceeds token threshold".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "turn that exceeds token threshold".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1915,13 +1916,13 @@ async fn auto_remote_compact_failure_stops_agent_loop() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "turn that triggers auto compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "turn that triggers auto compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2009,13 +2010,13 @@ async fn remote_compact_trim_estimate_uses_session_base_instructions() -> Result baseline_codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2026,13 +2027,13 @@ async fn remote_compact_trim_estimate_uses_session_base_instructions() -> Result baseline_codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2117,13 +2118,13 @@ async fn remote_compact_trim_estimate_uses_session_base_instructions() -> Result override_codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: first_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: first_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2134,13 +2135,13 @@ async fn remote_compact_trim_estimate_uses_session_base_instructions() -> Result override_codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: second_user_message.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: second_user_message.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2210,13 +2211,13 @@ async fn remote_manual_compact_emits_context_compaction_items() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "manual remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "manual remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2291,13 +2292,13 @@ async fn remote_manual_compact_failure_emits_task_error_event() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "manual remote compact".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "manual remote compact".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2377,13 +2378,13 @@ async fn remote_compact_persists_replacement_history_in_rollout() -> Result<()> codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "needs compaction".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "needs compaction".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2524,13 +2525,13 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start remote compact flow".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start remote compact flow".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2542,13 +2543,13 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact in same session".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact in same session".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2567,13 +2568,13 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after resume".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after resume".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2665,13 +2666,13 @@ async fn remote_compact_refreshes_stale_developer_instructions_without_resume() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start remote compact flow".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start remote compact flow".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2682,13 +2683,13 @@ async fn remote_compact_refreshes_stale_developer_instructions_without_resume() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after compact in same session".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after compact in same session".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2754,13 +2755,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_sta test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2768,13 +2769,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_sta test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2835,13 +2836,13 @@ async fn remote_request_uses_custom_experimental_realtime_start_instructions() - test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2896,13 +2897,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_end test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2912,13 +2913,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_end test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -2987,13 +2988,13 @@ async fn snapshot_request_shape_remote_manual_compact_restates_realtime_start() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3004,13 +3005,13 @@ async fn snapshot_request_shape_remote_manual_compact_restates_realtime_start() test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3087,13 +3088,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_does_not_restate_real test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "SETUP_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "SETUP_USER".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3103,13 +3104,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_does_not_restate_real test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3194,13 +3195,13 @@ async fn snapshot_request_shape_remote_compact_resume_restates_realtime_end() -> initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3224,13 +3225,13 @@ async fn snapshot_request_shape_remote_compact_resume_restates_realtime_end() -> resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3315,13 +3316,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_including_incoming_us } codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3402,13 +3403,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "BEFORE_SWITCH_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "BEFORE_SWITCH_USER".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3424,13 +3425,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model .await?; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "AFTER_SWITCH_USER".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "AFTER_SWITCH_USER".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3543,13 +3544,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_context_window_exceed codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3557,13 +3558,13 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_context_window_exceed codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3649,13 +3650,13 @@ async fn remote_pre_turn_compact_response_seeds_turn_state() -> Result<()> { for text in ["BEFORE_COMPACT_USER", "AFTER_COMPACT_USER"] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3725,13 +3726,13 @@ async fn remote_mid_turn_compact_v1_sends_turn_state_over_http() -> Result<()> { // Phase 1: sampling mints state and crosses the token limit with a pending tool follow-up. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "RUN_WITH_MID_TURN_COMPACT".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "RUN_WITH_MID_TURN_COMPACT".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3810,13 +3811,13 @@ async fn remote_mid_turn_compact_v2_sends_turn_state_over_http() -> Result<()> { // Phase 1: sampling mints state and schedules inline v2 compaction. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "RUN_WITH_MID_TURN_COMPACT_V2".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "RUN_WITH_MID_TURN_COMPACT_V2".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3913,13 +3914,13 @@ async fn remote_mid_turn_compact_v2_sends_turn_state_over_websocket() -> Result< // inline v2 compaction. test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "RUN_WITH_WS_MID_TURN_COMPACT_V2".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "RUN_WITH_WS_MID_TURN_COMPACT_V2".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3991,13 +3992,13 @@ async fn snapshot_request_shape_remote_mid_turn_continuation_compaction() -> Res codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -4070,13 +4071,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_summary_only_reinject codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -4156,13 +4157,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_multi_summary_reinjec codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -4173,13 +4174,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_multi_summary_reinjec codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_TWO".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_TWO".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -4255,13 +4256,13 @@ async fn snapshot_request_shape_remote_manual_compact_without_previous_user_mess codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "USER_ONE".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "USER_ONE".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/compact_remote_parity.rs b/codex-rs/core/tests/suite/compact_remote_parity.rs index 432e5815aa..e6b013f1a1 100644 --- a/codex-rs/core/tests/suite/compact_remote_parity.rs +++ b/codex-rs/core/tests/suite/compact_remote_parity.rs @@ -10,6 +10,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::hooks::trust_discovered_hooks; use core_test_support::responses; @@ -605,10 +606,10 @@ async fn capture_from_requests( async fn submit_user_input(codex: &codex_core::CodexThread, items: Vec) -> Result<()> { codex .submit(Op::UserInput { - items, - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items, + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/compact_resume_fork.rs b/codex-rs/core/tests/suite/compact_resume_fork.rs index 909dfb8c82..70db162b15 100644 --- a/codex-rs/core/tests/suite/compact_resume_fork.rs +++ b/codex-rs/core/tests/suite/compact_resume_fork.rs @@ -19,6 +19,7 @@ use codex_protocol::config_types::ModeKind; use codex_protocol::config_types::Settings; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::WarningEvent; use codex_protocol::user_input::UserInput; use core_test_support::context_snapshot; @@ -773,13 +774,13 @@ async fn start_test_conversation( async fn user_turn(conversation: &Arc, text: &str) { conversation .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/exec_policy.rs b/codex-rs/core/tests/suite/exec_policy.rs index 4e64c66b0a..31e0ebc436 100644 --- a/codex-rs/core/tests/suite/exec_policy.rs +++ b/codex-rs/core/tests/suite/exec_policy.rs @@ -9,6 +9,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; @@ -48,13 +49,13 @@ async fn submit_user_turn( turn_permission_fields(permission_profile, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), @@ -208,13 +209,13 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run shell command".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run shell command".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/extension_sandbox.rs b/codex-rs/core/tests/suite/extension_sandbox.rs index e4c01557de..7724bbb970 100644 --- a/codex-rs/core/tests/suite/extension_sandbox.rs +++ b/codex-rs/core/tests/suite/extension_sandbox.rs @@ -22,6 +22,7 @@ use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_protocol::request_permissions::RequestPermissionsResponse; @@ -242,13 +243,13 @@ async fn extension_tool_uses_granted_turn_permissions() -> Result<()> { turn_permission_fields(base_permission_profile, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "request access and edit the image".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "request access and edit the image".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::OnRequest), diff --git a/codex-rs/core/tests/suite/fork_thread.rs b/codex-rs/core/tests/suite/fork_thread.rs index a1fdf79a8e..3a8ea5b078 100644 --- a/codex-rs/core/tests/suite/fork_thread.rs +++ b/codex-rs/core/tests/suite/fork_thread.rs @@ -8,6 +8,7 @@ use codex_protocol::protocol::Op; use codex_protocol::protocol::ResumedHistory; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -50,13 +51,13 @@ async fn fork_thread_twice_drops_to_first_message() { for text in ["first", "second", "third"] { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -172,13 +173,13 @@ async fn fork_thread_from_history_does_not_require_source_rollout_path() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "fork me from stored history".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "fork me from stored history".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/guardian_review.rs b/codex-rs/core/tests/suite/guardian_review.rs index ae87350c39..b503a7c87d 100644 --- a/codex-rs/core/tests/suite/guardian_review.rs +++ b/codex-rs/core/tests/suite/guardian_review.rs @@ -8,6 +8,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::SandboxPolicy; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::fs_wait; use core_test_support::responses::ev_assistant_message; @@ -112,13 +113,13 @@ printf '%s\n' "${@: -1}" >> "${payload_path}""#, test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run a command that requires Guardian review".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run a command that requires Guardian review".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/hooks.rs b/codex-rs/core/tests/suite/hooks.rs index f0ad29fd68..de527e9633 100644 --- a/codex-rs/core/tests/suite/hooks.rs +++ b/codex-rs/core/tests/suite/hooks.rs @@ -20,6 +20,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; use core_test_support::hooks::trust_discovered_hooks; @@ -1829,13 +1830,13 @@ async fn blocked_queued_prompt_does_not_strand_earlier_accepted_prompt() -> Resu test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "initial prompt".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "initial prompt".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1848,13 +1849,13 @@ async fn blocked_queued_prompt_does_not_strand_earlier_accepted_prompt() -> Resu for text in ["accepted queued prompt", "blocked queued prompt"] { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/image_rollout.rs b/codex-rs/core/tests/suite/image_rollout.rs index 2b18559075..c2a1fddb43 100644 --- a/codex-rs/core/tests/suite/image_rollout.rs +++ b/codex-rs/core/tests/suite/image_rollout.rs @@ -8,6 +8,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::responses; @@ -116,19 +117,19 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu codex .submit(Op::UserInput { - items: vec![ - UserInput::LocalImage { - path: abs_path.clone(), - detail: None, - }, - UserInput::Text { - text: "pasted image".to_string(), - text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::LocalImage { + path: abs_path.clone(), + detail: None, + }, + UserInput::Text { + text: "pasted image".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), @@ -215,19 +216,19 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()> codex .submit(Op::UserInput { - items: vec![ - UserInput::Image { - image_url: image_url.clone(), - detail: None, - }, - UserInput::Text { - text: "dropped image".to_string(), - text_elements: Vec::new(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::Image { + image_url: image_url.clone(), + detail: None, + }, + UserInput::Text { + text: "dropped image".to_string(), + text_elements: Vec::new(), + }, + ], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/items.rs b/codex-rs/core/tests/suite/items.rs index a39a2b5e05..ff435eceab 100644 --- a/codex-rs/core/tests/suite/items.rs +++ b/codex-rs/core/tests/suite/items.rs @@ -13,6 +13,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ItemCompletedEvent; use codex_protocol::protocol::ItemStartedEvent; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::ByteRange; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; @@ -53,13 +54,13 @@ fn disabled_plan_turn( let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); Ok(Op::UserInput { - items: vec![UserInput::Text { - text: text.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), @@ -117,10 +118,10 @@ async fn user_message_item_is_emitted() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![expected_input.clone()], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![expected_input.clone()], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -173,13 +174,13 @@ async fn assistant_message_item_is_emitted() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please summarize results".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please summarize results".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -234,13 +235,13 @@ async fn reasoning_item_is_emitted() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "explain your reasoning".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "explain your reasoning".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -296,13 +297,13 @@ async fn web_search_item_is_emitted() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "find the weather".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "find the weather".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -376,13 +377,13 @@ async fn image_generation_call_event_is_emitted() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "generate a tiny blue square".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "generate a tiny blue square".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -463,13 +464,13 @@ async fn image_generation_call_event_is_emitted_when_image_save_fails() -> anyho codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "generate an image".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "generate an image".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -519,13 +520,13 @@ async fn agent_message_content_delta_has_item_metadata() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please stream text".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please stream text".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1103,13 +1104,13 @@ async fn reasoning_content_delta_has_item_metadata() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "reason through it".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "reason through it".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1158,13 +1159,13 @@ async fn reasoning_raw_content_delta_respects_flag() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "show raw reasoning".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "show raw reasoning".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/json_result.rs b/codex-rs/core/tests/suite/json_result.rs index c9a855e6af..addab2b7bc 100644 --- a/codex-rs/core/tests/suite/json_result.rs +++ b/codex-rs/core/tests/suite/json_result.rs @@ -4,6 +4,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses; use core_test_support::skip_if_no_network; @@ -78,13 +79,15 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> { // 1) Normal user input – should hit server once. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello world".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: Some(serde_json::from_str(SCHEMA)?), - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello world".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: Some(serde_json::from_str(SCHEMA)?), + responsesapi_client_metadata: None, + additional_context: Default::default(), + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/mcp_turn_metadata.rs b/codex-rs/core/tests/suite/mcp_turn_metadata.rs index 7fe0a95f44..2b7069ddf8 100644 --- a/codex-rs/core/tests/suite/mcp_turn_metadata.rs +++ b/codex-rs/core/tests/suite/mcp_turn_metadata.rs @@ -14,6 +14,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::ElicitationAction; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_user_input::RequestUserInputAnswer; use codex_protocol::request_user_input::RequestUserInputResponse; use codex_protocol::user_input::UserInput; @@ -97,13 +98,13 @@ async fn submit_user_turn( turn_permission_fields(PermissionProfile::Disabled, test.cwd.path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/model_runtime_selectors.rs b/codex-rs/core/tests/suite/model_runtime_selectors.rs index 3ee758372d..bc933888f5 100644 --- a/codex-rs/core/tests/suite/model_runtime_selectors.rs +++ b/codex-rs/core/tests/suite/model_runtime_selectors.rs @@ -15,6 +15,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::MultiAgentVersion; use codex_protocol::protocol::Op; use codex_protocol::protocol::ThreadSettingsOverrides; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses; use core_test_support::responses::ev_assistant_message; @@ -123,13 +124,13 @@ async fn response_body_for_remote_model( .await?; test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "list tools".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "list tools".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -273,13 +274,13 @@ async fn remote_multi_agent_selector_uses_model_selected_before_first_turn() -> test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: ROOT_PROMPT.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: ROOT_PROMPT.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index 22363eabea..d8e28b7d5c 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -20,6 +20,7 @@ use codex_protocol::openai_models::default_input_modalities; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed_with_tokens; use core_test_support::responses::ev_image_generation_call; @@ -45,10 +46,10 @@ fn read_only_user_turn(test: &TestCodex, items: Vec, model: String) - let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), test.cwd_path()); Op::UserInput { - items, - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items, + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/model_visible_layout.rs b/codex-rs/core/tests/suite/model_visible_layout.rs index ba20da039e..6c1113dfae 100644 --- a/codex-rs/core/tests/suite/model_visible_layout.rs +++ b/codex-rs/core/tests/suite/model_visible_layout.rs @@ -9,6 +9,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::PathBufExt; use core_test_support::context_snapshot; @@ -119,13 +120,13 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(first_turn_cwd)), approval_policy: Some(AskForApproval::Never), @@ -154,13 +155,13 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { ); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "second turn with context updates".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "second turn with context updates".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(preturn_context_diff_cwd)), approval_policy: Some(AskForApproval::OnRequest), @@ -245,13 +246,13 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn in agents_one".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn in agents_one".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_one.clone())), approval_policy: Some(AskForApproval::Never), @@ -278,13 +279,13 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R turn_permission_fields(PermissionProfile::read_only(), cwd_two.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "second turn in agents_two".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "second turn in agents_two".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_two)), approval_policy: Some(AskForApproval::Never), @@ -361,13 +362,13 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul .await; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "seed resume history".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "seed resume history".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -403,13 +404,13 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "resume and change personality".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "resume and change personality".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(resume_override_cwd)), approval_policy: Some(AskForApproval::Never), @@ -476,13 +477,13 @@ async fn snapshot_model_visible_layout_resume_override_matches_rollout_model() - .await; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "seed resume history".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "seed resume history".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -518,13 +519,13 @@ async fn snapshot_model_visible_layout_resume_override_matches_rollout_model() - resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first resumed turn after model override".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first resumed turn after model override".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/models_cache_ttl.rs b/codex-rs/core/tests/suite/models_cache_ttl.rs index 5103f82123..3e79405be6 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -21,6 +21,7 @@ use codex_protocol::openai_models::TruncationPolicyConfig; use codex_protocol::openai_models::default_input_modalities; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses; use core_test_support::responses::ev_assistant_message; @@ -94,13 +95,13 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hi".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hi".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(codex_protocol::protocol::AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/models_etag_responses.rs b/codex-rs/core/tests/suite/models_etag_responses.rs index 8b2e9f35b1..4aba3443d2 100644 --- a/codex-rs/core/tests/suite/models_etag_responses.rs +++ b/codex-rs/core/tests/suite/models_etag_responses.rs @@ -12,6 +12,7 @@ use codex_protocol::openai_models::ModelsResponse; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::responses; @@ -107,13 +108,13 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please run a tool".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please run a tool".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/otel.rs b/codex-rs/core/tests/suite/otel.rs index 95811d3f63..5f588c7da4 100644 --- a/codex-rs/core/tests/suite/otel.rs +++ b/codex-rs/core/tests/suite/otel.rs @@ -10,6 +10,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; use codex_protocol::protocol::SessionSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; @@ -120,13 +121,13 @@ async fn responses_api_emits_api_request_event() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -166,13 +167,13 @@ async fn process_sse_emits_tracing_for_output_item() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -212,13 +213,13 @@ async fn process_sse_emits_failed_event_on_parse_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -259,13 +260,13 @@ async fn process_sse_records_failed_event_when_stream_closes_without_completed() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -326,13 +327,13 @@ async fn process_sse_failed_event_records_response_error_message() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -391,13 +392,13 @@ async fn process_sse_failed_event_logs_parse_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -443,13 +444,13 @@ async fn process_sse_failed_event_logs_missing_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -504,13 +505,13 @@ async fn process_sse_failed_event_logs_response_completed_parse_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -559,13 +560,13 @@ async fn process_sse_emits_completed_telemetry() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -638,13 +639,13 @@ async fn turn_and_completed_response_spans_record_token_usage() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -726,13 +727,13 @@ async fn handle_responses_span_records_response_kind_and_tool_name() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -820,13 +821,13 @@ async fn record_responses_sets_span_fields_for_response_events() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -909,13 +910,13 @@ async fn handle_response_item_records_tool_result_for_custom_tool_call() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -985,13 +986,13 @@ async fn handle_response_item_records_tool_result_for_function_call() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1062,13 +1063,13 @@ async fn handle_response_item_records_tool_result_for_shell_command_call() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1235,13 +1236,13 @@ async fn handle_shell_command_autoapprove_from_config_records_tool_decision() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1290,13 +1291,13 @@ async fn handle_shell_command_user_approved_records_tool_decision() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "approved".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "approved".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1360,13 +1361,13 @@ async fn handle_shell_command_user_approved_for_session_records_tool_decision() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "persist".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "persist".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1430,13 +1431,13 @@ async fn handle_sandbox_error_user_approves_retry_records_tool_decision() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "retry".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "retry".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1500,13 +1501,13 @@ async fn handle_shell_command_user_denies_records_tool_decision() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "deny".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "deny".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1570,13 +1571,13 @@ async fn handle_sandbox_error_user_approves_for_session_records_tool_decision() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "persist".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "persist".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -1641,13 +1642,13 @@ async fn handle_sandbox_error_user_denies_records_tool_decision() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "deny".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "deny".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/pending_input.rs b/codex-rs/core/tests/suite/pending_input.rs index 269beae638..d286d62582 100644 --- a/codex-rs/core/tests/suite/pending_input.rs +++ b/codex-rs/core/tests/suite/pending_input.rs @@ -13,6 +13,7 @@ use codex_protocol::protocol::InterAgentCommunication; use codex_protocol::protocol::Op; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::context_snapshot; use core_test_support::context_snapshot::ContextSnapshotOptions; @@ -129,13 +130,13 @@ async fn build_codex(server: &StreamingSseServer) -> Arc { async fn submit_user_input(codex: &CodexThread, text: &str) { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -147,13 +148,13 @@ async fn submit_danger_full_access_user_turn(test: &TestCodex, text: &str) { turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), @@ -534,13 +535,13 @@ async fn injected_user_input_triggers_follow_up_request_with_deltas() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first prompt".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first prompt".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -553,13 +554,13 @@ async fn injected_user_input_triggers_follow_up_request_with_deltas() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "second prompt".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "second prompt".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/permissions_messages.rs b/codex-rs/core/tests/suite/permissions_messages.rs index e5a69962bc..f66cc7b751 100644 --- a/codex-rs/core/tests/suite/permissions_messages.rs +++ b/codex-rs/core/tests/suite/permissions_messages.rs @@ -10,6 +10,7 @@ use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; use core_test_support::responses::ResponsesRequest; @@ -51,13 +52,13 @@ async fn permissions_message_sent_once_on_start() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -91,13 +92,13 @@ async fn permissions_message_added_on_override_change() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -114,13 +115,13 @@ async fn permissions_message_added_on_override_change() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -160,13 +161,13 @@ async fn permissions_message_not_added_when_no_change() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -174,13 +175,13 @@ async fn permissions_message_not_added_when_no_change() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -220,13 +221,13 @@ async fn permissions_message_omitted_when_disabled() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -243,13 +244,13 @@ async fn permissions_message_omitted_when_disabled() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -302,13 +303,13 @@ async fn resume_replays_permissions_messages() -> Result<()> { initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -326,13 +327,13 @@ async fn resume_replays_permissions_messages() -> Result<()> { initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -342,13 +343,13 @@ async fn resume_replays_permissions_messages() -> Result<()> { resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after resume".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after resume".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -402,13 +403,13 @@ async fn resume_and_fork_append_permissions_messages() -> Result<()> { initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -426,13 +427,13 @@ async fn resume_and_fork_append_permissions_messages() -> Result<()> { initial .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -448,13 +449,13 @@ async fn resume_and_fork_append_permissions_messages() -> Result<()> { resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after resume".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after resume".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -483,13 +484,13 @@ async fn resume_and_fork_append_permissions_messages() -> Result<()> { forked .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "after fork".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "after fork".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -544,13 +545,13 @@ async fn permissions_message_includes_writable_roots() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/personality.rs b/codex-rs/core/tests/suite/personality.rs index a58e5f20fe..f348158142 100644 --- a/codex-rs/core/tests/suite/personality.rs +++ b/codex-rs/core/tests/suite/personality.rs @@ -17,6 +17,7 @@ use codex_protocol::openai_models::default_input_modalities; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::load_default_config_for_test; use core_test_support::responses::mount_models_once; @@ -62,13 +63,13 @@ fn read_only_text_turn_with_personality( let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), test.cwd_path()); Op::UserInput { - items: vec![UserInput::Text { - text: text.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/plugins.rs b/codex-rs/core/tests/suite/plugins.rs index 198db86d88..c0d5153061 100644 --- a/codex-rs/core/tests/suite/plugins.rs +++ b/codex-rs/core/tests/suite/plugins.rs @@ -11,6 +11,7 @@ use codex_login::CodexAuth; use codex_mcp::CODEX_APPS_MCP_SERVER_NAME; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use core_test_support::apps_test_server::AppsTestServer; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -187,13 +188,13 @@ async fn capability_sections_render_in_developer_message_in_order() -> Result<() codex .submit(Op::UserInput { - items: vec![codex_protocol::user_input::UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![codex_protocol::user_input::UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -263,13 +264,13 @@ async fn explicit_plugin_mentions_use_apps_for_chatgpt_dual_surface_plugins() -> codex .submit(Op::UserInput { - items: vec![codex_protocol::user_input::UserInput::Mention { - name: "sample".into(), - path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![codex_protocol::user_input::UserInput::Mention { + name: "sample".into(), + path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -353,13 +354,13 @@ async fn explicit_plugin_mentions_keep_non_conflicting_mcp_for_chatgpt_auth() -> codex .submit(Op::UserInput { - items: vec![codex_protocol::user_input::UserInput::Mention { - name: "sample".into(), - path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![codex_protocol::user_input::UserInput::Mention { + name: "sample".into(), + path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -442,13 +443,13 @@ async fn explicit_plugin_mentions_use_mcp_for_api_key_dual_surface_plugins() -> codex .submit(Op::UserInput { - items: vec![codex_protocol::user_input::UserInput::Mention { - name: "sample".into(), - path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![codex_protocol::user_input::UserInput::Mention { + name: "sample".into(), + path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -514,13 +515,13 @@ async fn explicit_plugin_mentions_track_plugin_used_analytics() -> Result<()> { codex .submit(Op::UserInput { - items: vec![codex_protocol::user_input::UserInput::Mention { - name: "sample".into(), - path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![codex_protocol::user_input::UserInput::Mention { + name: "sample".into(), + path: format!("plugin://{SAMPLE_PLUGIN_CONFIG_NAME}"), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index a455512321..3a5544df21 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -18,6 +18,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::ENVIRONMENT_CONTEXT_OPEN_TAG; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::responses::ev_completed; @@ -159,13 +160,13 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -173,13 +174,13 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -253,13 +254,13 @@ async fn gpt_5_tools_without_apply_patch_append_apply_patch_instructions() -> an codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -267,13 +268,13 @@ async fn gpt_5_tools_without_apply_patch_append_apply_patch_instructions() -> an wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -332,13 +333,13 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -346,13 +347,13 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -429,13 +430,13 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an // First turn codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -467,13 +468,13 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an // Second turn after overrides codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -564,13 +565,13 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first message".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first message".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -718,13 +719,13 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res // First turn codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -743,13 +744,13 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res turn_permission_fields(permission_profile, new_cwd.path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(new_cwd.abs())), approval_policy: Some(AskForApproval::Never), @@ -857,13 +858,13 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(default_cwd.clone())), approval_policy: Some(default_approval_policy), @@ -885,13 +886,13 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(default_cwd.clone())), approval_policy: Some(default_approval_policy), @@ -996,13 +997,13 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 1".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 1".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(default_cwd.clone())), approval_policy: Some(default_approval_policy), @@ -1026,13 +1027,13 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu turn_permission_fields(PermissionProfile::Disabled, default_cwd.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello 2".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello 2".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(default_cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/quota_exceeded.rs b/codex-rs/core/tests/suite/quota_exceeded.rs index 33f7d77fa7..b0810d7f58 100644 --- a/codex-rs/core/tests/suite/quota_exceeded.rs +++ b/codex-rs/core/tests/suite/quota_exceeded.rs @@ -1,6 +1,7 @@ use anyhow::Result; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_response_created; use core_test_support::responses::mount_sse_once; @@ -41,13 +42,13 @@ async fn quota_exceeded_emits_single_error_event() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "quota?".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "quota?".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/realtime_conversation.rs b/codex-rs/core/tests/suite/realtime_conversation.rs index 61fc38e8b1..1c30b0c921 100644 --- a/codex-rs/core/tests/suite/realtime_conversation.rs +++ b/codex-rs/core/tests/suite/realtime_conversation.rs @@ -27,6 +27,7 @@ use codex_protocol::protocol::RealtimeOutputModality; use codex_protocol::protocol::RealtimeVoice; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::SessionSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses; use core_test_support::responses::WebSocketConnectionConfig; @@ -2513,13 +2514,13 @@ async fn conversation_user_text_turn_is_not_sent_to_realtime() -> Result<()> { let user_text = "typed follow-up for realtime"; test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: user_text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: user_text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -3749,13 +3750,13 @@ async fn inbound_handoff_request_steers_active_turn() -> Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first prompt".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first prompt".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/remote_env.rs b/codex-rs/core/tests/suite/remote_env.rs index 311485c112..a020080714 100644 --- a/codex-rs/core/tests/suite/remote_env.rs +++ b/codex-rs/core/tests/suite/remote_env.rs @@ -23,6 +23,7 @@ use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::TurnEnvironmentSelection; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_protocol::request_permissions::RequestPermissionsResponse; @@ -81,13 +82,13 @@ async fn submit_turn_with_approval_and_environments( ); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(turn_environment_selections), approval_policy: Some(AskForApproval::OnRequest), diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index b63aff5400..2bedb9bb04 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -21,6 +21,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecCommandSource; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::load_default_config_for_test; @@ -154,13 +155,13 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "check context window".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "check context window".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -221,13 +222,13 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "check context window".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "check context window".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -287,13 +288,13 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "check context window".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "check context window".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -367,13 +368,13 @@ async fn remote_models_long_model_slug_is_sent_with_custom_reasoning() -> Result codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "check model slug".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "check model slug".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -417,13 +418,13 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "check namespaced model metadata".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "check namespaced model metadata".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -575,13 +576,13 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run call".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run call".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), @@ -803,13 +804,13 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello remote".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello remote".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/request_compression.rs b/codex-rs/core/tests/suite/request_compression.rs index e70346a5a3..cfe30e2045 100644 --- a/codex-rs/core/tests/suite/request_compression.rs +++ b/codex-rs/core/tests/suite/request_compression.rs @@ -4,6 +4,7 @@ use codex_features::Feature; use codex_login::CodexAuth; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -40,13 +41,13 @@ async fn request_body_is_zstd_compressed_for_codex_backend_when_enabled() -> any codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "compress me".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "compress me".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -90,13 +91,13 @@ async fn request_body_is_not_compressed_for_api_key_auth_even_when_enabled() -> codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "do not compress".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "do not compress".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/request_permissions.rs b/codex-rs/core/tests/suite/request_permissions.rs index 1b04582847..d165c2d7f9 100644 --- a/codex-rs/core/tests/suite/request_permissions.rs +++ b/codex-rs/core/tests/suite/request_permissions.rs @@ -15,6 +15,7 @@ use codex_protocol::protocol::ExecApprovalRequestEvent; use codex_protocol::protocol::GranularApprovalConfig; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_protocol::request_permissions::RequestPermissionsResponse; @@ -192,13 +193,13 @@ async fn submit_turn( turn_permission_fields(permission_profile, test.cwd.path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/request_permissions_tool.rs b/codex-rs/core/tests/suite/request_permissions_tool.rs index e8434896ea..a5328493a1 100644 --- a/codex-rs/core/tests/suite/request_permissions_tool.rs +++ b/codex-rs/core/tests/suite/request_permissions_tool.rs @@ -12,6 +12,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_protocol::request_permissions::RequestPermissionsResponse; @@ -144,13 +145,13 @@ async fn submit_turn( turn_permission_fields(permission_profile, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/request_user_input.rs b/codex-rs/core/tests/suite/request_user_input.rs index 1348a87186..cc2ee47faf 100644 --- a/codex-rs/core/tests/suite/request_user_input.rs +++ b/codex-rs/core/tests/suite/request_user_input.rs @@ -11,6 +11,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::request_user_input::RequestUserInputAnswer; use codex_protocol::request_user_input::RequestUserInputResponse; use codex_protocol::user_input::UserInput; @@ -144,13 +145,13 @@ async fn request_user_input_round_trip_for_mode( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please confirm".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please confirm".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), @@ -288,13 +289,13 @@ async fn request_user_input_interrupt_emits_deferred_token_count() -> anyhow::Re turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please confirm".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please confirm".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), @@ -392,13 +393,13 @@ where codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please confirm".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please confirm".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/responses_api_proxy_headers.rs b/codex-rs/core/tests/suite/responses_api_proxy_headers.rs index 768bbf11db..a7377f3a92 100644 --- a/codex-rs/core/tests/suite/responses_api_proxy_headers.rs +++ b/codex-rs/core/tests/suite/responses_api_proxy_headers.rs @@ -8,6 +8,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ResponseMock; use core_test_support::responses::ResponsesRequest; @@ -147,13 +148,13 @@ async fn submit_turn_with_timeout(test: &TestCodex, prompt: &str) -> Result<()> turn_permission_fields(PermissionProfile::workspace_write(), cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::OnRequest), diff --git a/codex-rs/core/tests/suite/responses_lite.rs b/codex-rs/core/tests/suite/responses_lite.rs index b137d5bc73..1c40bc159b 100644 --- a/codex-rs/core/tests/suite/responses_lite.rs +++ b/codex-rs/core/tests/suite/responses_lite.rs @@ -13,6 +13,7 @@ use codex_protocol::models::ImageDetail; use codex_protocol::openai_models::InputModality; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_web_search_extension::install as install_web_search_extension; use core_test_support::responses; @@ -76,13 +77,13 @@ async fn responses_lite_strips_data_image_detail_without_resize_all_images() -> test.codex .submit(Op::UserInput { - items: vec![UserInput::Image { - image_url: image_url.to_string(), - detail: Some(ImageDetail::Original), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Image { + image_url: image_url.to_string(), + detail: Some(ImageDetail::Original), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/resume.rs b/codex-rs/core/tests/suite/resume.rs index 8f760db417..0f634617ee 100644 --- a/codex-rs/core/tests/suite/resume.rs +++ b/codex-rs/core/tests/suite/resume.rs @@ -1,6 +1,7 @@ use anyhow::Result; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::ByteRange; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; @@ -86,13 +87,13 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Record some messages".into(), - text_elements: text_elements.clone(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Record some messages".into(), + text_elements: text_elements.clone(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -172,13 +173,13 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()> codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Record reasoning messages".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Record reasoning messages".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -262,13 +263,13 @@ async fn resume_switches_models_preserves_base_instructions() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Record initial instructions".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Record initial instructions".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -305,13 +306,13 @@ async fn resume_switches_models_preserves_base_instructions() -> Result<()> { resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Resume with different model".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Resume with different model".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -323,13 +324,13 @@ async fn resume_switches_models_preserves_base_instructions() -> Result<()> { resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Second turn after resume".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Second turn after resume".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -396,13 +397,13 @@ async fn resume_model_switch_is_not_duplicated_after_pre_turn_override() -> Resu .await; codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Record initial instructions".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Record initial instructions".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -434,13 +435,13 @@ async fn resume_model_switch_is_not_duplicated_after_pre_turn_override() -> Resu resumed .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first turn after override".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first turn after override".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/review.rs b/codex-rs/core/tests/suite/review.rs index 6b0f8552a2..1b8014f963 100644 --- a/codex-rs/core/tests/suite/review.rs +++ b/codex-rs/core/tests/suite/review.rs @@ -16,6 +16,7 @@ use codex_protocol::protocol::ReviewRequest; use codex_protocol::protocol::ReviewTarget; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::PathBufExt; use core_test_support::responses; @@ -708,13 +709,13 @@ async fn review_history_surfaces_in_parent_session() { let followup = "back to parent".to_string(); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: followup.clone(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: followup.clone(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 2be014b3f5..1a66b267bd 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -43,6 +43,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::McpInvocation; use codex_protocol::protocol::McpToolCallBeginEvent; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_cargo_bin::cargo_bin; use codex_utils_path_uri::PathUri; @@ -130,13 +131,13 @@ fn user_turn_with_permission_profile( let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, cwd.as_path()); Op::UserInput { - items: vec![UserInput::Text { - text: text.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { approval_policy: Some(AskForApproval::Never), sandbox_policy: Some(sandbox_policy), diff --git a/codex-rs/core/tests/suite/safety_check_downgrade.rs b/codex-rs/core/tests/suite/safety_check_downgrade.rs index a271702c9c..85371aa335 100644 --- a/codex-rs/core/tests/suite/safety_check_downgrade.rs +++ b/codex-rs/core/tests/suite/safety_check_downgrade.rs @@ -8,6 +8,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ModelRerouteReason; use codex_protocol::protocol::ModelVerification; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_function_call; @@ -39,13 +40,13 @@ fn disabled_text_turn(test: &TestCodex, text: &str) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.cwd_path()); Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/search_tool.rs b/codex-rs/core/tests/suite/search_tool.rs index 284ee49b8f..4da4483921 100644 --- a/codex-rs/core/tests/suite/search_tool.rs +++ b/codex-rs/core/tests/suite/search_tool.rs @@ -18,6 +18,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::McpInvocation; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::apps_test_server::AppsTestServer; use core_test_support::apps_test_server::AppsTestToolLoading; @@ -527,13 +528,13 @@ async fn tool_search_returns_deferred_tools_without_follow_up_tool_injection() - let test = builder.build(&server).await?; test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Find the calendar create tool".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Find the calendar create tool".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -942,13 +943,13 @@ async fn tool_search_returns_deferred_dynamic_tool_and_routes_follow_up_call() - test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Use the automation tool".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Use the automation tool".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1252,13 +1253,13 @@ async fn tool_search_surfaced_mcp_tool_errors_are_returned_to_model() -> Result< test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Find the rmcp echo tool and call it.".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Find the rmcp echo tool and call it.".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -1575,13 +1576,13 @@ async fn tool_search_matches_dynamic_tools_by_name_description_namespace_and_sch test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "Search for the dynamic tool".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "Search for the dynamic tool".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/shell_snapshot.rs b/codex-rs/core/tests/suite/shell_snapshot.rs index 04576f0818..09c2f3c545 100644 --- a/codex-rs/core/tests/suite/shell_snapshot.rs +++ b/codex-rs/core/tests/suite/shell_snapshot.rs @@ -6,6 +6,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecCommandBeginEvent; use codex_protocol::protocol::ExecCommandEndEvent; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; @@ -159,13 +160,13 @@ async fn run_snapshot_command_with_options( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run unified exec with shell snapshot".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run unified exec with shell snapshot".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), @@ -257,13 +258,13 @@ async fn run_shell_command_snapshot_with_options( codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run shell_command with shell snapshot".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run shell_command with shell snapshot".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), @@ -336,13 +337,13 @@ async fn run_tool_turn_on_harness( turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), @@ -579,13 +580,13 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "apply patch via shell_command with snapshot".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "apply patch via shell_command with snapshot".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/skill_approval.rs b/codex-rs/core/tests/suite/skill_approval.rs index 50ea9495ac..f0837f50a2 100644 --- a/codex-rs/core/tests/suite/skill_approval.rs +++ b/codex-rs/core/tests/suite/skill_approval.rs @@ -8,6 +8,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecApprovalRequestEvent; use codex_protocol::protocol::GranularApprovalConfig; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::mount_function_call_agent_response; use core_test_support::responses::start_mock_server; @@ -48,13 +49,13 @@ async fn submit_turn_with_policies( turn_permission_fields(permission_profile, test.cwd_path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/skills.rs b/codex-rs/core/tests/suite/skills.rs index 2de9bf26cb..2098760f83 100644 --- a/codex-rs/core/tests/suite/skills.rs +++ b/codex-rs/core/tests/suite/skills.rs @@ -7,6 +7,7 @@ use codex_exec_server::ExecutorFileSystem; use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_path_uri::PathUri; @@ -82,19 +83,19 @@ async fn user_turn_includes_skill_instructions() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex .submit(Op::UserInput { - items: vec![ - UserInput::Text { - text: "please use $demo".to_string(), - text_elements: Vec::new(), - }, - UserInput::Skill { - name: "demo".to_string(), - path: skill_path.clone(), - }, - ], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![ + UserInput::Text { + text: "please use $demo".to_string(), + text_elements: Vec::new(), + }, + UserInput::Skill { + name: "demo".to_string(), + path: skill_path.clone(), + }, + ], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/sqlite_state.rs b/codex-rs/core/tests/suite/sqlite_state.rs index eae82de9e1..9caaae39c5 100644 --- a/codex-rs/core/tests/suite/sqlite_state.rs +++ b/codex-rs/core/tests/suite/sqlite_state.rs @@ -21,6 +21,7 @@ use codex_protocol::protocol::SessionMeta; use codex_protocol::protocol::SessionMetaLine; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::UserMessageEvent; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_web_search_extension::install as install_web_search_extension; use core_test_support::responses; @@ -162,13 +163,13 @@ async fn resume_restores_dynamic_tools_from_rollout_with_sqlite_enabled() -> Res started .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "persist this thread".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "persist this thread".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -259,13 +260,13 @@ async fn resume_restores_legacy_dynamic_tools_from_rollout_with_sqlite_enabled() started .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "persist this thread".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "persist this thread".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; @@ -696,13 +697,13 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result< test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "call the rmcp echo tool".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "call the rmcp echo tool".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs index 1870feab9f..ab1268fe36 100644 --- a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs +++ b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs @@ -2,6 +2,7 @@ use codex_model_provider_info::ModelProviderInfo; use codex_model_provider_info::WireApi; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_response_created; @@ -94,13 +95,13 @@ async fn continue_after_stream_error() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "first message".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "first message".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await @@ -116,13 +117,13 @@ async fn continue_after_stream_error() { // error above, this submission would be rejected/queued indefinitely. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "follow up".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "follow up".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/stream_no_completed.rs b/codex-rs/core/tests/suite/stream_no_completed.rs index 6e028279b1..dff1ec1df5 100644 --- a/codex-rs/core/tests/suite/stream_no_completed.rs +++ b/codex-rs/core/tests/suite/stream_no_completed.rs @@ -5,6 +5,7 @@ use codex_model_provider_info::ModelProviderInfo; use codex_model_provider_info::WireApi; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses; use core_test_support::skip_if_no_network; @@ -76,13 +77,13 @@ async fn retries_on_early_close() { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs index a78e1fbc0c..d6ed5f1063 100644 --- a/codex-rs/core/tests/suite/subagent_notifications.rs +++ b/codex-rs/core/tests/suite/subagent_notifications.rs @@ -12,6 +12,7 @@ use codex_protocol::protocol::InitialHistory; use codex_protocol::protocol::Op; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::hooks::trust_discovered_hooks; use core_test_support::responses::ResponsesRequest; @@ -761,13 +762,13 @@ async fn subagent_stop_replaces_stop_and_skips_internal_subagents() -> Result<() internal_thread .thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: INTERNAL_SUBAGENT_PROMPT.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: INTERNAL_SUBAGENT_PROMPT.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/tool_harness.rs b/codex-rs/core/tests/suite/tool_harness.rs index 963123b59e..8c5c49e7f4 100644 --- a/codex-rs/core/tests/suite/tool_harness.rs +++ b/codex-rs/core/tests/suite/tool_harness.rs @@ -10,6 +10,7 @@ use codex_protocol::plan_tool::StepStatus; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::assert_regex_match; @@ -97,13 +98,13 @@ async fn shell_command_tool_executes_command_and_streams_output() -> anyhow::Res codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please run the shell command".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please run the shell command".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), @@ -178,13 +179,13 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please update the plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please update the plan".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), @@ -269,13 +270,13 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please update the plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please update the plan".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), @@ -370,13 +371,13 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<() codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please apply a patch".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please apply a patch".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), @@ -508,13 +509,13 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "please apply a patch".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "please apply a patch".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd_path)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/tool_parallelism.rs b/codex-rs/core/tests/suite/tool_parallelism.rs index a11ee5c2ee..ecc5634adc 100644 --- a/codex-rs/core/tests/suite/tool_parallelism.rs +++ b/codex-rs/core/tests/suite/tool_parallelism.rs @@ -10,6 +10,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; @@ -39,13 +40,13 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> { test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), @@ -364,13 +365,13 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an turn_permission_fields(PermissionProfile::Disabled, test.cwd.path()); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "stream delayed completion".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "stream delayed completion".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/truncation.rs b/codex-rs/core/tests/suite/truncation.rs index cc942cbc17..7fd84d4a70 100644 --- a/codex-rs/core/tests/suite/truncation.rs +++ b/codex-rs/core/tests/suite/truncation.rs @@ -9,6 +9,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::assert_regex_match; @@ -521,13 +522,13 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { fixture .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "call the rmcp image tool".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "call the rmcp image tool".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(fixture.cwd.abs())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/unified_exec.rs b/codex-rs/core/tests/suite/unified_exec.rs index 9f8d931da2..5793c43e8d 100644 --- a/codex-rs/core/tests/suite/unified_exec.rs +++ b/codex-rs/core/tests/suite/unified_exec.rs @@ -16,6 +16,7 @@ use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecCommandSource; use codex_protocol::protocol::ExecCommandStatus; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_path_uri::PathUri; use core_test_support::TempDirExt; @@ -197,13 +198,13 @@ async fn submit_unified_exec_turn( test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { approval_policy: Some(AskForApproval::Never), sandbox_policy: Some(sandbox_policy), @@ -289,13 +290,13 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "apply patch via unified exec".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "apply patch via unified exec".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), @@ -2432,13 +2433,13 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()> codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "keep unified exec process after turn end".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "keep unified exec process after turn end".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(turn_cwd)), approval_policy: Some(AskForApproval::Never), @@ -2535,13 +2536,13 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "interrupt long-running unified exec".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "interrupt long-running unified exec".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(turn_cwd)), approval_policy: Some(AskForApproval::Never), @@ -3018,13 +3019,13 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "summarize large output".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "summarize large output".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(turn_cwd)), approval_policy: Some(AskForApproval::Never), @@ -3140,13 +3141,13 @@ async fn unified_exec_enforces_glob_deny_read_policy() -> Result<()> { turn_permission_fields(PermissionProfile::read_only(), turn_cwd.as_path()); codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "read the fixture files".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "read the fixture files".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(turn_cwd)), approval_policy: Some(AskForApproval::Never), @@ -3278,13 +3279,13 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "start python under seatbelt".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "start python under seatbelt".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(turn_cwd)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/unified_exec_zsh_fork_approvals.rs b/codex-rs/core/tests/suite/unified_exec_zsh_fork_approvals.rs index 0d913d6541..37b2847401 100644 --- a/codex-rs/core/tests/suite/unified_exec_zsh_fork_approvals.rs +++ b/codex-rs/core/tests/suite/unified_exec_zsh_fork_approvals.rs @@ -20,6 +20,7 @@ use codex_protocol::protocol::ExecApprovalRequestEvent; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; use codex_protocol::protocol::ThreadSettingsOverrides; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::responses::ResponseMock; use core_test_support::responses::ev_assistant_message; @@ -403,13 +404,13 @@ async fn submit_turn_with_session_permissions( ); test.codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt.into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt.into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: ThreadSettingsOverrides { environments: Some(local_selections(test.config.cwd.clone())), approval_policy: Some(approval_policy), diff --git a/codex-rs/core/tests/suite/user_notification.rs b/codex-rs/core/tests/suite/user_notification.rs index 328a1c972a..5ad045609c 100644 --- a/codex-rs/core/tests/suite/user_notification.rs +++ b/codex-rs/core/tests/suite/user_notification.rs @@ -4,6 +4,7 @@ use std::os::unix::fs::PermissionsExt; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::fs_wait; use core_test_support::responses; @@ -57,13 +58,13 @@ mv "${tmp_path}" "${payload_path}""#, // 1) Normal user input – should hit server once. codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello world".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello world".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/core/tests/suite/user_shell_cmd.rs b/codex-rs/core/tests/suite/user_shell_cmd.rs index 4a9605497b..a544bd4922 100644 --- a/codex-rs/core/tests/suite/user_shell_cmd.rs +++ b/codex-rs/core/tests/suite/user_shell_cmd.rs @@ -9,6 +9,7 @@ use codex_protocol::protocol::ExecCommandSource; use codex_protocol::protocol::ExecOutputStream; use codex_protocol::protocol::Op; use codex_protocol::protocol::TurnAbortReason; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::PathBufExt; use core_test_support::assert_regex_match; @@ -211,13 +212,13 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()> fixture .codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "run model shell command".to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "run model shell command".to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd)), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 1857eedefd..6aeb45dac5 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -28,6 +28,7 @@ use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::TurnEnvironmentSelection; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_utils_path_uri::PathUri; use core_test_support::PathBufExt; @@ -77,10 +78,10 @@ fn disabled_user_turn(test: &TestCodex, items: Vec, model: String) -> let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); Op::UserInput { - items, - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items, + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { approval_policy: Some(AskForApproval::Never), sandbox_policy: Some(sandbox_policy), diff --git a/codex-rs/core/tests/suite/websocket_fallback.rs b/codex-rs/core/tests/suite/websocket_fallback.rs index cdf77694c2..41b1c9cab5 100644 --- a/codex-rs/core/tests/suite/websocket_fallback.rs +++ b/codex-rs/core/tests/suite/websocket_fallback.rs @@ -4,6 +4,7 @@ use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use core_test_support::TempDirExt; use core_test_support::responses; @@ -155,13 +156,13 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: "hello".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { environments: Some(local_selections(cwd.abs())), approval_policy: Some(AskForApproval::Never), diff --git a/codex-rs/core/tests/suite/window_headers.rs b/codex-rs/core/tests/suite/window_headers.rs index 8a2a097843..0c2ef1ace7 100644 --- a/codex-rs/core/tests/suite/window_headers.rs +++ b/codex-rs/core/tests/suite/window_headers.rs @@ -4,6 +4,7 @@ use codex_core::CodexThread; use codex_core::compact::SUMMARIZATION_PROMPT; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; +use codex_protocol::protocol::UserSubmission; use codex_protocol::protocol::WarningEvent; use codex_protocol::user_input::UserInput; use core_test_support::responses::ResponsesRequest; @@ -102,13 +103,13 @@ async fn window_id_advances_after_compact_persists_on_resume_and_resets_on_fork( async fn submit_user_turn(codex: &Arc, text: &str) -> Result<()> { codex .submit(Op::UserInput { - items: vec![UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: text.to_string(), + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await?; diff --git a/codex-rs/mcp-server/src/codex_tool_runner.rs b/codex-rs/mcp-server/src/codex_tool_runner.rs index c4ec218dc9..7ef7d1cbc8 100644 --- a/codex-rs/mcp-server/src/codex_tool_runner.rs +++ b/codex-rs/mcp-server/src/codex_tool_runner.rs @@ -22,6 +22,7 @@ use codex_protocol::protocol::ExecApprovalRequestEvent; use codex_protocol::protocol::Op; use codex_protocol::protocol::Submission; use codex_protocol::protocol::TurnCompleteEvent; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use rmcp::model::CallToolResult; use rmcp::model::Content; @@ -103,14 +104,14 @@ pub async fn run_codex_tool_session( let submission = Submission { id: sub_id.clone(), op: Op::UserInput { - items: vec![UserInput::Text { - text: initial_prompt.clone(), - // MCP tool prompts are plain text with no UI element ranges. - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: initial_prompt.clone(), + // MCP tool prompts are plain text with no UI element ranges. + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }, client_user_message_id: None, @@ -154,14 +155,14 @@ pub async fn run_codex_tool_session_reply( .insert(request_id.clone(), thread_id); if let Err(e) = thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt, - // MCP tool prompts are plain text with no UI element ranges. - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt, + // MCP tool prompts are plain text with no UI element ranges. + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/memories/write/src/runtime.rs b/codex-rs/memories/write/src/runtime.rs index 8dae6ca617..ba0b19a312 100644 --- a/codex-rs/memories/write/src/runtime.rs +++ b/codex-rs/memories/write/src/runtime.rs @@ -30,6 +30,7 @@ use codex_protocol::protocol::Op; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::ThreadSource; use codex_protocol::protocol::TokenUsage; +use codex_protocol::protocol::UserSubmission; use codex_protocol::user_input::UserInput; use codex_rollout_trace::InferenceTraceContext; use codex_state::StateRuntime; @@ -320,10 +321,10 @@ impl MemoryStartupContext { if let Err(err) = agent .thread .submit(Op::UserInput { - items: prompt, - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: prompt, + ..Default::default() + }, thread_settings: Default::default(), }) .await diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index b4b1659ee1..b758fe2dc2 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -479,19 +479,32 @@ pub struct ThreadSettingsOverrides { } /// Source classification for client-supplied context. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] pub enum AdditionalContextKind { Untrusted, Application, } /// Client-supplied context keyed by an opaque source identifier. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] pub struct AdditionalContextEntry { pub value: String, pub kind: AdditionalContextKind, } +/// User-authored content submitted to an active or future turn. +#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)] +pub struct UserSubmission { + /// User input items, see `InputItem`. + pub items: Vec, + /// Optional JSON Schema used to constrain the final assistant message. + pub final_output_json_schema: Option, + /// Optional turn-scoped Responses API `client_metadata`. + pub responsesapi_client_metadata: Option>, + /// Client-supplied context fragments keyed by an opaque source identifier. + pub additional_context: BTreeMap, +} + /// Submission operation #[derive(Debug, Clone, PartialEq)] #[allow(clippy::large_enum_variant)] @@ -525,15 +538,8 @@ pub enum Op { /// User input, optionally with thread-settings overrides applied first. UserInput { - /// User input items, see `InputItem` - items: Vec, - /// Optional JSON Schema used to constrain the final assistant message for this turn. - final_output_json_schema: Option, - /// Optional turn-scoped Responses API `client_metadata`. - responsesapi_client_metadata: Option>, - /// Client-supplied context fragments keyed by an opaque source identifier. - additional_context: BTreeMap, - + /// User-authored content for this submission. + submission: UserSubmission, /// Persistent thread-settings overrides to apply before the input. thread_settings: ThreadSettingsOverrides, }, @@ -665,10 +671,10 @@ pub enum ThreadMemoryMode { impl From> for Op { fn from(value: Vec) -> Self { Op::UserInput { - items: value, - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: value, + ..Default::default() + }, thread_settings: ThreadSettingsOverrides::default(), } } diff --git a/codex-rs/thread-manager-sample/src/main.rs b/codex-rs/thread-manager-sample/src/main.rs index 608c9a90a1..143656a6fb 100644 --- a/codex-rs/thread-manager-sample/src/main.rs +++ b/codex-rs/thread-manager-sample/src/main.rs @@ -52,6 +52,7 @@ use codex_core_api::TuiNotificationSettings; use codex_core_api::TuiPetAnchor; use codex_core_api::UriBasedFileOpener; use codex_core_api::UserInput; +use codex_core_api::UserSubmission; use codex_core_api::WebSearchMode; use codex_core_api::arg0_dispatch_or_else; use codex_core_api::built_in_model_providers; @@ -297,13 +298,13 @@ fn new_config(model: Option, arg0_paths: Arg0DispatchPaths) -> anyhow::R async fn run_turn(thread: &CodexThread, thread_id: &str, prompt: String) -> anyhow::Result<()> { thread .submit(Op::UserInput { - items: vec![UserInput::Text { - text: prompt, - text_elements: Vec::new(), - }], - final_output_json_schema: None, - responsesapi_client_metadata: None, - additional_context: Default::default(), + submission: UserSubmission { + items: vec![UserInput::Text { + text: prompt, + text_elements: Vec::new(), + }], + ..Default::default() + }, thread_settings: Default::default(), }) .await