diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index cf32a4689..ee2db7908 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -154,8 +154,13 @@ jobs: components: llvm-tools-preview, rustc-dev, rust-src - uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2 - name: Run argument comment lint on codex-rs + if: ${{ runner.os == 'macOS' }} shell: bash run: ./tools/argument-comment-lint/run-prebuilt-linter.sh + - name: Run argument comment lint on codex-rs (default targets only) + if: ${{ runner.os != 'macOS' }} + shell: bash + run: ./tools/argument-comment-lint/run-prebuilt-linter.sh -- --lib --bins # --- CI to validate on different os/targets -------------------------------- lint_build: diff --git a/codex-rs/analytics/src/analytics_client_tests.rs b/codex-rs/analytics/src/analytics_client_tests.rs index f64da8f58..4f49a7c71 100644 --- a/codex-rs/analytics/src/analytics_client_tests.rs +++ b/codex-rs/analytics/src/analytics_client_tests.rs @@ -49,7 +49,11 @@ fn normalize_path_for_skill_id_repo_scoped_uses_relative_path() { fn normalize_path_for_skill_id_user_scoped_uses_absolute_path() { let skill_path = PathBuf::from("/Users/abc/.codex/skills/doc/SKILL.md"); - let path = normalize_path_for_skill_id(None, None, skill_path.as_path()); + let path = normalize_path_for_skill_id( + /*repo_url*/ None, + /*repo_root*/ None, + skill_path.as_path(), + ); let expected = expected_absolute_path(&skill_path); assert_eq!(path, expected); @@ -59,7 +63,11 @@ fn normalize_path_for_skill_id_user_scoped_uses_absolute_path() { fn normalize_path_for_skill_id_admin_scoped_uses_absolute_path() { let skill_path = PathBuf::from("/etc/codex/skills/doc/SKILL.md"); - let path = normalize_path_for_skill_id(None, None, skill_path.as_path()); + let path = normalize_path_for_skill_id( + /*repo_url*/ None, + /*repo_root*/ None, + skill_path.as_path(), + ); let expected = expected_absolute_path(&skill_path); assert_eq!(path, expected); diff --git a/codex-rs/app-server-client/src/lib.rs b/codex-rs/app-server-client/src/lib.rs index ad9eca65e..39768820d 100644 --- a/codex-rs/app-server-client/src/lib.rs +++ b/codex-rs/app-server-client/src/lib.rs @@ -917,7 +917,7 @@ mod tests { + 'static, Fut: std::future::Future + Send + 'static, { - start_test_remote_server_with_auth(None, handler).await + start_test_remote_server_with_auth(/*expected_auth_token*/ None, handler).await } async fn start_test_remote_server_with_auth( @@ -1164,7 +1164,8 @@ mod tests { #[tokio::test] async fn tiny_channel_capacity_still_supports_request_roundtrip() { - let client = start_test_client_with_capacity(SessionSource::Exec, 1).await; + let client = + start_test_client_with_capacity(SessionSource::Exec, /*channel_capacity*/ 1).await; let _response: ConfigRequirementsReadResponse = client .request_typed(ClientRequest::ConfigRequirementsRead { request_id: RequestId::Integer(1), diff --git a/codex-rs/app-server-protocol/src/export.rs b/codex-rs/app-server-protocol/src/export.rs index 033f60597..358bb5c2d 100644 --- a/codex-rs/app-server-protocol/src/export.rs +++ b/codex-rs/app-server-protocol/src/export.rs @@ -2690,7 +2690,7 @@ export type Config = { stableField: Keep, unstableField: string | null } & ({ [k fn generate_json_filters_experimental_fields_and_methods() -> Result<()> { let output_dir = std::env::temp_dir().join(format!("codex_schema_{}", Uuid::now_v7())); fs::create_dir(&output_dir)?; - generate_json_with_experimental(&output_dir, false)?; + generate_json_with_experimental(&output_dir, /*experimental_api*/ false)?; let thread_start_json = fs::read_to_string(output_dir.join("v2").join("ThreadStartParams.json"))?; diff --git a/codex-rs/app-server-protocol/tests/schema_fixtures.rs b/codex-rs/app-server-protocol/tests/schema_fixtures.rs index fbe1fd440..20823466e 100644 --- a/codex-rs/app-server-protocol/tests/schema_fixtures.rs +++ b/codex-rs/app-server-protocol/tests/schema_fixtures.rs @@ -23,7 +23,7 @@ fn typescript_schema_fixtures_match_generated() -> Result<()> { #[test] fn json_schema_fixtures_match_generated() -> Result<()> { assert_schema_fixtures_match_generated("json", |output_dir| { - generate_json_with_experimental(output_dir, false) + generate_json_with_experimental(output_dir, /*experimental_api*/ false) }) } diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index f7e291674..2798dcb92 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -8747,7 +8747,7 @@ mod tests { fn config_load_error_marks_non_auth_cloud_requirements_failures_without_relogin() { let err = std::io::Error::other(CloudRequirementsLoadError::new( CloudRequirementsLoadErrorCode::RequestFailed, - None, + /*status_code*/ None, "failed to load your workspace-managed config", )); @@ -8961,7 +8961,8 @@ mod tests { fn merge_persisted_resume_metadata_skips_missing_values() -> Result<()> { let mut request_overrides = None; let mut typesafe_overrides = ConfigOverrides::default(); - let persisted_metadata = test_thread_metadata(None, None)?; + let persisted_metadata = + test_thread_metadata(/*model*/ None, /*reasoning_effort*/ None)?; merge_persisted_resume_metadata( &mut request_overrides, @@ -9013,7 +9014,7 @@ mod tests { path.clone(), &head, &session_meta, - None, + /*git*/ None, "test-provider", timestamp.clone(), ) @@ -9223,9 +9224,9 @@ mod tests { source, Some("atlas".to_string()), Some("explorer".to_string()), - None, - None, - None, + /*git_sha*/ None, + /*git_branch*/ None, + /*git_origin_url*/ None, ); let thread = summary_to_thread(summary); @@ -9244,7 +9245,9 @@ mod tests { manager.connection_initialized(connection).await; manager - .try_ensure_connection_subscribed(thread_id, connection, false) + .try_ensure_connection_subscribed( + thread_id, connection, /*experimental_raw_events*/ false, + ) .await .expect("connection should be live"); { @@ -9288,11 +9291,19 @@ mod tests { manager.connection_initialized(connection_a).await; manager.connection_initialized(connection_b).await; manager - .try_ensure_connection_subscribed(thread_id, connection_a, false) + .try_ensure_connection_subscribed( + thread_id, + connection_a, + /*experimental_raw_events*/ false, + ) .await .expect("connection_a should be live"); manager - .try_ensure_connection_subscribed(thread_id, connection_b, false) + .try_ensure_connection_subscribed( + thread_id, + connection_b, + /*experimental_raw_events*/ false, + ) .await .expect("connection_b should be live"); { @@ -9325,7 +9336,9 @@ mod tests { assert!( manager - .try_ensure_connection_subscribed(thread_id, connection, false) + .try_ensure_connection_subscribed( + thread_id, connection, /*experimental_raw_events*/ false + ) .await .is_none() ); diff --git a/codex-rs/app-server/src/codex_message_processor/plugin_app_helpers.rs b/codex-rs/app-server/src/codex_message_processor/plugin_app_helpers.rs index faeca5b2e..f2ba96d43 100644 --- a/codex-rs/app-server/src/codex_message_processor/plugin_app_helpers.rs +++ b/codex-rs/app-server/src/codex_message_processor/plugin_app_helpers.rs @@ -137,7 +137,7 @@ mod tests { &all_connectors, &[], &[AppConnectorId("alpha".to_string())], - false, + /*codex_apps_ready*/ false, ), Vec::new() ); diff --git a/codex-rs/app-server/src/filters.rs b/codex-rs/app-server/src/filters.rs index 6d2b90dba..20608d93c 100644 --- a/codex-rs/app-server/src/filters.rs +++ b/codex-rs/app-server/src/filters.rs @@ -90,7 +90,7 @@ mod tests { #[test] fn compute_source_filters_defaults_to_interactive_sources() { - let (allowed_sources, filter) = compute_source_filters(None); + let (allowed_sources, filter) = compute_source_filters(/*source_kinds*/ None); assert_eq!(allowed_sources, INTERACTIVE_SESSION_SOURCES.to_vec()); assert_eq!(filter, None); diff --git a/codex-rs/app-server/src/in_process.rs b/codex-rs/app-server/src/in_process.rs index 0405c7225..6b96bb4e3 100644 --- a/codex-rs/app-server/src/in_process.rs +++ b/codex-rs/app-server/src/in_process.rs @@ -786,7 +786,8 @@ mod tests { #[tokio::test] async fn in_process_start_clamps_zero_channel_capacity() { - let client = start_test_client_with_capacity(SessionSource::Cli, 0).await; + let client = + start_test_client_with_capacity(SessionSource::Cli, /*channel_capacity*/ 0).await; let response = loop { match client .request(ClientRequest::ConfigRequirementsRead { diff --git a/codex-rs/app-server/src/lib.rs b/codex-rs/app-server/src/lib.rs index e85a8f129..3ecefa83f 100644 --- a/codex-rs/app-server/src/lib.rs +++ b/codex-rs/app-server/src/lib.rs @@ -860,7 +860,10 @@ mod tests { #[test] fn log_format_from_env_value_defaults_for_non_json_values() { - assert_eq!(LogFormat::from_env_value(None), LogFormat::Default); + assert_eq!( + LogFormat::from_env_value(/*value*/ None), + LogFormat::Default + ); assert_eq!(LogFormat::from_env_value(Some("")), LogFormat::Default); assert_eq!(LogFormat::from_env_value(Some("text")), LogFormat::Default); assert_eq!(LogFormat::from_env_value(Some("jsonl")), LogFormat::Default); diff --git a/codex-rs/app-server/src/message_processor/tracing_tests.rs b/codex-rs/app-server/src/message_processor/tracing_tests.rs index d2fe9c23d..f52b6affe 100644 --- a/codex-rs/app-server/src/message_processor/tracing_tests.rs +++ b/codex-rs/app-server/src/message_processor/tracing_tests.rs @@ -147,7 +147,7 @@ impl TracingHarness { }), }, }, - None, + /*trace*/ None, ) .await; assert!(harness.session.initialized); @@ -213,7 +213,7 @@ async fn build_test_config(codex_home: &Path, server_uri: &str) -> Result .. } = RemoteTrace::new("00000000000000000000000000000011", "0000000000000022"); - let _: ThreadStartResponse = harness.start_thread(20_002, None).await; + let _: ThreadStartResponse = harness + .start_thread(/*request_id*/ 20_002, /*trace*/ None) + .await; let untraced_spans = wait_for_exported_spans(harness.tracing, |spans| { spans.iter().any(|span| { span.span_kind == SpanKind::Server @@ -538,10 +540,16 @@ async fn thread_start_jsonrpc_span_exports_server_span_and_parents_children() -> .span_context .trace_id(), ); - assert_has_internal_descendant_at_min_depth(&untraced_spans, untraced_server_span, 1); + assert_has_internal_descendant_at_min_depth( + &untraced_spans, + untraced_server_span, + /*min_depth*/ 1, + ); let baseline_len = untraced_spans.len(); - let _: ThreadStartResponse = harness.start_thread(20_003, Some(remote_trace)).await; + let _: ThreadStartResponse = harness + .start_thread(/*request_id*/ 20_003, Some(remote_trace)) + .await; let spans = wait_for_new_exported_spans(harness.tracing, baseline_len, |spans| { spans.iter().any(|span| { span.span_kind == SpanKind::Server @@ -561,8 +569,8 @@ async fn thread_start_jsonrpc_span_exports_server_span_and_parents_children() -> assert!(server_request_span.parent_span_is_remote); assert_eq!(server_request_span.span_context.trace_id(), remote_trace_id); assert_ne!(server_request_span.span_context.span_id(), SpanId::INVALID); - assert_has_internal_descendant_at_min_depth(&spans, server_request_span, 1); - assert_has_internal_descendant_at_min_depth(&spans, server_request_span, 2); + assert_has_internal_descendant_at_min_depth(&spans, server_request_span, /*min_depth*/ 1); + assert_has_internal_descendant_at_min_depth(&spans, server_request_span, /*min_depth*/ 2); harness.shutdown().await; Ok(()) @@ -572,7 +580,7 @@ async fn thread_start_jsonrpc_span_exports_server_span_and_parents_children() -> async fn turn_start_jsonrpc_span_parents_core_turn_spans() -> Result<()> { let _guard = tracing_test_guard().lock().await; let mut harness = TracingHarness::new().await?; - let thread_start_response = harness.start_thread(2, None).await; + let thread_start_response = harness.start_thread(/*request_id*/ 2, /*trace*/ None).await; let thread_id = thread_start_response.thread.id.clone(); harness.reset_tracing(); diff --git a/codex-rs/app-server/src/outgoing_message.rs b/codex-rs/app-server/src/outgoing_message.rs index 946a819d7..d4e4bde06 100644 --- a/codex-rs/app-server/src/outgoing_message.rs +++ b/codex-rs/app-server/src/outgoing_message.rs @@ -886,7 +886,7 @@ mod tests { .register_request_context(RequestContext::new( request_id.clone(), tracing::info_span!("app_server.request", rpc.method = "thread/start"), - None, + /*parent_trace*/ None, )) .await; assert_eq!(outgoing.request_context_count().await, 1); @@ -997,14 +997,14 @@ mod tests { .register_request_context(RequestContext::new( closed_connection_request, tracing::info_span!("app_server.request", rpc.method = "turn/interrupt"), - None, + /*parent_trace*/ None, )) .await; outgoing .register_request_context(RequestContext::new( open_connection_request, tracing::info_span!("app_server.request", rpc.method = "turn/start"), - None, + /*parent_trace*/ None, )) .await; assert_eq!(outgoing.request_context_count().await, 2); diff --git a/codex-rs/app-server/src/thread_status.rs b/codex-rs/app-server/src/thread_status.rs index f4728616d..0f0b3eea7 100644 --- a/codex-rs/app-server/src/thread_status.rs +++ b/codex-rs/app-server/src/thread_status.rs @@ -530,7 +530,7 @@ mod tests { #[test] fn resolves_in_progress_turn_to_active_status() { - let status = resolve_thread_status(ThreadStatus::Idle, true); + let status = resolve_thread_status(ThreadStatus::Idle, /*has_in_progress_turn*/ true); assert_eq!( status, ThreadStatus::Active { @@ -538,7 +538,8 @@ mod tests { } ); - let status = resolve_thread_status(ThreadStatus::NotLoaded, true); + let status = + resolve_thread_status(ThreadStatus::NotLoaded, /*has_in_progress_turn*/ true); assert_eq!( status, ThreadStatus::Active { @@ -550,11 +551,14 @@ mod tests { #[test] fn keeps_status_when_no_in_progress_turn() { assert_eq!( - resolve_thread_status(ThreadStatus::Idle, false), + resolve_thread_status(ThreadStatus::Idle, /*has_in_progress_turn*/ false), ThreadStatus::Idle ); assert_eq!( - resolve_thread_status(ThreadStatus::SystemError, false), + resolve_thread_status( + ThreadStatus::SystemError, + /*has_in_progress_turn*/ false + ), ThreadStatus::SystemError ); } diff --git a/codex-rs/app-server/src/transport/auth.rs b/codex-rs/app-server/src/transport/auth.rs index 1c6080e74..a67c692b7 100644 --- a/codex-rs/app-server/src/transport/auth.rs +++ b/codex-rs/app-server/src/transport/auth.rs @@ -506,8 +506,14 @@ mod tests { }), ); let tampered = token.replace(".eyJleHAi", ".eyJleHBi"); - let err = verify_signed_bearer_token(&tampered, shared_secret, None, None, 30) - .expect_err("tampered jwt should fail"); + let err = verify_signed_bearer_token( + &tampered, + shared_secret, + /*issuer*/ None, + /*audience*/ None, + /*max_clock_skew_seconds*/ 30, + ) + .expect_err("tampered jwt should fail"); assert_eq!(err.status_code(), StatusCode::UNAUTHORIZED); } @@ -522,8 +528,14 @@ mod tests { "aud": "audience", }), ); - verify_signed_bearer_token(&token, shared_secret, Some("issuer"), Some("audience"), 30) - .expect("valid signed token should verify"); + verify_signed_bearer_token( + &token, + shared_secret, + Some("issuer"), + Some("audience"), + /*max_clock_skew_seconds*/ 30, + ) + .expect("valid signed token should verify"); } #[test] @@ -536,8 +548,14 @@ mod tests { "aud": ["other-audience", "audience"], }), ); - verify_signed_bearer_token(&token, shared_secret, None, Some("audience"), 30) - .expect("jwt audience arrays should verify"); + verify_signed_bearer_token( + &token, + shared_secret, + /*issuer*/ None, + Some("audience"), + /*max_clock_skew_seconds*/ 30, + ) + .expect("jwt audience arrays should verify"); } #[test] @@ -550,9 +568,14 @@ mod tests { ); let header_segment = URL_SAFE_NO_PAD.encode(br#"{"alg":"none","typ":"JWT"}"#); let token = format!("{header_segment}.{claims_segment}."); - let err = - verify_signed_bearer_token(&token, b"0123456789abcdef0123456789abcdef", None, None, 30) - .expect_err("alg=none jwt should be rejected"); + let err = verify_signed_bearer_token( + &token, + b"0123456789abcdef0123456789abcdef", + /*issuer*/ None, + /*audience*/ None, + /*max_clock_skew_seconds*/ 30, + ) + .expect_err("alg=none jwt should be rejected"); assert_eq!(err.status_code(), StatusCode::UNAUTHORIZED); } @@ -565,8 +588,14 @@ mod tests { "iss": "issuer", }), ); - let err = verify_signed_bearer_token(&token, shared_secret, None, None, 30) - .expect_err("jwt without exp should be rejected"); + let err = verify_signed_bearer_token( + &token, + shared_secret, + /*issuer*/ None, + /*audience*/ None, + /*max_clock_skew_seconds*/ 30, + ) + .expect_err("jwt without exp should be rejected"); assert_eq!(err.status_code(), StatusCode::UNAUTHORIZED); } diff --git a/codex-rs/app-server/src/transport/mod.rs b/codex-rs/app-server/src/transport/mod.rs index c0653b903..fa744a1af 100644 --- a/codex-rs/app-server/src/transport/mod.rs +++ b/codex-rs/app-server/src/transport/mod.rs @@ -646,7 +646,7 @@ mod tests { initialized, Arc::new(AtomicBool::new(true)), opted_out_notification_methods, - None, + /*disconnect_sender*/ None, ), ); @@ -686,7 +686,7 @@ mod tests { Arc::new(AtomicBool::new(true)), Arc::new(AtomicBool::new(true)), Arc::new(RwLock::new(HashSet::from(["configWarning".to_string()]))), - None, + /*disconnect_sender*/ None, ), ); @@ -726,7 +726,7 @@ mod tests { Arc::new(AtomicBool::new(true)), Arc::new(AtomicBool::new(true)), Arc::new(RwLock::new(HashSet::new())), - None, + /*disconnect_sender*/ None, ), ); @@ -772,7 +772,7 @@ mod tests { Arc::new(AtomicBool::new(true)), Arc::new(AtomicBool::new(false)), Arc::new(RwLock::new(HashSet::new())), - None, + /*disconnect_sender*/ None, ), ); @@ -834,7 +834,7 @@ mod tests { Arc::new(AtomicBool::new(true)), Arc::new(AtomicBool::new(true)), Arc::new(RwLock::new(HashSet::new())), - None, + /*disconnect_sender*/ None, ), ); @@ -1006,7 +1006,7 @@ mod tests { Arc::new(AtomicBool::new(true)), Arc::new(AtomicBool::new(true)), Arc::new(RwLock::new(HashSet::new())), - None, + /*disconnect_sender*/ None, ), ); diff --git a/codex-rs/app-server/tests/suite/auth.rs b/codex-rs/app-server/tests/suite/auth.rs index ff50cd744..769d73b82 100644 --- a/codex-rs/app-server/tests/suite/auth.rs +++ b/codex-rs/app-server/tests/suite/auth.rs @@ -160,7 +160,7 @@ async fn get_auth_status_with_api_key() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn get_auth_status_with_api_key_when_auth_not_required() -> Result<()> { let codex_home = TempDir::new()?; - create_config_toml_custom_provider(codex_home.path(), false)?; + create_config_toml_custom_provider(codex_home.path(), /*requires_openai_auth*/ false)?; let mut mcp = McpProcess::new(codex_home.path()).await?; timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??; diff --git a/codex-rs/app-server/tests/suite/conversation_summary.rs b/codex-rs/app-server/tests/suite/conversation_summary.rs index 31108a845..9e292d602 100644 --- a/codex-rs/app-server/tests/suite/conversation_summary.rs +++ b/codex-rs/app-server/tests/suite/conversation_summary.rs @@ -45,7 +45,7 @@ async fn get_conversation_summary_by_thread_id_reads_rollout() -> Result<()> { META_RFC3339, PREVIEW, Some(MODEL_PROVIDER), - None, + /*git_info*/ None, )?; let thread_id = ThreadId::from_string(&conversation_id)?; let expected = expected_summary( @@ -86,7 +86,7 @@ async fn get_conversation_summary_by_relative_rollout_path_resolves_from_codex_h META_RFC3339, PREVIEW, Some(MODEL_PROVIDER), - None, + /*git_info*/ None, )?; let thread_id = ThreadId::from_string(&conversation_id)?; let rollout_path = rollout_path(codex_home.path(), FILENAME_TS, &conversation_id); diff --git a/codex-rs/app-server/tests/suite/fuzzy_file_search.rs b/codex-rs/app-server/tests/suite/fuzzy_file_search.rs index 692304c6f..5a34fa4d3 100644 --- a/codex-rs/app-server/tests/suite/fuzzy_file_search.rs +++ b/codex-rs/app-server/tests/suite/fuzzy_file_search.rs @@ -237,7 +237,11 @@ async fn test_fuzzy_file_search_sorts_and_includes_indices() -> Result<()> { let root_path = root.path().to_string_lossy().to_string(); // Send fuzzyFileSearch request. let request_id = mcp - .send_fuzzy_file_search_request("abe", vec![root_path.clone()], None) + .send_fuzzy_file_search_request( + "abe", + vec![root_path.clone()], + /*cancellation_token*/ None, + ) .await?; // Read response and verify shape and ordering. @@ -298,7 +302,11 @@ async fn test_fuzzy_file_search_accepts_cancellation_token() -> Result<()> { let root_path = root.path().to_string_lossy().to_string(); let request_id = mcp - .send_fuzzy_file_search_request("alp", vec![root_path.clone()], None) + .send_fuzzy_file_search_request( + "alp", + vec![root_path.clone()], + /*cancellation_token*/ None, + ) .await?; let request_id_2 = mcp diff --git a/codex-rs/app-server/tests/suite/v2/account.rs b/codex-rs/app-server/tests/suite/v2/account.rs index 9458ae7f2..1505060a9 100644 --- a/codex-rs/app-server/tests/suite/v2/account.rs +++ b/codex-rs/app-server/tests/suite/v2/account.rs @@ -981,7 +981,7 @@ async fn login_account_chatgpt_device_code_returns_error_when_disabled() -> Resu }, )?; write_models_cache(codex_home.path())?; - mock_device_code_usercode_failure(&mock_server, 404).await; + mock_device_code_usercode_failure(&mock_server, /*status*/ 404).await; let issuer = mock_server.uri(); let mut mcp = McpProcess::new_with_env( @@ -1038,7 +1038,7 @@ async fn login_account_chatgpt_device_code_succeeds_and_notifies() -> Result<()> )?; write_models_cache(codex_home.path())?; - mock_device_code_usercode(&mock_server, 0).await; + mock_device_code_usercode(&mock_server, /*interval_seconds*/ 0).await; mock_device_code_token_success(&mock_server).await; let id_token = encode_id_token( &ChatGptIdTokenClaims::new() @@ -1122,8 +1122,8 @@ async fn login_account_chatgpt_device_code_failure_notifies_without_account_upda )?; write_models_cache(codex_home.path())?; - mock_device_code_usercode(&mock_server, 0).await; - mock_device_code_token_failure(&mock_server, 500).await; + mock_device_code_usercode(&mock_server, /*interval_seconds*/ 0).await; + mock_device_code_token_failure(&mock_server, /*status*/ 500).await; let issuer = mock_server.uri(); let mut mcp = McpProcess::new_with_env( @@ -1197,8 +1197,8 @@ async fn login_account_chatgpt_device_code_can_be_cancelled() -> Result<()> { )?; write_models_cache(codex_home.path())?; - mock_device_code_usercode(&mock_server, 1).await; - mock_device_code_token_failure(&mock_server, 404).await; + mock_device_code_usercode(&mock_server, /*interval_seconds*/ 1).await; + mock_device_code_token_failure(&mock_server, /*status*/ 404).await; let issuer = mock_server.uri(); let mut mcp = McpProcess::new_with_env( diff --git a/codex-rs/app-server/tests/suite/v2/analytics.rs b/codex-rs/app-server/tests/suite/v2/analytics.rs index e64287cb2..a389ffbe1 100644 --- a/codex-rs/app-server/tests/suite/v2/analytics.rs +++ b/codex-rs/app-server/tests/suite/v2/analytics.rs @@ -31,7 +31,7 @@ async fn app_server_default_analytics_disabled_without_flag() -> Result<()> { &config, SERVICE_VERSION, Some("codex-app-server"), - false, + /*default_analytics_enabled*/ false, ) .map_err(|err| anyhow::anyhow!(err.to_string()))?; @@ -56,7 +56,7 @@ async fn app_server_default_analytics_enabled_with_flag() -> Result<()> { &config, SERVICE_VERSION, Some("codex-app-server"), - true, + /*default_analytics_enabled*/ true, ) .map_err(|err| anyhow::anyhow!(err.to_string()))?; diff --git a/codex-rs/app-server/tests/suite/v2/command_exec.rs b/codex-rs/app-server/tests/suite/v2/command_exec.rs index ecd897eb8..50e828566 100644 --- a/codex-rs/app-server/tests/suite/v2/command_exec.rs +++ b/codex-rs/app-server/tests/suite/v2/command_exec.rs @@ -722,15 +722,15 @@ async fn command_exec_process_ids_are_connection_scoped_and_disconnect_terminate let mut ws1 = connect_websocket(bind_addr).await?; let mut ws2 = connect_websocket(bind_addr).await?; - send_initialize_request(&mut ws1, 1, "ws_client_one").await?; - read_initialize_response(&mut ws1, 1).await?; - send_initialize_request(&mut ws2, 2, "ws_client_two").await?; - read_initialize_response(&mut ws2, 2).await?; + send_initialize_request(&mut ws1, /*id*/ 1, "ws_client_one").await?; + read_initialize_response(&mut ws1, /*request_id*/ 1).await?; + send_initialize_request(&mut ws2, /*id*/ 2, "ws_client_two").await?; + read_initialize_response(&mut ws2, /*request_id*/ 2).await?; send_request( &mut ws1, "command/exec", - 101, + /*id*/ 101, Some(serde_json::json!({ "command": [ "python3", @@ -749,12 +749,12 @@ async fn command_exec_process_ids_are_connection_scoped_and_disconnect_terminate assert_eq!(delta.stream, CommandExecOutputStream::Stdout); let delta_text = String::from_utf8(STANDARD.decode(&delta.delta_base64)?)?; assert!(delta_text.contains("ready")); - wait_for_process_marker(&marker, true).await?; + wait_for_process_marker(&marker, /*should_exist*/ true).await?; send_request( &mut ws2, "command/exec/terminate", - 102, + /*id*/ 102, Some(serde_json::json!({ "processId": "shared-process", })), @@ -773,12 +773,12 @@ async fn command_exec_process_ids_are_connection_scoped_and_disconnect_terminate terminate_error.error.message, "no active command/exec for process id \"shared-process\"" ); - wait_for_process_marker(&marker, true).await?; + wait_for_process_marker(&marker, /*should_exist*/ true).await?; assert_no_message(&mut ws2, Duration::from_millis(250)).await?; ws1.close(None).await?; - wait_for_process_marker(&marker, false).await?; + wait_for_process_marker(&marker, /*should_exist*/ false).await?; process .kill() diff --git a/codex-rs/app-server/tests/suite/v2/compaction.rs b/codex-rs/app-server/tests/suite/v2/compaction.rs index c0922d325..a1bde9e96 100644 --- a/codex-rs/app-server/tests/suite/v2/compaction.rs +++ b/codex-rs/app-server/tests/suite/v2/compaction.rs @@ -50,19 +50,19 @@ async fn auto_compaction_local_emits_started_and_completed_items() -> Result<()> let server = responses::start_mock_server().await; let sse1 = responses::sse(vec![ responses::ev_assistant_message("m1", "FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 70_000), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = responses::sse(vec![ responses::ev_assistant_message("m2", "SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 330_000), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let sse3 = responses::sse(vec![ responses::ev_assistant_message("m3", "LOCAL_SUMMARY"), - responses::ev_completed_with_tokens("r3", 200), + responses::ev_completed_with_tokens("r3", /*total_tokens*/ 200), ]); let sse4 = responses::sse(vec![ responses::ev_assistant_message("m4", "FINAL_REPLY"), - responses::ev_completed_with_tokens("r4", 120), + responses::ev_completed_with_tokens("r4", /*total_tokens*/ 120), ]); responses::mount_sse_sequence(&server, vec![sse1, sse2, sse3, sse4]).await; @@ -72,7 +72,7 @@ async fn auto_compaction_local_emits_started_and_completed_items() -> Result<()> &server.uri(), &BTreeMap::default(), AUTO_COMPACT_LIMIT, - None, + /*requires_openai_auth*/ None, "mock_provider", COMPACT_PROMPT, )?; @@ -110,15 +110,15 @@ async fn auto_compaction_remote_emits_started_and_completed_items() -> Result<() let server = responses::start_mock_server().await; let sse1 = responses::sse(vec![ responses::ev_assistant_message("m1", "FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 70_000), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = responses::sse(vec![ responses::ev_assistant_message("m2", "SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 330_000), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let sse3 = responses::sse(vec![ responses::ev_assistant_message("m3", "FINAL_REPLY"), - responses::ev_completed_with_tokens("r3", 120), + responses::ev_completed_with_tokens("r3", /*total_tokens*/ 120), ]); let responses_log = responses::mount_sse_sequence(&server, vec![sse1, sse2, sse3]).await; @@ -197,7 +197,7 @@ async fn thread_compact_start_triggers_compaction_and_returns_empty_response() - let server = responses::start_mock_server().await; let sse = responses::sse(vec![ responses::ev_assistant_message("m1", "MANUAL_COMPACT_SUMMARY"), - responses::ev_completed_with_tokens("r1", 200), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 200), ]); responses::mount_sse_sequence(&server, vec![sse]).await; @@ -207,7 +207,7 @@ async fn thread_compact_start_triggers_compaction_and_returns_empty_response() - &server.uri(), &BTreeMap::default(), AUTO_COMPACT_LIMIT, - None, + /*requires_openai_auth*/ None, "mock_provider", COMPACT_PROMPT, )?; @@ -257,7 +257,7 @@ async fn thread_compact_start_rejects_invalid_thread_id() -> Result<()> { &server.uri(), &BTreeMap::default(), AUTO_COMPACT_LIMIT, - None, + /*requires_openai_auth*/ None, "mock_provider", COMPACT_PROMPT, )?; @@ -293,7 +293,7 @@ async fn thread_compact_start_rejects_unknown_thread_id() -> Result<()> { &server.uri(), &BTreeMap::default(), AUTO_COMPACT_LIMIT, - None, + /*requires_openai_auth*/ None, "mock_provider", COMPACT_PROMPT, )?; diff --git a/codex-rs/app-server/tests/suite/v2/connection_handling_websocket.rs b/codex-rs/app-server/tests/suite/v2/connection_handling_websocket.rs index 19158c68c..bc311b31c 100644 --- a/codex-rs/app-server/tests/suite/v2/connection_handling_websocket.rs +++ b/codex-rs/app-server/tests/suite/v2/connection_handling_websocket.rs @@ -58,27 +58,27 @@ async fn websocket_transport_routes_per_connection_handshake_and_responses() -> let mut ws1 = connect_websocket(bind_addr).await?; let mut ws2 = connect_websocket(bind_addr).await?; - send_initialize_request(&mut ws1, 1, "ws_client_one").await?; - let first_init = read_response_for_id(&mut ws1, 1).await?; + send_initialize_request(&mut ws1, /*id*/ 1, "ws_client_one").await?; + let first_init = read_response_for_id(&mut ws1, /*id*/ 1).await?; assert_eq!(first_init.id, RequestId::Integer(1)); // Initialize responses are request-scoped and must not leak to other // connections. assert_no_message(&mut ws2, Duration::from_millis(250)).await?; - send_config_read_request(&mut ws2, 2).await?; - let not_initialized = read_error_for_id(&mut ws2, 2).await?; + send_config_read_request(&mut ws2, /*id*/ 2).await?; + let not_initialized = read_error_for_id(&mut ws2, /*id*/ 2).await?; assert_eq!(not_initialized.error.message, "Not initialized"); - send_initialize_request(&mut ws2, 3, "ws_client_two").await?; - let second_init = read_response_for_id(&mut ws2, 3).await?; + send_initialize_request(&mut ws2, /*id*/ 3, "ws_client_two").await?; + let second_init = read_response_for_id(&mut ws2, /*id*/ 3).await?; assert_eq!(second_init.id, RequestId::Integer(3)); // Same request-id on different connections must route independently. - send_config_read_request(&mut ws1, 77).await?; - send_config_read_request(&mut ws2, 77).await?; - let ws1_config = read_response_for_id(&mut ws1, 77).await?; - let ws2_config = read_response_for_id(&mut ws2, 77).await?; + send_config_read_request(&mut ws1, /*id*/ 77).await?; + send_config_read_request(&mut ws2, /*id*/ 77).await?; + let ws1_config = read_response_for_id(&mut ws1, /*id*/ 77).await?; + let ws2_config = read_response_for_id(&mut ws2, /*id*/ 77).await?; assert_eq!(ws1_config.id, RequestId::Integer(77)); assert_eq!(ws2_config.id, RequestId::Integer(77)); @@ -108,8 +108,8 @@ async fn websocket_transport_serves_health_endpoints_on_same_listener() -> Resul assert_eq!(healthz.status(), StatusCode::OK); let mut ws = connect_websocket(bind_addr).await?; - send_initialize_request(&mut ws, 1, "ws_health_client").await?; - let init = read_response_for_id(&mut ws, 1).await?; + send_initialize_request(&mut ws, /*id*/ 1, "ws_health_client").await?; + let init = read_response_for_id(&mut ws, /*id*/ 1).await?; assert_eq!(init.id, RequestId::Integer(1)); process @@ -128,14 +128,14 @@ async fn websocket_transport_rejects_browser_origin_without_auth() -> Result<()> let (mut process, bind_addr) = spawn_websocket_server(codex_home.path()).await?; let mut ws = connect_websocket(bind_addr).await?; - send_initialize_request(&mut ws, 1, "ws_loopback_client").await?; - let init = read_response_for_id(&mut ws, 1).await?; + send_initialize_request(&mut ws, /*id*/ 1, "ws_loopback_client").await?; + let init = read_response_for_id(&mut ws, /*id*/ 1).await?; assert_eq!(init.id, RequestId::Integer(1)); drop(ws); assert_websocket_connect_rejected_with_headers( bind_addr, - None, + /*bearer_token*/ None, Some("https://evil.example"), StatusCode::FORBIDDEN, ) @@ -165,12 +165,12 @@ async fn websocket_transport_rejects_missing_and_invalid_capability_tokens() -> let (mut process, bind_addr) = spawn_websocket_server_with_args(codex_home.path(), "ws://127.0.0.1:0", &auth_args).await?; - assert_websocket_connect_rejected(bind_addr, None).await?; + assert_websocket_connect_rejected(bind_addr, /*bearer_token*/ None).await?; assert_websocket_connect_rejected(bind_addr, Some("wrong-token")).await?; let mut ws = connect_websocket_with_bearer(bind_addr, Some("super-secret-token")).await?; - send_initialize_request(&mut ws, 1, "ws_auth_client").await?; - let init = read_response_for_id(&mut ws, 1).await?; + send_initialize_request(&mut ws, /*id*/ 1, "ws_auth_client").await?; + let init = read_response_for_id(&mut ws, /*id*/ 1).await?; assert_eq!(init.id, RequestId::Integer(1)); process @@ -266,8 +266,8 @@ async fn websocket_transport_verifies_signed_short_lived_bearer_tokens() -> Resu }), )?; let mut ws = connect_websocket_with_bearer(bind_addr, Some(valid_token.as_str())).await?; - send_initialize_request(&mut ws, 1, "ws_signed_auth_client").await?; - let init = read_response_for_id(&mut ws, 1).await?; + send_initialize_request(&mut ws, /*id*/ 1, "ws_signed_auth_client").await?; + let init = read_response_for_id(&mut ws, /*id*/ 1).await?; assert_eq!(init.id, RequestId::Integer(1)); process @@ -320,8 +320,8 @@ async fn websocket_transport_allows_unauthenticated_non_loopback_startup_by_defa spawn_websocket_server_with_args(codex_home.path(), "ws://0.0.0.0:0", &[]).await?; let mut ws = connect_websocket(bind_addr).await?; - send_initialize_request(&mut ws, 1, "ws_non_loopback_default_client").await?; - let init = read_response_for_id(&mut ws, 1).await?; + send_initialize_request(&mut ws, /*id*/ 1, "ws_non_loopback_default_client").await?; + let init = read_response_for_id(&mut ws, /*id*/ 1).await?; assert_eq!(init.id, RequestId::Integer(1)); process @@ -411,7 +411,7 @@ pub(super) async fn spawn_websocket_server_with_args( } pub(super) async fn connect_websocket(bind_addr: SocketAddr) -> Result { - connect_websocket_with_bearer(bind_addr, None).await + connect_websocket_with_bearer(bind_addr, /*bearer_token*/ None).await } pub(super) async fn connect_websocket_with_bearer( @@ -419,7 +419,7 @@ pub(super) async fn connect_websocket_with_bearer( bearer_token: Option<&str>, ) -> Result { let url = format!("ws://{}", connectable_bind_addr(bind_addr)); - let request = websocket_request(url.as_str(), bearer_token, None)?; + let request = websocket_request(url.as_str(), bearer_token, /*origin*/ None)?; let deadline = Instant::now() + Duration::from_secs(10); loop { match connect_async(request.clone()).await { @@ -441,7 +441,7 @@ async fn assert_websocket_connect_rejected( assert_websocket_connect_rejected_with_headers( bind_addr, bearer_token, - None, + /*origin*/ None, StatusCode::UNAUTHORIZED, ) .await diff --git a/codex-rs/app-server/tests/suite/v2/connection_handling_websocket_unix.rs b/codex-rs/app-server/tests/suite/v2/connection_handling_websocket_unix.rs index 08156b9d9..591b70af0 100644 --- a/codex-rs/app-server/tests/suite/v2/connection_handling_websocket_unix.rs +++ b/codex-rs/app-server/tests/suite/v2/connection_handling_websocket_unix.rs @@ -156,16 +156,16 @@ async fn start_ctrl_c_restart_fixture(turn_delay: Duration) -> Result Model { fn expected_visible_models() -> Vec { // Filter by supported_in_api to support testing with both ChatGPT and non-ChatGPT auth modes. - let mut presets = - ModelPreset::filter_by_auth(codex_core::test_support::all_model_presets().clone(), false); + let mut presets = ModelPreset::filter_by_auth( + codex_core::test_support::all_model_presets().clone(), + /*chatgpt_mode*/ false, + ); // Mirror `ModelsManager::build_available_models()` default selection after auth filtering. ModelPreset::mark_default_by_picker_visibility(&mut presets); diff --git a/codex-rs/app-server/tests/suite/v2/plan_item.rs b/codex-rs/app-server/tests/suite/v2/plan_item.rs index 0ed93cbea..97e67fa09 100644 --- a/codex-rs/app-server/tests/suite/v2/plan_item.rs +++ b/codex-rs/app-server/tests/suite/v2/plan_item.rs @@ -59,7 +59,7 @@ async fn plan_mode_uses_proposed_plan_block_for_plan_item() -> Result<()> { let turn = start_plan_mode_turn(&mut mcp).await?; let (_, completed_items, plan_deltas, turn_completed) = collect_turn_notifications(&mut mcp).await?; - wait_for_responses_request_count(&server, 1).await?; + wait_for_responses_request_count(&server, /*expected_count*/ 1).await?; assert_eq!(turn_completed.turn.id, turn.id); assert_eq!(turn_completed.turn.status, TurnStatus::Completed); @@ -116,7 +116,7 @@ async fn plan_mode_without_proposed_plan_does_not_emit_plan_item() -> Result<()> let _turn = start_plan_mode_turn(&mut mcp).await?; let (_, completed_items, plan_deltas, _) = collect_turn_notifications(&mut mcp).await?; - wait_for_responses_request_count(&server, 1).await?; + wait_for_responses_request_count(&server, /*expected_count*/ 1).await?; let has_plan_item = completed_items .iter() diff --git a/codex-rs/app-server/tests/suite/v2/plugin_install.rs b/codex-rs/app-server/tests/suite/v2/plugin_install.rs index 8c597d94a..90a7d813b 100644 --- a/codex-rs/app-server/tests/suite/v2/plugin_install.rs +++ b/codex-rs/app-server/tests/suite/v2/plugin_install.rs @@ -118,7 +118,7 @@ async fn plugin_install_returns_invalid_request_for_not_available_plugin() -> Re "sample-plugin", "./sample-plugin", Some("NOT_AVAILABLE"), - None, + /*auth_policy*/ None, )?; write_plugin_source(repo_root.path(), "sample-plugin", &[])?; let marketplace_path = @@ -217,8 +217,8 @@ async fn plugin_install_force_remote_sync_enables_remote_plugin_before_local_ins "debug", "sample-plugin", "./sample-plugin", - None, - None, + /*install_policy*/ None, + /*auth_policy*/ None, )?; write_plugin_source(repo_root.path(), "sample-plugin", &[])?; let marketplace_path = @@ -286,8 +286,8 @@ async fn plugin_install_tracks_analytics_event() -> Result<()> { "debug", "sample-plugin", "./sample-plugin", - None, - None, + /*install_policy*/ None, + /*auth_policy*/ None, )?; write_plugin_source(repo_root.path(), "sample-plugin", &[])?; let marketplace_path = @@ -401,8 +401,8 @@ async fn plugin_install_returns_apps_needing_auth() -> Result<()> { "debug", "sample-plugin", "./sample-plugin", - None, - None, + /*install_policy*/ None, + /*auth_policy*/ None, )?; write_plugin_source(repo_root.path(), "sample-plugin", &["alpha", "beta"])?; let marketplace_path = @@ -481,7 +481,7 @@ async fn plugin_install_filters_disallowed_apps_needing_auth() -> Result<()> { "debug", "sample-plugin", "./sample-plugin", - None, + /*install_policy*/ None, Some("ON_USE"), )?; write_plugin_source( @@ -542,8 +542,8 @@ async fn plugin_install_makes_bundled_mcp_servers_available_to_followup_requests "debug", "sample-plugin", "./sample-plugin", - None, - None, + /*install_policy*/ None, + /*auth_policy*/ None, )?; write_plugin_source(repo_root.path(), "sample-plugin", &[])?; std::fs::write( diff --git a/codex-rs/app-server/tests/suite/v2/plugin_list.rs b/codex-rs/app-server/tests/suite/v2/plugin_list.rs index ce3d4f528..4136c6d67 100644 --- a/codex-rs/app-server/tests/suite/v2/plugin_list.rs +++ b/codex-rs/app-server/tests/suite/v2/plugin_list.rs @@ -931,7 +931,8 @@ async fn app_server_startup_remote_plugin_sync_runs_once() -> Result<()> { timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; wait_for_path_exists(&marker_path).await?; - wait_for_remote_plugin_request_count(&server, "/plugins/list", 1).await?; + wait_for_remote_plugin_request_count(&server, "/plugins/list", /*expected_count*/ 1) + .await?; let request_id = mcp .send_plugin_list_request(PluginListParams { cwds: None, @@ -957,7 +958,8 @@ async fn app_server_startup_remote_plugin_sync_runs_once() -> Result<()> { .collect::>(), vec![("linear@openai-curated".to_string(), true, true)] ); - wait_for_remote_plugin_request_count(&server, "/plugins/list", 1).await?; + wait_for_remote_plugin_request_count(&server, "/plugins/list", /*expected_count*/ 1) + .await?; } let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?; @@ -969,7 +971,7 @@ async fn app_server_startup_remote_plugin_sync_runs_once() -> Result<()> { } tokio::time::sleep(Duration::from_millis(250)).await; - wait_for_remote_plugin_request_count(&server, "/plugins/list", 1).await?; + wait_for_remote_plugin_request_count(&server, "/plugins/list", /*expected_count*/ 1).await?; Ok(()) } @@ -1029,7 +1031,7 @@ async fn plugin_list_uses_warmed_featured_plugin_ids_cache_on_first_request() -> let mut mcp = McpProcess::new(codex_home.path()).await?; timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; - wait_for_featured_plugin_request_count(&server, 1).await?; + wait_for_featured_plugin_request_count(&server, /*expected_count*/ 1).await?; let request_id = mcp .send_plugin_list_request(PluginListParams { diff --git a/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs b/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs index e8a39efa6..317155da7 100644 --- a/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs +++ b/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs @@ -99,7 +99,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> { codex_home.path(), &responses_server.uri(), realtime_server.uri(), - true, + /*realtime_enabled*/ true, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -137,7 +137,9 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> { assert!(started.session_id.is_some()); assert_eq!(started.version, RealtimeConversationVersion::V2); - let startup_context_request = realtime_server.wait_for_request(0, 0).await; + let startup_context_request = realtime_server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 0) + .await; assert_eq!( startup_context_request.body_json()["type"].as_str(), Some("session.update") @@ -306,7 +308,7 @@ async fn realtime_conversation_stop_emits_closed_notification() -> Result<()> { codex_home.path(), &responses_server.uri(), realtime_server.uri(), - true, + /*realtime_enabled*/ true, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -378,7 +380,7 @@ async fn realtime_conversation_requires_feature_flag() -> Result<()> { codex_home.path(), &responses_server.uri(), realtime_server.uri(), - false, + /*realtime_enabled*/ false, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; diff --git a/codex-rs/app-server/tests/suite/v2/review.rs b/codex-rs/app-server/tests/suite/v2/review.rs index 6febbaf52..d56b9318e 100644 --- a/codex-rs/app-server/tests/suite/v2/review.rs +++ b/codex-rs/app-server/tests/suite/v2/review.rs @@ -149,7 +149,7 @@ async fn review_start_exec_approval_item_id_matches_command_execution_item() -> "rev-parse".to_string(), "HEAD".to_string(), ], - None, + /*workdir*/ None, Some(5000), "review-call-1", )?, diff --git a/codex-rs/app-server/tests/suite/v2/thread_fork.rs b/codex-rs/app-server/tests/suite/v2/thread_fork.rs index a81c87bd4..e6be4e5a7 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_fork.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_fork.rs @@ -53,7 +53,7 @@ async fn thread_fork_creates_new_thread_and_emits_started() -> Result<()> { "2025-01-05T12:00:00Z", preview, Some("mock_provider"), - None, + /*git_info*/ None, )?; let original_path = codex_home @@ -267,7 +267,7 @@ async fn thread_fork_surfaces_cloud_requirements_load_errors() -> Result<()> { "2025-01-05T12:00:00Z", "Saved user message", Some("mock_provider"), - None, + /*git_info*/ None, )?; let refresh_token_url = format!("{}/oauth/token", server.uri()); @@ -331,7 +331,7 @@ async fn thread_fork_ephemeral_remains_pathless_and_omits_listing() -> Result<() "2025-01-05T12:00:00Z", preview, Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; diff --git a/codex-rs/app-server/tests/suite/v2/thread_list.rs b/codex-rs/app-server/tests/suite/v2/thread_list.rs index 2b5d1fe8a..62faba9c1 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_list.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_list.rs @@ -58,7 +58,16 @@ async fn list_threads( source_kinds: Option>, archived: Option, ) -> Result { - list_threads_with_sort(mcp, cursor, limit, providers, source_kinds, None, archived).await + list_threads_with_sort( + mcp, + cursor, + limit, + providers, + source_kinds, + /*sort_key*/ None, + archived, + ) + .await } async fn list_threads_with_sort( @@ -110,7 +119,7 @@ where &ts_rfc, preview, Some(provider_for_index(i)), - None, + /*git_info*/ None, )?); } Ok(ids) @@ -172,11 +181,11 @@ async fn thread_list_basic_empty() -> Result<()> { data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert!(data.is_empty()); @@ -256,7 +265,7 @@ async fn thread_list_reports_system_error_idle_flag_after_failed_turn() -> Resul let ThreadListResponse { data, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ @@ -264,7 +273,7 @@ async fn thread_list_reports_system_error_idle_flag_after_failed_turn() -> Resul ThreadSourceKind::Cli, ThreadSourceKind::VsCode, ]), - None, + /*archived*/ None, ) .await?; let listed = data @@ -323,7 +332,7 @@ async fn thread_list_pagination_next_cursor_none_on_last_page() -> Result<()> { "2025-01-02T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let _b = create_fake_rollout( codex_home.path(), @@ -331,7 +340,7 @@ async fn thread_list_pagination_next_cursor_none_on_last_page() -> Result<()> { "2025-01-01T13:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let _c = create_fake_rollout( codex_home.path(), @@ -339,7 +348,7 @@ async fn thread_list_pagination_next_cursor_none_on_last_page() -> Result<()> { "2025-01-01T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = init_mcp(codex_home.path()).await?; @@ -350,11 +359,11 @@ async fn thread_list_pagination_next_cursor_none_on_last_page() -> Result<()> { next_cursor: cursor1, } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(2), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!(data1.len(), 2); @@ -380,8 +389,8 @@ async fn thread_list_pagination_next_cursor_none_on_last_page() -> Result<()> { Some(cursor1), Some(2), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert!(data2.len() <= 2); @@ -413,7 +422,7 @@ async fn thread_list_respects_provider_filter() -> Result<()> { "2025-01-02T10:00:00Z", "X", Some("mock_provider"), - None, + /*git_info*/ None, )?; // mock_provider let _b = create_fake_rollout( codex_home.path(), @@ -421,7 +430,7 @@ async fn thread_list_respects_provider_filter() -> Result<()> { "2025-01-02T11:00:00Z", "X", Some("other_provider"), - None, + /*git_info*/ None, )?; let mut mcp = init_mcp(codex_home.path()).await?; @@ -431,11 +440,11 @@ async fn thread_list_respects_provider_filter() -> Result<()> { data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["other_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!(data.len(), 1); @@ -465,7 +474,7 @@ async fn thread_list_respects_cwd_filter() -> Result<()> { "2025-01-02T10:00:00Z", "filtered", Some("mock_provider"), - None, + /*git_info*/ None, )?; let unfiltered_id = create_fake_rollout( codex_home.path(), @@ -473,7 +482,7 @@ async fn thread_list_respects_cwd_filter() -> Result<()> { "2025-01-02T11:00:00Z", "unfiltered", Some("mock_provider"), - None, + /*git_info*/ None, )?; let target_cwd = codex_home.path().join("target-cwd"); @@ -535,7 +544,7 @@ sqlite = true "2025-01-02T10:00:00Z", "match: needle", Some("mock_provider"), - None, + /*git_info*/ None, )?; let _non_match = create_fake_rollout( codex_home.path(), @@ -543,7 +552,7 @@ sqlite = true "2025-01-02T11:00:00Z", "no hit here", Some("mock_provider"), - None, + /*git_info*/ None, )?; let newer_match = create_fake_rollout( codex_home.path(), @@ -551,7 +560,7 @@ sqlite = true "2025-01-02T12:00:00Z", "needle suffix", Some("mock_provider"), - None, + /*git_info*/ None, )?; // `thread/list` only applies `search_term` on the sqlite path. In this test we @@ -560,7 +569,9 @@ sqlite = true let state_db = codex_state::StateRuntime::init(codex_home.path().to_path_buf(), "mock_provider".into()) .await?; - state_db.mark_backfill_complete(None).await?; + state_db + .mark_backfill_complete(/*last_watermark*/ None) + .await?; let mut mcp = init_mcp(codex_home.path()).await?; let request_id = mcp @@ -602,7 +613,7 @@ async fn thread_list_empty_source_kinds_defaults_to_interactive_only() -> Result "2025-02-01T10:00:00Z", "CLI", Some("mock_provider"), - None, + /*git_info*/ None, )?; let exec_id = create_fake_rollout_with_source( codex_home.path(), @@ -610,7 +621,7 @@ async fn thread_list_empty_source_kinds_defaults_to_interactive_only() -> Result "2025-02-01T11:00:00Z", "Exec", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::Exec, )?; @@ -620,11 +631,11 @@ async fn thread_list_empty_source_kinds_defaults_to_interactive_only() -> Result data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(Vec::new()), - None, + /*archived*/ None, ) .await?; @@ -648,7 +659,7 @@ async fn thread_list_filters_by_source_kind_subagent_thread_spawn() -> Result<() "2025-02-01T10:00:00Z", "CLI", Some("mock_provider"), - None, + /*git_info*/ None, )?; let parent_thread_id = ThreadId::from_string(&Uuid::new_v4().to_string())?; @@ -658,7 +669,7 @@ async fn thread_list_filters_by_source_kind_subagent_thread_spawn() -> Result<() "2025-02-01T11:00:00Z", "SubAgent", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::SubAgent(SubAgentSource::ThreadSpawn { parent_thread_id, depth: 1, @@ -674,11 +685,11 @@ async fn thread_list_filters_by_source_kind_subagent_thread_spawn() -> Result<() data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ThreadSourceKind::SubAgentThreadSpawn]), - None, + /*archived*/ None, ) .await?; @@ -704,7 +715,7 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { "2025-02-02T09:00:00Z", "Review", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::SubAgent(SubAgentSource::Review), )?; let compact_id = create_fake_rollout_with_source( @@ -713,7 +724,7 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { "2025-02-02T10:00:00Z", "Compact", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::SubAgent(SubAgentSource::Compact), )?; let spawn_id = create_fake_rollout_with_source( @@ -722,7 +733,7 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { "2025-02-02T11:00:00Z", "Spawn", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::SubAgent(SubAgentSource::ThreadSpawn { parent_thread_id, depth: 1, @@ -737,7 +748,7 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { "2025-02-02T12:00:00Z", "Other", Some("mock_provider"), - None, + /*git_info*/ None, CoreSessionSource::SubAgent(SubAgentSource::Other("custom".to_string())), )?; @@ -745,11 +756,11 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { let review = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ThreadSourceKind::SubAgentReview]), - None, + /*archived*/ None, ) .await?; let review_ids: Vec<_> = review @@ -761,11 +772,11 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { let compact = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ThreadSourceKind::SubAgentCompact]), - None, + /*archived*/ None, ) .await?; let compact_ids: Vec<_> = compact @@ -777,11 +788,11 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { let spawn = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ThreadSourceKind::SubAgentThreadSpawn]), - None, + /*archived*/ None, ) .await?; let spawn_ids: Vec<_> = spawn.data.iter().map(|thread| thread.id.as_str()).collect(); @@ -789,11 +800,11 @@ async fn thread_list_filters_by_subagent_variant() -> Result<()> { let other = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), Some(vec![ThreadSourceKind::SubAgentOther]), - None, + /*archived*/ None, ) .await?; let other_ids: Vec<_> = other.data.iter().map(|thread| thread.id.as_str()).collect(); @@ -812,7 +823,7 @@ async fn thread_list_fetches_until_limit_or_exhausted() -> Result<()> { // paging past the first two pages to reach the desired count. create_fake_rollouts( codex_home.path(), - 24, + /*count*/ 24, |i| { if i < 16 { "skip_provider" @@ -820,7 +831,16 @@ async fn thread_list_fetches_until_limit_or_exhausted() -> Result<()> { "target_provider" } }, - |i| timestamp_at(2025, 3, 30 - i as u32, 12, 0, 0), + |i| { + timestamp_at( + /*year*/ 2025, + /*month*/ 3, + 30 - i as u32, + /*hour*/ 12, + /*minute*/ 0, + /*second*/ 0, + ) + }, "Hello", )?; @@ -832,11 +852,11 @@ async fn thread_list_fetches_until_limit_or_exhausted() -> Result<()> { data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(8), Some(vec!["target_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!( @@ -864,12 +884,19 @@ async fn thread_list_enforces_max_limit() -> Result<()> { create_fake_rollouts( codex_home.path(), - 105, + /*count*/ 105, |_| "mock_provider", |i| { let month = 5 + (i / 28); let day = (i % 28) + 1; - timestamp_at(2025, month as u32, day as u32, 0, 0, 0) + timestamp_at( + /*year*/ 2025, + month as u32, + day as u32, + /*hour*/ 0, + /*minute*/ 0, + /*second*/ 0, + ) }, "Hello", )?; @@ -880,11 +907,11 @@ async fn thread_list_enforces_max_limit() -> Result<()> { data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(200), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!( @@ -909,7 +936,7 @@ async fn thread_list_stops_when_not_enough_filtered_results_exist() -> Result<() // ensure the server exhausts pagination without looping forever. create_fake_rollouts( codex_home.path(), - 22, + /*count*/ 22, |i| { if i < 15 { "skip_provider" @@ -917,7 +944,16 @@ async fn thread_list_stops_when_not_enough_filtered_results_exist() -> Result<() "target_provider" } }, - |i| timestamp_at(2025, 4, 28 - i as u32, 8, 0, 0), + |i| { + timestamp_at( + /*year*/ 2025, + /*month*/ 4, + 28 - i as u32, + /*hour*/ 8, + /*minute*/ 0, + /*second*/ 0, + ) + }, "Hello", )?; @@ -929,11 +965,11 @@ async fn thread_list_stops_when_not_enough_filtered_results_exist() -> Result<() data, next_cursor, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["target_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!( @@ -977,11 +1013,11 @@ async fn thread_list_includes_git_info() -> Result<()> { let ThreadListResponse { data, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; let thread = data @@ -1013,7 +1049,7 @@ async fn thread_list_default_sorts_by_created_at() -> Result<()> { "2025-01-02T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_b = create_fake_rollout( codex_home.path(), @@ -1021,7 +1057,7 @@ async fn thread_list_default_sorts_by_created_at() -> Result<()> { "2025-01-01T13:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_c = create_fake_rollout( codex_home.path(), @@ -1029,19 +1065,19 @@ async fn thread_list_default_sorts_by_created_at() -> Result<()> { "2025-01-01T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = init_mcp(codex_home.path()).await?; let ThreadListResponse { data, .. } = list_threads_with_sort( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, - None, - None, + /*source_kinds*/ None, + /*sort_key*/ None, + /*archived*/ None, ) .await?; @@ -1062,7 +1098,7 @@ async fn thread_list_sort_updated_at_orders_by_mtime() -> Result<()> { "2025-01-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_mid = create_fake_rollout( codex_home.path(), @@ -1070,7 +1106,7 @@ async fn thread_list_sort_updated_at_orders_by_mtime() -> Result<()> { "2025-01-01T11:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_new = create_fake_rollout( codex_home.path(), @@ -1078,7 +1114,7 @@ async fn thread_list_sort_updated_at_orders_by_mtime() -> Result<()> { "2025-01-01T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; set_rollout_mtime( @@ -1098,12 +1134,12 @@ async fn thread_list_sort_updated_at_orders_by_mtime() -> Result<()> { let ThreadListResponse { data, .. } = list_threads_with_sort( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(ThreadSortKey::UpdatedAt), - None, + /*archived*/ None, ) .await?; @@ -1124,7 +1160,7 @@ async fn thread_list_updated_at_paginates_with_cursor() -> Result<()> { "2025-02-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_b = create_fake_rollout( codex_home.path(), @@ -1132,7 +1168,7 @@ async fn thread_list_updated_at_paginates_with_cursor() -> Result<()> { "2025-02-01T11:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_c = create_fake_rollout( codex_home.path(), @@ -1140,7 +1176,7 @@ async fn thread_list_updated_at_paginates_with_cursor() -> Result<()> { "2025-02-01T12:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; set_rollout_mtime( @@ -1164,12 +1200,12 @@ async fn thread_list_updated_at_paginates_with_cursor() -> Result<()> { .. } = list_threads_with_sort( &mut mcp, - None, + /*cursor*/ None, Some(2), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(ThreadSortKey::UpdatedAt), - None, + /*archived*/ None, ) .await?; let ids_page1: Vec<_> = page1.iter().map(|thread| thread.id.as_str()).collect(); @@ -1185,9 +1221,9 @@ async fn thread_list_updated_at_paginates_with_cursor() -> Result<()> { Some(cursor1), Some(2), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(ThreadSortKey::UpdatedAt), - None, + /*archived*/ None, ) .await?; let ids_page2: Vec<_> = page2.iter().map(|thread| thread.id.as_str()).collect(); @@ -1208,7 +1244,7 @@ async fn thread_list_created_at_tie_breaks_by_uuid() -> Result<()> { "2025-02-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_b = create_fake_rollout( codex_home.path(), @@ -1216,18 +1252,18 @@ async fn thread_list_created_at_tie_breaks_by_uuid() -> Result<()> { "2025-02-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = init_mcp(codex_home.path()).await?; let ThreadListResponse { data, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; @@ -1251,7 +1287,7 @@ async fn thread_list_updated_at_tie_breaks_by_uuid() -> Result<()> { "2025-02-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let id_b = create_fake_rollout( codex_home.path(), @@ -1259,7 +1295,7 @@ async fn thread_list_updated_at_tie_breaks_by_uuid() -> Result<()> { "2025-02-01T11:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; let updated_at = "2025-02-03T00:00:00Z"; @@ -1276,12 +1312,12 @@ async fn thread_list_updated_at_tie_breaks_by_uuid() -> Result<()> { let ThreadListResponse { data, .. } = list_threads_with_sort( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(ThreadSortKey::UpdatedAt), - None, + /*archived*/ None, ) .await?; @@ -1305,7 +1341,7 @@ async fn thread_list_updated_at_uses_mtime() -> Result<()> { "2025-02-01T10:00:00Z", "Hello", Some("mock_provider"), - None, + /*git_info*/ None, )?; set_rollout_mtime( @@ -1317,12 +1353,12 @@ async fn thread_list_updated_at_uses_mtime() -> Result<()> { let ThreadListResponse { data, .. } = list_threads_with_sort( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(ThreadSortKey::UpdatedAt), - None, + /*archived*/ None, ) .await?; @@ -1351,7 +1387,7 @@ async fn thread_list_archived_filter() -> Result<()> { "2025-03-01T10:00:00Z", "Active", Some("mock_provider"), - None, + /*git_info*/ None, )?; let archived_id = create_fake_rollout( codex_home.path(), @@ -1359,7 +1395,7 @@ async fn thread_list_archived_filter() -> Result<()> { "2025-03-01T09:00:00Z", "Archived", Some("mock_provider"), - None, + /*git_info*/ None, )?; let archived_dir = codex_home.path().join(ARCHIVED_SESSIONS_SUBDIR); @@ -1376,11 +1412,11 @@ async fn thread_list_archived_filter() -> Result<()> { let ThreadListResponse { data, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, - None, + /*source_kinds*/ None, + /*archived*/ None, ) .await?; assert_eq!(data.len(), 1); @@ -1388,10 +1424,10 @@ async fn thread_list_archived_filter() -> Result<()> { let ThreadListResponse { data, .. } = list_threads( &mut mcp, - None, + /*cursor*/ None, Some(10), Some(vec!["mock_provider".to_string()]), - None, + /*source_kinds*/ None, Some(true), ) .await?; diff --git a/codex-rs/app-server/tests/suite/v2/thread_metadata_update.rs b/codex-rs/app-server/tests/suite/v2/thread_metadata_update.rs index 680e70f2d..9ce233f94 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_metadata_update.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_metadata_update.rs @@ -184,7 +184,7 @@ async fn thread_metadata_update_repairs_missing_sqlite_row_for_stored_thread() - "2025-01-05T12:00:00Z", preview, Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -237,7 +237,7 @@ async fn thread_metadata_update_repairs_loaded_thread_without_resetting_summary( "2025-01-06T08:30:00Z", preview, Some("mock_provider"), - None, + /*git_info*/ None, )?; let thread_uuid = ThreadId::from_string(&thread_id)?; let rollout_path = rollout_path(codex_home.path(), "2025-01-06T08-30-00", &thread_id); @@ -245,10 +245,10 @@ async fn thread_metadata_update_repairs_loaded_thread_without_resetting_summary( Some(&state_db), rollout_path.as_path(), "mock_provider", - None, + /*builder*/ None, &[], - None, - None, + /*archived_only*/ None, + /*new_thread_memory_mode*/ None, ) .await; @@ -317,7 +317,7 @@ async fn thread_metadata_update_repairs_missing_sqlite_row_for_archived_thread() "2025-01-06T08:30:00Z", preview, Some("mock_provider"), - None, + /*git_info*/ None, )?; let archived_dir = codex_home.path().join(ARCHIVED_SESSIONS_SUBDIR); @@ -430,7 +430,9 @@ async fn thread_metadata_update_can_clear_stored_git_fields() -> Result<()> { async fn init_state_db(codex_home: &Path) -> Result> { let state_db = StateRuntime::init(codex_home.to_path_buf(), "mock_provider".into()).await?; - state_db.mark_backfill_complete(None).await?; + state_db + .mark_backfill_complete(/*last_watermark*/ None) + .await?; Ok(state_db) } diff --git a/codex-rs/app-server/tests/suite/v2/thread_name_websocket.rs b/codex-rs/app-server/tests/suite/v2/thread_name_websocket.rs index a05518fc3..4ec7344d6 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_name_websocket.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_name_websocket.rs @@ -43,14 +43,14 @@ async fn thread_name_updated_broadcasts_for_loaded_threads() -> Result<()> { send_request( &mut ws1, "thread/resume", - 10, + /*id*/ 10, Some(serde_json::to_value(ThreadResumeParams { thread_id: conversation_id.clone(), ..Default::default() })?), ) .await?; - let resume_resp: JSONRPCResponse = read_response_for_id(&mut ws1, 10).await?; + let resume_resp: JSONRPCResponse = read_response_for_id(&mut ws1, /*id*/ 10).await?; let resume: ThreadResumeResponse = to_response::(resume_resp)?; assert_eq!(resume.thread.id, conversation_id); @@ -58,15 +58,19 @@ async fn thread_name_updated_broadcasts_for_loaded_threads() -> Result<()> { send_request( &mut ws1, "thread/name/set", - 11, + /*id*/ 11, Some(serde_json::to_value(ThreadSetNameParams { thread_id: conversation_id.clone(), name: renamed.to_string(), })?), ) .await?; - let (rename_resp, ws1_notification) = - read_response_and_notification_for_method(&mut ws1, 11, "thread/name/updated").await?; + let (rename_resp, ws1_notification) = read_response_and_notification_for_method( + &mut ws1, + /*id*/ 11, + "thread/name/updated", + ) + .await?; let _: ThreadSetNameResponse = to_response::(rename_resp)?; assert_thread_name_updated(ws1_notification, &conversation_id, renamed)?; @@ -105,15 +109,19 @@ async fn thread_name_updated_broadcasts_for_not_loaded_threads() -> Result<()> { send_request( &mut ws1, "thread/name/set", - 20, + /*id*/ 20, Some(serde_json::to_value(ThreadSetNameParams { thread_id: conversation_id.clone(), name: renamed.to_string(), })?), ) .await?; - let (rename_resp, ws1_notification) = - read_response_and_notification_for_method(&mut ws1, 20, "thread/name/updated").await?; + let (rename_resp, ws1_notification) = read_response_and_notification_for_method( + &mut ws1, + /*id*/ 20, + "thread/name/updated", + ) + .await?; let _: ThreadSetNameResponse = to_response::(rename_resp)?; assert_thread_name_updated(ws1_notification, &conversation_id, renamed)?; @@ -135,11 +143,11 @@ async fn thread_name_updated_broadcasts_for_not_loaded_threads() -> Result<()> { } async fn initialize_both_clients(ws1: &mut WsClient, ws2: &mut WsClient) -> Result<()> { - send_initialize_request(ws1, 1, "ws_client_one").await?; - timeout(DEFAULT_READ_TIMEOUT, read_response_for_id(ws1, 1)).await??; + send_initialize_request(ws1, /*id*/ 1, "ws_client_one").await?; + timeout(DEFAULT_READ_TIMEOUT, read_response_for_id(ws1, /*id*/ 1)).await??; - send_initialize_request(ws2, 2, "ws_client_two").await?; - timeout(DEFAULT_READ_TIMEOUT, read_response_for_id(ws2, 2)).await??; + send_initialize_request(ws2, /*id*/ 2, "ws_client_two").await?; + timeout(DEFAULT_READ_TIMEOUT, read_response_for_id(ws2, /*id*/ 2)).await??; Ok(()) } @@ -151,7 +159,7 @@ fn create_rollout(codex_home: &std::path::Path, filename_ts: &str) -> Result Result<()> { .map(|elem| serde_json::to_value(elem).expect("serialize text element")) .collect(), Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -112,7 +112,7 @@ async fn thread_read_can_include_turns() -> Result<()> { .map(|elem| serde_json::to_value(elem).expect("serialize text element")) .collect(), Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -215,7 +215,7 @@ async fn thread_name_set_is_reflected_in_read_list_and_resume() -> Result<()> { preview, vec![], Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; diff --git a/codex-rs/app-server/tests/suite/v2/thread_resume.rs b/codex-rs/app-server/tests/suite/v2/thread_resume.rs index 4443abd6e..564de50d3 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_resume.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_resume.rs @@ -171,7 +171,7 @@ async fn thread_resume_returns_rollout_history() -> Result<()> { .map(|elem| serde_json::to_value(elem).expect("serialize text element")) .collect(), Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -368,7 +368,9 @@ stream_max_retries = 0 )?; let state_db = StateRuntime::init(codex_home.path().to_path_buf(), "mock_provider".into()).await?; - state_db.mark_backfill_complete(None).await?; + state_db + .mark_backfill_complete(/*last_watermark*/ None) + .await?; let mut mcp = McpProcess::new(codex_home.path()).await?; timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??; @@ -429,7 +431,7 @@ async fn thread_resume_and_read_interrupt_incomplete_rollout_turn_when_thread_is "Saved user message", Vec::new(), Some("mock_provider"), - None, + /*git_info*/ None, )?; let rollout_file_path = rollout_path(codex_home.path(), filename_ts, &conversation_id); let persisted_rollout = std::fs::read_to_string(&rollout_file_path)?; @@ -1022,7 +1024,7 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call-1", )?, @@ -1143,7 +1145,7 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R primary.read_stream_until_notification_message("turn/completed"), ) .await??; - wait_for_responses_request_count(&server, 3).await?; + wait_for_responses_request_count(&server, /*expected_count*/ 3).await?; Ok(()) } @@ -1309,7 +1311,7 @@ async fn thread_resume_replays_pending_file_change_request_approval() -> Result< primary.read_stream_until_notification_message("turn/completed"), ) .await??; - wait_for_responses_request_count(&server, 3).await?; + wait_for_responses_request_count(&server, /*expected_count*/ 3).await?; Ok(()) } @@ -1465,7 +1467,7 @@ async fn thread_resume_surfaces_cloud_requirements_load_errors() -> Result<()> { "Saved user message", Vec::new(), Some("mock_provider"), - None, + /*git_info*/ None, )?; let refresh_token_url = format!("{}/oauth/token", server.uri()); let mut mcp = McpProcess::new_with_env( @@ -1933,7 +1935,7 @@ fn setup_rollout_fixture(codex_home: &Path, server_uri: &str) -> Result .await??; let _: ThreadShellCommandResponse = to_response::(shell_resp)?; - let started = wait_for_command_execution_started(&mut mcp, None).await?; + let started = wait_for_command_execution_started(&mut mcp, /*expected_id*/ None).await?; let ThreadItem::CommandExecution { id, source, status, .. } = &started.item @@ -167,7 +167,7 @@ async fn thread_shell_command_uses_existing_active_turn() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call-approve", )?, @@ -345,7 +345,7 @@ async fn wait_for_command_execution_started_by_source( expected_source: CommandExecutionSource, ) -> Result { loop { - let started = wait_for_command_execution_started(mcp, None).await?; + let started = wait_for_command_execution_started(mcp, /*expected_id*/ None).await?; let ThreadItem::CommandExecution { source, .. } = &started.item else { continue; }; diff --git a/codex-rs/app-server/tests/suite/v2/thread_unsubscribe.rs b/codex-rs/app-server/tests/suite/v2/thread_unsubscribe.rs index 6427ae7ce..5808f0fe7 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_unsubscribe.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_unsubscribe.rs @@ -219,7 +219,7 @@ async fn thread_unsubscribe_during_turn_interrupts_turn_and_emits_thread_closed( wait_for_responses_request_count_to_stabilize( &server, - 1, + /*expected_count*/ 1, std::time::Duration::from_millis(200), ) .await?; diff --git a/codex-rs/app-server/tests/suite/v2/turn_start.rs b/codex-rs/app-server/tests/suite/v2/turn_start.rs index 8d7ca0261..3155a4be9 100644 --- a/codex-rs/app-server/tests/suite/v2/turn_start.rs +++ b/codex-rs/app-server/tests/suite/v2/turn_start.rs @@ -888,7 +888,7 @@ async fn turn_start_uses_migrated_pragmatic_personality_without_override_v2() -> "2025-01-01T00:00:00Z", "history user message", Some("mock_provider"), - None, + /*git_info*/ None, )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -1031,7 +1031,7 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call1", )?, @@ -1042,7 +1042,7 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call2", )?, @@ -1186,7 +1186,7 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call-decline", )?, @@ -1331,14 +1331,14 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> { let responses = vec![ create_shell_command_sse_response( vec!["echo".to_string(), "first".to_string(), "turn".to_string()], - None, + /*workdir*/ None, Some(5000), "call-first", )?, create_final_assistant_message_sse_response("done first")?, create_shell_command_sse_response( vec!["echo".to_string(), "second".to_string(), "turn".to_string()], - None, + /*workdir*/ None, Some(5000), "call-second", )?, diff --git a/codex-rs/app-server/tests/suite/v2/turn_start_zsh_fork.rs b/codex-rs/app-server/tests/suite/v2/turn_start_zsh_fork.rs index c8ae882e2..105ae5454 100644 --- a/codex-rs/app-server/tests/suite/v2/turn_start_zsh_fork.rs +++ b/codex-rs/app-server/tests/suite/v2/turn_start_zsh_fork.rs @@ -71,7 +71,7 @@ async fn turn_start_shell_zsh_fork_executes_command_v2() -> Result<()> { format!("while [ ! -f '{release_marker_escaped}' ]; do sleep 0.01; done"); let response = create_shell_command_sse_response( vec!["/bin/sh".to_string(), "-c".to_string(), wait_for_interrupt], - None, + /*workdir*/ None, Some(5000), "call-zsh-fork", )?; @@ -197,7 +197,7 @@ async fn turn_start_shell_zsh_fork_exec_approval_decline_v2() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call-zsh-fork-decline", )?, @@ -332,7 +332,7 @@ async fn turn_start_shell_zsh_fork_exec_approval_cancel_v2() -> Result<()> { "-c".to_string(), "print(42)".to_string(), ], - None, + /*workdir*/ None, Some(5000), "call-zsh-fork-cancel", )?]; @@ -805,7 +805,7 @@ fn find_test_zsh_path() -> Result> { ); return Ok(None); } - match core_test_support::fetch_dotslash_file(&dotslash_zsh, None) { + match core_test_support::fetch_dotslash_file(&dotslash_zsh, /*dotslash_cache*/ None) { Ok(path) => return Ok(Some(path)), Err(error) => { eprintln!("failed to fetch vendored zsh via dotslash: {error:#}"); diff --git a/codex-rs/app-server/tests/suite/v2/windows_sandbox_setup.rs b/codex-rs/app-server/tests/suite/v2/windows_sandbox_setup.rs index b3cbfdf32..a0466a459 100644 --- a/codex-rs/app-server/tests/suite/v2/windows_sandbox_setup.rs +++ b/codex-rs/app-server/tests/suite/v2/windows_sandbox_setup.rs @@ -26,7 +26,7 @@ async fn windows_sandbox_setup_start_emits_completion_notification() -> Result<( codex_home.path(), &server.uri(), &BTreeMap::new(), - 500_000, + /*auto_compact_limit*/ 500_000, Some(false), "mock_provider", "compact prompt", diff --git a/codex-rs/apply-patch/src/invocation.rs b/codex-rs/apply-patch/src/invocation.rs index 7623aef80..519671798 100644 --- a/codex-rs/apply-patch/src/invocation.rs +++ b/codex-rs/apply-patch/src/invocation.rs @@ -524,14 +524,14 @@ mod tests { #[test] fn test_heredoc() { - assert_match(&heredoc_script(""), None); + assert_match(&heredoc_script(""), /*expected_workdir*/ None); } #[test] fn test_heredoc_non_login_shell() { let script = heredoc_script(""); let args = strs_to_strings(&["bash", "-c", &script]); - assert_match_args(args, None); + assert_match_args(args, /*expected_workdir*/ None); } #[test] @@ -565,17 +565,20 @@ PATCH"#, #[test] fn test_powershell_heredoc() { let script = heredoc_script(""); - assert_match_args(args_powershell(&script), None); + assert_match_args(args_powershell(&script), /*expected_workdir*/ None); } #[test] fn test_powershell_heredoc_no_profile() { let script = heredoc_script(""); - assert_match_args(args_powershell_no_profile(&script), None); + assert_match_args( + args_powershell_no_profile(&script), + /*expected_workdir*/ None, + ); } #[test] fn test_pwsh_heredoc() { let script = heredoc_script(""); - assert_match_args(args_pwsh(&script), None); + assert_match_args(args_pwsh(&script), /*expected_workdir*/ None); } #[test] diff --git a/codex-rs/apply-patch/src/parser.rs b/codex-rs/apply-patch/src/parser.rs index 8785b3851..274a45497 100644 --- a/codex-rs/apply-patch/src/parser.rs +++ b/codex-rs/apply-patch/src/parser.rs @@ -672,7 +672,7 @@ fn test_parse_patch_lenient() { #[test] fn test_parse_one_hunk() { assert_eq!( - parse_one_hunk(&["bad"], 234), + parse_one_hunk(&["bad"], /*line_number*/ 234), Err(InvalidHunkError { message: "'bad' is not a valid hunk header. \ Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'".to_string(), @@ -685,7 +685,11 @@ fn test_parse_one_hunk() { #[test] fn test_update_file_chunk() { assert_eq!( - parse_update_file_chunk(&["bad"], 123, false), + parse_update_file_chunk( + &["bad"], + /*line_number*/ 123, + /*allow_missing_context*/ false + ), Err(InvalidHunkError { message: "Expected update hunk to start with a @@ context marker, got: 'bad'" .to_string(), @@ -693,14 +697,18 @@ fn test_update_file_chunk() { }) ); assert_eq!( - parse_update_file_chunk(&["@@"], 123, false), + parse_update_file_chunk( + &["@@"], + /*line_number*/ 123, + /*allow_missing_context*/ false + ), Err(InvalidHunkError { message: "Update hunk does not contain any lines".to_string(), line_number: 124 }) ); assert_eq!( - parse_update_file_chunk(&["@@", "bad"], 123, false), + parse_update_file_chunk(&["@@", "bad"], /*line_number*/ 123, /*allow_missing_context*/ false), Err(InvalidHunkError { message: "Unexpected line found in update hunk: 'bad'. \ Every line should start with ' ' (context line), '+' (added line), or '-' (removed line)".to_string(), @@ -708,7 +716,11 @@ fn test_update_file_chunk() { }) ); assert_eq!( - parse_update_file_chunk(&["@@", "*** End of File"], 123, false), + parse_update_file_chunk( + &["@@", "*** End of File"], + /*line_number*/ 123, + /*allow_missing_context*/ false + ), Err(InvalidHunkError { message: "Update hunk does not contain any lines".to_string(), line_number: 124 @@ -725,8 +737,8 @@ fn test_update_file_chunk() { " context2", "*** End Patch", ], - 123, - false + /*line_number*/ 123, + /*allow_missing_context*/ false ), Ok(( (UpdateFileChunk { @@ -749,7 +761,11 @@ fn test_update_file_chunk() { )) ); assert_eq!( - parse_update_file_chunk(&["@@", "+line", "*** End of File"], 123, false), + parse_update_file_chunk( + &["@@", "+line", "*** End of File"], + /*line_number*/ 123, + /*allow_missing_context*/ false + ), Ok(( (UpdateFileChunk { change_context: None, diff --git a/codex-rs/apply-patch/src/seek_sequence.rs b/codex-rs/apply-patch/src/seek_sequence.rs index b005b08c7..355596312 100644 --- a/codex-rs/apply-patch/src/seek_sequence.rs +++ b/codex-rs/apply-patch/src/seek_sequence.rs @@ -122,7 +122,10 @@ mod tests { fn test_exact_match_finds_sequence() { let lines = to_vec(&["foo", "bar", "baz"]); let pattern = to_vec(&["bar", "baz"]); - assert_eq!(seek_sequence(&lines, &pattern, 0, false), Some(1)); + assert_eq!( + seek_sequence(&lines, &pattern, /*start*/ 0, /*eof*/ false), + Some(1) + ); } #[test] @@ -130,7 +133,10 @@ mod tests { let lines = to_vec(&["foo ", "bar\t\t"]); // Pattern omits trailing whitespace. let pattern = to_vec(&["foo", "bar"]); - assert_eq!(seek_sequence(&lines, &pattern, 0, false), Some(0)); + assert_eq!( + seek_sequence(&lines, &pattern, /*start*/ 0, /*eof*/ false), + Some(0) + ); } #[test] @@ -138,7 +144,10 @@ mod tests { let lines = to_vec(&[" foo ", " bar\t"]); // Pattern omits any additional whitespace. let pattern = to_vec(&["foo", "bar"]); - assert_eq!(seek_sequence(&lines, &pattern, 0, false), Some(0)); + assert_eq!( + seek_sequence(&lines, &pattern, /*start*/ 0, /*eof*/ false), + Some(0) + ); } #[test] @@ -146,6 +155,9 @@ mod tests { let lines = to_vec(&["just one line"]); let pattern = to_vec(&["too", "many", "lines"]); // Should not panic – must return None when pattern cannot possibly fit. - assert_eq!(seek_sequence(&lines, &pattern, 0, false), None); + assert_eq!( + seek_sequence(&lines, &pattern, /*start*/ 0, /*eof*/ false), + None + ); } } diff --git a/codex-rs/chatgpt/src/connectors.rs b/codex-rs/chatgpt/src/connectors.rs index 3c2b2fe4e..aa13d70d4 100644 --- a/codex-rs/chatgpt/src/connectors.rs +++ b/codex-rs/chatgpt/src/connectors.rs @@ -245,9 +245,9 @@ mod tests { let merged = merge_connectors_with_accessible( vec![app("alpha")], vec![app("alpha"), app("beta")], - true, + /*all_connectors_loaded*/ true, ); - assert_eq!(merged, vec![merged_app("alpha", true)]); + assert_eq!(merged, vec![merged_app("alpha", /*is_accessible*/ true)]); } #[test] @@ -255,11 +255,14 @@ mod tests { let merged = merge_connectors_with_accessible( vec![app("alpha")], vec![app("alpha"), app("beta")], - false, + /*all_connectors_loaded*/ false, ); assert_eq!( merged, - vec![merged_app("alpha", true), merged_app("beta", true)] + vec![ + merged_app("alpha", /*is_accessible*/ true), + merged_app("beta", /*is_accessible*/ true) + ] ); } @@ -272,7 +275,10 @@ mod tests { AppConnectorId("gmail".to_string()), ], ); - assert_eq!(connectors, vec![app("alpha"), merged_app("gmail", false)]); + assert_eq!( + connectors, + vec![app("alpha"), merged_app("gmail", /*is_accessible*/ false)] + ); } #[test] diff --git a/codex-rs/cli/src/debug_sandbox.rs b/codex-rs/cli/src/debug_sandbox.rs index f64c45c73..adb205eef 100644 --- a/codex-rs/cli/src/debug_sandbox.rs +++ b/codex-rs/cli/src/debug_sandbox.rs @@ -498,7 +498,7 @@ mod tests { let legacy_config = build_debug_sandbox_config( Vec::new(), ConfigOverrides { - sandbox_mode: Some(create_sandbox_mode(false)), + sandbox_mode: Some(create_sandbox_mode(/*full_auto*/ false)), ..Default::default() }, Some(codex_home_path.clone()), @@ -507,8 +507,8 @@ mod tests { let config = load_debug_sandbox_config_with_codex_home( Vec::new(), - None, - false, + /*codex_linux_sandbox_exe*/ None, + /*full_auto*/ false, Some(codex_home_path), ) .await?; @@ -541,8 +541,8 @@ mod tests { let err = load_debug_sandbox_config_with_codex_home( Vec::new(), - None, - true, + /*codex_linux_sandbox_exe*/ None, + /*full_auto*/ true, Some(codex_home.path().to_path_buf()), ) .await diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 4bf6dde00..f0a66c9b6 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -1513,14 +1513,17 @@ mod tests { update_action: None, exit_reason: ExitReason::UserRequested, }; - let lines = format_exit_messages(exit_info, false); + let lines = format_exit_messages(exit_info, /*color_enabled*/ false); assert!(lines.is_empty()); } #[test] fn format_exit_messages_includes_resume_hint_without_color() { - let exit_info = sample_exit_info(Some("123e4567-e89b-12d3-a456-426614174000"), None); - let lines = format_exit_messages(exit_info, false); + let exit_info = sample_exit_info( + Some("123e4567-e89b-12d3-a456-426614174000"), + /*thread_name*/ None, + ); + let lines = format_exit_messages(exit_info, /*color_enabled*/ false); assert_eq!( lines, vec![ @@ -1533,8 +1536,11 @@ mod tests { #[test] fn format_exit_messages_applies_color_when_enabled() { - let exit_info = sample_exit_info(Some("123e4567-e89b-12d3-a456-426614174000"), None); - let lines = format_exit_messages(exit_info, true); + let exit_info = sample_exit_info( + Some("123e4567-e89b-12d3-a456-426614174000"), + /*thread_name*/ None, + ); + let lines = format_exit_messages(exit_info, /*color_enabled*/ true); assert_eq!(lines.len(), 2); assert!(lines[1].contains("\u{1b}[36m")); } @@ -1545,7 +1551,7 @@ mod tests { Some("123e4567-e89b-12d3-a456-426614174000"), Some("my-thread"), ); - let lines = format_exit_messages(exit_info, false); + let lines = format_exit_messages(exit_info, /*color_enabled*/ false); assert_eq!( lines, vec![ @@ -1771,8 +1777,12 @@ mod tests { #[test] fn reject_remote_mode_for_non_interactive_subcommands() { - let err = reject_remote_mode_for_subcommand(Some("127.0.0.1:4500"), None, "exec") - .expect_err("non-interactive subcommands should reject --remote"); + let err = reject_remote_mode_for_subcommand( + Some("127.0.0.1:4500"), + /*remote_auth_token_env*/ None, + "exec", + ) + .expect_err("non-interactive subcommands should reject --remote"); assert!( err.to_string() .contains("only supported for interactive TUI commands") @@ -1781,8 +1791,12 @@ mod tests { #[test] fn reject_remote_auth_token_env_for_non_interactive_subcommands() { - let err = reject_remote_mode_for_subcommand(None, Some("CODEX_REMOTE_AUTH_TOKEN"), "exec") - .expect_err("non-interactive subcommands should reject --remote-auth-token-env"); + let err = reject_remote_mode_for_subcommand( + /*remote*/ None, + Some("CODEX_REMOTE_AUTH_TOKEN"), + "exec", + ) + .expect_err("non-interactive subcommands should reject --remote-auth-token-env"); assert!( err.to_string() .contains("only supported for interactive TUI commands") @@ -1796,7 +1810,7 @@ mod tests { out_dir: PathBuf::from("/tmp/out"), }); let err = reject_remote_mode_for_app_server_subcommand( - None, + /*remote*/ None, Some("CODEX_REMOTE_AUTH_TOKEN"), Some(&subcommand), ) diff --git a/codex-rs/cloud-requirements/src/lib.rs b/codex-rs/cloud-requirements/src/lib.rs index 65476432a..b5080ea63 100644 --- a/codex-rs/cloud-requirements/src/lib.rs +++ b/codex-rs/cloud-requirements/src/lib.rs @@ -848,7 +848,7 @@ mod tests { write_auth_json(tmp.path(), auth_json).expect("write auth"); Arc::new(AuthManager::new( tmp.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )) } @@ -872,7 +872,7 @@ mod tests { .expect("write auth"); Arc::new(AuthManager::new( tmp.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )) } @@ -909,7 +909,7 @@ mod tests { access_token, refresh_token, last_refresh, - None, + /*auth_mode*/ None, ) } @@ -980,7 +980,7 @@ mod tests { ManagedAuthContext { manager: Arc::new(AuthManager::new( home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )), _home: home, @@ -1225,7 +1225,7 @@ mod tests { #[tokio::test] async fn fetch_cloud_requirements_handles_missing_contents() { - let result = parse_for_fetch(None); + let result = parse_for_fetch(/*contents*/ None); assert!(result.is_none()); } @@ -1369,7 +1369,7 @@ enabled = false .expect("write initial auth"); let auth_manager = Arc::new(AuthManager::new( auth_home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )); @@ -1438,7 +1438,7 @@ enabled = false .expect("write initial auth"); let auth_manager = Arc::new(AuthManager::new( auth_home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )); @@ -1565,7 +1565,7 @@ enabled = false .expect("write auth"); let auth_manager = Arc::new(AuthManager::new( auth_home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )); @@ -1657,7 +1657,11 @@ enabled = false async fn fetch_cloud_requirements_writes_cache_when_identity_is_incomplete() { let codex_home = tempdir().expect("tempdir"); let service = CloudRequirementsService::new( - auth_manager_with_plan_and_identity("business", None, Some("account-12345")), + auth_manager_with_plan_and_identity( + "business", + /*chatgpt_user_id*/ None, + Some("account-12345"), + ), Arc::new(StaticFetcher { contents: Some("allowed_approval_policies = [\"never\"]".to_string()), }), @@ -1709,7 +1713,11 @@ enabled = false "allowed_approval_policies = [\"on-request\"]".to_string(), ))])); let service = CloudRequirementsService::new( - auth_manager_with_plan_and_identity("business", None, Some("account-12345")), + auth_manager_with_plan_and_identity( + "business", + /*chatgpt_user_id*/ None, + Some("account-12345"), + ), fetcher.clone(), codex_home.path().to_path_buf(), CLOUD_REQUIREMENTS_TIMEOUT, diff --git a/codex-rs/cloud-tasks/src/app.rs b/codex-rs/cloud-tasks/src/app.rs index 4a8ca9900..aa02be97f 100644 --- a/codex-rs/cloud-tasks/src/app.rs +++ b/codex-rs/cloud-tasks/src/app.rs @@ -408,7 +408,7 @@ mod tests { &self, id: TaskId, ) -> codex_cloud_tasks_client::Result { - self.list_tasks(None, None, None) + self.list_tasks(/*env*/ None, /*limit*/ None, /*cursor*/ None) .await? .tasks .into_iter() @@ -497,7 +497,7 @@ mod tests { let backend = FakeBackend { by_env }; // Act + Assert - let root = load_tasks(&backend, None).await.unwrap(); + let root = load_tasks(&backend, /*env*/ None).await.unwrap(); assert_eq!(root.len(), 2); assert_eq!(root[0].title, "root-1"); diff --git a/codex-rs/cloud-tasks/src/lib.rs b/codex-rs/cloud-tasks/src/lib.rs index afda4cd70..bc0abccf8 100644 --- a/codex-rs/cloud-tasks/src/lib.rs +++ b/codex-rs/cloud-tasks/src/lib.rs @@ -2174,7 +2174,7 @@ mod tests { async fn branch_override_is_used_when_provided() { let git_ref = resolve_git_ref_with_git_info( Some(&"feature/override".to_string()), - &StubGitInfo::new(None, None), + &StubGitInfo::new(/*default_branch*/ None, /*current_branch*/ None), ) .await; @@ -2185,7 +2185,7 @@ mod tests { async fn trims_override_whitespace() { let git_ref = resolve_git_ref_with_git_info( Some(&" feature/spaces ".to_string()), - &StubGitInfo::new(None, None), + &StubGitInfo::new(/*default_branch*/ None, /*current_branch*/ None), ) .await; @@ -2195,7 +2195,7 @@ mod tests { #[tokio::test] async fn prefers_current_branch_when_available() { let git_ref = resolve_git_ref_with_git_info( - None, + /*branch_override*/ None, &StubGitInfo::new( Some("default-main".to_string()), Some("feature/current".to_string()), @@ -2209,8 +2209,8 @@ mod tests { #[tokio::test] async fn falls_back_to_current_branch_when_default_is_missing() { let git_ref = resolve_git_ref_with_git_info( - None, - &StubGitInfo::new(None, Some("develop".to_string())), + /*branch_override*/ None, + &StubGitInfo::new(/*default_branch*/ None, Some("develop".to_string())), ) .await; @@ -2219,7 +2219,11 @@ mod tests { #[tokio::test] async fn falls_back_to_main_when_no_git_info_is_available() { - let git_ref = resolve_git_ref_with_git_info(None, &StubGitInfo::new(None, None)).await; + let git_ref = resolve_git_ref_with_git_info( + /*branch_override*/ None, + &StubGitInfo::new(/*default_branch*/ None, /*current_branch*/ None), + ) + .await; assert_eq!(git_ref, "main"); } @@ -2242,7 +2246,7 @@ mod tests { is_review: false, attempt_total: None, }; - let lines = format_task_status_lines(&task, now, false); + let lines = format_task_status_lines(&task, now, /*colorize*/ false); assert_eq!( lines, vec![ @@ -2267,7 +2271,7 @@ mod tests { is_review: false, attempt_total: Some(1), }; - let lines = format_task_status_lines(&task, now, false); + let lines = format_task_status_lines(&task, now, /*colorize*/ false); assert_eq!( lines, vec![ @@ -2309,7 +2313,12 @@ mod tests { attempt_total: Some(1), }, ]; - let lines = format_task_list_lines(&tasks, "https://chatgpt.com/backend-api", now, false); + let lines = format_task_list_lines( + &tasks, + "https://chatgpt.com/backend-api", + now, + /*colorize*/ false, + ); assert_eq!( lines, vec![ diff --git a/codex-rs/cloud-tasks/tests/env_filter.rs b/codex-rs/cloud-tasks/tests/env_filter.rs index 688ccd29b..89bd2fc71 100644 --- a/codex-rs/cloud-tasks/tests/env_filter.rs +++ b/codex-rs/cloud-tasks/tests/env_filter.rs @@ -5,23 +5,35 @@ use codex_cloud_tasks_client::MockClient; async fn mock_backend_varies_by_env() { let client = MockClient; - let root = CloudBackend::list_tasks(&client, None, None, None) - .await - .unwrap() - .tasks; + let root = CloudBackend::list_tasks( + &client, /*env*/ None, /*limit*/ None, /*cursor*/ None, + ) + .await + .unwrap() + .tasks; assert!(root.iter().any(|t| t.title.contains("Update README"))); - let a = CloudBackend::list_tasks(&client, Some("env-A"), None, None) - .await - .unwrap() - .tasks; + let a = CloudBackend::list_tasks( + &client, + Some("env-A"), + /*limit*/ None, + /*cursor*/ None, + ) + .await + .unwrap() + .tasks; assert_eq!(a.len(), 1); assert_eq!(a[0].title, "A: First"); - let b = CloudBackend::list_tasks(&client, Some("env-B"), None, None) - .await - .unwrap() - .tasks; + let b = CloudBackend::list_tasks( + &client, + Some("env-B"), + /*limit*/ None, + /*cursor*/ None, + ) + .await + .unwrap() + .tasks; assert_eq!(b.len(), 2); assert!(b[0].title.starts_with("B: ")); } diff --git a/codex-rs/code-mode/src/description.rs b/codex-rs/code-mode/src/description.rs index c875e2a1b..22639b324 100644 --- a/codex-rs/code-mode/src/description.rs +++ b/codex-rs/code-mode/src/description.rs @@ -548,8 +548,10 @@ mod tests { #[test] fn code_mode_only_description_includes_nested_tools() { - let description = - build_exec_tool_description(&[("foo".to_string(), "bar".to_string())], true); + let description = build_exec_tool_description( + &[("foo".to_string(), "bar".to_string())], + /*code_mode_only*/ true, + ); assert!(description.contains("### `foo` (`foo`)")); } } diff --git a/codex-rs/code-mode/src/service.rs b/codex-rs/code-mode/src/service.rs index 260b891d3..5b67dd17b 100644 --- a/codex-rs/code-mode/src/service.rs +++ b/codex-rs/code-mode/src/service.rs @@ -631,7 +631,7 @@ text(JSON.stringify(returnsUndefined)); event_rx, control_rx, initial_response_tx, - 60_000, + /*initial_yield_time_ms*/ 60_000, )); event_tx.send(RuntimeEvent::Started).unwrap(); diff --git a/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs b/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs index 10c72d72b..eed0e470a 100644 --- a/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs +++ b/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs @@ -967,8 +967,8 @@ mod tests { fn websocket_url_from_http_base_defaults_to_ws_path() { let url = websocket_url_from_api_url( "http://127.0.0.1:8011", - None, - None, + /*query_params*/ None, + /*model*/ None, RealtimeEventParser::V1, RealtimeSessionMode::Conversational, ) @@ -983,7 +983,7 @@ mod tests { fn websocket_url_from_ws_base_defaults_to_ws_path() { let url = websocket_url_from_api_url( "wss://example.com", - None, + /*query_params*/ None, Some("realtime-test-model"), RealtimeEventParser::V1, RealtimeSessionMode::Conversational, @@ -999,7 +999,7 @@ mod tests { fn websocket_url_from_v1_base_appends_realtime_path() { let url = websocket_url_from_api_url( "https://api.openai.com/v1", - None, + /*query_params*/ None, Some("snapshot"), RealtimeEventParser::V1, RealtimeSessionMode::Conversational, @@ -1015,7 +1015,7 @@ mod tests { fn websocket_url_from_nested_v1_base_appends_realtime_path() { let url = websocket_url_from_api_url( "https://example.com/openai/v1", - None, + /*query_params*/ None, Some("snapshot"), RealtimeEventParser::V1, RealtimeSessionMode::Conversational, @@ -1050,8 +1050,8 @@ mod tests { fn websocket_url_v1_ignores_transcription_mode() { let url = websocket_url_from_api_url( "https://example.com", - None, - None, + /*query_params*/ None, + /*model*/ None, RealtimeEventParser::V1, RealtimeSessionMode::Transcription, ) @@ -1085,8 +1085,8 @@ mod tests { fn websocket_url_omits_intent_for_realtime_v2_transcription_mode() { let url = websocket_url_from_api_url( "https://example.com", - None, - None, + /*query_params*/ None, + /*model*/ None, RealtimeEventParser::RealtimeV2, RealtimeSessionMode::Transcription, ) diff --git a/codex-rs/codex-api/src/rate_limits.rs b/codex-rs/codex-api/src/rate_limits.rs index 730f94d20..1c71dc750 100644 --- a/codex-rs/codex-api/src/rate_limits.rs +++ b/codex-rs/codex-api/src/rate_limits.rs @@ -277,7 +277,7 @@ mod tests { HeaderValue::from_static("1704069000"), ); - let snapshot = parse_rate_limit_for_limit(&headers, None).expect("snapshot"); + let snapshot = parse_rate_limit_for_limit(&headers, /*limit_id*/ None).expect("snapshot"); assert_eq!(snapshot.limit_id.as_deref(), Some("codex")); assert_eq!(snapshot.limit_name, None); let primary = snapshot.primary.expect("primary"); diff --git a/codex-rs/codex-api/src/sse/responses.rs b/codex-rs/codex-api/src/sse/responses.rs index 696fd2953..bf6d75506 100644 --- a/codex-rs/codex-api/src/sse/responses.rs +++ b/codex-rs/codex-api/src/sse/responses.rs @@ -515,7 +515,12 @@ mod tests { let stream = ReaderStream::new(reader).map_err(|err| TransportError::Network(err.to_string())); let (tx, mut rx) = mpsc::channel::>(16); - tokio::spawn(process_sse(Box::pin(stream), tx, idle_timeout(), None)); + tokio::spawn(process_sse( + Box::pin(stream), + tx, + idle_timeout(), + /*telemetry*/ None, + )); let mut events = Vec::new(); while let Some(ev) = rx.recv().await { @@ -541,7 +546,12 @@ mod tests { let (tx, mut rx) = mpsc::channel::>(8); let stream = ReaderStream::new(std::io::Cursor::new(body)) .map_err(|err| TransportError::Network(err.to_string())); - tokio::spawn(process_sse(Box::pin(stream), tx, idle_timeout(), None)); + tokio::spawn(process_sse( + Box::pin(stream), + tx, + idle_timeout(), + /*telemetry*/ None, + )); let mut out = Vec::new(); while let Some(ev) = rx.recv().await { @@ -695,7 +705,12 @@ mod tests { let stream: ByteStream = Box::pin(stream); let (tx, mut rx) = mpsc::channel::>(8); - tokio::spawn(process_sse(stream, tx, idle_timeout(), None)); + tokio::spawn(process_sse( + stream, + tx, + idle_timeout(), + /*telemetry*/ None, + )); let events = tokio::time::timeout(Duration::from_millis(1000), async { let mut events = Vec::new(); @@ -894,7 +909,12 @@ mod tests { bytes: Box::pin(bytes), }; - let mut stream = spawn_response_stream(stream_response, idle_timeout(), None, None); + let mut stream = spawn_response_stream( + stream_response, + idle_timeout(), + /*telemetry*/ None, + /*turn_state*/ None, + ); let event = stream .rx_event .recv() diff --git a/codex-rs/codex-api/tests/clients.rs b/codex-rs/codex-api/tests/clients.rs index 63a033dea..ba0f41678 100644 --- a/codex-rs/codex-api/tests/clients.rs +++ b/codex-rs/codex-api/tests/clients.rs @@ -203,7 +203,12 @@ async fn responses_client_uses_responses_path() -> Result<()> { let body = serde_json::json!({ "echo": true }); let _stream = client - .stream(body, HeaderMap::new(), Compression::None, None) + .stream( + body, + HeaderMap::new(), + Compression::None, + /*turn_state*/ None, + ) .await?; let requests = state.take_stream_requests(); @@ -220,7 +225,12 @@ async fn streaming_client_adds_auth_headers() -> Result<()> { let body = serde_json::json!({ "model": "gpt-test" }); let _stream = client - .stream(body, HeaderMap::new(), Compression::None, None) + .stream( + body, + HeaderMap::new(), + Compression::None, + /*turn_state*/ None, + ) .await?; let requests = state.take_stream_requests(); diff --git a/codex-rs/codex-api/tests/models_integration.rs b/codex-rs/codex-api/tests/models_integration.rs index 4167c877d..3ffb2496b 100644 --- a/codex-rs/codex-api/tests/models_integration.rs +++ b/codex-rs/codex-api/tests/models_integration.rs @@ -85,7 +85,7 @@ async fn models_client_hits_models_endpoint() { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/codex-api/tests/sse_end_to_end.rs b/codex-rs/codex-api/tests/sse_end_to_end.rs index f625fdcd9..80972340d 100644 --- a/codex-rs/codex-api/tests/sse_end_to_end.rs +++ b/codex-rs/codex-api/tests/sse_end_to_end.rs @@ -125,7 +125,7 @@ async fn responses_stream_parses_items_and_completed_end_to_end() -> Result<()> serde_json::json!({"echo": true}), HeaderMap::new(), Compression::None, - None, + /*turn_state*/ None, ) .await?; diff --git a/codex-rs/config/src/constraint.rs b/codex-rs/config/src/constraint.rs index d6c8e09f5..13cb867ce 100644 --- a/codex-rs/config/src/constraint.rs +++ b/codex-rs/config/src/constraint.rs @@ -188,8 +188,10 @@ mod tests { #[test] fn constrained_allow_any_accepts_any_value() { - let mut constrained = Constrained::allow_any(5); - constrained.set(-10).expect("allow any accepts all values"); + let mut constrained = Constrained::allow_any(/*initial_value*/ 5); + constrained + .set(/*value*/ -10) + .expect("allow any accepts all values"); assert_eq!(constrained.value(), -10); } @@ -201,13 +203,13 @@ mod tests { #[test] fn constrained_allow_only_rejects_different_values() { - let mut constrained = Constrained::allow_only(5); + let mut constrained = Constrained::allow_only(/*only_value*/ 5); constrained - .set(5) + .set(/*value*/ 5) .expect("allowed value should be accepted"); let err = constrained - .set(6) + .set(/*value*/ 6) .expect_err("different value should be rejected"); assert_eq!(err, invalid_value("6", "[5]")); assert_eq!(constrained.value(), 5); @@ -215,18 +217,19 @@ mod tests { #[test] fn constrained_normalizer_applies_on_init_and_set() -> anyhow::Result<()> { - let mut constrained = Constrained::normalized(-1, |value| value.max(0))?; + let mut constrained = + Constrained::normalized(/*initial_value*/ -1, |value| value.max(0))?; assert_eq!(constrained.value(), 0); - constrained.set(-5)?; + constrained.set(/*value*/ -5)?; assert_eq!(constrained.value(), 0); - constrained.set(10)?; + constrained.set(/*value*/ 10)?; assert_eq!(constrained.value(), 10); Ok(()) } #[test] fn constrained_new_rejects_invalid_initial_value() { - let result = Constrained::new(0, |value| { + let result = Constrained::new(/*initial_value*/ 0, |value| { if *value > 0 { Ok(()) } else { @@ -239,7 +242,7 @@ mod tests { #[test] fn constrained_set_rejects_invalid_value_and_leaves_previous() { - let mut constrained = Constrained::new(1, |value| { + let mut constrained = Constrained::new(/*initial_value*/ 1, |value| { if *value > 0 { Ok(()) } else { @@ -249,7 +252,7 @@ mod tests { .expect("initial value should be accepted"); let err = constrained - .set(-5) + .set(/*value*/ -5) .expect_err("negative values should be rejected"); assert_eq!(err, invalid_value("-5", "positive values")); assert_eq!(constrained.value(), 1); @@ -257,7 +260,7 @@ mod tests { #[test] fn constrained_can_set_allows_probe_without_setting() { - let constrained = Constrained::new(1, |value| { + let constrained = Constrained::new(/*initial_value*/ 1, |value| { if *value > 0 { Ok(()) } else { diff --git a/codex-rs/connectors/src/lib.rs b/codex-rs/connectors/src/lib.rs index 1d3a72923..a74ece5a3 100644 --- a/codex-rs/connectors/src/lib.rs +++ b/codex-rs/connectors/src/lib.rs @@ -419,7 +419,7 @@ mod tests { "https://chatgpt.example".to_string(), Some(format!("account-{id}")), Some(format!("user-{id}")), - true, + /*is_workspace_account*/ true, ) } @@ -444,21 +444,31 @@ mod tests { let call_counter = Arc::clone(&calls); let key = cache_key("shared"); - let first = list_all_connectors_with_options(key.clone(), false, false, move |_path| { - let call_counter = Arc::clone(&call_counter); - async move { - call_counter.fetch_add(1, Ordering::SeqCst); - Ok(DirectoryListResponse { - apps: vec![app("alpha", "Alpha")], - next_token: None, - }) - } - }) + let first = list_all_connectors_with_options( + key.clone(), + /*is_workspace_account*/ false, + /*force_refetch*/ false, + move |_path| { + let call_counter = Arc::clone(&call_counter); + async move { + call_counter.fetch_add(1, Ordering::SeqCst); + Ok(DirectoryListResponse { + apps: vec![app("alpha", "Alpha")], + next_token: None, + }) + } + }, + ) .await?; - let second = list_all_connectors_with_options(key, false, false, move |_path| async move { - anyhow::bail!("cache should have been used"); - }) + let second = list_all_connectors_with_options( + key, + /*is_workspace_account*/ false, + /*force_refetch*/ false, + move |_path| async move { + anyhow::bail!("cache should have been used"); + }, + ) .await?; assert_eq!(calls.load(Ordering::SeqCst), 1); @@ -472,40 +482,45 @@ mod tests { let calls = Arc::new(AtomicUsize::new(0)); let call_counter = Arc::clone(&calls); - let connectors = list_all_connectors_with_options(key, true, true, move |path| { - let call_counter = Arc::clone(&call_counter); - async move { - call_counter.fetch_add(1, Ordering::SeqCst); - if path.starts_with("/connectors/directory/list_workspace") { - Ok(DirectoryListResponse { - apps: vec![ - DirectoryApp { - description: Some("Merged description".to_string()), - branding: Some(AppBranding { - category: Some("calendar".to_string()), - developer: None, - website: None, - privacy_policy: None, - terms_of_service: None, - is_discoverable_app: true, - }), - ..app("alpha", "") - }, - DirectoryApp { - visibility: Some("HIDDEN".to_string()), - ..app("hidden", "Hidden") - }, - ], - next_token: None, - }) - } else { - Ok(DirectoryListResponse { - apps: vec![app("alpha", " Alpha "), app("beta", "Beta")], - next_token: None, - }) + let connectors = list_all_connectors_with_options( + key, + /*is_workspace_account*/ true, + /*force_refetch*/ true, + move |path| { + let call_counter = Arc::clone(&call_counter); + async move { + call_counter.fetch_add(1, Ordering::SeqCst); + if path.starts_with("/connectors/directory/list_workspace") { + Ok(DirectoryListResponse { + apps: vec![ + DirectoryApp { + description: Some("Merged description".to_string()), + branding: Some(AppBranding { + category: Some("calendar".to_string()), + developer: None, + website: None, + privacy_policy: None, + terms_of_service: None, + is_discoverable_app: true, + }), + ..app("alpha", "") + }, + DirectoryApp { + visibility: Some("HIDDEN".to_string()), + ..app("hidden", "Hidden") + }, + ], + next_token: None, + }) + } else { + Ok(DirectoryListResponse { + apps: vec![app("alpha", " Alpha "), app("beta", "Beta")], + next_token: None, + }) + } } - } - }) + }, + ) .await?; assert_eq!(calls.load(Ordering::SeqCst), 2); diff --git a/codex-rs/core-skills/src/loader_tests.rs b/codex-rs/core-skills/src/loader_tests.rs index ad196df67..370285630 100644 --- a/codex-rs/core-skills/src/loader_tests.rs +++ b/codex-rs/core-skills/src/loader_tests.rs @@ -115,7 +115,7 @@ fn load_skills_for_test(config: &TestConfig) -> SkillLoadOutcome { super::load_skills_from_roots(super::skill_roots_with_home_dir( &config.config_layer_stack, &config.cwd, - None, + /*home_dir*/ None, Vec::new(), )) } diff --git a/codex-rs/core-skills/src/manager_tests.rs b/codex-rs/core-skills/src/manager_tests.rs index 9e6c60c0e..62218f731 100644 --- a/codex-rs/core-skills/src/manager_tests.rs +++ b/codex-rs/core-skills/src/manager_tests.rs @@ -141,7 +141,10 @@ fn new_with_disabled_bundled_skills_removes_stale_cached_system_skills() { fs::write(stale_system_skill_dir.join("SKILL.md"), "# stale\n") .expect("write stale system skill"); - let _skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), false); + let _skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ false, + ); assert!( !codex_home.path().join("skills/.system").exists(), @@ -154,7 +157,10 @@ async fn skills_for_config_reuses_cache_for_same_effective_config() { let codex_home = tempfile::tempdir().expect("tempdir"); let cwd = tempfile::tempdir().expect("tempdir"); let config_layer_stack = config_stack(&codex_home, ""); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); write_user_skill(&codex_home, "a", "skill-a", "from a"); let outcome1 = skills_for_config_with_stack(&skills_manager, &cwd, &config_layer_stack, &[]); @@ -185,14 +191,17 @@ async fn skills_for_config_disables_plugin_skills_by_name() { ); let config_layer_stack = config_stack( &codex_home, - &name_toggle_config("sample:sample-search", false), + &name_toggle_config("sample:sample-search", /*enabled*/ false), ); let plugin_skill_root = skill_path .parent() .and_then(std::path::Path::parent) .expect("plugin skill should live under a skills root") .to_path_buf(); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); let outcome = skills_for_config_with_stack( &skills_manager, @@ -223,7 +232,10 @@ async fn skills_for_cwd_reuses_cached_entry_even_when_entry_has_extra_roots() { let cwd = tempfile::tempdir().expect("tempdir"); let extra_root = tempfile::tempdir().expect("tempdir"); let config_layer_stack = config_stack(&codex_home, ""); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); let _ = skills_for_config_with_stack(&skills_manager, &cwd, &config_layer_stack, &[]); write_user_skill(&extra_root, "x", "extra-skill", "from extra root"); @@ -237,7 +249,7 @@ async fn skills_for_cwd_reuses_cached_entry_even_when_entry_has_extra_roots() { let outcome_with_extra = skills_manager .skills_for_cwd_with_extra_user_roots( &base_input, - true, + /*force_reload*/ true, std::slice::from_ref(&extra_root_path), ) .await; @@ -262,7 +274,9 @@ async fn skills_for_cwd_reuses_cached_entry_even_when_entry_has_extra_roots() { config_layer_stack.clone(), bundled_skills_enabled_from_stack(&config_layer_stack), ); - let outcome_without_extra = skills_manager.skills_for_cwd(&base_input, false).await; + let outcome_without_extra = skills_manager + .skills_for_cwd(&base_input, /*force_reload*/ false) + .await; assert_eq!(outcome_without_extra.skills, outcome_with_extra.skills); assert_eq!(outcome_without_extra.errors, outcome_with_extra.errors); } @@ -279,7 +293,10 @@ async fn skills_for_config_excludes_bundled_skills_when_disabled_in_config() { ) .expect("write bundled skill"); let config_layer_stack = config_stack(&codex_home, "[skills.bundled]\nenabled = false\n"); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), false); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ false, + ); // Recreate the cached bundled skill after startup cleanup so this assertion exercises // root selection rather than relying on directory removal succeeding. @@ -312,7 +329,10 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { let extra_root_a = tempfile::tempdir().expect("tempdir"); let extra_root_b = tempfile::tempdir().expect("tempdir"); let config_layer_stack = config_stack(&codex_home, ""); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); let _ = skills_for_config_with_stack(&skills_manager, &cwd, &config_layer_stack, &[]); write_user_skill(&extra_root_a, "x", "extra-skill-a", "from extra root a"); @@ -328,7 +348,7 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { let outcome_a = skills_manager .skills_for_cwd_with_extra_user_roots( &base_input, - true, + /*force_reload*/ true, std::slice::from_ref(&extra_root_a_path), ) .await; @@ -349,7 +369,7 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { let outcome_b = skills_manager .skills_for_cwd_with_extra_user_roots( &base_input, - false, + /*force_reload*/ false, std::slice::from_ref(&extra_root_b_path), ) .await; @@ -369,7 +389,7 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { let outcome_reloaded = skills_manager .skills_for_cwd_with_extra_user_roots( &base_input, - true, + /*force_reload*/ true, std::slice::from_ref(&extra_root_b_path), ) .await; @@ -408,11 +428,13 @@ fn disabled_paths_for_skills_allows_session_flags_to_override_user_layer() { .expect("user config path should be absolute"); let user_layer = ConfigLayerEntry::new( ConfigLayerSource::User { file: user_file }, - toml::from_str(&path_toggle_config(&skill_path, false)).expect("user layer toml"), + toml::from_str(&path_toggle_config(&skill_path, /*enabled*/ false)) + .expect("user layer toml"), ); let session_layer = ConfigLayerEntry::new( ConfigLayerSource::SessionFlags, - toml::from_str(&path_toggle_config(&skill_path, true)).expect("session layer toml"), + toml::from_str(&path_toggle_config(&skill_path, /*enabled*/ true)) + .expect("session layer toml"), ); let stack = ConfigLayerStack::new( vec![user_layer, session_layer], @@ -438,11 +460,13 @@ fn disabled_paths_for_skills_allows_session_flags_to_disable_user_enabled_skill( .expect("user config path should be absolute"); let user_layer = ConfigLayerEntry::new( ConfigLayerSource::User { file: user_file }, - toml::from_str(&path_toggle_config(&skill_path, true)).expect("user layer toml"), + toml::from_str(&path_toggle_config(&skill_path, /*enabled*/ true)) + .expect("user layer toml"), ); let session_layer = ConfigLayerEntry::new( ConfigLayerSource::SessionFlags, - toml::from_str(&path_toggle_config(&skill_path, false)).expect("session layer toml"), + toml::from_str(&path_toggle_config(&skill_path, /*enabled*/ false)) + .expect("session layer toml"), ); let stack = ConfigLayerStack::new( vec![user_layer, session_layer], @@ -468,7 +492,8 @@ fn disabled_paths_for_skills_disables_matching_name_selectors() { .expect("user config path should be absolute"); let user_layer = ConfigLayerEntry::new( ConfigLayerSource::User { file: user_file }, - toml::from_str(&name_toggle_config("github:yeet", false)).expect("user layer toml"), + toml::from_str(&name_toggle_config("github:yeet", /*enabled*/ false)) + .expect("user layer toml"), ); let stack = ConfigLayerStack::new( vec![user_layer], @@ -494,11 +519,13 @@ fn disabled_paths_for_skills_allows_name_selector_to_override_path_selector() { .expect("user config path should be absolute"); let user_layer = ConfigLayerEntry::new( ConfigLayerSource::User { file: user_file }, - toml::from_str(&path_toggle_config(&skill_path, false)).expect("user layer toml"), + toml::from_str(&path_toggle_config(&skill_path, /*enabled*/ false)) + .expect("user layer toml"), ); let session_layer = ConfigLayerEntry::new( ConfigLayerSource::SessionFlags, - toml::from_str(&name_toggle_config("github:yeet", true)).expect("session layer toml"), + toml::from_str(&name_toggle_config("github:yeet", /*enabled*/ true)) + .expect("session layer toml"), ); let stack = ConfigLayerStack::new( vec![user_layer, session_layer], @@ -527,12 +554,15 @@ async fn skills_for_config_ignores_cwd_cache_when_session_flags_reenable_skill() "---\nname: demo-skill\ndescription: demo description\n---\n\n# Body\n", ) .expect("write skill"); - let disabled_skill_config = path_toggle_config(&skill_path, false); - let enabled_skill_config = path_toggle_config(&skill_path, true); + let disabled_skill_config = path_toggle_config(&skill_path, /*enabled*/ false); + let enabled_skill_config = path_toggle_config(&skill_path, /*enabled*/ true); let parent_stack = config_stack(&codex_home, &disabled_skill_config); let child_stack = config_stack_with_session_flags(&codex_home, &disabled_skill_config, &enabled_skill_config); - let skills_manager = SkillsManager::new(codex_home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + codex_home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); let parent_input = SkillsLoadInput::new( cwd.path().to_path_buf(), Vec::new(), @@ -540,7 +570,9 @@ async fn skills_for_config_ignores_cwd_cache_when_session_flags_reenable_skill() bundled_skills_enabled_from_stack(&parent_stack), ); - let parent_outcome = skills_manager.skills_for_cwd(&parent_input, true).await; + let parent_outcome = skills_manager + .skills_for_cwd(&parent_input, /*force_reload*/ true) + .await; let parent_skill = parent_outcome .skills .iter() diff --git a/codex-rs/core/src/agent/control_tests.rs b/codex-rs/core/src/agent/control_tests.rs index 41a01c5ff..2def29af9 100644 --- a/codex-rs/core/src/agent/control_tests.rs +++ b/codex-rs/core/src/agent/control_tests.rs @@ -289,7 +289,7 @@ async fn spawn_agent_errors_when_manager_dropped() { let control = AgentControl::default(); let (_home, config) = test_config().await; let err = control - .spawn_agent(config, text_input("hello"), None) + .spawn_agent(config, text_input("hello"), /*session_source*/ None) .await .expect_err("spawn_agent should fail without a manager"); assert_eq!( @@ -423,7 +423,7 @@ async fn send_inter_agent_communication_without_turn_queues_message_without_trig AgentPath::try_from("/root/worker").expect("agent path"), Vec::new(), "hello from tests".to_string(), - false, + /*trigger_turn*/ false, ); let submission_id = harness @@ -535,7 +535,11 @@ async fn spawn_agent_creates_thread_and_sends_prompt() { let harness = AgentControlHarness::new().await; let thread_id = harness .control - .spawn_agent(harness.config.clone(), text_input("spawned"), None) + .spawn_agent( + harness.config.clone(), + text_input("spawned"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed"); let _thread = harness @@ -830,12 +834,20 @@ async fn spawn_agent_respects_max_threads_limit() { .expect("start thread"); let first_agent_id = control - .spawn_agent(config.clone(), text_input("hello"), None) + .spawn_agent( + config.clone(), + text_input("hello"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed"); let err = control - .spawn_agent(config, text_input("hello again"), None) + .spawn_agent( + config, + text_input("hello again"), + /*session_source*/ None, + ) .await .expect_err("spawn_agent should respect max threads"); let CodexErr::AgentLimitReached { @@ -871,7 +883,11 @@ async fn spawn_agent_releases_slot_after_shutdown() { let control = manager.agent_control(); let first_agent_id = control - .spawn_agent(config.clone(), text_input("hello"), None) + .spawn_agent( + config.clone(), + text_input("hello"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed"); let _ = control @@ -880,7 +896,11 @@ async fn spawn_agent_releases_slot_after_shutdown() { .expect("shutdown agent"); let second_agent_id = control - .spawn_agent(config.clone(), text_input("hello again"), None) + .spawn_agent( + config.clone(), + text_input("hello again"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed after shutdown"); let _ = control @@ -909,12 +929,20 @@ async fn spawn_agent_limit_shared_across_clones() { let cloned = control.clone(); let first_agent_id = cloned - .spawn_agent(config.clone(), text_input("hello"), None) + .spawn_agent( + config.clone(), + text_input("hello"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed"); let err = control - .spawn_agent(config, text_input("hello again"), None) + .spawn_agent( + config, + text_input("hello again"), + /*session_source*/ None, + ) .await .expect_err("spawn_agent should respect shared guard"); let CodexErr::AgentLimitReached { max_threads } = err else { @@ -947,7 +975,11 @@ async fn resume_agent_respects_max_threads_limit() { let control = manager.agent_control(); let resumable_id = control - .spawn_agent(config.clone(), text_input("hello"), None) + .spawn_agent( + config.clone(), + text_input("hello"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed"); let _ = control @@ -956,7 +988,11 @@ async fn resume_agent_respects_max_threads_limit() { .expect("shutdown resumable thread"); let active_id = control - .spawn_agent(config.clone(), text_input("occupy"), None) + .spawn_agent( + config.clone(), + text_input("occupy"), + /*session_source*/ None, + ) .await .expect("spawn_agent should succeed for active slot"); @@ -1002,7 +1038,7 @@ async fn resume_agent_releases_slot_after_resume_failure() { .expect_err("resume should fail for missing rollout path"); let resumed_id = control - .spawn_agent(config, text_input("hello"), None) + .spawn_agent(config, text_input("hello"), /*session_source*/ None) .await .expect("spawn should succeed after failed resume"); let _ = control @@ -1140,7 +1176,7 @@ async fn multi_agent_v2_completion_ignores_dead_direct_parent() { AgentPath::root(), Vec::new(), "done".to_string(), - true, + /*trigger_turn*/ true, ) )); assert!(!has_subagent_notification(&root_history_items)); @@ -1203,7 +1239,7 @@ async fn multi_agent_v2_completion_queues_message_for_direct_parent() { worker_path.clone(), Vec::new(), expected_message.clone(), - false, + /*trigger_turn*/ false, ), }, ); @@ -1238,7 +1274,7 @@ async fn multi_agent_v2_completion_queues_message_for_direct_parent() { AgentPath::root(), Vec::new(), expected_message, - false, + /*trigger_turn*/ false, ) )); } @@ -1259,7 +1295,7 @@ async fn completion_watcher_notifies_parent_when_child_is_missing() { agent_role: Some("explorer".to_string()), })), child_thread_id.to_string(), - None, + /*child_agent_path*/ None, ); assert_eq!(wait_for_subagent_notification(&parent_thread).await, true); @@ -1520,7 +1556,11 @@ async fn resume_agent_from_rollout_reads_archived_rollout_path() { let harness = AgentControlHarness::new().await; let child_thread_id = harness .control - .spawn_agent(harness.config.clone(), text_input("hello"), None) + .spawn_agent( + harness.config.clone(), + text_input("hello"), + /*session_source*/ None, + ) .await .expect("child spawn should succeed"); diff --git a/codex-rs/core/src/agent/registry_tests.rs b/codex-rs/core/src/agent/registry_tests.rs index 43d91952a..fc172fb33 100644 --- a/codex-rs/core/src/agent/registry_tests.rs +++ b/codex-rs/core/src/agent/registry_tests.rs @@ -16,11 +16,26 @@ fn agent_metadata(thread_id: ThreadId) -> AgentMetadata { #[test] fn format_agent_nickname_adds_ordinals_after_reset() { - assert_eq!(format_agent_nickname("Plato", 0), "Plato"); - assert_eq!(format_agent_nickname("Plato", 1), "Plato the 2nd"); - assert_eq!(format_agent_nickname("Plato", 2), "Plato the 3rd"); - assert_eq!(format_agent_nickname("Plato", 10), "Plato the 11th"); - assert_eq!(format_agent_nickname("Plato", 20), "Plato the 21st"); + assert_eq!( + format_agent_nickname("Plato", /*nickname_reset_count*/ 0), + "Plato" + ); + assert_eq!( + format_agent_nickname("Plato", /*nickname_reset_count*/ 1), + "Plato the 2nd" + ); + assert_eq!( + format_agent_nickname("Plato", /*nickname_reset_count*/ 2), + "Plato the 3rd" + ); + assert_eq!( + format_agent_nickname("Plato", /*nickname_reset_count*/ 10), + "Plato the 11th" + ); + assert_eq!( + format_agent_nickname("Plato", /*nickname_reset_count*/ 20), + "Plato the 21st" + ); } #[test] @@ -39,7 +54,10 @@ fn thread_spawn_depth_increments_and_enforces_limit() { }); let child_depth = next_thread_spawn_depth(&session_source); assert_eq!(child_depth, 2); - assert!(exceeds_thread_spawn_depth_limit(child_depth, 1)); + assert!(exceeds_thread_spawn_depth_limit( + child_depth, + /*max_depth*/ 1 + )); } #[test] @@ -47,7 +65,9 @@ fn non_thread_spawn_subagents_default_to_depth_zero() { let session_source = SessionSource::SubAgent(SubAgentSource::Review); assert_eq!(session_depth(&session_source), 0); assert_eq!(next_thread_spawn_depth(&session_source), 1); - assert!(!exceeds_thread_spawn_depth_limit(1, 1)); + assert!(!exceeds_thread_spawn_depth_limit( + /*depth*/ 1, /*max_depth*/ 1 + )); } #[test] @@ -142,14 +162,18 @@ fn release_is_idempotent_for_registered_threads() { #[test] fn failed_spawn_keeps_nickname_marked_used() { let registry = Arc::new(AgentRegistry::default()); - let mut reservation = registry.reserve_spawn_slot(None).expect("reserve slot"); + let mut reservation = registry + .reserve_spawn_slot(/*max_threads*/ None) + .expect("reserve slot"); let agent_nickname = reservation .reserve_agent_nickname_with_preference(&["alpha"], /*preferred*/ None) .expect("reserve agent name"); assert_eq!(agent_nickname, "alpha"); drop(reservation); - let mut reservation = registry.reserve_spawn_slot(None).expect("reserve slot"); + let mut reservation = registry + .reserve_spawn_slot(/*max_threads*/ None) + .expect("reserve slot"); let agent_nickname = reservation .reserve_agent_nickname_with_preference(&["alpha", "beta"], /*preferred*/ None) .expect("unused name should still be preferred"); @@ -160,7 +184,7 @@ fn failed_spawn_keeps_nickname_marked_used() { fn agent_nickname_resets_used_pool_when_exhausted() { let registry = Arc::new(AgentRegistry::default()); let mut first = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve first slot"); let first_name = first .reserve_agent_nickname_with_preference(&["alpha"], /*preferred*/ None) @@ -170,7 +194,7 @@ fn agent_nickname_resets_used_pool_when_exhausted() { assert_eq!(first_name, "alpha"); let mut second = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve second slot"); let second_name = second .reserve_agent_nickname_with_preference(&["alpha"], /*preferred*/ None) @@ -188,7 +212,7 @@ fn released_nickname_stays_used_until_pool_reset() { let registry = Arc::new(AgentRegistry::default()); let mut first = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve first slot"); let first_name = first .reserve_agent_nickname_with_preference(&["alpha"], /*preferred*/ None) @@ -200,7 +224,7 @@ fn released_nickname_stays_used_until_pool_reset() { registry.release_spawned_thread(first_id); let mut second = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve second slot"); let second_name = second .reserve_agent_nickname_with_preference(&["alpha", "beta"], /*preferred*/ None) @@ -211,7 +235,7 @@ fn released_nickname_stays_used_until_pool_reset() { registry.release_spawned_thread(second_id); let mut third = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve third slot"); let third_name = third .reserve_agent_nickname_with_preference(&["alpha", "beta"], /*preferred*/ None) @@ -230,7 +254,7 @@ fn repeated_resets_advance_the_ordinal_suffix() { let registry = Arc::new(AgentRegistry::default()); let mut first = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve first slot"); let first_name = first .reserve_agent_nickname_with_preference(&["Plato"], /*preferred*/ None) @@ -241,7 +265,7 @@ fn repeated_resets_advance_the_ordinal_suffix() { registry.release_spawned_thread(first_id); let mut second = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve second slot"); let second_name = second .reserve_agent_nickname_with_preference(&["Plato"], /*preferred*/ None) @@ -252,7 +276,7 @@ fn repeated_resets_advance_the_ordinal_suffix() { registry.release_spawned_thread(second_id); let mut third = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve third slot"); let third_name = third .reserve_agent_nickname_with_preference(&["Plato"], /*preferred*/ None) @@ -282,7 +306,7 @@ fn register_root_thread_indexes_root_path() { fn reserved_agent_path_is_released_when_spawn_fails() { let registry = Arc::new(AgentRegistry::default()); let mut first = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve first slot"); first .reserve_agent_path(&agent_path("/root/researcher")) @@ -290,7 +314,7 @@ fn reserved_agent_path_is_released_when_spawn_fails() { drop(first); let mut second = registry - .reserve_spawn_slot(None) + .reserve_spawn_slot(/*max_threads*/ None) .expect("reserve second slot"); second .reserve_agent_path(&agent_path("/root/researcher")) @@ -301,7 +325,9 @@ fn reserved_agent_path_is_released_when_spawn_fails() { fn committed_agent_path_is_indexed_until_release() { let registry = Arc::new(AgentRegistry::default()); let thread_id = ThreadId::new(); - let mut reservation = registry.reserve_spawn_slot(None).expect("reserve slot"); + let mut reservation = registry + .reserve_spawn_slot(/*max_threads*/ None) + .expect("reserve slot"); reservation .reserve_agent_path(&agent_path("/root/researcher")) .expect("reserve path"); diff --git a/codex-rs/core/src/agent/role_tests.rs b/codex-rs/core/src/agent/role_tests.rs index c96bd2acf..5b3941ebd 100644 --- a/codex-rs/core/src/agent/role_tests.rs +++ b/codex-rs/core/src/agent/role_tests.rs @@ -40,7 +40,10 @@ async fn write_role_config(home: &TempDir, name: &str, contents: &str) -> PathBu fn session_flags_layer_count(config: &Config) -> usize { config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .filter(|layer| layer.name == ConfigLayerSource::SessionFlags) .count() @@ -51,7 +54,7 @@ async fn apply_role_defaults_to_default_and_leaves_config_unchanged() { let (_home, mut config) = test_config_with_cli_overrides(Vec::new()).await; let before = config.clone(); - apply_role_to_config(&mut config, None) + apply_role_to_config(&mut config, /*role_name*/ None) .await .expect("default role should apply"); @@ -529,7 +532,10 @@ writable_roots = ["./sandbox-root"] let role_layer = config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .rfind(|layer| layer.name == ConfigLayerSource::SessionFlags) .expect("expected a session flags layer"); @@ -630,7 +636,10 @@ enabled = false .expect("custom role should apply"); let plugins_manager = Arc::new(PluginsManager::new(home.path().to_path_buf())); - let skills_manager = SkillsManager::new(home.path().to_path_buf(), true); + let skills_manager = SkillsManager::new( + home.path().to_path_buf(), + /*bundled_skills_enabled*/ true, + ); let plugin_outcome = plugins_manager.plugins_for_config(&config); let effective_skill_roots = plugin_outcome.effective_skill_roots(); let skills_input = skills_load_input_from_config(&config, effective_skill_roots); diff --git a/codex-rs/core/src/auth_env_telemetry.rs b/codex-rs/core/src/auth_env_telemetry.rs index 85cd23fe0..cc5ffa120 100644 --- a/codex-rs/core/src/auth_env_telemetry.rs +++ b/codex-rs/core/src/auth_env_telemetry.rs @@ -76,7 +76,8 @@ mod tests { supports_websockets: false, }; - let telemetry = collect_auth_env_telemetry(&provider, false); + let telemetry = + collect_auth_env_telemetry(&provider, /*codex_api_key_env_enabled*/ false); assert_eq!( telemetry.provider_env_key_name, diff --git a/codex-rs/core/src/client_common_tests.rs b/codex-rs/core/src/client_common_tests.rs index c3add6237..16a37796a 100644 --- a/codex-rs/core/src/client_common_tests.rs +++ b/codex-rs/core/src/client_common_tests.rs @@ -52,7 +52,8 @@ fn serializes_text_schema_with_strict_format() { "required": ["answer"], }); let text_controls = - create_text_param_for_request(None, &Some(schema.clone())).expect("text controls"); + create_text_param_for_request(/*verbosity*/ None, &Some(schema.clone())) + .expect("text controls"); let req = ResponsesApiRequest { model: "gpt-5.1".to_string(), diff --git a/codex-rs/core/src/client_tests.rs b/codex-rs/core/src/client_tests.rs index 2c07b4fd1..b7d8075f0 100644 --- a/codex-rs/core/src/client_tests.rs +++ b/codex-rs/core/src/client_tests.rs @@ -16,14 +16,14 @@ fn test_model_client(session_source: SessionSource) -> ModelClient { crate::model_provider_info::WireApi::Responses, ); ModelClient::new( - None, + /*auth_manager*/ None, ThreadId::new(), provider, session_source, - None, - false, - false, - None, + /*model_verbosity*/ None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ) } @@ -62,11 +62,11 @@ fn test_session_telemetry() -> SessionTelemetry { ThreadId::new(), "gpt-test", "gpt-test", - None, - None, - None, + /*account_id*/ None, + /*account_email*/ None, + /*auth_mode*/ None, "test-originator".to_string(), - false, + /*log_user_prompts*/ false, "test-terminal".to_string(), SessionSource::Cli, ) @@ -91,7 +91,12 @@ async fn summarize_memories_returns_empty_for_empty_input() { let session_telemetry = test_session_telemetry(); let output = client - .summarize_memories(Vec::new(), &model_info, None, &session_telemetry) + .summarize_memories( + Vec::new(), + &model_info, + /*effort*/ None, + &session_telemetry, + ) .await .expect("empty summarize request should succeed"); assert_eq!(output.len(), 0); diff --git a/codex-rs/core/src/codex/rollout_reconstruction_tests.rs b/codex-rs/core/src/codex/rollout_reconstruction_tests.rs index e468bfceb..86abfa675 100644 --- a/codex-rs/core/src/codex/rollout_reconstruction_tests.rs +++ b/codex-rs/core/src/codex/rollout_reconstruction_tests.rs @@ -41,7 +41,7 @@ fn inter_agent_assistant_message(text: &str) -> ResponseItem { AgentPath::root().join("worker").unwrap(), Vec::new(), text.to_string(), - true, + /*trigger_turn*/ true, ); ResponseItem::Message { id: None, diff --git a/codex-rs/core/src/codex_tests.rs b/codex-rs/core/src/codex_tests.rs index ff0e08e21..f1a665277 100644 --- a/codex-rs/core/src/codex_tests.rs +++ b/codex-rs/core/src/codex_tests.rs @@ -247,17 +247,17 @@ async fn interrupting_regular_turn_waiting_on_startup_prewarm_emits_turn_aborted fn test_model_client_session() -> crate::client::ModelClientSession { crate::client::ModelClient::new( - None, + /*auth_manager*/ None, ThreadId::try_from("00000000-0000-4000-8000-000000000001") .expect("test thread id should be valid"), crate::model_provider_info::ModelProviderInfo::create_openai_provider( - /* base_url */ None, + /* base_url */ /*base_url*/ None, ), codex_protocol::protocol::SessionSource::Exec, - None, - false, - false, - None, + /*model_verbosity*/ None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ) .new_session() } @@ -313,7 +313,7 @@ fn make_connector(id: &str, name: &str) -> AppInfo { #[test] fn assistant_message_stream_parsers_can_be_seeded_from_output_item_added_text() { - let mut parsers = AssistantMessageStreamParsers::new(false); + let mut parsers = AssistantMessageStreamParsers::new(/*plan_mode*/ false); let item_id = "msg-1"; let seeded = parsers.seed_item_text(item_id, "hello doc"); @@ -330,7 +330,7 @@ fn assistant_message_stream_parsers_can_be_seeded_from_output_item_added_text() #[test] fn assistant_message_stream_parsers_seed_buffered_prefix_stays_out_of_finish_tail() { - let mut parsers = AssistantMessageStreamParsers::new(false); + let mut parsers = AssistantMessageStreamParsers::new(/*plan_mode*/ false); let item_id = "msg-1"; let seeded = parsers.seed_item_text(item_id, "hello anyhow::Result<()> { let spec = crate::config::NetworkProxySpec::from_config_and_constraints( NetworkProxyConfig::default(), - None, + /*requirements*/ None, &SandboxPolicy::new_workspace_write_policy(), )?; let mut exec_policy = Policy::empty(); @@ -457,16 +457,16 @@ async fn start_managed_network_proxy_applies_execpolicy_network_rules() -> anyho "example.com", NetworkRuleProtocol::Https, Decision::Allow, - None, + /*justification*/ None, )?; let (started_proxy, _) = Session::start_managed_network_proxy( &spec, &exec_policy, &SandboxPolicy::new_workspace_write_policy(), - None, - None, - false, + /*network_policy_decider*/ None, + /*blocked_request_observer*/ None, + /*managed_network_requirements_enabled*/ false, crate::config::NetworkProxyAuditMetadata::default(), ) .await?; @@ -501,16 +501,16 @@ async fn start_managed_network_proxy_ignores_invalid_execpolicy_network_rules() "example.com", NetworkRuleProtocol::Https, Decision::Allow, - None, + /*justification*/ None, )?; let (started_proxy, _) = Session::start_managed_network_proxy( &spec, &exec_policy, &SandboxPolicy::new_workspace_write_policy(), - None, - None, - false, + /*network_policy_decider*/ None, + /*blocked_request_observer*/ None, + /*managed_network_requirements_enabled*/ false, crate::config::NetworkProxyAuditMetadata::default(), ) .await?; @@ -737,7 +737,9 @@ fn non_app_mcp_tools_remain_visible_without_search_selection() { ), ( "mcp__rmcp__echo".to_string(), - make_mcp_tool("rmcp", "echo", None, None), + make_mcp_tool( + "rmcp", "echo", /*connector_id*/ None, /*connector_name*/ None, + ), ), ]); @@ -785,7 +787,9 @@ fn search_tool_selection_keeps_codex_apps_tools_without_mentions() { ), ( "mcp__rmcp__echo".to_string(), - make_mcp_tool("rmcp", "echo", None, None), + make_mcp_tool( + "rmcp", "echo", /*connector_id*/ None, /*connector_name*/ None, + ), ), ]); @@ -835,7 +839,9 @@ fn apps_mentions_add_codex_apps_tools_to_search_selected_set() { ), ( "mcp__rmcp__echo".to_string(), - make_mcp_tool("rmcp", "echo", None, None), + make_mcp_tool( + "rmcp", "echo", /*connector_id*/ None, /*connector_name*/ None, + ), ), ]); @@ -1179,7 +1185,13 @@ async fn fork_startup_context_then_first_turn_diff_snapshot() -> anyhow::Result< codex_config::Constrained::allow_any(AskForApproval::UnlessTrusted); let forked = initial .thread_manager - .fork_thread(usize::MAX, fork_config, rollout_path, false, None) + .fork_thread( + usize::MAX, + fork_config, + rollout_path, + /*persist_extended_history*/ false, + /*parent_trace*/ None, + ) .await?; let collaboration_mode = CollaborationMode { @@ -1351,7 +1363,7 @@ async fn thread_rollback_drops_last_turn_from_history() { state.set_reference_context_item(Some(tc.to_turn_context_item())); } - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let rollback_event = wait_for_thread_rolled_back(&rx).await; assert_eq!(rollback_event.num_turns, 1); @@ -1398,7 +1410,7 @@ async fn thread_rollback_clears_history_when_num_turns_exceeds_existing_turns() .collect(); sess.persist_rollout_items(&rollout_items).await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 99).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 99).await; let rollback_event = wait_for_thread_rolled_back(&rx).await; assert_eq!(rollback_event.num_turns, 99); @@ -1415,7 +1427,7 @@ async fn thread_rollback_fails_without_persisted_rollout_path() { sess.record_into_history(&initial_context, tc.as_ref()) .await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let error_event = wait_for_thread_rollback_failed(&rx).await; assert_eq!( @@ -1509,7 +1521,7 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context })) .await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let rollback_event = wait_for_thread_rolled_back(&rx).await; assert_eq!(rollback_event.num_turns, 1); @@ -1617,7 +1629,7 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio ) .await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let rollback_event = wait_for_thread_rolled_back(&rx).await; assert_eq!(rollback_event.num_turns, 1); @@ -1695,10 +1707,10 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() { ]) .await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let first_rollback = wait_for_thread_rolled_back(&rx).await; assert_eq!(first_rollback.num_turns, 1); - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let second_rollback = wait_for_thread_rolled_back(&rx).await; assert_eq!(second_rollback.num_turns, 1); @@ -1733,7 +1745,7 @@ async fn thread_rollback_fails_when_turn_in_progress() { .await; *sess.active_turn.lock().await = Some(crate::state::ActiveTurn::default()); - handlers::thread_rollback(&sess, "sub-1".to_string(), 1).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 1).await; let error_event = wait_for_thread_rollback_failed(&rx).await; assert_eq!( @@ -1753,7 +1765,7 @@ async fn thread_rollback_fails_when_num_turns_is_zero() { sess.record_into_history(&initial_context, tc.as_ref()) .await; - handlers::thread_rollback(&sess, "sub-1".to_string(), 0).await; + handlers::thread_rollback(&sess, "sub-1".to_string(), /*num_turns*/ 0).await; let error_event = wait_for_thread_rollback_failed(&rx).await; assert_eq!(error_event.message, "num_turns must be >= 1"); @@ -2152,14 +2164,14 @@ async fn attach_rollout_recorder(session: &Arc) -> PathBuf { config.as_ref(), RolloutRecorderParams::new( ThreadId::default(), - None, + /*forked_from_id*/ None, SessionSource::Exec, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), - None, - None, + /*state_db_ctx*/ None, + /*state_builder*/ None, ) .await .expect("create rollout recorder"); @@ -2198,11 +2210,11 @@ fn session_telemetry( conversation_id, ModelsManager::get_model_offline_for_tests(config.model.as_deref()).as_str(), model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), Some(TelemetryAuthMode::Chatgpt), "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), session_source, ) @@ -2325,7 +2337,7 @@ async fn new_default_turn_uses_config_aware_skills_for_role_overrides() { .skills_manager .skills_for_cwd( &crate::skills_load_input_from_config(&parent_config, Vec::new()), - true, + /*force_reload*/ true, ) .await; let parent_skill = parent_outcome @@ -2473,7 +2485,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() { let models_manager = Arc::new(ModelsManager::new( config.codex_home.clone(), auth_manager.clone(), - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), )); let model = ModelsManager::get_model_offline_for_tests(config.model.as_deref()); @@ -2522,7 +2534,10 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() { let (agent_status_tx, _agent_status_rx) = watch::channel(AgentStatus::PendingInit); let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone())); let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager))); - let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true)); + let skills_manager = Arc::new(SkillsManager::new( + config.codex_home.clone(), + /*bundled_skills_enabled*/ true, + )); let result = Session::new( session_configuration, Arc::clone(&config), @@ -2563,7 +2578,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) { let models_manager = Arc::new(ModelsManager::new( config.codex_home.clone(), auth_manager.clone(), - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), )); let agent_control = AgentControl::default(); @@ -2626,7 +2641,10 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) { let state = SessionState::new(session_configuration.clone()); let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone())); let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager))); - let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true)); + let skills_manager = Arc::new(SkillsManager::new( + config.codex_home.clone(), + /*bundled_skills_enabled*/ true, + )); let network_approval = Arc::new(NetworkApprovalService::default()); let environment = Arc::new( codex_exec_server::Environment::create(/*exec_server_url*/ None) @@ -2712,7 +2730,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) { per_turn_config, model_info, &models_manager, - None, + /*network*/ None, environment, "turn_id".to_string(), Arc::clone(&js_repl), @@ -3400,7 +3418,7 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx( let models_manager = Arc::new(ModelsManager::new( config.codex_home.clone(), auth_manager.clone(), - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), )); let agent_control = AgentControl::default(); @@ -3463,7 +3481,10 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx( let state = SessionState::new(session_configuration.clone()); let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone())); let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager))); - let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true)); + let skills_manager = Arc::new(SkillsManager::new( + config.codex_home.clone(), + /*bundled_skills_enabled*/ true, + )); let network_approval = Arc::new(NetworkApprovalService::default()); let environment = Arc::new( codex_exec_server::Environment::create(/*exec_server_url*/ None) @@ -3549,7 +3570,7 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx( per_turn_config, model_info, &models_manager, - None, + /*network*/ None, environment, "turn_id".to_string(), Arc::clone(&js_repl), @@ -3659,7 +3680,8 @@ async fn record_model_warning_appends_user_message() { #[tokio::test] async fn spawn_task_does_not_update_previous_turn_settings_for_non_run_turn_tasks() { let (sess, tc, _rx) = make_session_and_context_with_rx().await; - sess.set_previous_turn_settings(None).await; + sess.set_previous_turn_settings(/*previous_turn_settings*/ None) + .await; let input = vec![UserInput::Text { text: "hello".to_string(), text_elements: Vec::new(), @@ -3712,7 +3734,10 @@ async fn build_settings_update_items_emits_environment_item_for_network_changes( )); let layers = config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .cloned() .collect(); @@ -3909,7 +3934,7 @@ async fn build_initial_context_omits_default_image_save_location_with_image_hist revised_prompt: Some("a tiny blue square".to_string()), result: "Zm9v".to_string(), }], - None, + /*reference_context_item*/ None, ) .await; @@ -3963,7 +3988,7 @@ async fn handle_output_item_done_records_image_save_history_message() { tool_runtime: test_tool_runtime(Arc::clone(&session), Arc::clone(&turn_context)), cancellation_token: CancellationToken::new(), }; - handle_output_item_done(&mut ctx, item.clone(), None) + handle_output_item_done(&mut ctx, item.clone(), /*previously_active_item*/ None) .await .expect("image generation item should succeed"); @@ -4020,7 +4045,7 @@ async fn handle_output_item_done_skips_image_save_message_when_save_fails() { tool_runtime: test_tool_runtime(Arc::clone(&session), Arc::clone(&turn_context)), cancellation_token: CancellationToken::new(), }; - handle_output_item_done(&mut ctx, item.clone(), None) + handle_output_item_done(&mut ctx, item.clone(), /*previously_active_item*/ None) .await .expect("image generation item should still complete"); @@ -4112,10 +4137,13 @@ async fn record_context_updates_and_set_reference_context_item_reinjects_full_co .await; { let mut state = session.state.lock().await; - state.set_reference_context_item(None); + state.set_reference_context_item(/*item*/ None); } session - .replace_history(vec![compacted_summary.clone()], None) + .replace_history( + vec![compacted_summary.clone()], + /*reference_context_item*/ None, + ) .await; session @@ -4150,14 +4178,14 @@ async fn record_context_updates_and_set_reference_context_item_persists_baseline config.as_ref(), RolloutRecorderParams::new( ThreadId::default(), - None, + /*forked_from_id*/ None, SessionSource::Exec, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), - None, - None, + /*state_db_ctx*/ None, + /*state_builder*/ None, ) .await .expect("create rollout recorder"); @@ -4247,14 +4275,14 @@ async fn record_context_updates_and_set_reference_context_item_persists_full_rei config.as_ref(), RolloutRecorderParams::new( ThreadId::default(), - None, + /*forked_from_id*/ None, SessionSource::Exec, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), - None, - None, + /*state_db_ctx*/ None, + /*state_builder*/ None, ) .await .expect("create rollout recorder"); @@ -4276,7 +4304,7 @@ async fn record_context_updates_and_set_reference_context_item_persists_full_rei .await; { let mut state = session.state.lock().await; - state.set_reference_context_item(None); + state.set_reference_context_item(/*item*/ None); } session @@ -4315,7 +4343,7 @@ async fn run_user_shell_command_does_not_set_reference_context_item() { let (session, _turn_context, rx) = make_session_and_context_with_rx().await; { let mut state = session.state.lock().await; - state.set_reference_context_item(None); + state.set_reference_context_item(/*item*/ None); } handlers::run_user_shell_command(&session, "sub-id".to_string(), "echo shell".to_string()) @@ -4468,7 +4496,8 @@ async fn task_finish_emits_turn_item_lifecycle_for_leftover_pending_user_input() .await .expect("inject pending input into active turn"); - sess.on_task_finished(Arc::clone(&tc), None).await; + sess.on_task_finished(Arc::clone(&tc), /*last_agent_message*/ None) + .await; let history = sess.clone_history().await; let expected = ResponseItem::Message { @@ -4560,7 +4589,7 @@ async fn steer_input_requires_active_turn() { }]; let err = sess - .steer_input(input, None) + .steer_input(input, /*expected_turn_id*/ None) .await .expect_err("steering without active turn should fail"); diff --git a/codex-rs/core/src/codex_tests_guardian.rs b/codex-rs/core/src/codex_tests_guardian.rs index 18eb3d177..f5698d58f 100644 --- a/codex-rs/core/src/codex_tests_guardian.rs +++ b/codex-rs/core/src/codex_tests_guardian.rs @@ -425,11 +425,14 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() { let models_manager = Arc::new(ModelsManager::new( config.codex_home.clone(), auth_manager.clone(), - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), )); let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone())); - let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true)); + let skills_manager = Arc::new(SkillsManager::new( + config.codex_home.clone(), + /*bundled_skills_enabled*/ true, + )); let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager))); let skills_watcher = Arc::new(SkillsWatcher::noop()); diff --git a/codex-rs/core/src/commit_attribution_tests.rs b/codex-rs/core/src/commit_attribution_tests.rs index be7661a60..8b2ce27e1 100644 --- a/codex-rs/core/src/commit_attribution_tests.rs +++ b/codex-rs/core/src/commit_attribution_tests.rs @@ -11,7 +11,7 @@ fn blank_attribution_disables_trailer_prompt() { #[test] fn default_attribution_uses_codex_trailer() { assert_eq!( - build_commit_message_trailer(None).as_deref(), + build_commit_message_trailer(/*config_attribution*/ None).as_deref(), Some("Co-authored-by: Codex ") ); } @@ -19,7 +19,7 @@ fn default_attribution_uses_codex_trailer() { #[test] fn resolve_value_handles_default_custom_and_blank() { assert_eq!( - resolve_attribution_value(None), + resolve_attribution_value(/*config_attribution*/ None), Some("Codex ".to_string()) ); assert_eq!( diff --git a/codex-rs/core/src/compact_tests.rs b/codex-rs/core/src/compact_tests.rs index 92e889d64..cecf9ce9d 100644 --- a/codex-rs/core/src/compact_tests.rs +++ b/codex-rs/core/src/compact_tests.rs @@ -216,8 +216,11 @@ async fn process_compacted_history_replaces_developer_messages() { phase: None, }, ]; - let (refreshed, mut expected) = - process_compacted_history_with_test_session(compacted_history, None).await; + let (refreshed, mut expected) = process_compacted_history_with_test_session( + compacted_history, + /*previous_turn_settings*/ None, + ) + .await; expected.push(ResponseItem::Message { id: None, role: "user".to_string(), @@ -241,8 +244,11 @@ async fn process_compacted_history_reinjects_full_initial_context() { end_turn: None, phase: None, }]; - let (refreshed, mut expected) = - process_compacted_history_with_test_session(compacted_history, None).await; + let (refreshed, mut expected) = process_compacted_history_with_test_session( + compacted_history, + /*previous_turn_settings*/ None, + ) + .await; expected.push(ResponseItem::Message { id: None, role: "user".to_string(), @@ -317,8 +323,11 @@ keep me updated phase: None, }, ]; - let (refreshed, mut expected) = - process_compacted_history_with_test_session(compacted_history, None).await; + let (refreshed, mut expected) = process_compacted_history_with_test_session( + compacted_history, + /*previous_turn_settings*/ None, + ) + .await; expected.push(ResponseItem::Message { id: None, role: "user".to_string(), @@ -363,8 +372,11 @@ async fn process_compacted_history_inserts_context_before_last_real_user_message }, ]; - let (refreshed, initial_context) = - process_compacted_history_with_test_session(compacted_history, None).await; + let (refreshed, initial_context) = process_compacted_history_with_test_session( + compacted_history, + /*previous_turn_settings*/ None, + ) + .await; let mut expected = vec![ ResponseItem::Message { id: None, diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 60f0e06f7..00227fe2b 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -507,7 +507,7 @@ fn default_permissions_profile_populates_runtime_sandbox_policy() -> std::io::Re }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::project_roots(None), + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -709,7 +709,10 @@ fn permissions_profiles_allow_unknown_special_paths() -> std::io::Result<()> { config.permissions.file_system_sandbox_policy, FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::unknown(":future_special_path", None), + value: FileSystemSpecialPath::unknown( + ":future_special_path", + /*subpath*/ None + ), }, access: FileSystemAccessMode::Read, }]), @@ -976,10 +979,10 @@ network_access = false # This should be ignored. let sandbox_mode_override = None; let resolution = sandbox_full_access_cfg.derive_sandbox_policy( sandbox_mode_override, - None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &PathBuf::from("/tmp/test"), - None, + /*sandbox_policy_constraint*/ None, ); assert_eq!(resolution, SandboxPolicy::DangerFullAccess); @@ -995,10 +998,10 @@ network_access = true # This should be ignored. let sandbox_mode_override = None; let resolution = sandbox_read_only_cfg.derive_sandbox_policy( sandbox_mode_override, - None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &PathBuf::from("/tmp/test"), - None, + /*sandbox_policy_constraint*/ None, ); assert_eq!(resolution, SandboxPolicy::new_read_only_policy()); @@ -1022,10 +1025,10 @@ exclude_slash_tmp = true let sandbox_mode_override = None; let resolution = sandbox_workspace_write_cfg.derive_sandbox_policy( sandbox_mode_override, - None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &PathBuf::from("/tmp/test"), - None, + /*sandbox_policy_constraint*/ None, ); if cfg!(target_os = "windows") { assert_eq!(resolution, SandboxPolicy::new_read_only_policy()); @@ -1064,10 +1067,10 @@ trust_level = "trusted" let sandbox_mode_override = None; let resolution = sandbox_workspace_write_cfg.derive_sandbox_policy( sandbox_mode_override, - None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &PathBuf::from("/tmp/test"), - None, + /*sandbox_policy_constraint*/ None, ); if cfg!(target_os = "windows") { assert_eq!(resolution, SandboxPolicy::new_read_only_policy()); @@ -1245,7 +1248,7 @@ fn filter_mcp_servers_by_allowlist_allows_all_when_unset() { ("server-b".to_string(), http_mcp("https://example.com/b")), ]); - filter_mcp_servers_by_requirements(&mut servers, None); + filter_mcp_servers_by_requirements(&mut servers, /*mcp_requirements*/ None); assert_eq!( servers @@ -1874,7 +1877,7 @@ async fn replace_mcp_servers_round_trips_entries() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -1904,7 +1907,7 @@ async fn replace_mcp_servers_round_trips_entries() -> anyhow::Result<()> { let empty = BTreeMap::new(); apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(empty.clone())], )?; let loaded = load_global_mcp_servers(codex_home.path()).await?; @@ -2101,7 +2104,7 @@ async fn replace_mcp_servers_serializes_env_sorted() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2174,7 +2177,7 @@ async fn replace_mcp_servers_serializes_env_vars() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2227,7 +2230,7 @@ async fn replace_mcp_servers_serializes_cwd() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2278,7 +2281,7 @@ async fn replace_mcp_servers_streamable_http_serializes_bearer_token() -> anyhow apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2344,7 +2347,7 @@ async fn replace_mcp_servers_streamable_http_serializes_custom_headers() -> anyh )]); apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2424,7 +2427,7 @@ async fn replace_mcp_servers_streamable_http_removes_optional_sections() -> anyh apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; let serialized_with_optional = std::fs::read_to_string(&config_path)?; @@ -2455,7 +2458,7 @@ async fn replace_mcp_servers_streamable_http_removes_optional_sections() -> anyh ); apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2546,7 +2549,7 @@ async fn replace_mcp_servers_streamable_http_isolates_headers_between_servers() apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2630,7 +2633,7 @@ async fn replace_mcp_servers_serializes_disabled_flag() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2677,7 +2680,7 @@ async fn replace_mcp_servers_serializes_required_flag() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2724,7 +2727,7 @@ async fn replace_mcp_servers_serializes_tool_filters() -> anyhow::Result<()> { apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2775,7 +2778,7 @@ async fn replace_mcp_servers_streamable_http_serializes_oauth_resource() -> anyh apply_blocking( codex_home.path(), - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], )?; @@ -2929,7 +2932,7 @@ async fn set_feature_enabled_updates_profile() -> anyhow::Result<()> { ConfigEditsBuilder::new(codex_home.path()) .with_profile(Some("dev")) - .set_feature_enabled("guardian_approval", true) + .set_feature_enabled("guardian_approval", /*enabled*/ true) .apply() .await?; @@ -2965,13 +2968,13 @@ async fn set_feature_enabled_persists_default_false_feature_disable_in_profile() ConfigEditsBuilder::new(codex_home.path()) .with_profile(Some("dev")) - .set_feature_enabled("guardian_approval", true) + .set_feature_enabled("guardian_approval", /*enabled*/ true) .apply() .await?; ConfigEditsBuilder::new(codex_home.path()) .with_profile(Some("dev")) - .set_feature_enabled("guardian_approval", false) + .set_feature_enabled("guardian_approval", /*enabled*/ false) .apply() .await?; @@ -3005,13 +3008,13 @@ async fn set_feature_enabled_profile_disable_overrides_root_enable() -> anyhow:: let codex_home = TempDir::new()?; ConfigEditsBuilder::new(codex_home.path()) - .set_feature_enabled("guardian_approval", true) + .set_feature_enabled("guardian_approval", /*enabled*/ true) .apply() .await?; ConfigEditsBuilder::new(codex_home.path()) .with_profile(Some("dev")) - .set_feature_enabled("guardian_approval", false) + .set_feature_enabled("guardian_approval", /*enabled*/ false) .apply() .await?; @@ -4323,7 +4326,8 @@ model_verbosity = "high" supports_websockets: false, }; let model_provider_map = { - let mut model_provider_map = built_in_model_providers(/* openai_base_url */ None); + let mut model_provider_map = + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None); model_provider_map.insert("openai-custom".to_string(), openai_custom_provider.clone()); model_provider_map }; @@ -4392,7 +4396,7 @@ fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> { windows_sandbox_private_desktop: true, }, approvals_reviewer: ApprovalsReviewer::User, - enforce_residency: Constrained::allow_any(None), + enforce_residency: Constrained::allow_any(/*initial_value*/ None), user_instructions: None, notify: None, cwd: fixture.cwd(), @@ -4534,7 +4538,7 @@ fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> { windows_sandbox_private_desktop: true, }, approvals_reviewer: ApprovalsReviewer::User, - enforce_residency: Constrained::allow_any(None), + enforce_residency: Constrained::allow_any(/*initial_value*/ None), user_instructions: None, notify: None, cwd: fixture.cwd(), @@ -4674,7 +4678,7 @@ fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> { windows_sandbox_private_desktop: true, }, approvals_reviewer: ApprovalsReviewer::User, - enforce_residency: Constrained::allow_any(None), + enforce_residency: Constrained::allow_any(/*initial_value*/ None), user_instructions: None, notify: None, cwd: fixture.cwd(), @@ -4800,7 +4804,7 @@ fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> { windows_sandbox_private_desktop: true, }, approvals_reviewer: ApprovalsReviewer::User, - enforce_residency: Constrained::allow_any(None), + enforce_residency: Constrained::allow_any(/*initial_value*/ None), user_instructions: None, notify: None, cwd: fixture.cwd(), @@ -5142,11 +5146,11 @@ trust_level = "untrusted" .expect("TOML deserialization should succeed"); let resolution = cfg.derive_sandbox_policy( - None, - None, + /*sandbox_mode_override*/ None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &PathBuf::from("/tmp/test"), - None, + /*sandbox_policy_constraint*/ None, ); // Verify that untrusted projects get WorkspaceWrite (or ReadOnly on Windows due to downgrade) @@ -5194,8 +5198,8 @@ fn derive_sandbox_policy_falls_back_to_constraint_value_for_implicit_defaults() })?; let resolution = cfg.derive_sandbox_policy( - None, - None, + /*sandbox_mode_override*/ None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &project_path, Some(&constrained), @@ -5234,8 +5238,8 @@ fn derive_sandbox_policy_preserves_windows_downgrade_for_unsupported_fallback() })?; let resolution = cfg.derive_sandbox_policy( - None, - None, + /*sandbox_mode_override*/ None, + /*profile_sandbox_mode*/ None, WindowsSandboxLevel::Disabled, &project_path, Some(&constrained), @@ -5252,7 +5256,11 @@ fn derive_sandbox_policy_preserves_windows_downgrade_for_unsupported_fallback() #[test] fn test_resolve_oss_provider_explicit_override() { let config_toml = ConfigToml::default(); - let result = resolve_oss_provider(Some("custom-provider"), &config_toml, None); + let result = resolve_oss_provider( + Some("custom-provider"), + &config_toml, + /*config_profile*/ None, + ); assert_eq!(result, Some("custom-provider".to_string())); } @@ -5269,7 +5277,11 @@ fn test_resolve_oss_provider_from_profile() { ..Default::default() }; - let result = resolve_oss_provider(None, &config_toml, Some("test-profile".to_string())); + let result = resolve_oss_provider( + /*explicit_provider*/ None, + &config_toml, + Some("test-profile".to_string()), + ); assert_eq!(result, Some("profile-provider".to_string())); } @@ -5280,7 +5292,11 @@ fn test_resolve_oss_provider_from_global_config() { ..Default::default() }; - let result = resolve_oss_provider(None, &config_toml, None); + let result = resolve_oss_provider( + /*explicit_provider*/ None, + &config_toml, + /*config_profile*/ None, + ); assert_eq!(result, Some("global-provider".to_string())); } @@ -5295,14 +5311,22 @@ fn test_resolve_oss_provider_profile_fallback_to_global() { ..Default::default() }; - let result = resolve_oss_provider(None, &config_toml, Some("test-profile".to_string())); + let result = resolve_oss_provider( + /*explicit_provider*/ None, + &config_toml, + Some("test-profile".to_string()), + ); assert_eq!(result, Some("global-provider".to_string())); } #[test] fn test_resolve_oss_provider_none_when_not_configured() { let config_toml = ConfigToml::default(); - let result = resolve_oss_provider(None, &config_toml, None); + let result = resolve_oss_provider( + /*explicit_provider*/ None, + &config_toml, + /*config_profile*/ None, + ); assert_eq!(result, None); } diff --git a/codex-rs/core/src/config/edit_tests.rs b/codex-rs/core/src/config/edit_tests.rs index d7386c546..e27add005 100644 --- a/codex-rs/core/src/config/edit_tests.rs +++ b/codex-rs/core/src/config/edit_tests.rs @@ -16,7 +16,7 @@ fn blocking_set_model_top_level() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: Some("gpt-5.1-codex".to_string()), effort: Some(ReasoningEffort::High), @@ -150,7 +150,7 @@ profiles = { fast = { model = "gpt-4o", sandbox_mode = "strict" } } apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: Some("o4-mini".to_string()), effort: None, @@ -195,7 +195,7 @@ fn blocking_set_model_writes_through_symlink_chain() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: Some("gpt-5.1-codex".to_string()), effort: Some(ReasoningEffort::High), @@ -228,7 +228,7 @@ fn blocking_set_model_replaces_symlink_on_cycle() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: Some("gpt-5.1-codex".to_string()), effort: None, @@ -267,7 +267,7 @@ network_access = false apply_blocking( codex_home, - None, + /*profile*/ None, &[ ConfigEdit::SetPath { segments: vec![ @@ -322,7 +322,7 @@ profiles = { fast = { model = "gpt-4o", sandbox_mode = "strict" } } apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: None, effort: Some(ReasoningEffort::High), @@ -356,7 +356,7 @@ model_reasoning_effort = "low" apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetModel { model: Some("o5-preview".to_string()), effort: Some(ReasoningEffort::Minimal), @@ -420,7 +420,7 @@ existing = "value" apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetNoticeHideFullAccessWarning(true)], ) .expect("persist"); @@ -450,7 +450,7 @@ existing = "value" apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetNoticeHideRateLimitModelNudge(true)], ) .expect("persist"); @@ -476,7 +476,7 @@ existing = "value" .expect("seed"); apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetNoticeHideModelMigrationPrompt( "hide_gpt5_1_migration_prompt".to_string(), true, @@ -505,7 +505,7 @@ existing = "value" .expect("seed"); apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetNoticeHideModelMigrationPrompt( "hide_gpt-5.1-codex-max_migration_prompt".to_string(), true, @@ -534,7 +534,7 @@ existing = "value" .expect("seed"); apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::RecordModelMigrationSeen { from: "gpt-5".to_string(), to: "gpt-5.1".to_string(), @@ -616,7 +616,7 @@ fn blocking_replace_mcp_servers_round_trips() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(servers.clone())], ) .expect("persist"); @@ -681,7 +681,12 @@ fn blocking_replace_mcp_servers_serializes_tool_approval_overrides() { }, ); - apply_blocking(codex_home, None, &[ConfigEdit::ReplaceMcpServers(servers)]).expect("persist"); + apply_blocking( + codex_home, + /*profile*/ None, + &[ConfigEdit::ReplaceMcpServers(servers)], + ) + .expect("persist"); let raw = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config"); let expected = "\ @@ -731,7 +736,12 @@ foo = { command = "cmd" } }, ); - apply_blocking(codex_home, None, &[ConfigEdit::ReplaceMcpServers(servers)]).expect("persist"); + apply_blocking( + codex_home, + /*profile*/ None, + &[ConfigEdit::ReplaceMcpServers(servers)], + ) + .expect("persist"); let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config"); let expected = r#"[mcp_servers] @@ -777,7 +787,12 @@ foo = { command = "cmd" } # keep me }, ); - apply_blocking(codex_home, None, &[ConfigEdit::ReplaceMcpServers(servers)]).expect("persist"); + apply_blocking( + codex_home, + /*profile*/ None, + &[ConfigEdit::ReplaceMcpServers(servers)], + ) + .expect("persist"); let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config"); let expected = r#"[mcp_servers] @@ -822,7 +837,12 @@ foo = { command = "cmd", args = ["--flag"] } # keep me }, ); - apply_blocking(codex_home, None, &[ConfigEdit::ReplaceMcpServers(servers)]).expect("persist"); + apply_blocking( + codex_home, + /*profile*/ None, + &[ConfigEdit::ReplaceMcpServers(servers)], + ) + .expect("persist"); let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config"); let expected = r#"[mcp_servers] @@ -868,7 +888,12 @@ foo = { command = "cmd" } }, ); - apply_blocking(codex_home, None, &[ConfigEdit::ReplaceMcpServers(servers)]).expect("persist"); + apply_blocking( + codex_home, + /*profile*/ None, + &[ConfigEdit::ReplaceMcpServers(servers)], + ) + .expect("persist"); let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config"); let expected = r#"[mcp_servers] @@ -885,7 +910,7 @@ fn blocking_clear_path_noop_when_missing() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::ClearPath { segments: vec!["missing".to_string()], }], @@ -906,7 +931,7 @@ fn blocking_set_path_updates_notifications() { let item = value(false); apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::SetPath { segments: vec!["tui".to_string(), "notifications".to_string()], value: item, @@ -982,7 +1007,7 @@ async fn blocking_set_asynchronous_helpers_available() { let codex_home = tmp.path().to_path_buf(); ConfigEditsBuilder::new(&codex_home) - .set_hide_full_access_warning(true) + .set_hide_full_access_warning(/*acknowledged*/ true) .apply() .await .expect("persist"); @@ -1024,7 +1049,7 @@ fn blocking_builder_set_realtime_audio_persists_and_clears() { ); ConfigEditsBuilder::new(codex_home) - .set_realtime_microphone(None) + .set_realtime_microphone(/*microphone*/ None) .apply_blocking() .expect("clear realtime microphone"); @@ -1053,7 +1078,7 @@ fn replace_mcp_servers_blocking_clears_table_when_empty() { apply_blocking( codex_home, - None, + /*profile*/ None, &[ConfigEdit::ReplaceMcpServers(BTreeMap::new())], ) .expect("persist"); diff --git a/codex-rs/core/src/config/managed_features.rs b/codex-rs/core/src/config/managed_features.rs index 646a16153..44daa241c 100644 --- a/codex-rs/core/src/config/managed_features.rs +++ b/codex-rs/core/src/config/managed_features.rs @@ -96,7 +96,10 @@ impl ManagedFeatures { impl From for ManagedFeatures { fn from(features: Features) -> Self { Self { - value: ConstrainedWithSource::new(Constrained::allow_any(features), None), + value: ConstrainedWithSource::new( + Constrained::allow_any(features), + /*source*/ None, + ), pinned_features: BTreeMap::new(), } } diff --git a/codex-rs/core/src/config/permissions_tests.rs b/codex-rs/core/src/config/permissions_tests.rs index b1313d1b0..e3ea67d7b 100644 --- a/codex-rs/core/src/config/permissions_tests.rs +++ b/codex-rs/core/src/config/permissions_tests.rs @@ -9,8 +9,10 @@ use tempfile::TempDir; #[test] fn normalize_absolute_path_for_platform_simplifies_windows_verbatim_paths() { - let parsed = - normalize_absolute_path_for_platform(r"\\?\D:\c\x\worktrees\2508\swift-base", true); + let parsed = normalize_absolute_path_for_platform( + r"\\?\D:\c\x\worktrees\2508\swift-base", + /*is_windows*/ true, + ); assert_eq!(parsed, PathBuf::from(r"D:\c\x\worktrees\2508\swift-base")); } diff --git a/codex-rs/core/src/config_loader/tests.rs b/codex-rs/core/src/config_loader/tests.rs index 6a2bc0b6b..77e69a53c 100644 --- a/codex-rs/core/src/config_loader/tests.rs +++ b/codex-rs/core/src/config_loader/tests.rs @@ -797,7 +797,7 @@ async fn load_config_layers_fails_when_cloud_requirements_loader_fails() -> anyh CloudRequirementsLoader::new(async { Err(CloudRequirementsLoadError::new( codex_config::CloudRequirementsLoadErrorCode::RequestFailed, - None, + /*status_code*/ None, "cloud requirements failed", )) }), @@ -833,7 +833,13 @@ async fn project_layers_prefer_closest_cwd() -> std::io::Result<()> { let codex_home = tmp.path().join("home"); tokio::fs::create_dir_all(&codex_home).await?; - make_config_for_test(&codex_home, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &codex_home, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let cwd = AbsolutePathBuf::from_absolute_path(&nested)?; let layers = load_config_layers_state( &codex_home, @@ -899,7 +905,13 @@ model_instructions_file = "child.txt" let codex_home = tmp.path().join("home"); tokio::fs::create_dir_all(&codex_home).await?; - make_config_for_test(&codex_home, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &codex_home, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let config = ConfigBuilder::default() .codex_home(codex_home) @@ -965,7 +977,13 @@ async fn project_layer_is_added_when_dot_codex_exists_without_config_toml() -> s let codex_home = tmp.path().join("home"); tokio::fs::create_dir_all(&codex_home).await?; - make_config_for_test(&codex_home, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &codex_home, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let cwd = AbsolutePathBuf::from_absolute_path(&nested)?; let layers = load_config_layers_state( &codex_home, @@ -1018,7 +1036,7 @@ async fn codex_home_is_not_loaded_as_project_layer_from_home_dir() -> std::io::R let project_layers: Vec<_> = layers .get_layers( super::ConfigLayerStackOrdering::HighestPrecedenceFirst, - true, + /*include_disabled*/ true, ) .into_iter() .filter(|layer| matches!(layer.name, super::ConfigLayerSource::Project { .. })) @@ -1046,7 +1064,13 @@ async fn codex_home_within_project_tree_is_not_double_loaded() -> std::io::Resul tokio::fs::write(nested_dot_codex.join(CONFIG_TOML_FILE), "foo = \"child\"\n").await?; tokio::fs::create_dir_all(&project_dot_codex).await?; - make_config_for_test(&project_dot_codex, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &project_dot_codex, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let user_config_path = project_dot_codex.join(CONFIG_TOML_FILE); let user_config_contents = tokio::fs::read_to_string(&user_config_path).await?; tokio::fs::write( @@ -1068,7 +1092,7 @@ async fn codex_home_within_project_tree_is_not_double_loaded() -> std::io::Resul let project_layers: Vec<_> = layers .get_layers( super::ConfigLayerStackOrdering::HighestPrecedenceFirst, - true, + /*include_disabled*/ true, ) .into_iter() .filter(|layer| matches!(layer.name, super::ConfigLayerSource::Project { .. })) @@ -1115,7 +1139,7 @@ async fn project_layers_disabled_when_untrusted_or_unknown() -> std::io::Result< &codex_home_untrusted, &project_root, TrustLevel::Untrusted, - None, + /*project_root_markers*/ None, ) .await?; let untrusted_config_path = codex_home_untrusted.join(CONFIG_TOML_FILE); @@ -1137,7 +1161,7 @@ async fn project_layers_disabled_when_untrusted_or_unknown() -> std::io::Result< let project_layers_untrusted: Vec<_> = layers_untrusted .get_layers( super::ConfigLayerStackOrdering::HighestPrecedenceFirst, - true, + /*include_disabled*/ true, ) .into_iter() .filter(|layer| matches!(layer.name, super::ConfigLayerSource::Project { .. })) @@ -1175,7 +1199,7 @@ async fn project_layers_disabled_when_untrusted_or_unknown() -> std::io::Result< let project_layers_unknown: Vec<_> = layers_unknown .get_layers( super::ConfigLayerStackOrdering::HighestPrecedenceFirst, - true, + /*include_disabled*/ true, ) .into_iter() .filter(|layer| matches!(layer.name, super::ConfigLayerSource::Project { .. })) @@ -1218,7 +1242,13 @@ enabled = false "#, ) .await?; - make_config_for_test(&codex_home, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &codex_home, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let config = ConfigBuilder::default() .codex_home(codex_home) @@ -1303,7 +1333,13 @@ async fn invalid_project_config_ignored_when_untrusted_or_unknown() -> std::io:: let config_path = codex_home.join(CONFIG_TOML_FILE); if let Some(trust_level) = trust_level { - make_config_for_test(&codex_home, &project_root, trust_level, None).await?; + make_config_for_test( + &codex_home, + &project_root, + trust_level, + /*project_root_markers*/ None, + ) + .await?; let config_contents = tokio::fs::read_to_string(&config_path).await?; tokio::fs::write(&config_path, format!("foo = \"user\"\n{config_contents}")).await?; } else { @@ -1321,7 +1357,7 @@ async fn invalid_project_config_ignored_when_untrusted_or_unknown() -> std::io:: let project_layers: Vec<_> = layers .get_layers( super::ConfigLayerStackOrdering::HighestPrecedenceFirst, - true, + /*include_disabled*/ true, ) .into_iter() .filter(|layer| matches!(layer.name, super::ConfigLayerSource::Project { .. })) @@ -1358,7 +1394,13 @@ async fn cli_overrides_with_relative_paths_do_not_break_trust_check() -> std::io let codex_home = tmp.path().join("home"); tokio::fs::create_dir_all(&codex_home).await?; - make_config_for_test(&codex_home, &project_root, TrustLevel::Trusted, None).await?; + make_config_for_test( + &codex_home, + &project_root, + TrustLevel::Trusted, + /*project_root_markers*/ None, + ) + .await?; let cwd = AbsolutePathBuf::from_absolute_path(&nested)?; let cli_overrides = vec![( diff --git a/codex-rs/core/src/connectors_tests.rs b/codex-rs/core/src/connectors_tests.rs index 2a98621a8..98515921e 100644 --- a/codex-rs/core/src/connectors_tests.rs +++ b/codex-rs/core/src/connectors_tests.rs @@ -171,7 +171,7 @@ fn accessible_connectors_from_mcp_tools_carries_plugin_display_names() { codex_app_tool( "calendar_list_events", "calendar", - None, + /*connector_name*/ None, &["sample", "sample"], ), ), @@ -229,8 +229,8 @@ async fn refresh_accessible_connectors_cache_from_mcp_tools_writes_latest_instal .build() .await .expect("config should load"); - let _ = config.features.set_enabled(Feature::Apps, true); - let cache_key = accessible_connectors_cache_key(&config, None); + let _ = config.features.set_enabled(Feature::Apps, /*enabled*/ true); + let cache_key = accessible_connectors_cache_key(&config, /*auth*/ None); let tools = HashMap::from([ ( "mcp__codex_apps__calendar_list_events".to_string(), @@ -253,7 +253,7 @@ async fn refresh_accessible_connectors_cache_from_mcp_tools_writes_latest_instal ]); let cached = with_accessible_connectors_cache_cleared(|| { - refresh_accessible_connectors_cache_from_mcp_tools(&config, None, &tools); + refresh_accessible_connectors_cache_from_mcp_tools(&config, /*auth*/ None, &tools); read_cached_accessible_connectors(&cache_key).expect("cache should be populated") }); @@ -367,8 +367,8 @@ fn app_tool_policy_uses_global_defaults_for_destructive_hints() { Some(&apps_config), Some("calendar"), "events/create", - None, - Some(&annotations(Some(true), None)), + /*tool_title*/ None, + Some(&annotations(Some(true), /*open_world_hint*/ None)), ); assert_eq!( @@ -392,7 +392,7 @@ fn app_is_enabled_uses_default_for_unconfigured_apps() { }; assert!(!app_is_enabled(&apps_config, Some("calendar"))); - assert!(!app_is_enabled(&apps_config, None)); + assert!(!app_is_enabled(&apps_config, /*connector_id*/ None)); } #[test] @@ -518,7 +518,13 @@ enabled = true .await .expect("config should build"); - let policy = app_tool_policy(&config, Some("connector_123123"), "events.list", None, None); + let policy = app_tool_policy( + &config, + Some("connector_123123"), + "events.list", + /*tool_title*/ None, + /*annotations*/ None, + ); assert_eq!( policy, AppToolPolicy { @@ -555,7 +561,13 @@ async fn cloud_requirements_disable_connector_applies_without_user_apps_table() .await .expect("config should build"); - let policy = app_tool_policy(&config, Some("connector_123123"), "events.list", None, None); + let policy = app_tool_policy( + &config, + Some("connector_123123"), + "events.list", + /*tool_title*/ None, + /*annotations*/ None, + ); assert_eq!( policy, AppToolPolicy { @@ -602,7 +614,13 @@ enabled = true .expect("apps config"), ); - let policy = app_tool_policy(&config, Some("connector_123123"), "events.list", None, None); + let policy = app_tool_policy( + &config, + Some("connector_123123"), + "events.list", + /*tool_title*/ None, + /*annotations*/ None, + ); assert_eq!( policy, AppToolPolicy { @@ -637,7 +655,13 @@ async fn local_requirements_disable_connector_applies_without_user_apps_table() ConfigLayerStack::new(Vec::new(), ConfigRequirements::default(), requirements) .expect("requirements stack"); - let policy = app_tool_policy(&config, Some("connector_123123"), "events.list", None, None); + let policy = app_tool_policy( + &config, + Some("connector_123123"), + "events.list", + /*tool_title*/ None, + /*annotations*/ None, + ); assert_eq!( policy, AppToolPolicy { @@ -699,8 +723,10 @@ fn app_tool_policy_honors_default_app_enabled_false() { Some(&apps_config), Some("calendar"), "events/list", - None, - Some(&annotations(None, None)), + /*tool_title*/ None, + Some(&annotations( + /*destructive_hint*/ None, /*open_world_hint*/ None, + )), ); assert_eq!( @@ -737,8 +763,10 @@ fn app_tool_policy_allows_per_app_enable_when_default_is_disabled() { Some(&apps_config), Some("calendar"), "events/list", - None, - Some(&annotations(None, None)), + /*tool_title*/ None, + Some(&annotations( + /*destructive_hint*/ None, /*open_world_hint*/ None, + )), ); assert_eq!( @@ -779,7 +807,7 @@ fn app_tool_policy_per_tool_enabled_true_overrides_app_level_disable_flags() { Some(&apps_config), Some("calendar"), "events/create", - None, + /*tool_title*/ None, Some(&annotations(Some(true), Some(true))), ); @@ -813,7 +841,7 @@ fn app_tool_policy_default_tools_enabled_true_overrides_app_level_tool_hints() { Some(&apps_config), Some("calendar"), "events/create", - None, + /*tool_title*/ None, Some(&annotations(Some(true), Some(true))), ); @@ -847,8 +875,10 @@ fn app_tool_policy_default_tools_enabled_false_overrides_app_level_tool_hints() Some(&apps_config), Some("calendar"), "events/list", - None, - Some(&annotations(None, None)), + /*tool_title*/ None, + Some(&annotations( + /*destructive_hint*/ None, /*open_world_hint*/ None, + )), ); assert_eq!( @@ -883,8 +913,10 @@ fn app_tool_policy_uses_default_tools_approval_mode() { Some(&apps_config), Some("calendar"), "events/list", - None, - Some(&annotations(None, None)), + /*tool_title*/ None, + Some(&annotations( + /*destructive_hint*/ None, /*open_world_hint*/ None, + )), ); assert_eq!( diff --git a/codex-rs/core/src/context_manager/history_tests.rs b/codex-rs/core/src/context_manager/history_tests.rs index 3c508e05f..9720492c1 100644 --- a/codex-rs/core/src/context_manager/history_tests.rs +++ b/codex-rs/core/src/context_manager/history_tests.rs @@ -51,7 +51,7 @@ fn inter_agent_assistant_msg(text: &str) -> ResponseItem { AgentPath::root().join("worker").unwrap(), Vec::new(), text.to_string(), - true, + /*trigger_turn*/ true, ); ResponseItem::Message { id: None, @@ -246,7 +246,8 @@ fn filters_non_api_messages() { #[test] fn non_last_reasoning_tokens_return_zero_when_no_user_messages() { - let history = create_history_with_items(vec![reasoning_with_encrypted_content(800)]); + let history = + create_history_with_items(vec![reasoning_with_encrypted_content(/*len*/ 800)]); assert_eq!(history.get_non_last_reasoning_items_tokens(), 0); } @@ -254,11 +255,11 @@ fn non_last_reasoning_tokens_return_zero_when_no_user_messages() { #[test] fn non_last_reasoning_tokens_ignore_entries_after_last_user() { let history = create_history_with_items(vec![ - reasoning_with_encrypted_content(900), + reasoning_with_encrypted_content(/*len*/ 900), user_msg("first"), - reasoning_with_encrypted_content(1_000), + reasoning_with_encrypted_content(/*len*/ 1_000), user_msg("second"), - reasoning_with_encrypted_content(2_000), + reasoning_with_encrypted_content(/*len*/ 2_000), ]); // first: (900 * 0.75 - 650) / 4 = 6.25 tokens // second: (1000 * 0.75 - 650) / 4 = 25 tokens @@ -330,7 +331,7 @@ fn drop_last_n_user_turns_treats_inter_agent_assistant_messages_as_instruction_t inter_agent_reply, ]); - history.drop_last_n_user_turns(1); + history.drop_last_n_user_turns(/*num_turns*/ 1); assert_eq!(history.raw_items(), &vec![first_turn, first_reply]); } @@ -352,7 +353,7 @@ fn total_token_usage_includes_all_items_after_last_model_generated_item() { total_tokens: 100, ..Default::default() }, - None, + /*model_context_window*/ None, ); let added_user = user_msg("new user message"); let added_tool_output = custom_tool_call_output("tool-tail", "new tool output"); @@ -362,7 +363,7 @@ fn total_token_usage_includes_all_items_after_last_model_generated_item() { ); assert_eq!( - history.get_total_token_usage(true), + history.get_total_token_usage(/*server_reasoning_included*/ true), 100 + estimate_item_token_count(&added_user) + estimate_item_token_count(&added_tool_output) ); @@ -606,7 +607,12 @@ fn for_prompt_clears_image_generation_result_when_images_are_unsupported() { #[test] fn get_history_for_prompt_drops_ghost_commits() { let items = vec![ResponseItem::GhostSnapshot { - ghost_commit: GhostCommit::new("ghost-1".to_string(), None, Vec::new(), Vec::new()), + ghost_commit: GhostCommit::new( + "ghost-1".to_string(), + /*parent*/ None, + Vec::new(), + Vec::new(), + ), }]; let history = create_history_with_items(items); let modalities = default_input_modalities(); @@ -792,7 +798,7 @@ fn drop_last_n_user_turns_preserves_prefix() { let modalities = default_input_modalities(); let mut history = create_history_with_items(items); - history.drop_last_n_user_turns(1); + history.drop_last_n_user_turns(/*num_turns*/ 1); assert_eq!( history.for_prompt(&modalities), vec![ @@ -809,7 +815,7 @@ fn drop_last_n_user_turns_preserves_prefix() { user_msg("u2"), assistant_msg("a2"), ]); - history.drop_last_n_user_turns(99); + history.drop_last_n_user_turns(/*num_turns*/ 99); assert_eq!( history.for_prompt(&modalities), vec![assistant_msg("session prefix item")] @@ -838,7 +844,7 @@ fn drop_last_n_user_turns_ignores_session_prefix_user_messages() { let modalities = default_input_modalities(); let mut history = create_history_with_items(items); - history.drop_last_n_user_turns(1); + history.drop_last_n_user_turns(/*num_turns*/ 1); let expected_prefix_and_first_turn = vec![ user_input_text_msg("ctx"), @@ -892,7 +898,7 @@ fn drop_last_n_user_turns_ignores_session_prefix_user_messages() { user_input_text_msg("turn 2 user"), assistant_msg("turn 2 assistant"), ]); - history.drop_last_n_user_turns(2); + history.drop_last_n_user_turns(/*num_turns*/ 2); assert_eq!(history.for_prompt(&modalities), expected_prefix_only); let mut history = create_history_with_items(vec![ @@ -912,7 +918,7 @@ fn drop_last_n_user_turns_ignores_session_prefix_user_messages() { user_input_text_msg("turn 2 user"), assistant_msg("turn 2 assistant"), ]); - history.drop_last_n_user_turns(3); + history.drop_last_n_user_turns(/*num_turns*/ 3); assert_eq!(history.for_prompt(&modalities), expected_prefix_only); } @@ -935,7 +941,7 @@ fn drop_last_n_user_turns_trims_context_updates_above_rolled_back_turn() { let mut history = create_history_with_items(items); let reference_context_item = reference_context_item(); history.set_reference_context_item(Some(reference_context_item.clone())); - history.drop_last_n_user_turns(1); + history.drop_last_n_user_turns(/*num_turns*/ 1); assert_eq!( history.clone().for_prompt(&modalities), @@ -973,7 +979,7 @@ fn drop_last_n_user_turns_clears_reference_context_for_mixed_developer_context_b let modalities = default_input_modalities(); let mut history = create_history_with_items(items); history.set_reference_context_item(Some(reference_context_item())); - history.drop_last_n_user_turns(1); + history.drop_last_n_user_turns(/*num_turns*/ 1); assert_eq!( history.clone().for_prompt(&modalities), @@ -1165,7 +1171,7 @@ fn format_exec_output_truncates_large_error() { let truncated = truncate_exec_output(&large_error); - assert_truncated_message_matches(&truncated, line, 36250); + assert_truncated_message_matches(&truncated, line, /*expected_removed*/ 36250); assert_ne!(truncated, large_error); } @@ -1174,7 +1180,7 @@ fn format_exec_output_marks_byte_truncation_without_omitted_lines() { let long_line = "a".repeat(EXEC_FORMAT_MAX_BYTES + 10000); let truncated = truncate_exec_output(&long_line); assert_ne!(truncated, long_line); - assert_truncated_message_matches(&truncated, "a", 2500); + assert_truncated_message_matches(&truncated, "a", /*expected_removed*/ 2500); assert!( !truncated.contains("omitted"), "line omission marker should not appear when no lines were dropped: {truncated}" @@ -1196,7 +1202,7 @@ fn format_exec_output_reports_omitted_lines_and_keeps_head_and_tail() { .collect(); let truncated = truncate_exec_output(&content); - assert_truncated_message_matches(&truncated, "line-0-", 34_723); + assert_truncated_message_matches(&truncated, "line-0-", /*expected_removed*/ 34_723); assert!( truncated.contains("line-0-"), "expected head line to remain: {truncated}" @@ -1219,7 +1225,7 @@ fn format_exec_output_prefers_line_marker_when_both_limits_exceeded() { let truncated = truncate_exec_output(&content); - assert_truncated_message_matches(&truncated, "line-0-", 17_423); + assert_truncated_message_matches(&truncated, "line-0-", /*expected_removed*/ 17_423); } #[cfg(not(debug_assertions))] diff --git a/codex-rs/core/src/contextual_user_message_tests.rs b/codex-rs/core/src/contextual_user_message_tests.rs index 93db860ea..406f03c27 100644 --- a/codex-rs/core/src/contextual_user_message_tests.rs +++ b/codex-rs/core/src/contextual_user_message_tests.rs @@ -86,8 +86,8 @@ fn detects_hook_prompt_fragment_and_roundtrips_escaping() { let ContentItem::InputText { text } = content_item else { panic!("expected input text content item"); }; - let parsed = - parse_visible_hook_prompt_message(None, content.as_slice()).expect("visible hook prompt"); + let parsed = parse_visible_hook_prompt_message(/*id*/ None, content.as_slice()) + .expect("visible hook prompt"); assert_eq!( parsed.fragments, vec![HookPromptFragment { diff --git a/codex-rs/core/src/environment_context_tests.rs b/codex-rs/core/src/environment_context_tests.rs index 5718c09de..073f1fe16 100644 --- a/codex-rs/core/src/environment_context_tests.rs +++ b/codex-rs/core/src/environment_context_tests.rs @@ -20,8 +20,8 @@ fn serialize_workspace_write_environment_context() { fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, - None, + /*network*/ None, + /*subagents*/ None, ); let expected = format!( @@ -49,7 +49,7 @@ fn serialize_environment_context_with_network() { Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), Some(network), - None, + /*subagents*/ None, ); let expected = format!( @@ -73,12 +73,12 @@ fn serialize_environment_context_with_network() { #[test] fn serialize_read_only_environment_context() { let context = EnvironmentContext::new( - None, + /*cwd*/ None, fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, - None, + /*network*/ None, + /*subagents*/ None, ); let expected = r#" @@ -93,12 +93,12 @@ fn serialize_read_only_environment_context() { #[test] fn serialize_external_sandbox_environment_context() { let context = EnvironmentContext::new( - None, + /*cwd*/ None, fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, - None, + /*network*/ None, + /*subagents*/ None, ); let expected = r#" @@ -113,12 +113,12 @@ fn serialize_external_sandbox_environment_context() { #[test] fn serialize_external_sandbox_with_restricted_network_environment_context() { let context = EnvironmentContext::new( - None, + /*cwd*/ None, fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, - None, + /*network*/ None, + /*subagents*/ None, ); let expected = r#" @@ -133,12 +133,12 @@ fn serialize_external_sandbox_with_restricted_network_environment_context() { #[test] fn serialize_full_access_environment_context() { let context = EnvironmentContext::new( - None, + /*cwd*/ None, fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, - None, + /*network*/ None, + /*subagents*/ None, ); let expected = r#" @@ -155,18 +155,18 @@ fn equals_except_shell_compares_cwd() { let context1 = EnvironmentContext::new( Some(PathBuf::from("/repo")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); let context2 = EnvironmentContext::new( Some(PathBuf::from("/repo")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); assert!(context1.equals_except_shell(&context2)); } @@ -176,18 +176,18 @@ fn equals_except_shell_ignores_sandbox_policy() { let context1 = EnvironmentContext::new( Some(PathBuf::from("/repo")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); let context2 = EnvironmentContext::new( Some(PathBuf::from("/repo")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); assert!(context1.equals_except_shell(&context2)); @@ -198,18 +198,18 @@ fn equals_except_shell_compares_cwd_differences() { let context1 = EnvironmentContext::new( Some(PathBuf::from("/repo1")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); let context2 = EnvironmentContext::new( Some(PathBuf::from("/repo2")), fake_shell(), - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); assert!(!context1.equals_except_shell(&context2)); @@ -224,10 +224,10 @@ fn equals_except_shell_ignores_shell() { shell_path: "/bin/bash".into(), shell_snapshot: crate::shell::empty_shell_snapshot_receiver(), }, - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); let context2 = EnvironmentContext::new( Some(PathBuf::from("/repo")), @@ -236,10 +236,10 @@ fn equals_except_shell_ignores_shell() { shell_path: "/bin/zsh".into(), shell_snapshot: crate::shell::empty_shell_snapshot_receiver(), }, - None, - None, - None, - None, + /*current_date*/ None, + /*timezone*/ None, + /*network*/ None, + /*subagents*/ None, ); assert!(context1.equals_except_shell(&context2)); @@ -252,7 +252,7 @@ fn serialize_environment_context_with_subagents() { fake_shell(), Some("2026-02-26".to_string()), Some("America/Los_Angeles".to_string()), - None, + /*network*/ None, Some("- agent-1: atlas\n- agent-2".to_string()), ); diff --git a/codex-rs/core/src/event_mapping_tests.rs b/codex-rs/core/src/event_mapping_tests.rs index 65c2e7d97..a06111fd9 100644 --- a/codex-rs/core/src/event_mapping_tests.rs +++ b/codex-rs/core/src/event_mapping_tests.rs @@ -56,7 +56,7 @@ fn parses_user_message_with_text_and_two_images() { #[test] fn skips_local_image_label_text() { let image_url = "data:image/png;base64,abc".to_string(); - let label = codex_protocol::models::local_image_open_tag_text(1); + let label = codex_protocol::models::local_image_open_tag_text(/*label_number*/ 1); let user_text = "Please review this image.".to_string(); let item = ResponseItem::Message { diff --git a/codex-rs/core/src/exec_env_tests.rs b/codex-rs/core/src/exec_env_tests.rs index 6f001b582..ec6b5b5bb 100644 --- a/codex-rs/core/src/exec_env_tests.rs +++ b/codex-rs/core/src/exec_env_tests.rs @@ -121,7 +121,7 @@ fn populate_env_inserts_thread_id() { fn populate_env_omits_thread_id_when_missing() { let vars = make_vars(&[("PATH", "/usr/bin")]); let policy = ShellEnvironmentPolicy::default(); - let result = populate_env(vars, &policy, None); + let result = populate_env(vars, &policy, /*thread_id*/ None); let expected: HashMap = hashmap! { "PATH".to_string() => "/usr/bin".to_string(), diff --git a/codex-rs/core/src/exec_policy_tests.rs b/codex-rs/core/src/exec_policy_tests.rs index 200f302a2..03a586214 100644 --- a/codex-rs/core/src/exec_policy_tests.rs +++ b/codex-rs/core/src/exec_policy_tests.rs @@ -115,7 +115,10 @@ async fn child_uses_parent_exec_policy_when_non_exec_policy_layers_differ() { let mut child_config = parent_config.clone(); let mut layers: Vec<_> = child_config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .cloned() .collect(); @@ -156,7 +159,10 @@ async fn child_does_not_use_parent_exec_policy_when_requirements_exec_policy_dif child_config.config_layer_stack = ConfigLayerStack::new( child_config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .cloned() .collect(), @@ -291,7 +297,7 @@ async fn merges_requirements_exec_policy_network_rules() -> anyhow::Result<()> { "blocked.example.com", codex_execpolicy::NetworkRuleProtocol::Https, Decision::Forbidden, - None, + /*justification*/ None, )?; let requirements = ConfigRequirements { @@ -338,7 +344,7 @@ host_executable(name = "git", paths = ["{git_path_literal}"]) "blocked.example.com", codex_execpolicy::NetworkRuleProtocol::Https, Decision::Forbidden, - None, + /*justification*/ None, )?; let requirements = ConfigRequirements { @@ -805,7 +811,7 @@ fn unmatched_granular_policy_still_prompts_for_restricted_sandbox_escalation() { &read_only_file_system_sandbox_policy(), &command, SandboxPermissions::RequireEscalated, - false, + /*used_complex_parsing*/ false, ) ); } @@ -823,7 +829,7 @@ fn unmatched_on_request_uses_split_filesystem_policy_for_escalation_prompts() { &restricted_file_system_policy, &command, SandboxPermissions::RequireEscalated, - false, + /*used_complex_parsing*/ false, ) ); } @@ -1348,7 +1354,7 @@ fn derive_requested_execpolicy_amendment_for_test( fn derive_requested_execpolicy_amendment_returns_none_for_missing_prefix_rule() { assert_eq!( None, - derive_requested_execpolicy_amendment_for_test(None, &[]) + derive_requested_execpolicy_amendment_for_test(/*prefix_rule*/ None, &[]) ); } diff --git a/codex-rs/core/src/exec_tests.rs b/codex-rs/core/src/exec_tests.rs index 07532e5a1..cf00d7050 100644 --- a/codex-rs/core/src/exec_tests.rs +++ b/codex-rs/core/src/exec_tests.rs @@ -24,7 +24,7 @@ fn make_exec_output( #[test] fn sandbox_detection_requires_keywords() { - let output = make_exec_output(1, "", "", ""); + let output = make_exec_output(/*exit_code*/ 1, "", "", ""); assert!(!is_likely_sandbox_denied( SandboxType::LinuxSeccomp, &output @@ -33,13 +33,13 @@ fn sandbox_detection_requires_keywords() { #[test] fn sandbox_detection_identifies_keyword_in_stderr() { - let output = make_exec_output(1, "", "Operation not permitted", ""); + let output = make_exec_output(/*exit_code*/ 1, "", "Operation not permitted", ""); assert!(is_likely_sandbox_denied(SandboxType::LinuxSeccomp, &output)); } #[test] fn sandbox_detection_respects_quick_reject_exit_codes() { - let output = make_exec_output(127, "", "command not found", ""); + let output = make_exec_output(/*exit_code*/ 127, "", "command not found", ""); assert!(!is_likely_sandbox_denied( SandboxType::LinuxSeccomp, &output @@ -48,14 +48,14 @@ fn sandbox_detection_respects_quick_reject_exit_codes() { #[test] fn sandbox_detection_ignores_non_sandbox_mode() { - let output = make_exec_output(1, "", "Operation not permitted", ""); + let output = make_exec_output(/*exit_code*/ 1, "", "Operation not permitted", ""); assert!(!is_likely_sandbox_denied(SandboxType::None, &output)); } #[test] fn sandbox_detection_ignores_network_policy_text_in_non_sandbox_mode() { let output = make_exec_output( - 0, + /*exit_code*/ 0, "", "", r#"CODEX_NETWORK_POLICY_DECISION {"decision":"ask","reason":"not_allowed","source":"decider","protocol":"http","host":"google.com","port":80}"#, @@ -66,7 +66,7 @@ fn sandbox_detection_ignores_network_policy_text_in_non_sandbox_mode() { #[test] fn sandbox_detection_uses_aggregated_output() { let output = make_exec_output( - 101, + /*exit_code*/ 101, "", "", "cargo failed: Read-only file system when writing target", @@ -80,7 +80,7 @@ fn sandbox_detection_uses_aggregated_output() { #[test] fn sandbox_detection_ignores_network_policy_text_with_zero_exit_code() { let output = make_exec_output( - 0, + /*exit_code*/ 0, "", "", r#"CODEX_NETWORK_POLICY_DECISION {"decision":"ask","source":"decider","protocol":"http","host":"google.com","port":80}"#, @@ -100,9 +100,14 @@ async fn read_output_limits_retained_bytes_for_shell_capture() { writer.write_all(&bytes).await.expect("write"); }); - let out = read_output(reader, None, false, Some(EXEC_OUTPUT_MAX_BYTES)) - .await - .expect("read"); + let out = read_output( + reader, + /*stream*/ None, + /*is_stderr*/ false, + Some(EXEC_OUTPUT_MAX_BYTES), + ) + .await + .expect("read"); assert_eq!(out.text.len(), EXEC_OUTPUT_MAX_BYTES); } @@ -196,7 +201,11 @@ async fn read_output_retains_all_bytes_for_full_buffer_capture() { writer.write_all(&bytes).await.expect("write"); }); - let out = read_output(reader, None, false, None).await.expect("read"); + let out = read_output( + reader, /*stream*/ None, /*is_stderr*/ false, /*max_bytes*/ None, + ) + .await + .expect("read"); assert_eq!(out.text.len(), expected_len); } @@ -211,7 +220,7 @@ fn aggregate_output_keeps_all_bytes_when_uncapped() { truncated_after_lines: None, }; - let aggregated = aggregate_output(&stdout, &stderr, None); + let aggregated = aggregate_output(&stdout, &stderr, /*max_bytes*/ None); assert_eq!(aggregated.text.len(), EXEC_OUTPUT_MAX_BYTES * 2); assert_eq!( @@ -362,8 +371,8 @@ async fn process_exec_tool_call_preserves_full_buffer_capture_policy() -> Result NetworkSandboxPolicy::Enabled, cwd.as_path(), &None, - false, - None, + /*use_legacy_landlock*/ false, + /*stdout_stream*/ None, ) .await?; @@ -675,14 +684,15 @@ fn windows_elevated_rejects_split_write_read_carveouts() { #[test] fn process_exec_tool_call_uses_platform_sandbox_for_network_only_restrictions() { - let expected = codex_sandboxing::get_platform_sandbox(false).unwrap_or(SandboxType::None); + let expected = codex_sandboxing::get_platform_sandbox(/*windows_sandbox_enabled*/ false) + .unwrap_or(SandboxType::None); assert_eq!( select_process_exec_tool_sandbox_type( &FileSystemSandboxPolicy::unrestricted(), NetworkSandboxPolicy::Restricted, codex_protocol::config_types::WindowsSandboxLevel::Disabled, - false, + /*enforce_managed_network*/ false, ), expected ); @@ -736,8 +746,8 @@ async fn kill_child_process_group_kills_grandchildren_on_timeout() -> Result<()> &FileSystemSandboxPolicy::from(&SandboxPolicy::new_read_only_policy()), None, NetworkSandboxPolicy::Restricted, - None, - None, + /*stdout_stream*/ None, + /*after_spawn*/ None, ) .await?; assert!(output.timed_out); @@ -798,8 +808,8 @@ async fn process_exec_tool_call_respects_cancellation_token() -> Result<()> { NetworkSandboxPolicy::Enabled, cwd.as_path(), &None, - false, - None, + /*use_legacy_landlock*/ false, + /*stdout_stream*/ None, ) .await; let output = match result { diff --git a/codex-rs/core/src/external_agent_config_tests.rs b/codex-rs/core/src/external_agent_config_tests.rs index a760f73e1..7baadbec0 100644 --- a/codex-rs/core/src/external_agent_config_tests.rs +++ b/codex-rs/core/src/external_agent_config_tests.rs @@ -390,7 +390,7 @@ fn import_skills_returns_only_new_skill_directory_count() { fs::create_dir_all(agents_skills.join("skill-a")).expect("create existing target"); let copied_count = service_for_paths(claude_home, codex_home) - .import_skills(None) + .import_skills(/*cwd*/ None) .expect("import skills"); assert_eq!(copied_count, 1); diff --git a/codex-rs/core/src/file_watcher_tests.rs b/codex-rs/core/src/file_watcher_tests.rs index 53f6391f5..11bb37c8c 100644 --- a/codex-rs/core/src/file_watcher_tests.rs +++ b/codex-rs/core/src/file_watcher_tests.rs @@ -115,10 +115,10 @@ fn is_mutating_event_filters_non_mutating_event_kinds() { fn register_dedupes_by_path_and_scope() { let watcher = Arc::new(FileWatcher::noop()); let (subscriber, _rx) = watcher.add_subscriber(); - let _first = subscriber.register_path(path("/tmp/skills"), false); - let _second = subscriber.register_path(path("/tmp/skills"), false); - let _third = subscriber.register_path(path("/tmp/skills"), true); - let _fourth = subscriber.register_path(path("/tmp/other-skills"), true); + let _first = subscriber.register_path(path("/tmp/skills"), /*recursive*/ false); + let _second = subscriber.register_path(path("/tmp/skills"), /*recursive*/ false); + let _third = subscriber.register_path(path("/tmp/skills"), /*recursive*/ true); + let _fourth = subscriber.register_path(path("/tmp/other-skills"), /*recursive*/ true); assert_eq!( watcher.watch_counts_for_test(&path("/tmp/skills")), @@ -134,7 +134,7 @@ fn register_dedupes_by_path_and_scope() { fn watch_registration_drop_unregisters_paths() { let watcher = Arc::new(FileWatcher::noop()); let (subscriber, _rx) = watcher.add_subscriber(); - let registration = subscriber.register_path(path("/tmp/skills"), true); + let registration = subscriber.register_path(path("/tmp/skills"), /*recursive*/ true); drop(registration); @@ -146,7 +146,7 @@ fn subscriber_drop_unregisters_paths() { let watcher = Arc::new(FileWatcher::noop()); let registration = { let (subscriber, _rx) = watcher.add_subscriber(); - subscriber.register_path(path("/tmp/skills"), true) + subscriber.register_path(path("/tmp/skills"), /*recursive*/ true) }; assert_eq!(watcher.watch_counts_for_test(&path("/tmp/skills")), None); @@ -174,8 +174,8 @@ fn recursive_registration_downgrades_to_non_recursive_after_drop() { let watcher = Arc::new(FileWatcher::new().expect("watcher")); let (subscriber, _rx) = watcher.add_subscriber(); - let non_recursive = subscriber.register_path(root.clone(), false); - let recursive = subscriber.register_path(root.clone(), true); + let non_recursive = subscriber.register_path(root.clone(), /*recursive*/ false); + let recursive = subscriber.register_path(root.clone(), /*recursive*/ true); { let inner = watcher.inner.as_ref().expect("watcher inner"); @@ -209,7 +209,7 @@ fn unregister_holds_state_lock_until_unwatch_finishes() { let watcher = Arc::new(FileWatcher::new().expect("watcher")); let (unregister_subscriber, _unregister_rx) = watcher.add_subscriber(); let (register_subscriber, _register_rx) = watcher.add_subscriber(); - let registration = unregister_subscriber.register_path(root.clone(), true); + let registration = unregister_subscriber.register_path(root.clone(), /*recursive*/ true); let inner = watcher.inner.as_ref().expect("watcher inner"); let inner_guard = inner.lock().expect("inner lock"); @@ -229,7 +229,8 @@ fn unregister_holds_state_lock_until_unwatch_finishes() { let register_root = root.clone(); let register_thread = std::thread::spawn(move || { - let registration = register_subscriber.register_path(register_root, false); + let registration = + register_subscriber.register_path(register_root, /*recursive*/ false); (register_subscriber, registration) }); @@ -257,8 +258,8 @@ async fn matching_subscribers_are_notified() { let watcher = Arc::new(FileWatcher::noop()); let (skills_subscriber, skills_rx) = watcher.add_subscriber(); let (plugins_subscriber, plugins_rx) = watcher.add_subscriber(); - let _skills = skills_subscriber.register_path(path("/tmp/skills"), true); - let _plugins = plugins_subscriber.register_path(path("/tmp/plugins"), true); + let _skills = skills_subscriber.register_path(path("/tmp/skills"), /*recursive*/ true); + let _plugins = plugins_subscriber.register_path(path("/tmp/plugins"), /*recursive*/ true); let mut skills_rx = ThrottledWatchReceiver::new(skills_rx, TEST_THROTTLE_INTERVAL); let mut plugins_rx = ThrottledWatchReceiver::new(plugins_rx, TEST_THROTTLE_INTERVAL); @@ -285,7 +286,7 @@ async fn matching_subscribers_are_notified() { async fn non_recursive_watch_ignores_grandchildren() { let watcher = Arc::new(FileWatcher::noop()); let (subscriber, rx) = watcher.add_subscriber(); - let _registration = subscriber.register_path(path("/tmp/skills"), false); + let _registration = subscriber.register_path(path("/tmp/skills"), /*recursive*/ false); let mut rx = ThrottledWatchReceiver::new(rx, TEST_THROTTLE_INTERVAL); watcher @@ -300,7 +301,8 @@ async fn non_recursive_watch_ignores_grandchildren() { async fn ancestor_events_notify_child_watches() { let watcher = Arc::new(FileWatcher::noop()); let (subscriber, rx) = watcher.add_subscriber(); - let _registration = subscriber.register_path(path("/tmp/skills/rust/SKILL.md"), false); + let _registration = + subscriber.register_path(path("/tmp/skills/rust/SKILL.md"), /*recursive*/ false); let mut rx = ThrottledWatchReceiver::new(rx, TEST_THROTTLE_INTERVAL); watcher.send_paths_for_test(vec![path("/tmp/skills")]).await; @@ -321,7 +323,7 @@ async fn ancestor_events_notify_child_watches() { async fn spawn_event_loop_filters_non_mutating_events() { let watcher = Arc::new(FileWatcher::noop()); let (subscriber, rx) = watcher.add_subscriber(); - let _registration = subscriber.register_path(path("/tmp/skills"), true); + let _registration = subscriber.register_path(path("/tmp/skills"), /*recursive*/ true); let mut rx = ThrottledWatchReceiver::new(rx, TEST_THROTTLE_INTERVAL); let (raw_tx, raw_rx) = mpsc::unbounded_channel(); watcher.spawn_event_loop_for_test(raw_rx); diff --git a/codex-rs/core/src/git_info_tests.rs b/codex-rs/core/src/git_info_tests.rs index f6f77d166..4cb50f02f 100644 --- a/codex-rs/core/src/git_info_tests.rs +++ b/codex-rs/core/src/git_info_tests.rs @@ -72,7 +72,7 @@ async fn create_test_git_repo(temp_dir: &TempDir) -> PathBuf { #[tokio::test] async fn test_recent_commits_non_git_directory_returns_empty() { let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let entries = recent_commits(temp_dir.path(), 10).await; + let entries = recent_commits(temp_dir.path(), /*limit*/ 10).await; assert!(entries.is_empty(), "expected no commits outside a git repo"); } @@ -133,7 +133,7 @@ async fn test_recent_commits_orders_and_limits() { .expect("git commit 3"); // Request the latest 3 commits; should be our three changes in reverse time order. - let entries = recent_commits(&repo_path, 3).await; + let entries = recent_commits(&repo_path, /*limit*/ 3).await; assert_eq!(entries.len(), 3); assert_eq!(entries[0].subject, "third change"); assert_eq!(entries[1].subject, "second change"); diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index 64e27c42c..17993a974 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -746,9 +746,13 @@ mod tests { #[test] fn guardian_review_session_config_change_invalidates_cached_session() { let parent_config = crate::config::test_config(); - let cached_spawn_config = - build_guardian_review_session_config(&parent_config, None, "active-model", None) - .expect("cached guardian config"); + let cached_spawn_config = build_guardian_review_session_config( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect("cached guardian config"); let cached_reuse_key = GuardianReviewSessionReuseKey::from_spawn_config(&cached_spawn_config); @@ -757,9 +761,9 @@ mod tests { Some("https://guardian.example.invalid/v1".to_string()); let next_spawn_config = build_guardian_review_session_config( &changed_parent_config, - None, + /*live_network_config*/ None, "active-model", - None, + /*reasoning_effort*/ None, ) .expect("next guardian config"); let next_reuse_key = GuardianReviewSessionReuseKey::from_spawn_config(&next_spawn_config); @@ -775,7 +779,7 @@ mod tests { async fn run_before_review_deadline_times_out_before_future_completes() { let outcome = run_before_review_deadline( tokio::time::Instant::now() + Duration::from_millis(10), - None, + /*external_cancel*/ None, async { tokio::time::sleep(Duration::from_millis(50)).await; }, @@ -816,7 +820,7 @@ mod tests { let outcome = run_before_review_deadline_with_cancel( tokio::time::Instant::now() + Duration::from_millis(10), - None, + /*external_cancel*/ None, &cancel_token, async { tokio::time::sleep(Duration::from_millis(50)).await; @@ -862,7 +866,7 @@ mod tests { let outcome = run_before_review_deadline_with_cancel( tokio::time::Instant::now() + Duration::from_secs(1), - None, + /*external_cancel*/ None, &cancel_token, async { 42usize }, ) diff --git a/codex-rs/core/src/guardian/tests.rs b/codex-rs/core/src/guardian/tests.rs index b71b48bd6..c0df326eb 100644 --- a/codex-rs/core/src/guardian/tests.rs +++ b/codex-rs/core/src/guardian/tests.rs @@ -251,7 +251,7 @@ fn collect_guardian_transcript_entries_includes_recent_tool_calls_and_output() { fn guardian_truncate_text_keeps_prefix_suffix_and_xml_marker() { let content = "prefix ".repeat(200) + &" suffix".repeat(200); - let truncated = guardian_truncate_text(&content, 20); + let truncated = guardian_truncate_text(&content, /*token_cap*/ 20); assert!(truncated.starts_with("prefix")); assert!(truncated.contains(" anyhow: Arc::clone(&turn), first_prompt, guardian_output_schema(), - None, + /*external_cancel*/ None, ) .await; let second_prompt = build_guardian_prompt_items( @@ -659,7 +659,7 @@ async fn guardian_reuses_prompt_cache_key_and_appends_prior_reviews() -> anyhow: Arc::clone(&turn), second_prompt, guardian_output_schema(), - None, + /*external_cancel*/ None, ) .await; @@ -772,7 +772,7 @@ async fn guardian_review_surfaces_responses_api_errors_in_rejection_reason() -> additional_permissions: None, justification: Some("Need to push the reviewed docs fix.".to_string()), }, - None, + /*retry_reason*/ None, ) .await; @@ -884,7 +884,7 @@ async fn guardian_parallel_reviews_fork_from_last_committed_trunk_history() -> a justification: Some("Inspect repo state before proceeding.".to_string()), }; assert_eq!( - review_approval_request(&session, &turn, initial_request, None).await, + review_approval_request(&session, &turn, initial_request, /*retry_reason*/ None).await, ReviewDecision::Approved ); @@ -988,7 +988,7 @@ fn guardian_review_session_config_preserves_parent_network_proxy() { let guardian_config = build_guardian_review_session_config_for_test( &parent_config, - None, + /*live_network_config*/ None, "parent-active-model", Some(codex_protocol::openai_models::ReasoningEffort::Low), ) @@ -1019,9 +1019,13 @@ fn guardian_review_session_config_overrides_parent_developer_instructions() { parent_config.developer_instructions = Some("parent or managed config should not replace guardian policy".to_string()); - let guardian_config = - build_guardian_review_session_config_for_test(&parent_config, None, "active-model", None) - .expect("guardian config"); + let guardian_config = build_guardian_review_session_config_for_test( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect("guardian config"); assert_eq!( guardian_config.developer_instructions, @@ -1040,7 +1044,7 @@ fn guardian_review_session_config_uses_live_network_proxy_state() { parent_config.permissions.network = Some( NetworkProxySpec::from_config_and_constraints( parent_network, - None, + /*requirements*/ None, parent_config.permissions.sandbox_policy.get(), ) .expect("parent network proxy spec"), @@ -1056,7 +1060,7 @@ fn guardian_review_session_config_uses_live_network_proxy_state() { &parent_config, Some(live_network.clone()), "active-model", - None, + /*reasoning_effort*/ None, ) .expect("guardian config"); @@ -1065,7 +1069,7 @@ fn guardian_review_session_config_uses_live_network_proxy_state() { Some( NetworkProxySpec::from_config_and_constraints( live_network, - None, + /*requirements*/ None, &SandboxPolicy::new_read_only_policy(), ) .expect("live network proxy spec") @@ -1087,9 +1091,13 @@ fn guardian_review_session_config_rejects_pinned_collab_feature() { ) .expect("managed features"); - let err = - build_guardian_review_session_config_for_test(&parent_config, None, "active-model", None) - .expect_err("guardian config should fail when collab is pinned on"); + let err = build_guardian_review_session_config_for_test( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect_err("guardian config should fail when collab is pinned on"); assert!( err.to_string() @@ -1102,9 +1110,13 @@ fn guardian_review_session_config_uses_parent_active_model_instead_of_hardcoded_ let mut parent_config = test_config(); parent_config.model = Some("configured-model".to_string()); - let guardian_config = - build_guardian_review_session_config_for_test(&parent_config, None, "active-model", None) - .expect("guardian config"); + let guardian_config = build_guardian_review_session_config_for_test( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect("guardian config"); assert_eq!(guardian_config.model, Some("active-model".to_string())); } @@ -1135,9 +1147,13 @@ fn guardian_review_session_config_uses_requirements_guardian_override() { ) .expect("load config"); - let guardian_config = - build_guardian_review_session_config_for_test(&parent_config, None, "active-model", None) - .expect("guardian config"); + let guardian_config = build_guardian_review_session_config_for_test( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect("guardian config"); assert_eq!( guardian_config.developer_instructions, @@ -1163,9 +1179,13 @@ fn guardian_review_session_config_uses_default_guardian_policy_without_requireme ) .expect("load config"); - let guardian_config = - build_guardian_review_session_config_for_test(&parent_config, None, "active-model", None) - .expect("guardian config"); + let guardian_config = build_guardian_review_session_config_for_test( + &parent_config, + /*live_network_config*/ None, + "active-model", + /*reasoning_effort*/ None, + ) + .expect("guardian config"); assert_eq!( guardian_config.developer_instructions, diff --git a/codex-rs/core/src/mcp/auth.rs b/codex-rs/core/src/mcp/auth.rs index 06ddbdd51..6b146f129 100644 --- a/codex-rs/core/src/mcp/auth.rs +++ b/codex-rs/core/src/mcp/auth.rs @@ -209,7 +209,7 @@ mod tests { #[test] fn resolve_oauth_scopes_prefers_configured_over_discovered() { let resolved = resolve_oauth_scopes( - None, + /*explicit_scopes*/ None, Some(vec!["configured".to_string()]), Some(vec!["discovered".to_string()]), ); @@ -225,7 +225,11 @@ mod tests { #[test] fn resolve_oauth_scopes_uses_discovered_when_needed() { - let resolved = resolve_oauth_scopes(None, None, Some(vec!["discovered".to_string()])); + let resolved = resolve_oauth_scopes( + /*explicit_scopes*/ None, + /*configured_scopes*/ None, + Some(vec!["discovered".to_string()]), + ); assert_eq!( resolved, @@ -238,7 +242,11 @@ mod tests { #[test] fn resolve_oauth_scopes_preserves_explicitly_empty_configured_scopes() { - let resolved = resolve_oauth_scopes(None, Some(Vec::new()), Some(vec!["ignored".into()])); + let resolved = resolve_oauth_scopes( + /*explicit_scopes*/ None, + Some(Vec::new()), + Some(vec!["ignored".into()]), + ); assert_eq!( resolved, @@ -251,7 +259,10 @@ mod tests { #[test] fn resolve_oauth_scopes_falls_back_to_empty() { - let resolved = resolve_oauth_scopes(None, None, None); + let resolved = resolve_oauth_scopes( + /*explicit_scopes*/ None, /*configured_scopes*/ None, + /*discovered_scopes*/ None, + ); assert_eq!( resolved, diff --git a/codex-rs/core/src/mcp/mod_tests.rs b/codex-rs/core/src/mcp/mod_tests.rs index d1bbf68f6..6821fbce3 100644 --- a/codex-rs/core/src/mcp/mod_tests.rs +++ b/codex-rs/core/src/mcp/mod_tests.rs @@ -167,7 +167,12 @@ fn codex_apps_server_config_uses_legacy_codex_apps_path() { let mut config = crate::config::test_config(); config.chatgpt_base_url = "https://chatgpt.com".to_string(); - let mut servers = with_codex_apps_mcp(HashMap::new(), false, None, &config); + let mut servers = with_codex_apps_mcp( + HashMap::new(), + /*connectors_enabled*/ false, + /*auth*/ None, + &config, + ); assert!(!servers.contains_key(CODEX_APPS_MCP_SERVER_NAME)); config @@ -175,7 +180,9 @@ fn codex_apps_server_config_uses_legacy_codex_apps_path() { .enable(Feature::Apps) .expect("test config should allow apps"); - servers = with_codex_apps_mcp(servers, true, None, &config); + servers = with_codex_apps_mcp( + servers, /*connectors_enabled*/ true, /*auth*/ None, &config, + ); let server = servers .get(CODEX_APPS_MCP_SERVER_NAME) .expect("codex apps should be present when apps is enabled"); @@ -252,7 +259,7 @@ async fn effective_mcp_servers_include_plugins_without_overriding_user_config() .expect("test config should accept MCP servers"); let mcp_manager = McpManager::new(Arc::new(PluginsManager::new(config.codex_home.clone()))); - let effective = mcp_manager.effective_servers(&config, None); + let effective = mcp_manager.effective_servers(&config, /*auth*/ None); let sample = effective.get("sample").expect("user server should exist"); let docs = effective.get("docs").expect("plugin server should exist"); diff --git a/codex-rs/core/src/mcp_connection_manager_tests.rs b/codex-rs/core/src/mcp_connection_manager_tests.rs index 2331d0c1f..ec3b58678 100644 --- a/codex-rs/core/src/mcp_connection_manager_tests.rs +++ b/codex-rs/core/src/mcp_connection_manager_tests.rs @@ -562,7 +562,7 @@ fn mcp_init_error_display_prompts_for_login_when_auth_required() { let server_name = "example"; let err: StartupOutcomeError = anyhow::anyhow!("Auth required for server").into(); - let display = mcp_init_error_display(server_name, None, &err); + let display = mcp_init_error_display(server_name, /*entry*/ None, &err); let expected = format!( "The {server_name} MCP server is not logged in. Run `codex mcp login {server_name}`." @@ -609,7 +609,7 @@ fn mcp_init_error_display_includes_startup_timeout_hint() { let server_name = "slow"; let err: StartupOutcomeError = anyhow::anyhow!("request timed out").into(); - let display = mcp_init_error_display(server_name, None, &err); + let display = mcp_init_error_display(server_name, /*entry*/ None, &err); assert_eq!( "MCP client for `slow` timed out after 10 seconds. Add or adjust `startup_timeout_sec` in your config.toml:\n[mcp_servers.slow]\nstartup_timeout_sec = XX", diff --git a/codex-rs/core/src/mcp_tool_approval_templates.rs b/codex-rs/core/src/mcp_tool_approval_templates.rs index b1e0ee27d..66002ab5a 100644 --- a/codex-rs/core/src/mcp_tool_approval_templates.rs +++ b/codex-rs/core/src/mcp_tool_approval_templates.rs @@ -330,7 +330,7 @@ mod tests { &templates, "codex_apps", Some("github"), - None, + /*connector_name*/ None, Some("add_comment"), Some(&json!({})), ); @@ -361,7 +361,7 @@ mod tests { &templates, "codex_apps", Some("calendar"), - None, + /*connector_name*/ None, Some("create_event"), Some(&json!({})), ), diff --git a/codex-rs/core/src/mcp_tool_call_tests.rs b/codex-rs/core/src/mcp_tool_call_tests.rs index 42d703518..d7fcb374f 100644 --- a/codex-rs/core/src/mcp_tool_call_tests.rs +++ b/codex-rs/core/src/mcp_tool_call_tests.rs @@ -72,13 +72,13 @@ fn prompt_options( #[test] fn approval_required_when_read_only_false_and_destructive() { - let annotations = annotations(Some(false), Some(true), None); + let annotations = annotations(Some(false), Some(true), /*open_world*/ None); assert_eq!(requires_mcp_tool_approval(Some(&annotations)), true); } #[test] fn approval_required_when_read_only_false_and_open_world() { - let annotations = annotations(Some(false), None, Some(true)); + let annotations = annotations(Some(false), /*destructive*/ None, Some(true)); assert_eq!(requires_mcp_tool_approval(Some(&annotations)), true); } @@ -90,12 +90,16 @@ fn approval_required_when_destructive_even_if_read_only_true() { #[test] fn approval_required_when_annotations_are_absent() { - assert_eq!(requires_mcp_tool_approval(None), true); + assert_eq!(requires_mcp_tool_approval(/*annotations*/ None), true); } #[test] fn approval_not_required_when_read_only_and_other_hints_are_absent() { - let annotations = annotations(Some(true), None, None); + let annotations = annotations( + Some(true), + /*destructive*/ None, + /*open_world*/ None, + ); assert_eq!(requires_mcp_tool_approval(Some(&annotations)), false); } @@ -187,7 +191,9 @@ async fn approval_elicitation_request_uses_message_override_and_preserves_tool_p CODEX_APPS_MCP_SERVER_NAME, "create_event", Some("Calendar"), - prompt_options(true, true), + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true, + ), Some("Allow Calendar to create an event?"), ); @@ -221,7 +227,9 @@ async fn approval_elicitation_request_uses_message_override_and_preserves_tool_p ]), question, message_override: Some("Allow Calendar to create an event?"), - prompt_options: prompt_options(true, true), + prompt_options: prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true, + ), }, ); @@ -279,9 +287,11 @@ fn custom_mcp_tool_question_mentions_server_name() { "q".to_string(), "custom_server", "run_action", - None, - prompt_options(false, false), - None, + /*connector_name*/ None, + prompt_options( + /*allow_session_remember*/ false, /*allow_persistent_approval*/ false, + ), + /*question_override*/ None, ); assert_eq!(question.header, "Approve app tool call?"); @@ -305,9 +315,11 @@ fn codex_apps_tool_question_uses_fallback_app_label() { "q".to_string(), CODEX_APPS_MCP_SERVER_NAME, "run_action", - None, - prompt_options(true, true), - None, + /*connector_name*/ None, + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true, + ), + /*question_override*/ None, ); assert_eq!( @@ -323,8 +335,10 @@ fn trusted_codex_apps_tool_question_offers_always_allow() { CODEX_APPS_MCP_SERVER_NAME, "run_action", Some("Calendar"), - prompt_options(true, true), - None, + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true, + ), + /*question_override*/ None, ); let options = question.options.expect("options"); @@ -363,8 +377,12 @@ fn codex_apps_tool_question_without_elicitation_omits_always_allow() { CODEX_APPS_MCP_SERVER_NAME, "run_action", Some("Calendar"), - mcp_tool_approval_prompt_options(Some(&session_key), Some(&persistent_key), false), - None, + mcp_tool_approval_prompt_options( + Some(&session_key), + Some(&persistent_key), + /*tool_call_mcp_elicitation_enabled*/ false, + ), + /*question_override*/ None, ); assert_eq!( @@ -388,9 +406,11 @@ fn custom_mcp_tool_question_offers_session_remember_and_always_allow() { "q".to_string(), "custom_server", "run_action", - None, - prompt_options(true, true), - None, + /*connector_name*/ None, + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true, + ), + /*question_override*/ None, ); assert_eq!( @@ -423,11 +443,15 @@ fn custom_servers_support_session_and_persistent_approval() { }; assert_eq!( - session_mcp_tool_approval_key(&invocation, None, AppToolApproval::Auto), + session_mcp_tool_approval_key(&invocation, /*metadata*/ None, AppToolApproval::Auto), Some(expected.clone()) ); assert_eq!( - persistent_mcp_tool_approval_key(&invocation, None, AppToolApproval::Auto), + persistent_mcp_tool_approval_key( + &invocation, + /*metadata*/ None, + AppToolApproval::Auto + ), Some(expected) ); } @@ -439,7 +463,13 @@ fn codex_apps_connectors_support_persistent_approval() { tool: "calendar/list_events".to_string(), arguments: None, }; - let metadata = approval_metadata(Some("calendar"), Some("Calendar"), None, None, None); + let metadata = approval_metadata( + Some("calendar"), + Some("Calendar"), + /*connector_description*/ None, + /*tool_title*/ None, + /*tool_description*/ None, + ); let expected = McpToolApprovalKey { server: CODEX_APPS_MCP_SERVER_NAME.to_string(), connector_id: Some("calendar".to_string()), @@ -475,7 +505,8 @@ fn sanitize_mcp_tool_result_for_model_rewrites_image_content() { meta: None, }); - let got = sanitize_mcp_tool_result_for_model(false, result).expect("sanitized result"); + let got = sanitize_mcp_tool_result_for_model(/*supports_image_input*/ false, result) + .expect("sanitized result"); assert_eq!( got.content, @@ -505,8 +536,11 @@ fn sanitize_mcp_tool_result_for_model_preserves_image_when_supported() { meta: Some(serde_json::json!({"k": "v"})), }; - let got = - sanitize_mcp_tool_result_for_model(true, Ok(original.clone())).expect("unsanitized result"); + let got = sanitize_mcp_tool_result_for_model( + /*supports_image_input*/ true, + Ok(original.clone()), + ) + .expect("unsanitized result"); assert_eq!(got, original); } @@ -606,10 +640,12 @@ fn approval_elicitation_meta_marks_tool_approvals() { assert_eq!( build_mcp_tool_approval_elicitation_meta( "custom_server", - None, - None, - None, - prompt_options(false, false), + /*metadata*/ None, + /*tool_params*/ None, + /*tool_params_display*/ None, + prompt_options( + /*allow_session_remember*/ false, /*allow_persistent_approval*/ false + ), ), Some(serde_json::json!({ MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL, @@ -623,15 +659,17 @@ fn approval_elicitation_meta_merges_session_and_always_persist_for_custom_server build_mcp_tool_approval_elicitation_meta( "custom_server", Some(&approval_metadata( - None, - None, - None, + /*connector_id*/ None, + /*connector_name*/ None, + /*connector_description*/ None, Some("Run Action"), Some("Runs the selected action."), )), Some(&serde_json::json!({"id": 1})), - None, - prompt_options(true, true), + /*tool_params_display*/ None, + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true + ), ), Some(serde_json::json!({ MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL, @@ -742,11 +780,11 @@ fn prepare_arc_request_action_serializes_mcp_tool_call_shape() { let action = prepare_arc_request_action( &invocation, Some(&approval_metadata( - None, + /*connector_id*/ None, Some("Playwright"), - None, + /*connector_description*/ None, Some("Navigate"), - None, + /*tool_description*/ None, )), ); @@ -796,8 +834,10 @@ fn approval_elicitation_meta_includes_connector_source_for_codex_apps() { Some(&serde_json::json!({ "calendar_id": "primary", })), - None, - prompt_options(false, false), + /*tool_params_display*/ None, + prompt_options( + /*allow_session_remember*/ false, /*allow_persistent_approval*/ false + ), ), Some(serde_json::json!({ MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL, @@ -829,8 +869,10 @@ fn approval_elicitation_meta_merges_session_and_always_persist_with_connector_so Some(&serde_json::json!({ "calendar_id": "primary", })), - None, - prompt_options(true, true), + /*tool_params_display*/ None, + prompt_options( + /*allow_session_remember*/ true, /*allow_persistent_approval*/ true + ), ), Some(serde_json::json!({ MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL, @@ -1170,7 +1212,11 @@ async fn approve_mode_skips_when_annotations_do_not_require_approval() { arguments: None, }; let metadata = McpToolApprovalMetadata { - annotations: Some(annotations(Some(true), None, None)), + annotations: Some(annotations( + Some(true), + /*destructive*/ None, + /*open_world*/ None, + )), connector_id: None, connector_name: None, connector_description: None, @@ -1233,7 +1279,11 @@ async fn guardian_mode_skips_auto_when_annotations_do_not_require_approval() { arguments: None, }; let metadata = McpToolApprovalMetadata { - annotations: Some(annotations(Some(true), None, None)), + annotations: Some(annotations( + Some(true), + /*destructive*/ None, + /*open_world*/ None, + )), connector_id: None, connector_name: None, connector_description: None, @@ -1268,7 +1318,11 @@ async fn prompt_mode_waits_for_approval_when_annotations_do_not_require_approval arguments: None, }; let metadata = McpToolApprovalMetadata { - annotations: Some(annotations(Some(true), None, None)), + annotations: Some(annotations( + Some(true), + /*destructive*/ None, + /*open_world*/ None, + )), connector_id: None, connector_name: None, connector_description: None, diff --git a/codex-rs/core/src/memories/storage_tests.rs b/codex-rs/core/src/memories/storage_tests.rs index 5e0f2ce89..fe2821976 100644 --- a/codex-rs/core/src/memories/storage_tests.rs +++ b/codex-rs/core/src/memories/storage_tests.rs @@ -29,7 +29,7 @@ fn fixed_thread_id() -> ThreadId { #[test] fn rollout_summary_file_stem_uses_uuid_timestamp_and_hash_when_slug_missing() { let thread_id = fixed_thread_id(); - let memory = stage1_output_with_slug(thread_id, None); + let memory = stage1_output_with_slug(thread_id, /*rollout_slug*/ None); assert_eq!(rollout_summary_file_stem(&memory), FIXED_PREFIX); assert_eq!( diff --git a/codex-rs/core/src/memories/tests.rs b/codex-rs/core/src/memories/tests.rs index 03dbe7185..8eae9db86 100644 --- a/codex-rs/core/src/memories/tests.rs +++ b/codex-rs/core/src/memories/tests.rs @@ -526,8 +526,8 @@ mod phase2 { thread_id, self.session.conversation_id, source_updated_at, - 3_600, - 64, + /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, ) .await .expect("claim stage-1 job"); @@ -543,7 +543,7 @@ mod phase2 { source_updated_at, "raw memory", "rollout summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage-1 success"), @@ -571,24 +571,24 @@ mod phase2 { #[test] fn completion_watermark_never_regresses_below_claimed_input_watermark() { - let stage1_output = stage1_output_with_source_updated_at(123); + let stage1_output = stage1_output_with_source_updated_at(/*source_updated_at*/ 123); - let completion = phase2::get_watermark(1_000, &[stage1_output]); + let completion = phase2::get_watermark(/*claimed_watermark*/ 1_000, &[stage1_output]); pretty_assertions::assert_eq!(completion, 1_000); } #[test] fn completion_watermark_uses_claimed_watermark_when_there_are_no_memories() { - let completion = phase2::get_watermark(777, &[]); + let completion = phase2::get_watermark(/*claimed_watermark*/ 777, &[]); pretty_assertions::assert_eq!(completion, 777); } #[test] fn completion_watermark_uses_latest_memory_timestamp_when_it_is_newer() { - let older = stage1_output_with_source_updated_at(123); - let newer = stage1_output_with_source_updated_at(456); + let older = stage1_output_with_source_updated_at(/*source_updated_at*/ 123); + let newer = stage1_output_with_source_updated_at(/*source_updated_at*/ 456); - let completion = phase2::get_watermark(200, &[older, newer]); + let completion = phase2::get_watermark(/*claimed_watermark*/ 200, &[older, newer]); pretty_assertions::assert_eq!(completion, 456); } @@ -608,12 +608,12 @@ mod phase2 { let harness = DispatchHarness::new().await; harness .state_db - .enqueue_global_consolidation(123) + .enqueue_global_consolidation(/*input_watermark*/ 123) .await .expect("enqueue global consolidation"); let claimed = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim running global lock"); assert!( @@ -625,7 +625,7 @@ mod phase2 { let running_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim while lock is still running"); pretty_assertions::assert_eq!(running_claim, Phase2JobClaimOutcome::SkippedRunning); @@ -641,7 +641,7 @@ mod phase2 { let stale_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 0) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 0) .await .expect("claim stale global lock"); assert!( @@ -653,7 +653,7 @@ mod phase2 { let post_dispatch_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim after stale lock dispatch"); assert!( @@ -759,7 +759,7 @@ mod phase2 { harness .state_db - .enqueue_global_consolidation(999) + .enqueue_global_consolidation(/*input_watermark*/ 999) .await .expect("enqueue global consolidation"); @@ -801,7 +801,7 @@ mod phase2 { ); let next_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim global job after empty consolidation success"); pretty_assertions::assert_eq!(next_claim, Phase2JobClaimOutcome::SkippedNotDirty); @@ -817,7 +817,7 @@ mod phase2 { let harness = DispatchHarness::new().await; harness .state_db - .enqueue_global_consolidation(99) + .enqueue_global_consolidation(/*input_watermark*/ 99) .await .expect("enqueue global consolidation"); let mut constrained_config = harness.config.as_ref().clone(); @@ -828,7 +828,7 @@ mod phase2 { let retry_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim global job after sandbox policy failure"); pretty_assertions::assert_eq!(retry_claim, Phase2JobClaimOutcome::SkippedNotDirty); @@ -840,7 +840,7 @@ mod phase2 { #[tokio::test] async fn dispatch_marks_job_for_retry_when_syncing_artifacts_fails() { let harness = DispatchHarness::new().await; - harness.seed_stage1_output(100).await; + harness.seed_stage1_output(/*source_updated_at*/ 100).await; let root = memory_root(&harness.config.codex_home); tokio::fs::write(&root, "not a directory") .await @@ -850,7 +850,7 @@ mod phase2 { let retry_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim global job after sync failure"); pretty_assertions::assert_eq!(retry_claim, Phase2JobClaimOutcome::SkippedNotDirty); @@ -862,7 +862,7 @@ mod phase2 { #[tokio::test] async fn dispatch_marks_job_for_retry_when_rebuilding_raw_memories_fails() { let harness = DispatchHarness::new().await; - harness.seed_stage1_output(100).await; + harness.seed_stage1_output(/*source_updated_at*/ 100).await; let root = memory_root(&harness.config.codex_home); tokio::fs::create_dir_all(raw_memories_file(&root)) .await @@ -872,7 +872,7 @@ mod phase2 { let retry_claim = harness .state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim global job after rebuild failure"); pretty_assertions::assert_eq!(retry_claim, Phase2JobClaimOutcome::SkippedNotDirty); @@ -917,7 +917,13 @@ mod phase2 { .expect("upsert thread metadata"); let claim = state_db - .try_claim_stage1_job(thread_id, session.conversation_id, 100, 3_600, 64) + .try_claim_stage1_job( + thread_id, + session.conversation_id, + /*source_updated_at*/ 100, + /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage-1 job"); let ownership_token = match claim { @@ -929,10 +935,10 @@ mod phase2 { .mark_stage1_job_succeeded( thread_id, &ownership_token, - 100, + /*source_updated_at*/ 100, "raw memory", "rollout summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage-1 success"), @@ -942,7 +948,7 @@ mod phase2 { phase2::run(&session, Arc::clone(&config)).await; let retry_claim = state_db - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim global job after spawn failure"); pretty_assertions::assert_eq!( diff --git a/codex-rs/core/src/message_history_tests.rs b/codex-rs/core/src/message_history_tests.rs index 59b9c8c7b..de89a3eb9 100644 --- a/codex-rs/core/src/message_history_tests.rs +++ b/codex-rs/core/src/message_history_tests.rs @@ -37,8 +37,8 @@ async fn lookup_reads_history_entries() { let (log_id, count) = history_metadata_for_file(&history_path).await; assert_eq!(count, entries.len()); - let second_entry = - lookup_history_entry(&history_path, log_id, 1).expect("fetch second history entry"); + let second_entry = lookup_history_entry(&history_path, log_id, /*offset*/ 1) + .expect("fetch second history entry"); assert_eq!(second_entry, entries[1]); } @@ -80,8 +80,8 @@ async fn lookup_uses_stable_log_id_after_appends() { ) .expect("append history entry"); - let fetched = - lookup_history_entry(&history_path, log_id, 1).expect("lookup appended history entry"); + let fetched = lookup_history_entry(&history_path, log_id, /*offset*/ 1) + .expect("lookup appended history entry"); assert_eq!(fetched, appended); } diff --git a/codex-rs/core/src/models_manager/collaboration_mode_presets_tests.rs b/codex-rs/core/src/models_manager/collaboration_mode_presets_tests.rs index 9b43e3bbd..361c51762 100644 --- a/codex-rs/core/src/models_manager/collaboration_mode_presets_tests.rs +++ b/codex-rs/core/src/models_manager/collaboration_mode_presets_tests.rs @@ -31,8 +31,10 @@ fn default_mode_instructions_replace_mode_names_placeholder() { let expected_snippet = format!("Known mode names are {known_mode_names}."); assert!(default_instructions.contains(&expected_snippet)); - let expected_availability_message = - request_user_input_availability_message(ModeKind::Default, true); + let expected_availability_message = request_user_input_availability_message( + ModeKind::Default, + /*default_mode_request_user_input*/ true, + ); assert!(default_instructions.contains(&expected_availability_message)); assert!(default_instructions.contains("prefer using the `request_user_input` tool")); } diff --git a/codex-rs/core/src/models_manager/manager_tests.rs b/codex-rs/core/src/models_manager/manager_tests.rs index 07cf4dc39..7b4b2be53 100644 --- a/codex-rs/core/src/models_manager/manager_tests.rs +++ b/codex-rs/core/src/models_manager/manager_tests.rs @@ -145,7 +145,7 @@ async fn get_model_info_tracks_fallback_usage() { let manager = ModelsManager::new( codex_home.path().to_path_buf(), auth_manager, - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), ); let known_slug = manager @@ -175,7 +175,7 @@ async fn get_model_info_uses_custom_catalog() { .build() .await .expect("load default test config"); - let mut overlay = remote_model("gpt-overlay", "Overlay", 0); + let mut overlay = remote_model("gpt-overlay", "Overlay", /*priority*/ 0); overlay.supports_image_detail_original = true; let auth_manager = AuthManager::from_auth_for_testing(CodexAuth::from_api_key("Test API Key")); @@ -208,7 +208,7 @@ async fn get_model_info_matches_namespaced_suffix() { .build() .await .expect("load default test config"); - let mut remote = remote_model("gpt-image", "Image", 0); + let mut remote = remote_model("gpt-image", "Image", /*priority*/ 0); remote.supports_image_detail_original = true; let auth_manager = AuthManager::from_auth_for_testing(CodexAuth::from_api_key("Test API Key")); let manager = ModelsManager::new( @@ -240,7 +240,7 @@ async fn get_model_info_rejects_multi_segment_namespace_suffix_matching() { let manager = ModelsManager::new( codex_home.path().to_path_buf(), auth_manager, - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), ); let known_slug = manager @@ -262,8 +262,8 @@ async fn get_model_info_rejects_multi_segment_namespace_suffix_matching() { async fn refresh_available_models_sorts_by_priority() { let server = MockServer::start().await; let remote_models = vec![ - remote_model("priority-low", "Low", 1), - remote_model("priority-high", "High", 0), + remote_model("priority-low", "Low", /*priority*/ 1), + remote_model("priority-high", "High", /*priority*/ 0), ]; let models_mock = mount_models_once( &server, @@ -313,7 +313,7 @@ async fn refresh_available_models_sorts_by_priority() { #[tokio::test] async fn refresh_available_models_uses_cache_when_fresh() { let server = MockServer::start().await; - let remote_models = vec![remote_model("cached", "Cached", 5)]; + let remote_models = vec![remote_model("cached", "Cached", /*priority*/ 5)]; let models_mock = mount_models_once( &server, ModelsResponse { @@ -354,7 +354,7 @@ async fn refresh_available_models_uses_cache_when_fresh() { #[tokio::test] async fn refresh_available_models_refetches_when_cache_stale() { let server = MockServer::start().await; - let initial_models = vec![remote_model("stale", "Stale", 1)]; + let initial_models = vec![remote_model("stale", "Stale", /*priority*/ 1)]; let initial_mock = mount_models_once( &server, ModelsResponse { @@ -387,7 +387,7 @@ async fn refresh_available_models_refetches_when_cache_stale() { .await .expect("cache manipulation succeeds"); - let updated_models = vec![remote_model("fresh", "Fresh", 9)]; + let updated_models = vec![remote_model("fresh", "Fresh", /*priority*/ 9)]; server.reset().await; let refreshed_mock = mount_models_once( &server, @@ -417,7 +417,7 @@ async fn refresh_available_models_refetches_when_cache_stale() { #[tokio::test] async fn refresh_available_models_refetches_when_version_mismatch() { let server = MockServer::start().await; - let initial_models = vec![remote_model("old", "Old", 1)]; + let initial_models = vec![remote_model("old", "Old", /*priority*/ 1)]; let initial_mock = mount_models_once( &server, ModelsResponse { @@ -450,7 +450,7 @@ async fn refresh_available_models_refetches_when_version_mismatch() { .await .expect("cache mutation succeeds"); - let updated_models = vec![remote_model("new", "New", 2)]; + let updated_models = vec![remote_model("new", "New", /*priority*/ 2)]; server.reset().await; let refreshed_mock = mount_models_once( &server, @@ -480,7 +480,11 @@ async fn refresh_available_models_refetches_when_version_mismatch() { #[tokio::test] async fn refresh_available_models_drops_removed_remote_models() { let server = MockServer::start().await; - let initial_models = vec![remote_model("remote-old", "Remote Old", 1)]; + let initial_models = vec![remote_model( + "remote-old", + "Remote Old", + /*priority*/ 1, + )]; let initial_mock = mount_models_once( &server, ModelsResponse { @@ -506,7 +510,11 @@ async fn refresh_available_models_drops_removed_remote_models() { .expect("initial refresh succeeds"); server.reset().await; - let refreshed_models = vec![remote_model("remote-new", "Remote New", 1)]; + let refreshed_models = vec![remote_model( + "remote-new", + "Remote New", + /*priority*/ 1, + )]; let refreshed_mock = mount_models_once( &server, ModelsResponse { @@ -550,7 +558,7 @@ async fn refresh_available_models_skips_network_without_chatgpt_auth() { let models_mock = mount_models_once( &server, ModelsResponse { - models: vec![remote_model(dynamic_slug, "No Auth", 1)], + models: vec![remote_model(dynamic_slug, "No Auth", /*priority*/ 1)], }, ) .await; @@ -558,7 +566,7 @@ async fn refresh_available_models_skips_network_without_chatgpt_auth() { let codex_home = tempdir().expect("temp dir"); let auth_manager = Arc::new(AuthManager::new( codex_home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, )); let provider = provider_for(server.uri()); @@ -621,7 +629,7 @@ fn models_request_telemetry_emits_auth_env_feedback_tags_on_failure() { .unwrap(), ); telemetry.on_request( - 1, + /*attempt*/ 1, Some(StatusCode::UNAUTHORIZED), Some(&TransportError::Http { status: StatusCode::UNAUTHORIZED, @@ -695,8 +703,10 @@ fn build_available_models_picks_default_after_hiding_hidden_models() { provider, ); - let hidden_model = remote_model_with_visibility("hidden", "Hidden", 0, "hide"); - let visible_model = remote_model_with_visibility("visible", "Visible", 1, "list"); + let hidden_model = + remote_model_with_visibility("hidden", "Hidden", /*priority*/ 0, "hide"); + let visible_model = + remote_model_with_visibility("visible", "Visible", /*priority*/ 1, "list"); let expected_hidden = ModelPreset::from(hidden_model.clone()); let mut expected_visible = ModelPreset::from(visible_model.clone()); diff --git a/codex-rs/core/src/network_proxy_loader_tests.rs b/codex-rs/core/src/network_proxy_loader_tests.rs index 395b761dd..b5adb935e 100644 --- a/codex-rs/core/src/network_proxy_loader_tests.rs +++ b/codex-rs/core/src/network_proxy_loader_tests.rs @@ -120,7 +120,7 @@ fn execpolicy_network_rules_overlay_network_lists() { "blocked.example.com", NetworkRuleProtocol::Https, Decision::Allow, - None, + /*justification*/ None, ) .expect("allow rule should be valid"); exec_policy @@ -128,7 +128,7 @@ fn execpolicy_network_rules_overlay_network_lists() { "api.example.com", NetworkRuleProtocol::Http, Decision::Forbidden, - None, + /*justification*/ None, ) .expect("deny rule should be valid"); diff --git a/codex-rs/core/src/original_image_detail_tests.rs b/codex-rs/core/src/original_image_detail_tests.rs index e4a3c0988..05094e0a6 100644 --- a/codex-rs/core/src/original_image_detail_tests.rs +++ b/codex-rs/core/src/original_image_detail_tests.rs @@ -20,7 +20,7 @@ fn image_detail_original_feature_enables_explicit_original_without_force() { Some(ImageDetail::Original) ); assert_eq!( - normalize_output_image_detail(&features, &model_info, None), + normalize_output_image_detail(&features, &model_info, /*detail*/ None), None ); } diff --git a/codex-rs/core/src/plugins/manager_tests.rs b/codex-rs/core/src/plugins/manager_tests.rs index b845e085f..ab0ad7084 100644 --- a/codex-rs/core/src/plugins/manager_tests.rs +++ b/codex-rs/core/src/plugins/manager_tests.rs @@ -131,7 +131,10 @@ fn load_plugins_loads_default_skills_and_mcp_servers() { }"#, ); - let outcome = load_plugins_from_config(&plugin_config_toml(true, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), + codex_home.path(), + ); assert_eq!( outcome.plugins(), @@ -340,7 +343,10 @@ fn capability_summary_sanitizes_plugin_descriptions_to_one_line() { "---\nname: sample-search\ndescription: search sample data\n---\n", ); - let outcome = load_plugins_from_config(&plugin_config_toml(true, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), + codex_home.path(), + ); assert_eq!( outcome.plugins()[0].manifest_description.as_deref(), @@ -375,7 +381,10 @@ fn capability_summary_truncates_overlong_plugin_descriptions() { "---\nname: sample-search\ndescription: search sample data\n---\n", ); - let outcome = load_plugins_from_config(&plugin_config_toml(true, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), + codex_home.path(), + ); assert_eq!( outcome.plugins()[0].manifest_description.as_deref(), @@ -455,7 +464,10 @@ fn load_plugins_uses_manifest_configured_component_paths() { }"#, ); - let outcome = load_plugins_from_config(&plugin_config_toml(true, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), + codex_home.path(), + ); assert_eq!( outcome.plugins()[0].skill_roots, @@ -562,7 +574,10 @@ fn load_plugins_ignores_manifest_component_paths_without_dot_slash() { }"#, ); - let outcome = load_plugins_from_config(&plugin_config_toml(true, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), + codex_home.path(), + ); assert_eq!( outcome.plugins()[0].skill_roots, @@ -622,7 +637,12 @@ fn load_plugins_preserves_disabled_plugins_without_effective_contributions() { }"#, ); - let outcome = load_plugins_from_config(&plugin_config_toml(false, true), codex_home.path()); + let outcome = load_plugins_from_config( + &plugin_config_toml( + /*enabled*/ false, /*plugins_feature_enabled*/ true, + ), + codex_home.path(), + ); assert_eq!( outcome.plugins(), @@ -831,7 +851,9 @@ fn load_plugins_returns_empty_when_feature_disabled() { ); write_file( &codex_home.path().join(CONFIG_TOML_FILE), - &plugin_config_toml(true, false), + &plugin_config_toml( + /*enabled*/ true, /*plugins_feature_enabled*/ false, + ), ); let config = load_config_blocking(codex_home.path(), codex_home.path()); @@ -1326,7 +1348,7 @@ plugins = false let config = load_config(tmp.path(), tmp.path()).await; let outcome = PluginsManager::new(tmp.path().to_path_buf()) - .sync_plugins_from_remote(&config, None, /*additive_only*/ false) + .sync_plugins_from_remote(&config, /*auth*/ None, /*additive_only*/ false) .await .unwrap(); @@ -2110,10 +2132,13 @@ plugins = true let mut config = load_config(tmp.path(), tmp.path()).await; config.chatgpt_base_url = format!("{}/backend-api/", server.uri()); - let manager = PluginsManager::new_with_restriction_product(tmp.path().to_path_buf(), None); + let manager = PluginsManager::new_with_restriction_product( + tmp.path().to_path_buf(), + /*restriction_product*/ None, + ); let featured_plugin_ids = manager - .featured_plugin_ids_for_config(&config, None) + .featured_plugin_ids_for_config(&config, /*auth*/ None) .await .unwrap(); @@ -2219,7 +2244,7 @@ fn load_plugins_ignores_project_config_files() { ); write_file( &project_root.join(".codex/config.toml"), - &plugin_config_toml(true, true), + &plugin_config_toml(/*enabled*/ true, /*plugins_feature_enabled*/ true), ); let stack = ConfigLayerStack::new( @@ -2227,7 +2252,10 @@ fn load_plugins_ignores_project_config_files() { ConfigLayerSource::Project { dot_codex_folder: AbsolutePathBuf::try_from(project_root.join(".codex")).unwrap(), }, - toml::from_str(&plugin_config_toml(true, true)).expect("project config should parse"), + toml::from_str(&plugin_config_toml( + /*enabled*/ true, /*plugins_feature_enabled*/ true, + )) + .expect("project config should parse"), )], ConfigRequirements::default(), ConfigRequirementsToml::default(), diff --git a/codex-rs/core/src/plugins/marketplace_tests.rs b/codex-rs/core/src/plugins/marketplace_tests.rs index 0c5e72e64..d3cf55425 100644 --- a/codex-rs/core/src/plugins/marketplace_tests.rs +++ b/codex-rs/core/src/plugins/marketplace_tests.rs @@ -342,7 +342,7 @@ fn list_marketplaces_dedupes_multiple_roots_in_same_repo() { AbsolutePathBuf::try_from(repo_root.clone()).unwrap(), AbsolutePathBuf::try_from(nested_root).unwrap(), ], - None, + /*home_dir*/ None, ) .unwrap() .marketplaces; @@ -397,10 +397,12 @@ fn list_marketplaces_reads_marketplace_display_name() { ) .unwrap(); - let marketplaces = - list_marketplaces_with_home(&[AbsolutePathBuf::try_from(repo_root).unwrap()], None) - .unwrap() - .marketplaces; + let marketplaces = list_marketplaces_with_home( + &[AbsolutePathBuf::try_from(repo_root).unwrap()], + /*home_dir*/ None, + ) + .unwrap() + .marketplaces; assert_eq!( marketplaces[0].interface, @@ -458,7 +460,7 @@ fn list_marketplaces_skips_marketplaces_that_fail_to_load() { AbsolutePathBuf::try_from(valid_repo_root).unwrap(), AbsolutePathBuf::try_from(invalid_repo_root).unwrap(), ], - None, + /*home_dir*/ None, ) .unwrap() .marketplaces; @@ -503,7 +505,7 @@ fn list_marketplaces_reports_marketplace_load_errors() { AbsolutePathBuf::try_from(valid_repo_root).unwrap(), AbsolutePathBuf::try_from(invalid_repo_root).unwrap(), ], - None, + /*home_dir*/ None, ) .unwrap(); @@ -566,10 +568,12 @@ fn list_marketplaces_resolves_plugin_interface_paths_to_absolute() { ) .unwrap(); - let marketplaces = - list_marketplaces_with_home(&[AbsolutePathBuf::try_from(repo_root).unwrap()], None) - .unwrap() - .marketplaces; + let marketplaces = list_marketplaces_with_home( + &[AbsolutePathBuf::try_from(repo_root).unwrap()], + /*home_dir*/ None, + ) + .unwrap() + .marketplaces; assert_eq!( marketplaces[0].plugins[0].policy.installation, @@ -634,10 +638,12 @@ fn list_marketplaces_ignores_legacy_top_level_policy_fields() { ) .unwrap(); - let marketplaces = - list_marketplaces_with_home(&[AbsolutePathBuf::try_from(repo_root).unwrap()], None) - .unwrap() - .marketplaces; + let marketplaces = list_marketplaces_with_home( + &[AbsolutePathBuf::try_from(repo_root).unwrap()], + /*home_dir*/ None, + ) + .unwrap() + .marketplaces; assert_eq!( marketplaces[0].plugins[0].policy.installation, @@ -690,10 +696,12 @@ fn list_marketplaces_ignores_plugin_interface_assets_without_dot_slash() { ) .unwrap(); - let marketplaces = - list_marketplaces_with_home(&[AbsolutePathBuf::try_from(repo_root).unwrap()], None) - .unwrap() - .marketplaces; + let marketplaces = list_marketplaces_with_home( + &[AbsolutePathBuf::try_from(repo_root).unwrap()], + /*home_dir*/ None, + ) + .unwrap() + .marketplaces; assert_eq!( marketplaces[0].plugins[0].interface, diff --git a/codex-rs/core/src/project_doc_tests.rs b/codex-rs/core/src/project_doc_tests.rs index 866831d8b..9f4d9c528 100644 --- a/codex-rs/core/src/project_doc_tests.rs +++ b/codex-rs/core/src/project_doc_tests.rs @@ -75,7 +75,9 @@ async fn make_config_with_project_root_markers( async fn no_doc_file_returns_none() { let tmp = tempfile::tempdir().expect("tempdir"); - let res = get_user_instructions(&make_config(&tmp, 4096, None).await).await; + let res = + get_user_instructions(&make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await) + .await; assert!( res.is_none(), "Expected None when AGENTS.md is absent and no system instructions provided" @@ -89,9 +91,10 @@ async fn doc_smaller_than_limit_is_returned() { let tmp = tempfile::tempdir().expect("tempdir"); fs::write(tmp.path().join("AGENTS.md"), "hello world").unwrap(); - let res = get_user_instructions(&make_config(&tmp, 4096, None).await) - .await - .expect("doc expected"); + let res = + get_user_instructions(&make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await) + .await + .expect("doc expected"); assert_eq!( res, "hello world", @@ -108,7 +111,7 @@ async fn doc_larger_than_limit_is_truncated() { let huge = "A".repeat(LIMIT * 2); // 2 KiB fs::write(tmp.path().join("AGENTS.md"), &huge).unwrap(); - let res = get_user_instructions(&make_config(&tmp, LIMIT, None).await) + let res = get_user_instructions(&make_config(&tmp, LIMIT, /*instructions*/ None).await) .await .expect("doc expected"); @@ -137,7 +140,7 @@ async fn finds_doc_in_repo_root() { std::fs::create_dir_all(&nested).unwrap(); // Build config pointing at the nested dir. - let mut cfg = make_config(&repo, 4096, None).await; + let mut cfg = make_config(&repo, /*limit*/ 4096, /*instructions*/ None).await; cfg.cwd = nested.abs(); let res = get_user_instructions(&cfg).await.expect("doc expected"); @@ -150,7 +153,8 @@ async fn zero_byte_limit_disables_docs() { let tmp = tempfile::tempdir().expect("tempdir"); fs::write(tmp.path().join("AGENTS.md"), "something").unwrap(); - let res = get_user_instructions(&make_config(&tmp, 0, None).await).await; + let res = + get_user_instructions(&make_config(&tmp, /*limit*/ 0, /*instructions*/ None).await).await; assert!( res.is_none(), "With limit 0 the function should return None" @@ -160,7 +164,7 @@ async fn zero_byte_limit_disables_docs() { #[tokio::test] async fn js_repl_instructions_are_appended_when_enabled() { let tmp = tempfile::tempdir().expect("tempdir"); - let mut cfg = make_config(&tmp, 4096, None).await; + let mut cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; cfg.features .enable(Feature::JsRepl) .expect("test config should allow js_repl"); @@ -175,7 +179,7 @@ async fn js_repl_instructions_are_appended_when_enabled() { #[tokio::test] async fn js_repl_tools_only_instructions_are_feature_gated() { let tmp = tempfile::tempdir().expect("tempdir"); - let mut cfg = make_config(&tmp, 4096, None).await; + let mut cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; let mut features = cfg.features.get().clone(); features .enable(Feature::JsRepl) @@ -194,7 +198,7 @@ async fn js_repl_tools_only_instructions_are_feature_gated() { #[tokio::test] async fn js_repl_image_detail_original_does_not_change_instructions() { let tmp = tempfile::tempdir().expect("tempdir"); - let mut cfg = make_config(&tmp, 4096, None).await; + let mut cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; let mut features = cfg.features.get().clone(); features .enable(Feature::JsRepl) @@ -219,7 +223,7 @@ async fn merges_existing_instructions_with_project_doc() { const INSTRUCTIONS: &str = "base instructions"; - let res = get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)).await) + let res = get_user_instructions(&make_config(&tmp, /*limit*/ 4096, Some(INSTRUCTIONS)).await) .await .expect("should produce a combined instruction string"); @@ -236,7 +240,8 @@ async fn keeps_existing_instructions_when_doc_missing() { const INSTRUCTIONS: &str = "some instructions"; - let res = get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)).await).await; + let res = + get_user_instructions(&make_config(&tmp, /*limit*/ 4096, Some(INSTRUCTIONS)).await).await; assert_eq!(res, Some(INSTRUCTIONS.to_string())); } @@ -262,7 +267,7 @@ async fn concatenates_root_and_cwd_docs() { std::fs::create_dir_all(&nested).unwrap(); fs::write(nested.join("AGENTS.md"), "crate doc").unwrap(); - let mut cfg = make_config(&repo, 4096, None).await; + let mut cfg = make_config(&repo, /*limit*/ 4096, /*instructions*/ None).await; cfg.cwd = nested.abs(); let res = get_user_instructions(&cfg).await.expect("doc expected"); @@ -279,7 +284,13 @@ async fn project_root_markers_are_honored_for_agents_discovery() { fs::create_dir_all(nested.join(".git")).unwrap(); fs::write(nested.join("AGENTS.md"), "child doc").unwrap(); - let mut cfg = make_config_with_project_root_markers(&root, 4096, None, &[".codex-root"]).await; + let mut cfg = make_config_with_project_root_markers( + &root, + /*limit*/ 4096, + /*instructions*/ None, + &[".codex-root"], + ) + .await; cfg.cwd = nested.abs(); let discovery = discover_project_doc_paths(&cfg).expect("discover paths"); @@ -302,7 +313,7 @@ async fn agents_local_md_preferred() { fs::write(tmp.path().join(DEFAULT_PROJECT_DOC_FILENAME), "versioned").unwrap(); fs::write(tmp.path().join(LOCAL_PROJECT_DOC_FILENAME), "local").unwrap(); - let cfg = make_config(&tmp, 4096, None).await; + let cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; let res = get_user_instructions(&cfg) .await @@ -324,7 +335,13 @@ async fn uses_configured_fallback_when_agents_missing() { let tmp = tempfile::tempdir().expect("tempdir"); fs::write(tmp.path().join("EXAMPLE.md"), "example instructions").unwrap(); - let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md"]).await; + let cfg = make_config_with_fallback( + &tmp, + /*limit*/ 4096, + /*instructions*/ None, + &["EXAMPLE.md"], + ) + .await; let res = get_user_instructions(&cfg) .await @@ -340,7 +357,13 @@ async fn agents_md_preferred_over_fallbacks() { fs::write(tmp.path().join("AGENTS.md"), "primary").unwrap(); fs::write(tmp.path().join("EXAMPLE.md"), "secondary").unwrap(); - let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md", ".example.md"]).await; + let cfg = make_config_with_fallback( + &tmp, + /*limit*/ 4096, + /*instructions*/ None, + &["EXAMPLE.md", ".example.md"], + ) + .await; let res = get_user_instructions(&cfg) .await @@ -364,7 +387,7 @@ async fn skills_are_not_appended_to_project_doc() { let tmp = tempfile::tempdir().expect("tempdir"); fs::write(tmp.path().join("AGENTS.md"), "base doc").unwrap(); - let cfg = make_config(&tmp, 4096, None).await; + let cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; create_skill( cfg.codex_home.clone(), "pdf-processing", @@ -380,7 +403,7 @@ async fn skills_are_not_appended_to_project_doc() { #[tokio::test] async fn apps_feature_does_not_emit_user_instructions_by_itself() { let tmp = tempfile::tempdir().expect("tempdir"); - let mut cfg = make_config(&tmp, 4096, None).await; + let mut cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; cfg.features .enable(Feature::Apps) .expect("test config should allow apps"); @@ -394,7 +417,7 @@ async fn apps_feature_does_not_append_to_project_doc_user_instructions() { let tmp = tempfile::tempdir().expect("tempdir"); fs::write(tmp.path().join("AGENTS.md"), "base doc").unwrap(); - let mut cfg = make_config(&tmp, 4096, None).await; + let mut cfg = make_config(&tmp, /*limit*/ 4096, /*instructions*/ None).await; cfg.features .enable(Feature::Apps) .expect("test config should allow apps"); diff --git a/codex-rs/core/src/realtime_context_tests.rs b/codex-rs/core/src/realtime_context_tests.rs index a19abf3ed..709bf3176 100644 --- a/codex-rs/core/src/realtime_context_tests.rs +++ b/codex-rs/core/src/realtime_context_tests.rs @@ -47,7 +47,7 @@ fn thread_metadata(cwd: &str, title: &str, first_user_message: &str) -> ThreadMe fn workspace_section_requires_meaningful_structure() { let cwd = TempDir::new().expect("tempdir"); assert_eq!( - build_workspace_section_with_user_root(cwd.path(), None), + build_workspace_section_with_user_root(cwd.path(), /*user_root*/ None), None ); } @@ -58,8 +58,8 @@ fn workspace_section_includes_tree_when_entries_exist() { fs::create_dir(cwd.path().join("docs")).expect("create docs dir"); fs::write(cwd.path().join("README.md"), "hello").expect("write readme"); - let section = - build_workspace_section_with_user_root(cwd.path(), None).expect("workspace section"); + let section = build_workspace_section_with_user_root(cwd.path(), /*user_root*/ None) + .expect("workspace section"); assert!(section.contains("Working directory tree:")); assert!(section.contains("- docs/")); assert!(section.contains("- README.md")); diff --git a/codex-rs/core/src/sandbox_tags_tests.rs b/codex-rs/core/src/sandbox_tags_tests.rs index 40062e031..cc75d4750 100644 --- a/codex-rs/core/src/sandbox_tags_tests.rs +++ b/codex-rs/core/src/sandbox_tags_tests.rs @@ -32,7 +32,7 @@ fn default_linux_sandbox_uses_platform_sandbox_tag() { &SandboxPolicy::new_read_only_policy(), WindowsSandboxLevel::Disabled, ); - let expected = get_platform_sandbox(false) + let expected = get_platform_sandbox(/*windows_sandbox_enabled*/ false) .map(SandboxType::as_metric_tag) .unwrap_or("none"); assert_eq!(actual, expected); diff --git a/codex-rs/core/src/shell_snapshot_tests.rs b/codex-rs/core/src/shell_snapshot_tests.rs index 2819f67d3..90288300f 100644 --- a/codex-rs/core/src/shell_snapshot_tests.rs +++ b/codex-rs/core/src/shell_snapshot_tests.rs @@ -269,9 +269,15 @@ async fn snapshot_shell_does_not_inherit_stdin() -> Result<()> { "HOME=\"{home_display}\"; export HOME; {}", bash_snapshot_script() ); - let output = run_script_with_timeout(&shell, &script, Duration::from_secs(2), true, home) - .await - .context("run snapshot command")?; + let output = run_script_with_timeout( + &shell, + &script, + Duration::from_secs(2), + /*use_login_shell*/ true, + home, + ) + .await + .context("run snapshot command")?; let read_status = fs::read_to_string(&read_status_path) .await .context("read stdin probe status")?; diff --git a/codex-rs/core/src/shell_tests.rs b/codex-rs/core/src/shell_tests.rs index 88025e8b8..f0974900b 100644 --- a/codex-rs/core/src/shell_tests.rs +++ b/codex-rs/core/src/shell_tests.rs @@ -5,7 +5,7 @@ use std::process::Command; #[test] #[cfg(target_os = "macos")] fn detects_zsh() { - let zsh_shell = get_shell(ShellType::Zsh, None).unwrap(); + let zsh_shell = get_shell(ShellType::Zsh, /*path*/ None).unwrap(); let shell_path = zsh_shell.shell_path; @@ -24,7 +24,7 @@ fn fish_fallback_to_zsh() { #[test] fn detects_bash() { - let bash_shell = get_shell(ShellType::Bash, None).unwrap(); + let bash_shell = get_shell(ShellType::Bash, /*path*/ None).unwrap(); let shell_path = bash_shell.shell_path; assert!( @@ -35,7 +35,7 @@ fn detects_bash() { #[test] fn detects_sh() { - let sh_shell = get_shell(ShellType::Sh, None).unwrap(); + let sh_shell = get_shell(ShellType::Sh, /*path*/ None).unwrap(); let shell_path = sh_shell.shell_path; assert!( shell_path.file_name().and_then(|name| name.to_str()) == Some("sh"), @@ -48,23 +48,47 @@ fn can_run_on_shell_test() { let cmd = "echo \"Works\""; if cfg!(windows) { assert!(shell_works( - get_shell(ShellType::PowerShell, None), + get_shell(ShellType::PowerShell, /*path*/ None), "Out-String 'Works'", - true, + /*required*/ true, + )); + assert!(shell_works( + get_shell(ShellType::Cmd, /*path*/ None), + cmd, + /*required*/ true, + )); + assert!(shell_works( + Some(ultimate_fallback_shell()), + cmd, + /*required*/ true )); - assert!(shell_works(get_shell(ShellType::Cmd, None), cmd, true,)); - assert!(shell_works(Some(ultimate_fallback_shell()), cmd, true)); } else { - assert!(shell_works(Some(ultimate_fallback_shell()), cmd, true)); - assert!(shell_works(get_shell(ShellType::Zsh, None), cmd, false)); - assert!(shell_works(get_shell(ShellType::Bash, None), cmd, true)); - assert!(shell_works(get_shell(ShellType::Sh, None), cmd, true)); + assert!(shell_works( + Some(ultimate_fallback_shell()), + cmd, + /*required*/ true + )); + assert!(shell_works( + get_shell(ShellType::Zsh, /*path*/ None), + cmd, + /*required*/ false + )); + assert!(shell_works( + get_shell(ShellType::Bash, /*path*/ None), + cmd, + /*required*/ true + )); + assert!(shell_works( + get_shell(ShellType::Sh, /*path*/ None), + cmd, + /*required*/ true + )); } } fn shell_works(shell: Option, command: &str, required: bool) -> bool { if let Some(shell) = shell { - let args = shell.derive_exec_args(command, false); + let args = shell.derive_exec_args(command, /*use_login_shell*/ false); let output = Command::new(args[0].clone()) .args(&args[1..]) .output() @@ -85,11 +109,11 @@ fn derive_exec_args() { shell_snapshot: empty_shell_snapshot_receiver(), }; assert_eq!( - test_bash_shell.derive_exec_args("echo hello", false), + test_bash_shell.derive_exec_args("echo hello", /*use_login_shell*/ false), vec!["/bin/bash", "-c", "echo hello"] ); assert_eq!( - test_bash_shell.derive_exec_args("echo hello", true), + test_bash_shell.derive_exec_args("echo hello", /*use_login_shell*/ true), vec!["/bin/bash", "-lc", "echo hello"] ); @@ -99,11 +123,11 @@ fn derive_exec_args() { shell_snapshot: empty_shell_snapshot_receiver(), }; assert_eq!( - test_zsh_shell.derive_exec_args("echo hello", false), + test_zsh_shell.derive_exec_args("echo hello", /*use_login_shell*/ false), vec!["/bin/zsh", "-c", "echo hello"] ); assert_eq!( - test_zsh_shell.derive_exec_args("echo hello", true), + test_zsh_shell.derive_exec_args("echo hello", /*use_login_shell*/ true), vec!["/bin/zsh", "-lc", "echo hello"] ); @@ -113,11 +137,11 @@ fn derive_exec_args() { shell_snapshot: empty_shell_snapshot_receiver(), }; assert_eq!( - test_powershell_shell.derive_exec_args("echo hello", false), + test_powershell_shell.derive_exec_args("echo hello", /*use_login_shell*/ false), vec!["pwsh.exe", "-NoProfile", "-Command", "echo hello"] ); assert_eq!( - test_powershell_shell.derive_exec_args("echo hello", true), + test_powershell_shell.derive_exec_args("echo hello", /*use_login_shell*/ true), vec!["pwsh.exe", "-Command", "echo hello"] ); } @@ -161,7 +185,7 @@ fn finds_powershell() { return; } - let powershell_shell = get_shell(ShellType::PowerShell, None).unwrap(); + let powershell_shell = get_shell(ShellType::PowerShell, /*path*/ None).unwrap(); let shell_path = powershell_shell.shell_path; assert!(shell_path.ends_with("pwsh.exe") || shell_path.ends_with("powershell.exe")); diff --git a/codex-rs/core/src/skills_watcher.rs b/codex-rs/core/src/skills_watcher.rs index 947137353..b5a1256cd 100644 --- a/codex-rs/core/src/skills_watcher.rs +++ b/codex-rs/core/src/skills_watcher.rs @@ -102,7 +102,7 @@ mod tests { let mut rx = skills_watcher.subscribe(); let _registration = skills_watcher .subscriber - .register_path(PathBuf::from("/tmp/skill"), true); + .register_path(PathBuf::from("/tmp/skill"), /*recursive*/ true); file_watcher .send_paths_for_test(vec![PathBuf::from("/tmp/skill/SKILL.md")]) diff --git a/codex-rs/core/src/stream_events_utils_tests.rs b/codex-rs/core/src/stream_events_utils_tests.rs index 3757577b5..23f52a068 100644 --- a/codex-rs/core/src/stream_events_utils_tests.rs +++ b/codex-rs/core/src/stream_events_utils_tests.rs @@ -28,9 +28,10 @@ async fn handle_non_tool_response_item_strips_citations_from_assistant_message() "hello\nMEMORY.md:1-2|note=[x]\n\n\n019cc2ea-1dff-7902-8d40-c8f6e5d83cc4\n world", ); - let turn_item = handle_non_tool_response_item(&session, &turn_context, &item, false) - .await - .expect("assistant message should parse"); + let turn_item = + handle_non_tool_response_item(&session, &turn_context, &item, /*plan_mode*/ false) + .await + .expect("assistant message should parse"); let TurnItem::AgentMessage(agent_message) = turn_item else { panic!("expected agent message"); @@ -60,7 +61,7 @@ fn last_assistant_message_from_item_strips_citations_and_plan_blocks() { "beforedoc1\n\n- x\n\nafter", ); - let message = last_assistant_message_from_item(&item, true) + let message = last_assistant_message_from_item(&item, /*plan_mode*/ true) .expect("assistant text should remain after stripping"); assert_eq!(message, "before\nafter"); @@ -70,14 +71,20 @@ fn last_assistant_message_from_item_strips_citations_and_plan_blocks() { fn last_assistant_message_from_item_returns_none_for_citation_only_message() { let item = assistant_output_text("doc1"); - assert_eq!(last_assistant_message_from_item(&item, false), None); + assert_eq!( + last_assistant_message_from_item(&item, /*plan_mode*/ false), + None + ); } #[test] fn last_assistant_message_from_item_returns_none_for_plan_only_hidden_message() { let item = assistant_output_text("\n- x\n"); - assert_eq!(last_assistant_message_from_item(&item, true), None); + assert_eq!( + last_assistant_message_from_item(&item, /*plan_mode*/ true), + None + ); } #[tokio::test] diff --git a/codex-rs/core/src/tasks/ghost_snapshot_tests.rs b/codex-rs/core/src/tasks/ghost_snapshot_tests.rs index 68bcbf9f2..c901137e8 100644 --- a/codex-rs/core/src/tasks/ghost_snapshot_tests.rs +++ b/codex-rs/core/src/tasks/ghost_snapshot_tests.rs @@ -27,5 +27,8 @@ fn large_untracked_warning_disabled_when_threshold_disabled() { ignored_untracked_files: Vec::new(), }; - assert_eq!(format_large_untracked_warning(None, &report), None); + assert_eq!( + format_large_untracked_warning(/*ignore_large_untracked_dirs*/ None, &report), + None + ); } diff --git a/codex-rs/core/src/tasks/mod_tests.rs b/codex-rs/core/src/tasks/mod_tests.rs index 7a55d55f6..6573da5d4 100644 --- a/codex-rs/core/src/tasks/mod_tests.rs +++ b/codex-rs/core/src/tasks/mod_tests.rs @@ -25,11 +25,11 @@ fn test_session_telemetry() -> SessionTelemetry { ThreadId::new(), "gpt-5.1", "gpt-5.1", - None, - None, - None, + /*account_id*/ None, + /*account_email*/ None, + /*auth_mode*/ None, "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "tty".to_string(), SessionSource::Cli, ) @@ -75,7 +75,11 @@ fn metric_point(resource_metrics: &ResourceMetrics) -> (BTreeMap fn emit_turn_network_proxy_metric_records_active_turn() { let session_telemetry = test_session_telemetry(); - emit_turn_network_proxy_metric(&session_telemetry, true, ("tmp_mem_enabled", "true")); + emit_turn_network_proxy_metric( + &session_telemetry, + /*network_proxy_active*/ true, + ("tmp_mem_enabled", "true"), + ); let snapshot = session_telemetry .snapshot_metrics() @@ -96,7 +100,11 @@ fn emit_turn_network_proxy_metric_records_active_turn() { fn emit_turn_network_proxy_metric_records_inactive_turn() { let session_telemetry = test_session_telemetry(); - emit_turn_network_proxy_metric(&session_telemetry, false, ("tmp_mem_enabled", "false")); + emit_turn_network_proxy_metric( + &session_telemetry, + /*network_proxy_active*/ false, + ("tmp_mem_enabled", "false"), + ); let snapshot = session_telemetry .snapshot_metrics() diff --git a/codex-rs/core/src/thread_manager_tests.rs b/codex-rs/core/src/thread_manager_tests.rs index c80f5f743..62a9aa199 100644 --- a/codex-rs/core/src/thread_manager_tests.rs +++ b/codex-rs/core/src/thread_manager_tests.rs @@ -75,7 +75,7 @@ fn truncates_before_requested_user_message() { .collect(); let truncated = truncate_before_nth_user_message( InitialHistory::Forked(initial), - 1, + /*n*/ 1, &SnapshotTurnState { ends_mid_turn: false, active_turn_id: None, @@ -100,7 +100,7 @@ fn truncates_before_requested_user_message() { .collect(); let truncated2 = truncate_before_nth_user_message( InitialHistory::Forked(initial2.clone()), - 2, + /*n*/ 2, &SnapshotTurnState { ends_mid_turn: false, active_turn_id: None, @@ -210,7 +210,7 @@ async fn ignores_session_prefix_messages_when_truncating() { let truncated = truncate_before_nth_user_message( InitialHistory::Forked(rollout_items), - 1, + /*n*/ 1, &SnapshotTurnState { ends_mid_turn: false, active_turn_id: None, diff --git a/codex-rs/core/src/thread_rollout_truncation_tests.rs b/codex-rs/core/src/thread_rollout_truncation_tests.rs index 20f65cd9a..d251b722d 100644 --- a/codex-rs/core/src/thread_rollout_truncation_tests.rs +++ b/codex-rs/core/src/thread_rollout_truncation_tests.rs @@ -61,7 +61,8 @@ fn truncates_rollout_from_start_before_nth_user_only() { .map(RolloutItem::ResponseItem) .collect(); - let truncated = truncate_rollout_before_nth_user_message_from_start(&rollout, 1); + let truncated = + truncate_rollout_before_nth_user_message_from_start(&rollout, /*n_from_start*/ 1); let expected = vec![ RolloutItem::ResponseItem(items[0].clone()), RolloutItem::ResponseItem(items[1].clone()), @@ -72,7 +73,8 @@ fn truncates_rollout_from_start_before_nth_user_only() { serde_json::to_value(&expected).unwrap() ); - let truncated2 = truncate_rollout_before_nth_user_message_from_start(&rollout, 2); + let truncated2 = + truncate_rollout_before_nth_user_message_from_start(&rollout, /*n_from_start*/ 2); assert_eq!( serde_json::to_value(&truncated2).unwrap(), serde_json::to_value(&rollout).unwrap() @@ -113,7 +115,10 @@ fn truncates_rollout_from_start_applies_thread_rollback_markers() { // Effective user history after applying rollback(1) is: u1, u3, u4. // So n_from_start=2 should cut before u4 (not u3). - let truncated = truncate_rollout_before_nth_user_message_from_start(&rollout_items, 2); + let truncated = truncate_rollout_before_nth_user_message_from_start( + &rollout_items, + /*n_from_start*/ 2, + ); let expected = rollout_items[..7].to_vec(); assert_eq!( serde_json::to_value(&truncated).unwrap(), @@ -136,7 +141,10 @@ async fn ignores_session_prefix_messages_when_truncating_rollout_from_start() { .map(RolloutItem::ResponseItem) .collect(); - let truncated = truncate_rollout_before_nth_user_message_from_start(&rollout_items, 1); + let truncated = truncate_rollout_before_nth_user_message_from_start( + &rollout_items, + /*n_from_start*/ 1, + ); let expected: Vec = vec![ RolloutItem::ResponseItem(items[0].clone()), RolloutItem::ResponseItem(items[1].clone()), diff --git a/codex-rs/core/src/tools/handlers/js_repl_tests.rs b/codex-rs/core/src/tools/handlers/js_repl_tests.rs index 9613a8303..51f7b3a17 100644 --- a/codex-rs/core/src/tools/handlers/js_repl_tests.rs +++ b/codex-rs/core/src/tools/handlers/js_repl_tests.rs @@ -58,7 +58,7 @@ async fn emit_js_repl_exec_end_sends_event() { turn.as_ref(), "call-1", "hello", - None, + /*error*/ None, Duration::from_millis(12), ) .await; diff --git a/codex-rs/core/src/tools/handlers/list_dir_tests.rs b/codex-rs/core/src/tools/handlers/list_dir_tests.rs index 8e3991a75..ccc30b532 100644 --- a/codex-rs/core/src/tools/handlers/list_dir_tests.rs +++ b/codex-rs/core/src/tools/handlers/list_dir_tests.rs @@ -34,9 +34,11 @@ async fn lists_directory_entries() { symlink(dir_path.join("entry.txt"), &link_path).expect("create symlink"); } - let entries = list_dir_slice(dir_path, 1, 20, 3) - .await - .expect("list directory"); + let entries = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 20, /*depth*/ 3, + ) + .await + .expect("list directory"); #[cfg(unix)] let expected = vec![ @@ -68,9 +70,11 @@ async fn errors_when_offset_exceeds_entries() { .await .expect("create sub dir"); - let err = list_dir_slice(dir_path, 10, 1, 2) - .await - .expect_err("offset exceeds entries"); + let err = list_dir_slice( + dir_path, /*offset*/ 10, /*limit*/ 1, /*depth*/ 2, + ) + .await + .expect_err("offset exceeds entries"); assert_eq!( err, FunctionCallError::RespondToModel("offset exceeds directory entry count".to_string()) @@ -95,17 +99,21 @@ async fn respects_depth_parameter() { .await .expect("write deeper"); - let entries_depth_one = list_dir_slice(dir_path, 1, 10, 1) - .await - .expect("list depth 1"); + let entries_depth_one = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 10, /*depth*/ 1, + ) + .await + .expect("list depth 1"); assert_eq!( entries_depth_one, vec!["nested/".to_string(), "root.txt".to_string(),] ); - let entries_depth_two = list_dir_slice(dir_path, 1, 20, 2) - .await - .expect("list depth 2"); + let entries_depth_two = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 20, /*depth*/ 2, + ) + .await + .expect("list depth 2"); assert_eq!( entries_depth_two, vec![ @@ -116,9 +124,11 @@ async fn respects_depth_parameter() { ] ); - let entries_depth_three = list_dir_slice(dir_path, 1, 30, 3) - .await - .expect("list depth 3"); + let entries_depth_three = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 30, /*depth*/ 3, + ) + .await + .expect("list depth 3"); assert_eq!( entries_depth_three, vec![ @@ -148,9 +158,11 @@ async fn paginates_in_sorted_order() { .await .expect("write b child"); - let first_page = list_dir_slice(dir_path, 1, 2, 2) - .await - .expect("list page one"); + let first_page = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 2, /*depth*/ 2, + ) + .await + .expect("list page one"); assert_eq!( first_page, vec![ @@ -160,9 +172,11 @@ async fn paginates_in_sorted_order() { ] ); - let second_page = list_dir_slice(dir_path, 3, 2, 2) - .await - .expect("list page two"); + let second_page = list_dir_slice( + dir_path, /*offset*/ 3, /*limit*/ 2, /*depth*/ 2, + ) + .await + .expect("list page two"); assert_eq!( second_page, vec!["b/".to_string(), " b_child.txt".to_string()] @@ -183,7 +197,7 @@ async fn handles_large_limit_without_overflow() { .await .expect("write gamma"); - let entries = list_dir_slice(dir_path, 2, usize::MAX, 1) + let entries = list_dir_slice(dir_path, /*offset*/ 2, usize::MAX, /*depth*/ 1) .await .expect("list without overflow"); assert_eq!( @@ -204,9 +218,11 @@ async fn indicates_truncated_results() { .expect("write file"); } - let entries = list_dir_slice(dir_path, 1, 25, 1) - .await - .expect("list directory"); + let entries = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 25, /*depth*/ 1, + ) + .await + .expect("list directory"); assert_eq!(entries.len(), 26); assert_eq!( entries.last(), @@ -226,7 +242,10 @@ async fn truncation_respects_sorted_order() -> anyhow::Result<()> { tokio::fs::write(nested.join("child.txt"), b"child").await?; tokio::fs::write(deeper.join("grandchild.txt"), b"deep").await?; - let entries_depth_three = list_dir_slice(dir_path, 1, 3, 3).await?; + let entries_depth_three = list_dir_slice( + dir_path, /*offset*/ 1, /*limit*/ 3, /*depth*/ 3, + ) + .await?; assert_eq!( entries_depth_three, vec![ diff --git a/codex-rs/core/src/tools/handlers/mod.rs b/codex-rs/core/src/tools/handlers/mod.rs index 1afab676a..86f2175be 100644 --- a/codex-rs/core/src/tools/handlers/mod.rs +++ b/codex-rs/core/src/tools/handlers/mod.rs @@ -261,7 +261,7 @@ mod tests { let cwd = tempdir().expect("tempdir"); let normalized = normalize_and_validate_additional_permissions( - false, + /*additional_permissions_allowed*/ false, AskForApproval::Granular(GranularApprovalConfig { sandbox_approval: true, rules: true, @@ -271,7 +271,7 @@ mod tests { }), SandboxPermissions::WithAdditionalPermissions, Some(network_permissions()), - true, + /*permissions_preapproved*/ true, cwd.path(), ) .expect("preapproved permissions should be allowed"); @@ -284,11 +284,11 @@ mod tests { let cwd = tempdir().expect("tempdir"); let err = normalize_and_validate_additional_permissions( - false, + /*additional_permissions_allowed*/ false, AskForApproval::OnRequest, SandboxPermissions::WithAdditionalPermissions, Some(network_permissions()), - false, + /*permissions_preapproved*/ false, cwd.path(), ) .expect_err("fresh inline permission requests should remain disabled"); @@ -305,7 +305,7 @@ mod tests { let granted_permissions = file_system_permissions(cwd.path()); let implicit_permissions = implicit_granted_permissions( SandboxPermissions::UseDefault, - None, + /*additional_permissions*/ None, &EffectiveAdditionalPermissions { sandbox_permissions: SandboxPermissions::WithAdditionalPermissions, additional_permissions: Some(granted_permissions.clone()), 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 f6f4677be..8006ee220 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -82,7 +82,7 @@ fn parse_agent_id(id: &str) -> ThreadId { fn thread_manager() -> ThreadManager { ThreadManager::with_models_provider_for_tests( CodexAuth::from_api_key("dummy"), - built_in_model_providers(/* openai_base_url */ None)["openai"].clone(), + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone(), ) } @@ -247,7 +247,8 @@ async fn spawn_agent_uses_explorer_role_and_preserves_approval_policy() { let manager = thread_manager(); session.services.agent_control = manager.agent_control(); let mut config = (*turn.config).clone(); - let provider = built_in_model_providers(/* openai_base_url */ None)["ollama"].clone(); + let provider = + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["ollama"].clone(); config.model_provider_id = "ollama".to_string(); config.model_provider = provider.clone(); config @@ -962,7 +963,7 @@ async fn multi_agent_v2_send_message_interrupts_busy_child_without_triggering_tu AgentPath::try_from("/root/worker").expect("agent path"), Vec::new(), "continue".to_string(), - false, + /*trigger_turn*/ false, ), ); let saw_user_message = history_items.iter().any(|item| { @@ -1094,7 +1095,7 @@ async fn multi_agent_v2_assign_task_interrupts_busy_child_without_losing_message AgentPath::try_from("/root/worker").expect("agent path"), Vec::new(), "continue".to_string(), - true, + /*trigger_turn*/ true, ), ); let saw_user_message = history_items.iter().any(|item| { @@ -1636,8 +1637,8 @@ async fn resume_agent_restores_closed_agent_and_accepts_send_input() { phase: None, })]), AuthManager::from_auth_for_testing(CodexAuth::from_api_key("dummy")), - false, - None, + /*persist_extended_history*/ false, + /*parent_trace*/ None, ) .await .expect("start thread"); @@ -2557,7 +2558,7 @@ async fn build_agent_resume_config_clears_base_instructions() { .set(AskForApproval::OnRequest) .expect("approval policy set"); - let config = build_agent_resume_config(&turn, 0).expect("resume config"); + let config = build_agent_resume_config(&turn, /*child_depth*/ 0).expect("resume config"); let mut expected = (*turn.config).clone(); expected.base_instructions = None; diff --git a/codex-rs/core/src/tools/handlers/request_user_input_tests.rs b/codex-rs/core/src/tools/handlers/request_user_input_tests.rs index f4df3c43c..bf44233e7 100644 --- a/codex-rs/core/src/tools/handlers/request_user_input_tests.rs +++ b/codex-rs/core/src/tools/handlers/request_user_input_tests.rs @@ -12,23 +12,38 @@ fn request_user_input_mode_availability_defaults_to_plan_only() { #[test] fn request_user_input_unavailable_messages_respect_default_mode_feature_flag() { assert_eq!( - request_user_input_unavailable_message(ModeKind::Plan, false), + request_user_input_unavailable_message( + ModeKind::Plan, + /*default_mode_request_user_input*/ false + ), None ); assert_eq!( - request_user_input_unavailable_message(ModeKind::Default, false), + request_user_input_unavailable_message( + ModeKind::Default, + /*default_mode_request_user_input*/ false + ), Some("request_user_input is unavailable in Default mode".to_string()) ); assert_eq!( - request_user_input_unavailable_message(ModeKind::Default, true), + request_user_input_unavailable_message( + ModeKind::Default, + /*default_mode_request_user_input*/ true + ), None ); assert_eq!( - request_user_input_unavailable_message(ModeKind::Execute, false), + request_user_input_unavailable_message( + ModeKind::Execute, + /*default_mode_request_user_input*/ false + ), Some("request_user_input is unavailable in Execute mode".to_string()) ); assert_eq!( - request_user_input_unavailable_message(ModeKind::PairProgramming, false), + request_user_input_unavailable_message( + ModeKind::PairProgramming, + /*default_mode_request_user_input*/ false + ), Some("request_user_input is unavailable in Pair Programming mode".to_string()) ); } @@ -36,11 +51,11 @@ fn request_user_input_unavailable_messages_respect_default_mode_feature_flag() { #[test] fn request_user_input_tool_description_mentions_available_modes() { assert_eq!( - request_user_input_tool_description(false), + request_user_input_tool_description(/*default_mode_request_user_input*/ false), "Request user input for one to three short questions and wait for the response. This tool is only available in Plan mode.".to_string() ); assert_eq!( - request_user_input_tool_description(true), + request_user_input_tool_description(/*default_mode_request_user_input*/ true), "Request user input for one to three short questions and wait for the response. This tool is only available in Default or Plan mode.".to_string() ); } diff --git a/codex-rs/core/src/tools/handlers/shell_tests.rs b/codex-rs/core/src/tools/handlers/shell_tests.rs index fdc015c5e..68b92dcf9 100644 --- a/codex-rs/core/src/tools/handlers/shell_tests.rs +++ b/codex-rs/core/src/tools/handlers/shell_tests.rs @@ -63,12 +63,12 @@ fn commands_generated_by_shell_command_handler_can_be_matched_by_is_known_safe_c } fn assert_safe(shell: &Shell, command: &str) { - assert!(is_known_safe_command( - &shell.derive_exec_args(command, /* use_login_shell */ true) - )); - assert!(is_known_safe_command( - &shell.derive_exec_args(command, /* use_login_shell */ false) - )); + assert!(is_known_safe_command(&shell.derive_exec_args( + command, /* use_login_shell */ /*use_login_shell*/ true + ))); + assert!(is_known_safe_command(&shell.derive_exec_args( + command, /* use_login_shell */ /*use_login_shell*/ false + ))); } #[tokio::test] @@ -82,7 +82,9 @@ async fn shell_command_handler_to_exec_params_uses_session_shell_and_turn_contex let sandbox_permissions = SandboxPermissions::RequireEscalated; let justification = Some("because tests".to_string()); - let expected_command = session.user_shell().derive_exec_args(&command, true); + let expected_command = session + .user_shell() + .derive_exec_args(&command, /*use_login_shell*/ true); let expected_cwd = turn_context.resolve_path(workdir.clone()); let expected_env = create_env( &turn_context.shell_environment_policy, @@ -105,7 +107,7 @@ async fn shell_command_handler_to_exec_params_uses_session_shell_and_turn_contex &session, &turn_context, session.conversation_id, - true, + /*allow_login_shell*/ true, ) .expect("login shells should be allowed"); @@ -132,17 +134,24 @@ fn shell_command_handler_respects_explicit_login_flag() { shell_snapshot, }; - let login_command = ShellCommandHandler::base_command(&shell, "echo login shell", true); + let login_command = ShellCommandHandler::base_command( + &shell, + "echo login shell", + /*use_login_shell*/ true, + ); assert_eq!( login_command, - shell.derive_exec_args("echo login shell", true) + shell.derive_exec_args("echo login shell", /*use_login_shell*/ true) ); - let non_login_command = - ShellCommandHandler::base_command(&shell, "echo non login shell", false); + let non_login_command = ShellCommandHandler::base_command( + &shell, + "echo non login shell", + /*use_login_shell*/ false, + ); assert_eq!( non_login_command, - shell.derive_exec_args("echo non login shell", false) + shell.derive_exec_args("echo non login shell", /*use_login_shell*/ false) ); } @@ -165,20 +174,23 @@ async fn shell_command_handler_defaults_to_non_login_when_disallowed() { &session, &turn_context, session.conversation_id, - false, + /*allow_login_shell*/ false, ) .expect("non-login shells should still be allowed"); assert_eq!( exec_params.command, - session.user_shell().derive_exec_args("echo hello", false) + session + .user_shell() + .derive_exec_args("echo hello", /*use_login_shell*/ false) ); } #[test] fn shell_command_handler_rejects_login_when_disallowed() { - let err = ShellCommandHandler::resolve_use_login_shell(Some(true), false) - .expect_err("explicit login should be rejected"); + let err = + ShellCommandHandler::resolve_use_login_shell(Some(true), /*allow_login_shell*/ false) + .expect_err("explicit login should be rejected"); assert!( err.to_string() diff --git a/codex-rs/core/src/tools/handlers/unified_exec_tests.rs b/codex-rs/core/src/tools/handlers/unified_exec_tests.rs index 2390068cc..11b75b28d 100644 --- a/codex-rs/core/src/tools/handlers/unified_exec_tests.rs +++ b/codex-rs/core/src/tools/handlers/unified_exec_tests.rs @@ -31,7 +31,7 @@ fn test_get_command_uses_default_shell_when_unspecified() -> anyhow::Result<()> &args, Arc::new(default_user_shell()), &UnifiedExecShellMode::Direct, - true, + /*allow_login_shell*/ true, ) .map_err(anyhow::Error::msg)?; @@ -52,7 +52,7 @@ fn test_get_command_respects_explicit_bash_shell() -> anyhow::Result<()> { &args, Arc::new(default_user_shell()), &UnifiedExecShellMode::Direct, - true, + /*allow_login_shell*/ true, ) .map_err(anyhow::Error::msg)?; @@ -78,7 +78,7 @@ fn test_get_command_respects_explicit_powershell_shell() -> anyhow::Result<()> { &args, Arc::new(default_user_shell()), &UnifiedExecShellMode::Direct, - true, + /*allow_login_shell*/ true, ) .map_err(anyhow::Error::msg)?; @@ -98,7 +98,7 @@ fn test_get_command_respects_explicit_cmd_shell() -> anyhow::Result<()> { &args, Arc::new(default_user_shell()), &UnifiedExecShellMode::Direct, - true, + /*allow_login_shell*/ true, ) .map_err(anyhow::Error::msg)?; @@ -115,7 +115,7 @@ fn test_get_command_rejects_explicit_login_when_disallowed() -> anyhow::Result<( &args, Arc::new(default_user_shell()), &UnifiedExecShellMode::Direct, - false, + /*allow_login_shell*/ false, ) .expect_err("explicit login should be rejected"); @@ -144,8 +144,13 @@ fn test_get_command_ignores_explicit_shell_in_zsh_fork_mode() -> anyhow::Result< })?, }); - let command = get_command(&args, Arc::new(default_user_shell()), &shell_mode, true) - .map_err(anyhow::Error::msg)?; + let command = get_command( + &args, + Arc::new(default_user_shell()), + &shell_mode, + /*allow_login_shell*/ true, + ) + .map_err(anyhow::Error::msg)?; assert_eq!( command, diff --git a/codex-rs/core/src/tools/js_repl/mod_tests.rs b/codex-rs/core/src/tools/js_repl/mod_tests.rs index c75955400..242fe9140 100644 --- a/codex-rs/core/src/tools/js_repl/mod_tests.rs +++ b/codex-rs/core/src/tools/js_repl/mod_tests.rs @@ -47,13 +47,19 @@ fn node_version_parses_v_prefix_and_suffix() { #[test] fn truncate_utf8_prefix_by_bytes_preserves_character_boundaries() { let input = "aΓ©πŸ™‚z"; - assert_eq!(truncate_utf8_prefix_by_bytes(input, 0), ""); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 1), "a"); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 2), "a"); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 3), "aΓ©"); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 6), "aΓ©"); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 7), "aΓ©πŸ™‚"); - assert_eq!(truncate_utf8_prefix_by_bytes(input, 8), "aΓ©πŸ™‚z"); + assert_eq!(truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 0), ""); + assert_eq!(truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 1), "a"); + assert_eq!(truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 2), "a"); + assert_eq!(truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 3), "aΓ©"); + assert_eq!(truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 6), "aΓ©"); + assert_eq!( + truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 7), + "aΓ©πŸ™‚" + ); + assert_eq!( + truncate_utf8_prefix_by_bytes(input, /*max_bytes*/ 8), + "aΓ©πŸ™‚z" + ); } #[test] @@ -203,7 +209,7 @@ async fn wait_for_exec_tool_calls_map_drains_inflight_calls_without_hanging() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn reset_waits_for_exec_lock_before_clearing_exec_tool_calls() { - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let permit = manager @@ -300,8 +306,11 @@ async fn emitted_image_content_item_does_not_force_original_when_enabled() { .expect("test turn features should allow feature update"); turn.model_info.supports_image_detail_original = true; - let content_item = - emitted_image_content_item(&turn, "data:image/png;base64,AAA".to_string(), None); + let content_item = emitted_image_content_item( + &turn, + "data:image/png;base64,AAA".to_string(), + /*detail*/ None, + ); assert_eq!( content_item, @@ -427,7 +436,7 @@ fn summarize_tool_call_error_marks_error_payload() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn reset_clears_inflight_exec_tool_calls_without_waiting() { - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let exec_id = Uuid::new_v4().to_string(); @@ -460,7 +469,7 @@ async fn reset_clears_inflight_exec_tool_calls_without_waiting() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn reset_aborts_inflight_exec_tool_tasks() { - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let exec_id = Uuid::new_v4().to_string(); @@ -621,14 +630,14 @@ async fn interrupt_turn_exec_clears_matching_submitted_exec() -> anyhow::Result< return Ok(()); } - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let (_session, turn) = make_session_and_context().await; let turn = Arc::new(turn); let dependency_env = HashMap::new(); let mut state = manager - .start_kernel(Arc::clone(&turn), &dependency_env, None) + .start_kernel(Arc::clone(&turn), &dependency_env, /*thread_id*/ None) .await .map_err(anyhow::Error::msg)?; let child = Arc::clone(&state.child); @@ -667,14 +676,14 @@ async fn interrupt_turn_exec_resets_matching_pending_kernel_start() -> anyhow::R return Ok(()); } - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let (_session, turn) = make_session_and_context().await; let turn = Arc::new(turn); let dependency_env = HashMap::new(); let mut state = manager - .start_kernel(Arc::clone(&turn), &dependency_env, None) + .start_kernel(Arc::clone(&turn), &dependency_env, /*thread_id*/ None) .await .map_err(anyhow::Error::msg)?; state.top_level_exec_state = TopLevelExecState::FreshKernel { @@ -711,14 +720,14 @@ async fn interrupt_turn_exec_does_not_reset_reused_kernel_before_submit() -> any return Ok(()); } - let manager = JsReplManager::new(None, Vec::new()) + let manager = JsReplManager::new(/*node_path*/ None, Vec::new()) .await .expect("manager should initialize"); let (_session, turn) = make_session_and_context().await; let turn = Arc::new(turn); let dependency_env = HashMap::new(); let mut state = manager - .start_kernel(Arc::clone(&turn), &dependency_env, None) + .start_kernel(Arc::clone(&turn), &dependency_env, /*thread_id*/ None) .await .map_err(anyhow::Error::msg)?; state.top_level_exec_state = TopLevelExecState::ReusedKernelPending { diff --git a/codex-rs/core/src/tools/registry_tests.rs b/codex-rs/core/src/tools/registry_tests.rs index 301828206..687364872 100644 --- a/codex-rs/core/src/tools/registry_tests.rs +++ b/codex-rs/core/src/tools/registry_tests.rs @@ -29,7 +29,7 @@ fn handler_looks_up_namespaced_aliases_explicitly() { (namespaced_name, Arc::clone(&namespaced_handler)), ])); - let plain = registry.handler(tool_name, None); + let plain = registry.handler(tool_name, /*namespace*/ None); let namespaced = registry.handler(tool_name, Some(namespace)); let missing_namespaced = registry.handler(tool_name, Some("mcp__codex_apps__calendar")); diff --git a/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs b/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs index 589e5216d..a94f1f99b 100644 --- a/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs +++ b/codex-rs/core/src/tools/runtimes/apply_patch_tests.rs @@ -126,8 +126,8 @@ fn build_sandbox_command_falls_back_to_current_exe_for_apply_patch() { timeout_ms: None, }; - let command = - ApplyPatchRuntime::build_sandbox_command(&request, None).expect("build sandbox command"); + let command = ApplyPatchRuntime::build_sandbox_command(&request, /*codex_self_exe*/ None) + .expect("build sandbox command"); assert_eq!( command.program, diff --git a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs index 41cfce515..226f7f054 100644 --- a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs +++ b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs @@ -95,15 +95,24 @@ fn execve_prompt_rejection_keeps_unmatched_commands_on_sandbox_flag() { #[test] fn approval_sandbox_permissions_only_downgrades_preapproved_additional_permissions() { assert_eq!( - super::approval_sandbox_permissions(SandboxPermissions::WithAdditionalPermissions, true), + super::approval_sandbox_permissions( + SandboxPermissions::WithAdditionalPermissions, + /*additional_permissions_preapproved*/ true + ), SandboxPermissions::UseDefault, ); assert_eq!( - super::approval_sandbox_permissions(SandboxPermissions::WithAdditionalPermissions, false), + super::approval_sandbox_permissions( + SandboxPermissions::WithAdditionalPermissions, + /*additional_permissions_preapproved*/ false + ), SandboxPermissions::WithAdditionalPermissions, ); assert_eq!( - super::approval_sandbox_permissions(SandboxPermissions::RequireEscalated, true), + super::approval_sandbox_permissions( + SandboxPermissions::RequireEscalated, + /*additional_permissions_preapproved*/ true + ), SandboxPermissions::RequireEscalated, ); } @@ -278,7 +287,7 @@ fn shell_request_escalation_execution_is_explicit() { &sandbox_policy, &file_system_sandbox_policy, network_sandbox_policy, - None, + /*additional_permissions*/ None, ), EscalationExecution::TurnDefault, ); @@ -288,7 +297,7 @@ fn shell_request_escalation_execution_is_explicit() { &sandbox_policy, &file_system_sandbox_policy, network_sandbox_policy, - None, + /*additional_permissions*/ None, ), EscalationExecution::Unsandboxed, ); @@ -466,7 +475,7 @@ fn intercepted_exec_policy_treats_preapproved_additional_permissions_as_default( file_system_sandbox_policy: &file_system_sandbox_policy, sandbox_permissions: super::approval_sandbox_permissions( SandboxPermissions::WithAdditionalPermissions, - true, + /*additional_permissions_preapproved*/ true, ), enable_shell_wrapper_parsing: false, }, diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index e938f82f8..2a0704262 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -2389,7 +2389,13 @@ pub(crate) fn build_specs( app_tools: Option>, dynamic_tools: &[DynamicToolSpec], ) -> ToolRegistryBuilder { - build_specs_with_discoverable_tools(config, mcp_tools, app_tools, None, dynamic_tools) + build_specs_with_discoverable_tools( + config, + mcp_tools, + app_tools, + /*discoverable_tools*/ None, + dynamic_tools, + ) } pub(crate) fn build_specs_with_discoverable_tools( diff --git a/codex-rs/core/src/tools/spec_tests.rs b/codex-rs/core/src/tools/spec_tests.rs index 9a096b8bc..b62407778 100644 --- a/codex-rs/core/src/tools/spec_tests.rs +++ b/codex-rs/core/src/tools/spec_tests.rs @@ -220,22 +220,22 @@ fn model_info_from_models_json(slug: &str) -> ModelInfo { #[test] fn unified_exec_is_blocked_for_windows_sandboxed_policies_only() { assert!(!unified_exec_allowed_in_environment( - true, + /*is_windows*/ true, &SandboxPolicy::new_read_only_policy(), WindowsSandboxLevel::RestrictedToken, )); assert!(!unified_exec_allowed_in_environment( - true, + /*is_windows*/ true, &SandboxPolicy::new_workspace_write_policy(), WindowsSandboxLevel::RestrictedToken, )); assert!(unified_exec_allowed_in_environment( - true, + /*is_windows*/ true, &SandboxPolicy::DangerFullAccess, WindowsSandboxLevel::RestrictedToken, )); assert!(unified_exec_allowed_in_environment( - true, + /*is_windows*/ true, &SandboxPolicy::DangerFullAccess, WindowsSandboxLevel::Disabled, )); @@ -280,7 +280,13 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&config, None, None, &[]).build(); + let (tools, _) = build_specs( + &config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); // Build actual map name -> spec use std::collections::BTreeMap; @@ -301,7 +307,9 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() { // Build expected from the same helpers used by the builder. let mut expected: BTreeMap = BTreeMap::from([]); for spec in [ - create_exec_command_tool(true, false), + create_exec_command_tool( + /*allow_login_shell*/ true, /*exec_permission_approvals_enabled*/ false, + ), create_write_stdin_tool(), PLAN_TOOL.clone(), create_request_user_input_tool(CollaborationModesConfig::default()), @@ -376,7 +384,13 @@ fn test_build_specs_collab_tools_enabled() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names( &tools, &["spawn_agent", "send_input", "wait_agent", "close_agent"], @@ -402,7 +416,13 @@ fn test_build_specs_multi_agent_v2_uses_task_names_and_hides_resume() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names( &tools, &[ @@ -554,7 +574,13 @@ fn test_build_specs_enable_fanout_enables_agent_jobs_and_collab_tools() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names( &tools, &[ @@ -584,7 +610,13 @@ fn view_image_tool_omits_detail_without_original_detail_feature() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let view_image = find_tool(&tools, VIEW_IMAGE_TOOL_NAME); let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = &view_image.spec else { panic!("view_image should be a function tool"); @@ -613,7 +645,13 @@ fn view_image_tool_includes_detail_with_original_detail_feature() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let view_image = find_tool(&tools, VIEW_IMAGE_TOOL_NAME); let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = &view_image.spec else { panic!("view_image should be a function tool"); @@ -652,7 +690,13 @@ fn test_build_specs_agent_job_worker_tools_enabled() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names( &tools, &[ @@ -683,7 +727,13 @@ fn request_user_input_description_reflects_default_mode_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let request_user_input_tool = find_tool(&tools, "request_user_input"); assert_eq!( request_user_input_tool.spec, @@ -701,7 +751,13 @@ fn request_user_input_description_reflects_default_mode_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let request_user_input_tool = find_tool(&tools, "request_user_input"); assert_eq!( request_user_input_tool.spec, @@ -726,7 +782,13 @@ fn request_permissions_requires_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_lacks_tool_name(&tools, "request_permissions"); let mut features = Features::with_defaults(); @@ -741,7 +803,13 @@ fn request_permissions_requires_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let request_permissions_tool = find_tool(&tools, "request_permissions"); assert_eq!( request_permissions_tool.spec, @@ -765,7 +833,13 @@ fn request_permissions_tool_is_independent_from_additional_permissions() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_lacks_tool_name(&tools, "request_permissions"); } @@ -786,7 +860,13 @@ fn get_memory_requires_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( !tools.iter().any(|t| t.spec.name() == "get_memory"), "get_memory should be disabled when memory_tool feature is off" @@ -809,7 +889,13 @@ fn js_repl_requires_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( !tools.iter().any(|tool| tool.spec.name() == "js_repl"), @@ -838,7 +924,13 @@ fn js_repl_enabled_adds_tools() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names(&tools, &["js_repl", "js_repl_reset"]); } @@ -864,7 +956,13 @@ fn image_generation_tools_require_feature_and_supported_model() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (default_tools, _) = build_specs(&default_tools_config, None, None, &[]).build(); + let (default_tools, _) = build_specs( + &default_tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( !default_tools .iter() @@ -881,7 +979,13 @@ fn image_generation_tools_require_feature_and_supported_model() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (supported_tools, _) = build_specs(&supported_tools_config, None, None, &[]).build(); + let (supported_tools, _) = build_specs( + &supported_tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names(&supported_tools, &["image_generation"]); let image_generation_tool = find_tool(&supported_tools, "image_generation"); assert_eq!( @@ -901,7 +1005,13 @@ fn image_generation_tools_require_feature_and_supported_model() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( !tools .iter() @@ -992,7 +1102,13 @@ fn web_search_mode_cached_sets_external_web_access_false() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let tool = find_tool(&tools, "web_search"); assert_eq!( @@ -1023,7 +1139,13 @@ fn web_search_mode_live_sets_external_web_access_true() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let tool = find_tool(&tools, "web_search"); assert_eq!( @@ -1068,7 +1190,13 @@ fn web_search_config_is_forwarded_to_tool_spec() { windows_sandbox_level: WindowsSandboxLevel::Disabled, }) .with_web_search_config(Some(web_search_config.clone())); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let tool = find_tool(&tools, "web_search"); assert_eq!( @@ -1105,7 +1233,13 @@ fn web_search_tool_type_text_and_image_sets_search_content_types() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let tool = find_tool(&tools, "web_search"); assert_eq!( @@ -1140,7 +1274,13 @@ fn mcp_resource_tools_are_hidden_without_mcp_servers() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( !tools.iter().any(|tool| matches!( @@ -1166,7 +1306,13 @@ fn mcp_resource_tools_are_included_when_mcp_servers_are_present() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, Some(HashMap::new()), None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + Some(HashMap::new()), + /*app_tools*/ None, + &[], + ) + .build(); assert_contains_tool_names( &tools, @@ -1406,7 +1552,13 @@ fn test_build_specs_default_shell_present() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, Some(HashMap::new()), None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + Some(HashMap::new()), + /*app_tools*/ None, + &[], + ) + .build(); // Only check the shell variant and a couple of core tools. let mut subset = vec!["exec_command", "write_stdin", "update_plan"]; @@ -1496,7 +1648,13 @@ fn test_parallel_support_flags() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!(find_tool(&tools, "exec_command").supports_parallel_tool_calls); assert!(!find_tool(&tools, "write_stdin").supports_parallel_tool_calls); @@ -1518,7 +1676,13 @@ fn test_test_model_info_includes_sync_tool() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); assert!( tools @@ -1568,7 +1732,7 @@ fn test_build_specs_mcp_tools_converted() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -1653,7 +1817,7 @@ fn test_build_specs_mcp_tools_sorted_by_name() { ), ]); - let (tools, _) = build_specs(&tools_config, Some(tools_map), None, &[]).build(); + let (tools, _) = build_specs(&tools_config, Some(tools_map), /*app_tools*/ None, &[]).build(); // Only assert that the MCP tools themselves are sorted by fully-qualified name. let mcp_names: Vec<_> = tools @@ -1827,7 +1991,13 @@ fn search_tool_requires_model_capability_and_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, app_tools.clone(), &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + app_tools.clone(), + &[], + ) + .build(); assert_lacks_tool_name(&tools, TOOL_SEARCH_TOOL_NAME); let available_models = Vec::new(); @@ -1840,7 +2010,13 @@ fn search_tool_requires_model_capability_and_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, app_tools.clone(), &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + app_tools.clone(), + &[], + ) + .build(); assert_lacks_tool_name(&tools, TOOL_SEARCH_TOOL_NAME); let mut features = Features::with_defaults(); @@ -1855,7 +2031,7 @@ fn search_tool_requires_model_capability_and_feature_flag() { sandbox_policy: &SandboxPolicy::DangerFullAccess, windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, app_tools, &[]).build(); + let (tools, _) = build_specs(&tools_config, /*mcp_tools*/ None, app_tools, &[]).build(); assert_contains_tool_names(&tools, &[TOOL_SEARCH_TOOL_NAME]); } @@ -1879,8 +2055,8 @@ fn tool_suggest_is_not_registered_without_feature_flag() { }); let (tools, _) = build_specs_with_discoverable_tools( &tools_config, - None, - None, + /*mcp_tools*/ None, + /*app_tools*/ None, Some(vec![discoverable_connector( "connector_2128aebfecb84f64a069897515042a44", "Google Calendar", @@ -1919,8 +2095,8 @@ fn tool_suggest_can_be_registered_without_search_tool() { }); let (tools, _) = build_specs_with_discoverable_tools( &tools_config, - None, - None, + /*mcp_tools*/ None, + /*app_tools*/ None, Some(vec![discoverable_connector( "connector_2128aebfecb84f64a069897515042a44", "Google Calendar", @@ -1974,8 +2150,8 @@ fn tool_suggest_requires_apps_and_plugins_features() { }); let (tools, _) = build_specs_with_discoverable_tools( &tools_config, - None, - None, + /*mcp_tools*/ None, + /*app_tools*/ None, discoverable_tools.clone(), &[], ) @@ -2007,7 +2183,13 @@ fn search_tool_description_handles_no_enabled_apps() { windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, Some(HashMap::new()), &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + Some(HashMap::new()), + &[], + ) + .build(); let search_tool = find_tool(&tools, TOOL_SEARCH_TOOL_NAME); let ToolSpec::ToolSearch { description, .. } = &search_tool.spec else { panic!("expected tool_search tool"); @@ -2036,7 +2218,7 @@ fn search_tool_description_falls_back_to_connector_name_without_description() { let (tools, _) = build_specs( &tools_config, - None, + /*mcp_tools*/ None, Some(HashMap::from([( "mcp__codex_apps__calendar_create_event".to_string(), ToolInfo { @@ -2085,7 +2267,7 @@ fn search_tool_registers_namespaced_app_tool_aliases() { let (_, registry) = build_specs( &tools_config, - None, + /*mcp_tools*/ None, Some(HashMap::from([ ( "mcp__codex_apps__calendar_create_event".to_string(), @@ -2128,8 +2310,8 @@ fn search_tool_registers_namespaced_app_tool_aliases() { let alias = tool_handler_key("_create_event", Some("mcp__codex_apps__calendar")); - assert!(registry.has_handler(TOOL_SEARCH_TOOL_NAME, None)); - assert!(registry.has_handler(alias.as_str(), None)); + assert!(registry.has_handler(TOOL_SEARCH_TOOL_NAME, /*namespace*/ None)); + assert!(registry.has_handler(alias.as_str(), /*namespace*/ None)); } #[test] @@ -2174,8 +2356,8 @@ fn tool_suggest_description_lists_discoverable_tools() { let (tools, _) = build_specs_with_discoverable_tools( &tools_config, - None, - None, + /*mcp_tools*/ None, + /*app_tools*/ None, Some(discoverable_tools), &[], ) @@ -2269,7 +2451,7 @@ fn test_mcp_tool_property_missing_type_defaults_to_string() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2327,7 +2509,7 @@ fn test_mcp_tool_integer_normalized_to_number() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2384,7 +2566,7 @@ fn test_mcp_tool_array_without_items_gets_default_string_items() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2445,7 +2627,7 @@ fn test_mcp_tool_anyof_defaults_to_string() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2473,7 +2655,7 @@ fn test_mcp_tool_anyof_defaults_to_string() { #[test] fn test_shell_tool() { - let tool = super::create_shell_tool(false); + let tool = super::create_shell_tool(/*exec_permission_approvals_enabled*/ false); let ToolSpec::Function(ResponsesApiTool { description, name, .. }) = &tool @@ -2506,7 +2688,9 @@ Examples of valid command strings: #[test] fn test_exec_command_tool_windows_description_includes_shell_safety_guidance() { - let tool = super::create_exec_command_tool(true, false); + let tool = super::create_exec_command_tool( + /*allow_login_shell*/ true, /*exec_permission_approvals_enabled*/ false, + ); let ToolSpec::Function(ResponsesApiTool { description, name, .. }) = &tool @@ -2529,7 +2713,7 @@ fn test_exec_command_tool_windows_description_includes_shell_safety_guidance() { #[test] fn shell_tool_with_request_permission_includes_additional_permissions() { - let tool = super::create_shell_tool(true); + let tool = super::create_shell_tool(/*exec_permission_approvals_enabled*/ true); let ToolSpec::Function(ResponsesApiTool { parameters, .. }) = tool else { panic!("expected function tool"); }; @@ -2609,7 +2793,9 @@ fn request_permissions_tool_includes_full_permission_schema() { #[test] fn test_shell_command_tool() { - let tool = super::create_shell_command_tool(true, false); + let tool = super::create_shell_command_tool( + /*allow_login_shell*/ true, /*exec_permission_approvals_enabled*/ false, + ); let ToolSpec::Function(ResponsesApiTool { description, name, .. }) = &tool @@ -2686,7 +2872,7 @@ fn test_get_openai_tools_mcp_tools_with_additional_properties_schema() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2766,7 +2952,13 @@ fn code_mode_augments_builtin_tool_descriptions_with_typed_sample() { windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let ToolSpec::Function(ResponsesApiTool { description, .. }) = &find_tool(&tools, "view_image").spec else { @@ -2814,7 +3006,7 @@ fn code_mode_augments_mcp_tool_descriptions_with_namespaced_sample() { }), ), )])), - None, + /*app_tools*/ None, &[], ) .build(); @@ -2863,7 +3055,13 @@ fn code_mode_only_exec_description_includes_full_nested_tool_details() { windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let ToolSpec::Freeform(FreeformTool { description, .. }) = &find_tool(&tools, "exec").spec else { panic!("expected freeform tool"); @@ -2895,7 +3093,13 @@ fn code_mode_exec_description_omits_nested_tool_details_when_not_code_mode_only( windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, _) = build_specs(&tools_config, None, None, &[]).build(); + let (tools, _) = build_specs( + &tools_config, + /*mcp_tools*/ None, + /*app_tools*/ None, + &[], + ) + .build(); let ToolSpec::Freeform(FreeformTool { description, .. }) = &find_tool(&tools, "exec").spec else { panic!("expected freeform tool"); diff --git a/codex-rs/core/src/unified_exec/async_watcher_tests.rs b/codex-rs/core/src/unified_exec/async_watcher_tests.rs index bdf8f7534..07d1bec60 100644 --- a/codex-rs/core/src/unified_exec/async_watcher_tests.rs +++ b/codex-rs/core/src/unified_exec/async_watcher_tests.rs @@ -6,11 +6,13 @@ use pretty_assertions::assert_eq; fn split_valid_utf8_prefix_respects_max_bytes_for_ascii() { let mut buf = b"hello word!".to_vec(); - let first = split_valid_utf8_prefix_with_max(&mut buf, 5).expect("expected prefix"); + let first = + split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 5).expect("expected prefix"); assert_eq!(first, b"hello".to_vec()); assert_eq!(buf, b" word!".to_vec()); - let second = split_valid_utf8_prefix_with_max(&mut buf, 5).expect("expected prefix"); + let second = + split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 5).expect("expected prefix"); assert_eq!(second, b" word".to_vec()); assert_eq!(buf, b"!".to_vec()); } @@ -20,7 +22,8 @@ fn split_valid_utf8_prefix_avoids_splitting_utf8_codepoints() { // "Γ©" is 2 bytes in UTF-8. With a max of 3 bytes, we should only emit 1 char (2 bytes). let mut buf = "ééé".as_bytes().to_vec(); - let first = split_valid_utf8_prefix_with_max(&mut buf, 3).expect("expected prefix"); + let first = + split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 3).expect("expected prefix"); assert_eq!(std::str::from_utf8(&first).unwrap(), "Γ©"); assert_eq!(buf, "éé".as_bytes().to_vec()); } @@ -29,7 +32,8 @@ fn split_valid_utf8_prefix_avoids_splitting_utf8_codepoints() { fn split_valid_utf8_prefix_makes_progress_on_invalid_utf8() { let mut buf = vec![0xff, b'a', b'b']; - let first = split_valid_utf8_prefix_with_max(&mut buf, 2).expect("expected prefix"); + let first = + split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 2).expect("expected prefix"); assert_eq!(first, vec![0xff]); assert_eq!(buf, b"ab".to_vec()); } diff --git a/codex-rs/core/src/unified_exec/head_tail_buffer_tests.rs b/codex-rs/core/src/unified_exec/head_tail_buffer_tests.rs index 55493a6b8..34da5be5f 100644 --- a/codex-rs/core/src/unified_exec/head_tail_buffer_tests.rs +++ b/codex-rs/core/src/unified_exec/head_tail_buffer_tests.rs @@ -4,7 +4,7 @@ use pretty_assertions::assert_eq; #[test] fn keeps_prefix_and_suffix_when_over_budget() { - let mut buf = HeadTailBuffer::new(10); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10); buf.push_chunk(b"0123456789".to_vec()); assert_eq!(buf.omitted_bytes(), 0); @@ -20,7 +20,7 @@ fn keeps_prefix_and_suffix_when_over_budget() { #[test] fn max_bytes_zero_drops_everything() { - let mut buf = HeadTailBuffer::new(0); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 0); buf.push_chunk(b"abc".to_vec()); assert_eq!(buf.retained_bytes(), 0); @@ -31,7 +31,7 @@ fn max_bytes_zero_drops_everything() { #[test] fn head_budget_zero_keeps_only_last_byte_in_tail() { - let mut buf = HeadTailBuffer::new(1); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 1); buf.push_chunk(b"abc".to_vec()); assert_eq!(buf.retained_bytes(), 1); @@ -41,7 +41,7 @@ fn head_budget_zero_keeps_only_last_byte_in_tail() { #[test] fn draining_resets_state() { - let mut buf = HeadTailBuffer::new(10); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10); buf.push_chunk(b"0123456789".to_vec()); buf.push_chunk(b"ab".to_vec()); @@ -55,7 +55,7 @@ fn draining_resets_state() { #[test] fn chunk_larger_than_tail_budget_keeps_only_tail_end() { - let mut buf = HeadTailBuffer::new(10); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10); buf.push_chunk(b"0123456789".to_vec()); // Tail budget is 5 bytes. This chunk should replace the tail and keep only its last 5 bytes. @@ -69,7 +69,7 @@ fn chunk_larger_than_tail_budget_keeps_only_tail_end() { #[test] fn fills_head_then_tail_across_multiple_chunks() { - let mut buf = HeadTailBuffer::new(10); + let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10); // Fill the 5-byte head budget across multiple chunks. buf.push_chunk(b"01".to_vec()); diff --git a/codex-rs/core/src/unified_exec/mod_tests.rs b/codex-rs/core/src/unified_exec/mod_tests.rs index b3a10410a..8348614f9 100644 --- a/codex-rs/core/src/unified_exec/mod_tests.rs +++ b/codex-rs/core/src/unified_exec/mod_tests.rs @@ -33,7 +33,15 @@ async fn exec_command( yield_time_ms: u64, workdir: Option, ) -> Result { - exec_command_with_tty(session, turn, cmd, yield_time_ms, workdir, true).await + exec_command_with_tty( + session, + turn, + cmd, + yield_time_ms, + workdir, + /*tty*/ true, + ) + .await } fn shell_env() -> HashMap { @@ -227,14 +235,17 @@ async fn unified_exec_persists_across_requests() -> anyhow::Result<()> { let (session, turn) = test_session_and_turn().await; - let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?; + let open_shell = exec_command( + &session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None, + ) + .await?; let process_id = open_shell.process_id.expect("expected process_id"); write_stdin( &session, process_id, "export CODEX_INTERACTIVE_SHELL_VAR=codex\n", - 2_500, + /*yield_time_ms*/ 2_500, ) .await?; @@ -242,7 +253,7 @@ async fn unified_exec_persists_across_requests() -> anyhow::Result<()> { &session, process_id, "echo $CODEX_INTERACTIVE_SHELL_VAR\n", - 2_500, + /*yield_time_ms*/ 2_500, ) .await?; assert!( @@ -259,14 +270,17 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> { let (session, turn) = test_session_and_turn().await; - let shell_a = exec_command(&session, &turn, "bash -i", 2_500, None).await?; + let shell_a = exec_command( + &session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None, + ) + .await?; let session_a = shell_a.process_id.expect("expected process id"); write_stdin( &session, session_a, "export CODEX_INTERACTIVE_SHELL_VAR=codex\n", - 2_500, + /*yield_time_ms*/ 2_500, ) .await?; @@ -274,8 +288,8 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> { &session, &turn, "echo $CODEX_INTERACTIVE_SHELL_VAR", - 2_500, - None, + /*yield_time_ms*/ 2_500, + /*workdir*/ None, ) .await?; tokio::time::sleep(Duration::from_secs(2)).await; @@ -292,7 +306,7 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> { &session, shell_a.process_id.expect("expected process id"), "echo $CODEX_INTERACTIVE_SHELL_VAR\n", - 2_500, + /*yield_time_ms*/ 2_500, ) .await?; assert!( @@ -311,14 +325,17 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> { let (session, turn) = test_session_and_turn().await; - let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?; + let open_shell = exec_command( + &session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None, + ) + .await?; let process_id = open_shell.process_id.expect("expected process id"); write_stdin( &session, process_id, format!("export CODEX_INTERACTIVE_SHELL_VAR={TEST_VAR_VALUE}\n").as_str(), - 2_500, + /*yield_time_ms*/ 2_500, ) .await?; @@ -326,7 +343,7 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> { &session, process_id, "sleep 5 && echo $CODEX_INTERACTIVE_SHELL_VAR\n", - 10, + /*yield_time_ms*/ 10, ) .await?; assert!( @@ -336,7 +353,7 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> { tokio::time::sleep(Duration::from_secs(7)).await; - let out_3 = write_stdin(&session, process_id, "", 100).await?; + let out_3 = write_stdin(&session, process_id, "", /*yield_time_ms*/ 100).await?; assert!( out_3.truncated_output().contains(TEST_VAR_VALUE), @@ -351,12 +368,12 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> { skip_if_sandbox!(Ok(())); let (session, turn) = test_session_and_turn().await; - session.set_out_of_band_elicitation_pause_state(true); + session.set_out_of_band_elicitation_pause_state(/*paused*/ true); let paused_session = Arc::clone(&session); tokio::spawn(async move { tokio::time::sleep(Duration::from_secs(2)).await; - paused_session.set_out_of_band_elicitation_pause_state(false); + paused_session.set_out_of_band_elicitation_pause_state(/*paused*/ false); }); let started = tokio::time::Instant::now(); @@ -364,8 +381,8 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> { &session, &turn, "sleep 1 && echo unified-exec-done", - 250, - None, + /*yield_time_ms*/ 250, + /*workdir*/ None, ) .await?; @@ -390,7 +407,14 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> { async fn requests_with_large_timeout_are_capped() -> anyhow::Result<()> { let (session, turn) = test_session_and_turn().await; - let result = exec_command(&session, &turn, "echo codex", 120_000, None).await?; + let result = exec_command( + &session, + &turn, + "echo codex", + /*yield_time_ms*/ 120_000, + /*workdir*/ None, + ) + .await?; assert!(result.process_id.is_some()); assert!(result.truncated_output().contains("codex")); @@ -402,7 +426,14 @@ async fn requests_with_large_timeout_are_capped() -> anyhow::Result<()> { #[ignore] // Ignored while we have a better way to test this. async fn completed_commands_do_not_persist_sessions() -> anyhow::Result<()> { let (session, turn) = test_session_and_turn().await; - let result = exec_command(&session, &turn, "echo codex", 2_500, None).await?; + let result = exec_command( + &session, + &turn, + "echo codex", + /*yield_time_ms*/ 2_500, + /*workdir*/ None, + ) + .await?; assert!( result.process_id.is_some(), @@ -430,14 +461,17 @@ async fn reusing_completed_process_returns_unknown_process() -> anyhow::Result<( let (session, turn) = test_session_and_turn().await; - let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?; + let open_shell = exec_command( + &session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None, + ) + .await?; let process_id = open_shell.process_id.expect("expected process id"); - write_stdin(&session, process_id, "exit\n", 2_500).await?; + write_stdin(&session, process_id, "exit\n", /*yield_time_ms*/ 2_500).await?; tokio::time::sleep(Duration::from_millis(200)).await; - let err = write_stdin(&session, process_id, "", 100) + let err = write_stdin(&session, process_id, "", /*yield_time_ms*/ 100) .await .expect_err("expected unknown process error"); @@ -475,9 +509,9 @@ async fn completed_pipe_commands_preserve_exit_code() -> anyhow::Result<()> { let environment = codex_exec_server::Environment::default(); let process = UnifiedExecProcessManager::default() .open_session_with_exec_env( - 1234, + /*process_id*/ 1234, &request, - false, + /*tty*/ false, Box::new(NoopSpawnLifecycle), &environment, ) @@ -517,9 +551,9 @@ async fn unified_exec_uses_remote_exec_server_when_configured() -> anyhow::Resul let manager = UnifiedExecProcessManager::default(); let process = manager .open_session_with_exec_env( - 1234, + /*process_id*/ 1234, &request, - true, + /*tty*/ true, Box::new(NoopSpawnLifecycle), remote_test_env.environment(), ) @@ -541,7 +575,7 @@ async fn unified_exec_uses_remote_exec_server_when_configured() -> anyhow::Resul &output_closed, &output_closed_notify, &cancellation_token, - None, + /*pause_state*/ None, Instant::now() + Duration::from_millis(2_500), ) .await; @@ -571,9 +605,9 @@ async fn remote_exec_server_rejects_inherited_fd_launches() -> anyhow::Result<() let manager = UnifiedExecProcessManager::default(); let err = manager .open_session_with_exec_env( - 1234, + /*process_id*/ 1234, &request, - true, + /*tty*/ true, Box::new(TestSpawnLifecycle { inherited_fds: vec![42], }), diff --git a/codex-rs/core/src/unified_exec/process_manager_tests.rs b/codex-rs/core/src/unified_exec/process_manager_tests.rs index 112fcd37c..6897f4a5f 100644 --- a/codex-rs/core/src/unified_exec/process_manager_tests.rs +++ b/codex-rs/core/src/unified_exec/process_manager_tests.rs @@ -36,7 +36,7 @@ fn unified_exec_env_overrides_existing_values() { #[test] fn exec_server_process_id_matches_unified_exec_process_id() { - assert_eq!(exec_server_process_id(4321), "4321"); + assert_eq!(exec_server_process_id(/*process_id*/ 4321), "4321"); } #[test] diff --git a/codex-rs/core/src/util_tests.rs b/codex-rs/core/src/util_tests.rs index d1291774c..61bf70284 100644 --- a/codex-rs/core/src/util_tests.rs +++ b/codex-rs/core/src/util_tests.rs @@ -232,9 +232,9 @@ fn emit_feedback_auth_recovery_tags_clears_stale_401_fields() { "done", "recovery_not_run", Some("req-401-b"), - None, - None, - None, + /*auth_cf_ray*/ None, + /*auth_error*/ None, + /*auth_error_code*/ None, ); let tags = tags.lock().unwrap().clone(); @@ -440,7 +440,7 @@ fn resume_command_prefers_name_over_id() { #[test] fn resume_command_with_only_id() { let thread_id = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap(); - let command = resume_command(None, Some(thread_id)); + let command = resume_command(/*thread_name*/ None, Some(thread_id)); assert_eq!( command, Some("codex resume 123e4567-e89b-12d3-a456-426614174000".to_string()) @@ -449,21 +449,21 @@ fn resume_command_with_only_id() { #[test] fn resume_command_with_no_name_or_id() { - let command = resume_command(None, None); + let command = resume_command(/*thread_name*/ None, /*thread_id*/ None); assert_eq!(command, None); } #[test] fn resume_command_quotes_thread_name_when_needed() { - let command = resume_command(Some("-starts-with-dash"), None); + let command = resume_command(Some("-starts-with-dash"), /*thread_id*/ None); assert_eq!( command, Some("codex resume -- -starts-with-dash".to_string()) ); - let command = resume_command(Some("two words"), None); + let command = resume_command(Some("two words"), /*thread_id*/ None); assert_eq!(command, Some("codex resume 'two words'".to_string())); - let command = resume_command(Some("quote'case"), None); + let command = resume_command(Some("quote'case"), /*thread_id*/ None); assert_eq!(command, Some("codex resume \"quote'case\"".to_string())); } diff --git a/codex-rs/core/src/windows_sandbox_tests.rs b/codex-rs/core/src/windows_sandbox_tests.rs index cc41dfa4c..d0ffa07b8 100644 --- a/codex-rs/core/src/windows_sandbox_tests.rs +++ b/codex-rs/core/src/windows_sandbox_tests.rs @@ -52,8 +52,11 @@ fn elevated_wins_when_both_flags_are_enabled() { #[test] fn legacy_mode_prefers_elevated() { let mut entries = BTreeMap::new(); - entries.insert("experimental_windows_sandbox".to_string(), true); - entries.insert("elevated_windows_sandbox".to_string(), true); + entries.insert( + "experimental_windows_sandbox".to_string(), + /*value*/ true, + ); + entries.insert("elevated_windows_sandbox".to_string(), /*value*/ true); assert_eq!( legacy_windows_sandbox_mode_from_entries(&entries), @@ -64,7 +67,10 @@ fn legacy_mode_prefers_elevated() { #[test] fn legacy_mode_supports_alias_key() { let mut entries = BTreeMap::new(); - entries.insert("enable_experimental_windows_sandbox".to_string(), true); + entries.insert( + "enable_experimental_windows_sandbox".to_string(), + /*value*/ true, + ); assert_eq!( legacy_windows_sandbox_mode_from_entries(&entries), @@ -98,7 +104,10 @@ fn resolve_windows_sandbox_mode_prefers_profile_windows() { #[test] fn resolve_windows_sandbox_mode_falls_back_to_legacy_keys() { let mut entries = BTreeMap::new(); - entries.insert("experimental_windows_sandbox".to_string(), true); + entries.insert( + "experimental_windows_sandbox".to_string(), + /*value*/ true, + ); let cfg = ConfigToml { features: Some(FeaturesToml { entries }), ..Default::default() @@ -113,7 +122,10 @@ fn resolve_windows_sandbox_mode_falls_back_to_legacy_keys() { #[test] fn resolve_windows_sandbox_mode_profile_legacy_false_blocks_top_level_legacy_true() { let mut profile_entries = BTreeMap::new(); - profile_entries.insert("experimental_windows_sandbox".to_string(), false); + profile_entries.insert( + "experimental_windows_sandbox".to_string(), + /*value*/ false, + ); let profile = ConfigProfile { features: Some(FeaturesToml { entries: profile_entries, @@ -122,7 +134,10 @@ fn resolve_windows_sandbox_mode_profile_legacy_false_blocks_top_level_legacy_tru }; let mut cfg_entries = BTreeMap::new(); - cfg_entries.insert("experimental_windows_sandbox".to_string(), true); + cfg_entries.insert( + "experimental_windows_sandbox".to_string(), + /*value*/ true, + ); let cfg = ConfigToml { features: Some(FeaturesToml { entries: cfg_entries, diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index 823057797..515d07f20 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -77,24 +77,24 @@ async fn responses_stream_includes_subagent_header_on_review() { conversation_id, model.as_str(), model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), Some(auth_mode), "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), session_source.clone(), ); let client = ModelClient::new( - None, + /*auth_manager*/ None, conversation_id, provider.clone(), session_source, config.model_verbosity, - false, - false, - None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ); let mut client_session = client.new_session(); @@ -116,8 +116,8 @@ async fn responses_stream_includes_subagent_header_on_review() { &session_telemetry, effort, summary.unwrap_or(model_info.default_reasoning_summary), - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("stream failed"); @@ -190,24 +190,24 @@ async fn responses_stream_includes_subagent_header_on_other() { conversation_id, model.as_str(), model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), Some(auth_mode), "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), session_source.clone(), ); let client = ModelClient::new( - None, + /*auth_manager*/ None, conversation_id, provider.clone(), session_source, config.model_verbosity, - false, - false, - None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ); let mut client_session = client.new_session(); @@ -229,8 +229,8 @@ async fn responses_stream_includes_subagent_header_on_other() { &session_telemetry, effort, summary.unwrap_or(model_info.default_reasoning_summary), - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("stream failed"); @@ -302,24 +302,24 @@ async fn responses_respects_model_info_overrides_from_config() { conversation_id, model.as_str(), model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), auth_mode, "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), session_source.clone(), ); let client = ModelClient::new( - None, + /*auth_manager*/ None, conversation_id, provider.clone(), session_source, config.model_verbosity, - false, - false, - None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ); let mut client_session = client.new_session(); @@ -341,8 +341,8 @@ async fn responses_respects_model_info_overrides_from_config() { &session_telemetry, effort, summary.unwrap_or(model_info.default_reasoning_summary), - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("stream failed"); diff --git a/codex-rs/core/tests/suite/agent_jobs.rs b/codex-rs/core/tests/suite/agent_jobs.rs index 75204a865..b275b1878 100644 --- a/codex-rs/core/tests/suite/agent_jobs.rs +++ b/codex-rs/core/tests/suite/agent_jobs.rs @@ -268,7 +268,7 @@ async fn report_agent_job_result_rejects_wrong_thread() -> Result<()> { .expect("job_id from csv"); let job = db.get_agent_job(job_id.as_str()).await?.expect("job"); let items = db - .list_agent_job_items(job.id.as_str(), None, Some(10)) + .list_agent_job_items(job.id.as_str(), /*status*/ None, Some(10)) .await?; let item = items.first().expect("item"); let wrong_thread_id = "00000000-0000-0000-0000-000000000000"; diff --git a/codex-rs/core/tests/suite/agent_websocket.rs b/codex-rs/core/tests/suite/agent_websocket.rs index 5c1c5bd07..fb0cd8412 100644 --- a/codex-rs/core/tests/suite/agent_websocket.rs +++ b/codex-rs/core/tests/suite/agent_websocket.rs @@ -273,7 +273,10 @@ async fn websocket_v2_first_turn_uses_updated_fast_tier_after_startup_prewarm() }); let test = builder.build_with_websocket_server(&server).await?; - let warmup = server.wait_for_request(0, 0).await.body_json(); + let warmup = server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 0) + .await + .body_json(); assert_eq!(warmup["type"].as_str(), Some("response.create")); assert_eq!(warmup["generate"].as_bool(), Some(false)); assert_eq!(warmup.get("service_tier"), None); @@ -326,12 +329,16 @@ async fn websocket_v2_first_turn_drops_fast_tier_after_startup_prewarm() -> Resu }); let test = builder.build_with_websocket_server(&server).await?; - let warmup = server.wait_for_request(0, 0).await.body_json(); + let warmup = server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 0) + .await + .body_json(); assert_eq!(warmup["type"].as_str(), Some("response.create")); assert_eq!(warmup["generate"].as_bool(), Some(false)); assert_eq!(warmup["service_tier"].as_str(), Some("priority")); - test.submit_turn_with_service_tier("hello", None).await?; + test.submit_turn_with_service_tier("hello", /*service_tier*/ None) + .await?; assert_eq!(server.handshakes().len(), 1); let connection = server.single_connection(); @@ -382,14 +389,18 @@ async fn websocket_v2_next_turn_uses_updated_service_tier() -> Result<()> { }); let test = builder.build_with_websocket_server(&server).await?; - let warmup = server.wait_for_request(0, 0).await.body_json(); + let warmup = server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 0) + .await + .body_json(); assert_eq!(warmup["type"].as_str(), Some("response.create")); assert_eq!(warmup["generate"].as_bool(), Some(false)); assert_eq!(warmup.get("service_tier"), None); test.submit_turn_with_service_tier("first", Some(ServiceTier::Fast)) .await?; - test.submit_turn_with_service_tier("second", None).await?; + test.submit_turn_with_service_tier("second", /*service_tier*/ None) + .await?; assert_eq!(server.handshakes().len(), 1); let connection = server.single_connection(); diff --git a/codex-rs/core/tests/suite/approvals.rs b/codex-rs/core/tests/suite/approvals.rs index 1a7183a68..f7874eaf4 100644 --- a/codex-rs/core/tests/suite/approvals.rs +++ b/codex-rs/core/tests/suite/approvals.rs @@ -131,7 +131,12 @@ impl ActionKind { "from pathlib import Path; path = Path({path_str:?}); content = {content:?}; path.write_text(content, encoding='utf-8'); print(path.read_text(encoding='utf-8'), end='')", ); let command = format!("python3 -c {script:?}"); - let event = shell_event(call_id, &command, 5_000, sandbox_permissions)?; + let event = shell_event( + call_id, + &command, + /*timeout_ms*/ 5_000, + sandbox_permissions, + )?; Ok((event, Some(command))) } ActionKind::FetchUrl { @@ -153,7 +158,12 @@ impl ActionKind { ); let command = format!("python3 -c \"{script}\""); - let event = shell_event(call_id, &command, 5_000, sandbox_permissions)?; + let event = shell_event( + call_id, + &command, + /*timeout_ms*/ 5_000, + sandbox_permissions, + )?; Ok((event, Some(command))) } ActionKind::FetchUrlNoProxy { @@ -175,11 +185,21 @@ impl ActionKind { ); let command = format!("python3 -c \"{script}\""); - let event = shell_event(call_id, &command, 5_000, sandbox_permissions)?; + let event = shell_event( + call_id, + &command, + /*timeout_ms*/ 5_000, + sandbox_permissions, + )?; Ok((event, Some(command))) } ActionKind::RunCommand { command } => { - let event = shell_event(call_id, command, 2_000, sandbox_permissions)?; + let event = shell_event( + call_id, + command, + /*timeout_ms*/ 2_000, + sandbox_permissions, + )?; Ok((event, Some(command.to_string()))) } ActionKind::RunUnifiedExecCommand { @@ -206,7 +226,12 @@ impl ActionKind { let _ = fs::remove_file(&path); let patch = build_add_file_patch(&patch_path, content); let command = shell_apply_patch_command(&patch); - let event = shell_event(call_id, &command, 5_000, sandbox_permissions)?; + let event = shell_event( + call_id, + &command, + /*timeout_ms*/ 5_000, + sandbox_permissions, + )?; Ok((event, Some(command))) } } @@ -233,7 +258,13 @@ fn shell_event( timeout_ms: u64, sandbox_permissions: SandboxPermissions, ) -> Result { - shell_event_with_prefix_rule(call_id, command, timeout_ms, sandbox_permissions, None) + shell_event_with_prefix_rule( + call_id, + command, + timeout_ms, + sandbox_permissions, + /*prefix_rule*/ None, + ) } fn shell_event_with_prefix_rule( @@ -2259,7 +2290,12 @@ async fn matched_prefix_rule_runs_unsandboxed_under_zsh_fork() -> Result<()> { .await?; let call_id = "zsh-fork-prefix-rule-unsandboxed"; - let event = shell_event(call_id, &command, 1_000, SandboxPermissions::UseDefault)?; + let event = shell_event( + call_id, + &command, + /*timeout_ms*/ 1_000, + SandboxPermissions::UseDefault, + )?; let _ = mount_sse_once( &server, sse(vec![ @@ -2318,7 +2354,7 @@ async fn invalid_requested_prefix_rule_falls_back_for_compound_command() -> Resu let event = shell_event_with_prefix_rule( call_id, command, - 1_000, + /*timeout_ms*/ 1_000, SandboxPermissions::RequireEscalated, Some(vec!["touch".to_string()]), )?; @@ -2369,7 +2405,7 @@ async fn approving_fallback_rule_for_compound_command_works() -> Result<()> { let event = shell_event_with_prefix_rule( call_id, command, - 1_000, + /*timeout_ms*/ 1_000, SandboxPermissions::RequireEscalated, Some(vec!["touch".to_string()]), )?; @@ -2416,7 +2452,7 @@ async fn approving_fallback_rule_for_compound_command_works() -> Result<()> { let event = shell_event_with_prefix_rule( call_id, command, - 1_000, + /*timeout_ms*/ 1_000, SandboxPermissions::RequireEscalated, Some(vec!["touch".to_string()]), )?; @@ -2498,7 +2534,10 @@ allow_local_binding = true config.permissions.sandbox_policy = Constrained::allow_any(sandbox_policy_for_config); let layers = config .config_layer_stack - .get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, true) + .get_layers( + ConfigLayerStackOrdering::LowestPrecedenceFirst, + /*include_disabled*/ true, + ) .into_iter() .cloned() .collect(); @@ -2542,7 +2581,7 @@ allow_local_binding = true let first_event = shell_event( call_id_first, &fetch_command, - 30_000, + /*timeout_ms*/ 30_000, SandboxPermissions::UseDefault, )?; @@ -2682,7 +2721,7 @@ allow_local_binding = true let second_event = shell_event( call_id_second, &fetch_command, - 30_000, + /*timeout_ms*/ 30_000, SandboxPermissions::UseDefault, )?; diff --git a/codex-rs/core/tests/suite/auth_refresh.rs b/codex-rs/core/tests/suite/auth_refresh.rs index c5302bbac..bdac334a6 100644 --- a/codex-rs/core/tests/suite/auth_refresh.rs +++ b/codex-rs/core/tests/suite/auth_refresh.rs @@ -960,7 +960,7 @@ impl RefreshTokenTestContext { let auth_manager = AuthManager::shared( codex_home.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, ); diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index e0e265666..9be02cf97 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -718,7 +718,8 @@ async fn chatgpt_auth_sends_correct_request() { ) .await; - let mut model_provider = built_in_model_providers(/* openai_base_url */ None)["openai"].clone(); + let mut model_provider = + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone(); model_provider.base_url = Some(format!("{}/api/codex", server.uri())); model_provider.supports_websockets = false; let mut builder = test_codex() @@ -796,7 +797,7 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() { let model_provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), supports_websockets: false, - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; // Init session @@ -1825,24 +1826,24 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() { conversation_id, model.as_str(), model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), auth_manager.auth_mode().map(TelemetryAuthMode::from), "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), SessionSource::Exec, ); let client = ModelClient::new( - None, + /*auth_manager*/ None, conversation_id, provider.clone(), SessionSource::Exec, config.model_verbosity, - false, - false, - None, + /*enable_request_compression*/ false, + /*include_timing_metrics*/ false, + /*beta_features_header*/ None, ); let mut client_session = client.new_session(); @@ -1917,8 +1918,8 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() { &session_telemetry, effort, summary.unwrap_or(ReasoningSummary::Auto), - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("responses stream to start"); @@ -1957,7 +1958,10 @@ async fn token_count_includes_rate_limits_snapshot() { skip_if_no_network!(); let server = MockServer::start().await; - let sse_body = sse(vec![ev_completed_with_tokens("resp_rate", 123)]); + let sse_body = sse(vec![ev_completed_with_tokens( + "resp_rate", + /*total_tokens*/ 123, + )]); let response = ResponseTemplate::new(200) .insert_header("content-type", "text/event-stream") @@ -1976,7 +1980,8 @@ async fn token_count_includes_rate_limits_snapshot() { .mount(&server) .await; - let mut provider = built_in_model_providers(/* openai_base_url */ None)["openai"].clone(); + let mut provider = + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone(); provider.base_url = Some(format!("{}/v1", server.uri())); provider.supports_websockets = false; diff --git a/codex-rs/core/tests/suite/client_websockets.rs b/codex-rs/core/tests/suite/client_websockets.rs index b568c6aee..1f94330cb 100755 --- a/codex-rs/core/tests/suite/client_websockets.rs +++ b/codex-rs/core/tests/suite/client_websockets.rs @@ -139,7 +139,7 @@ async fn responses_websocket_streams_without_feature_flag_when_provider_supports ]]]) .await; - let harness = websocket_harness_with_options(&server, false).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ false).await; let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); @@ -292,7 +292,7 @@ async fn responses_websocket_request_prewarm_reuses_connection() { ]]) .await; - let harness = websocket_harness_with_options(&server, true).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ true).await; let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); client_session @@ -302,8 +302,8 @@ async fn responses_websocket_request_prewarm_reuses_connection() { &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket prewarm failed"); @@ -383,8 +383,8 @@ async fn responses_websocket_preconnect_is_reused_even_with_header_changes() { &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -411,7 +411,7 @@ async fn responses_websocket_request_prewarm_is_reused_even_with_header_changes( ]]) .await; - let harness = websocket_harness_with_options(&server, true).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ true).await; let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); client_session @@ -421,8 +421,8 @@ async fn responses_websocket_request_prewarm_is_reused_even_with_header_changes( &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket prewarm failed"); @@ -433,8 +433,8 @@ async fn responses_websocket_request_prewarm_is_reused_even_with_header_changes( &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -476,7 +476,7 @@ async fn responses_websocket_prewarm_uses_v2_when_provider_supports_websockets() ]]]) .await; - let harness = websocket_harness_with_options(&server, false).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ false).await; let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); client_session @@ -486,8 +486,8 @@ async fn responses_websocket_prewarm_uses_v2_when_provider_supports_websockets() &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket prewarm failed"); @@ -533,7 +533,7 @@ async fn responses_websocket_preconnect_runs_when_only_v2_feature_enabled() { ]]]) .await; - let harness = websocket_harness_with_options(&server, true).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ true).await; let mut client_session = harness.client.new_session(); client_session .preconnect_websocket(&harness.session_telemetry, &harness.model_info) @@ -576,7 +576,7 @@ async fn responses_websocket_v2_requests_use_v2_when_provider_supports_websocket ]]) .await; - let harness = websocket_harness_with_options(&server, true).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ true).await; let mut client_session = harness.client.new_session(); let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![ @@ -625,7 +625,7 @@ async fn responses_websocket_v2_incremental_requests_are_reused_across_turns() { ]]) .await; - let harness = websocket_harness_with_options(&server, false).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ false).await; let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![ message_item("hello"), @@ -669,7 +669,7 @@ async fn responses_websocket_v2_wins_when_both_features_enabled() { ]]) .await; - let harness = websocket_harness_with_options(&server, false).await; + let harness = websocket_harness_with_options(&server, /*runtime_metrics_enabled*/ false).await; let mut client_session = harness.client.new_session(); let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![ @@ -757,7 +757,8 @@ async fn responses_websocket_includes_timing_metrics_header_when_runtime_metrics ]]]) .await; - let harness = websocket_harness_with_runtime_metrics(&server, true).await; + let harness = + websocket_harness_with_runtime_metrics(&server, /*runtime_metrics_enabled*/ true).await; harness.session_telemetry.reset_runtime_metrics(); let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); @@ -795,7 +796,8 @@ async fn responses_websocket_omits_timing_metrics_header_when_runtime_metrics_di ]]]) .await; - let harness = websocket_harness_with_runtime_metrics(&server, false).await; + let harness = + websocket_harness_with_runtime_metrics(&server, /*runtime_metrics_enabled*/ false).await; let mut client_session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); @@ -833,8 +835,8 @@ async fn responses_websocket_emits_reasoning_included_event() { &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -906,8 +908,8 @@ async fn responses_websocket_emits_rate_limit_events() { &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -1213,7 +1215,7 @@ async fn responses_websocket_forwards_turn_metadata_on_initial_and_incremental_c &mut client_session, &harness, &prompt_one, - None, + /*service_tier*/ None, Some(first_turn_metadata), ) .await; @@ -1221,7 +1223,7 @@ async fn responses_websocket_forwards_turn_metadata_on_initial_and_incremental_c &mut client_session, &harness, &prompt_two, - None, + /*service_tier*/ None, Some(enriched_turn_metadata), ) .await; @@ -1381,7 +1383,7 @@ async fn responses_websocket_v2_creates_with_previous_response_id_on_prefix() { ]]) .await; - let harness = websocket_harness_with_v2(&server, true).await; + let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await; let mut session = harness.client.new_session(); let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![ @@ -1420,7 +1422,7 @@ async fn responses_websocket_v2_creates_without_previous_response_id_when_non_in ]]) .await; - let harness = websocket_harness_with_v2(&server, true).await; + let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await; let mut session = harness.client.new_session(); let prompt_one = prompt_with_input_and_instructions(vec![message_item("hello")], "base instructions one"); @@ -1467,7 +1469,7 @@ async fn responses_websocket_v2_after_error_uses_full_create_without_previous_re ]) .await; - let harness = websocket_harness_with_v2(&server, true).await; + let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await; let mut session = harness.client.new_session(); let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![message_item("hello"), message_item("second")]); @@ -1486,8 +1488,8 @@ async fn responses_websocket_v2_after_error_uses_full_create_without_previous_re &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -1559,7 +1561,7 @@ async fn responses_websocket_v2_surfaces_terminal_error_without_close_handshake( }]) .await; - let harness = websocket_harness_with_v2(&server, true).await; + let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await; let mut session = harness.client.new_session(); let prompt_one = prompt_with_input(vec![message_item("hello")]); let prompt_two = prompt_with_input(vec![message_item("hello"), message_item("second")]); @@ -1573,8 +1575,8 @@ async fn responses_websocket_v2_surfaces_terminal_error_without_close_handshake( &harness.session_telemetry, harness.effort, harness.summary, - None, - None, + /*service_tier*/ None, + /*turn_metadata_header*/ None, ) .await .expect("websocket stream failed"); @@ -1605,7 +1607,7 @@ async fn responses_websocket_v2_sets_openai_beta_header() { ]]]) .await; - let harness = websocket_harness_with_v2(&server, true).await; + let harness = websocket_harness_with_v2(&server, /*runtime_metrics_enabled*/ true).await; let mut session = harness.client.new_session(); let prompt = prompt_with_input(vec![message_item("hello")]); @@ -1659,7 +1661,7 @@ fn prompt_with_input_and_instructions(input: Vec, instructions: &s } fn websocket_provider(server: &WebSocketTestServer) -> ModelProviderInfo { - websocket_provider_with_connect_timeout(server, None) + websocket_provider_with_connect_timeout(server, /*websocket_connect_timeout_ms*/ None) } fn websocket_provider_with_connect_timeout( @@ -1686,7 +1688,7 @@ fn websocket_provider_with_connect_timeout( } async fn websocket_harness(server: &WebSocketTestServer) -> WebsocketTestHarness { - websocket_harness_with_runtime_metrics(server, false).await + websocket_harness_with_runtime_metrics(server, /*runtime_metrics_enabled*/ false).await } async fn websocket_harness_with_runtime_metrics( @@ -1739,11 +1741,11 @@ async fn websocket_harness_with_provider_options( conversation_id, MODEL, model_info.slug.as_str(), - None, + /*account_id*/ None, Some("test@test.com".to_string()), auth_manager.auth_mode().map(TelemetryAuthMode::from), "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), SessionSource::Exec, ) @@ -1751,14 +1753,14 @@ async fn websocket_harness_with_provider_options( let effort = None; let summary = ReasoningSummary::Auto; let client = ModelClient::new( - None, + /*auth_manager*/ None, conversation_id, provider.clone(), SessionSource::Exec, config.model_verbosity, - false, + /*enable_request_compression*/ false, runtime_metrics_enabled, - None, + /*beta_features_header*/ None, ); WebsocketTestHarness { @@ -1777,7 +1779,13 @@ async fn stream_until_complete( harness: &WebsocketTestHarness, prompt: &Prompt, ) { - stream_until_complete_with_service_tier(client_session, harness, prompt, None).await; + stream_until_complete_with_service_tier( + client_session, + harness, + prompt, + /*service_tier*/ None, + ) + .await; } async fn stream_until_complete_with_service_tier( @@ -1786,8 +1794,14 @@ async fn stream_until_complete_with_service_tier( prompt: &Prompt, service_tier: Option, ) { - stream_until_complete_with_turn_metadata(client_session, harness, prompt, service_tier, None) - .await; + stream_until_complete_with_turn_metadata( + client_session, + harness, + prompt, + service_tier, + /*turn_metadata_header*/ None, + ) + .await; } async fn stream_until_complete_with_turn_metadata( diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index ae38261f1..9b69149e9 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -252,7 +252,7 @@ async fn code_mode_can_return_exec_command_output() -> Result<()> { r#" text(JSON.stringify(await tools.exec_command({ cmd: "printf code_mode_exec_marker" }))); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -264,9 +264,9 @@ text(JSON.stringify(await tools.exec_command({ cmd: "printf code_mode_exec_marke r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); - let parsed: Value = serde_json::from_str(text_item(&items, 1))?; + let parsed: Value = serde_json::from_str(text_item(&items, /*index*/ 1))?; assert!( parsed .get("chunk_id") @@ -378,7 +378,7 @@ const result = await tools.update_plan({ }); text(JSON.stringify(result)); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -483,7 +483,7 @@ text(JSON.stringify(results)); .expect("parallel code mode run should send a completion request"); let items = custom_tool_output_items(&req, "call-1"); assert_eq!(items.len(), 2); - assert_eq!(text_item(&items, 1), "[\"ok\",\"ok\"]"); + assert_eq!(text_item(&items, /*index*/ 1), "[\"ok\",\"ok\"]"); Ok(()) } @@ -503,7 +503,7 @@ text(JSON.stringify(await tools.exec_command({ max_output_tokens: 100 }))); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -515,7 +515,7 @@ text(JSON.stringify(await tools.exec_command({ r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); let expected_pattern = r#"(?sx) \A @@ -524,7 +524,7 @@ Total\ output\ lines:\ 1\n .*…\d+\ tokens\ truncated….* \z "#; - assert_regex_match(expected_pattern, text_item(&items, 1)); + assert_regex_match(expected_pattern, text_item(&items, /*index*/ 1)); Ok(()) } @@ -542,7 +542,7 @@ text("before crash"); text("still before crash"); throw new Error("boom"); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -554,10 +554,10 @@ throw new Error("boom"); r"(?s)\A", r"Script failed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); - assert_eq!(text_item(&items, 1), "before crash"); - assert_eq!(text_item(&items, 2), "still before crash"); + assert_eq!(text_item(&items, /*index*/ 1), "before crash"); + assert_eq!(text_item(&items, /*index*/ 2), "still before crash"); assert_regex_match( r#"(?sx) \A @@ -566,7 +566,7 @@ Error:\ boom\n (?:\s+at\ .+\n?)+ \z "#, - text_item(&items, 3), + text_item(&items, /*index*/ 3), ); Ok(()) @@ -589,7 +589,7 @@ try { text(`caught:${error?.message ?? String(error)}`); } "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -666,10 +666,10 @@ text("phase 3"); r"(?s)\A", r"Script running with cell ID \d+\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&first_items, 0), + text_item(&first_items, /*index*/ 0), ); - assert_eq!(text_item(&first_items, 1), "phase 1"); - let cell_id = extract_running_cell_id(text_item(&first_items, 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "phase 1"); + let cell_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); responses::mount_sse_once( &server, @@ -707,13 +707,13 @@ text("phase 3"); r"(?s)\A", r"Script running with cell ID \d+\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&second_items, 0), + text_item(&second_items, /*index*/ 0), ); assert_eq!( - extract_running_cell_id(text_item(&second_items, 0)), + extract_running_cell_id(text_item(&second_items, /*index*/ 0)), cell_id ); - assert_eq!(text_item(&second_items, 1), "phase 2"); + assert_eq!(text_item(&second_items, /*index*/ 1), "phase 2"); responses::mount_sse_once( &server, @@ -751,9 +751,9 @@ text("phase 3"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&third_items, 0), + text_item(&third_items, /*index*/ 0), ); - assert_eq!(text_item(&third_items, 1), "phase 3"); + assert_eq!(text_item(&third_items, /*index*/ 1), "phase 3"); Ok(()) } @@ -806,10 +806,10 @@ while (true) {} r"(?s)\A", r"Script running with cell ID \d+\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&first_items, 0), + text_item(&first_items, /*index*/ 0), ); - assert_eq!(text_item(&first_items, 1), "phase 1"); - let cell_id = extract_running_cell_id(text_item(&first_items, 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "phase 1"); + let cell_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); responses::mount_sse_once( &server, @@ -846,7 +846,7 @@ while (true) {} r"(?s)\A", r"Script terminated\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&second_items, 0), + text_item(&second_items, /*index*/ 0), ); Ok(()) @@ -907,8 +907,8 @@ text("session b done"); let first_request = first_completion.single_request(); let first_items = custom_tool_output_items(&first_request, "call-1"); assert_eq!(first_items.len(), 2); - let session_a_id = extract_running_cell_id(text_item(&first_items, 0)); - assert_eq!(text_item(&first_items, 1), "session a start"); + let session_a_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "session a start"); responses::mount_sse_once( &server, @@ -933,8 +933,8 @@ text("session b done"); let second_request = second_completion.single_request(); let second_items = custom_tool_output_items(&second_request, "call-2"); assert_eq!(second_items.len(), 2); - let session_b_id = extract_running_cell_id(text_item(&second_items, 0)); - assert_eq!(text_item(&second_items, 1), "session b start"); + let session_b_id = extract_running_cell_id(text_item(&second_items, /*index*/ 0)); + assert_eq!(text_item(&second_items, /*index*/ 1), "session b start"); assert_ne!(session_a_id, session_b_id); fs::write(&session_a_gate, "ready")?; @@ -973,9 +973,9 @@ text("session b done"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&third_items, 0), + text_item(&third_items, /*index*/ 0), ); - assert_eq!(text_item(&third_items, 1), "session a done"); + assert_eq!(text_item(&third_items, /*index*/ 1), "session a done"); fs::write(&session_b_gate, "ready")?; responses::mount_sse_once( @@ -1013,9 +1013,9 @@ text("session b done"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&fourth_items, 0), + text_item(&fourth_items, /*index*/ 0), ); - assert_eq!(text_item(&fourth_items, 1), "session b done"); + assert_eq!(text_item(&fourth_items, /*index*/ 1), "session b done"); Ok(()) } @@ -1065,8 +1065,8 @@ text("phase 2"); let first_request = first_completion.single_request(); let first_items = custom_tool_output_items(&first_request, "call-1"); assert_eq!(first_items.len(), 2); - let cell_id = extract_running_cell_id(text_item(&first_items, 0)); - assert_eq!(text_item(&first_items, 1), "phase 1"); + let cell_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "phase 1"); responses::mount_sse_once( &server, @@ -1103,7 +1103,7 @@ text("phase 2"); r"(?s)\A", r"Script terminated\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&second_items, 0), + text_item(&second_items, /*index*/ 0), ); responses::mount_sse_once( @@ -1140,9 +1140,9 @@ text("after terminate"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&third_items, 0), + text_item(&third_items, /*index*/ 0), ); - assert_eq!(text_item(&third_items, 1), "after terminate"); + assert_eq!(text_item(&third_items, /*index*/ 1), "after terminate"); Ok(()) } @@ -1197,10 +1197,10 @@ async fn code_mode_wait_returns_error_for_unknown_session() -> Result<()> { r"(?s)\A", r"Script failed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); assert_eq!( - text_item(&items, 1), + text_item(&items, /*index*/ 1), "Script error:\nexec cell 999999 not found" ); @@ -1268,8 +1268,8 @@ text("session b done"); let first_request = first_completion.single_request(); let first_items = custom_tool_output_items(&first_request, "call-1"); assert_eq!(first_items.len(), 2); - let session_a_id = extract_running_cell_id(text_item(&first_items, 0)); - assert_eq!(text_item(&first_items, 1), "session a start"); + let session_a_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "session a start"); responses::mount_sse_once( &server, @@ -1294,8 +1294,8 @@ text("session b done"); let second_request = second_completion.single_request(); let second_items = custom_tool_output_items(&second_request, "call-2"); assert_eq!(second_items.len(), 2); - let session_b_id = extract_running_cell_id(text_item(&second_items, 0)); - assert_eq!(text_item(&second_items, 1), "session b start"); + let session_b_id = extract_running_cell_id(text_item(&second_items, /*index*/ 0)); + assert_eq!(text_item(&second_items, /*index*/ 1), "session b start"); fs::write(&session_a_gate, "ready")?; responses::mount_sse_once( @@ -1333,10 +1333,10 @@ text("session b done"); r"(?s)\A", r"Script running with cell ID \d+\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&third_items, 0), + text_item(&third_items, /*index*/ 0), ); assert_eq!( - extract_running_cell_id(text_item(&third_items, 0)), + extract_running_cell_id(text_item(&third_items, /*index*/ 0)), session_b_id ); @@ -1384,7 +1384,7 @@ text("session b done"); r"(?s)\A", r"Script terminated\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&fourth_items, 0), + text_item(&fourth_items, /*index*/ 0), ); } 2 => { @@ -1393,9 +1393,9 @@ text("session b done"); r"(?s)\A", r"Script (?:completed|terminated)\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&fourth_items, 0), + text_item(&fourth_items, /*index*/ 0), ); - assert_eq!(text_item(&fourth_items, 1), "session a done"); + assert_eq!(text_item(&fourth_items, /*index*/ 1), "session a done"); } other => panic!("unexpected number of content items: {other}"), } @@ -1455,9 +1455,9 @@ text("after yield"); r"(?s)\A", r"Script running with cell ID \d+\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&first_items, 0), + text_item(&first_items, /*index*/ 0), ); - assert_eq!(text_item(&first_items, 1), "before yield"); + assert_eq!(text_item(&first_items, /*index*/ 1), "before yield"); responses::mount_sse_once( &server, @@ -1541,8 +1541,8 @@ text("token one token two token three token four token five token six token seve let first_request = first_completion.single_request(); let first_items = custom_tool_output_items(&first_request, "call-1"); assert_eq!(first_items.len(), 2); - assert_eq!(text_item(&first_items, 1), "phase 1"); - let cell_id = extract_running_cell_id(text_item(&first_items, 0)); + assert_eq!(text_item(&first_items, /*index*/ 1), "phase 1"); + let cell_id = extract_running_cell_id(text_item(&first_items, /*index*/ 0)); fs::write(&completion_gate, "ready")?; responses::mount_sse_once( @@ -1581,7 +1581,7 @@ text("token one token two token three token four token five token six token seve r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&second_items, 0), + text_item(&second_items, /*index*/ 0), ); let expected_pattern = r#"(?sx) \A @@ -1590,7 +1590,7 @@ Total\ output\ lines:\ 1\n .*…\d+\ tokens\ truncated….* \z "#; - assert_regex_match(expected_pattern, text_item(&second_items, 1)); + assert_regex_match(expected_pattern, text_item(&second_items, /*index*/ 1)); Ok(()) } @@ -1606,7 +1606,7 @@ async fn code_mode_can_output_serialized_text_via_global_helper() -> Result<()> r#" text({ json: true }); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -1639,7 +1639,7 @@ notify("code_mode_notify_marker"); await tools.test_sync_tool({}); text("done"); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -1677,7 +1677,7 @@ text("before"); exit(); text("after"); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -1695,9 +1695,9 @@ text("after"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); - assert_eq!(text_item(&items, 1), "before"); + assert_eq!(text_item(&items, /*index*/ 1), "before"); assert_eq!(output, "before"); Ok(()) @@ -1716,7 +1716,7 @@ const circular = {}; circular.self = circular; text(circular); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -1736,10 +1736,10 @@ text(circular); r"(?s)\A", r"Script failed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); - assert!(text_item(&items, 1).contains("Script error:")); - assert!(text_item(&items, 1).contains("Converting circular structure to JSON")); + assert!(text_item(&items, /*index*/ 1).contains("Script error:")); + assert!(text_item(&items, /*index*/ 1).contains("Converting circular structure to JSON")); Ok(()) } @@ -1756,7 +1756,7 @@ async fn code_mode_can_output_images_via_global_helper() -> Result<()> { image("https://example.com/image.jpg"); image("data:image/png;base64,AAA"); "#, - false, + /*include_apply_patch*/ false, ) .await?; @@ -1774,7 +1774,7 @@ image("data:image/png;base64,AAA"); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); assert_eq!( items[1], @@ -1857,7 +1857,7 @@ image(out); r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); assert_eq!( @@ -1889,8 +1889,13 @@ async fn code_mode_can_apply_patch_via_nested_tool() -> Result<()> { ); let code = format!("text(await tools.apply_patch({patch:?}));\n"); - let (test, second_mock) = - run_code_mode_turn(&server, "use exec to run apply_patch", &code, true).await?; + let (test, second_mock) = run_code_mode_turn( + &server, + "use exec to run apply_patch", + &code, + /*include_apply_patch*/ true, + ) + .await?; let req = second_mock.single_request(); let items = custom_tool_output_items(&req, "call-1"); @@ -1908,9 +1913,9 @@ async fn code_mode_can_apply_patch_via_nested_tool() -> Result<()> { r"(?s)\A", r"Script completed\nWall time \d+\.\d seconds\nOutput:\n\z" ), - text_item(&items, 0), + text_item(&items, /*index*/ 0), ); - assert_eq!(text_item(&items, 1), "{}"); + assert_eq!(text_item(&items, /*index*/ 1), "{}"); let file_path = test.cwd_path().join(file_name); assert_eq!(fs::read_to_string(&file_path)?, "hello from code_mode\n"); @@ -2183,8 +2188,13 @@ const tool = ALL_TOOLS.find(({ name }) => name === "view_image"); text(JSON.stringify(tool)); "#; - let (_test, second_mock) = - run_code_mode_turn(&server, "use exec to inspect ALL_TOOLS", code, false).await?; + let (_test, second_mock) = run_code_mode_turn( + &server, + "use exec to inspect ALL_TOOLS", + code, + /*include_apply_patch*/ false, + ) + .await?; let req = second_mock.single_request(); let (output, success) = custom_tool_output_body_and_success(&req, "call-1"); @@ -2273,7 +2283,7 @@ async fn code_mode_can_call_hidden_dynamic_tools() -> Result<()> { }), defer_loading: true, }], - false, + /*persist_extended_history*/ false, ) .await?; let mut test = base_test; diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index a54d74011..8be8c72da 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -94,7 +94,8 @@ fn json_fragment(text: &str) -> String { } fn non_openai_model_provider(server: &MockServer) -> ModelProviderInfo { - let mut provider = built_in_model_providers(/* openai_base_url */ None)["openai"].clone(); + let mut provider = + built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone(); provider.name = "OpenAI (test)".into(); provider.base_url = Some(format!("{}/v1", server.uri())); provider.supports_websockets = false; @@ -413,11 +414,11 @@ async fn manual_compact_uses_custom_prompt() { let server = start_mock_server().await; let first_turn = sse(vec![ ev_assistant_message("m0", FIRST_REPLY), - ev_completed_with_tokens("r0", 80), + ev_completed_with_tokens("r0", /*total_tokens*/ 80), ]); let compact_turn = sse(vec![ ev_assistant_message("m1", SUMMARY_TEXT), - ev_completed_with_tokens("r1", 100), + ev_completed_with_tokens("r1", /*total_tokens*/ 100), ]); let request_log = mount_sse_sequence(&server, vec![first_turn, compact_turn]).await; @@ -508,7 +509,7 @@ async fn manual_compact_emits_api_and_local_token_usage_events() { // history. let sse_compact = sse(vec![ ev_assistant_message("m1", SUMMARY_TEXT), - ev_completed_with_tokens("r1", 0), + ev_completed_with_tokens("r1", /*total_tokens*/ 0), ]); mount_sse_once(&server, sse_compact).await; @@ -1211,21 +1212,21 @@ async fn auto_compact_runs_after_token_limit_hit() { let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 70_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = sse(vec![ ev_assistant_message("m2", "SECOND_REPLY"), - ev_completed_with_tokens("r2", 330_000), + ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let sse3 = sse(vec![ ev_assistant_message("m3", AUTO_SUMMARY_TEXT), - ev_completed_with_tokens("r3", 200), + ev_completed_with_tokens("r3", /*total_tokens*/ 200), ]); let sse4 = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 120), + ev_completed_with_tokens("r4", /*total_tokens*/ 120), ]); let prefixed_auto_summary = AUTO_SUMMARY_TEXT; @@ -1404,19 +1405,19 @@ async fn auto_compact_emits_context_compaction_items() { let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 70_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = sse(vec![ ev_assistant_message("m2", "SECOND_REPLY"), - ev_completed_with_tokens("r2", 330_000), + ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let sse3 = sse(vec![ ev_assistant_message("m3", AUTO_SUMMARY_TEXT), - ev_completed_with_tokens("r3", 200), + ev_completed_with_tokens("r3", /*total_tokens*/ 200), ]); let sse4 = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 120), + ev_completed_with_tokens("r4", /*total_tokens*/ 120), ]); mount_sse_sequence(&server, vec![sse1, sse2, sse3, sse4]).await; @@ -1487,19 +1488,19 @@ async fn auto_compact_starts_after_turn_started() { let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 70_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = sse(vec![ ev_assistant_message("m2", "SECOND_REPLY"), - ev_completed_with_tokens("r2", 330_000), + ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let sse3 = sse(vec![ ev_assistant_message("m3", AUTO_SUMMARY_TEXT), - ev_completed_with_tokens("r3", 200), + ev_completed_with_tokens("r3", /*total_tokens*/ 200), ]); let sse4 = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 120), + ev_completed_with_tokens("r4", /*total_tokens*/ 120), ]); mount_sse_sequence(&server, vec![sse1, sse2, sse3, sse4]).await; @@ -1704,8 +1705,8 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() { &server, ModelsResponse { models: vec![ - model_info_with_context_window(previous_model, 273_000), - model_info_with_context_window(next_model, 125_000), + model_info_with_context_window(previous_model, /*context_window*/ 273_000), + model_info_with_context_window(next_model, /*context_window*/ 125_000), ], }, ) @@ -1716,15 +1717,15 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() { vec![ sse(vec![ ev_assistant_message("m1", "before switch"), - ev_completed_with_tokens("r1", 120_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 120_000), ]), sse(vec![ ev_assistant_message("m2", "PRE_SAMPLING_SUMMARY"), - ev_completed_with_tokens("r2", 10), + ev_completed_with_tokens("r2", /*total_tokens*/ 10), ]), sse(vec![ ev_assistant_message("m3", "after switch"), - ev_completed_with_tokens("r3", 100), + ev_completed_with_tokens("r3", /*total_tokens*/ 100), ]), ], ) @@ -1830,8 +1831,8 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() { &server, ModelsResponse { models: vec![ - model_info_with_context_window(previous_model, 273_000), - model_info_with_context_window(next_model, 125_000), + model_info_with_context_window(previous_model, /*context_window*/ 273_000), + model_info_with_context_window(next_model, /*context_window*/ 125_000), ], }, ) @@ -1842,15 +1843,15 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() { vec![ sse(vec![ ev_assistant_message("m1", "before resume"), - ev_completed_with_tokens("r1", 120_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 120_000), ]), sse(vec![ ev_assistant_message("m2", "PRE_SAMPLING_SUMMARY"), - ev_completed_with_tokens("r2", 10), + ev_completed_with_tokens("r2", /*total_tokens*/ 10), ]), sse(vec![ ev_assistant_message("m3", "after resume"), - ev_completed_with_tokens("r3", 100), + ev_completed_with_tokens("r3", /*total_tokens*/ 100), ]), ], ) @@ -1971,22 +1972,22 @@ async fn auto_compact_persists_rollout_entries() { let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 70_000), + ev_completed_with_tokens("r1", /*total_tokens*/ 70_000), ]); let sse2 = sse(vec![ ev_assistant_message("m2", "SECOND_REPLY"), - ev_completed_with_tokens("r2", 330_000), + ev_completed_with_tokens("r2", /*total_tokens*/ 330_000), ]); let auto_summary_payload = auto_summary(AUTO_SUMMARY_TEXT); let sse3 = sse(vec![ ev_assistant_message("m3", &auto_summary_payload), - ev_completed_with_tokens("r3", 200), + ev_completed_with_tokens("r3", /*total_tokens*/ 200), ]); let sse4 = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 120), + ev_completed_with_tokens("r4", /*total_tokens*/ 120), ]); let first_matcher = |req: &wiremock::Request| { @@ -2492,29 +2493,29 @@ async fn auto_compact_allows_multiple_attempts_when_interleaved_with_other_turn_ let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 500), + ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]); let first_summary_payload = auto_summary(FIRST_AUTO_SUMMARY); let sse2 = sse(vec![ ev_assistant_message("m2", &first_summary_payload), - ev_completed_with_tokens("r2", 50), + ev_completed_with_tokens("r2", /*total_tokens*/ 50), ]); let sse3 = sse(vec![ ev_function_call(DUMMY_CALL_ID, DUMMY_FUNCTION_NAME, "{}"), - ev_completed_with_tokens("r3", 150), + ev_completed_with_tokens("r3", /*total_tokens*/ 150), ]); let sse4 = sse(vec![ ev_assistant_message("m4", SECOND_LARGE_REPLY), - ev_completed_with_tokens("r4", 450), + ev_completed_with_tokens("r4", /*total_tokens*/ 450), ]); let second_summary_payload = auto_summary(SECOND_AUTO_SUMMARY); let sse5 = sse(vec![ ev_assistant_message("m5", &second_summary_payload), - ev_completed_with_tokens("r5", 60), + ev_completed_with_tokens("r5", /*total_tokens*/ 60), ]); let sse6 = sse(vec![ ev_assistant_message("m6", FINAL_REPLY), - ev_completed_with_tokens("r6", 120), + ev_completed_with_tokens("r6", /*total_tokens*/ 120), ]); let follow_up_user = "FOLLOW_UP_AUTO_COMPACT"; let final_user = "FINAL_AUTO_COMPACT"; @@ -2612,11 +2613,11 @@ async fn snapshot_request_shape_mid_turn_continuation_compaction() { let auto_summary_payload = auto_summary(AUTO_SUMMARY_TEXT); let auto_compact_turn = sse(vec![ ev_assistant_message("m2", &auto_summary_payload), - ev_completed_with_tokens("r3", 10), + ev_completed_with_tokens("r3", /*total_tokens*/ 10), ]); let post_auto_compact_turn = sse(vec![ ev_assistant_message("m3", FINAL_REPLY), - ev_completed_with_tokens("r4", 10), + ev_completed_with_tokens("r4", /*total_tokens*/ 10), ]); // Mount responses in order and keep mocks only for the ones we assert on. @@ -2716,9 +2717,11 @@ async fn auto_compact_clamps_config_limit_to_context_window() { let auto_summary_payload = auto_summary(AUTO_SUMMARY_TEXT); let auto_compact_turn = sse(vec![ ev_assistant_message("m2", &auto_summary_payload), - ev_completed_with_tokens("r2", 10), + ev_completed_with_tokens("r2", /*total_tokens*/ 10), ]); - let post_auto_compact_turn = sse(vec![ev_completed_with_tokens("r3", 10)]); + let post_auto_compact_turn = sse(vec![ev_completed_with_tokens( + "r3", /*total_tokens*/ 10, + )]); let first_turn_mock = mount_sse_once(&server, first_turn).await; let auto_compact_mock = mount_sse_once(&server, auto_compact_turn).await; @@ -2772,15 +2775,15 @@ async fn auto_compact_counts_encrypted_reasoning_before_last_user() { let first_turn = sse(vec![ ev_reasoning_item("pre-reasoning", &["pre"], &[&pre_last_reasoning_content]), - ev_completed_with_tokens("r1", 10), + ev_completed_with_tokens("r1", /*total_tokens*/ 10), ]); let second_turn = sse(vec![ ev_reasoning_item("post-reasoning", &["post"], &[&post_last_reasoning_content]), - ev_completed_with_tokens("r2", 80), + ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]); let third_turn = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 1), + ev_completed_with_tokens("r4", /*total_tokens*/ 1), ]); let request_log = mount_sse_sequence( @@ -2898,15 +2901,15 @@ async fn auto_compact_runs_when_reasoning_header_clears_between_turns() { let first_turn = sse(vec![ ev_reasoning_item("pre-reasoning", &["pre"], &[&pre_last_reasoning_content]), - ev_completed_with_tokens("r1", 10), + ev_completed_with_tokens("r1", /*total_tokens*/ 10), ]); let second_turn = sse(vec![ ev_reasoning_item("post-reasoning", &["post"], &[&post_last_reasoning_content]), - ev_completed_with_tokens("r2", 80), + ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]); let third_turn = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 1), + ev_completed_with_tokens("r4", /*total_tokens*/ 1), ]); let responses = vec![ @@ -2975,19 +2978,19 @@ async fn snapshot_request_shape_pre_turn_compaction_including_incoming_user_mess let sse1 = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 60), + ev_completed_with_tokens("r1", /*total_tokens*/ 60), ]); let sse2 = sse(vec![ ev_assistant_message("m2", "SECOND_REPLY"), - ev_completed_with_tokens("r2", 500), + ev_completed_with_tokens("r2", /*total_tokens*/ 500), ]); let sse3 = sse(vec![ ev_assistant_message("m3", "PRE_TURN_SUMMARY"), - ev_completed_with_tokens("r3", 100), + ev_completed_with_tokens("r3", /*total_tokens*/ 100), ]); let sse4 = sse(vec![ ev_assistant_message("m4", FINAL_REPLY), - ev_completed_with_tokens("r4", 80), + ev_completed_with_tokens("r4", /*total_tokens*/ 80), ]); let request_log = mount_sse_sequence(&server, vec![sse1, sse2, sse3, sse4]).await; @@ -3100,15 +3103,15 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch vec![ sse(vec![ ev_assistant_message("m1", "BEFORE_SWITCH_REPLY"), - ev_completed_with_tokens("r1", 500), + ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), sse(vec![ ev_assistant_message("m2", "PRETURN_SWITCH_SUMMARY"), - ev_completed_with_tokens("r2", 100), + ev_completed_with_tokens("r2", /*total_tokens*/ 100), ]), sse(vec![ ev_assistant_message("m3", "AFTER_SWITCH_REPLY"), - ev_completed_with_tokens("r3", 100), + ev_completed_with_tokens("r3", /*total_tokens*/ 100), ]), ], ) @@ -3222,7 +3225,7 @@ async fn snapshot_request_shape_pre_turn_compaction_context_window_exceeded() { let first_turn = sse(vec![ ev_assistant_message("m1", FIRST_REPLY), - ev_completed_with_tokens("r1", 500), + ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]); let mut responses = vec![first_turn]; responses.extend( @@ -3309,11 +3312,11 @@ async fn snapshot_request_shape_manual_compact_without_previous_user_messages() let compact_turn = sse(vec![ ev_assistant_message("m1", "MANUAL_EMPTY_SUMMARY"), - ev_completed_with_tokens("r1", 90), + ev_completed_with_tokens("r1", /*total_tokens*/ 90), ]); let follow_up_turn = sse(vec![ ev_assistant_message("m2", FINAL_REPLY), - ev_completed_with_tokens("r2", 80), + ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]); let request_log = mount_sse_sequence(&server, vec![compact_turn, follow_up_turn]).await; diff --git a/codex-rs/core/tests/suite/compact_remote.rs b/codex-rs/core/tests/suite/compact_remote.rs index 96ade23c8..3ab92e773 100644 --- a/codex-rs/core/tests/suite/compact_remote.rs +++ b/codex-rs/core/tests/suite/compact_remote.rs @@ -353,7 +353,7 @@ async fn remote_compact_runs_automatically() -> Result<()> { harness.server(), sse(vec![ responses::ev_shell_command_call("m1", "echo 'hi'"), - responses::ev_completed_with_tokens("resp-1", 100000000), // over token limit + responses::ev_completed_with_tokens("resp-1", /*total_tokens*/ 100000000), // over token limit ]), ) .await; @@ -548,7 +548,10 @@ async fn auto_remote_compact_trims_function_call_history_to_fit_context_window() vec![ sse(vec![ responses::ev_shell_command_call(retained_call_id, retained_command), - responses::ev_completed_with_tokens("retained-call-response", 100), + responses::ev_completed_with_tokens( + "retained-call-response", + /*total_tokens*/ 100, + ), ]), sse(vec![ responses::ev_assistant_message("retained-assistant", "retained complete"), @@ -556,11 +559,14 @@ async fn auto_remote_compact_trims_function_call_history_to_fit_context_window() ]), sse(vec![ responses::ev_shell_command_call(trimmed_call_id, trimmed_command), - responses::ev_completed_with_tokens("trimmed-call-response", 100), + responses::ev_completed_with_tokens( + "trimmed-call-response", + /*total_tokens*/ 100, + ), ]), sse(vec![responses::ev_completed_with_tokens( "trimmed-final-response", - 500_000, + /*total_tokens*/ 500_000, )]), ], ) @@ -672,7 +678,7 @@ async fn auto_remote_compact_failure_stops_agent_loop() -> Result<()> { harness.server(), sse(vec![ responses::ev_assistant_message("initial-assistant", "initial turn complete"), - responses::ev_completed_with_tokens("initial-response", 500_000), + responses::ev_completed_with_tokens("initial-response", /*total_tokens*/ 500_000), ]), ) .await; @@ -1468,11 +1474,11 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_sta vec![ responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -1601,11 +1607,11 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_restates_realtime_end vec![ responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -1686,11 +1692,11 @@ async fn snapshot_request_shape_remote_manual_compact_restates_realtime_start() vec![ responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 60), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 60), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -1776,15 +1782,15 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_does_not_restate_real vec![ responses::sse(vec![ responses::ev_assistant_message("setup", "REMOTE_SETUP_REPLY"), - responses::ev_completed_with_tokens("setup-response", 60), + responses::ev_completed_with_tokens("setup-response", /*total_tokens*/ 60), ]), responses::sse(vec![ responses::ev_function_call("call-remote-mid-turn", DUMMY_FUNCTION_NAME, "{}"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_MID_TURN_FINAL_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -1880,11 +1886,11 @@ async fn snapshot_request_shape_remote_compact_resume_restates_realtime_end() -> vec![ responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 60), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 60), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_AFTER_RESUME_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -1984,15 +1990,15 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_including_incoming_us vec![ responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 60), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 60), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_SECOND_REPLY"), - responses::ev_completed_with_tokens("r2", 500), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 500), ]), responses::sse(vec![ responses::ev_assistant_message("m3", "REMOTE_FINAL_REPLY"), - responses::ev_completed_with_tokens("r3", 80), + responses::ev_completed_with_tokens("r3", /*total_tokens*/ 80), ]), ], ) @@ -2088,7 +2094,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model harness.server(), responses::sse(vec![ responses::ev_assistant_message("m1", "BEFORE_SWITCH_REPLY"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), ) .await; @@ -2096,7 +2102,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model harness.server(), responses::sse(vec![ responses::ev_assistant_message("m2", "AFTER_SWITCH_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ) .await; @@ -2224,7 +2230,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_context_window_exceed harness.server(), vec![responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_FIRST_REPLY"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ])], ) .await; @@ -2243,7 +2249,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_context_window_exceed harness.server(), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_POST_COMPACT_SHOULD_NOT_RUN"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ) .await; @@ -2325,11 +2331,11 @@ async fn snapshot_request_shape_remote_mid_turn_continuation_compaction() -> Res vec![ responses::sse(vec![ responses::ev_function_call("call-remote-mid-turn", DUMMY_FUNCTION_NAME, "{}"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_MID_TURN_FINAL_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ], ) @@ -2394,7 +2400,7 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_summary_only_reinject harness.server(), responses::sse(vec![ responses::ev_function_call("call-remote-summary-only", DUMMY_FUNCTION_NAME, "{}"), - responses::ev_completed_with_tokens("r1", 500), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 500), ]), ) .await; @@ -2402,7 +2408,7 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_summary_only_reinject harness.server(), responses::sse(vec![ responses::ev_assistant_message("m2", "REMOTE_SUMMARY_ONLY_FINAL_REPLY"), - responses::ev_completed_with_tokens("r2", 80), + responses::ev_completed_with_tokens("r2", /*total_tokens*/ 80), ]), ) .await; @@ -2477,7 +2483,7 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_multi_summary_reinjec harness.server(), responses::sse(vec![ responses::ev_assistant_message("setup", "REMOTE_SETUP_REPLY"), - responses::ev_completed_with_tokens("setup-response", 60), + responses::ev_completed_with_tokens("setup-response", /*total_tokens*/ 60), ]), ) .await; @@ -2485,7 +2491,7 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_multi_summary_reinjec harness.server(), responses::sse(vec![ responses::ev_shell_command_call("call-remote-multi-summary", "echo multi-summary"), - responses::ev_completed_with_tokens("r1", 1_000), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 1_000), ]), ) .await; @@ -2580,7 +2586,7 @@ async fn snapshot_request_shape_remote_manual_compact_without_previous_user_mess harness.server(), responses::sse(vec![ responses::ev_assistant_message("m1", "REMOTE_MANUAL_EMPTY_FOLLOW_UP_REPLY"), - responses::ev_completed_with_tokens("r1", 80), + responses::ev_completed_with_tokens("r1", /*total_tokens*/ 80), ]), ) .await; diff --git a/codex-rs/core/tests/suite/compact_resume_fork.rs b/codex-rs/core/tests/suite/compact_resume_fork.rs index 5f01e10d5..3fd0dab04 100644 --- a/codex-rs/core/tests/suite/compact_resume_fork.rs +++ b/codex-rs/core/tests/suite/compact_resume_fork.rs @@ -180,7 +180,7 @@ async fn compact_resume_and_fork_preserve_model_history_view() { "compact+resume test expects resumed path {resumed_path:?} to exist", ); - let forked = fork_thread(&manager, &config, resumed_path, 2).await; + let forked = fork_thread(&manager, &config, resumed_path, /*nth_user_message*/ 2).await; user_turn(&forked, "AFTER_FORK").await; // 3. Capture the requests to the model and validate the history slices. @@ -316,7 +316,7 @@ async fn compact_resume_after_second_compaction_preserves_history() -> Result<() let request_log = mount_second_compact_sequence(&server).await; // 2. Drive the conversation through compact -> resume -> fork -> compact -> resume. - let (_home, config, manager, base) = start_test_conversation(&server, None).await; + let (_home, config, manager, base) = start_test_conversation(&server, /*model*/ None).await; user_turn(&base, "hello world").await; compact_conversation(&base).await; @@ -335,7 +335,7 @@ async fn compact_resume_after_second_compaction_preserves_history() -> Result<() "second compact test expects resumed path {resumed_path:?} to exist", ); - let forked = fork_thread(&manager, &config, resumed_path, 3).await; + let forked = fork_thread(&manager, &config, resumed_path, /*nth_user_message*/ 3).await; user_turn(&forked, "AFTER_FORK").await; compact_conversation(&forked).await; @@ -468,7 +468,7 @@ async fn snapshot_rollback_past_compaction_replays_append_only_history() -> Resu let request_log = mount_sse_sequence(&server, vec![sse1, sse2, sse3, sse4]).await; - let (_home, _config, _manager, base) = start_test_conversation(&server, None).await; + let (_home, _config, _manager, base) = start_test_conversation(&server, /*model*/ None).await; user_turn(&base, "hello world").await; compact_conversation(&base).await; @@ -845,10 +845,15 @@ async fn resume_conversation( let auth_manager = codex_core::test_support::auth_manager_from_auth( codex_core::CodexAuth::from_api_key("dummy"), ); - Box::pin(manager.resume_thread_from_rollout(config.clone(), path, auth_manager, None)) - .await - .expect("resume conversation") - .thread + Box::pin(manager.resume_thread_from_rollout( + config.clone(), + path, + auth_manager, + /*parent_trace*/ None, + )) + .await + .expect("resume conversation") + .thread } #[cfg(test)] @@ -858,8 +863,14 @@ async fn fork_thread( path: std::path::PathBuf, nth_user_message: usize, ) -> Arc { - Box::pin(manager.fork_thread(nth_user_message, config.clone(), path, false, None)) - .await - .expect("fork conversation") - .thread + Box::pin(manager.fork_thread( + nth_user_message, + config.clone(), + path, + /*persist_extended_history*/ false, + /*parent_trace*/ None, + )) + .await + .expect("fork conversation") + .thread } diff --git a/codex-rs/core/tests/suite/exec.rs b/codex-rs/core/tests/suite/exec.rs index f29731282..8f334fbe2 100644 --- a/codex-rs/core/tests/suite/exec.rs +++ b/codex-rs/core/tests/suite/exec.rs @@ -30,7 +30,8 @@ fn skip_test() -> bool { #[expect(clippy::expect_used)] async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result { - let sandbox_type = get_platform_sandbox(false).expect("should be able to get sandbox type"); + let sandbox_type = get_platform_sandbox(/*windows_sandbox_enabled*/ false) + .expect("should be able to get sandbox type"); assert_eq!(sandbox_type, SandboxType::MacosSeatbelt); let params = ExecParams { @@ -56,8 +57,8 @@ async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result Result<()> { let mut builder = test_codex() .with_pre_build_hook(|home| { - if let Err(error) = write_pre_tool_use_hook(home, None, "json_deny", "should not fire") + if let Err(error) = + write_pre_tool_use_hook(home, /*matcher*/ None, "json_deny", "should not fire") { panic!("failed to write pre tool use hook test fixture: {error}"); } @@ -1775,9 +1776,12 @@ async fn post_tool_use_does_not_fire_for_non_shell_tools() -> Result<()> { let mut builder = test_codex() .with_pre_build_hook(|home| { - if let Err(error) = - write_post_tool_use_hook(home, None, "decision_block", "should not fire") - { + if let Err(error) = write_post_tool_use_hook( + home, + /*matcher*/ None, + "decision_block", + "should not fire", + ) { panic!("failed to write post tool use hook test fixture: {error}"); } }) diff --git a/codex-rs/core/tests/suite/image_rollout.rs b/codex-rs/core/tests/suite/image_rollout.rs index 1526fe11a..8195bd0a8 100644 --- a/codex-rs/core/tests/suite/image_rollout.rs +++ b/codex-rs/core/tests/suite/image_rollout.rs @@ -148,7 +148,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu role: "user".to_string(), content: vec![ ContentItem::InputText { - text: codex_protocol::models::local_image_open_tag_text(1), + text: codex_protocol::models::local_image_open_tag_text(/*label_number*/ 1), }, ContentItem::InputImage { image_url }, ContentItem::InputText { diff --git a/codex-rs/core/tests/suite/memories.rs b/codex-rs/core/tests/suite/memories.rs index c4e97f964..98e618643 100644 --- a/codex-rs/core/tests/suite/memories.rs +++ b/codex-rs/core/tests/suite/memories.rs @@ -253,7 +253,9 @@ async fn web_search_pollution_moves_selected_thread_into_removed_phase2_inputs() .resume(&server, home.clone(), rollout_path.clone()) .await?; - let first_phase2_request = wait_for_request(&responses, 1).await.remove(0); + let first_phase2_request = wait_for_request(&responses, /*expected_count*/ 1) + .await + .remove(0); let first_phase2_prompt = phase2_prompt_text(&first_phase2_request); assert!( first_phase2_prompt.contains("- selected inputs this run: 1"), @@ -295,7 +297,9 @@ async fn web_search_pollution_moves_selected_thread_into_removed_phase2_inputs() let selection = { let deadline = Instant::now() + Duration::from_secs(10); loop { - let selection = db.get_phase2_input_selection(1, 30).await?; + let selection = db + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 30) + .await?; if selection.selected.is_empty() && selection.retained_thread_ids.is_empty() && selection.removed.len() == 1 @@ -340,7 +344,7 @@ async fn build_test_codex(server: &wiremock::MockServer, home: Arc) -> async fn init_state_db(home: &Arc) -> Result> { let db = codex_state::StateRuntime::init(home.path().to_path_buf(), "test-provider".into()).await?; - db.mark_backfill_complete(None).await?; + db.mark_backfill_complete(/*last_watermark*/ None).await?; Ok(db) } @@ -379,7 +383,7 @@ async fn seed_stage1_output( } async fn wait_for_single_request(mock: &ResponseMock) -> ResponsesRequest { - wait_for_request(mock, 1).await.remove(0) + wait_for_request(mock, /*expected_count*/ 1).await.remove(0) } async fn wait_for_request(mock: &ResponseMock, expected_count: usize) -> Vec { @@ -412,7 +416,9 @@ async fn wait_for_phase2_success( ) -> Result<()> { let deadline = Instant::now() + Duration::from_secs(10); loop { - let selection = db.get_phase2_input_selection(1, 30).await?; + let selection = db + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 30) + .await?; if selection.selected.len() == 1 && selection.selected[0].thread_id == expected_thread_id && selection.retained_thread_ids == vec![expected_thread_id] @@ -439,7 +445,10 @@ async fn seed_stage1_output_for_existing_thread( ) -> Result<()> { let owner = ThreadId::new(); let claim = db - .try_claim_stage1_job(thread_id, owner, updated_at, 3_600, 64) + .try_claim_stage1_job( + thread_id, owner, updated_at, /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, + ) .await?; let ownership_token = match claim { codex_state::Stage1JobClaimOutcome::Claimed { ownership_token } => ownership_token, diff --git a/codex-rs/core/tests/suite/model_info_overrides.rs b/codex-rs/core/tests/suite/model_info_overrides.rs index ee4afc36b..fc1cbac76 100644 --- a/codex-rs/core/tests/suite/model_info_overrides.rs +++ b/codex-rs/core/tests/suite/model_info_overrides.rs @@ -16,7 +16,7 @@ async fn offline_model_info_without_tool_output_override() { let manager = ModelsManager::new( config.codex_home.clone(), auth_manager, - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), ); @@ -24,7 +24,7 @@ async fn offline_model_info_without_tool_output_override() { assert_eq!( model_info.truncation_policy, - TruncationPolicyConfig::bytes(10_000) + TruncationPolicyConfig::bytes(/*limit*/ 10_000) ); } @@ -39,7 +39,7 @@ async fn offline_model_info_with_tool_output_override() { let manager = ModelsManager::new( config.codex_home.clone(), auth_manager, - None, + /*model_catalog*/ None, CollaborationModesConfig::default(), ); @@ -47,6 +47,6 @@ async fn offline_model_info_with_tool_output_override() { assert_eq!( model_info.truncation_policy, - TruncationPolicyConfig::tokens(123) + TruncationPolicyConfig::tokens(/*limit*/ 123) ); } diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index a7c5ceb0d..808b04191 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -92,7 +92,7 @@ fn test_model_info( availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), @@ -308,7 +308,7 @@ async fn service_tier_change_is_applied_on_next_http_turn() -> Result<()> { test.submit_turn_with_service_tier("fast turn", Some(ServiceTier::Fast)) .await?; - test.submit_turn_with_service_tier("standard turn", None) + test.submit_turn_with_service_tier("standard turn", /*service_tier*/ None) .await?; let requests = resp_mock.requests(); @@ -498,7 +498,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> { sse(vec![ ev_response_created("resp-1"), ev_image_generation_call("ig_123", "completed", "lobster", "Zm9v"), - ev_completed_with_tokens("resp-1", 10), + ev_completed_with_tokens("resp-1", /*total_tokens*/ 10), ]), sse_completed("resp-2"), ], @@ -630,7 +630,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima sse(vec![ ev_response_created("resp-1"), ev_image_generation_call("ig_123", "completed", "lobster", "Zm9v"), - ev_completed_with_tokens("resp-1", 10), + ev_completed_with_tokens("resp-1", /*total_tokens*/ 10), ]), sse_completed("resp-2"), ], @@ -764,7 +764,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history() sse(vec![ ev_response_created("resp-1"), ev_image_generation_call("ig_rollback", "completed", "lobster", "Zm9v"), - ev_completed_with_tokens("resp-1", 10), + ev_completed_with_tokens("resp-1", /*total_tokens*/ 10), ]), sse_completed("resp-2"), ], @@ -908,7 +908,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(large_context_window), @@ -935,11 +935,11 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< vec![ sse(vec![ ev_response_created("resp-1"), - ev_completed_with_tokens("resp-1", 100), + ev_completed_with_tokens("resp-1", /*total_tokens*/ 100), ]), sse(vec![ ev_response_created("resp-2"), - ev_completed_with_tokens("resp-2", 120), + ev_completed_with_tokens("resp-2", /*total_tokens*/ 120), ]), ], ) diff --git a/codex-rs/core/tests/suite/models_cache_ttl.rs b/codex-rs/core/tests/suite/models_cache_ttl.rs index 3d5904bd7..7d0ce8046 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -44,7 +44,7 @@ const DIFFERENT_VERSION_MODEL: &str = "codex-test-different-version"; async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> { let server = MockServer::start().await; - let remote_model = test_remote_model(REMOTE_MODEL, 1); + let remote_model = test_remote_model(REMOTE_MODEL, /*priority*/ 1); let models_mock = responses::mount_models_once_with_etag( &server, ModelsResponse { @@ -138,11 +138,11 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn uses_cache_when_version_matches() -> Result<()> { let server = MockServer::start().await; - let cached_model = test_remote_model(VERSIONED_MODEL, 1); + let cached_model = test_remote_model(VERSIONED_MODEL, /*priority*/ 1); let models_mock = responses::mount_models_once( &server, ModelsResponse { - models: vec![test_remote_model("remote", 2)], + models: vec![test_remote_model("remote", /*priority*/ 2)], }, ) .await; @@ -185,11 +185,11 @@ async fn uses_cache_when_version_matches() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn refreshes_when_cache_version_missing() -> Result<()> { let server = MockServer::start().await; - let cached_model = test_remote_model(MISSING_VERSION_MODEL, 1); + let cached_model = test_remote_model(MISSING_VERSION_MODEL, /*priority*/ 1); let models_mock = responses::mount_models_once( &server, ModelsResponse { - models: vec![test_remote_model("remote-missing", 2)], + models: vec![test_remote_model("remote-missing", /*priority*/ 2)], }, ) .await; @@ -232,9 +232,9 @@ async fn refreshes_when_cache_version_missing() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn refreshes_when_cache_version_differs() -> Result<()> { let server = MockServer::start().await; - let cached_model = test_remote_model(DIFFERENT_VERSION_MODEL, 1); + let cached_model = test_remote_model(DIFFERENT_VERSION_MODEL, /*priority*/ 1); let models_response = ModelsResponse { - models: vec![test_remote_model("remote-different", 2)], + models: vec![test_remote_model("remote-different", /*priority*/ 2)], }; let mut models_mocks = Vec::new(); for _ in 0..3 { @@ -344,7 +344,7 @@ fn test_remote_model(slug: &str, priority: i32) -> ModelInfo { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/permissions_messages.rs b/codex-rs/core/tests/suite/permissions_messages.rs index e71a15879..5945c04f8 100644 --- a/codex-rs/core/tests/suite/permissions_messages.rs +++ b/codex-rs/core/tests/suite/permissions_messages.rs @@ -503,8 +503,8 @@ async fn permissions_message_includes_writable_roots() -> Result<()> { test.config.approvals_reviewer, &Policy::empty(), test.config.cwd.as_path(), - false, - false, + /*exec_permission_approvals_enabled*/ false, + /*request_permissions_tool_enabled*/ false, ) .into_text(); // Normalize line endings to handle Windows vs Unix differences diff --git a/codex-rs/core/tests/suite/personality.rs b/codex-rs/core/tests/suite/personality.rs index ed4da0716..cc68c5715 100644 --- a/codex-rs/core/tests/suite/personality.rs +++ b/codex-rs/core/tests/suite/personality.rs @@ -661,7 +661,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(128_000), @@ -777,7 +777,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() - availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(128_000), diff --git a/codex-rs/core/tests/suite/realtime_conversation.rs b/codex-rs/core/tests/suite/realtime_conversation.rs index 06cb31630..415d764e4 100644 --- a/codex-rs/core/tests/suite/realtime_conversation.rs +++ b/codex-rs/core/tests/suite/realtime_conversation.rs @@ -172,7 +172,11 @@ async fn conversation_start_audio_text_close_round_trip() -> Result<()> { let mut builder = test_codex(); let test = builder.build_with_websocket_server(&server).await?; - assert!(server.wait_for_handshakes(1, Duration::from_secs(2)).await); + assert!( + server + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) + .await + ); test.codex .submit(Op::RealtimeConversationStart(ConversationStartParams { @@ -310,7 +314,11 @@ async fn conversation_start_uses_openai_env_key_fallback_with_chatgpt_auth() -> let mut builder = test_codex().with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()); let test = builder.build_with_websocket_server(&server).await?; - assert!(server.wait_for_handshakes(1, Duration::from_secs(2)).await); + assert!( + server + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) + .await + ); test.codex .submit(Op::RealtimeConversationStart(ConversationStartParams { @@ -365,7 +373,11 @@ async fn conversation_transport_close_emits_closed_event() -> Result<()> { let mut builder = test_codex(); let test = builder.build_with_websocket_server(&server).await?; - assert!(server.wait_for_handshakes(1, Duration::from_secs(2)).await); + assert!( + server + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) + .await + ); test.codex .submit(Op::RealtimeConversationStart(ConversationStartParams { @@ -572,7 +584,11 @@ async fn conversation_second_start_replaces_runtime() -> Result<()> { .await; let mut builder = test_codex(); let test = builder.build_with_websocket_server(&server).await?; - assert!(server.wait_for_handshakes(1, Duration::from_secs(2)).await); + assert!( + server + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) + .await + ); test.codex .submit(Op::RealtimeConversationStart(ConversationStartParams { @@ -672,7 +688,7 @@ async fn conversation_uses_experimental_realtime_ws_base_url_override() -> Resul let test = builder.build_with_websocket_server(&startup_server).await?; assert!( startup_server - .wait_for_handshakes(1, Duration::from_secs(2)) + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) .await ); @@ -724,7 +740,11 @@ async fn conversation_uses_experimental_realtime_ws_backend_prompt_override() -> config.experimental_realtime_ws_backend_prompt = Some("prompt from config".to_string()); }); let test = builder.build_with_websocket_server(&server).await?; - assert!(server.wait_for_handshakes(1, Duration::from_secs(2)).await); + assert!( + server + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) + .await + ); test.codex .submit(Op::RealtimeConversationStart(ConversationStartParams { @@ -784,7 +804,7 @@ async fn conversation_uses_experimental_realtime_ws_startup_context_override() - fs::write(test.workspace_path("README.md"), "workspace marker")?; assert!( startup_server - .wait_for_handshakes(1, Duration::from_secs(2)) + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) .await ); @@ -844,7 +864,7 @@ async fn conversation_disables_realtime_startup_context_with_empty_override() -> fs::write(test.workspace_path("README.md"), "workspace marker")?; assert!( startup_server - .wait_for_handshakes(1, Duration::from_secs(2)) + .wait_for_handshakes(/*expected*/ 1, Duration::from_secs(2)) .await ); @@ -1238,7 +1258,9 @@ async fn conversation_handoff_persists_across_item_done_until_turn_complete() -> }) .await; - let first_append = realtime_server.wait_for_request(0, 1).await; + let first_append = realtime_server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 1) + .await; assert_eq!( first_append.body_json()["type"].as_str(), Some("conversation.handoff.append") @@ -1262,7 +1284,9 @@ async fn conversation_handoff_persists_across_item_done_until_turn_complete() -> let _ = gate_second_message_tx.send(()); - let second_append = realtime_server.wait_for_request(0, 2).await; + let second_append = realtime_server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 2) + .await; assert_eq!( second_append.body_json()["type"].as_str(), Some("conversation.handoff.append") @@ -1777,7 +1801,9 @@ async fn delegated_turn_user_role_echo_does_not_redelegate_and_still_forwards_au "delegate now" ); - let mirrored_request = realtime_server.wait_for_request(0, 1).await; + let mirrored_request = realtime_server + .wait_for_request(/*connection_index*/ 0, /*request_index*/ 1) + .await; let mirrored_request_body = mirrored_request.body_json(); eprintln!( "[realtime test +{}ms] saw mirrored request type={:?} handoff_id={:?} text={:?}", diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 83d911533..6b2da1116 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -62,14 +62,14 @@ async fn remote_models_get_model_info_uses_longest_matching_prefix() -> Result<( let generic = test_remote_model_with_policy( "gpt-5.3", ModelVisibility::List, - 1_000, - TruncationPolicyConfig::bytes(10_000), + /*priority*/ 1_000, + TruncationPolicyConfig::bytes(/*limit*/ 10_000), ); let specific = test_remote_model_with_policy( "gpt-5.3-codex", ModelVisibility::List, - 1_000, - TruncationPolicyConfig::bytes(10_000), + /*priority*/ 1_000, + TruncationPolicyConfig::bytes(/*limit*/ 10_000), ); let specific = ModelInfo { display_name: "GPT 5.3 Codex".to_string(), @@ -95,7 +95,7 @@ async fn remote_models_get_model_info_uses_longest_matching_prefix() -> Result<( let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -124,8 +124,8 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( let mut remote_model = test_remote_model_with_policy( prefix_model, ModelVisibility::List, - 1_000, - TruncationPolicyConfig::bytes(10_000), + /*priority*/ 1_000, + TruncationPolicyConfig::bytes(/*limit*/ 10_000), ); remote_model.default_reasoning_level = Some(ReasoningEffort::High); remote_model.supported_reasoning_levels = vec![ @@ -304,7 +304,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), @@ -434,8 +434,8 @@ async fn remote_models_truncation_policy_without_override_preserves_remote() -> let remote_model = test_remote_model_with_policy( slug, ModelVisibility::List, - 1, - TruncationPolicyConfig::bytes(12_000), + /*priority*/ 1, + TruncationPolicyConfig::bytes(/*limit*/ 12_000), ); mount_models_once( &server, @@ -458,7 +458,7 @@ async fn remote_models_truncation_policy_without_override_preserves_remote() -> let model_info = models_manager.get_model_info(slug, &test.config).await; assert_eq!( model_info.truncation_policy, - TruncationPolicyConfig::bytes(12_000) + TruncationPolicyConfig::bytes(/*limit*/ 12_000) ); Ok(()) @@ -478,8 +478,8 @@ async fn remote_models_truncation_policy_with_tool_output_override() -> Result<( let remote_model = test_remote_model_with_policy( slug, ModelVisibility::List, - 1, - TruncationPolicyConfig::bytes(10_000), + /*priority*/ 1, + TruncationPolicyConfig::bytes(/*limit*/ 10_000), ); mount_models_once( &server, @@ -503,7 +503,7 @@ async fn remote_models_truncation_policy_with_tool_output_override() -> Result<( let model_info = models_manager.get_model_info(slug, &test.config).await; assert_eq!( model_info.truncation_policy, - TruncationPolicyConfig::bytes(200) + TruncationPolicyConfig::bytes(/*limit*/ 200) ); Ok(()) @@ -548,7 +548,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), @@ -642,7 +642,8 @@ async fn remote_models_do_not_append_removed_builtin_presets() -> Result<()> { skip_if_sandbox!(Ok(())); let server = MockServer::start().await; - let remote_model = test_remote_model("remote-alpha", ModelVisibility::List, 0); + let remote_model = + test_remote_model("remote-alpha", ModelVisibility::List, /*priority*/ 0); let models_mock = mount_models_once( &server, ModelsResponse { @@ -656,7 +657,7 @@ async fn remote_models_do_not_append_removed_builtin_presets() -> Result<()> { let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -699,7 +700,11 @@ async fn remote_models_merge_adds_new_high_priority_first() -> Result<()> { skip_if_sandbox!(Ok(())); let server = MockServer::start().await; - let remote_model = test_remote_model("remote-top", ModelVisibility::List, -10_000); + let remote_model = test_remote_model( + "remote-top", + ModelVisibility::List, + /*priority*/ -10_000, + ); let models_mock = mount_models_once( &server, ModelsResponse { @@ -713,7 +718,7 @@ async fn remote_models_merge_adds_new_high_priority_first() -> Result<()> { let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -744,7 +749,7 @@ async fn remote_models_merge_replaces_overlapping_model() -> Result<()> { let server = MockServer::start().await; let slug = bundled_model_slug(); - let mut remote_model = test_remote_model(&slug, ModelVisibility::List, 0); + let mut remote_model = test_remote_model(&slug, ModelVisibility::List, /*priority*/ 0); remote_model.display_name = "Overridden".to_string(); remote_model.description = Some("Overridden description".to_string()); let models_mock = mount_models_once( @@ -760,7 +765,7 @@ async fn remote_models_merge_replaces_overlapping_model() -> Result<()> { let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -804,7 +809,7 @@ async fn remote_models_merge_preserves_bundled_models_on_empty_response() -> Res let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -830,7 +835,8 @@ async fn remote_models_request_times_out_after_5s() -> Result<()> { skip_if_sandbox!(Ok(())); let server = MockServer::start().await; - let remote_model = test_remote_model("remote-timeout", ModelVisibility::List, 0); + let remote_model = + test_remote_model("remote-timeout", ModelVisibility::List, /*priority*/ 0); let models_mock = mount_models_once_with_delay( &server, ModelsResponse { @@ -845,7 +851,7 @@ async fn remote_models_request_times_out_after_5s() -> Result<()> { let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -897,7 +903,11 @@ async fn remote_models_hide_picker_only_models() -> Result<()> { skip_if_sandbox!(Ok(())); let server = MockServer::start().await; - let remote_model = test_remote_model("codex-auto-balanced", ModelVisibility::Hide, 0); + let remote_model = test_remote_model( + "codex-auto-balanced", + ModelVisibility::Hide, + /*priority*/ 0, + ); let models_mock = mount_models_once( &server, ModelsResponse { @@ -911,7 +921,7 @@ async fn remote_models_hide_picker_only_models() -> Result<()> { let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing(); let provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers(/* openai_base_url */ None)["openai"].clone() + ..built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone() }; let manager = codex_core::test_support::models_manager_with_provider( codex_home.path().to_path_buf(), @@ -982,7 +992,7 @@ fn test_remote_model(slug: &str, visibility: ModelVisibility, priority: i32) -> slug, visibility, priority, - TruncationPolicyConfig::bytes(10_000), + TruncationPolicyConfig::bytes(/*limit*/ 10_000), ) } diff --git a/codex-rs/core/tests/suite/resume_warning.rs b/codex-rs/core/tests/suite/resume_warning.rs index e60900543..f55f87e53 100644 --- a/codex-rs/core/tests/suite/resume_warning.rs +++ b/codex-rs/core/tests/suite/resume_warning.rs @@ -98,7 +98,13 @@ async fn emits_warning_when_resumed_model_differs() { thread: conversation, .. } = thread_manager - .resume_thread_with_history(config, initial_history, auth_manager, false, None) + .resume_thread_with_history( + config, + initial_history, + auth_manager, + /*persist_extended_history*/ false, + /*parent_trace*/ None, + ) .await .expect("resume conversation"); diff --git a/codex-rs/core/tests/suite/review.rs b/codex-rs/core/tests/suite/review.rs index 7aa05f972..503bc8745 100644 --- a/codex-rs/core/tests/suite/review.rs +++ b/codex-rs/core/tests/suite/review.rs @@ -70,7 +70,8 @@ async fn review_op_emits_lifecycle_and_review_output() { ]"#; let review_json_escaped = serde_json::to_string(&review_json).unwrap(); let sse_raw = sse_template.replace("__REVIEW__", &review_json_escaped); - let (server, _request_log) = start_responses_server_with_sse(&sse_raw, 1).await; + let (server, _request_log) = + start_responses_server_with_sse(&sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |_| {}).await; @@ -192,7 +193,8 @@ async fn review_op_with_plain_text_emits_review_fallback() { }}, {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, _request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, _request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |_| {}).await; @@ -253,7 +255,8 @@ async fn review_filters_agent_message_related_events() { }}, {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, _request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, _request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |_| {}).await; @@ -335,7 +338,8 @@ async fn review_does_not_emit_agent_message_on_structured_output() { ]"#; let review_json_escaped = serde_json::to_string(&review_json).unwrap(); let sse_raw = sse_template.replace("__REVIEW__", &review_json_escaped); - let (server, _request_log) = start_responses_server_with_sse(&sse_raw, 1).await; + let (server, _request_log) = + start_responses_server_with_sse(&sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |_| {}).await; @@ -390,7 +394,8 @@ async fn review_uses_custom_review_model_from_config() { let sse_raw = r#"[ {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); // Choose a review model different from the main model; ensure it is used. let codex = new_conversation_for_server(&server, codex_home.clone(), |cfg| { @@ -444,7 +449,8 @@ async fn review_uses_session_model_when_review_model_unset() { let sse_raw = r#"[ {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |cfg| { cfg.model = Some("gpt-4.1".to_string()); @@ -498,7 +504,8 @@ async fn review_input_isolated_from_parent_history() { let sse_raw = r#"[ {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; // Seed a parent session history via resume file with both user + assistant items. let codex_home = Arc::new(TempDir::new().unwrap()); @@ -681,7 +688,8 @@ async fn review_history_surfaces_in_parent_session() { }}, {"type":"response.completed", "response": {"id": "__ID__"}} ]"#; - let (server, request_log) = start_responses_server_with_sse(sse_raw, 2).await; + let (server, request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 2).await; let codex_home = Arc::new(TempDir::new().unwrap()); let codex = new_conversation_for_server(&server, codex_home.clone(), |_| {}).await; @@ -773,7 +781,8 @@ async fn review_uses_overridden_cwd_for_base_branch_merge_base() { skip_if_no_network!(); let sse_raw = r#"[{"type":"response.completed", "response": {"id": "__ID__"}}]"#; - let (server, request_log) = start_responses_server_with_sse(sse_raw, 1).await; + let (server, request_log) = + start_responses_server_with_sse(sse_raw, /*expected_requests*/ 1).await; let initial_cwd = TempDir::new().unwrap(); diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 431895e2e..0335ead7e 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -415,7 +415,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/rollout_list_find.rs b/codex-rs/core/tests/suite/rollout_list_find.rs index a9ea2b9c8..7445a4ba0 100644 --- a/codex-rs/core/tests/suite/rollout_list_find.rs +++ b/codex-rs/core/tests/suite/rollout_list_find.rs @@ -60,7 +60,10 @@ async fn upsert_thread_metadata(codex_home: &Path, thread_id: ThreadId, rollout_ let runtime = StateRuntime::init(codex_home.to_path_buf(), "test-provider".to_string()) .await .unwrap(); - runtime.mark_backfill_complete(None).await.unwrap(); + runtime + .mark_backfill_complete(/*last_watermark*/ None) + .await + .unwrap(); let mut builder = ThreadMetadataBuilder::new( thread_id, rollout_path, @@ -168,14 +171,14 @@ async fn find_locates_rollout_file_written_by_recorder() -> std::io::Result<()> &config, RolloutRecorderParams::new( thread_id, - None, + /*forked_from_id*/ None, SessionSource::Exec, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), - None, - None, + /*state_db_ctx*/ None, + /*state_builder*/ None, ) .await?; recorder.persist().await?; diff --git a/codex-rs/core/tests/suite/seatbelt.rs b/codex-rs/core/tests/suite/seatbelt.rs index cfb91caee..f66eaa76f 100644 --- a/codex-rs/core/tests/suite/seatbelt.rs +++ b/codex-rs/core/tests/suite/seatbelt.rs @@ -192,7 +192,7 @@ assert os.read(master, 4) == b"ping""# &policy, sandbox_cwd.as_path(), StdioPolicy::RedirectForShellTool, - None, + /*network*/ None, HashMap::new(), ) .await @@ -245,7 +245,7 @@ async fn java_home_finds_runtime_under_seatbelt() { &policy, sandbox_cwd.as_path(), StdioPolicy::RedirectForShellTool, - None, + /*network*/ None, env, ) .await @@ -302,7 +302,7 @@ async fn touch(path: &Path, policy: &SandboxPolicy) -> bool { policy, sandbox_cwd.as_path(), StdioPolicy::RedirectForShellTool, - None, + /*network*/ None, HashMap::new(), ) .await diff --git a/codex-rs/core/tests/suite/shell_command.rs b/codex-rs/core/tests/suite/shell_command.rs index 6eda4a7c3..ad02a645e 100644 --- a/codex-rs/core/tests/suite/shell_command.rs +++ b/codex-rs/core/tests/suite/shell_command.rs @@ -112,7 +112,13 @@ async fn shell_command_works() -> anyhow::Result<()> { let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?; let call_id = "shell-command-call"; - mount_shell_responses(&harness, call_id, "echo 'hello, world'", None).await; + mount_shell_responses( + &harness, + call_id, + "echo 'hello, world'", + /*login*/ None, + ) + .await; harness.submit("run the echo command").await?; let output = harness.function_call_stdout(call_id).await; @@ -183,7 +189,13 @@ async fn pipe_output_with_login() -> anyhow::Result<()> { let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?; let call_id = "shell-command-call-second-extra-no-login"; - mount_shell_responses(&harness, call_id, "echo 'hello, world' | cat", None).await; + mount_shell_responses( + &harness, + call_id, + "echo 'hello, world' | cat", + /*login*/ None, + ) + .await; harness.submit("run the command without login").await?; let output = harness.function_call_stdout(call_id).await; @@ -224,7 +236,7 @@ async fn shell_command_times_out_with_timeout_ms() -> anyhow::Result<()> { &harness, call_id, command, - None, + /*login*/ None, Duration::from_millis(200), ) .await; diff --git a/codex-rs/core/tests/suite/shell_serialization.rs b/codex-rs/core/tests/suite/shell_serialization.rs index ccbff4a4b..55ac77da7 100644 --- a/codex-rs/core/tests/suite/shell_serialization.rs +++ b/codex-rs/core/tests/suite/shell_serialization.rs @@ -125,7 +125,11 @@ async fn shell_output_stays_json_without_freeform_apply_patch( skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = configure_shell_model(test_codex(), output_type, false); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ false, + ); let test = builder.build(&server).await?; let call_id = "shell-json"; @@ -177,7 +181,11 @@ async fn shell_output_is_structured_with_freeform_apply_patch( skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = configure_shell_model(test_codex(), output_type, true); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ true, + ); let test = builder.build(&server).await?; let call_id = "shell-structured"; @@ -222,7 +230,11 @@ async fn shell_output_preserves_fixture_json_without_serialization( skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = configure_shell_model(test_codex(), output_type, false); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ false, + ); let test = builder.build(&server).await?; let fixture_path = test.cwd.path().join("fixture.json"); @@ -286,7 +298,11 @@ async fn shell_output_structures_fixture_with_serialization( skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = configure_shell_model(test_codex(), output_type, true); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ true, + ); let test = builder.build(&server).await?; let fixture_path = test.cwd.path().join("fixture.json"); @@ -345,7 +361,11 @@ async fn shell_output_for_freeform_tool_records_duration( skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = configure_shell_model(test_codex(), output_type, true); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ true, + ); let test = builder.build(&server).await?; let call_id = "shell-structured"; @@ -395,10 +415,14 @@ async fn shell_output_reserializes_truncated_content(output_type: ShellModelOutp skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let mut builder = - configure_shell_model(test_codex(), output_type, true).with_config(move |config| { - config.tool_output_token_limit = Some(200); - }); + let mut builder = configure_shell_model( + test_codex(), + output_type, + /*include_apply_patch_tool*/ true, + ) + .with_config(move |config| { + config.tool_output_token_limit = Some(200); + }); let test = builder.build(&server).await?; let call_id = "shell-truncated"; diff --git a/codex-rs/core/tests/suite/spawn_agent_description.rs b/codex-rs/core/tests/suite/spawn_agent_description.rs index dfc5a2e54..e27e3466f 100644 --- a/codex-rs/core/tests/suite/spawn_agent_description.rs +++ b/codex-rs/core/tests/suite/spawn_agent_description.rs @@ -77,7 +77,7 @@ fn test_model_info( availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs index 33abc6c7a..a1a8c29b9 100644 --- a/codex-rs/core/tests/suite/subagent_notifications.rs +++ b/codex-rs/core/tests/suite/subagent_notifications.rs @@ -144,7 +144,7 @@ async fn setup_turn_one_with_spawned_child( "message": CHILD_PROMPT, }), child_response_delay, - true, + /*wait_for_parent_notification*/ true, |builder| builder, ) .await @@ -253,9 +253,14 @@ async fn spawn_child_and_capture_snapshot( core_test_support::test_codex::TestCodexBuilder, ) -> core_test_support::test_codex::TestCodexBuilder, ) -> Result { - let (test, spawned_id) = - setup_turn_one_with_custom_spawned_child(server, spawn_args, None, false, configure_test) - .await?; + let (test, spawned_id) = setup_turn_one_with_custom_spawned_child( + server, + spawn_args, + /*child_response_delay*/ None, + /*wait_for_parent_notification*/ false, + configure_test, + ) + .await?; let thread_id = ThreadId::from_string(&spawned_id)?; Ok(test .thread_manager @@ -270,7 +275,8 @@ async fn subagent_notification_is_included_without_wait() -> Result<()> { skip_if_no_network!(Ok(())); let server = start_mock_server().await; - let (test, _spawned_id) = setup_turn_one_with_spawned_child(&server, None).await?; + let (test, _spawned_id) = + setup_turn_one_with_spawned_child(&server, /*child_response_delay*/ None).await?; let turn2 = mount_sse_once_match( &server, diff --git a/codex-rs/core/tests/suite/tools.rs b/codex-rs/core/tests/suite/tools.rs index af8d70f22..8dc91cc08 100644 --- a/codex-rs/core/tests/suite/tools.rs +++ b/codex-rs/core/tests/suite/tools.rs @@ -321,7 +321,7 @@ async fn collect_tools(use_unified_exec: bool) -> Result> { async fn unified_exec_spec_toggle_end_to_end() -> Result<()> { skip_if_no_network!(Ok(())); - let tools_disabled = collect_tools(false).await?; + let tools_disabled = collect_tools(/*use_unified_exec*/ false).await?; assert!( !tools_disabled.iter().any(|name| name == "exec_command"), "tools list should not include exec_command when disabled: {tools_disabled:?}" @@ -331,7 +331,7 @@ async fn unified_exec_spec_toggle_end_to_end() -> Result<()> { "tools list should not include write_stdin when disabled: {tools_disabled:?}" ); - let tools_enabled = collect_tools(true).await?; + let tools_enabled = collect_tools(/*use_unified_exec*/ true).await?; assert!( tools_enabled.iter().any(|name| name == "exec_command"), "tools list should include exec_command when enabled: {tools_enabled:?}" diff --git a/codex-rs/core/tests/suite/unstable_features_warning.rs b/codex-rs/core/tests/suite/unstable_features_warning.rs index 18be16b62..efb154e6e 100644 --- a/codex-rs/core/tests/suite/unstable_features_warning.rs +++ b/codex-rs/core/tests/suite/unstable_features_warning.rs @@ -42,7 +42,13 @@ async fn emits_warning_when_unstable_features_enabled_via_config() { thread: conversation, .. } = thread_manager - .resume_thread_with_history(config, InitialHistory::New, auth_manager, false, None) + .resume_thread_with_history( + config, + InitialHistory::New, + auth_manager, + /*persist_extended_history*/ false, + /*parent_trace*/ None, + ) .await .expect("spawn conversation"); @@ -83,7 +89,13 @@ async fn suppresses_warning_when_configured() { thread: conversation, .. } = thread_manager - .resume_thread_with_history(config, InitialHistory::New, auth_manager, false, None) + .resume_thread_with_history( + config, + InitialHistory::New, + auth_manager, + /*persist_extended_history*/ false, + /*parent_trace*/ None, + ) .await .expect("spawn conversation"); diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 4041ca1d1..fab2098ca 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -476,7 +476,14 @@ async fn view_image_tool_errors_clearly_for_unsupported_detail_values() -> anyho } = &test; let rel_path = "assets/unsupported-detail.png"; - write_workspace_png(&test, rel_path, 256, 128, [0u8, 80, 255, 255]).await?; + write_workspace_png( + &test, + rel_path, + /*width*/ 256, + /*height*/ 128, + [0u8, 80, 255, 255], + ) + .await?; let call_id = "view-image-unsupported-detail"; let arguments = serde_json::json!({ "path": rel_path, "detail": "low" }).to_string(); @@ -1352,7 +1359,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: Some(272_000), @@ -1377,7 +1384,14 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an let TestCodex { codex, config, .. } = &test; let rel_path = "assets/example.png"; - write_workspace_png(&test, rel_path, 20, 20, [255u8, 0, 0, 255]).await?; + write_workspace_png( + &test, + rel_path, + /*width*/ 20, + /*height*/ 20, + [255u8, 0, 0, 255], + ) + .await?; let call_id = "view-image-unsupported-model"; let arguments = serde_json::json!({ "path": rel_path }).to_string(); diff --git a/codex-rs/exec-server/tests/exec_process.rs b/codex-rs/exec-server/tests/exec_process.rs index 689869a6b..ab232ccd3 100644 --- a/codex-rs/exec-server/tests/exec_process.rs +++ b/codex-rs/exec-server/tests/exec_process.rs @@ -235,7 +235,8 @@ async fn remote_exec_process_reports_transport_disconnect() -> Result<()> { server.shutdown().await?; let mut wake_rx = session.process.subscribe_wake(); - let response = read_process_until_change(session.process, &mut wake_rx, None).await?; + let response = + read_process_until_change(session.process, &mut wake_rx, /*after_seq*/ None).await?; let message = response .failure .expect("disconnect should surface as a failure"); diff --git a/codex-rs/exec/src/event_processor_with_human_output.rs b/codex-rs/exec/src/event_processor_with_human_output.rs index 8851233e5..df1cb31a4 100644 --- a/codex-rs/exec/src/event_processor_with_human_output.rs +++ b/codex-rs/exec/src/event_processor_with_human_output.rs @@ -582,8 +582,8 @@ mod tests { fn suppresses_final_stdout_message_when_both_streams_are_terminals() { assert!(!should_print_final_message_to_stdout( Some("hello"), - true, - true + /*stdout_is_terminal*/ true, + /*stderr_is_terminal*/ true )); } @@ -591,8 +591,8 @@ mod tests { fn prints_final_stdout_message_when_stdout_is_not_terminal() { assert!(should_print_final_message_to_stdout( Some("hello"), - false, - true + /*stdout_is_terminal*/ false, + /*stderr_is_terminal*/ true )); } @@ -600,23 +600,26 @@ mod tests { fn prints_final_stdout_message_when_stderr_is_not_terminal() { assert!(should_print_final_message_to_stdout( Some("hello"), - true, - false + /*stdout_is_terminal*/ true, + /*stderr_is_terminal*/ false )); } #[test] fn suppresses_final_stdout_message_when_missing() { - assert!(!should_print_final_message_to_stdout(None, false, false)); + assert!(!should_print_final_message_to_stdout( + /*final_message*/ None, /*stdout_is_terminal*/ false, + /*stderr_is_terminal*/ false + )); } #[test] fn prints_final_tty_message_when_not_yet_rendered() { assert!(should_print_final_message_to_tty( Some("hello"), - false, - true, - true + /*final_message_rendered*/ false, + /*stdout_is_terminal*/ true, + /*stderr_is_terminal*/ true )); } @@ -624,9 +627,9 @@ mod tests { fn suppresses_final_tty_message_when_already_rendered() { assert!(!should_print_final_message_to_tty( Some("hello"), - true, - true, - true + /*final_message_rendered*/ true, + /*stdout_is_terminal*/ true, + /*stderr_is_terminal*/ true )); } diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 0cc5ad28c..0a5362851 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -1781,7 +1781,7 @@ mod tests { #[test] fn lagged_event_warning_message_is_explicit() { assert_eq!( - lagged_event_warning_message(7), + lagged_event_warning_message(/*skipped*/ 7), "in-process app-server event stream lagged; dropped 7 events".to_string() ); } diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index 58579ccc2..5491e895e 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -134,7 +134,7 @@ fn session_configured_produces_thread_started_event() { #[test] fn turn_started_emits_turn_started_event() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::TurnStarted(TurnStartedNotification { @@ -158,7 +158,7 @@ fn turn_started_emits_turn_started_event() { #[test] fn command_execution_started_and_completed_translate_to_thread_events() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let command_item = ThreadItem::CommandExecution { id: "cmd-1".to_string(), command: "ls".to_string(), @@ -235,7 +235,7 @@ fn command_execution_started_and_completed_translate_to_thread_events() { #[test] fn empty_reasoning_items_are_ignored() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -260,7 +260,7 @@ fn empty_reasoning_items_are_ignored() { #[test] fn unsupported_items_do_not_consume_synthetic_ids() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let ignored = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -312,7 +312,7 @@ fn unsupported_items_do_not_consume_synthetic_ids() { #[test] fn reasoning_items_emit_summary_not_raw_content() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -344,7 +344,7 @@ fn reasoning_items_emit_summary_not_raw_content() { #[test] fn web_search_completion_preserves_query_and_action() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -384,7 +384,7 @@ fn web_search_completion_preserves_query_and_action() { #[test] fn web_search_start_and_completion_reuse_item_id() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -451,7 +451,7 @@ fn web_search_start_and_completion_reuse_item_id() { #[test] fn mcp_tool_call_begin_and_end_emit_item_events() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -533,7 +533,7 @@ fn mcp_tool_call_begin_and_end_emit_item_events() { #[test] fn mcp_tool_call_failure_sets_failed_status() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -579,7 +579,7 @@ fn mcp_tool_call_failure_sets_failed_status() { #[test] fn mcp_tool_call_defaults_arguments_and_preserves_structured_content() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -667,7 +667,7 @@ fn mcp_tool_call_defaults_arguments_and_preserves_structured_content() { #[test] fn collab_spawn_begin_and_end_emit_item_events() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -757,7 +757,7 @@ fn collab_spawn_begin_and_end_emit_item_events() { #[test] fn file_change_completion_maps_change_kinds() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -819,7 +819,7 @@ fn file_change_completion_maps_change_kinds() { #[test] fn file_change_declined_maps_to_failed_status() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -859,7 +859,7 @@ fn file_change_declined_maps_to_failed_status() { #[test] fn agent_message_item_updates_final_message() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -893,7 +893,7 @@ fn agent_message_item_updates_final_message() { #[test] fn agent_message_item_started_is_ignored() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -918,7 +918,7 @@ fn agent_message_item_started_is_ignored() { #[test] fn reasoning_item_completed_uses_synthetic_id() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -950,7 +950,7 @@ fn reasoning_item_completed_uses_synthetic_id() { #[test] fn warning_event_produces_error_item() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_warning( "Heads up: Long conversations and multiple compactions can cause the model to be less accurate. Start a new conversation when possible to keep conversations small and targeted.".to_string(), @@ -974,7 +974,7 @@ fn warning_event_produces_error_item() { #[test] fn plan_update_emits_started_then_updated_then_completed() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::TurnPlanUpdated( TurnPlanUpdatedNotification { @@ -1101,7 +1101,7 @@ fn plan_update_emits_started_then_updated_then_completed() { #[test] fn plan_update_after_completion_starts_new_todo_list_with_new_id() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let _ = processor.collect_thread_events(ServerNotification::TurnPlanUpdated( TurnPlanUpdatedNotification { @@ -1159,7 +1159,7 @@ fn plan_update_after_completion_starts_new_todo_list_with_new_id() { #[test] fn token_usage_update_is_emitted_on_turn_completion() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let usage_update = processor.collect_thread_events(ServerNotification::ThreadTokenUsageUpdated( @@ -1221,7 +1221,7 @@ fn token_usage_update_is_emitted_on_turn_completion() { #[test] fn turn_completion_recovers_final_message_from_turn_items() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let completed = processor.collect_thread_events(ServerNotification::TurnCompleted( TurnCompletedNotification { @@ -1254,7 +1254,7 @@ fn turn_completion_recovers_final_message_from_turn_items() { #[test] fn turn_completion_reconciles_started_items_from_turn_items() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let started = processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification { @@ -1340,7 +1340,7 @@ fn turn_completion_reconciles_started_items_from_turn_items() { #[test] fn turn_completion_overwrites_stale_final_message_from_turn_items() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let _ = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { item: ThreadItem::AgentMessage { @@ -1385,7 +1385,7 @@ fn turn_completion_overwrites_stale_final_message_from_turn_items() { #[test] fn turn_completion_preserves_streamed_final_message_when_turn_items_are_empty() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let _ = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { item: ThreadItem::AgentMessage { @@ -1425,7 +1425,7 @@ fn turn_completion_preserves_streamed_final_message_when_turn_items_are_empty() #[test] fn failed_turn_clears_stale_final_message() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ItemCompleted( ItemCompletedNotification { @@ -1465,7 +1465,7 @@ fn failed_turn_clears_stale_final_message() { #[test] fn turn_completion_falls_back_to_final_plan_text() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let completed = processor.collect_thread_events(ServerNotification::TurnCompleted( TurnCompletedNotification { @@ -1496,7 +1496,7 @@ fn turn_completion_falls_back_to_final_plan_text() { #[test] fn turn_failure_prefers_structured_error_message() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let error = processor.collect_thread_events(ServerNotification::Error(ErrorNotification { error: TurnError { @@ -1544,7 +1544,7 @@ fn turn_failure_prefers_structured_error_message() { #[test] fn model_reroute_surfaces_as_error_item() { - let mut processor = EventProcessorWithJsonOutput::new(None); + let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None); let collected = processor.collect_thread_events(ServerNotification::ModelRerouted( codex_app_server_protocol::ModelReroutedNotification { diff --git a/codex-rs/exec/tests/suite/sandbox.rs b/codex-rs/exec/tests/suite/sandbox.rs index 196fc68e8..81b2d44a1 100644 --- a/codex-rs/exec/tests/suite/sandbox.rs +++ b/codex-rs/exec/tests/suite/sandbox.rs @@ -27,7 +27,7 @@ async fn spawn_command_under_sandbox( sandbox_policy, sandbox_cwd, stdio_policy, - None, + /*network*/ None, env, ) .await diff --git a/codex-rs/execpolicy-legacy/src/execv_checker.rs b/codex-rs/execpolicy-legacy/src/execv_checker.rs index e84b92cac..a36003987 100644 --- a/codex-rs/execpolicy-legacy/src/execv_checker.rs +++ b/codex-rs/execpolicy-legacy/src/execv_checker.rs @@ -268,12 +268,13 @@ system_path=[{fake_cp:?}] program: "cp".into(), args: vec![ MatchedArg::new( - 0, + /*index*/ 0, ArgType::ReadableFile, root_path.parent().unwrap().to_str().unwrap(), ) .map_err(|e| anyhow!("{e:?}"))?, - MatchedArg::new(1, ArgType::WriteableFile, &dest).map_err(|e| anyhow!("{e:?}"))?, + MatchedArg::new(/*index*/ 1, ArgType::WriteableFile, &dest) + .map_err(|e| anyhow!("{e:?}"))?, ], ..Default::default() }; diff --git a/codex-rs/execpolicy-legacy/tests/suite/cp.rs b/codex-rs/execpolicy-legacy/tests/suite/cp.rs index 3cfc9ac5c..a0572ccd3 100644 --- a/codex-rs/execpolicy-legacy/tests/suite/cp.rs +++ b/codex-rs/execpolicy-legacy/tests/suite/cp.rs @@ -53,8 +53,8 @@ fn test_cp_one_file() -> Result<()> { exec: ValidExec::new( "cp", vec![ - MatchedArg::new(0, ArgType::ReadableFile, "foo/bar")?, - MatchedArg::new(1, ArgType::WriteableFile, "../baz")?, + MatchedArg::new(/*index*/ 0, ArgType::ReadableFile, "foo/bar")?, + MatchedArg::new(/*index*/ 1, ArgType::WriteableFile, "../baz")?, ], &["/bin/cp", "/usr/bin/cp"] ) @@ -73,9 +73,9 @@ fn test_cp_multiple_files() -> Result<()> { exec: ValidExec::new( "cp", vec![ - MatchedArg::new(0, ArgType::ReadableFile, "foo")?, - MatchedArg::new(1, ArgType::ReadableFile, "bar")?, - MatchedArg::new(2, ArgType::WriteableFile, "baz")?, + MatchedArg::new(/*index*/ 0, ArgType::ReadableFile, "foo")?, + MatchedArg::new(/*index*/ 1, ArgType::ReadableFile, "bar")?, + MatchedArg::new(/*index*/ 2, ArgType::WriteableFile, "baz")?, ], &["/bin/cp", "/usr/bin/cp"] ) diff --git a/codex-rs/execpolicy-legacy/tests/suite/head.rs b/codex-rs/execpolicy-legacy/tests/suite/head.rs index 390b4ddb3..4dbcd7200 100644 --- a/codex-rs/execpolicy-legacy/tests/suite/head.rs +++ b/codex-rs/execpolicy-legacy/tests/suite/head.rs @@ -47,7 +47,7 @@ fn test_head_one_file_no_flags() -> Result<()> { exec: ValidExec::new( "head", vec![MatchedArg::new( - 0, + /*index*/ 0, ArgType::ReadableFile, "src/extension.ts" )?], @@ -73,7 +73,7 @@ fn test_head_one_flag_one_file() -> Result<()> { .expect("should validate") ], args: vec![MatchedArg::new( - 2, + /*index*/ 2, ArgType::ReadableFile, "src/extension.ts" )?], diff --git a/codex-rs/execpolicy-legacy/tests/suite/literal.rs b/codex-rs/execpolicy-legacy/tests/suite/literal.rs index 296206dbc..d7dcb4413 100644 --- a/codex-rs/execpolicy-legacy/tests/suite/literal.rs +++ b/codex-rs/execpolicy-legacy/tests/suite/literal.rs @@ -25,9 +25,13 @@ define_program( exec: ValidExec::new( "fake_executable", vec![ - MatchedArg::new(0, ArgType::Literal("subcommand".to_string()), "subcommand")?, MatchedArg::new( - 1, + /*index*/ 0, + ArgType::Literal("subcommand".to_string()), + "subcommand" + )?, + MatchedArg::new( + /*index*/ 1, ArgType::Literal("sub-subcommand".to_string()), "sub-subcommand" )?, diff --git a/codex-rs/execpolicy-legacy/tests/suite/ls.rs b/codex-rs/execpolicy-legacy/tests/suite/ls.rs index b4b27b0e2..63c04d1c6 100644 --- a/codex-rs/execpolicy-legacy/tests/suite/ls.rs +++ b/codex-rs/execpolicy-legacy/tests/suite/ls.rs @@ -86,7 +86,11 @@ fn test_ls_one_file_arg() -> Result<()> { Ok(MatchedExec::Match { exec: ValidExec::new( "ls", - vec![MatchedArg::new(0, ArgType::ReadableFile, "foo")?], + vec![MatchedArg::new( + /*index*/ 0, + ArgType::ReadableFile, + "foo" + )?], &["/bin/ls", "/usr/bin/ls"] ) }), @@ -105,9 +109,9 @@ fn test_ls_multiple_file_args() -> Result<()> { exec: ValidExec::new( "ls", vec![ - MatchedArg::new(0, ArgType::ReadableFile, "foo")?, - MatchedArg::new(1, ArgType::ReadableFile, "bar")?, - MatchedArg::new(2, ArgType::ReadableFile, "baz")?, + MatchedArg::new(/*index*/ 0, ArgType::ReadableFile, "foo")?, + MatchedArg::new(/*index*/ 1, ArgType::ReadableFile, "bar")?, + MatchedArg::new(/*index*/ 2, ArgType::ReadableFile, "baz")?, ], &["/bin/ls", "/usr/bin/ls"] ) @@ -128,9 +132,9 @@ fn test_ls_multiple_flags_and_file_args() -> Result<()> { program: "ls".into(), flags: vec![MatchedFlag::new("-l"), MatchedFlag::new("-a")], args: vec![ - MatchedArg::new(2, ArgType::ReadableFile, "foo")?, - MatchedArg::new(3, ArgType::ReadableFile, "bar")?, - MatchedArg::new(4, ArgType::ReadableFile, "baz")?, + MatchedArg::new(/*index*/ 2, ArgType::ReadableFile, "foo")?, + MatchedArg::new(/*index*/ 3, ArgType::ReadableFile, "bar")?, + MatchedArg::new(/*index*/ 4, ArgType::ReadableFile, "baz")?, ], system_path: ["/bin/ls".into(), "/usr/bin/ls".into()].into(), ..Default::default() @@ -156,7 +160,11 @@ fn test_flags_after_file_args() -> Result<()> { exec: ValidExec { program: "ls".into(), flags: vec![MatchedFlag::new("-l")], - args: vec![MatchedArg::new(0, ArgType::ReadableFile, "foo")?], + args: vec![MatchedArg::new( + /*index*/ 0, + ArgType::ReadableFile, + "foo" + )?], system_path: ["/bin/ls".into(), "/usr/bin/ls".into()].into(), ..Default::default() } diff --git a/codex-rs/execpolicy-legacy/tests/suite/sed.rs b/codex-rs/execpolicy-legacy/tests/suite/sed.rs index d732cc7c9..94898afcd 100644 --- a/codex-rs/execpolicy-legacy/tests/suite/sed.rs +++ b/codex-rs/execpolicy-legacy/tests/suite/sed.rs @@ -27,8 +27,8 @@ fn test_sed_print_specific_lines() -> Result<()> { program: "sed".to_string(), flags: vec![MatchedFlag::new("-n")], args: vec![ - MatchedArg::new(1, ArgType::SedCommand, "122,202p")?, - MatchedArg::new(2, ArgType::ReadableFile, "hello.txt")?, + MatchedArg::new(/*index*/ 1, ArgType::SedCommand, "122,202p")?, + MatchedArg::new(/*index*/ 2, ArgType::ReadableFile, "hello.txt")?, ], system_path: vec!["/usr/bin/sed".to_string()], ..Default::default() @@ -52,7 +52,11 @@ fn test_sed_print_specific_lines_with_e_flag() -> Result<()> { MatchedOpt::new("-e", "122,202p", ArgType::SedCommand) .expect("should validate") ], - args: vec![MatchedArg::new(3, ArgType::ReadableFile, "hello.txt")?], + args: vec![MatchedArg::new( + /*index*/ 3, + ArgType::ReadableFile, + "hello.txt" + )?], system_path: vec!["/usr/bin/sed".to_string()], } }), diff --git a/codex-rs/execpolicy/src/amend.rs b/codex-rs/execpolicy/src/amend.rs index 2a6115c2f..7909fc14a 100644 --- a/codex-rs/execpolicy/src/amend.rs +++ b/codex-rs/execpolicy/src/amend.rs @@ -327,7 +327,7 @@ network_rule(host="api.github.com", protocol="https", decision="allow", justific "*.example.com", NetworkRuleProtocol::Https, Decision::Allow, - None, + /*justification*/ None, ) .expect_err("wildcards should be rejected"); assert_eq!( diff --git a/codex-rs/features/src/tests.rs b/codex-rs/features/src/tests.rs index ecfa87b41..5fdb03a77 100644 --- a/codex-rs/features/src/tests.rs +++ b/codex-rs/features/src/tests.rs @@ -195,10 +195,10 @@ fn enable_fanout_normalization_enables_multi_agent_one_way() { #[test] fn apps_require_feature_flag_and_chatgpt_auth() { let mut features = Features::with_defaults(); - assert!(!features.apps_enabled_for_auth(None)); + assert!(!features.apps_enabled_for_auth(/*auth*/ None)); features.enable(Feature::Apps); - assert!(!features.apps_enabled_for_auth(None)); + assert!(!features.apps_enabled_for_auth(/*auth*/ None)); let api_key_auth = codex_login::CodexAuth::from_api_key("test-api-key"); assert!(!features.apps_enabled_for_auth(Some(&api_key_auth))); @@ -256,7 +256,7 @@ fn unstable_warning_event_only_mentions_enabled_under_development_features() { let warning = unstable_features_warning_event( Some(&configured_features), - false, + /*suppress_unstable_features_warning*/ false, &features, "/tmp/config.toml", ) diff --git a/codex-rs/feedback/src/lib.rs b/codex-rs/feedback/src/lib.rs index dbd23dfbe..19c6abffd 100644 --- a/codex-rs/feedback/src/lib.rs +++ b/codex-rs/feedback/src/lib.rs @@ -490,13 +490,13 @@ mod tests { #[test] fn ring_buffer_drops_front_when_full() { - let fb = CodexFeedback::with_capacity(8); + let fb = CodexFeedback::with_capacity(/*max_bytes*/ 8); { let mut w = fb.make_writer().make_writer(); w.write_all(b"abcdefgh").unwrap(); w.write_all(b"ij").unwrap(); } - let snap = fb.snapshot(None); + let snap = fb.snapshot(/*session_id*/ None); // Capacity 8: after writing 10 bytes, we should keep the last 8. pretty_assertions::assert_eq!(std::str::from_utf8(snap.as_bytes()).unwrap(), "cdefghij"); } @@ -510,7 +510,7 @@ mod tests { tracing::info!(target: FEEDBACK_TAGS_TARGET, model = "gpt-5", cached = true, "tags"); - let snap = fb.snapshot(None); + let snap = fb.snapshot(/*session_id*/ None); pretty_assertions::assert_eq!(snap.tags.get("model").map(String::as_str), Some("gpt-5")); pretty_assertions::assert_eq!(snap.tags.get("cached").map(String::as_str), Some("true")); } @@ -522,14 +522,14 @@ mod tests { fs::write(&extra_path, "rollout").expect("extra attachment should be written"); let snapshot_with_diagnostics = CodexFeedback::new() - .snapshot(None) + .snapshot(/*session_id*/ None) .with_feedback_diagnostics(FeedbackDiagnostics::new(vec![FeedbackDiagnostic { headline: "OPENAI_BASE_URL is set and may affect connectivity.".to_string(), details: vec!["OPENAI_BASE_URL = https://example.com/v1".to_string()], }])); let attachments_with_diagnostics = snapshot_with_diagnostics.feedback_attachments( - true, + /*include_logs*/ true, std::slice::from_ref(&extra_path), Some(vec![1]), ); @@ -556,8 +556,8 @@ mod tests { OsStr::new(extra_filename.as_str()) ); let attachments_without_diagnostics = CodexFeedback::new() - .snapshot(None) - .feedback_attachments(true, &[], Some(vec![1])); + .snapshot(/*session_id*/ None) + .feedback_attachments(/*include_logs*/ true, &[], Some(vec![1])); assert_eq!( attachments_without_diagnostics diff --git a/codex-rs/file-search/src/lib.rs b/codex-rs/file-search/src/lib.rs index 64f4c19f7..83e5d9880 100644 --- a/codex-rs/file-search/src/lib.rs +++ b/codex-rs/file-search/src/lib.rs @@ -789,13 +789,13 @@ mod tests { #[test] fn session_scanned_file_count_is_monotonic_across_queries() { - let dir = create_temp_tree(200); + let dir = create_temp_tree(/*file_count*/ 200); let reporter = Arc::new(RecordingReporter::default()); let session = create_session( vec![dir.path().to_path_buf()], FileSearchOptions::default(), reporter.clone(), - None, + /*cancel_flag*/ None, ) .expect("session"); @@ -814,13 +814,13 @@ mod tests { #[test] fn session_streams_updates_before_walk_complete() { - let dir = create_temp_tree(600); + let dir = create_temp_tree(/*file_count*/ 600); let reporter = Arc::new(RecordingReporter::default()); let session = create_session( vec![dir.path().to_path_buf()], FileSearchOptions::default(), reporter.clone(), - None, + /*cancel_flag*/ None, ) .expect("session"); @@ -842,7 +842,7 @@ mod tests { vec![dir.path().to_path_buf()], FileSearchOptions::default(), reporter.clone(), - None, + /*cancel_flag*/ None, ) .expect("session"); @@ -873,7 +873,7 @@ mod tests { vec![dir.path().to_path_buf()], FileSearchOptions::default(), reporter.clone(), - None, + /*cancel_flag*/ None, ) .expect("session"); @@ -893,8 +893,8 @@ mod tests { #[test] fn dropping_session_does_not_cancel_siblings_with_shared_cancel_flag() { - let root_a = create_temp_tree(200); - let root_b = create_temp_tree(4_000); + let root_a = create_temp_tree(/*file_count*/ 200); + let root_b = create_temp_tree(/*file_count*/ 4_000); let cancel_flag = Arc::new(AtomicBool::new(false)); let reporter_a = Arc::new(RecordingReporter::default()); @@ -927,13 +927,13 @@ mod tests { #[test] fn session_emits_updates_when_query_changes() { - let dir = create_temp_tree(200); + let dir = create_temp_tree(/*file_count*/ 200); let reporter = Arc::new(RecordingReporter::default()); let session = create_session( vec![dir.path().to_path_buf()], FileSearchOptions::default(), reporter.clone(), - None, + /*cancel_flag*/ None, ) .expect("session"); @@ -953,7 +953,7 @@ mod tests { #[test] fn run_returns_matches_for_query() { - let dir = create_temp_tree(40); + let dir = create_temp_tree(/*file_count*/ 40); let options = FileSearchOptions { limit: NonZero::new(20).unwrap(), exclude: Vec::new(), @@ -961,8 +961,13 @@ mod tests { compute_indices: false, respect_gitignore: true, }; - let results = - run("file-000", vec![dir.path().to_path_buf()], options, None).expect("run ok"); + let results = run( + "file-000", + vec![dir.path().to_path_buf()], + options, + /*cancel_flag*/ None, + ) + .expect("run ok"); assert!(!results.matches.is_empty()); assert!(results.total_match_count >= results.matches.len()); @@ -991,7 +996,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); @@ -1003,7 +1008,7 @@ mod tests { #[test] fn cancel_exits_run() { - let dir = create_temp_tree(200); + let dir = create_temp_tree(/*file_count*/ 200); let cancel_flag = Arc::new(AtomicBool::new(true)); let search_dir = dir.path().to_path_buf(); let options = FileSearchOptions { @@ -1059,7 +1064,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); assert!( @@ -1079,7 +1084,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); assert!( @@ -1123,7 +1128,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); assert!( @@ -1143,7 +1148,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); assert!( @@ -1163,7 +1168,7 @@ mod tests { compute_indices: false, respect_gitignore: true, }, - None, + /*cancel_flag*/ None, ) .expect("run ok"); assert!( diff --git a/codex-rs/git-utils/src/ghost_commits.rs b/codex-rs/git-utils/src/ghost_commits.rs index 8cb5fad7d..c35cd44b4 100644 --- a/codex-rs/git-utils/src/ghost_commits.rs +++ b/codex-rs/git-utils/src/ghost_commits.rs @@ -997,7 +997,7 @@ mod tests { OsString::from("show"), OsString::from(format!("{}:ignored.txt", ghost.id())), ], - None, + /*env*/ None, )?; assert_eq!(cat, ignored_contents.trim()); @@ -1049,7 +1049,7 @@ mod tests { create_sparse_file(&big, big_size)?; let (ghost, report) = create_ghost_commit_with_report( - &CreateGhostCommitOptions::new(repo).ignore_large_untracked_files(1024), + &CreateGhostCommitOptions::new(repo).ignore_large_untracked_files(/*bytes*/ 1024), )?; assert!(ghost.parent().is_some()); assert_eq!( @@ -1183,7 +1183,8 @@ mod tests { std::fs::write(repo.join("ephemeral.txt"), "temp\n")?; restore_ghost_commit_with_options( - &RestoreGhostCommitOptions::new(repo).ignore_large_untracked_dirs(0), + &RestoreGhostCommitOptions::new(repo) + .ignore_large_untracked_dirs(/*file_count*/ 0), &ghost, )?; diff --git a/codex-rs/hooks/src/engine/dispatcher.rs b/codex-rs/hooks/src/engine/dispatcher.rs index 133fc4898..642231ff1 100644 --- a/codex-rs/hooks/src/engine/dispatcher.rs +++ b/codex-rs/hooks/src/engine/dispatcher.rs @@ -144,11 +144,21 @@ mod tests { #[test] fn select_handlers_keeps_duplicate_stop_handlers() { let handlers = vec![ - make_handler(HookEventName::Stop, None, "echo same", 0), - make_handler(HookEventName::Stop, None, "echo same", 1), + make_handler( + HookEventName::Stop, + /*matcher*/ None, + "echo same", + /*display_order*/ 0, + ), + make_handler( + HookEventName::Stop, + /*matcher*/ None, + "echo same", + /*display_order*/ 1, + ), ]; - let selected = select_handlers(&handlers, HookEventName::Stop, None); + let selected = select_handlers(&handlers, HookEventName::Stop, /*matcher_input*/ None); assert_eq!(selected.len(), 2); assert_eq!(selected[0].display_order, 0); @@ -158,12 +168,17 @@ mod tests { #[test] fn select_handlers_keeps_overlapping_session_start_matchers() { let handlers = vec![ - make_handler(HookEventName::SessionStart, Some("start.*"), "echo same", 0), + make_handler( + HookEventName::SessionStart, + Some("start.*"), + "echo same", + /*display_order*/ 0, + ), make_handler( HookEventName::SessionStart, Some("^startup$"), "echo same", - 1, + /*display_order*/ 1, ), ]; @@ -177,8 +192,18 @@ mod tests { #[test] fn pre_tool_use_matches_tool_name() { let handlers = vec![ - make_handler(HookEventName::PreToolUse, Some("^Bash$"), "echo same", 0), - make_handler(HookEventName::PreToolUse, Some("^Edit$"), "echo same", 1), + make_handler( + HookEventName::PreToolUse, + Some("^Bash$"), + "echo same", + /*display_order*/ 0, + ), + make_handler( + HookEventName::PreToolUse, + Some("^Edit$"), + "echo same", + /*display_order*/ 1, + ), ]; let selected = select_handlers(&handlers, HookEventName::PreToolUse, Some("Bash")); @@ -190,8 +215,18 @@ mod tests { #[test] fn post_tool_use_matches_tool_name() { let handlers = vec![ - make_handler(HookEventName::PostToolUse, Some("^Bash$"), "echo same", 0), - make_handler(HookEventName::PostToolUse, Some("^Edit$"), "echo same", 1), + make_handler( + HookEventName::PostToolUse, + Some("^Bash$"), + "echo same", + /*display_order*/ 0, + ), + make_handler( + HookEventName::PostToolUse, + Some("^Edit$"), + "echo same", + /*display_order*/ 1, + ), ]; let selected = select_handlers(&handlers, HookEventName::PostToolUse, Some("Bash")); @@ -203,8 +238,18 @@ mod tests { #[test] fn pre_tool_use_star_matcher_matches_all_tools() { let handlers = vec![ - make_handler(HookEventName::PreToolUse, Some("*"), "echo same", 0), - make_handler(HookEventName::PreToolUse, Some("^Edit$"), "echo same", 1), + make_handler( + HookEventName::PreToolUse, + Some("*"), + "echo same", + /*display_order*/ 0, + ), + make_handler( + HookEventName::PreToolUse, + Some("^Edit$"), + "echo same", + /*display_order*/ 1, + ), ]; let selected = select_handlers(&handlers, HookEventName::PreToolUse, Some("Bash")); @@ -219,7 +264,7 @@ mod tests { HookEventName::PreToolUse, Some("Edit|Write"), "echo same", - 0, + /*display_order*/ 0, )]; let selected_edit = select_handlers(&handlers, HookEventName::PreToolUse, Some("Edit")); @@ -238,12 +283,21 @@ mod tests { HookEventName::UserPromptSubmit, Some("^hello"), "echo first", - 0, + /*display_order*/ 0, + ), + make_handler( + HookEventName::UserPromptSubmit, + Some("["), + "echo second", + /*display_order*/ 1, ), - make_handler(HookEventName::UserPromptSubmit, Some("["), "echo second", 1), ]; - let selected = select_handlers(&handlers, HookEventName::UserPromptSubmit, None); + let selected = select_handlers( + &handlers, + HookEventName::UserPromptSubmit, + /*matcher_input*/ None, + ); assert_eq!(selected.len(), 2); assert_eq!(selected[0].display_order, 0); @@ -253,12 +307,27 @@ mod tests { #[test] fn select_handlers_preserves_declaration_order() { let handlers = vec![ - make_handler(HookEventName::Stop, None, "first", 0), - make_handler(HookEventName::Stop, None, "second", 1), - make_handler(HookEventName::Stop, None, "third", 2), + make_handler( + HookEventName::Stop, + /*matcher*/ None, + "first", + /*display_order*/ 0, + ), + make_handler( + HookEventName::Stop, + /*matcher*/ None, + "second", + /*display_order*/ 1, + ), + make_handler( + HookEventName::Stop, + /*matcher*/ None, + "third", + /*display_order*/ 2, + ), ]; - let selected = select_handlers(&handlers, HookEventName::Stop, None); + let selected = select_handlers(&handlers, HookEventName::Stop, /*matcher_input*/ None); assert_eq!(selected.len(), 3); assert_eq!(selected[0].command, "first"); diff --git a/codex-rs/hooks/src/events/common.rs b/codex-rs/hooks/src/events/common.rs index 48fbed242..8b6ba138e 100644 --- a/codex-rs/hooks/src/events/common.rs +++ b/codex-rs/hooks/src/events/common.rs @@ -117,8 +117,8 @@ mod tests { #[test] fn matcher_omitted_matches_all_occurrences() { - assert!(matches_matcher(None, Some("Bash"))); - assert!(matches_matcher(None, Some("Write"))); + assert!(matches_matcher(/*matcher*/ None, Some("Bash"))); + assert!(matches_matcher(/*matcher*/ None, Some("Write"))); } #[test] diff --git a/codex-rs/hooks/src/events/session_start.rs b/codex-rs/hooks/src/events/session_start.rs index 6b8fcad1e..057c5d0e7 100644 --- a/codex-rs/hooks/src/events/session_start.rs +++ b/codex-rs/hooks/src/events/session_start.rs @@ -263,7 +263,7 @@ mod tests { let parsed = parse_completed( &handler(), run_result(Some(0), "hello from hook\n", ""), - None, + /*turn_id*/ None, ); assert_eq!( @@ -293,7 +293,7 @@ mod tests { r#"{"continue":false,"stopReason":"pause","hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"do not inject"}}"#, "", ), - None, + /*turn_id*/ None, ); assert_eq!( @@ -329,7 +329,7 @@ mod tests { r#"{"hookSpecificOutput":{"hookEventName":"SessionStart""#, "", ), - None, + /*turn_id*/ None, ); assert_eq!( diff --git a/codex-rs/hooks/src/events/stop.rs b/codex-rs/hooks/src/events/stop.rs index 3d94e321c..5eba1414b 100644 --- a/codex-rs/hooks/src/events/stop.rs +++ b/codex-rs/hooks/src/events/stop.rs @@ -424,7 +424,11 @@ mod tests { #[test] fn exit_code_two_without_stderr_does_not_block() { - let parsed = parse_completed(&handler(), run_result(Some(2), "", " "), None); + let parsed = parse_completed( + &handler(), + run_result(Some(2), "", " "), + /*turn_id*/ None, + ); assert_eq!(parsed.data, StopHandlerData::default()); assert_eq!(parsed.completed.run.status, HookRunStatus::Failed); diff --git a/codex-rs/linux-sandbox/src/linux_run_main_tests.rs b/codex-rs/linux-sandbox/src/linux_run_main_tests.rs index d8b84ffba..96c3c8a73 100644 --- a/codex-rs/linux-sandbox/src/linux_run_main_tests.rs +++ b/codex-rs/linux-sandbox/src/linux_run_main_tests.rs @@ -53,7 +53,7 @@ fn inserts_bwrap_argv0_before_command_separator() { .args; apply_inner_command_argv0_for_launcher( &mut argv, - true, + /*supports_argv0*/ true, "/tmp/codex-arg0-session/codex-linux-sandbox".to_string(), ); assert_eq!( @@ -95,7 +95,7 @@ fn rewrites_inner_command_path_when_bwrap_lacks_argv0() { .args; apply_inner_command_argv0_for_launcher( &mut argv, - false, + /*supports_argv0*/ false, "/tmp/codex-arg0-session/codex-linux-sandbox".to_string(), ); @@ -126,7 +126,7 @@ fn rewrites_bwrap_helper_command_not_nested_user_command_when_current_exe_appear apply_inner_command_argv0_for_launcher( &mut argv, - false, + /*supports_argv0*/ false, "/tmp/argv0-fallback-helper".to_string(), ); @@ -182,7 +182,10 @@ fn inserts_unshare_net_when_proxy_only_network_mode_requested() { #[test] fn proxy_only_mode_takes_precedence_over_full_network_policy() { - let mode = bwrap_network_mode(NetworkSandboxPolicy::Enabled, true); + let mode = bwrap_network_mode( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ true, + ); assert_eq!(mode, BwrapNetworkMode::ProxyOnly); } @@ -236,7 +239,10 @@ fn root_write_read_only_carveout_requires_direct_runtime_enforcement() { #[test] fn managed_proxy_preflight_argv_is_wrapped_for_full_access_policy() { - let mode = bwrap_network_mode(NetworkSandboxPolicy::Enabled, true); + let mode = bwrap_network_mode( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ true, + ); let argv = build_preflight_bwrap_argv( Path::new("/"), Path::new("/"), @@ -326,9 +332,13 @@ fn managed_proxy_inner_command_requires_route_spec() { fn resolve_sandbox_policies_derives_split_policies_from_legacy_policy() { let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let resolved = - resolve_sandbox_policies(Path::new("/tmp"), Some(sandbox_policy.clone()), None, None) - .expect("legacy policy should resolve"); + let resolved = resolve_sandbox_policies( + Path::new("/tmp"), + Some(sandbox_policy.clone()), + /*file_system_sandbox_policy*/ None, + /*network_sandbox_policy*/ None, + ) + .expect("legacy policy should resolve"); assert_eq!(resolved.sandbox_policy, sandbox_policy); assert_eq!( @@ -349,7 +359,7 @@ fn resolve_sandbox_policies_derives_legacy_policy_from_split_policies() { let resolved = resolve_sandbox_policies( Path::new("/tmp"), - None, + /*sandbox_policy*/ None, Some(file_system_sandbox_policy.clone()), Some(network_sandbox_policy), ) @@ -369,7 +379,7 @@ fn resolve_sandbox_policies_rejects_partial_split_policies() { Path::new("/tmp"), Some(SandboxPolicy::new_read_only_policy()), Some(FileSystemSandboxPolicy::default()), - None, + /*network_sandbox_policy*/ None, ) .expect_err("partial split policies should fail"); @@ -471,7 +481,11 @@ fn resolve_sandbox_policies_accepts_semantically_equivalent_workspace_write_inpu #[test] fn apply_seccomp_then_exec_with_legacy_landlock_panics() { - let result = std::panic::catch_unwind(|| ensure_inner_stage_mode_is_valid(true, true)); + let result = std::panic::catch_unwind(|| { + ensure_inner_stage_mode_is_valid( + /*apply_seccomp_then_exec*/ true, /*use_legacy_landlock*/ true, + ) + }); assert!(result.is_err()); } @@ -496,7 +510,7 @@ fn legacy_landlock_rejects_split_only_filesystem_policies() { let result = std::panic::catch_unwind(|| { ensure_legacy_landlock_mode_supports_policy( - true, + /*use_legacy_landlock*/ true, &policy, NetworkSandboxPolicy::Restricted, temp_dir.path(), @@ -508,7 +522,13 @@ fn legacy_landlock_rejects_split_only_filesystem_policies() { #[test] fn valid_inner_stage_modes_do_not_panic() { - ensure_inner_stage_mode_is_valid(false, false); - ensure_inner_stage_mode_is_valid(false, true); - ensure_inner_stage_mode_is_valid(true, false); + ensure_inner_stage_mode_is_valid( + /*apply_seccomp_then_exec*/ false, /*use_legacy_landlock*/ false, + ); + ensure_inner_stage_mode_is_valid( + /*apply_seccomp_then_exec*/ false, /*use_legacy_landlock*/ true, + ); + ensure_inner_stage_mode_is_valid( + /*apply_seccomp_then_exec*/ true, /*use_legacy_landlock*/ false, + ); } diff --git a/codex-rs/login/src/auth/auth_tests.rs b/codex-rs/login/src/auth/auth_tests.rs index d467e07de..ef0238d3c 100644 --- a/codex-rs/login/src/auth/auth_tests.rs +++ b/codex-rs/login/src/auth/auth_tests.rs @@ -33,7 +33,7 @@ async fn refresh_without_id_token() { ); let updated = super::persist_tokens( &storage, - None, + /*id_token*/ None, Some("new-access-token".to_string()), Some("new-refresh-token".to_string()), ) @@ -97,9 +97,13 @@ async fn pro_account_with_no_api_key_uses_chatgpt_auth() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .unwrap() - .unwrap(); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .unwrap() + .unwrap(); assert_eq!(None, auth.api_key()); assert_eq!(crate::AuthMode::Chatgpt, auth.auth_mode()); assert_eq!(auth.get_chatgpt_user_id().as_deref(), Some("user-12345")); @@ -144,9 +148,13 @@ async fn loads_api_key_from_auth_json() { ) .unwrap(); - let auth = super::load_auth(dir.path(), false, AuthCredentialsStoreMode::File) - .unwrap() - .unwrap(); + let auth = super::load_auth( + dir.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .unwrap() + .unwrap(); assert_eq!(auth.auth_mode(), crate::AuthMode::ApiKey); assert_eq!(auth.api_key(), Some("sk-test-key")); @@ -175,7 +183,7 @@ fn unauthorized_recovery_reports_mode_and_step_names() { let dir = tempdir().unwrap(); let manager = AuthManager::shared( dir.path().to_path_buf(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, ); let managed = UnauthorizedRecovery { @@ -210,9 +218,13 @@ fn refresh_failure_is_scoped_to_the_matching_auth_snapshot() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); let mut updated_auth_dot_json = auth .get_current_auth_json() .expect("AuthDotJson should exist"); @@ -347,7 +359,12 @@ async fn enforce_login_restrictions_logs_out_for_method_mismatch() { login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File) .expect("seed api key"); - let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None).await; + let config = build_config( + codex_home.path(), + Some(ForcedLoginMethod::Chatgpt), + /*forced_chatgpt_workspace_id*/ None, + ) + .await; let err = super::enforce_login_restrictions(&config).expect_err("expected method mismatch to error"); @@ -372,7 +389,12 @@ async fn enforce_login_restrictions_logs_out_for_workspace_mismatch() { ) .expect("failed to write auth file"); - let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await; + let config = build_config( + codex_home.path(), + /*forced_login_method*/ None, + Some("org_mine".to_string()), + ) + .await; let err = super::enforce_login_restrictions(&config) .expect_err("expected workspace mismatch to error"); @@ -397,7 +419,12 @@ async fn enforce_login_restrictions_allows_matching_workspace() { ) .expect("failed to write auth file"); - let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await; + let config = build_config( + codex_home.path(), + /*forced_login_method*/ None, + Some("org_mine".to_string()), + ) + .await; super::enforce_login_restrictions(&config).expect("matching workspace should succeed"); assert!( @@ -413,7 +440,12 @@ async fn enforce_login_restrictions_allows_api_key_if_login_method_not_set_but_f login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File) .expect("seed api key"); - let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await; + let config = build_config( + codex_home.path(), + /*forced_login_method*/ None, + Some("org_mine".to_string()), + ) + .await; super::enforce_login_restrictions(&config).expect("matching workspace should succeed"); assert!( @@ -428,7 +460,12 @@ async fn enforce_login_restrictions_blocks_env_api_key_when_chatgpt_required() { let _guard = EnvVarGuard::set(CODEX_API_KEY_ENV_VAR, "sk-env"); let codex_home = tempdir().unwrap(); - let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None).await; + let config = build_config( + codex_home.path(), + Some(ForcedLoginMethod::Chatgpt), + /*forced_chatgpt_workspace_id*/ None, + ) + .await; let err = super::enforce_login_restrictions(&config) .expect_err("environment API key should not satisfy forced ChatGPT login"); @@ -451,9 +488,13 @@ fn plan_type_maps_known_plan() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); pretty_assertions::assert_eq!(auth.account_plan_type(), Some(AccountPlanType::Pro)); } @@ -471,9 +512,13 @@ fn plan_type_maps_self_serve_business_usage_based_plan() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); pretty_assertions::assert_eq!( auth.account_plan_type(), @@ -494,9 +539,13 @@ fn plan_type_maps_enterprise_cbp_usage_based_plan() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); pretty_assertions::assert_eq!( auth.account_plan_type(), @@ -517,9 +566,13 @@ fn plan_type_maps_unknown_to_unknown() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); pretty_assertions::assert_eq!(auth.account_plan_type(), Some(AccountPlanType::Unknown)); } @@ -537,9 +590,13 @@ fn missing_plan_type_maps_to_unknown() { ) .expect("failed to write auth file"); - let auth = super::load_auth(codex_home.path(), false, AuthCredentialsStoreMode::File) - .expect("load auth") - .expect("auth available"); + let auth = super::load_auth( + codex_home.path(), + /*enable_codex_api_key_env*/ false, + AuthCredentialsStoreMode::File, + ) + .expect("load auth") + .expect("auth available"); pretty_assertions::assert_eq!(auth.account_plan_type(), Some(AccountPlanType::Unknown)); } diff --git a/codex-rs/login/src/auth/default_client_tests.rs b/codex-rs/login/src/auth/default_client_tests.rs index e534efa8f..6a0ce1432 100644 --- a/codex-rs/login/src/auth/default_client_tests.rs +++ b/codex-rs/login/src/auth/default_client_tests.rs @@ -85,7 +85,7 @@ async fn test_create_client_sets_default_headers() { .expect("residency header missing"); assert_eq!(residency_header.to_str().unwrap(), "us"); - set_default_client_residency_requirement(None); + set_default_client_residency_requirement(/*enforce_residency*/ None); } #[test] diff --git a/codex-rs/login/tests/suite/device_code_login.rs b/codex-rs/login/tests/suite/device_code_login.rs index a87998697..80c4fc0e5 100644 --- a/codex-rs/login/tests/suite/device_code_login.rs +++ b/codex-rs/login/tests/suite/device_code_login.rs @@ -105,7 +105,7 @@ fn server_opts( let mut opts = ServerOptions::new( codex_home.path().to_path_buf(), "client-id".to_string(), - None, + /*forced_chatgpt_workspace_id*/ None, cli_auth_credentials_store_mode, ); opts.issuer = issuer; @@ -122,7 +122,12 @@ async fn device_code_login_integration_succeeds() -> anyhow::Result<()> { mock_usercode_success(&mock_server).await; - mock_poll_token_two_step(&mock_server, Arc::new(AtomicUsize::new(0)), 404).await; + mock_poll_token_two_step( + &mock_server, + Arc::new(AtomicUsize::new(0)), + /*first_response_status*/ 404, + ) + .await; let jwt = make_jwt(json!({ "https://api.openai.com/auth": { @@ -160,7 +165,12 @@ async fn device_code_login_rejects_workspace_mismatch() -> anyhow::Result<()> { mock_usercode_success(&mock_server).await; - mock_poll_token_two_step(&mock_server, Arc::new(AtomicUsize::new(0)), 404).await; + mock_poll_token_two_step( + &mock_server, + Arc::new(AtomicUsize::new(0)), + /*first_response_status*/ 404, + ) + .await; let jwt = make_jwt(json!({ "https://api.openai.com/auth": { @@ -196,7 +206,7 @@ async fn device_code_login_integration_handles_usercode_http_failure() -> anyhow let codex_home = tempdir().unwrap(); let mock_server = MockServer::start().await; - mock_usercode_failure(&mock_server, 503).await; + mock_usercode_failure(&mock_server, /*status*/ 503).await; let issuer = mock_server.uri(); @@ -231,7 +241,12 @@ async fn device_code_login_integration_persists_without_api_key_on_exchange_fail mock_usercode_success(&mock_server).await; - mock_poll_token_two_step(&mock_server, Arc::new(AtomicUsize::new(0)), 404).await; + mock_poll_token_two_step( + &mock_server, + Arc::new(AtomicUsize::new(0)), + /*first_response_status*/ 404, + ) + .await; let jwt = make_jwt(json!({})); @@ -242,7 +257,7 @@ async fn device_code_login_integration_persists_without_api_key_on_exchange_fail let mut opts = ServerOptions::new( codex_home.path().to_path_buf(), "client-id".to_string(), - None, + /*forced_chatgpt_workspace_id*/ None, AuthCredentialsStoreMode::File, ); opts.issuer = issuer; @@ -292,7 +307,7 @@ async fn device_code_login_integration_handles_error_payload() -> anyhow::Result let mut opts = ServerOptions::new( codex_home.path().to_path_buf(), "client-id".to_string(), - None, + /*forced_chatgpt_workspace_id*/ None, AuthCredentialsStoreMode::File, ); opts.issuer = issuer; diff --git a/codex-rs/mcp-server/src/codex_tool_runner.rs b/codex-rs/mcp-server/src/codex_tool_runner.rs index ae9d26e99..a08f93007 100644 --- a/codex-rs/mcp-server/src/codex_tool_runner.rs +++ b/codex-rs/mcp-server/src/codex_tool_runner.rs @@ -421,7 +421,11 @@ mod tests { #[test] fn call_tool_result_includes_thread_id_in_structured_content() { let thread_id = ThreadId::new(); - let result = create_call_tool_result_with_thread_id(thread_id, "done".to_string(), None); + let result = create_call_tool_result_with_thread_id( + thread_id, + "done".to_string(), + /*is_error*/ None, + ); assert_eq!( result.structured_content, Some(json!({ diff --git a/codex-rs/mcp-server/src/outgoing_message.rs b/codex-rs/mcp-server/src/outgoing_message.rs index b862884c0..6f93abea6 100644 --- a/codex-rs/mcp-server/src/outgoing_message.rs +++ b/codex-rs/mcp-server/src/outgoing_message.rs @@ -315,7 +315,7 @@ mod tests { }; outgoing_message_sender - .send_event_as_notification(&event, None) + .send_event_as_notification(&event, /*meta*/ None) .await; let result = outgoing_rx.recv().await.unwrap(); diff --git a/codex-rs/mcp-server/tests/suite/codex_tool.rs b/codex-rs/mcp-server/tests/suite/codex_tool.rs index c6df62dbf..04763b884 100644 --- a/codex-rs/mcp-server/tests/suite/codex_tool.rs +++ b/codex-rs/mcp-server/tests/suite/codex_tool.rs @@ -287,8 +287,8 @@ async fn patch_approval_triggers_elicitation() -> anyhow::Result<()> { elicitation_request.request.params, Some(create_expected_patch_approval_elicitation_request_params( expected_changes, - None, // No grant_root expected - None, // No reason expected + /*grant_root*/ None, // No grant_root expected + /*reason*/ None, // No reason expected codex_request_id.to_string(), params.codex_event_id.clone(), params.thread_id, diff --git a/codex-rs/network-proxy/src/config.rs b/codex-rs/network-proxy/src/config.rs index b081abb15..1b80b80fd 100644 --- a/codex-rs/network-proxy/src/config.rs +++ b/codex-rs/network-proxy/src/config.rs @@ -659,18 +659,18 @@ mod tests { #[test] fn parse_host_port_defaults_for_empty_string() { - assert!(parse_host_port("", 1234).is_err()); + assert!(parse_host_port("", /*default_port*/ 1234).is_err()); } #[test] fn parse_host_port_defaults_for_whitespace() { - assert!(parse_host_port(" ", 5555).is_err()); + assert!(parse_host_port(" ", /*default_port*/ 5555).is_err()); } #[test] fn parse_host_port_parses_host_port_without_scheme() { assert_eq!( - parse_host_port("127.0.0.1:8080", 3128).unwrap(), + parse_host_port("127.0.0.1:8080", /*default_port*/ 3128).unwrap(), SocketAddressParts { host: "127.0.0.1".to_string(), port: 8080, @@ -681,7 +681,11 @@ mod tests { #[test] fn parse_host_port_parses_host_port_with_scheme_and_path() { assert_eq!( - parse_host_port("http://example.com:8080/some/path", 3128).unwrap(), + parse_host_port( + "http://example.com:8080/some/path", + /*default_port*/ 3128 + ) + .unwrap(), SocketAddressParts { host: "example.com".to_string(), port: 8080, @@ -692,7 +696,11 @@ mod tests { #[test] fn parse_host_port_strips_userinfo() { assert_eq!( - parse_host_port("http://user:pass@host.example:5555", 3128).unwrap(), + parse_host_port( + "http://user:pass@host.example:5555", + /*default_port*/ 3128 + ) + .unwrap(), SocketAddressParts { host: "host.example".to_string(), port: 5555, @@ -703,7 +711,7 @@ mod tests { #[test] fn parse_host_port_parses_ipv6_with_brackets() { assert_eq!( - parse_host_port("http://[::1]:9999", 3128).unwrap(), + parse_host_port("http://[::1]:9999", /*default_port*/ 3128).unwrap(), SocketAddressParts { host: "::1".to_string(), port: 9999, @@ -714,7 +722,7 @@ mod tests { #[test] fn parse_host_port_does_not_treat_unbracketed_ipv6_as_host_port() { assert_eq!( - parse_host_port("2001:db8::1", 3128).unwrap(), + parse_host_port("2001:db8::1", /*default_port*/ 3128).unwrap(), SocketAddressParts { host: "2001:db8::1".to_string(), port: 3128, @@ -725,7 +733,7 @@ mod tests { #[test] fn parse_host_port_falls_back_to_default_port_when_port_is_invalid() { assert_eq!( - parse_host_port("example.com:notaport", 3128).unwrap(), + parse_host_port("example.com:notaport", /*default_port*/ 3128).unwrap(), SocketAddressParts { host: "example.com".to_string(), port: 3128, @@ -735,13 +743,16 @@ mod tests { #[test] fn host_and_port_from_network_addr_defaults_for_empty_string() { - assert_eq!(host_and_port_from_network_addr("", 1234), ""); + assert_eq!( + host_and_port_from_network_addr("", /*default_port*/ 1234), + "" + ); } #[test] fn host_and_port_from_network_addr_formats_ipv6() { assert_eq!( - host_and_port_from_network_addr("http://[::1]:8080", 3128), + host_and_port_from_network_addr("http://[::1]:8080", /*default_port*/ 3128), "[::1]:8080" ); } @@ -749,7 +760,7 @@ mod tests { #[test] fn resolve_addr_maps_localhost_to_loopback() { assert_eq!( - resolve_addr("localhost", 3128).unwrap(), + resolve_addr("localhost", /*default_port*/ 3128).unwrap(), "127.0.0.1:3128".parse::().unwrap() ); } @@ -757,7 +768,7 @@ mod tests { #[test] fn resolve_addr_parses_ip_literals() { assert_eq!( - resolve_addr("1.2.3.4", 80).unwrap(), + resolve_addr("1.2.3.4", /*default_port*/ 80).unwrap(), "1.2.3.4:80".parse::().unwrap() ); } @@ -765,7 +776,7 @@ mod tests { #[test] fn resolve_addr_parses_ipv6_literals() { assert_eq!( - resolve_addr("http://[::1]:8080", 3128).unwrap(), + resolve_addr("http://[::1]:8080", /*default_port*/ 3128).unwrap(), "[::1]:8080".parse::().unwrap() ); } @@ -773,7 +784,7 @@ mod tests { #[test] fn resolve_addr_falls_back_to_loopback_for_hostnames() { assert_eq!( - resolve_addr("http://example.com:5555", 3128).unwrap(), + resolve_addr("http://example.com:5555", /*default_port*/ 3128).unwrap(), "127.0.0.1:5555".parse::().unwrap() ); } diff --git a/codex-rs/network-proxy/src/http_proxy.rs b/codex-rs/network-proxy/src/http_proxy.rs index 1be610feb..a29af08b1 100644 --- a/codex-rs/network-proxy/src/http_proxy.rs +++ b/codex-rs/network-proxy/src/http_proxy.rs @@ -1018,7 +1018,9 @@ mod tests { .unwrap(); req.extensions_mut().insert(state); - let response = http_connect_accept(None, req).await.unwrap_err(); + let response = http_connect_accept(/*policy_decider*/ None, req) + .await + .unwrap_err(); assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_eq!( response.headers().get("x-proxy-error").unwrap(), @@ -1043,7 +1045,9 @@ mod tests { .unwrap(); req.extensions_mut().insert(state); - let (response, _request) = http_connect_accept(None, req).await.unwrap(); + let (response, _request) = http_connect_accept(/*policy_decider*/ None, req) + .await + .unwrap(); assert_eq!(response.status(), StatusCode::OK); } @@ -1075,7 +1079,9 @@ mod tests { let proxy_addr = listener .local_addr() .expect("proxy listener should expose local addr"); - let proxy_task = tokio::spawn(run_http_proxy_with_std_listener(state, listener, None)); + let proxy_task = tokio::spawn(run_http_proxy_with_std_listener( + state, listener, /*policy_decider*/ None, + )); let mut stream = tokio::net::TcpStream::connect(proxy_addr) .await @@ -1125,7 +1131,9 @@ mod tests { .expect("request should build"); req.extensions_mut().insert(state); - let response = http_plain_proxy(None, req).await.unwrap(); + let response = http_plain_proxy(/*policy_decider*/ None, req) + .await + .unwrap(); assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_eq!( @@ -1148,7 +1156,9 @@ mod tests { .expect("request should build"); req.extensions_mut().insert(state); - let response = http_plain_proxy(None, req).await.unwrap(); + let response = http_plain_proxy(/*policy_decider*/ None, req) + .await + .unwrap(); if cfg!(target_os = "macos") { assert_eq!(response.status(), StatusCode::FORBIDDEN); @@ -1178,7 +1188,9 @@ mod tests { .expect("request should build"); req.extensions_mut().insert(state); - let response = http_plain_proxy(None, req).await.unwrap(); + let response = http_plain_proxy(/*policy_decider*/ None, req) + .await + .unwrap(); assert_eq!(response.status(), StatusCode::BAD_GATEWAY); } @@ -1200,7 +1212,9 @@ mod tests { .unwrap(); req.extensions_mut().insert(state); - let response = http_connect_accept(None, req).await.unwrap_err(); + let response = http_connect_accept(/*policy_decider*/ None, req) + .await + .unwrap_err(); assert_eq!(response.status(), StatusCode::FORBIDDEN); assert_eq!( response.headers().get("x-proxy-error").unwrap(), @@ -1221,7 +1235,7 @@ mod tests { .unwrap(); req.extensions_mut().insert(state); - let response = http_plain_proxy(None, req).await; + let response = http_plain_proxy(/*policy_decider*/ None, req).await; assert_eq!(response.unwrap().status(), StatusCode::BAD_REQUEST); } diff --git a/codex-rs/network-proxy/src/mitm_tests.rs b/codex-rs/network-proxy/src/mitm_tests.rs index 28eb5c5f7..862372075 100644 --- a/codex-rs/network-proxy/src/mitm_tests.rs +++ b/codex-rs/network-proxy/src/mitm_tests.rs @@ -31,7 +31,12 @@ async fn mitm_policy_blocks_disallowed_method_and_records_telemetry() { network.set_allowed_domains(vec!["example.com".to_string()]); network })); - let ctx = policy_ctx(app_state.clone(), NetworkMode::Limited, "example.com", 443); + let ctx = policy_ctx( + app_state.clone(), + NetworkMode::Limited, + "example.com", + /*target_port*/ 443, + ); let req = Request::builder() .method(Method::POST) .uri("/v1/responses?api_key=secret") @@ -65,7 +70,12 @@ async fn mitm_policy_rejects_host_mismatch() { network.set_allowed_domains(vec!["example.com".to_string()]); network })); - let ctx = policy_ctx(app_state.clone(), NetworkMode::Full, "example.com", 443); + let ctx = policy_ctx( + app_state.clone(), + NetworkMode::Full, + "example.com", + /*target_port*/ 443, + ); let req = Request::builder() .method(Method::GET) .uri("/") @@ -90,7 +100,12 @@ async fn mitm_policy_rechecks_local_private_target_after_connect() { network.allow_local_binding = false; network })); - let ctx = policy_ctx(app_state.clone(), NetworkMode::Full, "10.0.0.1", 443); + let ctx = policy_ctx( + app_state.clone(), + NetworkMode::Full, + "10.0.0.1", + /*target_port*/ 443, + ); let req = Request::builder() .method(Method::GET) .uri("/health?token=secret") diff --git a/codex-rs/network-proxy/src/network_policy.rs b/codex-rs/network-proxy/src/network_policy.rs index f9670c055..936abf3e2 100644 --- a/codex-rs/network-proxy/src/network_policy.rs +++ b/codex-rs/network-proxy/src/network_policy.rs @@ -693,7 +693,9 @@ mod tests { }); let (decision, events) = capture_events(|| async { - evaluate_host_policy(&state, None, &request).await.unwrap() + evaluate_host_policy(&state, /*decider*/ None, &request) + .await + .unwrap() }) .await; assert_eq!( @@ -784,7 +786,9 @@ mod tests { }); let (_decision, events) = capture_events(|| async { - evaluate_host_policy(&state, None, &request).await.unwrap() + evaluate_host_policy(&state, /*decider*/ None, &request) + .await + .unwrap() }) .await; @@ -867,7 +871,9 @@ mod tests { exec_policy_hint: None, }); - let decision = evaluate_host_policy(&state, None, &request).await.unwrap(); + let decision = evaluate_host_policy(&state, /*decider*/ None, &request) + .await + .unwrap(); assert_eq!( decision, NetworkDecision::Deny { diff --git a/codex-rs/network-proxy/src/proxy.rs b/codex-rs/network-proxy/src/proxy.rs index 3dc6f6bad..715e762b5 100644 --- a/codex-rs/network-proxy/src/proxy.rs +++ b/codex-rs/network-proxy/src/proxy.rs @@ -705,7 +705,7 @@ mod tests { let state = Arc::new(network_proxy_state_for_policy(settings)); let proxy = NetworkProxy::builder() .state(state) - .managed_by_codex(false) + .managed_by_codex(/*managed_by_codex*/ false) .build() .await .unwrap(); @@ -839,8 +839,8 @@ mod tests { &mut env, SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 3128), SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081), - true, - false, + /*socks_enabled*/ true, + /*allow_local_binding*/ false, ); assert_eq!( @@ -889,8 +889,8 @@ mod tests { &mut env, SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 3128), SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081), - false, - true, + /*socks_enabled*/ false, + /*allow_local_binding*/ true, ); assert_eq!( @@ -907,8 +907,8 @@ mod tests { &mut env, SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 3128), SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081), - true, - false, + /*socks_enabled*/ true, + /*allow_local_binding*/ false, ); assert_eq!( @@ -952,8 +952,8 @@ mod tests { &mut env, SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 3128), SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081), - true, - false, + /*socks_enabled*/ true, + /*allow_local_binding*/ false, ); assert_eq!( diff --git a/codex-rs/network-proxy/src/runtime.rs b/codex-rs/network-proxy/src/runtime.rs index c03c3da4a..e96783256 100644 --- a/codex-rs/network-proxy/src/runtime.rs +++ b/codex-rs/network-proxy/src/runtime.rs @@ -878,7 +878,10 @@ mod tests { network_proxy_state_for_policy(network_settings(&["example.com"], &["example.com"])); assert_eq!( - state.host_blocked("example.com", 80).await.unwrap(), + state + .host_blocked("example.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Blocked(HostBlockReason::Denied) ); } @@ -888,13 +891,16 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["example.com"], &[])); assert_eq!( - state.host_blocked("example.com", 80).await.unwrap(), + state + .host_blocked("example.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Allowed ); assert_eq!( // Use a public IP literal to avoid relying on ambient DNS behavior (some networks // resolve unknown hostnames to private IPs, which would trigger `not_allowed_local`). - state.host_blocked("8.8.8.8", 80).await.unwrap(), + state.host_blocked("8.8.8.8", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowed) ); } @@ -909,7 +915,10 @@ mod tests { assert_eq!(allowed, vec!["example.com".to_string()]); assert!(denied.is_empty()); assert_eq!( - state.host_blocked("example.com", 80).await.unwrap(), + state + .host_blocked("example.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Allowed ); } @@ -924,7 +933,10 @@ mod tests { assert!(allowed.is_empty()); assert_eq!(denied, vec!["example.com".to_string()]); assert_eq!( - state.host_blocked("example.com", 80).await.unwrap(), + state + .host_blocked("example.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Blocked(HostBlockReason::Denied) ); } @@ -935,7 +947,7 @@ mod tests { assert_eq!( // Use a public IP literal to avoid relying on ambient DNS behavior. - state.host_blocked("8.8.8.8", 80).await.unwrap(), + state.host_blocked("8.8.8.8", /*port*/ 80).await.unwrap(), HostBlockDecision::Allowed ); @@ -945,7 +957,7 @@ mod tests { assert_eq!(allowed, vec!["*".to_string()]); assert_eq!(denied, vec!["8.8.8.8".to_string()]); assert_eq!( - state.host_blocked("8.8.8.8", 80).await.unwrap(), + state.host_blocked("8.8.8.8", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::Denied) ); } @@ -1133,11 +1145,14 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["*.openai.com"], &[])); assert_eq!( - state.host_blocked("api.openai.com", 80).await.unwrap(), + state + .host_blocked("api.openai.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Allowed ); assert_eq!( - state.host_blocked("openai.com", 80).await.unwrap(), + state.host_blocked("openai.com", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowed) ); } @@ -1147,15 +1162,24 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["*"], &["evil.example"])); assert_eq!( - state.host_blocked("example.com", 80).await.unwrap(), + state + .host_blocked("example.com", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Allowed ); assert_eq!( - state.host_blocked("api.openai.com", 443).await.unwrap(), + state + .host_blocked("api.openai.com", /*port*/ 443) + .await + .unwrap(), HostBlockDecision::Allowed ); assert_eq!( - state.host_blocked("evil.example", 80).await.unwrap(), + state + .host_blocked("evil.example", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Blocked(HostBlockReason::Denied) ); } @@ -1165,11 +1189,11 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["example.com"], &[])); assert_eq!( - state.host_blocked("127.0.0.1", 80).await.unwrap(), + state.host_blocked("127.0.0.1", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) ); assert_eq!( - state.host_blocked("localhost", 80).await.unwrap(), + state.host_blocked("localhost", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) ); } @@ -1179,7 +1203,7 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["localhost"], &[])); assert_eq!( - state.host_blocked("localhost", 80).await.unwrap(), + state.host_blocked("localhost", /*port*/ 80).await.unwrap(), HostBlockDecision::Allowed ); } @@ -1189,7 +1213,7 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["10.0.0.1"], &[])); assert_eq!( - state.host_blocked("10.0.0.1", 80).await.unwrap(), + state.host_blocked("10.0.0.1", /*port*/ 80).await.unwrap(), HostBlockDecision::Allowed ); } @@ -1199,7 +1223,10 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["example.com"], &[])); assert_eq!( - state.host_blocked("fe80::1%lo0", 80).await.unwrap(), + state + .host_blocked("fe80::1%lo0", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) ); } @@ -1209,7 +1236,10 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["fe80::1%lo0"], &[])); assert_eq!( - state.host_blocked("fe80::1%lo0", 80).await.unwrap(), + state + .host_blocked("fe80::1%lo0", /*port*/ 80) + .await + .unwrap(), HostBlockDecision::Allowed ); } @@ -1219,7 +1249,7 @@ mod tests { let state = network_proxy_state_for_policy(network_settings(&["example.com"], &[])); assert_eq!( - state.host_blocked("10.0.0.1", 80).await.unwrap(), + state.host_blocked("10.0.0.1", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) ); } @@ -1229,7 +1259,7 @@ mod tests { let state = network_proxy_state_for_policy(NetworkProxySettings::default()); assert_eq!( - state.host_blocked("127.0.0.1", 80).await.unwrap(), + state.host_blocked("127.0.0.1", /*port*/ 80).await.unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) ); } @@ -1242,7 +1272,7 @@ mod tests { assert_eq!( state - .host_blocked("does-not-resolve.invalid", 80) + .host_blocked("does-not-resolve.invalid", /*port*/ 80) .await .unwrap(), HostBlockDecision::Blocked(HostBlockReason::NotAllowedLocal) diff --git a/codex-rs/network-proxy/src/socks5.rs b/codex-rs/network-proxy/src/socks5.rs index 30ec4d290..b360d6853 100644 --- a/codex-rs/network-proxy/src/socks5.rs +++ b/codex-rs/network-proxy/src/socks5.rs @@ -546,7 +546,12 @@ mod tests { request.extensions_mut().insert(state.clone()); let (result, events) = capture_events(|| async { - handle_socks5_tcp(request, TcpConnector::default(), None).await + handle_socks5_tcp( + request, + TcpConnector::default(), + /*policy_decider*/ None, + ) + .await }) .await; assert!(result.is_err(), "proxy-disabled request should be denied"); @@ -584,8 +589,10 @@ mod tests { extensions: Extensions::new(), }; - let (result, events) = - capture_events(|| async { inspect_socks5_udp(request, state, None).await }).await; + let (result, events) = capture_events(|| async { + inspect_socks5_udp(request, state, /*policy_decider*/ None).await + }) + .await; assert!(result.is_err(), "limited-mode UDP request should be denied"); let event = find_event_by_name(&events, POLICY_DECISION_EVENT_NAME) diff --git a/codex-rs/otel/src/provider.rs b/codex-rs/otel/src/provider.rs index 6227e33bd..b6df9f5ad 100644 --- a/codex-rs/otel/src/provider.rs +++ b/codex-rs/otel/src/provider.rs @@ -406,7 +406,11 @@ mod tests { #[test] fn resource_attributes_omit_host_name_when_missing_or_empty() { - let missing = resource_attributes(&test_otel_settings(), None, ResourceKind::Logs); + let missing = resource_attributes( + &test_otel_settings(), + /*host_name*/ None, + ResourceKind::Logs, + ); let empty = resource_attributes(&test_otel_settings(), Some(" "), ResourceKind::Logs); let trace_attrs = resource_attributes( &test_otel_settings(), diff --git a/codex-rs/otel/src/trace_context.rs b/codex-rs/otel/src/trace_context.rs index b2a57a951..010078e99 100644 --- a/codex-rs/otel/src/trace_context.rs +++ b/codex-rs/otel/src/trace_context.rs @@ -141,7 +141,9 @@ mod tests { #[test] fn invalid_traceparent_returns_none() { - assert!(context_from_trace_headers(Some("not-a-traceparent"), None).is_none()); + assert!( + context_from_trace_headers(Some("not-a-traceparent"), /*tracestate*/ None).is_none() + ); } #[test] diff --git a/codex-rs/otel/tests/suite/manager_metrics.rs b/codex-rs/otel/tests/suite/manager_metrics.rs index a3160d5a4..8a61403c7 100644 --- a/codex-rs/otel/tests/suite/manager_metrics.rs +++ b/codex-rs/otel/tests/suite/manager_metrics.rs @@ -21,16 +21,20 @@ fn manager_attaches_metadata_tags_to_metrics() -> Result<()> { "gpt-5.1", "gpt-5.1", Some("account-id".to_string()), - None, + /*account_email*/ None, Some(TelemetryAuthMode::ApiKey), "test_originator".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) .with_metrics(metrics); - manager.counter("codex.session_started", 1, &[("source", "tui")]); + manager.counter( + "codex.session_started", + /*inc*/ 1, + &[("source", "tui")], + ); manager.shutdown_metrics()?; let resource_metrics = latest_metrics(&exporter); @@ -77,16 +81,20 @@ fn manager_allows_disabling_metadata_tags() -> Result<()> { "gpt-4o", "gpt-4o", Some("account-id".to_string()), - None, + /*account_email*/ None, Some(TelemetryAuthMode::ApiKey), "test_originator".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) .with_metrics_without_metadata_tags(metrics); - manager.counter("codex.session_started", 1, &[("source", "tui")]); + manager.counter( + "codex.session_started", + /*inc*/ 1, + &[("source", "tui")], + ); manager.shutdown_metrics()?; let resource_metrics = latest_metrics(&exporter); @@ -117,18 +125,18 @@ fn manager_attaches_optional_service_name_tag() -> Result<()> { ThreadId::new(), "gpt-5.1", "gpt-5.1", - None, - None, - None, + /*account_id*/ None, + /*account_email*/ None, + /*auth_mode*/ None, "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "tty".to_string(), SessionSource::Cli, ) .with_metrics_service_name("my_app_server_client") .with_metrics(metrics); - manager.counter("codex.session_started", 1, &[]); + manager.counter("codex.session_started", /*inc*/ 1, &[]); manager.shutdown_metrics()?; let resource_metrics = latest_metrics(&exporter); diff --git a/codex-rs/otel/tests/suite/otel_export_routing_policy.rs b/codex-rs/otel/tests/suite/otel_export_routing_policy.rs index b7fce8614..fa02cc7f3 100644 --- a/codex-rs/otel/tests/suite/otel_export_routing_policy.rs +++ b/codex-rs/otel/tests/suite/otel_export_routing_policy.rs @@ -126,7 +126,7 @@ fn otel_export_routing_policy_routes_user_prompt_log_and_trace_events() { Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::ApiKey), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ); @@ -235,7 +235,7 @@ fn otel_export_routing_policy_routes_tool_result_log_and_trace_events() { Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::ApiKey), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ); @@ -246,7 +246,7 @@ fn otel_export_routing_policy_routes_tool_result_log_and_trace_events() { "call-1", "secret arguments", std::time::Duration::from_millis(42), - true, + /*success*/ true, "secret output\nsecond line", &[], Some("internal-mcp"), @@ -348,7 +348,7 @@ fn otel_export_routing_policy_routes_auth_recovery_log_and_trace_events() { Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::Chatgpt), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ); @@ -362,7 +362,7 @@ fn otel_export_routing_policy_routes_auth_recovery_log_and_trace_events() { Some("ray-401"), Some("missing_authorization_header"), Some("token_expired"), - None, + /*recovery_reason*/ None, Some(true), ); }); @@ -494,7 +494,7 @@ fn otel_export_routing_policy_routes_api_request_auth_observability() { Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::Chatgpt), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) @@ -503,23 +503,23 @@ fn otel_export_routing_policy_routes_api_request_auth_observability() { let _root_guard = root_span.enter(); manager.conversation_starts( "openai", - None, + /*reasoning_effort*/ None, ReasoningSummary::Auto, - None, - None, + /*context_window*/ None, + /*auto_compact_token_limit*/ None, AskForApproval::Never, SandboxPolicy::DangerFullAccess, Vec::new(), - None, + /*active_profile*/ None, ); manager.record_api_request( - 1, + /*attempt*/ 1, Some(401), Some("http 401"), std::time::Duration::from_millis(42), - true, + /*auth_header_attached*/ true, Some("authorization"), - true, + /*retry_after_unauthorized*/ true, Some("managed"), Some("refresh_token"), "/responses", @@ -679,7 +679,7 @@ fn otel_export_routing_policy_routes_websocket_connect_auth_observability() { Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::Chatgpt), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) @@ -690,13 +690,13 @@ fn otel_export_routing_policy_routes_websocket_connect_auth_observability() { std::time::Duration::from_millis(17), Some(401), Some("http 401"), - true, + /*auth_header_attached*/ true, Some("authorization"), - true, + /*retry_after_unauthorized*/ true, Some("managed"), Some("reload"), "/responses", - false, + /*connection_reused*/ false, Some("req-ws-401"), Some("ray-ws-401"), Some("missing_authorization_header"), @@ -796,7 +796,7 @@ fn otel_export_routing_policy_routes_websocket_request_transport_observability() Some("engineer@example.com".to_string()), Some(TelemetryAuthMode::Chatgpt), "codex_exec".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) @@ -806,7 +806,7 @@ fn otel_export_routing_policy_routes_websocket_request_transport_observability() manager.record_websocket_request( std::time::Duration::from_millis(23), Some("stream error"), - true, + /*connection_reused*/ true, ); }); diff --git a/codex-rs/otel/tests/suite/otlp_http_loopback.rs b/codex-rs/otel/tests/suite/otlp_http_loopback.rs index c3bb042fe..eb84dfdf5 100644 --- a/codex-rs/otel/tests/suite/otlp_http_loopback.rs +++ b/codex-rs/otel/tests/suite/otlp_http_loopback.rs @@ -178,7 +178,7 @@ fn otlp_http_exporter_sends_metrics_to_collector() -> Result<()> { }, ))?; - metrics.counter("codex.turns", 1, &[("source", "test")])?; + metrics.counter("codex.turns", /*inc*/ 1, &[("source", "test")])?; metrics.shutdown()?; server.join().expect("server join"); diff --git a/codex-rs/otel/tests/suite/runtime_summary.rs b/codex-rs/otel/tests/suite/runtime_summary.rs index 778ed0578..7ffa03e02 100644 --- a/codex-rs/otel/tests/suite/runtime_summary.rs +++ b/codex-rs/otel/tests/suite/runtime_summary.rs @@ -25,10 +25,10 @@ fn runtime_metrics_summary_collects_tool_api_and_streaming_metrics() -> Result<( "gpt-5.1", "gpt-5.1", Some("account-id".to_string()), - None, + /*account_email*/ None, Some(TelemetryAuthMode::ApiKey), "test_originator".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) @@ -41,29 +41,33 @@ fn runtime_metrics_summary_collects_tool_api_and_streaming_metrics() -> Result<( "call-1", "{\"cmd\":\"echo\"}", Duration::from_millis(250), - true, + /*success*/ true, "ok", &[], - None, - None, + /*mcp_server*/ None, + /*mcp_server_origin*/ None, ); manager.record_api_request( - 1, + /*attempt*/ 1, Some(200), - None, + /*error*/ None, Duration::from_millis(300), - false, - None, - false, - None, - None, + /*auth_header_attached*/ false, + /*auth_header_name*/ None, + /*retry_after_unauthorized*/ false, + /*recovery_mode*/ None, + /*recovery_phase*/ None, "/responses", - None, - None, - None, - None, + /*request_id*/ None, + /*cf_ray*/ None, + /*auth_error*/ None, + /*auth_error_code*/ None, + ); + manager.record_websocket_request( + Duration::from_millis(400), + /*error*/ None, + /*connection_reused*/ false, ); - manager.record_websocket_request(Duration::from_millis(400), None, false); let sse_response: std::result::Result< Option>>, tokio::time::error::Elapsed, diff --git a/codex-rs/otel/tests/suite/send.rs b/codex-rs/otel/tests/suite/send.rs index 4e7e02792..a50c57908 100644 --- a/codex-rs/otel/tests/suite/send.rs +++ b/codex-rs/otel/tests/suite/send.rs @@ -13,8 +13,16 @@ fn send_builds_payload_with_tags_and_histograms() -> Result<()> { let (metrics, exporter) = build_metrics_with_defaults(&[("service", "codex-cli"), ("env", "prod")])?; - metrics.counter("codex.turns", 1, &[("model", "gpt-5.1"), ("env", "dev")])?; - metrics.histogram("codex.tool_latency", 25, &[("tool", "shell")])?; + metrics.counter( + "codex.turns", + /*inc*/ 1, + &[("model", "gpt-5.1"), ("env", "dev")], + )?; + metrics.histogram( + "codex.tool_latency", + /*value*/ 25, + &[("tool", "shell")], + )?; metrics.shutdown()?; let resource_metrics = latest_metrics(&exporter); @@ -82,10 +90,14 @@ fn send_merges_default_tags_per_line() -> Result<()> { ("region", "us"), ])?; - metrics.counter("codex.alpha", 1, &[("env", "dev"), ("component", "alpha")])?; + metrics.counter( + "codex.alpha", + /*inc*/ 1, + &[("env", "dev"), ("component", "alpha")], + )?; metrics.counter( "codex.beta", - 2, + /*inc*/ 2, &[("service", "worker"), ("component", "beta")], )?; metrics.shutdown()?; @@ -145,7 +157,7 @@ fn send_merges_default_tags_per_line() -> Result<()> { fn client_sends_enqueued_metric() -> Result<()> { let (metrics, exporter) = build_metrics_with_defaults(&[])?; - metrics.counter("codex.turns", 1, &[("model", "gpt-5.1")])?; + metrics.counter("codex.turns", /*inc*/ 1, &[("model", "gpt-5.1")])?; metrics.shutdown()?; let resource_metrics = latest_metrics(&exporter); @@ -173,7 +185,7 @@ fn client_sends_enqueued_metric() -> Result<()> { fn shutdown_flushes_in_memory_exporter() -> Result<()> { let (metrics, exporter) = build_metrics_with_defaults(&[])?; - metrics.counter("codex.turns", 1, &[])?; + metrics.counter("codex.turns", /*inc*/ 1, &[])?; metrics.shutdown()?; let resource_metrics = latest_metrics(&exporter); diff --git a/codex-rs/otel/tests/suite/snapshot.rs b/codex-rs/otel/tests/suite/snapshot.rs index 6bd9bd819..4686e79d3 100644 --- a/codex-rs/otel/tests/suite/snapshot.rs +++ b/codex-rs/otel/tests/suite/snapshot.rs @@ -28,7 +28,7 @@ fn snapshot_collects_metrics_without_shutdown() -> Result<()> { metrics.counter( "codex.tool.call", - 1, + /*inc*/ 1, &[("tool", "shell"), ("success", "true")], )?; @@ -74,10 +74,10 @@ fn manager_snapshot_metrics_collects_without_shutdown() -> Result<()> { "gpt-5.1", "gpt-5.1", Some("account-id".to_string()), - None, + /*account_email*/ None, Some(TelemetryAuthMode::ApiKey), "test_originator".to_string(), - true, + /*log_user_prompts*/ true, "tty".to_string(), SessionSource::Cli, ) @@ -85,7 +85,7 @@ fn manager_snapshot_metrics_collects_without_shutdown() -> Result<()> { manager.counter( "codex.tool.call", - 1, + /*inc*/ 1, &[("tool", "shell"), ("success", "true")], ); diff --git a/codex-rs/otel/tests/suite/validation.rs b/codex-rs/otel/tests/suite/validation.rs index f88d9fbcd..81f07ed14 100644 --- a/codex-rs/otel/tests/suite/validation.rs +++ b/codex-rs/otel/tests/suite/validation.rs @@ -34,7 +34,7 @@ fn invalid_tag_component_is_rejected() -> Result<()> { fn counter_rejects_invalid_tag_key() -> Result<()> { let metrics = build_in_memory_client()?; let err = metrics - .counter("codex.turns", 1, &[("bad key", "value")]) + .counter("codex.turns", /*inc*/ 1, &[("bad key", "value")]) .unwrap_err(); assert!(matches!( err, @@ -50,7 +50,11 @@ fn counter_rejects_invalid_tag_key() -> Result<()> { fn histogram_rejects_invalid_tag_value() -> Result<()> { let metrics = build_in_memory_client()?; let err = metrics - .histogram("codex.request_latency", 3, &[("route", "bad value")]) + .histogram( + "codex.request_latency", + /*value*/ 3, + &[("route", "bad value")], + ) .unwrap_err(); assert!(matches!( err, @@ -65,7 +69,7 @@ fn histogram_rejects_invalid_tag_value() -> Result<()> { #[test] fn counter_rejects_invalid_metric_name() -> Result<()> { let metrics = build_in_memory_client()?; - let err = metrics.counter("bad name", 1, &[]).unwrap_err(); + let err = metrics.counter("bad name", /*inc*/ 1, &[]).unwrap_err(); assert!(matches!( err, MetricsError::InvalidMetricName { name } if name == "bad name" @@ -77,7 +81,7 @@ fn counter_rejects_invalid_metric_name() -> Result<()> { #[test] fn counter_rejects_negative_increment() -> Result<()> { let metrics = build_in_memory_client()?; - let err = metrics.counter("codex.turns", -1, &[]).unwrap_err(); + let err = metrics.counter("codex.turns", /*inc*/ -1, &[]).unwrap_err(); assert!(matches!( err, MetricsError::NegativeCounterIncrement { name, inc } if name == "codex.turns" && inc == -1 diff --git a/codex-rs/protocol/src/items.rs b/codex-rs/protocol/src/items.rs index 36c8cdbae..72a955133 100644 --- a/codex-rs/protocol/src/items.rs +++ b/codex-rs/protocol/src/items.rs @@ -426,7 +426,7 @@ mod tests { panic!("expected hook prompt message"); }; - let parsed = parse_hook_prompt_message(None, &content).expect("parsed hook prompt"); + let parsed = parse_hook_prompt_message(/*id*/ None, &content).expect("parsed hook prompt"); assert_eq!(parsed.fragments, original); } diff --git a/codex-rs/protocol/src/models.rs b/codex-rs/protocol/src/models.rs index 7ab0009b4..d4e568fea 100644 --- a/codex-rs/protocol/src/models.rs +++ b/codex-rs/protocol/src/models.rs @@ -1694,7 +1694,7 @@ mod tests { exec_permission_approvals_enabled: false, request_permissions_tool_enabled: false, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1724,8 +1724,8 @@ mod tests { ApprovalsReviewer::User, &Policy::empty(), &PathBuf::from("/tmp"), - false, - false, + /*exec_permission_approvals_enabled*/ false, + /*request_permissions_tool_enabled*/ false, ); let text = instructions.into_text(); assert!(text.contains("Network access is enabled.")); @@ -1751,7 +1751,7 @@ mod tests { exec_permission_approvals_enabled: false, request_permissions_tool_enabled: false, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1772,7 +1772,7 @@ mod tests { exec_permission_approvals_enabled: false, request_permissions_tool_enabled: true, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1792,7 +1792,7 @@ mod tests { exec_permission_approvals_enabled: false, request_permissions_tool_enabled: true, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1812,7 +1812,7 @@ mod tests { exec_permission_approvals_enabled: true, request_permissions_tool_enabled: false, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1832,7 +1832,7 @@ mod tests { exec_permission_approvals_enabled: false, request_permissions_tool_enabled: true, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1854,7 +1854,7 @@ mod tests { exec_permission_approvals_enabled: true, request_permissions_tool_enabled: true, }, - None, + /*writable_roots*/ None, ); let text = instructions.into_text(); @@ -1868,8 +1868,8 @@ mod tests { AskForApproval::OnRequest, ApprovalsReviewer::GuardianSubagent, &Policy::empty(), - false, - false, + /*exec_permission_approvals_enabled*/ false, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -1883,8 +1883,8 @@ mod tests { AskForApproval::Never, ApprovalsReviewer::GuardianSubagent, &Policy::empty(), - false, - false, + /*exec_permission_approvals_enabled*/ false, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -1935,8 +1935,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - true, - false, + /*exec_permission_approvals_enabled*/ true, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -1969,8 +1969,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - true, - false, + /*exec_permission_approvals_enabled*/ true, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -1984,8 +1984,8 @@ mod tests { "- `mcp_elicitations`", ], &[], - true, - false, + /*include_shell_permission_request_instructions*/ true, + /*include_request_permissions_tool_section*/ false, ) ); } @@ -2002,8 +2002,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - false, - false, + /*exec_permission_approvals_enabled*/ false, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -2017,8 +2017,8 @@ mod tests { "- `mcp_elicitations`", ], &[], - false, - false, + /*include_shell_permission_request_instructions*/ false, + /*include_request_permissions_tool_section*/ false, ) ); } @@ -2035,8 +2035,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - true, - true, + /*exec_permission_approvals_enabled*/ true, + /*request_permissions_tool_enabled*/ true, ) .into_text(); assert!(allowed.contains("# request_permissions Tool")); @@ -2051,8 +2051,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - true, - true, + /*exec_permission_approvals_enabled*/ true, + /*request_permissions_tool_enabled*/ true, ) .into_text(); assert!(!rejected.contains("# request_permissions Tool")); @@ -2071,8 +2071,8 @@ mod tests { }), ApprovalsReviewer::User, &Policy::empty(), - true, - false, + /*exec_permission_approvals_enabled*/ true, + /*request_permissions_tool_enabled*/ false, ) .into_text(); @@ -2652,7 +2652,7 @@ mod tests { assert_eq!( content.get(3), Some(&ContentItem::InputText { - text: local_image_open_tag_text(2), + text: local_image_open_tag_text(/*label_number*/ 2), }) ); assert!(matches!( diff --git a/codex-rs/protocol/src/openai_models.rs b/codex-rs/protocol/src/openai_models.rs index 01515d107..3c633cbd8 100644 --- a/codex-rs/protocol/src/openai_models.rs +++ b/codex-rs/protocol/src/openai_models.rs @@ -537,7 +537,7 @@ mod tests { default_verbosity: None, apply_patch_tool_type: None, web_search_tool_type: WebSearchToolType::Text, - truncation_policy: TruncationPolicyConfig::bytes(10_000), + truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_parallel_tool_calls: false, supports_image_detail_original: false, context_window: None, @@ -606,7 +606,10 @@ mod tests { model.get_model_instructions(Some(Personality::None)), "Hello\n" ); - assert_eq!(model.get_model_instructions(None), "Hello\n"); + assert_eq!( + model.get_model_instructions(/*personality*/ None), + "Hello\n" + ); let model_no_personality = test_model(Some(ModelMessages { instructions_template: Some("Hello\n{{ personality }}".to_string()), @@ -628,7 +631,10 @@ mod tests { model_no_personality.get_model_instructions(Some(Personality::None)), "Hello\n" ); - assert_eq!(model_no_personality.get_model_instructions(None), "Hello\n"); + assert_eq!( + model_no_personality.get_model_instructions(/*personality*/ None), + "Hello\n" + ); } #[test] @@ -651,7 +657,7 @@ mod tests { fn get_personality_message_returns_default_when_personality_is_none() { let personality_template = personality_variables(); assert_eq!( - personality_template.get_personality_message(None), + personality_template.get_personality_message(/*personality*/ None), Some("default".to_string()) ); } @@ -672,7 +678,7 @@ mod tests { Some(String::new()) ); assert_eq!( - personality_variables.get_personality_message(None), + personality_variables.get_personality_message(/*personality*/ None), Some("default".to_string()) ); @@ -694,7 +700,7 @@ mod tests { Some(String::new()) ); assert_eq!( - personality_variables.get_personality_message(None), + personality_variables.get_personality_message(/*personality*/ None), Some("default".to_string()) ); @@ -715,7 +721,10 @@ mod tests { personality_variables.get_personality_message(Some(Personality::None)), Some(String::new()) ); - assert_eq!(personality_variables.get_personality_message(None), None); + assert_eq!( + personality_variables.get_personality_message(/*personality*/ None), + None + ); } #[test] @@ -763,7 +772,7 @@ mod tests { availability_nux: Some(ModelAvailabilityNux { message: "Try Spark.".to_string(), }), - ..test_model(None) + ..test_model(/*spec*/ None) }); assert_eq!( diff --git a/codex-rs/protocol/src/permissions.rs b/codex-rs/protocol/src/permissions.rs index 978334f69..4aa1c7b36 100644 --- a/codex-rs/protocol/src/permissions.rs +++ b/codex-rs/protocol/src/permissions.rs @@ -1268,7 +1268,10 @@ mod tests { fn unknown_special_paths_are_ignored_by_legacy_bridge() -> std::io::Result<()> { let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::unknown(":future_special_path", None), + value: FileSystemSpecialPath::unknown( + ":future_special_path", + /*subpath*/ None, + ), }, access: FileSystemAccessMode::Write, }]); diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 8b38a5050..27e7b4e46 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -4291,7 +4291,7 @@ mod tests { }), }; - let legacy_events = event.as_legacy_events(false); + let legacy_events = event.as_legacy_events(/*show_raw_agent_reasoning*/ false); assert_eq!(legacy_events.len(), 1); match &legacy_events[0] { EventMsg::WebSearchBegin(event) => assert_eq!(event.call_id, "search-1"), @@ -4307,7 +4307,11 @@ mod tests { item: TurnItem::UserMessage(UserMessageItem::new(&[])), }; - assert!(event.as_legacy_events(false).is_empty()); + assert!( + event + .as_legacy_events(/*show_raw_agent_reasoning*/ false) + .is_empty() + ); } #[test] @@ -4324,7 +4328,7 @@ mod tests { }), }; - let legacy_events = event.as_legacy_events(false); + let legacy_events = event.as_legacy_events(/*show_raw_agent_reasoning*/ false); assert_eq!(legacy_events.len(), 1); match &legacy_events[0] { EventMsg::ImageGenerationBegin(event) => assert_eq!(event.call_id, "ig-1"), @@ -4346,7 +4350,7 @@ mod tests { }), }; - let legacy_events = event.as_legacy_events(false); + let legacy_events = event.as_legacy_events(/*show_raw_agent_reasoning*/ false); assert_eq!(legacy_events.len(), 1); match &legacy_events[0] { EventMsg::ImageGenerationEnd(event) => { @@ -4761,8 +4765,9 @@ mod tests { total_tokens: 10, }); - let info = TokenUsageInfo::new_or_append(&initial, &last, None) - .expect("new_or_append should return info"); + let info = + TokenUsageInfo::new_or_append(&initial, &last, /*model_context_window*/ None) + .expect("new_or_append should return info"); assert_eq!(info.model_context_window, Some(258_400)); } diff --git a/codex-rs/rmcp-client/src/auth_status.rs b/codex-rs/rmcp-client/src/auth_status.rs index 3936f8ef9..f97898548 100644 --- a/codex-rs/rmcp-client/src/auth_status.rs +++ b/codex-rs/rmcp-client/src/auth_status.rs @@ -276,12 +276,12 @@ mod tests { let status = determine_streamable_http_auth_status( "server", "not-a-url", - None, + /*bearer_token_env_var*/ None, Some(HashMap::from([( "Authorization".to_string(), "Bearer token".to_string(), )])), - None, + /*env_http_headers*/ None, OAuthCredentialsStoreMode::Keyring, ) .await @@ -297,8 +297,8 @@ mod tests { let status = determine_streamable_http_auth_status( "server", "not-a-url", - None, - None, + /*bearer_token_env_var*/ None, + /*http_headers*/ None, Some(HashMap::from([( "Authorization".to_string(), "CODEX_RMCP_CLIENT_AUTH_STATUS_TEST_TOKEN".to_string(), @@ -320,10 +320,14 @@ mod tests { })) .await; - let discovery = discover_streamable_http_oauth(&server.url, None, None) - .await - .expect("discovery should succeed") - .expect("oauth support should be detected"); + let discovery = discover_streamable_http_oauth( + &server.url, + /*http_headers*/ None, + /*env_http_headers*/ None, + ) + .await + .expect("discovery should succeed") + .expect("oauth support should be detected"); assert_eq!( discovery.scopes_supported, @@ -340,10 +344,14 @@ mod tests { })) .await; - let discovery = discover_streamable_http_oauth(&server.url, None, None) - .await - .expect("discovery should succeed") - .expect("oauth support should be detected"); + let discovery = discover_streamable_http_oauth( + &server.url, + /*http_headers*/ None, + /*env_http_headers*/ None, + ) + .await + .expect("discovery should succeed") + .expect("oauth support should be detected"); assert_eq!(discovery.scopes_supported, None); } diff --git a/codex-rs/rmcp-client/src/utils.rs b/codex-rs/rmcp-client/src/utils.rs index cb906aaaa..cf8d4cbb2 100644 --- a/codex-rs/rmcp-client/src/utils.rs +++ b/codex-rs/rmcp-client/src/utils.rs @@ -193,7 +193,7 @@ mod tests { let value = "from-env"; let expected = OsString::from(value); let _guard = EnvVarGuard::set(custom_var, value); - let env = create_env_for_mcp_server(None, &[custom_var.to_string()]); + let env = create_env_for_mcp_server(/*extra_env*/ None, &[custom_var.to_string()]); assert_eq!(env.get(OsStr::new(custom_var)), Some(&expected)); } @@ -207,7 +207,7 @@ mod tests { let expected = raw_path.to_os_string(); let _guard = EnvVarGuard::set("PATH", raw_path); - let env = create_env_for_mcp_server(None, &[]); + let env = create_env_for_mcp_server(/*extra_env*/ None, &[]); assert_eq!(env.get(OsStr::new("PATH")), Some(&expected)); } diff --git a/codex-rs/rmcp-client/tests/process_group_cleanup.rs b/codex-rs/rmcp-client/tests/process_group_cleanup.rs index 2d6c220ce..5d8a80e1e 100644 --- a/codex-rs/rmcp-client/tests/process_group_cleanup.rs +++ b/codex-rs/rmcp-client/tests/process_group_cleanup.rs @@ -77,7 +77,7 @@ async fn drop_kills_wrapper_process_group() -> Result<()> { OsString::from(child_pid_file_str), )])), &[], - None, + /*cwd*/ None, ) .await?; diff --git a/codex-rs/rmcp-client/tests/resources.rs b/codex-rs/rmcp-client/tests/resources.rs index ba1a8e431..e41b9268a 100644 --- a/codex-rs/rmcp-client/tests/resources.rs +++ b/codex-rs/rmcp-client/tests/resources.rs @@ -58,9 +58,9 @@ async fn rmcp_client_can_list_and_read_resources() -> anyhow::Result<()> { let client = RmcpClient::new_stdio_client( stdio_server_bin()?.into(), Vec::::new(), - None, + /*env*/ None, &[], - None, + /*cwd*/ None, ) .await?; @@ -82,7 +82,7 @@ async fn rmcp_client_can_list_and_read_resources() -> anyhow::Result<()> { .await?; let list = client - .list_resources(None, Some(Duration::from_secs(5))) + .list_resources(/*params*/ None, Some(Duration::from_secs(5))) .await?; let memo = list .resources @@ -104,7 +104,7 @@ async fn rmcp_client_can_list_and_read_resources() -> anyhow::Result<()> { .no_annotation() ); let templates = client - .list_resource_templates(None, Some(Duration::from_secs(5))) + .list_resource_templates(/*params*/ None, Some(Duration::from_secs(5))) .await?; assert_eq!( templates, diff --git a/codex-rs/rmcp-client/tests/streamable_http_recovery.rs b/codex-rs/rmcp-client/tests/streamable_http_recovery.rs index fb2fc96d2..6a75582c9 100644 --- a/codex-rs/rmcp-client/tests/streamable_http_recovery.rs +++ b/codex-rs/rmcp-client/tests/streamable_http_recovery.rs @@ -74,8 +74,8 @@ async fn create_client(base_url: &str) -> anyhow::Result { "test-streamable-http", &format!("{base_url}/mcp"), Some("test-bearer".to_string()), - None, - None, + /*http_headers*/ None, + /*env_http_headers*/ None, OAuthCredentialsStoreMode::File, ) .await?; @@ -105,7 +105,7 @@ async fn call_echo_tool(client: &RmcpClient, message: &str) -> anyhow::Result anyho let warmup = call_echo_tool(&client, "warmup").await?; assert_eq!(warmup, expected_echo_result("warmup")); - arm_session_post_failure(&base_url, 404, 1).await?; + arm_session_post_failure(&base_url, /*status*/ 404, /*remaining*/ 1).await?; let recovered = call_echo_tool(&client, "recovered").await?; assert_eq!(recovered, expected_echo_result("recovered")); @@ -210,7 +210,7 @@ async fn streamable_http_401_does_not_trigger_recovery() -> anyhow::Result<()> { let warmup = call_echo_tool(&client, "warmup").await?; assert_eq!(warmup, expected_echo_result("warmup")); - arm_session_post_failure(&base_url, 401, 2).await?; + arm_session_post_failure(&base_url, /*status*/ 401, /*remaining*/ 2).await?; let first_error = call_echo_tool(&client, "unauthorized").await.unwrap_err(); assert!(first_error.to_string().contains("401")); @@ -231,7 +231,7 @@ async fn streamable_http_404_recovery_only_retries_once() -> anyhow::Result<()> let warmup = call_echo_tool(&client, "warmup").await?; assert_eq!(warmup, expected_echo_result("warmup")); - arm_session_post_failure(&base_url, 404, 2).await?; + arm_session_post_failure(&base_url, /*status*/ 404, /*remaining*/ 2).await?; let error = call_echo_tool(&client, "double-404").await.unwrap_err(); assert!( @@ -255,7 +255,7 @@ async fn streamable_http_non_session_failure_does_not_trigger_recovery() -> anyh let warmup = call_echo_tool(&client, "warmup").await?; assert_eq!(warmup, expected_echo_result("warmup")); - arm_session_post_failure(&base_url, 500, 2).await?; + arm_session_post_failure(&base_url, /*status*/ 500, /*remaining*/ 2).await?; let first_error = call_echo_tool(&client, "server-error").await.unwrap_err(); assert!(first_error.to_string().contains("500")); diff --git a/codex-rs/rollout/src/metadata_tests.rs b/codex-rs/rollout/src/metadata_tests.rs index e08680662..8a149313d 100644 --- a/codex-rs/rollout/src/metadata_tests.rs +++ b/codex-rs/rollout/src/metadata_tests.rs @@ -186,14 +186,14 @@ async fn backfill_sessions_resumes_from_watermark_and_marks_complete() { "2026-01-27T12-34-56", "2026-01-27T12:34:56Z", first_uuid, - None, + /*git*/ None, ); let second_path = write_rollout_in_sessions( codex_home.as_path(), "2026-01-27T12-35-56", "2026-01-27T12:35:56Z", second_uuid, - None, + /*git*/ None, ); let runtime = codex_state::StateRuntime::init(codex_home.clone(), "test-provider".to_string()) @@ -306,7 +306,7 @@ async fn backfill_sessions_normalizes_cwd_before_upsert() { "2026-01-27T12:34:56Z", thread_uuid, session_cwd.clone(), - None, + /*git*/ None, ); let runtime = codex_state::StateRuntime::init(codex_home.clone(), "test-provider".to_string()) diff --git a/codex-rs/rollout/src/recorder_tests.rs b/codex-rs/rollout/src/recorder_tests.rs index 5a868b162..163c8a1ee 100644 --- a/codex-rs/rollout/src/recorder_tests.rs +++ b/codex-rs/rollout/src/recorder_tests.rs @@ -71,14 +71,14 @@ async fn recorder_materializes_only_after_explicit_persist() -> std::io::Result< &config, RolloutRecorderParams::new( thread_id, - None, + /*forked_from_id*/ None, SessionSource::Exec, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), - None, - None, + /*state_db_ctx*/ None, + /*state_builder*/ None, ) .await?; @@ -155,7 +155,7 @@ async fn metadata_irrelevant_events_touch_state_db_updated_at() -> std::io::Resu .await .expect("state db should initialize"); state_db - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("backfill should be complete"); @@ -164,14 +164,14 @@ async fn metadata_irrelevant_events_touch_state_db_updated_at() -> std::io::Resu &config, RolloutRecorderParams::new( thread_id, - None, + /*forked_from_id*/ None, SessionSource::Cli, BaseInstructions::default(), Vec::new(), EventPersistenceMode::Limited, ), Some(state_db.clone()), - None, + /*state_builder*/ None, ) .await?; @@ -257,7 +257,7 @@ async fn metadata_irrelevant_events_fall_back_to_upsert_when_thread_missing() -> Some(&builder), items.as_slice(), config.model_provider_id.as_str(), - None, + /*new_thread_memory_mode*/ None, ) .await; @@ -283,13 +283,13 @@ async fn list_threads_db_disabled_does_not_skip_paginated_items() -> std::io::Re let default_provider = config.model_provider_id.clone(); let page1 = RolloutRecorder::list_threads( &config, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, &[], - None, + /*model_providers*/ None, default_provider.as_str(), - None, + /*search_term*/ None, ) .await?; assert_eq!(page1.items.len(), 1); @@ -298,13 +298,13 @@ async fn list_threads_db_disabled_does_not_skip_paginated_items() -> std::io::Re let page2 = RolloutRecorder::list_threads( &config, - 1, + /*page_size*/ 1, Some(&cursor), ThreadSortKey::CreatedAt, &[], - None, + /*model_providers*/ None, default_provider.as_str(), - None, + /*search_term*/ None, ) .await?; assert_eq!(page2.items.len(), 1); @@ -330,7 +330,7 @@ async fn list_threads_db_enabled_drops_missing_rollout_paths() -> std::io::Resul .await .expect("state db should initialize"); runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("backfill should be complete"); let created_at = chrono::Utc @@ -355,13 +355,13 @@ async fn list_threads_db_enabled_drops_missing_rollout_paths() -> std::io::Resul let default_provider = config.model_provider_id.clone(); let page = RolloutRecorder::list_threads( &config, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, &[], - None, + /*model_providers*/ None, default_provider.as_str(), - None, + /*search_term*/ None, ) .await?; assert_eq!(page.items.len(), 0); @@ -392,7 +392,7 @@ async fn list_threads_db_enabled_repairs_stale_rollout_paths() -> std::io::Resul .await .expect("state db should initialize"); runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("backfill should be complete"); let created_at = chrono::Utc @@ -417,13 +417,13 @@ async fn list_threads_db_enabled_repairs_stale_rollout_paths() -> std::io::Resul let default_provider = config.model_provider_id.clone(); let page = RolloutRecorder::list_threads( &config, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, &[], - None, + /*model_providers*/ None, default_provider.as_str(), - None, + /*search_term*/ None, ) .await?; assert_eq!(page.items.len(), 1); diff --git a/codex-rs/rollout/src/tests.rs b/codex-rs/rollout/src/tests.rs index 6a5f25286..e647a54cd 100644 --- a/codex-rs/rollout/src/tests.rs +++ b/codex-rs/rollout/src/tests.rs @@ -63,7 +63,7 @@ async fn insert_state_db_thread( .await .expect("state db should initialize"); runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("backfill should be complete"); let created_at = chrono::Utc @@ -223,13 +223,26 @@ async fn find_thread_path_falls_back_when_db_path_is_stale() { let uuid = Uuid::from_u128(302); let thread_id = ThreadId::from_string(&uuid.to_string()).expect("valid thread id"); let ts = "2025-01-03T13-00-00"; - write_session_file(home, ts, uuid, 1, Some(SessionSource::Cli)).unwrap(); + write_session_file( + home, + ts, + uuid, + /*num_records*/ 1, + Some(SessionSource::Cli), + ) + .unwrap(); let fs_rollout_path = home.join(format!("sessions/2025/01/03/rollout-{ts}-{uuid}.jsonl")); let stale_db_path = home.join(format!( "sessions/2099/01/01/rollout-2099-01-01T00-00-00-{uuid}.jsonl" )); - insert_state_db_thread(home, thread_id, stale_db_path.as_path(), false).await; + insert_state_db_thread( + home, + thread_id, + stale_db_path.as_path(), + /*archived*/ false, + ) + .await; let found = find_thread_path_by_id_str(home, &uuid.to_string()) .await @@ -245,7 +258,14 @@ async fn find_thread_path_repairs_missing_db_row_after_filesystem_fallback() { let uuid = Uuid::from_u128(303); let thread_id = ThreadId::from_string(&uuid.to_string()).expect("valid thread id"); let ts = "2025-01-03T13-00-00"; - write_session_file(home, ts, uuid, 1, Some(SessionSource::Cli)).unwrap(); + write_session_file( + home, + ts, + uuid, + /*num_records*/ 1, + Some(SessionSource::Cli), + ) + .unwrap(); let fs_rollout_path = home.join(format!("sessions/2025/01/03/rollout-{ts}-{uuid}.jsonl")); // Create an empty state DB so lookup takes the DB-first path and then falls back to files. @@ -253,7 +273,7 @@ async fn find_thread_path_repairs_missing_db_row_after_filesystem_fallback() { .await .expect("state db should initialize"); _runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("backfill should be complete"); @@ -491,7 +511,7 @@ async fn test_list_conversations_latest_first() { home, "2025-01-01T12-00-00", u1, - 3, + /*num_records*/ 3, Some(SessionSource::VSCode), ) .unwrap(); @@ -499,7 +519,7 @@ async fn test_list_conversations_latest_first() { home, "2025-01-02T12-00-00", u2, - 3, + /*num_records*/ 3, Some(SessionSource::VSCode), ) .unwrap(); @@ -507,7 +527,7 @@ async fn test_list_conversations_latest_first() { home, "2025-01-03T12-00-00", u3, - 3, + /*num_records*/ 3, Some(SessionSource::VSCode), ) .unwrap(); @@ -515,8 +535,8 @@ async fn test_list_conversations_latest_first() { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -624,7 +644,7 @@ async fn test_pagination_cursor() { home, "2025-03-01T09-00-00", u1, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), ) .unwrap(); @@ -632,7 +652,7 @@ async fn test_pagination_cursor() { home, "2025-03-02T09-00-00", u2, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), ) .unwrap(); @@ -640,7 +660,7 @@ async fn test_pagination_cursor() { home, "2025-03-03T09-00-00", u3, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), ) .unwrap(); @@ -648,7 +668,7 @@ async fn test_pagination_cursor() { home, "2025-03-04T09-00-00", u4, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), ) .unwrap(); @@ -656,7 +676,7 @@ async fn test_pagination_cursor() { home, "2025-03-05T09-00-00", u5, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), ) .unwrap(); @@ -664,8 +684,8 @@ async fn test_pagination_cursor() { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page1 = get_threads( home, - 2, - None, + /*page_size*/ 2, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -732,7 +752,7 @@ async fn test_pagination_cursor() { let page2 = get_threads( home, - 2, + /*page_size*/ 2, page1.next_cursor.as_ref(), ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), @@ -800,7 +820,7 @@ async fn test_pagination_cursor() { let page3 = get_threads( home, - 2, + /*page_size*/ 2, page2.next_cursor.as_ref(), ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), @@ -848,13 +868,14 @@ async fn test_list_threads_scans_past_head_for_user_event() { let uuid = Uuid::from_u128(99); let ts = "2025-05-01T10-30-00"; - write_session_file_with_delayed_user_event(home, ts, uuid, 12).unwrap(); + write_session_file_with_delayed_user_event(home, ts, uuid, /*meta_lines_before_user*/ 12) + .unwrap(); let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -874,13 +895,20 @@ async fn test_get_thread_contents() { let uuid = Uuid::new_v4(); let ts = "2025-04-01T10-30-00"; - write_session_file(home, ts, uuid, 2, Some(SessionSource::VSCode)).unwrap(); + write_session_file( + home, + ts, + uuid, + /*num_records*/ 2, + Some(SessionSource::VSCode), + ) + .unwrap(); let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -969,8 +997,8 @@ async fn test_base_instructions_missing_in_meta_defaults_to_null() { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1012,8 +1040,8 @@ async fn test_base_instructions_present_in_meta_is_preserved() { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1040,7 +1068,14 @@ async fn test_created_at_sort_uses_file_mtime_for_updated_at() -> Result<()> { let ts = "2025-06-01T08-00-00"; let uuid = Uuid::from_u128(43); - write_session_file(home, ts, uuid, 0, Some(SessionSource::VSCode)).unwrap(); + write_session_file( + home, + ts, + uuid, + /*num_records*/ 0, + Some(SessionSource::VSCode), + ) + .unwrap(); let created = PrimitiveDateTime::parse( ts, @@ -1063,8 +1098,8 @@ async fn test_created_at_sort_uses_file_mtime_for_updated_at() -> Result<()> { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1148,8 +1183,8 @@ async fn test_updated_at_uses_file_mtime() -> Result<()> { let provider_filter = provider_vec(&[TEST_PROVIDER]); let page = get_threads( home, - 1, - None, + /*page_size*/ 1, + /*cursor*/ None, ThreadSortKey::UpdatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1181,15 +1216,36 @@ async fn test_stable_ordering_same_second_pagination() { let u2 = Uuid::from_u128(2); let u3 = Uuid::from_u128(3); - write_session_file(home, ts, u1, 0, Some(SessionSource::VSCode)).unwrap(); - write_session_file(home, ts, u2, 0, Some(SessionSource::VSCode)).unwrap(); - write_session_file(home, ts, u3, 0, Some(SessionSource::VSCode)).unwrap(); + write_session_file( + home, + ts, + u1, + /*num_records*/ 0, + Some(SessionSource::VSCode), + ) + .unwrap(); + write_session_file( + home, + ts, + u2, + /*num_records*/ 0, + Some(SessionSource::VSCode), + ) + .unwrap(); + write_session_file( + home, + ts, + u3, + /*num_records*/ 0, + Some(SessionSource::VSCode), + ) + .unwrap(); let provider_filter = provider_vec(&[TEST_PROVIDER]); let page1 = get_threads( home, - 2, - None, + /*page_size*/ 2, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1256,7 +1312,7 @@ async fn test_stable_ordering_same_second_pagination() { let page2 = get_threads( home, - 2, + /*page_size*/ 2, page1.next_cursor.as_ref(), ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), @@ -1309,7 +1365,7 @@ async fn test_source_filter_excludes_non_matching_sessions() { home, "2025-08-02T10-00-00", interactive_id, - 2, + /*num_records*/ 2, Some(SessionSource::Cli), ) .unwrap(); @@ -1317,7 +1373,7 @@ async fn test_source_filter_excludes_non_matching_sessions() { home, "2025-08-01T10-00-00", non_interactive_id, - 2, + /*num_records*/ 2, Some(SessionSource::Exec), ) .unwrap(); @@ -1325,8 +1381,8 @@ async fn test_source_filter_excludes_non_matching_sessions() { let provider_filter = provider_vec(&[TEST_PROVIDER]); let interactive_only = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, INTERACTIVE_SESSION_SOURCES.as_slice(), Some(provider_filter.as_slice()), @@ -1347,11 +1403,11 @@ async fn test_source_filter_excludes_non_matching_sessions() { let all_sessions = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, NO_SOURCE_FILTER, - None, + /*model_providers*/ None, TEST_PROVIDER, ) .await @@ -1383,7 +1439,7 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( home, "2025-09-01T12-00-00", openai_id, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), Some("openai"), )?; @@ -1391,7 +1447,7 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( home, "2025-09-01T11-00-00", beta_id, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), Some("beta"), )?; @@ -1399,9 +1455,9 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( home, "2025-09-01T10-00-00", none_id, - 1, + /*num_records*/ 1, Some(SessionSource::VSCode), - None, + /*model_provider*/ None, )?; let openai_id_str = openai_id.to_string(); @@ -1409,8 +1465,8 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( let openai_filter = provider_vec(&["openai"]); let openai_sessions = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, NO_SOURCE_FILTER, Some(openai_filter.as_slice()), @@ -1429,8 +1485,8 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( let beta_filter = provider_vec(&["beta"]); let beta_sessions = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, NO_SOURCE_FILTER, Some(beta_filter.as_slice()), @@ -1448,8 +1504,8 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( let unknown_filter = provider_vec(&["unknown"]); let unknown_sessions = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, NO_SOURCE_FILTER, Some(unknown_filter.as_slice()), @@ -1460,11 +1516,11 @@ async fn test_model_provider_filter_selects_only_matching_sessions() -> Result<( let all_sessions = get_threads( home, - 10, - None, + /*page_size*/ 10, + /*cursor*/ None, ThreadSortKey::CreatedAt, NO_SOURCE_FILTER, - None, + /*model_providers*/ None, "openai", ) .await?; diff --git a/codex-rs/sandboxing/src/bwrap_tests.rs b/codex-rs/sandboxing/src/bwrap_tests.rs index 8aa9a8020..43eddb39c 100644 --- a/codex-rs/sandboxing/src/bwrap_tests.rs +++ b/codex-rs/sandboxing/src/bwrap_tests.rs @@ -6,8 +6,8 @@ use tempfile::tempdir; #[test] fn system_bwrap_warning_reports_missing_system_bwrap() { - let warning = - system_bwrap_warning_for_lookup(None).expect("missing system bwrap should emit a warning"); + let warning = system_bwrap_warning_for_lookup(/*system_bwrap_path*/ None) + .expect("missing system bwrap should emit a warning"); assert!(warning.contains("could not find system bubblewrap")); } diff --git a/codex-rs/sandboxing/src/landlock_tests.rs b/codex-rs/sandboxing/src/landlock_tests.rs index 454878cd5..b1dd6236a 100644 --- a/codex-rs/sandboxing/src/landlock_tests.rs +++ b/codex-rs/sandboxing/src/landlock_tests.rs @@ -7,14 +7,25 @@ fn legacy_landlock_flag_is_included_when_requested() { let command_cwd = Path::new("/tmp/link"); let cwd = Path::new("/tmp"); - let default_bwrap = - create_linux_sandbox_command_args(command.clone(), command_cwd, cwd, false, false); + let default_bwrap = create_linux_sandbox_command_args( + command.clone(), + command_cwd, + cwd, + /*use_legacy_landlock*/ false, + /*allow_network_for_proxy*/ false, + ); assert_eq!( default_bwrap.contains(&"--use-legacy-landlock".to_string()), false ); - let legacy_landlock = create_linux_sandbox_command_args(command, command_cwd, cwd, true, false); + let legacy_landlock = create_linux_sandbox_command_args( + command, + command_cwd, + cwd, + /*use_legacy_landlock*/ true, + /*allow_network_for_proxy*/ false, + ); assert_eq!( legacy_landlock.contains(&"--use-legacy-landlock".to_string()), true @@ -27,7 +38,13 @@ fn proxy_flag_is_included_when_requested() { let command_cwd = Path::new("/tmp/link"); let cwd = Path::new("/tmp"); - let args = create_linux_sandbox_command_args(command, command_cwd, cwd, true, true); + let args = create_linux_sandbox_command_args( + command, + command_cwd, + cwd, + /*use_legacy_landlock*/ true, + /*allow_network_for_proxy*/ true, + ); assert_eq!( args.contains(&"--allow-network-for-proxy".to_string()), true @@ -50,8 +67,8 @@ fn split_policy_flags_are_included() { &file_system_sandbox_policy, network_sandbox_policy, cwd, - true, - false, + /*use_legacy_landlock*/ true, + /*allow_network_for_proxy*/ false, ); assert_eq!( @@ -73,6 +90,12 @@ fn split_policy_flags_are_included() { #[test] fn proxy_network_requires_managed_requirements() { - assert_eq!(allow_network_for_proxy(false), false); - assert_eq!(allow_network_for_proxy(true), true); + assert_eq!( + allow_network_for_proxy(/*enforce_managed_network*/ false), + false + ); + assert_eq!( + allow_network_for_proxy(/*enforce_managed_network*/ true), + true + ); } diff --git a/codex-rs/sandboxing/src/manager_tests.rs b/codex-rs/sandboxing/src/manager_tests.rs index a32c9e586..6fc34c963 100644 --- a/codex-rs/sandboxing/src/manager_tests.rs +++ b/codex-rs/sandboxing/src/manager_tests.rs @@ -31,7 +31,7 @@ fn danger_full_access_defaults_to_no_sandbox_without_network_requirements() { NetworkSandboxPolicy::Enabled, SandboxablePreference::Auto, WindowsSandboxLevel::Disabled, - false, + /*has_managed_network_requirements*/ false, ); assert_eq!(sandbox, SandboxType::None); } @@ -39,13 +39,14 @@ fn danger_full_access_defaults_to_no_sandbox_without_network_requirements() { #[test] fn danger_full_access_uses_platform_sandbox_with_network_requirements() { let manager = SandboxManager::new(); - let expected = get_platform_sandbox(false).unwrap_or(SandboxType::None); + let expected = + get_platform_sandbox(/*windows_sandbox_enabled*/ false).unwrap_or(SandboxType::None); let sandbox = manager.select_initial( &FileSystemSandboxPolicy::unrestricted(), NetworkSandboxPolicy::Enabled, SandboxablePreference::Auto, WindowsSandboxLevel::Disabled, - true, + /*has_managed_network_requirements*/ true, ); assert_eq!(sandbox, expected); } @@ -53,7 +54,8 @@ fn danger_full_access_uses_platform_sandbox_with_network_requirements() { #[test] fn restricted_file_system_uses_platform_sandbox_without_managed_network() { let manager = SandboxManager::new(); - let expected = get_platform_sandbox(false).unwrap_or(SandboxType::None); + let expected = + get_platform_sandbox(/*windows_sandbox_enabled*/ false).unwrap_or(SandboxType::None); let sandbox = manager.select_initial( &FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { @@ -64,7 +66,7 @@ fn restricted_file_system_uses_platform_sandbox_without_managed_network() { NetworkSandboxPolicy::Enabled, SandboxablePreference::Auto, WindowsSandboxLevel::Disabled, - false, + /*has_managed_network_requirements*/ false, ); assert_eq!(sandbox, expected); } diff --git a/codex-rs/sandboxing/src/policy_transforms_tests.rs b/codex-rs/sandboxing/src/policy_transforms_tests.rs index 30dbac924..d287bd243 100644 --- a/codex-rs/sandboxing/src/policy_transforms_tests.rs +++ b/codex-rs/sandboxing/src/policy_transforms_tests.rs @@ -38,7 +38,11 @@ fn full_access_restricted_policy_skips_platform_sandbox_when_network_is_enabled( }]); assert_eq!( - should_require_platform_sandbox(&policy, NetworkSandboxPolicy::Enabled, false), + should_require_platform_sandbox( + &policy, + NetworkSandboxPolicy::Enabled, + /*has_managed_network_requirements*/ false + ), false ); } @@ -64,7 +68,11 @@ fn root_write_policy_with_carveouts_still_uses_platform_sandbox() { ]); assert_eq!( - should_require_platform_sandbox(&policy, NetworkSandboxPolicy::Enabled, false), + should_require_platform_sandbox( + &policy, + NetworkSandboxPolicy::Enabled, + /*has_managed_network_requirements*/ false + ), true ); } @@ -79,7 +87,11 @@ fn full_access_restricted_policy_still_uses_platform_sandbox_for_restricted_netw }]); assert_eq!( - should_require_platform_sandbox(&policy, NetworkSandboxPolicy::Restricted, false), + should_require_platform_sandbox( + &policy, + NetworkSandboxPolicy::Restricted, + /*has_managed_network_requirements*/ false + ), true ); } @@ -363,7 +375,8 @@ fn effective_file_system_sandbox_policy_returns_base_policy_without_additional_p }, ]); - let effective_policy = effective_file_system_sandbox_policy(&base_policy, None); + let effective_policy = + effective_file_system_sandbox_policy(&base_policy, /*additional_permissions*/ None); assert_eq!(effective_policy, base_policy); } diff --git a/codex-rs/sandboxing/src/seatbelt_tests.rs b/codex-rs/sandboxing/src/seatbelt_tests.rs index b83ac3118..d2ac67c0e 100644 --- a/codex-rs/sandboxing/src/seatbelt_tests.rs +++ b/codex-rs/sandboxing/src/seatbelt_tests.rs @@ -64,7 +64,7 @@ fn base_policy_allows_node_cpu_sysctls() { fn create_seatbelt_args_routes_network_through_proxy_ports() { let policy = dynamic_network_policy( &SandboxPolicy::new_read_only_policy(), - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![43128, 48081], has_proxy_config: true, @@ -116,8 +116,8 @@ fn explicit_unreadable_paths_are_excluded_from_full_disk_read_and_write_access() &file_system_policy, NetworkSandboxPolicy::Restricted, Path::new("/"), - false, - None, + /*enforce_managed_network*/ false, + /*network*/ None, ); let policy = seatbelt_policy_arg(&args); @@ -181,8 +181,8 @@ fn explicit_unreadable_paths_are_excluded_from_readable_roots() { &file_system_policy, NetworkSandboxPolicy::Restricted, Path::new("/"), - false, - None, + /*enforce_managed_network*/ false, + /*network*/ None, ); let policy = seatbelt_policy_arg(&args); @@ -219,7 +219,7 @@ fn seatbelt_args_without_extension_profile_keep_legacy_preferences_read_access() &SandboxPolicy::new_read_only_policy(), cwd.as_path(), /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let policy = &args[1]; assert!(policy.contains("(allow user-preference-read)")); @@ -246,7 +246,7 @@ fn seatbelt_legacy_workspace_write_nested_readable_root_stays_writable() { }, cwd.as_path(), /*enforce_managed_network*/ false, - None, + /*network*/ None, ); assert!( @@ -267,7 +267,7 @@ fn seatbelt_legacy_workspace_write_nested_readable_root_stays_writable() { fn create_seatbelt_args_allows_local_binding_when_explicitly_enabled() { let policy = dynamic_network_policy( &SandboxPolicy::new_read_only_policy(), - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![43128], has_proxy_config: true, @@ -304,7 +304,7 @@ fn dynamic_network_policy_preserves_restricted_policy_when_proxy_config_without_ exclude_tmpdir_env_var: false, exclude_slash_tmp: false, }, - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![], has_proxy_config: true, @@ -337,7 +337,7 @@ fn dynamic_network_policy_preserves_restricted_policy_for_managed_network_withou exclude_tmpdir_env_var: false, exclude_slash_tmp: false, }, - true, + /*enforce_managed_network*/ true, &ProxyPolicyInputs { ports: vec![], has_proxy_config: false, @@ -360,7 +360,7 @@ fn dynamic_network_policy_preserves_restricted_policy_for_managed_network_withou fn create_seatbelt_args_allowlists_unix_socket_paths() { let policy = dynamic_network_policy( &SandboxPolicy::new_read_only_policy(), - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![43128], has_proxy_config: true, @@ -453,7 +453,7 @@ fn normalize_path_for_sandbox_rejects_relative_paths() { fn create_seatbelt_args_allows_all_unix_sockets_when_enabled() { let policy = dynamic_network_policy( &SandboxPolicy::new_read_only_policy(), - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![43128], has_proxy_config: true, @@ -490,7 +490,7 @@ fn create_seatbelt_args_full_network_with_proxy_is_still_proxy_only() { exclude_tmpdir_env_var: false, exclude_slash_tmp: false, }, - false, + /*enforce_managed_network*/ false, &ProxyPolicyInputs { ports: vec![43128], has_proxy_config: true, @@ -562,7 +562,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() { &policy, &cwd, /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let policy_text = seatbelt_policy_arg(&args); @@ -676,7 +676,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() { &policy, &cwd, /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let output = Command::new(MACOS_PATH_TO_SEATBELT_EXECUTABLE) .args(&write_hooks_file_args) @@ -712,7 +712,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() { &policy, &cwd, /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let output = Command::new(MACOS_PATH_TO_SEATBELT_EXECUTABLE) .args(&write_allowed_file_args) @@ -832,7 +832,7 @@ fn create_seatbelt_args_with_read_only_git_pointer_file() { &policy, &cwd, /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let output = Command::new(MACOS_PATH_TO_SEATBELT_EXECUTABLE) @@ -868,7 +868,7 @@ fn create_seatbelt_args_with_read_only_git_pointer_file() { &policy, &cwd, /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let output = Command::new(MACOS_PATH_TO_SEATBELT_EXECUTABLE) .args(&gitdir_args) @@ -931,7 +931,7 @@ fn create_seatbelt_args_for_cwd_as_git_repo() { &policy, vulnerable_root.as_path(), /*enforce_managed_network*/ false, - None, + /*network*/ None, ); let tmpdir_env_var = std::env::var("TMPDIR") diff --git a/codex-rs/secrets/src/lib.rs b/codex-rs/secrets/src/lib.rs index fe482f7d2..280c723d3 100644 --- a/codex-rs/secrets/src/lib.rs +++ b/codex-rs/secrets/src/lib.rs @@ -219,7 +219,7 @@ mod tests { manager.set(&scope, &name, "token-1")?; assert_eq!(manager.get(&scope, &name)?, Some("token-1".to_string())); - let listed = manager.list(None)?; + let listed = manager.list(/*scope_filter*/ None)?; assert_eq!(listed.len(), 1); assert_eq!(listed[0].name, name); diff --git a/codex-rs/shell-escalation/src/unix/socket.rs b/codex-rs/shell-escalation/src/unix/socket.rs index aa97b5f37..cfff1268a 100644 --- a/codex-rs/shell-escalation/src/unix/socket.rs +++ b/codex-rs/shell-escalation/src/unix/socket.rs @@ -441,7 +441,7 @@ mod tests { id: 7, label: "round-trip".to_string(), }; - let send_fds = fd_list(1)?; + let send_fds = fd_list(/*count*/ 1)?; let receive_task = tokio::spawn(async move { server.receive_with_fds::().await }); @@ -474,7 +474,7 @@ mod tests { async fn async_datagram_sockets_round_trip_messages() -> std::io::Result<()> { let (server, client) = AsyncDatagramSocket::pair()?; let data = b"datagram payload".to_vec(); - let send_fds = fd_list(1)?; + let send_fds = fd_list(/*count*/ 1)?; let receive_task = tokio::spawn(async move { server.receive_with_fds().await }); client.send_with_fds(&data, &send_fds).await?; @@ -499,7 +499,7 @@ mod tests { fn send_stream_chunk_rejects_excessive_fd_counts() -> std::io::Result<()> { let (socket, _peer) = Socket::pair_raw(Domain::UNIX, Type::STREAM, None)?; let fds = fd_list(MAX_FDS_PER_MESSAGE + 1)?; - let err = send_stream_chunk(&socket, b"hello", &fds, true).unwrap_err(); + let err = send_stream_chunk(&socket, b"hello", &fds, /*include_fds*/ true).unwrap_err(); assert_eq!(std::io::ErrorKind::InvalidInput, err.kind()); Ok(()) } diff --git a/codex-rs/state/src/model/thread_metadata.rs b/codex-rs/state/src/model/thread_metadata.rs index 03a8a6f94..d14e3b479 100644 --- a/codex-rs/state/src/model/thread_metadata.rs +++ b/codex-rs/state/src/model/thread_metadata.rs @@ -525,6 +525,9 @@ mod tests { let metadata = ThreadMetadata::try_from(thread_row(Some("future"))) .expect("thread metadata should parse"); - assert_eq!(metadata, expected_thread_metadata(None)); + assert_eq!( + metadata, + expected_thread_metadata(/*reasoning_effort*/ None) + ); } } diff --git a/codex-rs/state/src/runtime/backfill.rs b/codex-rs/state/src/runtime/backfill.rs index ff63eda5f..cac3163f0 100644 --- a/codex-rs/state/src/runtime/backfill.rs +++ b/codex-rs/state/src/runtime/backfill.rs @@ -265,13 +265,13 @@ mod tests { .expect("initialize runtime"); let claimed = runtime - .try_claim_backfill(3600) + .try_claim_backfill(/*lease_seconds*/ 3600) .await .expect("initial backfill claim"); assert_eq!(claimed, true); let duplicate_claim = runtime - .try_claim_backfill(3600) + .try_claim_backfill(/*lease_seconds*/ 3600) .await .expect("duplicate backfill claim"); assert_eq!(duplicate_claim, false); @@ -291,17 +291,17 @@ WHERE id = 1 .expect("force stale backfill lease"); let stale_claim = runtime - .try_claim_backfill(10) + .try_claim_backfill(/*lease_seconds*/ 10) .await .expect("stale backfill claim"); assert_eq!(stale_claim, true); runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .expect("mark complete"); let claim_after_complete = runtime - .try_claim_backfill(3600) + .try_claim_backfill(/*lease_seconds*/ 3600) .await .expect("claim after complete"); assert_eq!(claim_after_complete, false); diff --git a/codex-rs/state/src/runtime/logs.rs b/codex-rs/state/src/runtime/logs.rs index b77678fc0..568795ba1 100644 --- a/codex-rs/state/src/runtime/logs.rs +++ b/codex-rs/state/src/runtime/logs.rs @@ -679,7 +679,12 @@ mod tests { #[test] fn format_feedback_log_line_matches_feedback_formatter_shape() { assert_eq!( - format_feedback_log_line(1, 123_456_000, "INFO", "alpha"), + format_feedback_log_line( + /*ts*/ 1, + /*ts_nanos*/ 123_456_000, + "INFO", + "alpha" + ), "1970-01-01T00:00:01.123456Z INFO alpha\n" ); } @@ -687,7 +692,12 @@ mod tests { #[test] fn format_feedback_log_line_preserves_existing_trailing_newline() { assert_eq!( - format_feedback_log_line(1, 123_456_000, "INFO", "alpha\n"), + format_feedback_log_line( + /*ts*/ 1, + /*ts_nanos*/ 123_456_000, + "INFO", + "alpha\n" + ), "1970-01-01T00:00:01.123456Z INFO alpha\n" ); } @@ -1247,9 +1257,9 @@ mod tests { assert_eq!( String::from_utf8(bytes).expect("valid utf-8"), [ - format_feedback_log_line(1, 0, "INFO", "alpha"), - format_feedback_log_line(2, 0, "INFO", "bravo"), - format_feedback_log_line(3, 0, "INFO", "charlie"), + format_feedback_log_line(/*ts*/ 1, /*ts_nanos*/ 0, "INFO", "alpha"), + format_feedback_log_line(/*ts*/ 2, /*ts_nanos*/ 0, "INFO", "bravo"), + format_feedback_log_line(/*ts*/ 3, /*ts_nanos*/ 0, "INFO", "charlie"), ] .concat() ); @@ -1380,9 +1390,24 @@ mod tests { assert_eq!( String::from_utf8(bytes).expect("valid utf-8"), [ - format_feedback_log_line(1, 0, "INFO", "threadless-before"), - format_feedback_log_line(2, 0, "INFO", "thread-scoped"), - format_feedback_log_line(3, 0, "INFO", "threadless-after"), + format_feedback_log_line( + /*ts*/ 1, + /*ts_nanos*/ 0, + "INFO", + "threadless-before" + ), + format_feedback_log_line( + /*ts*/ 2, + /*ts_nanos*/ 0, + "INFO", + "thread-scoped" + ), + format_feedback_log_line( + /*ts*/ 3, + /*ts_nanos*/ 0, + "INFO", + "threadless-after" + ), ] .concat() ); @@ -1463,9 +1488,24 @@ mod tests { assert_eq!( String::from_utf8(bytes).expect("valid utf-8"), [ - format_feedback_log_line(2, 0, "INFO", "old-process-thread"), - format_feedback_log_line(3, 0, "INFO", "new-process-thread"), - format_feedback_log_line(4, 0, "INFO", "new-process-threadless"), + format_feedback_log_line( + /*ts*/ 2, + /*ts_nanos*/ 0, + "INFO", + "old-process-thread" + ), + format_feedback_log_line( + /*ts*/ 3, + /*ts_nanos*/ 0, + "INFO", + "new-process-thread" + ), + format_feedback_log_line( + /*ts*/ 4, + /*ts_nanos*/ 0, + "INFO", + "new-process-threadless" + ), ] .concat() ); @@ -1647,10 +1687,20 @@ mod tests { assert_eq!( String::from_utf8(bytes).expect("valid utf-8"), [ - format_feedback_log_line(1, 0, "INFO", "thread-1"), - format_feedback_log_line(2, 0, "INFO", "thread-2"), - format_feedback_log_line(3, 0, "INFO", "threadless-proc-1"), - format_feedback_log_line(4, 0, "INFO", "threadless-proc-2"), + format_feedback_log_line(/*ts*/ 1, /*ts_nanos*/ 0, "INFO", "thread-1"), + format_feedback_log_line(/*ts*/ 2, /*ts_nanos*/ 0, "INFO", "thread-2"), + format_feedback_log_line( + /*ts*/ 3, + /*ts_nanos*/ 0, + "INFO", + "threadless-proc-1" + ), + format_feedback_log_line( + /*ts*/ 4, + /*ts_nanos*/ 0, + "INFO", + "threadless-proc-2" + ), ] .concat() ); diff --git a/codex-rs/state/src/runtime/memories.rs b/codex-rs/state/src/runtime/memories.rs index 386e0fd3e..1c1060d0b 100644 --- a/codex-rs/state/src/runtime/memories.rs +++ b/codex-rs/state/src/runtime/memories.rs @@ -1314,7 +1314,10 @@ mod tests { let owner_b = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner id"); let claim = runtime - .try_claim_stage1_job(thread_id, owner_a, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_a, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 job"); let ownership_token = match claim { @@ -1327,10 +1330,10 @@ mod tests { .mark_stage1_job_succeeded( thread_id, ownership_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw", "sum", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded"), @@ -1338,13 +1341,19 @@ mod tests { ); let up_to_date = runtime - .try_claim_stage1_job(thread_id, owner_b, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 up-to-date"); assert_eq!(up_to_date, Stage1JobClaimOutcome::SkippedUpToDate); let needs_rerun = runtime - .try_claim_stage1_job(thread_id, owner_b, 101, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 newer source"); assert!( @@ -1372,13 +1381,19 @@ mod tests { .expect("upsert thread"); let claim_a = runtime - .try_claim_stage1_job(thread_id, owner_a, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_a, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim a"); assert!(matches!(claim_a, Stage1JobClaimOutcome::Claimed { .. })); let claim_b_fresh = runtime - .try_claim_stage1_job(thread_id, owner_b, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim b fresh"); assert_eq!(claim_b_fresh, Stage1JobClaimOutcome::SkippedRunning); @@ -1390,7 +1405,10 @@ mod tests { .expect("force stale lease"); let claim_b_stale = runtime - .try_claim_stage1_job(thread_id, owner_b, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim b stale"); assert!(matches!( @@ -1429,7 +1447,10 @@ mod tests { owner: ThreadId| async move { for attempt in 0..5 { match runtime - .try_claim_stage1_job(thread_id, owner, 100, 3_600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, + /*lease_seconds*/ 3_600, /*max_running_jobs*/ 64, + ) .await { Ok(outcome) => return outcome, @@ -1500,13 +1521,19 @@ mod tests { let (claim_a, claim_b) = tokio::join!( async move { runtime_a - .try_claim_stage1_job(thread_a, owner_a, 100, 3_600, 1) + .try_claim_stage1_job( + thread_a, owner_a, /*source_updated_at*/ 100, + /*lease_seconds*/ 3_600, /*max_running_jobs*/ 1, + ) .await .expect("claim stage1 thread a") }, async move { runtime_b - .try_claim_stage1_job(thread_b, owner_b, 101, 3_600, 1) + .try_claim_stage1_job( + thread_b, owner_b, /*source_updated_at*/ 101, + /*lease_seconds*/ 3_600, /*max_running_jobs*/ 1, + ) .await .expect("claim stage1 thread b") }, @@ -1663,8 +1690,8 @@ mod tests { up_to_date_thread_id, worker_id, up_to_date.updated_at.timestamp(), - 3600, - 64, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, ) .await .expect("claim up-to-date thread for seed"); @@ -1680,7 +1707,7 @@ mod tests { up_to_date.updated_at.timestamp(), "raw", "summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark up-to-date thread succeeded"), @@ -1816,8 +1843,8 @@ mod tests { enabled_thread_id, worker_id, enabled.updated_at.timestamp(), - 3600, - 64, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, ) .await .expect("claim enabled thread"); @@ -1833,7 +1860,7 @@ mod tests { enabled.updated_at.timestamp(), "raw", "summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark enabled thread succeeded"), @@ -2084,7 +2111,7 @@ WHERE kind = 'memory_stage1' claim.thread.updated_at.timestamp(), "raw", "summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark first-batch stage1 success"), @@ -2127,7 +2154,10 @@ WHERE kind = 'memory_stage1' .expect("upsert thread"); let claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2139,10 +2169,10 @@ WHERE kind = 'memory_stage1' .mark_stage1_job_succeeded( thread_id, ownership_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw", "sum", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded"), @@ -2198,7 +2228,10 @@ WHERE kind = 'memory_stage1' .expect("upsert thread"); let claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2227,7 +2260,10 @@ WHERE kind = 'memory_stage1' ); let up_to_date = runtime - .try_claim_stage1_job(thread_id, owner_b, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 up-to-date"); assert_eq!(up_to_date, Stage1JobClaimOutcome::SkippedUpToDate); @@ -2245,7 +2281,7 @@ WHERE kind = 'memory_stage1' ); let claim_phase2 = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); assert_eq!( @@ -2277,7 +2313,10 @@ WHERE kind = 'memory_stage1' .expect("upsert thread"); let first_claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim initial stage1"); let first_token = match first_claim { @@ -2286,14 +2325,21 @@ WHERE kind = 'memory_stage1' }; assert!( runtime - .mark_stage1_job_succeeded(thread_id, first_token.as_str(), 100, "raw", "sum", None) + .mark_stage1_job_succeeded( + thread_id, + first_token.as_str(), + /*source_updated_at*/ 100, + "raw", + "sum", + /*rollout_slug*/ None + ) .await .expect("mark initial stage1 succeeded"), "initial stage1 success should create stage1 output" ); let phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2 after initial output"); let (phase2_token, phase2_input_watermark) = match phase2_claim { @@ -2317,7 +2363,10 @@ WHERE kind = 'memory_stage1' ); let no_output_claim = runtime - .try_claim_stage1_job(thread_id, owner_b, 101, 3600, 64) + .try_claim_stage1_job( + thread_id, owner_b, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 for no-output delete"); let no_output_token = match no_output_claim { @@ -2343,7 +2392,7 @@ WHERE kind = 'memory_stage1' assert_eq!(output_row_count, 0); let claim_phase2 = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2 after no-output deletion"); let (phase2_token, phase2_input_watermark) = match claim_phase2 { @@ -2388,7 +2437,10 @@ WHERE kind = 'memory_stage1' for attempt in 0..3 { let claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3_600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 for retry exhaustion"); let ownership_token = match claim { @@ -2400,7 +2452,12 @@ WHERE kind = 'memory_stage1' }; assert!( runtime - .mark_stage1_job_failed(thread_id, ownership_token.as_str(), "boom", 0) + .mark_stage1_job_failed( + thread_id, + ownership_token.as_str(), + "boom", + /*retry_delay_seconds*/ 0 + ) .await .expect("mark stage1 failed"), "attempt {} should decrement retry budget", @@ -2409,7 +2466,10 @@ WHERE kind = 'memory_stage1' } let exhausted_claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3_600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 after retry exhaustion"); assert_eq!( @@ -2418,7 +2478,10 @@ WHERE kind = 'memory_stage1' ); let newer_source_claim = runtime - .try_claim_stage1_job(thread_id, owner, 101, 3_600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3_600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 with newer source watermark"); assert!( @@ -2460,12 +2523,12 @@ WHERE kind = 'memory_stage1' let owner = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner id"); runtime - .enqueue_global_consolidation(100) + .enqueue_global_consolidation(/*input_watermark*/ 100) .await .expect("enqueue global consolidation"); let claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (ownership_token, input_watermark) = match claim { @@ -2484,18 +2547,18 @@ WHERE kind = 'memory_stage1' ); let claim_up_to_date = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2 up-to-date"); assert_eq!(claim_up_to_date, Phase2JobClaimOutcome::SkippedNotDirty); runtime - .enqueue_global_consolidation(101) + .enqueue_global_consolidation(/*input_watermark*/ 101) .await .expect("enqueue global consolidation again"); let claim_rerun = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2 rerun"); assert!( @@ -2533,7 +2596,13 @@ WHERE kind = 'memory_stage1' .expect("upsert thread b"); let claim = runtime - .try_claim_stage1_job(thread_id_a, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id_a, + owner, + /*source_updated_at*/ 100, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 a"); let ownership_token = match claim { @@ -2545,10 +2614,10 @@ WHERE kind = 'memory_stage1' .mark_stage1_job_succeeded( thread_id_a, ownership_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw memory a", "summary a", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded a"), @@ -2556,7 +2625,13 @@ WHERE kind = 'memory_stage1' ); let claim = runtime - .try_claim_stage1_job(thread_id_b, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_id_b, + owner, + /*source_updated_at*/ 101, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 b"); let ownership_token = match claim { @@ -2568,7 +2643,7 @@ WHERE kind = 'memory_stage1' .mark_stage1_job_succeeded( thread_id_b, ownership_token.as_str(), - 101, + /*source_updated_at*/ 101, "raw memory b", "summary b", Some("rollout-b"), @@ -2579,7 +2654,7 @@ WHERE kind = 'memory_stage1' ); let outputs = runtime - .list_stage1_outputs_for_global(10) + .list_stage1_outputs_for_global(/*n*/ 10) .await .expect("list stage1 outputs for global"); assert_eq!(outputs.len(), 2); @@ -2655,7 +2730,7 @@ VALUES (?, ?, ?, ?, ?) .expect("insert empty stage1 output"); let outputs = runtime - .list_stage1_outputs_for_global(1) + .list_stage1_outputs_for_global(/*n*/ 1) .await .expect("list stage1 outputs for global"); assert_eq!(outputs.len(), 1); @@ -2693,7 +2768,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2705,10 +2783,10 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, ownership_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw memory", "summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded"), @@ -2722,7 +2800,7 @@ VALUES (?, ?, ?, ?, ?) .expect("mark thread polluted"); let outputs = runtime - .list_stage1_outputs_for_global(10) + .list_stage1_outputs_for_global(/*n*/ 10) .await .expect("list stage1 outputs for global"); assert_eq!(outputs.len(), 1); @@ -2764,7 +2842,10 @@ VALUES (?, ?, ?, ?, ?) (thread_id_c, 102, Some("rollout-c")), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, updated_at, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2788,7 +2869,7 @@ VALUES (?, ?, ?, ?, ?) } let claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (ownership_token, input_watermark) = match claim { @@ -2800,7 +2881,7 @@ VALUES (?, ?, ?, ?, ?) }; assert_eq!(input_watermark, 102); let selected_outputs = runtime - .list_stage1_outputs_for_global(10) + .list_stage1_outputs_for_global(/*n*/ 10) .await .expect("list stage1 outputs for global") .into_iter() @@ -2819,7 +2900,7 @@ VALUES (?, ?, ?, ?, ?) ); let selection = runtime - .get_phase2_input_selection(2, 36_500) + .get_phase2_input_selection(/*n*/ 2, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); @@ -2867,7 +2948,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let claim = runtime - .try_claim_stage1_job(thread_id, owner, updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, updated_at, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2882,7 +2966,7 @@ VALUES (?, ?, ?, ?, ?) updated_at, &format!("raw-{updated_at}"), &format!("summary-{updated_at}"), - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded"), @@ -2891,7 +2975,7 @@ VALUES (?, ?, ?, ?, ?) } let claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (ownership_token, input_watermark) = match claim { @@ -2902,7 +2986,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected phase2 claim outcome: {other:?}"), }; let selected_outputs = runtime - .list_stage1_outputs_for_global(10) + .list_stage1_outputs_for_global(/*n*/ 10) .await .expect("list stage1 outputs for global"); assert!( @@ -2923,7 +3007,7 @@ VALUES (?, ?, ?, ?, ?) .expect("mark thread polluted"); let selection = runtime - .get_phase2_input_selection(2, 36_500) + .get_phase2_input_selection(/*n*/ 2, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); @@ -2968,7 +3052,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -2980,10 +3067,10 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, ownership_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw", "summary", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded"), @@ -2991,7 +3078,7 @@ VALUES (?, ?, ?, ?, ?) ); let phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (phase2_token, input_watermark) = match phase2_claim { @@ -3002,7 +3089,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected phase2 claim outcome: {other:?}"), }; let selected_outputs = runtime - .list_stage1_outputs_for_global(10) + .list_stage1_outputs_for_global(/*n*/ 10) .await .expect("list stage1 outputs"); assert!( @@ -3026,7 +3113,7 @@ VALUES (?, ?, ?, ?, ?) ); let next_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2 after pollution"); assert!(matches!(next_claim, Phase2JobClaimOutcome::Claimed { .. })); @@ -3053,7 +3140,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let first_claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim initial stage1"); let first_token = match first_claim { @@ -3065,7 +3155,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, first_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw-100", "summary-100", Some("rollout-100"), @@ -3076,7 +3166,7 @@ VALUES (?, ?, ?, ?, ?) ); let phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (phase2_token, input_watermark) = match phase2_claim { @@ -3087,7 +3177,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected phase2 claim outcome: {other:?}"), }; let selected_outputs = runtime - .list_stage1_outputs_for_global(1) + .list_stage1_outputs_for_global(/*n*/ 1) .await .expect("list selected outputs"); assert!( @@ -3103,7 +3193,10 @@ VALUES (?, ?, ?, ?, ?) ); let refreshed_claim = runtime - .try_claim_stage1_job(thread_id, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim refreshed stage1"); let refreshed_token = match refreshed_claim { @@ -3115,7 +3208,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, refreshed_token.as_str(), - 101, + /*source_updated_at*/ 101, "raw-101", "summary-101", Some("rollout-101"), @@ -3126,7 +3219,7 @@ VALUES (?, ?, ?, ?, ?) ); let selection = runtime - .get_phase2_input_selection(1, 36_500) + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); assert_eq!(selection.selected.len(), 1); @@ -3186,7 +3279,10 @@ VALUES (?, ?, ?, ?, ?) (thread_id_d, 98, Some("rollout-d-98")), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, updated_at, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim initial stage1"); let ownership_token = match claim { @@ -3210,7 +3306,7 @@ VALUES (?, ?, ?, ?, ?) } let phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (phase2_token, input_watermark) = match phase2_claim { @@ -3221,7 +3317,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected phase2 claim outcome: {other:?}"), }; let selected_outputs = runtime - .list_stage1_outputs_for_global(2) + .list_stage1_outputs_for_global(/*n*/ 2) .await .expect("list selected outputs"); assert_eq!( @@ -3249,7 +3345,10 @@ VALUES (?, ?, ?, ?, ?) (thread_id_d, 104, Some("rollout-d-104")), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, updated_at, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim refreshed stage1"); let ownership_token = match claim { @@ -3273,7 +3372,7 @@ VALUES (?, ?, ?, ?, ?) } let selection = runtime - .get_phase2_input_selection(2, 36_500) + .get_phase2_input_selection(/*n*/ 2, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); assert_eq!( @@ -3324,7 +3423,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let initial_claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim initial stage1"); let initial_token = match initial_claim { @@ -3336,7 +3438,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, initial_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw-100", "summary-100", Some("rollout-100"), @@ -3347,7 +3449,7 @@ VALUES (?, ?, ?, ?, ?) ); let first_phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim first phase2"); let (first_phase2_token, first_input_watermark) = match first_phase2_claim { @@ -3358,7 +3460,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected first phase2 claim outcome: {other:?}"), }; let first_selected_outputs = runtime - .list_stage1_outputs_for_global(1) + .list_stage1_outputs_for_global(/*n*/ 1) .await .expect("list first selected outputs"); assert!( @@ -3374,7 +3476,10 @@ VALUES (?, ?, ?, ?, ?) ); let refreshed_claim = runtime - .try_claim_stage1_job(thread_id, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim refreshed stage1"); let refreshed_token = match refreshed_claim { @@ -3386,7 +3491,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, refreshed_token.as_str(), - 101, + /*source_updated_at*/ 101, "raw-101", "summary-101", Some("rollout-101"), @@ -3397,7 +3502,7 @@ VALUES (?, ?, ?, ?, ?) ); let second_phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim second phase2"); let (second_phase2_token, second_input_watermark) = match second_phase2_claim { @@ -3408,7 +3513,7 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected second phase2 claim outcome: {other:?}"), }; let second_selected_outputs = runtime - .list_stage1_outputs_for_global(1) + .list_stage1_outputs_for_global(/*n*/ 1) .await .expect("list second selected outputs"); assert_eq!( @@ -3428,7 +3533,7 @@ VALUES (?, ?, ?, ?, ?) ); let selection = runtime - .get_phase2_input_selection(1, 36_500) + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection after refresh"); assert_eq!(selection.retained_thread_ids, vec![thread_id]); @@ -3466,7 +3571,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread"); let initial_claim = runtime - .try_claim_stage1_job(thread_id, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim initial stage1"); let initial_token = match initial_claim { @@ -3478,7 +3586,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, initial_token.as_str(), - 100, + /*source_updated_at*/ 100, "raw-100", "summary-100", Some("rollout-100"), @@ -3489,7 +3597,7 @@ VALUES (?, ?, ?, ?, ?) ); let phase2_claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim phase2"); let (phase2_token, input_watermark) = match phase2_claim { @@ -3500,13 +3608,16 @@ VALUES (?, ?, ?, ?, ?) other => panic!("unexpected phase2 claim outcome: {other:?}"), }; let selected_outputs = runtime - .list_stage1_outputs_for_global(1) + .list_stage1_outputs_for_global(/*n*/ 1) .await .expect("list selected outputs"); assert_eq!(selected_outputs[0].source_updated_at.timestamp(), 100); let refreshed_claim = runtime - .try_claim_stage1_job(thread_id, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_id, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim refreshed stage1"); let refreshed_token = match refreshed_claim { @@ -3518,7 +3629,7 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_id, refreshed_token.as_str(), - 101, + /*source_updated_at*/ 101, "raw-101", "summary-101", Some("rollout-101"), @@ -3552,7 +3663,7 @@ VALUES (?, ?, ?, ?, ?) assert_eq!(selected_for_phase2_source_updated_at, None); let selection = runtime - .get_phase2_input_selection(1, 36_500) + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); assert_eq!(selection.selected.len(), 1); @@ -3592,7 +3703,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread b"); let claim_a = runtime - .try_claim_stage1_job(thread_a, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_a, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 a"); let token_a = match claim_a { @@ -3601,13 +3715,23 @@ VALUES (?, ?, ?, ?, ?) }; assert!( runtime - .mark_stage1_job_succeeded(thread_a, token_a.as_str(), 100, "raw a", "sum a", None) + .mark_stage1_job_succeeded( + thread_a, + token_a.as_str(), + /*source_updated_at*/ 100, + "raw a", + "sum a", + /*rollout_slug*/ None + ) .await .expect("mark stage1 succeeded a") ); let claim_b = runtime - .try_claim_stage1_job(thread_b, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_b, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 b"); let token_b = match claim_b { @@ -3616,7 +3740,14 @@ VALUES (?, ?, ?, ?, ?) }; assert!( runtime - .mark_stage1_job_succeeded(thread_b, token_b.as_str(), 101, "raw b", "sum b", None) + .mark_stage1_job_succeeded( + thread_b, + token_b.as_str(), + /*source_updated_at*/ 101, + "raw b", + "sum b", + /*rollout_slug*/ None + ) .await .expect("mark stage1 succeeded b") ); @@ -3696,7 +3827,13 @@ VALUES (?, ?, ?, ?, ?) ] { let source_updated_at = generated_at.timestamp(); let claim = runtime - .try_claim_stage1_job(thread_id, owner, source_updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, + owner, + source_updated_at, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -3711,7 +3848,7 @@ VALUES (?, ?, ?, ?, ?) source_updated_at, &format!("raw-{summary}"), summary, - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 success"), @@ -3736,7 +3873,7 @@ VALUES (?, ?, ?, ?, ?) } let selection = runtime - .get_phase2_input_selection(3, 30) + .get_phase2_input_selection(/*n*/ 3, /*max_unused_days*/ 30) .await .expect("load phase2 input selection"); @@ -3787,7 +3924,13 @@ VALUES (?, ?, ?, ?, ?) ] { let source_updated_at = generated_at.timestamp(); let claim = runtime - .try_claim_stage1_job(thread_id, owner, source_updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, + owner, + source_updated_at, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -3802,7 +3945,7 @@ VALUES (?, ?, ?, ?, ?) source_updated_at, &format!("raw-{summary}"), summary, - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 success"), @@ -3827,7 +3970,7 @@ VALUES (?, ?, ?, ?, ?) } let selection = runtime - .get_phase2_input_selection(3, 30) + .get_phase2_input_selection(/*n*/ 3, /*max_unused_days*/ 30) .await .expect("load phase2 input selection"); @@ -3875,7 +4018,13 @@ VALUES (?, ?, ?, ?, ?) (newer_thread, 200_i64, "summary-newer"), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, source_updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, + owner, + source_updated_at, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -3890,7 +4039,7 @@ VALUES (?, ?, ?, ?, ?) source_updated_at, &format!("raw-{summary}"), summary, - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 success"), @@ -3912,7 +4061,7 @@ VALUES (?, ?, ?, ?, ?) .expect("update newer generated_at"); let selection = runtime - .get_phase2_input_selection(1, 36_500) + .get_phase2_input_selection(/*n*/ 1, /*max_unused_days*/ 36_500) .await .expect("load phase2 input selection"); @@ -3978,7 +4127,13 @@ VALUES (?, ?, ?, ?, ?) ), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, source_updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, + owner, + source_updated_at, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -3993,7 +4148,7 @@ VALUES (?, ?, ?, ?, ?) source_updated_at, &format!("raw-{summary}"), summary, - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 success"), @@ -4034,7 +4189,7 @@ VALUES (?, ?, ?, ?, ?) .expect("count stage1 jobs before prune"); let pruned = runtime - .prune_stage1_outputs_for_retention(30, 100) + .prune_stage1_outputs_for_retention(/*max_unused_days*/ 30, /*limit*/ 100) .await .expect("prune stage1 outputs"); assert_eq!(pruned, 2); @@ -4093,7 +4248,13 @@ VALUES (?, ?, ?, ?, ?) (thread_c, now - Duration::days(40).num_seconds(), "stale-c"), ] { let claim = runtime - .try_claim_stage1_job(thread_id, owner, source_updated_at, 3600, 64) + .try_claim_stage1_job( + thread_id, + owner, + source_updated_at, + /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1"); let ownership_token = match claim { @@ -4108,7 +4269,7 @@ VALUES (?, ?, ?, ?, ?) source_updated_at, &format!("raw-{summary}"), summary, - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 success"), @@ -4117,7 +4278,7 @@ VALUES (?, ?, ?, ?, ?) } let pruned = runtime - .prune_stage1_outputs_for_retention(30, 2) + .prune_stage1_outputs_for_retention(/*max_unused_days*/ 30, /*limit*/ 2) .await .expect("prune stage1 outputs with limit"); assert_eq!(pruned, 2); @@ -4160,7 +4321,10 @@ VALUES (?, ?, ?, ?, ?) .expect("upsert thread b"); let claim_a = runtime - .try_claim_stage1_job(thread_a, owner, 100, 3600, 64) + .try_claim_stage1_job( + thread_a, owner, /*source_updated_at*/ 100, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 a"); let token_a = match claim_a { @@ -4172,10 +4336,10 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_a, token_a.as_str(), - 100, + /*source_updated_at*/ 100, "raw-a", "summary-a", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded a"), @@ -4183,7 +4347,10 @@ VALUES (?, ?, ?, ?, ?) ); let claim_b = runtime - .try_claim_stage1_job(thread_b, owner, 101, 3600, 64) + .try_claim_stage1_job( + thread_b, owner, /*source_updated_at*/ 101, /*lease_seconds*/ 3600, + /*max_running_jobs*/ 64, + ) .await .expect("claim stage1 b"); let token_b = match claim_b { @@ -4195,10 +4362,10 @@ VALUES (?, ?, ?, ?, ?) .mark_stage1_job_succeeded( thread_b, token_b.as_str(), - 101, + /*source_updated_at*/ 101, "raw-b", "summary-b", - None, + /*rollout_slug*/ None, ) .await .expect("mark stage1 succeeded b"), @@ -4206,7 +4373,7 @@ VALUES (?, ?, ?, ?, ?) ); let claim = runtime - .try_claim_global_phase2_job(owner, 3600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3600) .await .expect("claim global consolidation"); let input_watermark = match claim { @@ -4228,7 +4395,7 @@ VALUES (?, ?, ?, ?, ?) .expect("initialize runtime"); runtime - .enqueue_global_consolidation(200) + .enqueue_global_consolidation(/*input_watermark*/ 200) .await .expect("enqueue global consolidation"); @@ -4236,7 +4403,7 @@ VALUES (?, ?, ?, ?, ?) let owner_b = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner b"); let running_claim = runtime - .try_claim_global_phase2_job(owner_a, 3600) + .try_claim_global_phase2_job(owner_a, /*lease_seconds*/ 3600) .await .expect("claim global lock"); assert!( @@ -4245,7 +4412,7 @@ VALUES (?, ?, ?, ?, ?) ); let second_claim = runtime - .try_claim_global_phase2_job(owner_b, 3600) + .try_claim_global_phase2_job(owner_b, /*lease_seconds*/ 3600) .await .expect("claim global lock from second owner"); assert_eq!(second_claim, Phase2JobClaimOutcome::SkippedRunning); @@ -4261,7 +4428,7 @@ VALUES (?, ?, ?, ?, ?) .expect("initialize runtime"); runtime - .enqueue_global_consolidation(300) + .enqueue_global_consolidation(/*input_watermark*/ 300) .await .expect("enqueue global consolidation"); @@ -4269,7 +4436,7 @@ VALUES (?, ?, ?, ?, ?) let owner_b = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner b"); let initial_claim = runtime - .try_claim_global_phase2_job(owner_a, 3600) + .try_claim_global_phase2_job(owner_a, /*lease_seconds*/ 3600) .await .expect("claim initial global lock"); let token_a = match initial_claim { @@ -4288,7 +4455,7 @@ VALUES (?, ?, ?, ?, ?) .expect("expire global consolidation lease"); let takeover_claim = runtime - .try_claim_global_phase2_job(owner_b, 3600) + .try_claim_global_phase2_job(owner_b, /*lease_seconds*/ 3600) .await .expect("claim stale global lock"); let (token_b, input_watermark) = match takeover_claim { @@ -4303,7 +4470,11 @@ VALUES (?, ?, ?, ?, ?) assert_eq!( runtime - .mark_global_phase2_job_succeeded(token_a.as_str(), 300, &[]) + .mark_global_phase2_job_succeeded( + token_a.as_str(), + /*completed_watermark*/ 300, + &[] + ) .await .expect("mark stale owner success result"), false, @@ -4311,7 +4482,11 @@ VALUES (?, ?, ?, ?, ?) ); assert!( runtime - .mark_global_phase2_job_succeeded(token_b.as_str(), 300, &[]) + .mark_global_phase2_job_succeeded( + token_b.as_str(), + /*completed_watermark*/ 300, + &[] + ) .await .expect("mark takeover owner success"), "takeover owner should finalize consolidation" @@ -4328,12 +4503,12 @@ VALUES (?, ?, ?, ?, ?) .expect("initialize runtime"); runtime - .enqueue_global_consolidation(500) + .enqueue_global_consolidation(/*input_watermark*/ 500) .await .expect("enqueue initial consolidation"); let owner_a = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner a"); let claim_a = runtime - .try_claim_global_phase2_job(owner_a, 3_600) + .try_claim_global_phase2_job(owner_a, /*lease_seconds*/ 3_600) .await .expect("claim initial consolidation"); let token_a = match claim_a { @@ -4348,20 +4523,24 @@ VALUES (?, ?, ?, ?, ?) }; assert!( runtime - .mark_global_phase2_job_succeeded(token_a.as_str(), 500, &[]) + .mark_global_phase2_job_succeeded( + token_a.as_str(), + /*completed_watermark*/ 500, + &[] + ) .await .expect("mark initial phase2 success"), "initial phase2 success should finalize" ); runtime - .enqueue_global_consolidation(400) + .enqueue_global_consolidation(/*input_watermark*/ 400) .await .expect("enqueue backfilled consolidation"); let owner_b = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner b"); let claim_b = runtime - .try_claim_global_phase2_job(owner_b, 3_600) + .try_claim_global_phase2_job(owner_b, /*lease_seconds*/ 3_600) .await .expect("claim backfilled consolidation"); match claim_b { @@ -4387,13 +4566,13 @@ VALUES (?, ?, ?, ?, ?) .expect("initialize runtime"); runtime - .enqueue_global_consolidation(400) + .enqueue_global_consolidation(/*input_watermark*/ 400) .await .expect("enqueue global consolidation"); let owner = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner"); let claim = runtime - .try_claim_global_phase2_job(owner, 3_600) + .try_claim_global_phase2_job(owner, /*lease_seconds*/ 3_600) .await .expect("claim global consolidation"); let ownership_token = match claim { @@ -4412,7 +4591,11 @@ VALUES (?, ?, ?, ?, ?) assert_eq!( runtime - .mark_global_phase2_job_failed(ownership_token.as_str(), "lost", 3_600) + .mark_global_phase2_job_failed( + ownership_token.as_str(), + "lost", + /*retry_delay_seconds*/ 3_600 + ) .await .expect("mark phase2 failed with strict ownership"), false, @@ -4420,14 +4603,18 @@ VALUES (?, ?, ?, ?, ?) ); assert!( runtime - .mark_global_phase2_job_failed_if_unowned(ownership_token.as_str(), "lost", 3_600) + .mark_global_phase2_job_failed_if_unowned( + ownership_token.as_str(), + "lost", + /*retry_delay_seconds*/ 3_600 + ) .await .expect("fallback failure update should match unowned running job"), "fallback failure update should transition the unowned running job" ); let claim = runtime - .try_claim_global_phase2_job(ThreadId::new(), 3_600) + .try_claim_global_phase2_job(ThreadId::new(), /*lease_seconds*/ 3_600) .await .expect("claim after fallback failure"); assert_eq!(claim, Phase2JobClaimOutcome::SkippedNotDirty); diff --git a/codex-rs/state/src/runtime/threads.rs b/codex-rs/state/src/runtime/threads.rs index e3312c87d..09b23a431 100644 --- a/codex-rs/state/src/runtime/threads.rs +++ b/codex-rs/state/src/runtime/threads.rs @@ -1037,7 +1037,10 @@ mod tests { })]; runtime - .apply_rollout_items(&builder, &items, None, None) + .apply_rollout_items( + &builder, &items, /*new_thread_memory_mode*/ None, + /*updated_at_override*/ None, + ) .await .expect("apply_rollout_items should succeed"); @@ -1096,7 +1099,10 @@ mod tests { })]; runtime - .apply_rollout_items(&builder, &items, None, None) + .apply_rollout_items( + &builder, &items, /*new_thread_memory_mode*/ None, + /*updated_at_override*/ None, + ) .await .expect("apply_rollout_items should succeed"); @@ -1329,7 +1335,12 @@ mod tests { DateTime::::from_timestamp(1_700_001_234, 0).expect("timestamp"); runtime - .apply_rollout_items(&builder, &items, None, Some(override_updated_at)) + .apply_rollout_items( + &builder, + &items, + /*new_thread_memory_mode*/ None, + Some(override_updated_at), + ) .await .expect("apply_rollout_items should succeed"); diff --git a/codex-rs/terminal-detection/src/terminal_tests.rs b/codex-rs/terminal-detection/src/terminal_tests.rs index d779a54ab..bd527bc55 100644 --- a/codex-rs/terminal-detection/src/terminal_tests.rs +++ b/codex-rs/terminal-detection/src/terminal_tests.rs @@ -68,8 +68,8 @@ fn detects_term_program() { TerminalName::Iterm2, Some("iTerm.app"), Some("3.5.0"), - None, - None, + /*term*/ None, + /*multiplexer*/ None, ), "term_program_with_version_info" ); @@ -85,7 +85,13 @@ fn detects_term_program() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Iterm2, Some("iTerm.app"), None, None, None), + terminal_info( + TerminalName::Iterm2, + Some("iTerm.app"), + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "term_program_without_version_info" ); assert_eq!( @@ -100,7 +106,13 @@ fn detects_term_program() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Iterm2, Some("iTerm.app"), None, None, None), + terminal_info( + TerminalName::Iterm2, + Some("iTerm.app"), + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "term_program_overrides_wezterm_info" ); assert_eq!( @@ -116,7 +128,13 @@ fn detects_iterm2() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Iterm2, None, None, None, None), + terminal_info( + TerminalName::Iterm2, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "iterm_session_id_info" ); assert_eq!( @@ -135,9 +153,9 @@ fn detects_apple_terminal() { terminal_info( TerminalName::AppleTerminal, Some("Apple_Terminal"), - None, - None, - None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None, ), "apple_term_program_info" ); @@ -151,7 +169,13 @@ fn detects_apple_terminal() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::AppleTerminal, None, None, None, None), + terminal_info( + TerminalName::AppleTerminal, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "apple_term_session_id_info" ); assert_eq!( @@ -167,7 +191,13 @@ fn detects_ghostty() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Ghostty, Some("Ghostty"), None, None, None), + terminal_info( + TerminalName::Ghostty, + Some("Ghostty"), + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "ghostty_term_program_info" ); assert_eq!( @@ -189,8 +219,8 @@ fn detects_vscode() { TerminalName::VsCode, Some("vscode"), Some("1.86.0"), - None, - None + /*term*/ None, + /*multiplexer*/ None ), "vscode_term_program_info" ); @@ -213,8 +243,8 @@ fn detects_warp_terminal() { TerminalName::WarpTerminal, Some("WarpTerminal"), Some("v0.2025.12.10.08.12.stable_03"), - None, - None, + /*term*/ None, + /*multiplexer*/ None, ), "warp_term_program_info" ); @@ -237,7 +267,7 @@ fn detects_tmux_multiplexer() { terminal_info( TerminalName::Unknown, Some("xterm-256color"), - None, + /*version*/ None, Some("screen-256color"), Some(Multiplexer::Tmux { version: None }), ), @@ -272,15 +302,15 @@ fn detects_tmux_client_termtype() { let env = FakeEnvironment::new() .with_var("TMUX", "/tmp/tmux-1000/default,123,0") .with_var("TERM_PROGRAM", "tmux") - .with_tmux_client_info(Some("WezTerm"), None); + .with_tmux_client_info(Some("WezTerm"), /*termname*/ None); let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, terminal_info( TerminalName::WezTerm, Some("WezTerm"), - None, - None, + /*version*/ None, + /*term*/ None, Some(Multiplexer::Tmux { version: None }), ), "tmux_client_termtype_info" @@ -297,14 +327,14 @@ fn detects_tmux_client_termname() { let env = FakeEnvironment::new() .with_var("TMUX", "/tmp/tmux-1000/default,123,0") .with_var("TERM_PROGRAM", "tmux") - .with_tmux_client_info(None, Some("xterm-256color")); + .with_tmux_client_info(/*termtype*/ None, Some("xterm-256color")); let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, terminal_info( TerminalName::Unknown, - None, - None, + /*term_program*/ None, + /*version*/ None, Some("xterm-256color"), Some(Multiplexer::Tmux { version: None }) ), @@ -351,7 +381,13 @@ fn detects_wezterm() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::WezTerm, None, Some("2024.2"), None, None), + terminal_info( + TerminalName::WezTerm, + /*term_program*/ None, + Some("2024.2"), + /*term*/ None, + /*multiplexer*/ None + ), "wezterm_version_info" ); assert_eq!( @@ -370,8 +406,8 @@ fn detects_wezterm() { TerminalName::WezTerm, Some("WezTerm"), Some("2024.2"), - None, - None + /*term*/ None, + /*multiplexer*/ None ), "wezterm_term_program_info" ); @@ -385,7 +421,13 @@ fn detects_wezterm() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::WezTerm, None, None, None, None), + terminal_info( + TerminalName::WezTerm, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "wezterm_empty_info" ); assert_eq!( @@ -401,7 +443,13 @@ fn detects_kitty() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Kitty, None, None, None, None), + terminal_info( + TerminalName::Kitty, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "kitty_window_id_info" ); assert_eq!( @@ -420,8 +468,8 @@ fn detects_kitty() { TerminalName::Kitty, Some("kitty"), Some("0.30.1"), - None, - None + /*term*/ None, + /*multiplexer*/ None ), "kitty_term_program_info" ); @@ -437,7 +485,13 @@ fn detects_kitty() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Kitty, None, None, None, None), + terminal_info( + TerminalName::Kitty, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "kitty_term_over_alacritty_info" ); assert_eq!( @@ -453,7 +507,13 @@ fn detects_alacritty() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Alacritty, None, None, None, None), + terminal_info( + TerminalName::Alacritty, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "alacritty_socket_info" ); assert_eq!( @@ -472,8 +532,8 @@ fn detects_alacritty() { TerminalName::Alacritty, Some("Alacritty"), Some("0.13.2"), - None, - None, + /*term*/ None, + /*multiplexer*/ None, ), "alacritty_term_program_info" ); @@ -487,7 +547,13 @@ fn detects_alacritty() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Alacritty, None, None, None, None), + terminal_info( + TerminalName::Alacritty, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "alacritty_term_info" ); assert_eq!( @@ -503,7 +569,13 @@ fn detects_konsole() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Konsole, None, Some("230800"), None, None), + terminal_info( + TerminalName::Konsole, + /*term_program*/ None, + Some("230800"), + /*term*/ None, + /*multiplexer*/ None + ), "konsole_version_info" ); assert_eq!( @@ -522,8 +594,8 @@ fn detects_konsole() { TerminalName::Konsole, Some("Konsole"), Some("230800"), - None, - None + /*term*/ None, + /*multiplexer*/ None ), "konsole_term_program_info" ); @@ -537,7 +609,13 @@ fn detects_konsole() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Konsole, None, None, None, None), + terminal_info( + TerminalName::Konsole, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "konsole_empty_info" ); assert_eq!( @@ -553,7 +631,13 @@ fn detects_gnome_terminal() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::GnomeTerminal, None, None, None, None), + terminal_info( + TerminalName::GnomeTerminal, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "gnome_terminal_screen_info" ); assert_eq!( @@ -572,8 +656,8 @@ fn detects_gnome_terminal() { TerminalName::GnomeTerminal, Some("gnome-terminal"), Some("3.50"), - None, - None, + /*term*/ None, + /*multiplexer*/ None, ), "gnome_terminal_term_program_info" ); @@ -590,7 +674,13 @@ fn detects_vte() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Vte, None, Some("7000"), None, None), + terminal_info( + TerminalName::Vte, + /*term_program*/ None, + Some("7000"), + /*term*/ None, + /*multiplexer*/ None + ), "vte_version_info" ); assert_eq!( @@ -605,7 +695,13 @@ fn detects_vte() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Vte, Some("VTE"), Some("7000"), None, None), + terminal_info( + TerminalName::Vte, + Some("VTE"), + Some("7000"), + /*term*/ None, + /*multiplexer*/ None + ), "vte_term_program_info" ); assert_eq!( @@ -618,7 +714,13 @@ fn detects_vte() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Vte, None, None, None, None), + terminal_info( + TerminalName::Vte, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "vte_empty_info" ); assert_eq!(terminal.user_agent_token(), "VTE", "vte_empty_user_agent"); @@ -630,7 +732,13 @@ fn detects_windows_terminal() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::WindowsTerminal, None, None, None, None), + terminal_info( + TerminalName::WindowsTerminal, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "wt_session_info" ); assert_eq!( @@ -649,8 +757,8 @@ fn detects_windows_terminal() { TerminalName::WindowsTerminal, Some("WindowsTerminal"), Some("1.21"), - None, - None, + /*term*/ None, + /*multiplexer*/ None, ), "windows_terminal_term_program_info" ); @@ -669,10 +777,10 @@ fn detects_term_fallbacks() { terminal, terminal_info( TerminalName::Unknown, - None, - None, + /*term_program*/ None, + /*version*/ None, Some("xterm-256color"), - None, + /*multiplexer*/ None, ), "term_fallback_info" ); @@ -686,7 +794,13 @@ fn detects_term_fallbacks() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Dumb, None, None, Some("dumb"), None), + terminal_info( + TerminalName::Dumb, + /*term_program*/ None, + /*version*/ None, + Some("dumb"), + /*multiplexer*/ None + ), "dumb_term_info" ); assert_eq!(terminal.user_agent_token(), "dumb", "dumb_term_user_agent"); @@ -695,7 +809,13 @@ fn detects_term_fallbacks() { let terminal = detect_terminal_info_from_env(&env); assert_eq!( terminal, - terminal_info(TerminalName::Unknown, None, None, None, None), + terminal_info( + TerminalName::Unknown, + /*term_program*/ None, + /*version*/ None, + /*term*/ None, + /*multiplexer*/ None + ), "unknown_info" ); assert_eq!(terminal.user_agent_token(), "unknown", "unknown_user_agent"); diff --git a/codex-rs/tui_app_server/src/app.rs b/codex-rs/tui_app_server/src/app.rs index 945bf0f4e..8abb4e448 100644 --- a/codex-rs/tui_app_server/src/app.rs +++ b/codex-rs/tui_app_server/src/app.rs @@ -5971,12 +5971,18 @@ mod tests { App::should_wait_for_initial_session(&SessionSelection::StartFresh); assert_eq!(wait_for_initial_session, true); assert_eq!( - App::should_handle_active_thread_events(wait_for_initial_session, true), + App::should_handle_active_thread_events( + wait_for_initial_session, + /*has_active_thread_receiver*/ true + ), false ); assert_eq!( - App::should_stop_waiting_for_initial_session(wait_for_initial_session, None), + App::should_stop_waiting_for_initial_session( + wait_for_initial_session, + /*primary_thread_id*/ None + ), false ); if App::should_stop_waiting_for_initial_session( @@ -5988,7 +5994,10 @@ mod tests { assert_eq!(wait_for_initial_session, false); assert_eq!( - App::should_handle_active_thread_events(wait_for_initial_session, true), + App::should_handle_active_thread_events( + wait_for_initial_session, + /*has_active_thread_receiver*/ true + ), true ); } @@ -6002,7 +6011,10 @@ mod tests { }, )); assert_eq!( - App::should_handle_active_thread_events(wait_for_resume, true), + App::should_handle_active_thread_events( + wait_for_resume, + /*has_active_thread_receiver*/ true + ), true ); let wait_for_fork = App::should_wait_for_initial_session(&SessionSelection::Fork( @@ -6012,7 +6024,10 @@ mod tests { }, )); assert_eq!( - App::should_handle_active_thread_events(wait_for_fork, true), + App::should_handle_active_thread_events( + wait_for_fork, + /*has_active_thread_receiver*/ true + ), true ); } @@ -6021,7 +6036,8 @@ mod tests { async fn enqueue_primary_thread_session_replays_buffered_approval_after_attach() -> Result<()> { let (mut app, mut app_event_rx, _op_rx) = make_test_app_with_channels().await; let thread_id = ThreadId::new(); - let approval_request = exec_approval_request(thread_id, "turn-1", "call-1", None); + let approval_request = + exec_approval_request(thread_id, "turn-1", "call-1", /*approval_id*/ None); app.enqueue_primary_thread_request(approval_request).await?; app.enqueue_primary_thread_session( @@ -6118,7 +6134,7 @@ mod tests { while let Ok(event) = app_event_rx.try_recv() { match event { AppEvent::InsertHistoryCell(cell) => { - let transcript = lines_to_single_string(&cell.transcript_lines(80)); + let transcript = lines_to_single_string(&cell.transcript_lines(/*width*/ 80)); saw_replayed_answer |= transcript.contains("earlier prompt"); } AppEvent::SubmitThreadOp { @@ -6227,8 +6243,8 @@ mod tests { let mut app = make_test_app().await; let thread_id = ThreadId::new(); app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); - app.set_thread_active(thread_id, true).await; + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); + app.set_thread_active(thread_id, /*active*/ true).await; let event = thread_closed_notification(thread_id); @@ -6310,7 +6326,7 @@ mod tests { make_chatwidget_manual_with_sender().await; app.chat_widget = chat_widget; - app.replay_thread_snapshot(snapshot, true); + app.replay_thread_snapshot(snapshot, /*resume_restored_queue*/ true); assert_eq!(app.chat_widget.composer_text_with_pending(), "draft prompt"); assert!(app.chat_widget.queued_user_message_texts().is_empty()); @@ -6348,11 +6364,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6377,7 +6395,7 @@ mod tests { )], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); match next_user_turn_op(&mut new_op_rx) { @@ -6398,11 +6416,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6428,7 +6448,7 @@ mod tests { )], input_state: Some(input_state), }, - false, + /*resume_restored_queue*/ false, ); assert_eq!( @@ -6447,11 +6467,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6475,7 +6497,7 @@ mod tests { events: vec![], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); assert_eq!( @@ -6494,11 +6516,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6522,7 +6546,7 @@ mod tests { events: Vec::new(), input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); assert_eq!( @@ -6552,7 +6576,7 @@ mod tests { events: Vec::new(), input_state: None, }, - false, + /*resume_restored_queue*/ false, ); assert!(app.chat_widget.is_task_running_for_test()); @@ -6564,11 +6588,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6601,7 +6627,7 @@ mod tests { ], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); assert!( @@ -6615,7 +6641,7 @@ mod tests { app.chat_widget.handle_server_notification( turn_completed_notification(thread_id, "turn-1", TurnStatus::Completed), - None, + /*replay_kind*/ None, ); match next_user_turn_op(&mut new_op_rx) { @@ -6668,7 +6694,7 @@ mod tests { let (chat_widget, _app_event_tx, _rx, mut new_op_rx) = make_chatwidget_manual_with_sender().await; app.chat_widget = chat_widget; - app.replay_thread_snapshot(snapshot, true); + app.replay_thread_snapshot(snapshot, /*resume_restored_queue*/ true); assert_eq!(app.chat_widget.composer_text_with_pending(), large); @@ -6733,7 +6759,7 @@ mod tests { events: vec![], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); app.chat_widget .handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); @@ -6814,7 +6840,7 @@ mod tests { events: vec![], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); assert_eq!( @@ -6834,11 +6860,13 @@ mod tests { let thread_id = ThreadId::new(); let session = test_thread_session(thread_id, PathBuf::from("/tmp/project")); app.chat_widget.handle_thread_session(session.clone()); - app.chat_widget - .handle_server_notification(turn_started_notification(thread_id, "turn-1"), None); + app.chat_widget.handle_server_notification( + turn_started_notification(thread_id, "turn-1"), + /*replay_kind*/ None, + ); app.chat_widget.handle_server_notification( agent_message_delta_notification(thread_id, "turn-1", "agent-1", "streaming"), - None, + /*replay_kind*/ None, ); app.chat_widget .apply_external_edit("queued follow-up".to_string()); @@ -6864,7 +6892,7 @@ mod tests { )], input_state: Some(input_state), }, - true, + /*resume_restored_queue*/ true, ); assert_eq!( @@ -6907,7 +6935,7 @@ mod tests { .expect("embedded app server"); let thread_id = ThreadId::new(); app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.open_agent_picker(&mut app_server).await; @@ -6933,12 +6961,12 @@ mod tests { .expect("embedded app server"); let thread_id = ThreadId::new(); app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.agent_navigation.upsert( thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - true, + /*is_closed*/ true, ); app.open_agent_picker(&mut app_server).await; @@ -6964,12 +6992,12 @@ mod tests { .expect("embedded app server"); let thread_id = ThreadId::new(); app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.agent_navigation.upsert( thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); app.open_agent_picker(&mut app_server).await; @@ -7037,7 +7065,7 @@ mod tests { .await?; let thread_id = started.session.thread_id; app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.open_agent_picker(&mut app_server).await; @@ -7074,7 +7102,7 @@ mod tests { other => panic!("expected InsertHistoryCell event, got {other:?}"), }; let rendered = cell - .display_lines(120) + .display_lines(/*width*/ 120) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -7151,7 +7179,7 @@ mod tests { other => panic!("expected InsertHistoryCell event, got {other:?}"), }; let rendered = cell - .display_lines(120) + .display_lines(/*width*/ 120) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -7182,9 +7210,9 @@ mod tests { .with_user_config(&config_toml_path, user_config); app.config .features - .set_enabled(Feature::GuardianApproval, true)?; + .set_enabled(Feature::GuardianApproval, /*enabled*/ true)?; app.chat_widget - .set_feature_enabled(Feature::GuardianApproval, true); + .set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); app.config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent; app.chat_widget .set_approvals_reviewer(ApprovalsReviewer::GuardianSubagent); @@ -7242,7 +7270,7 @@ mod tests { other => panic!("expected InsertHistoryCell event, got {other:?}"), }; let rendered = cell - .display_lines(120) + .display_lines(/*width*/ 120) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -7341,9 +7369,9 @@ mod tests { .with_user_config(&config_toml_path, user_config); app.config .features - .set_enabled(Feature::GuardianApproval, true)?; + .set_enabled(Feature::GuardianApproval, /*enabled*/ true)?; app.chat_widget - .set_feature_enabled(Feature::GuardianApproval, true); + .set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); app.config.approvals_reviewer = ApprovalsReviewer::User; app.chat_widget .set_approvals_reviewer(ApprovalsReviewer::User); @@ -7481,9 +7509,9 @@ guardian_approval = true .with_user_config(&config_toml_path, user_config); app.config .features - .set_enabled(Feature::GuardianApproval, true)?; + .set_enabled(Feature::GuardianApproval, /*enabled*/ true)?; app.chat_widget - .set_feature_enabled(Feature::GuardianApproval, true); + .set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); app.config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent; app.chat_widget .set_approvals_reviewer(ApprovalsReviewer::GuardianSubagent); @@ -7524,7 +7552,7 @@ guardian_approval = true other => panic!("expected InsertHistoryCell event, got {other:?}"), }; let rendered = cell - .display_lines(120) + .display_lines(/*width*/ 120) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -7560,9 +7588,9 @@ guardian_approval = true .with_user_config(&config_toml_path, user_config); app.config .features - .set_enabled(Feature::GuardianApproval, true)?; + .set_enabled(Feature::GuardianApproval, /*enabled*/ true)?; app.chat_widget - .set_feature_enabled(Feature::GuardianApproval, true); + .set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); app.config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent; app.chat_widget .set_approvals_reviewer(ApprovalsReviewer::GuardianSubagent); @@ -7593,7 +7621,7 @@ guardian_approval = true assert!( !app_events.iter().any(|event| match event { AppEvent::InsertHistoryCell(cell) => cell - .display_lines(120) + .display_lines(/*width*/ 120) .iter() .any(|line| line.to_string().contains("Permissions updated to")), _ => false, @@ -7622,7 +7650,7 @@ guardian_approval = true .expect("embedded app server"); let thread_id = ThreadId::new(); app.thread_event_channels - .insert(thread_id, ThreadEventChannel::new(1)); + .insert(thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.open_agent_picker(&mut app_server).await; app.chat_widget @@ -7646,16 +7674,16 @@ guardian_approval = true app.primary_thread_id = Some(main_thread_id); app.active_thread_id = Some(main_thread_id); app.thread_event_channels - .insert(main_thread_id, ThreadEventChannel::new(1)); + .insert(main_thread_id, ThreadEventChannel::new(/*capacity*/ 1)); - let agent_channel = ThreadEventChannel::new(1); + let agent_channel = ThreadEventChannel::new(/*capacity*/ 1); { let mut store = agent_channel.store.lock().await; store.push_request(exec_approval_request( agent_thread_id, "turn-1", "call-1", - None, + /*approval_id*/ None, )); } app.thread_event_channels @@ -7664,7 +7692,7 @@ guardian_approval = true agent_thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); app.refresh_pending_thread_approvals().await; @@ -7689,11 +7717,11 @@ guardian_approval = true app.primary_thread_id = Some(main_thread_id); app.active_thread_id = Some(main_thread_id); app.thread_event_channels - .insert(main_thread_id, ThreadEventChannel::new(1)); + .insert(main_thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.thread_event_channels.insert( agent_thread_id, ThreadEventChannel::new_with_session( - 1, + /*capacity*/ 1, ThreadSessionState { approval_policy: AskForApproval::OnRequest, sandbox_policy: SandboxPolicy::new_workspace_write_policy(), @@ -7707,12 +7735,17 @@ guardian_approval = true agent_thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); app.enqueue_thread_request( agent_thread_id, - exec_approval_request(agent_thread_id, "turn-approval", "call-approval", None), + exec_approval_request( + agent_thread_id, + "turn-approval", + "call-approval", + /*approval_id*/ None, + ), ) .await?; @@ -7729,7 +7762,12 @@ guardian_approval = true async fn inactive_thread_exec_approval_preserves_context() { let app = make_test_app().await; let thread_id = ThreadId::new(); - let mut request = exec_approval_request(thread_id, "turn-approval", "call-approval", None); + let mut request = exec_approval_request( + thread_id, + "turn-approval", + "call-approval", + /*approval_id*/ None, + ); let ServerRequest::CommandExecutionRequestApproval { params, .. } = &mut request else { panic!("expected exec approval request"); }; @@ -7797,7 +7835,12 @@ guardian_approval = true let app = make_test_app().await; let thread_id = ThreadId::new(); let script = r#"python3 -c 'print("Hello, world!")'"#; - let mut request = exec_approval_request(thread_id, "turn-approval", "call-approval", None); + let mut request = exec_approval_request( + thread_id, + "turn-approval", + "call-approval", + /*approval_id*/ None, + ); let ServerRequest::CommandExecutionRequestApproval { params, .. } = &mut request else { panic!("expected exec approval request"); }; @@ -7834,11 +7877,11 @@ guardian_approval = true app.primary_thread_id = Some(main_thread_id); app.active_thread_id = Some(main_thread_id); app.thread_event_channels - .insert(main_thread_id, ThreadEventChannel::new(1)); + .insert(main_thread_id, ThreadEventChannel::new(/*capacity*/ 1)); app.thread_event_channels.insert( agent_thread_id, ThreadEventChannel::new_with_session( - 4, + /*capacity*/ 4, ThreadSessionState { approval_policy: AskForApproval::OnRequest, sandbox_policy: SandboxPolicy::new_workspace_write_policy(), @@ -7852,12 +7895,17 @@ guardian_approval = true agent_thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); app.enqueue_thread_request( agent_thread_id, - exec_approval_request(agent_thread_id, "turn-approval", "call-approval", None), + exec_approval_request( + agent_thread_id, + "turn-approval", + "call-approval", + /*approval_id*/ None, + ), ) .await?; assert_eq!( @@ -7898,7 +7946,11 @@ guardian_approval = true app.primary_session_configured = Some(primary_session.clone()); app.thread_event_channels.insert( main_thread_id, - ThreadEventChannel::new_with_session(4, primary_session.clone(), Vec::new()), + ThreadEventChannel::new_with_session( + /*capacity*/ 4, + primary_session.clone(), + Vec::new(), + ), ); let rollout_path = temp_dir.path().join("agent-rollout.jsonl"); @@ -8003,7 +8055,11 @@ guardian_approval = true app.primary_session_configured = Some(primary_session.clone()); app.thread_event_channels.insert( main_thread_id, - ThreadEventChannel::new_with_session(4, primary_session.clone(), Vec::new()), + ThreadEventChannel::new_with_session( + /*capacity*/ 4, + primary_session.clone(), + Vec::new(), + ), ); app.enqueue_thread_notification( @@ -8052,27 +8108,46 @@ guardian_approval = true let snapshot = [ format!( "{} | {}", - format_agent_picker_item_name(Some("Robie"), Some("explorer"), true), + format_agent_picker_item_name( + Some("Robie"), + Some("explorer"), + /*is_primary*/ true + ), thread_id ), format!( "{} | {}", - format_agent_picker_item_name(Some("Robie"), Some("explorer"), false), + format_agent_picker_item_name( + Some("Robie"), + Some("explorer"), + /*is_primary*/ false + ), thread_id ), format!( "{} | {}", - format_agent_picker_item_name(Some("Robie"), None, false), + format_agent_picker_item_name( + Some("Robie"), + /*agent_role*/ None, + /*is_primary*/ false + ), thread_id ), format!( "{} | {}", - format_agent_picker_item_name(None, Some("explorer"), false), + format_agent_picker_item_name( + /*agent_nickname*/ None, + Some("explorer"), + /*is_primary*/ false + ), thread_id ), format!( "{} | {}", - format_agent_picker_item_name(None, None, false), + format_agent_picker_item_name( + /*agent_nickname*/ None, /*agent_role*/ None, + /*is_primary*/ false + ), thread_id ), ] @@ -8202,7 +8277,7 @@ guardian_approval = true let agent_cell = |text: &str| -> Arc { Arc::new(AgentMessageCell::new( vec![Line::from(text.to_string())], - true, + /*is_first_line*/ true, )) as Arc }; let make_header = |is_first| -> Arc { @@ -8229,9 +8304,9 @@ guardian_approval = true app.chat_widget.current_model(), event, is_first, - None, - None, - false, + /*tooltip_override*/ None, + /*auth_plan*/ None, + /*show_fast_status*/ false, )) as Arc }; @@ -8239,7 +8314,7 @@ guardian_approval = true make_header(true), Arc::new(crate::history_cell::new_info_event( "startup tip that used to replay".to_string(), - None, + /*hint*/ None, )) as Arc, user_cell("Tell me a long story about a town with a dark lighthouse."), agent_cell(story_part_one), @@ -8251,7 +8326,7 @@ guardian_approval = true app.has_emitted_history_lines = true; let rendered = app - .clear_ui_header_lines_with_version(80, "") + .clear_ui_header_lines_with_version(/*width*/ 80, "") .iter() .map(|line| { line.spans @@ -8309,7 +8384,7 @@ guardian_approval = true set_chatgpt_auth(&mut app.chat_widget); let rendered = app - .clear_ui_header_lines_with_version(80, "") + .clear_ui_header_lines_with_version(/*width*/ 80, "") .iter() .map(|line| { line.spans @@ -8605,7 +8680,7 @@ guardian_approval = true #[test] fn thread_event_store_tracks_active_turn_lifecycle() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); assert_eq!(store.active_turn_id(), None); let thread_id = ThreadId::new(); @@ -8636,17 +8711,18 @@ guardian_approval = true test_turn("turn-2", TurnStatus::InProgress, Vec::new()), ]; - let store = ThreadEventStore::new_with_session(8, session.clone(), turns.clone()); + let store = + ThreadEventStore::new_with_session(/*capacity*/ 8, session.clone(), turns.clone()); assert_eq!(store.active_turn_id(), Some("turn-2")); - let mut refreshed_store = ThreadEventStore::new(8); + let mut refreshed_store = ThreadEventStore::new(/*capacity*/ 8); refreshed_store.set_session(session, turns); assert_eq!(refreshed_store.active_turn_id(), Some("turn-2")); } #[test] fn thread_event_store_clear_active_turn_id_resets_cached_turn() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); let thread_id = ThreadId::new(); store.push_notification(turn_started_notification(thread_id, "turn-1")); @@ -8658,12 +8734,12 @@ guardian_approval = true #[test] fn thread_event_store_rebase_preserves_resolved_request_state() { let thread_id = ThreadId::new(); - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(exec_approval_request( thread_id, "turn-approval", "call-approval", - None, + /*approval_id*/ None, )); store.push_notification(ServerNotification::ServerRequestResolved( codex_app_server_protocol::ServerRequestResolvedNotification { @@ -8682,7 +8758,7 @@ guardian_approval = true #[test] fn thread_event_store_rebase_preserves_hook_notifications() { let thread_id = ThreadId::new(); - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_notification(hook_started_notification(thread_id, "turn-hook")); store.push_notification(hook_completed_notification(thread_id, "turn-hook")); @@ -8740,11 +8816,11 @@ guardian_approval = true ThreadId::new(), model, model_info.slug.as_str(), - None, - None, - None, + /*account_id*/ None, + /*account_email*/ None, + /*auth_mode*/ None, "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), SessionSource::Cli, ) @@ -9301,7 +9377,7 @@ guardian_approval = true let agent_cell = |text: &str| -> Arc { Arc::new(AgentMessageCell::new( vec![Line::from(text.to_string())], - true, + /*is_first_line*/ true, )) as Arc }; @@ -9329,16 +9405,19 @@ guardian_approval = true app.chat_widget.current_model(), event, is_first, - None, - None, - false, + /*tooltip_override*/ None, + /*auth_plan*/ None, + /*show_fast_status*/ false, )) as Arc }; let placeholder = "[Image #1]"; let edited_text = format!("follow-up (edited) {placeholder}"); let edited_range = edited_text.len().saturating_sub(placeholder.len())..edited_text.len(); - let edited_text_elements = vec![TextElement::new(edited_range.into(), None)]; + let edited_text_elements = vec![TextElement::new( + edited_range.into(), + /*placeholder*/ None, + )]; let edited_local_image_paths = vec![PathBuf::from("/tmp/fake-image.png")]; // Simulate a transcript with duplicated history (e.g., from prior backtracks) @@ -9565,7 +9644,7 @@ guardian_approval = true events: Vec::new(), input_state: None, }, - false, + /*resume_restored_queue*/ false, ); while let Ok(event) = app_event_rx.try_recv() { @@ -9599,7 +9678,7 @@ guardian_approval = true receiver_thread_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); let replacement = ChatWidget::new_with_app_event(ChatWidgetInit { @@ -9646,13 +9725,13 @@ guardian_approval = true )], input_state: None, }, - false, + /*resume_restored_queue*/ false, ); let mut saw_named_wait = false; while let Ok(event) = app_event_rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { - let transcript = lines_to_single_string(&cell.transcript_lines(80)); + let transcript = lines_to_single_string(&cell.transcript_lines(/*width*/ 80)); saw_named_wait |= transcript.contains("Robie [explorer]"); } } @@ -9670,7 +9749,11 @@ guardian_approval = true let initial_session = test_thread_session(thread_id, PathBuf::from("/tmp/original")); app.thread_event_channels.insert( thread_id, - ThreadEventChannel::new_with_session(4, initial_session.clone(), Vec::new()), + ThreadEventChannel::new_with_session( + /*capacity*/ 4, + initial_session.clone(), + Vec::new(), + ), ); let resumed_turns = vec![test_turn( @@ -9732,7 +9815,7 @@ guardian_approval = true }) as Arc, Arc::new(AgentMessageCell::new( vec![Line::from("after first")], - false, + /*is_first_line*/ false, )) as Arc, Arc::new(UserHistoryCell { message: "second".to_string(), @@ -9742,7 +9825,7 @@ guardian_approval = true }) as Arc, Arc::new(AgentMessageCell::new( vec![Line::from("after second")], - false, + /*is_first_line*/ false, )) as Arc, ]; app.overlay = Some(Overlay::new_transcript(app.transcript_cells.clone())); @@ -9750,7 +9833,7 @@ guardian_approval = true app.backtrack.overlay_preview_active = true; app.backtrack.nth_user_message = 1; - let changed = app.apply_non_pending_thread_rollback(1); + let changed = app.apply_non_pending_thread_rollback(/*num_turns*/ 1); assert!(changed); assert!(app.backtrack_render_pending); @@ -9793,7 +9876,7 @@ guardian_approval = true app.handle_thread_rollback_response( thread_id, - 1, + /*num_turns*/ 1, &ThreadRollbackResponse { thread: Thread { id: thread_id.to_string(), @@ -9971,7 +10054,14 @@ guardian_approval = true #[tokio::test] async fn session_summary_skip_zero_usage() { - assert!(session_summary(TokenUsage::default(), None, None).is_none()); + assert!( + session_summary( + TokenUsage::default(), + /*thread_id*/ None, + /*thread_name*/ None + ) + .is_none() + ); } #[tokio::test] @@ -9984,7 +10074,8 @@ guardian_approval = true }; let conversation = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap(); - let summary = session_summary(usage, Some(conversation), None).expect("summary"); + let summary = + session_summary(usage, Some(conversation), /*thread_name*/ None).expect("summary"); assert_eq!( summary.usage_line, "Token usage: total=12 input=10 output=2" diff --git a/codex-rs/tui_app_server/src/app/agent_navigation.rs b/codex-rs/tui_app_server/src/app/agent_navigation.rs index 28428a742..c97c93f38 100644 --- a/codex-rs/tui_app_server/src/app/agent_navigation.rs +++ b/codex-rs/tui_app_server/src/app/agent_navigation.rs @@ -253,18 +253,23 @@ mod tests { let second_agent_id = ThreadId::from_string("00000000-0000-0000-0000-000000000103").expect("valid thread"); - state.upsert(main_thread_id, None, None, false); + state.upsert( + main_thread_id, + /*agent_nickname*/ None, + /*agent_role*/ None, + /*is_closed*/ false, + ); state.upsert( first_agent_id, Some("Robie".to_string()), Some("explorer".to_string()), - false, + /*is_closed*/ false, ); state.upsert( second_agent_id, Some("Bob".to_string()), Some("worker".to_string()), - false, + /*is_closed*/ false, ); (state, main_thread_id, first_agent_id, second_agent_id) @@ -278,7 +283,7 @@ mod tests { first_agent_id, Some("Robie".to_string()), Some("worker".to_string()), - true, + /*is_closed*/ true, ); assert_eq!( diff --git a/codex-rs/tui_app_server/src/app/pending_interactive_replay.rs b/codex-rs/tui_app_server/src/app/pending_interactive_replay.rs index 0110c8795..63c8fe124 100644 --- a/codex-rs/tui_app_server/src/app/pending_interactive_replay.rs +++ b/codex-rs/tui_app_server/src/app/pending_interactive_replay.rs @@ -695,7 +695,7 @@ mod tests { #[test] fn thread_event_snapshot_keeps_pending_request_user_input() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); let request = request_user_input_request("call-1", "turn-1"); store.push_request(request); @@ -711,7 +711,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_request_user_input_after_user_answer() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(request_user_input_request("call-1", "turn-1")); store.note_outbound_op(&Op::UserInputAnswer { @@ -730,7 +730,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_request_user_input_after_server_resolution() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(request_user_input_request("call-1", "turn-1")); store.push_notification(request_resolved(AppServerRequestId::Integer(1))); @@ -749,7 +749,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_exec_approval_after_outbound_approval_id() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(exec_approval_request( "call-1", Some("approval-1"), @@ -771,7 +771,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_exec_approval_after_server_resolution() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(exec_approval_request( "call-1", Some("approval-1"), @@ -796,7 +796,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_answered_request_user_input_for_multi_prompt_turn() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(request_user_input_request("call-1", "turn-1")); store.note_outbound_op(&Op::UserInputAnswer { @@ -819,7 +819,7 @@ mod tests { #[test] fn thread_event_snapshot_keeps_newer_request_user_input_pending_when_same_turn_has_queue() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(request_user_input_request("call-1", "turn-1")); store.push_request(request_user_input_request("call-2", "turn-1")); @@ -841,7 +841,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_patch_approval_after_outbound_approval() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(patch_approval_request("call-1", "turn-1")); store.note_outbound_op(&Op::PatchApproval { @@ -858,7 +858,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_pending_approvals_when_turn_completes() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(exec_approval_request( "exec-call-1", Some("approval-1"), @@ -879,7 +879,7 @@ mod tests { #[test] fn thread_event_snapshot_drops_resolved_elicitation_after_outbound_resolution() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); let request_id = codex_protocol::mcp::RequestId::String("request-1".to_string()); store.push_request(elicitation_request("server-1", "request-1", "turn-1")); @@ -900,10 +900,12 @@ mod tests { #[test] fn thread_event_store_reports_pending_thread_approvals() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); assert_eq!(store.has_pending_thread_approvals(), false); - store.push_request(exec_approval_request("call-1", None, "turn-1")); + store.push_request(exec_approval_request( + "call-1", /*approval_id*/ None, "turn-1", + )); assert_eq!(store.has_pending_thread_approvals(), true); @@ -918,7 +920,7 @@ mod tests { #[test] fn request_user_input_does_not_count_as_pending_thread_approval() { - let mut store = ThreadEventStore::new(8); + let mut store = ThreadEventStore::new(/*capacity*/ 8); store.push_request(request_user_input_request("call-1", "turn-1")); assert_eq!(store.has_pending_thread_approvals(), false); @@ -926,8 +928,10 @@ mod tests { #[test] fn thread_event_snapshot_drops_pending_requests_when_thread_closes() { - let mut store = ThreadEventStore::new(8); - store.push_request(exec_approval_request("call-1", None, "turn-1")); + let mut store = ThreadEventStore::new(/*capacity*/ 8); + store.push_request(exec_approval_request( + "call-1", /*approval_id*/ None, "turn-1", + )); store.push_notification(thread_closed()); assert!(store.snapshot().events.iter().all(|event| { diff --git a/codex-rs/tui_app_server/src/app_backtrack.rs b/codex-rs/tui_app_server/src/app_backtrack.rs index 7bcb67e45..db1149e76 100644 --- a/codex-rs/tui_app_server/src/app_backtrack.rs +++ b/codex-rs/tui_app_server/src/app_backtrack.rs @@ -652,10 +652,12 @@ mod tests { local_image_paths: Vec::new(), remote_image_urls: Vec::new(), }) as Arc, - Arc::new(AgentMessageCell::new(vec![Line::from("assistant")], true)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("assistant")], + /*is_first_line*/ true, + )) as Arc, ]; - trim_transcript_cells_to_nth_user(&mut cells, 0); + trim_transcript_cells_to_nth_user(&mut cells, /*nth_user_message*/ 0); assert!(cells.is_empty()); } @@ -663,18 +665,22 @@ mod tests { #[test] fn trim_transcript_preserves_cells_before_selected_user() { let mut cells: Vec> = vec![ - Arc::new(AgentMessageCell::new(vec![Line::from("intro")], true)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("intro")], + /*is_first_line*/ true, + )) as Arc, Arc::new(UserHistoryCell { message: "first".to_string(), text_elements: Vec::new(), local_image_paths: Vec::new(), remote_image_urls: Vec::new(), }) as Arc, - Arc::new(AgentMessageCell::new(vec![Line::from("after")], false)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("after")], + /*is_first_line*/ false, + )) as Arc, ]; - trim_transcript_cells_to_nth_user(&mut cells, 0); + trim_transcript_cells_to_nth_user(&mut cells, /*nth_user_message*/ 0); assert_eq!(cells.len(), 1); let agent = cells[0] @@ -694,26 +700,32 @@ mod tests { #[test] fn trim_transcript_for_later_user_keeps_prior_history() { let mut cells: Vec> = vec![ - Arc::new(AgentMessageCell::new(vec![Line::from("intro")], true)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("intro")], + /*is_first_line*/ true, + )) as Arc, Arc::new(UserHistoryCell { message: "first".to_string(), text_elements: Vec::new(), local_image_paths: Vec::new(), remote_image_urls: Vec::new(), }) as Arc, - Arc::new(AgentMessageCell::new(vec![Line::from("between")], false)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("between")], + /*is_first_line*/ false, + )) as Arc, Arc::new(UserHistoryCell { message: "second".to_string(), text_elements: Vec::new(), local_image_paths: Vec::new(), remote_image_urls: Vec::new(), }) as Arc, - Arc::new(AgentMessageCell::new(vec![Line::from("tail")], false)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("tail")], + /*is_first_line*/ false, + )) as Arc, ]; - trim_transcript_cells_to_nth_user(&mut cells, 1); + trim_transcript_cells_to_nth_user(&mut cells, /*nth_user_message*/ 1); assert_eq!(cells.len(), 3); let agent_intro = cells[0] @@ -758,7 +770,7 @@ mod tests { }) as Arc, Arc::new(AgentMessageCell::new( vec![Line::from("after first")], - false, + /*is_first_line*/ false, )) as Arc, Arc::new(UserHistoryCell { message: "second".to_string(), @@ -768,11 +780,12 @@ mod tests { }) as Arc, Arc::new(AgentMessageCell::new( vec![Line::from("after second")], - false, + /*is_first_line*/ false, )) as Arc, ]; - let changed = trim_transcript_cells_drop_last_n_user_turns(&mut cells, 1); + let changed = + trim_transcript_cells_drop_last_n_user_turns(&mut cells, /*num_turns*/ 1); assert!(changed); assert_eq!(cells.len(), 2); @@ -786,16 +799,20 @@ mod tests { #[test] fn trim_drop_last_n_user_turns_allows_overflow() { let mut cells: Vec> = vec![ - Arc::new(AgentMessageCell::new(vec![Line::from("intro")], true)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("intro")], + /*is_first_line*/ true, + )) as Arc, Arc::new(UserHistoryCell { message: "first".to_string(), text_elements: Vec::new(), local_image_paths: Vec::new(), remote_image_urls: Vec::new(), }) as Arc, - Arc::new(AgentMessageCell::new(vec![Line::from("after")], false)) - as Arc, + Arc::new(AgentMessageCell::new( + vec![Line::from("after")], + /*is_first_line*/ false, + )) as Arc, ]; let changed = trim_transcript_cells_drop_last_n_user_turns(&mut cells, u32::MAX); diff --git a/codex-rs/tui_app_server/src/app_server_session.rs b/codex-rs/tui_app_server/src/app_server_session.rs index 49ec7a2b3..eb6c17607 100644 --- a/codex-rs/tui_app_server/src/app_server_session.rs +++ b/codex-rs/tui_app_server/src/app_server_session.rs @@ -1235,15 +1235,15 @@ mod tests { let session = thread_session_state_from_thread_response( &thread_id.to_string(), Some("restore".to_string()), - None, + /*rollout_path*/ None, "gpt-5.4".to_string(), "openai".to_string(), - None, + /*service_tier*/ None, AskForApproval::Never, codex_protocol::config_types::ApprovalsReviewer::User, SandboxPolicy::new_read_only_policy(), PathBuf::from("/tmp/project"), - None, + /*reasoning_effort*/ None, &config, ) .await diff --git a/codex-rs/tui_app_server/src/bottom_pane/app_link_view.rs b/codex-rs/tui_app_server/src/bottom_pane/app_link_view.rs index ba5ea6cb7..e39d54762 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/app_link_view.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/app_link_view.rs @@ -669,7 +669,7 @@ mod tests { view.screen = AppLinkScreen::InstallConfirmation; let rendered: Vec = view - .content_lines(40) + .content_lines(/*width*/ 40) .into_iter() .map(|line| { line.spans @@ -911,7 +911,10 @@ mod tests { assert_snapshot!( "app_link_view_install_suggestion_with_reason", - render_snapshot(&view, Rect::new(0, 0, 72, view.desired_height(72))) + render_snapshot( + &view, + Rect::new(0, 0, 72, view.desired_height(/*width*/ 72)) + ) ); } @@ -937,7 +940,10 @@ mod tests { assert_snapshot!( "app_link_view_enable_suggestion_with_reason", - render_snapshot(&view, Rect::new(0, 0, 72, view.desired_height(72))) + render_snapshot( + &view, + Rect::new(0, 0, 72, view.desired_height(/*width*/ 72)) + ) ); } } diff --git a/codex-rs/tui_app_server/src/bottom_pane/approval_overlay.rs b/codex-rs/tui_app_server/src/bottom_pane/approval_overlay.rs index 84f6da6cb..82e74888f 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/approval_overlay.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/approval_overlay.rs @@ -997,7 +997,7 @@ mod tests { assert_snapshot!( "approval_overlay_cross_thread_prompt", - render_overlay_lines(&view, 80) + render_overlay_lines(&view, /*width*/ 80) ); } @@ -1109,8 +1109,11 @@ mod tests { }; let view = ApprovalOverlay::new(exec_request, tx, Features::with_defaults()); - let mut buf = Buffer::empty(Rect::new(0, 0, 80, view.desired_height(80))); - view.render(Rect::new(0, 0, 80, view.desired_height(80)), &mut buf); + let mut buf = Buffer::empty(Rect::new(0, 0, 80, view.desired_height(/*width*/ 80))); + view.render( + Rect::new(0, 0, 80, view.desired_height(/*width*/ 80)), + &mut buf, + ); let rendered: Vec = (0..buf.area.height) .map(|row| { @@ -1146,7 +1149,7 @@ mod tests { ReviewDecision::Abort, ], Some(&network_context), - None, + /*additional_permissions*/ None, ); let labels: Vec = options.into_iter().map(|option| option.label).collect(); @@ -1169,8 +1172,8 @@ mod tests { ReviewDecision::ApprovedForSession, ReviewDecision::Abort, ], - None, - None, + /*network_approval_context*/ None, + /*additional_permissions*/ None, ); let labels: Vec = options.into_iter().map(|option| option.label).collect(); @@ -1195,7 +1198,7 @@ mod tests { }; let options = exec_options( &[ReviewDecision::Approved, ReviewDecision::Abort], - None, + /*network_approval_context*/ None, Some(&additional_permissions), ); @@ -1276,8 +1279,11 @@ mod tests { }; let view = ApprovalOverlay::new(exec_request, tx, Features::with_defaults()); - let mut buf = Buffer::empty(Rect::new(0, 0, 120, view.desired_height(120))); - view.render(Rect::new(0, 0, 120, view.desired_height(120)), &mut buf); + let mut buf = Buffer::empty(Rect::new(0, 0, 120, view.desired_height(/*width*/ 120))); + view.render( + Rect::new(0, 0, 120, view.desired_height(/*width*/ 120)), + &mut buf, + ); let rendered: Vec = (0..buf.area.height) .map(|row| { @@ -1325,7 +1331,7 @@ mod tests { let view = ApprovalOverlay::new(exec_request, tx, Features::with_defaults()); assert_snapshot!( "approval_overlay_additional_permissions_prompt", - normalize_snapshot_paths(render_overlay_lines(&view, 120)) + normalize_snapshot_paths(render_overlay_lines(&view, /*width*/ 120)) ); } @@ -1336,7 +1342,7 @@ mod tests { let view = ApprovalOverlay::new(make_permissions_request(), tx, Features::with_defaults()); assert_snapshot!( "approval_overlay_permissions_prompt", - normalize_snapshot_paths(render_overlay_lines(&view, 120)) + normalize_snapshot_paths(render_overlay_lines(&view, /*width*/ 120)) ); } @@ -1369,8 +1375,11 @@ mod tests { }; let view = ApprovalOverlay::new(exec_request, tx, Features::with_defaults()); - let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(100))); - view.render(Rect::new(0, 0, 100, view.desired_height(100)), &mut buf); + let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(/*width*/ 100))); + view.render( + Rect::new(0, 0, 100, view.desired_height(/*width*/ 100)), + &mut buf, + ); assert_snapshot!("network_exec_prompt", format!("{buf:?}")); let rendered: Vec = (0..buf.area.height) @@ -1409,7 +1418,7 @@ mod tests { ReviewDecision::Approved, history_cell::ApprovalDecisionActor::User, ); - let lines = cell.display_lines(28); + let lines = cell.display_lines(/*width*/ 28); let rendered: Vec = lines .iter() .map(|line| { diff --git a/codex-rs/tui_app_server/src/bottom_pane/chat_composer.rs b/codex-rs/tui_app_server/src/bottom_pane/chat_composer.rs index 7a8fa254f..3f77abc16 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/chat_composer.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/chat_composer.rs @@ -4548,11 +4548,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 40, 6); @@ -4602,11 +4602,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_footer_hint_override(Some(vec![("K".to_string(), "label".to_string())])); composer.show_footer_flash(Line::from("FLASH"), Duration::from_secs(10)); @@ -4640,11 +4640,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_footer_hint_override(Some(vec![("K".to_string(), "label".to_string())])); composer.show_footer_flash(Line::from("FLASH"), Duration::from_secs(10)); @@ -4689,11 +4689,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, enhanced_keys_supported, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); setup(&mut composer); let footer_props = composer.footer_props(); @@ -4711,7 +4711,12 @@ mod tests { where F: FnOnce(&mut ChatComposer), { - snapshot_composer_state_with_width(name, 100, enhanced_keys_supported, setup); + snapshot_composer_state_with_width( + name, + /*width*/ 100, + enhanced_keys_supported, + setup, + ); } #[test] @@ -4720,50 +4725,87 @@ mod tests { use crossterm::event::KeyEvent; use crossterm::event::KeyModifiers; - snapshot_composer_state("footer_mode_shortcut_overlay", true, |composer| { - composer.set_esc_backtrack_hint(true); - let _ = - composer.handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); - }); - - snapshot_composer_state("footer_mode_ctrl_c_quit", true, |composer| { - composer.show_quit_shortcut_hint(key_hint::ctrl(KeyCode::Char('c')), true); - }); - - snapshot_composer_state("footer_mode_ctrl_c_interrupt", true, |composer| { - composer.set_task_running(true); - composer.show_quit_shortcut_hint(key_hint::ctrl(KeyCode::Char('c')), true); - }); - - snapshot_composer_state("footer_mode_ctrl_c_then_esc_hint", true, |composer| { - composer.show_quit_shortcut_hint(key_hint::ctrl(KeyCode::Char('c')), true); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - }); - - snapshot_composer_state("footer_mode_esc_hint_from_overlay", true, |composer| { - let _ = - composer.handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - }); - - snapshot_composer_state("footer_mode_esc_hint_backtrack", true, |composer| { - composer.set_esc_backtrack_hint(true); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - }); - snapshot_composer_state( - "footer_mode_overlay_then_external_esc_hint", - true, + "footer_mode_shortcut_overlay", + /*enhanced_keys_supported*/ true, |composer| { + composer.set_esc_backtrack_hint(/*show*/ true); let _ = composer .handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); - composer.set_esc_backtrack_hint(true); }, ); - snapshot_composer_state("footer_mode_hidden_while_typing", true, |composer| { - type_chars_humanlike(composer, &['h']); - }); + snapshot_composer_state( + "footer_mode_ctrl_c_quit", + /*enhanced_keys_supported*/ true, + |composer| { + composer.show_quit_shortcut_hint( + key_hint::ctrl(KeyCode::Char('c')), + /*has_focus*/ true, + ); + }, + ); + + snapshot_composer_state( + "footer_mode_ctrl_c_interrupt", + /*enhanced_keys_supported*/ true, + |composer| { + composer.set_task_running(/*running*/ true); + composer.show_quit_shortcut_hint( + key_hint::ctrl(KeyCode::Char('c')), + /*has_focus*/ true, + ); + }, + ); + + snapshot_composer_state( + "footer_mode_ctrl_c_then_esc_hint", + /*enhanced_keys_supported*/ true, + |composer| { + composer.show_quit_shortcut_hint( + key_hint::ctrl(KeyCode::Char('c')), + /*has_focus*/ true, + ); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); + }, + ); + + snapshot_composer_state( + "footer_mode_esc_hint_from_overlay", + /*enhanced_keys_supported*/ true, + |composer| { + let _ = composer + .handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); + }, + ); + + snapshot_composer_state( + "footer_mode_esc_hint_backtrack", + /*enhanced_keys_supported*/ true, + |composer| { + composer.set_esc_backtrack_hint(/*show*/ true); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); + }, + ); + + snapshot_composer_state( + "footer_mode_overlay_then_external_esc_hint", + /*enhanced_keys_supported*/ true, + |composer| { + let _ = composer + .handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); + composer.set_esc_backtrack_hint(/*show*/ true); + }, + ); + + snapshot_composer_state( + "footer_mode_hidden_while_typing", + /*enhanced_keys_supported*/ true, + |composer| { + type_chars_humanlike(composer, &['h']); + }, + ); } #[test] @@ -4773,117 +4815,161 @@ mod tests { context_percent: i64, indicator: Option, ) { - composer.set_collaboration_modes_enabled(true); + composer.set_collaboration_modes_enabled(/*enabled*/ true); composer.set_collaboration_mode_indicator(indicator); - composer.set_context_window(Some(context_percent), None); + composer.set_context_window(Some(context_percent), /*used_tokens*/ None); } // Empty textarea, agent idle: shortcuts hint can show, and cycle hint is hidden. - snapshot_composer_state_with_width("footer_collapse_empty_full", 120, true, |composer| { - setup_collab_footer(composer, 100, None); - }); + snapshot_composer_state_with_width( + "footer_collapse_empty_full", + /*width*/ 120, + /*enhanced_keys_supported*/ true, + |composer| { + setup_collab_footer( + composer, /*context_percent*/ 100, /*indicator*/ None, + ); + }, + ); snapshot_composer_state_with_width( "footer_collapse_empty_mode_cycle_with_context", - 60, - true, + /*width*/ 60, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, None); + setup_collab_footer( + composer, /*context_percent*/ 100, /*indicator*/ None, + ); }, ); snapshot_composer_state_with_width( "footer_collapse_empty_mode_cycle_without_context", - 44, - true, + /*width*/ 44, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, None); + setup_collab_footer( + composer, /*context_percent*/ 100, /*indicator*/ None, + ); }, ); snapshot_composer_state_with_width( "footer_collapse_empty_mode_only", - 26, - true, + /*width*/ 26, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, None); + setup_collab_footer( + composer, /*context_percent*/ 100, /*indicator*/ None, + ); }, ); // Empty textarea, plan mode idle: shortcuts hint and cycle hint are available. snapshot_composer_state_with_width( "footer_collapse_plan_empty_full", - 120, - true, + /*width*/ 120, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan)); + setup_collab_footer( + composer, + /*context_percent*/ 100, + Some(CollaborationModeIndicator::Plan), + ); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_empty_mode_cycle_with_context", - 60, - true, + /*width*/ 60, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan)); + setup_collab_footer( + composer, + /*context_percent*/ 100, + Some(CollaborationModeIndicator::Plan), + ); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_empty_mode_cycle_without_context", - 44, - true, + /*width*/ 44, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan)); + setup_collab_footer( + composer, + /*context_percent*/ 100, + Some(CollaborationModeIndicator::Plan), + ); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_empty_mode_only", - 26, - true, + /*width*/ 26, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan)); + setup_collab_footer( + composer, + /*context_percent*/ 100, + Some(CollaborationModeIndicator::Plan), + ); }, ); // Textarea has content, agent running: queue hint is shown. - snapshot_composer_state_with_width("footer_collapse_queue_full", 120, true, |composer| { - setup_collab_footer(composer, 98, None); - composer.set_task_running(true); - composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); - }); + snapshot_composer_state_with_width( + "footer_collapse_queue_full", + /*width*/ 120, + /*enhanced_keys_supported*/ true, + |composer| { + setup_collab_footer( + composer, /*context_percent*/ 98, /*indicator*/ None, + ); + composer.set_task_running(/*running*/ true); + composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); + }, + ); snapshot_composer_state_with_width( "footer_collapse_queue_short_with_context", - 50, - true, + /*width*/ 50, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, None); - composer.set_task_running(true); + setup_collab_footer( + composer, /*context_percent*/ 98, /*indicator*/ None, + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_queue_message_without_context", - 40, - true, + /*width*/ 40, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, None); - composer.set_task_running(true); + setup_collab_footer( + composer, /*context_percent*/ 98, /*indicator*/ None, + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_queue_short_without_context", - 30, - true, + /*width*/ 30, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, None); - composer.set_task_running(true); + setup_collab_footer( + composer, /*context_percent*/ 98, /*indicator*/ None, + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_queue_mode_only", - 20, - true, + /*width*/ 20, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, None); - composer.set_task_running(true); + setup_collab_footer( + composer, /*context_percent*/ 98, /*indicator*/ None, + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); @@ -4891,51 +4977,71 @@ mod tests { // Textarea has content, plan mode active, agent running: queue hint + mode. snapshot_composer_state_with_width( "footer_collapse_plan_queue_full", - 120, - true, + /*width*/ 120, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan)); - composer.set_task_running(true); + setup_collab_footer( + composer, + /*context_percent*/ 98, + Some(CollaborationModeIndicator::Plan), + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_queue_short_with_context", - 50, - true, + /*width*/ 50, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan)); - composer.set_task_running(true); + setup_collab_footer( + composer, + /*context_percent*/ 98, + Some(CollaborationModeIndicator::Plan), + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_queue_message_without_context", - 40, - true, + /*width*/ 40, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan)); - composer.set_task_running(true); + setup_collab_footer( + composer, + /*context_percent*/ 98, + Some(CollaborationModeIndicator::Plan), + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_queue_short_without_context", - 30, - true, + /*width*/ 30, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan)); - composer.set_task_running(true); + setup_collab_footer( + composer, + /*context_percent*/ 98, + Some(CollaborationModeIndicator::Plan), + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); snapshot_composer_state_with_width( "footer_collapse_plan_queue_mode_only", - 20, - true, + /*width*/ 20, + /*enhanced_keys_supported*/ true, |composer| { - setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan)); - composer.set_task_running(true); + setup_collab_footer( + composer, + /*context_percent*/ 98, + Some(CollaborationModeIndicator::Plan), + ); + composer.set_task_running(/*running*/ true); composer.set_text_content("Test".to_string(), Vec::new(), Vec::new()); }, ); @@ -4950,11 +5056,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - true, + /*enhanced_keys_supported*/ true, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['d']); @@ -4977,15 +5083,16 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['d']); - composer.show_quit_shortcut_hint(key_hint::ctrl(KeyCode::Char('c')), true); + composer + .show_quit_shortcut_hint(key_hint::ctrl(KeyCode::Char('c')), /*has_focus*/ true); composer.quit_shortcut_expires_at = Some(Instant::now() - std::time::Duration::from_secs(1)); @@ -5000,11 +5107,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_text_content("draft text".to_string(), Vec::new(), Vec::new()); @@ -5026,11 +5133,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let large = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5); @@ -5088,16 +5195,16 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path = PathBuf::from("example.png"); composer.attach_image(path.clone()); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); composer.clear_for_ctrl_c(); assert!(composer.is_empty()); @@ -5131,11 +5238,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let remote_image_url = "https://example.com/one.png".to_string(); composer.set_remote_image_urls(vec![remote_image_url.clone()]); @@ -5173,11 +5280,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let remote_image_url = "https://example.com/one.png".to_string(); @@ -5216,11 +5323,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let (result, needs_redraw) = @@ -5258,11 +5365,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Force an active paste burst so this test doesn't depend on tight timing. @@ -5287,13 +5394,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_connectors_enabled(true); + composer.set_connectors_enabled(/*enabled*/ true); composer.set_text_content("$".to_string(), Vec::new(), Vec::new()); assert!(matches!(composer.active_popup, ActivePopup::None)); @@ -5329,13 +5436,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_connectors_enabled(true); + composer.set_connectors_enabled(/*enabled*/ true); composer.set_text_content("$".to_string(), Vec::new(), Vec::new()); assert!(matches!(composer.active_popup, ActivePopup::None)); @@ -5367,11 +5474,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_text_content("$".to_string(), Vec::new(), Vec::new()); assert!(matches!(composer.active_popup, ActivePopup::None)); @@ -5400,13 +5507,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_connectors_enabled(true); + composer.set_connectors_enabled(/*enabled*/ true); composer.set_text_content("$goog".to_string(), Vec::new(), Vec::new()); composer.set_skill_mentions(Some(vec![SkillMetadata { name: "google-calendar:availability".to_string(), @@ -5475,47 +5582,55 @@ mod tests { #[test] fn plugin_mention_popup_snapshot() { - snapshot_composer_state("plugin_mention_popup", false, |composer| { - composer.set_text_content("$sa".to_string(), Vec::new(), Vec::new()); - composer.set_plugin_mentions(Some(vec![PluginCapabilitySummary { - config_name: "sample@test".to_string(), - display_name: "Sample Plugin".to_string(), - description: Some( - "Plugin that includes the Figma MCP server and Skills for common workflows" - .to_string(), - ), - has_skills: true, - mcp_server_names: vec!["sample".to_string()], - app_connector_ids: vec![codex_core::plugins::AppConnectorId( - "calendar".to_string(), - )], - }])); - }); + snapshot_composer_state( + "plugin_mention_popup", + /*enhanced_keys_supported*/ false, + |composer| { + composer.set_text_content("$sa".to_string(), Vec::new(), Vec::new()); + composer.set_plugin_mentions(Some(vec![PluginCapabilitySummary { + config_name: "sample@test".to_string(), + display_name: "Sample Plugin".to_string(), + description: Some( + "Plugin that includes the Figma MCP server and Skills for common workflows" + .to_string(), + ), + has_skills: true, + mcp_server_names: vec!["sample".to_string()], + app_connector_ids: vec![codex_core::plugins::AppConnectorId( + "calendar".to_string(), + )], + }])); + }, + ); } #[test] fn mention_popup_type_prefixes_snapshot() { - snapshot_composer_state_with_width("mention_popup_type_prefixes", 72, false, |composer| { - composer.set_connectors_enabled(true); - composer.set_text_content("$goog".to_string(), Vec::new(), Vec::new()); - composer.set_skill_mentions(Some(vec![SkillMetadata { - name: "google-calendar-skill".to_string(), - description: "Find availability and plan event changes".to_string(), - short_description: None, - interface: Some(codex_core::skills::model::SkillInterface { - display_name: Some("Google Calendar".to_string()), + snapshot_composer_state_with_width( + "mention_popup_type_prefixes", + /*width*/ 72, + /*enhanced_keys_supported*/ false, + |composer| { + composer.set_connectors_enabled(/*enabled*/ true); + composer.set_text_content("$goog".to_string(), Vec::new(), Vec::new()); + composer.set_skill_mentions(Some(vec![SkillMetadata { + name: "google-calendar-skill".to_string(), + description: "Find availability and plan event changes".to_string(), short_description: None, - icon_small: None, - icon_large: None, - brand_color: None, - default_prompt: None, - }), - dependencies: None, - policy: None, - path_to_skills_md: PathBuf::from("/tmp/repo/google-calendar/SKILL.md"), - scope: codex_protocol::protocol::SkillScope::Repo, - }])); - composer.set_plugin_mentions(Some(vec![PluginCapabilitySummary { + interface: Some(codex_core::skills::model::SkillInterface { + display_name: Some("Google Calendar".to_string()), + short_description: None, + icon_small: None, + icon_large: None, + brand_color: None, + default_prompt: None, + }), + dependencies: None, + policy: None, + path_to_skills_md: PathBuf::from("/tmp/repo/google-calendar/SKILL.md"), + scope: codex_protocol::protocol::SkillScope::Repo, + }])); + composer.set_plugin_mentions(Some(vec![PluginCapabilitySummary { config_name: "google-calendar@debug".to_string(), display_name: "Google Calendar".to_string(), description: Some( @@ -5526,24 +5641,25 @@ mod tests { mcp_server_names: vec!["google-calendar".to_string()], app_connector_ids: Vec::new(), }])); - composer.set_connector_mentions(Some(ConnectorsSnapshot { - connectors: vec![AppInfo { - id: "google_calendar".to_string(), - name: "Google Calendar".to_string(), - description: Some("Look up events and availability".to_string()), - logo_url: None, - logo_url_dark: None, - distribution_channel: None, - branding: None, - app_metadata: None, - labels: None, - install_url: Some("https://example.test/google-calendar".to_string()), - is_accessible: true, - is_enabled: true, - plugin_display_names: Vec::new(), - }], - })); - }); + composer.set_connector_mentions(Some(ConnectorsSnapshot { + connectors: vec![AppInfo { + id: "google_calendar".to_string(), + name: "Google Calendar".to_string(), + description: Some("Look up events and availability".to_string()), + logo_url: None, + logo_url_dark: None, + distribution_channel: None, + branding: None, + app_metadata: None, + labels: None, + install_url: Some("https://example.test/google-calendar".to_string()), + is_accessible: true, + is_enabled: true, + plugin_display_names: Vec::new(), + }], + })); + }, + ); } #[test] @@ -5551,13 +5667,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_connectors_enabled(true); + composer.set_connectors_enabled(/*enabled*/ true); composer.set_text_content("$".to_string(), Vec::new(), Vec::new()); let connectors = vec![AppInfo { @@ -5589,17 +5705,17 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE)); assert_eq!(composer.footer_mode, FooterMode::ShortcutOverlay); - composer.set_task_running(true); + composer.set_task_running(/*running*/ true); assert_eq!(composer.footer_mode, FooterMode::ShortcutOverlay); assert_eq!(composer.footer_mode(), FooterMode::ShortcutOverlay); @@ -5839,11 +5955,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let input = "npx -y @kaeawc/auto-mobile@latest"; @@ -5874,11 +5990,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Char('1'), KeyModifiers::NONE)); @@ -5905,11 +6021,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Char('あ'), KeyModifiers::NONE)); @@ -5929,11 +6045,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer @@ -5962,11 +6078,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer @@ -6010,11 +6126,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Force an active burst so the test doesn't depend on timing heuristics. @@ -6047,11 +6163,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let mut now = Instant::now(); @@ -6068,7 +6184,7 @@ mod tests { ); now += step; - let (result, _) = composer.handle_submission_with_time(false, now); + let (result, _) = composer.handle_submission_with_time(/*should_queue*/ false, now); assert!( matches!(result, InputResult::None), "Enter during a burst should insert newline, not submit" @@ -6101,11 +6217,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.textarea.set_text_clearing_elements("/diff"); @@ -6130,11 +6246,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Force an active burst so we can deterministically buffer characters without relying on @@ -6165,11 +6281,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // First ASCII char is normally held briefly. Flip the config mid-stream and ensure the @@ -6178,7 +6294,7 @@ mod tests { assert!(composer.is_in_paste_burst()); assert!(composer.textarea.text().is_empty()); - composer.set_disable_paste_burst(true); + composer.set_disable_paste_burst(/*disabled*/ true); assert_eq!(composer.textarea.text(), "a"); assert!(!composer.is_in_paste_burst()); @@ -6198,11 +6314,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let needs_redraw = composer.handle_paste("hello".to_string()); @@ -6227,11 +6343,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Ensure composer is empty and press Enter. @@ -6256,11 +6372,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let large = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 10); @@ -6290,11 +6406,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_steer_enabled(true); let input = "x".repeat(MAX_USER_INPUT_TEXT_CHARS); @@ -6318,11 +6434,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_steer_enabled(true); let input = "x".repeat(MAX_USER_INPUT_TEXT_CHARS + 1); @@ -6338,7 +6454,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -6360,11 +6476,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_steer_enabled(false); let input = "x".repeat(MAX_USER_INPUT_TEXT_CHARS + 1); @@ -6380,7 +6496,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -6405,11 +6521,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.handle_paste(large); @@ -6446,11 +6562,11 @@ mod tests { for (name, input) in test_cases { // Create a fresh composer for each test case let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender.clone(), - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); if let Some(text) = input { @@ -6482,14 +6598,22 @@ mod tests { #[test] fn image_placeholder_snapshots() { - snapshot_composer_state("image_placeholder_single", false, |composer| { - composer.attach_image(PathBuf::from("/tmp/image1.png")); - }); + snapshot_composer_state( + "image_placeholder_single", + /*enhanced_keys_supported*/ false, + |composer| { + composer.attach_image(PathBuf::from("/tmp/image1.png")); + }, + ); - snapshot_composer_state("image_placeholder_multiple", false, |composer| { - composer.attach_image(PathBuf::from("/tmp/image1.png")); - composer.attach_image(PathBuf::from("/tmp/image2.png")); - }); + snapshot_composer_state( + "image_placeholder_multiple", + /*enhanced_keys_supported*/ false, + |composer| { + composer.attach_image(PathBuf::from("/tmp/image1.png")); + composer.attach_image(PathBuf::from("/tmp/image2.png")); + }, + ); } #[test] @@ -6498,35 +6622,48 @@ mod tests { use crossterm::event::KeyEvent; use crossterm::event::KeyModifiers; - snapshot_composer_state("remote_image_rows", false, |composer| { - composer.set_remote_image_urls(vec![ - "https://example.com/one.png".to_string(), - "https://example.com/two.png".to_string(), - ]); - composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); - }); + snapshot_composer_state( + "remote_image_rows", + /*enhanced_keys_supported*/ false, + |composer| { + composer.set_remote_image_urls(vec![ + "https://example.com/one.png".to_string(), + "https://example.com/two.png".to_string(), + ]); + composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); + }, + ); - snapshot_composer_state("remote_image_rows_selected", false, |composer| { - composer.set_remote_image_urls(vec![ - "https://example.com/one.png".to_string(), - "https://example.com/two.png".to_string(), - ]); - composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); - composer.textarea.set_cursor(0); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); - }); + snapshot_composer_state( + "remote_image_rows_selected", + /*enhanced_keys_supported*/ false, + |composer| { + composer.set_remote_image_urls(vec![ + "https://example.com/one.png".to_string(), + "https://example.com/two.png".to_string(), + ]); + composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); + composer.textarea.set_cursor(/*pos*/ 0); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); + }, + ); - snapshot_composer_state("remote_image_rows_after_delete_first", false, |composer| { - composer.set_remote_image_urls(vec![ - "https://example.com/one.png".to_string(), - "https://example.com/two.png".to_string(), - ]); - composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); - composer.textarea.set_cursor(0); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); - let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE)); - }); + snapshot_composer_state( + "remote_image_rows_after_delete_first", + /*enhanced_keys_supported*/ false, + |composer| { + composer.set_remote_image_urls(vec![ + "https://example.com/one.png".to_string(), + "https://example.com/two.png".to_string(), + ]); + composer.set_text_content("describe these".to_string(), Vec::new(), Vec::new()); + composer.textarea.set_cursor(/*pos*/ 0); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); + let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); + let _ = + composer.handle_key_event(KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE)); + }, + ); } #[test] @@ -6538,11 +6675,11 @@ mod tests { let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Type "/mo" humanlike so paste-burst doesn’t interfere. @@ -6566,11 +6703,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['/', 'm', 'o']); @@ -6597,11 +6734,11 @@ mod tests { let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Type "/res" humanlike so paste-burst doesn’t interfere. @@ -6622,11 +6759,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['/', 'r', 'e', 's']); @@ -6678,11 +6815,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Type the slash command. @@ -6721,15 +6858,15 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_steer_enabled(true); composer.textarea.insert_str("restore me"); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); let (_result, _needs_redraw) = composer.handle_key_event(KeyEvent::new(KeyCode::Char('k'), KeyModifiers::CONTROL)); @@ -6755,14 +6892,14 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.textarea.insert_str("restore me"); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); let (_result, _needs_redraw) = composer.handle_key_event(KeyEvent::new(KeyCode::Char('k'), KeyModifiers::CONTROL)); @@ -6793,13 +6930,13 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_task_running(true); + composer.set_task_running(/*running*/ true); composer .textarea .set_text_clearing_elements("/review these changes"); @@ -6814,7 +6951,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -6837,11 +6974,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - true, + /*disable_paste_burst*/ true, ); composer.set_text_content("x".to_string(), Vec::new(), Vec::new()); composer.move_cursor_to_end(); @@ -6866,13 +7003,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_voice_transcription_enabled(true); + composer.set_voice_transcription_enabled(/*enabled*/ true); composer.set_text_content("x".to_string(), Vec::new(), Vec::new()); composer.move_cursor_to_end(); @@ -6898,13 +7035,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_voice_transcription_enabled(true); + composer.set_voice_transcription_enabled(/*enabled*/ true); composer.set_text_content("x".to_string(), Vec::new(), Vec::new()); composer.move_cursor_to_end(); @@ -6932,13 +7069,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_voice_transcription_enabled(true); + composer.set_voice_transcription_enabled(/*enabled*/ true); composer.set_text_content("x ".to_string(), Vec::new(), Vec::new()); composer.move_cursor_to_end(); @@ -6966,11 +7103,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let id = "voice-placeholder".to_string(); @@ -6993,11 +7130,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let flag_one = Arc::new(AtomicBool::new(false)); @@ -7063,11 +7200,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['/', 'c']); @@ -7084,11 +7221,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Type a prefix and complete with Tab, which inserts a trailing space @@ -7122,13 +7259,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_collaboration_modes_enabled(true); + composer.set_collaboration_modes_enabled(/*enabled*/ true); type_chars_humanlike(&mut composer, &['/', 'p', 'l', 'a', 'n', ' ']); @@ -7144,13 +7281,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_collaboration_modes_enabled(true); + composer.set_collaboration_modes_enabled(/*enabled*/ true); type_chars_humanlike(&mut composer, &['/', 'U', 's', 'e', 'r', 's', ' ']); @@ -7165,11 +7302,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['/', 'r', 'e', 'v', 'i', 'e', 'w', ' ']); @@ -7179,7 +7316,7 @@ mod tests { assert_eq!(text, "/review "); assert_eq!(elements.len(), 1); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); type_chars_humanlike(&mut composer, &['x']); let text = composer.textarea.text().to_string(); @@ -7197,11 +7334,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['h', 'i']); @@ -7225,13 +7362,13 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_task_running(false); + composer.set_task_running(/*running*/ false); type_chars_humanlike(&mut composer, &['!', 'l', 's']); @@ -7254,11 +7391,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['/', 'm', 'e', 'n', 't', 'i', 'o', 'n']); @@ -7295,16 +7432,16 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - composer.set_collaboration_modes_enabled(true); + composer.set_collaboration_modes_enabled(/*enabled*/ true); type_chars_humanlike(&mut composer, &['/', 'p', 'l', 'a', 'n', ' ']); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); composer.attach_image(PathBuf::from("/tmp/plan.png")); let (result, _needs_redraw) = @@ -7333,11 +7470,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let large = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5); @@ -7391,11 +7528,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Define test cases: (paste content, is_large) @@ -7470,11 +7607,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Define test cases: (content, is_large) @@ -7544,11 +7681,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let paste = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 4); @@ -7583,11 +7720,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let paste = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 4); @@ -7623,11 +7760,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Define test cases: (cursor_position_from_end, expected_pending_count) @@ -7671,11 +7808,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path = PathBuf::from("/tmp/image1.png"); composer.attach_image(path.clone()); @@ -7709,11 +7846,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let mention_bindings = vec![MentionBinding { @@ -7742,11 +7879,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let remote_image_url = "https://example.com/remote.png".to_string(); composer.set_remote_image_urls(vec![remote_image_url.clone()]); @@ -7776,11 +7913,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let remote_image_urls = vec![ "https://example.com/one.png".to_string(), @@ -7789,7 +7926,7 @@ mod tests { composer.set_remote_image_urls(remote_image_urls.clone()); let (submitted_text, submitted_elements) = composer - .prepare_submission_text(true) + .prepare_submission_text(/*record_history*/ true) .expect("remote-only submission should be prepared"); assert_eq!(submitted_text, ""); assert!(submitted_elements.is_empty()); @@ -7808,11 +7945,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); type_chars_humanlike(&mut composer, &['f', 'i', 'r', 's', 't']); @@ -7851,16 +7988,19 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); let text = format!("{placeholder} restored"); - let text_elements = vec![TextElement::new((0..placeholder.len()).into(), None)]; + let text_elements = vec![TextElement::new( + (0..placeholder.len()).into(), + /*placeholder*/ None, + )]; let path = PathBuf::from("/tmp/image1.png"); composer.set_text_content(text, text_elements, vec![path.clone()]); @@ -7873,11 +8013,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let large_content = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5); @@ -7916,11 +8056,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let large_content = format!(" {}", "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5)); @@ -7959,11 +8099,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let pasted = "line1\r\nline2\r\n".to_string(); @@ -8002,11 +8142,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.textarea.set_text_clearing_elements("/unknown "); @@ -8026,7 +8166,7 @@ mod tests { assert_eq!(composer.pending_pastes.len(), 1); assert_eq!(composer.textarea.text(), format!("/unknown {placeholder}")); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); composer.textarea.insert_str(" "); let (result, _) = composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); @@ -8048,11 +8188,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path = PathBuf::from("/tmp/image2.png"); composer.attach_image(path.clone()); @@ -8087,11 +8227,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path = PathBuf::from("/tmp/image_dup.png"); composer.attach_image(path.clone()); @@ -8110,18 +8250,20 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path = PathBuf::from("/tmp/image3.png"); composer.attach_image(path.clone()); let placeholder = composer.attached_images[0].placeholder.clone(); // Case 1: backspace at end - composer.textarea.move_cursor_to_end_of_line(false); + composer + .textarea + .move_cursor_to_end_of_line(/*move_down_at_eol*/ false); composer.handle_key_event(KeyEvent::new(KeyCode::Backspace, KeyModifiers::NONE)); assert!(!composer.textarea.text().contains(&placeholder)); assert!(composer.attached_images.is_empty()); @@ -8150,11 +8292,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Insert an image placeholder at the start @@ -8176,11 +8318,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path1 = PathBuf::from("/tmp/image_dup1.png"); @@ -8236,17 +8378,17 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path1 = PathBuf::from("/tmp/image_first.png"); let path2 = PathBuf::from("/tmp/image_second.png"); - let placeholder1 = local_image_label_text(1); - let placeholder2 = local_image_label_text(2); + let placeholder1 = local_image_label_text(/*label_number*/ 1); + let placeholder2 = local_image_label_text(/*label_number*/ 2); // Placeholders can be reordered in the text buffer; deleting image #1 should renumber // image #2 wherever it appears, not just after the cursor. @@ -8299,11 +8441,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let path1 = PathBuf::from("/tmp/image_first.png"); @@ -8316,7 +8458,7 @@ mod tests { assert_eq!(composer.attached_images.len(), 2); // Delete the first element using normal textarea editing (forward Delete at cursor start). - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); composer.handle_key_event(KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE)); // Remaining image should be renumbered and the textarea element updated. @@ -8337,11 +8479,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let needs_redraw = composer.handle_paste(tmp_path.to_string_lossy().to_string()); @@ -8359,11 +8501,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Inject prompts as if received via event. @@ -8398,11 +8540,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8433,11 +8575,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8472,11 +8614,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8501,7 +8643,7 @@ mod tests { text, text_elements, } => { - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); assert_eq!(text, format!("Review {placeholder}")); assert_eq!( text_elements, @@ -8527,11 +8669,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8557,7 +8699,7 @@ mod tests { text, text_elements, } => { - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); assert_eq!(text, format!("Review {placeholder}")); assert_eq!( text_elements, @@ -8583,11 +8725,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8631,11 +8773,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Create a custom prompt with positional args (no named args like $USER) @@ -8695,11 +8837,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8727,7 +8869,7 @@ mod tests { text, text_elements, } => { - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); assert_eq!(text, format!("Review {placeholder}\n\n{large_content}")); assert_eq!( text_elements, @@ -8753,11 +8895,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer @@ -8789,11 +8931,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer @@ -8821,11 +8963,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8853,7 +8995,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -8871,11 +9013,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer @@ -8893,7 +9035,7 @@ mod tests { panic!("expected stub history cell"); }; let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -8906,11 +9048,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8936,7 +9078,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -8961,11 +9103,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -8999,11 +9141,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9015,7 +9157,7 @@ mod tests { }]); composer.attach_image(PathBuf::from("/tmp/unused.png")); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); composer.handle_paste(format!("/{PROMPTS_CMD_PREFIX}:my-prompt ")); let (result, _needs_redraw) = @@ -9037,11 +9179,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9080,11 +9222,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9120,11 +9262,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9140,7 +9282,7 @@ mod tests { .set_text_clearing_elements("/prompts:my-prompt foo "); composer.textarea.set_cursor(composer.textarea.text().len()); composer.attach_image(PathBuf::from("/tmp/unused.png")); - composer.set_task_running(true); + composer.set_task_running(/*running*/ true); let (result, _needs_redraw) = composer.handle_key_event(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE)); @@ -9161,11 +9303,11 @@ mod tests { let (tx, mut rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_steer_enabled(true); @@ -9194,7 +9336,7 @@ mod tests { while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { let message = cell - .display_lines(80) + .display_lines(/*width*/ 80) .into_iter() .map(|line| line.to_string()) .collect::>() @@ -9244,11 +9386,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9280,11 +9422,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9316,11 +9458,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9354,11 +9496,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_custom_prompts(vec![CustomPrompt { @@ -9397,11 +9539,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::NONE)); @@ -9426,11 +9568,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let count = 32; @@ -9473,11 +9615,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let count = LARGE_PASTE_CHAR_THRESHOLD + 1; // > threshold to trigger placeholder @@ -9512,11 +9654,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let count = LARGE_PASTE_CHAR_THRESHOLD; // 1000 in current config @@ -9537,11 +9679,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Simulate history-like content: "/ test" @@ -9567,11 +9709,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); // Case 1: bare "/" @@ -9610,14 +9752,14 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); composer.textarea.insert_element(&placeholder); composer.attached_images.push(AttachedImage { placeholder: placeholder.clone(), @@ -9644,14 +9786,14 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); composer.textarea.insert_element(&placeholder); composer.attached_images.push(AttachedImage { placeholder: placeholder.clone(), @@ -9669,11 +9811,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let first_path = PathBuf::from("img1.png"); @@ -9681,10 +9823,10 @@ mod tests { composer.attach_image(first_path); composer.attach_image(second_path.clone()); - let placeholder2 = local_image_label_text(2); + let placeholder2 = local_image_label_text(/*label_number*/ 2); composer.apply_external_edit(format!("Keep {placeholder2}")); - let placeholder1 = local_image_label_text(1); + let placeholder1 = local_image_label_text(/*label_number*/ 1); assert_eq!(composer.current_text(), format!("Keep {placeholder1}")); assert_eq!(composer.attached_images.len(), 1); assert_eq!(composer.attached_images[0].placeholder, placeholder1); @@ -9697,11 +9839,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); let placeholder = "[Pasted Content 5 chars]".to_string(); @@ -9722,14 +9864,14 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); - let placeholder = local_image_label_text(1); + let placeholder = local_image_label_text(/*label_number*/ 1); composer.textarea.insert_element(&placeholder); composer.attached_images.push(AttachedImage { placeholder: placeholder.clone(), @@ -9750,11 +9892,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_remote_image_urls(vec![ @@ -9771,11 +9913,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_remote_image_urls(vec![ @@ -9793,11 +9935,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_remote_image_urls(vec!["https://example.com/one.png".to_string()]); @@ -9813,7 +9955,7 @@ mod tests { ); let (submitted_text, submitted_elements) = composer - .prepare_submission_text(true) + .prepare_submission_text(/*record_history*/ true) .expect("remote+local submission should be generated"); assert_eq!(submitted_text, "[Image #2] hello"); assert_eq!( @@ -9830,16 +9972,16 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_remote_image_urls(vec!["https://example.com/one.png".to_string()]); let (submitted_text, submitted_elements) = composer - .prepare_submission_text(true) + .prepare_submission_text(/*record_history*/ true) .expect("remote-only submission should be generated"); assert_eq!(submitted_text, ""); assert!(submitted_elements.is_empty()); @@ -9850,11 +9992,11 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_remote_image_urls(vec![ @@ -9862,7 +10004,7 @@ mod tests { "https://example.com/two.png".to_string(), ]); composer.attach_image(PathBuf::from("/tmp/local.png")); - composer.textarea.set_cursor(0); + composer.textarea.set_cursor(/*pos*/ 0); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Up, KeyModifiers::NONE)); let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE)); @@ -9889,15 +10031,18 @@ mod tests { let (tx, _rx) = unbounded_channel::(); let sender = AppEventSender::new(tx); let mut composer = ChatComposer::new( - true, + /*has_input_focus*/ true, sender, - false, + /*enhanced_keys_supported*/ false, "Ask Codex to do anything".to_string(), - false, + /*disable_paste_burst*/ false, ); composer.set_text_content("hello".to_string(), Vec::new(), Vec::new()); - composer.set_input_enabled(false, Some("Input disabled for test.".to_string())); + composer.set_input_enabled( + /*enabled*/ false, + Some("Input disabled for test.".to_string()), + ); let (result, needs_redraw) = composer.handle_key_event(KeyEvent::new(KeyCode::Char('x'), KeyModifiers::NONE)); diff --git a/codex-rs/tui_app_server/src/bottom_pane/chat_composer_history.rs b/codex-rs/tui_app_server/src/bottom_pane/chat_composer_history.rs index 8bb763994..cc212b5db 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/chat_composer_history.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/chat_composer_history.rs @@ -330,10 +330,10 @@ mod tests { let mut history = ChatComposerHistory::new(); // Pretend there are 3 persistent entries. - history.set_metadata(1, 3); + history.set_metadata(/*log_id*/ 1, /*entry_count*/ 3); // First Up should request offset 2 (latest) and await async data. - assert!(history.should_handle_navigation("", 0)); + assert!(history.should_handle_navigation("", /*cursor*/ 0)); assert!(history.navigate_up(&tx).is_none()); // don't replace the text yet // Verify that a history lookup request was sent. @@ -352,7 +352,7 @@ mod tests { // Inject the async response. assert_eq!( Some(HistoryEntry::new("latest".to_string())), - history.on_entry_response(1, 2, Some("latest".into())) + history.on_entry_response(/*log_id*/ 1, /*offset*/ 2, Some("latest".into())) ); // Next Up should move to offset 1. @@ -373,7 +373,7 @@ mod tests { assert_eq!( Some(HistoryEntry::new("older".to_string())), - history.on_entry_response(1, 1, Some("older".into())) + history.on_entry_response(/*log_id*/ 1, /*offset*/ 1, Some("older".into())) ); } @@ -383,7 +383,7 @@ mod tests { let tx = AppEventSender::new(tx); let mut history = ChatComposerHistory::new(); - history.set_metadata(1, 3); + history.set_metadata(/*log_id*/ 1, /*entry_count*/ 3); history .fetched_history .insert(1, HistoryEntry::new("command2".to_string())); @@ -416,9 +416,9 @@ mod tests { history.record_local_submission(HistoryEntry::new("hello".to_string())); history.last_history_text = Some("hello".to_string()); - assert!(history.should_handle_navigation("hello", 0)); + assert!(history.should_handle_navigation("hello", /*cursor*/ 0)); assert!(history.should_handle_navigation("hello", "hello".len())); - assert!(!history.should_handle_navigation("hello", 1)); - assert!(!history.should_handle_navigation("other", 0)); + assert!(!history.should_handle_navigation("hello", /*cursor*/ 1)); + assert!(!history.should_handle_navigation("other", /*cursor*/ 0)); } } diff --git a/codex-rs/tui_app_server/src/bottom_pane/feedback_view.rs b/codex-rs/tui_app_server/src/bottom_pane/feedback_view.rs index 98667f8f1..f9fb50764 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/feedback_view.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/feedback_view.rs @@ -628,13 +628,13 @@ mod tests { fn make_view(category: FeedbackCategory) -> FeedbackNoteView { let (tx_raw, _rx) = tokio::sync::mpsc::unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let snapshot = codex_feedback::CodexFeedback::new().snapshot(None); + let snapshot = codex_feedback::CodexFeedback::new().snapshot(/*session_id*/ None); FeedbackNoteView::new( category, snapshot, - None, + /*rollout_path*/ None, tx, - true, + /*include_logs*/ true, FeedbackAudience::External, ) } @@ -642,35 +642,35 @@ mod tests { #[test] fn feedback_view_bad_result() { let view = make_view(FeedbackCategory::BadResult); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_bad_result", rendered); } #[test] fn feedback_view_good_result() { let view = make_view(FeedbackCategory::GoodResult); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_good_result", rendered); } #[test] fn feedback_view_bug() { let view = make_view(FeedbackCategory::Bug); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_bug", rendered); } #[test] fn feedback_view_other() { let view = make_view(FeedbackCategory::Other); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_other", rendered); } #[test] fn feedback_view_safety_check() { let view = make_view(FeedbackCategory::SafetyCheck); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_safety_check", rendered); } @@ -690,17 +690,17 @@ mod tests { }, ]); let snapshot = codex_feedback::CodexFeedback::new() - .snapshot(None) + .snapshot(/*session_id*/ None) .with_feedback_diagnostics(diagnostics); let view = FeedbackNoteView::new( FeedbackCategory::Bug, snapshot, - None, + /*rollout_path*/ None, tx, - false, + /*include_logs*/ false, FeedbackAudience::External, ); - let rendered = render(&view, 60); + let rendered = render(&view, /*width*/ 60); insta::assert_snapshot!("feedback_view_with_connectivity_diagnostics", rendered); } diff --git a/codex-rs/tui_app_server/src/bottom_pane/footer.rs b/codex-rs/tui_app_server/src/bottom_pane/footer.rs index c8148c90b..194f662b3 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/footer.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/footer.rs @@ -1068,7 +1068,9 @@ mod tests { use ratatui::backend::TestBackend; fn snapshot_footer(name: &str, props: FooterProps) { - snapshot_footer_with_mode_indicator(name, 80, &props, None); + snapshot_footer_with_mode_indicator( + name, /*width*/ 80, &props, /*collaboration_mode_indicator*/ None, + ); } fn draw_footer_frame( @@ -1135,7 +1137,10 @@ mod tests { }; let right_line = if status_line_active { let full = mode_indicator_line(collaboration_mode_indicator, show_cycle_hint); - let compact = mode_indicator_line(collaboration_mode_indicator, false); + let compact = mode_indicator_line( + collaboration_mode_indicator, + /*show_cycle_hint*/ false, + ); let full_width = full.as_ref().map(|line| line.width() as u16).unwrap_or(0); if can_show_left_with_context(area, left_width, full_width) { full @@ -1455,14 +1460,14 @@ mod tests { snapshot_footer_with_mode_indicator( "footer_mode_indicator_wide", - 120, + /*width*/ 120, &props, Some(CollaborationModeIndicator::Plan), ); snapshot_footer_with_mode_indicator( "footer_mode_indicator_narrow_overlap_hides", - 50, + /*width*/ 50, &props, Some(CollaborationModeIndicator::Plan), ); @@ -1484,7 +1489,7 @@ mod tests { snapshot_footer_with_mode_indicator( "footer_mode_indicator_running_hides_hint", - 120, + /*width*/ 120, &props, Some(CollaborationModeIndicator::Plan), ); @@ -1557,7 +1562,7 @@ mod tests { snapshot_footer_with_mode_indicator( "footer_status_line_enabled_mode_right", - 120, + /*width*/ 120, &props, Some(CollaborationModeIndicator::Plan), ); @@ -1579,7 +1584,7 @@ mod tests { snapshot_footer_with_mode_indicator( "footer_status_line_disabled_context_right", - 120, + /*width*/ 120, &props, Some(CollaborationModeIndicator::Plan), ); @@ -1602,9 +1607,9 @@ mod tests { // has status line and no collaboration mode snapshot_footer_with_mode_indicator( "footer_status_line_enabled_no_mode_right", - 120, + /*width*/ 120, &props, - None, + /*collaboration_mode_indicator*/ None, ); let props = FooterProps { @@ -1626,7 +1631,7 @@ mod tests { snapshot_footer_with_mode_indicator( "footer_status_line_truncated_with_gap", - 40, + /*width*/ 40, &props, Some(CollaborationModeIndicator::Plan), ); @@ -1686,8 +1691,11 @@ mod tests { active_agent_label: None, }; - let screen = - render_footer_with_mode_indicator(80, &props, Some(CollaborationModeIndicator::Plan)); + let screen = render_footer_with_mode_indicator( + /*width*/ 80, + &props, + Some(CollaborationModeIndicator::Plan), + ); let collapsed = screen.split_whitespace().collect::>().join(" "); assert!( collapsed.contains("Plan mode"), diff --git a/codex-rs/tui_app_server/src/bottom_pane/list_selection_view.rs b/codex-rs/tui_app_server/src/bottom_pane/list_selection_view.rs index 10e641655..e3eecf2ed 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/list_selection_view.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/list_selection_view.rs @@ -1073,7 +1073,7 @@ mod tests { } fn render_lines(view: &ListSelectionView) -> String { - render_lines_with_width(view, 48) + render_lines_with_width(view, /*width*/ 48) } fn render_lines_with_width(view: &ListSelectionView, width: u16) -> String { @@ -1153,7 +1153,7 @@ mod tests { #[test] fn renders_blank_line_between_title_and_items_without_subtitle() { - let view = make_selection_view(None); + let view = make_selection_view(/*subtitle*/ None); assert_snapshot!( "list_selection_spacing_without_subtitle", render_lines(&view) @@ -1172,17 +1172,24 @@ mod tests { let tx = AppEventSender::new(tx_raw); let home = dirs::home_dir().expect("home directory should be available"); let codex_home = home.join(".codex"); - let params = - crate::theme_picker::build_theme_picker_params(None, Some(&codex_home), Some(94)); + let params = crate::theme_picker::build_theme_picker_params( + /*current_name*/ None, + Some(&codex_home), + Some(94), + ); let view = ListSelectionView::new(params, tx); - let rendered = render_lines_in_area(&view, 94, 35); + let rendered = render_lines_in_area(&view, /*width*/ 94, /*height*/ 35); assert!(rendered.contains("Move up/down to live preview themes")); } #[test] fn theme_picker_enables_side_content_background_preservation() { - let params = crate::theme_picker::build_theme_picker_params(None, None, Some(120)); + let params = crate::theme_picker::build_theme_picker_params( + /*current_name*/ None, + /*codex_home*/ None, + Some(120), + ); assert!( params.preserve_side_content_bg, "theme picker should preserve side-content backgrounds to keep diff preview styling", @@ -1260,7 +1267,7 @@ mod tests { ); assert_snapshot!( "list_selection_footer_note_wraps", - render_lines_with_width(&view, 40) + render_lines_with_width(&view, /*width*/ 40) ); } @@ -1380,7 +1387,7 @@ mod tests { tx, ); - let rendered = render_lines_with_width(&view, 60); + let rendered = render_lines_with_width(&view, /*width*/ 60); let command_line = rendered .lines() .find(|line| line.contains("python -mpre_commit run")) @@ -1471,7 +1478,7 @@ mod tests { }, tx, ); - let rendered = render_lines_with_width(&view, 24); + let rendered = render_lines_with_width(&view, /*width*/ 24); assert!( rendered.contains("3."), "third option missing for width 24:\n{rendered}" @@ -1521,7 +1528,7 @@ mod tests { ); assert_snapshot!( "list_selection_model_picker_width_80", - render_lines_with_width(&view, 80) + render_lines_with_width(&view, /*width*/ 80) ); } @@ -1548,7 +1555,7 @@ mod tests { ); assert_snapshot!( "list_selection_narrow_width_preserves_rows", - render_lines_with_width(&view, 24) + render_lines_with_width(&view, /*width*/ 24) ); } @@ -1556,7 +1563,7 @@ mod tests { fn snapshot_auto_visible_col_width_mode_scroll_behavior() { assert_snapshot!( "list_selection_col_width_mode_auto_visible_scroll", - render_before_after_scroll_snapshot(ColumnWidthMode::AutoVisible, 96) + render_before_after_scroll_snapshot(ColumnWidthMode::AutoVisible, /*width*/ 96) ); } @@ -1564,7 +1571,7 @@ mod tests { fn snapshot_auto_all_rows_col_width_mode_scroll_behavior() { assert_snapshot!( "list_selection_col_width_mode_auto_all_rows_scroll", - render_before_after_scroll_snapshot(ColumnWidthMode::AutoAllRows, 96) + render_before_after_scroll_snapshot(ColumnWidthMode::AutoAllRows, /*width*/ 96) ); } @@ -1572,7 +1579,7 @@ mod tests { fn snapshot_fixed_col_width_mode_scroll_behavior() { assert_snapshot!( "list_selection_col_width_mode_fixed_scroll", - render_before_after_scroll_snapshot(ColumnWidthMode::Fixed, 96) + render_before_after_scroll_snapshot(ColumnWidthMode::Fixed, /*width*/ 96) ); } @@ -1591,11 +1598,11 @@ mod tests { tx, ); - let before_scroll = render_lines_with_width(&view, 96); + let before_scroll = render_lines_with_width(&view, /*width*/ 96); for _ in 0..8 { view.handle_key_event(KeyEvent::from(KeyCode::Down)); } - let after_scroll = render_lines_with_width(&view, 96); + let after_scroll = render_lines_with_width(&view, /*width*/ 96); assert!( after_scroll.contains("9. Item 9 with an intentionally much longer name"), @@ -1693,7 +1700,7 @@ mod tests { tx, ); - assert_eq!(view.side_layout_width(80), None); + assert_eq!(view.side_layout_width(/*content_width*/ 80), None); } #[test] @@ -1723,7 +1730,7 @@ mod tests { tx, ); - let rendered = render_lines_with_width(&view, 70); + let rendered = render_lines_with_width(&view, /*width*/ 70); assert!( rendered.contains('N'), "expected stacked marker to be rendered:\n{rendered}" diff --git a/codex-rs/tui_app_server/src/bottom_pane/mcp_server_elicitation.rs b/codex-rs/tui_app_server/src/bottom_pane/mcp_server_elicitation.rs index 23f09b49c..e826e1191 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/mcp_server_elicitation.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/mcp_server_elicitation.rs @@ -1800,7 +1800,7 @@ mod tests { }, "required": ["confirmed"], }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); @@ -1855,7 +1855,7 @@ mod tests { } }, }), - None, + /*meta*/ None, ), ); @@ -1867,7 +1867,7 @@ mod tests { let thread_id = ThreadId::default(); let request = McpServerElicitationFormRequest::from_event( thread_id, - form_request("Allow this request?", Value::Null, None), + form_request("Allow this request?", Value::Null, /*meta*/ None), ) .expect("expected approval fallback"); @@ -1921,7 +1921,11 @@ mod tests { form_request( "Allow this request?", empty_object_schema(), - tool_approval_meta(&[], None, None), + tool_approval_meta( + &[], + /*tool_params*/ None, + /*tool_params_display*/ None, + ), ), ) .expect("expected approval fallback"); @@ -2030,7 +2034,7 @@ mod tests { fn empty_unmarked_schema_falls_back() { let request = McpServerElicitationFormRequest::from_event( ThreadId::default(), - form_request("Empty form", empty_object_schema(), None), + form_request("Empty form", empty_object_schema(), /*meta*/ None), ); assert_eq!(request, None); @@ -2102,13 +2106,16 @@ mod tests { }, "required": ["confirmed"], }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); - let mut overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let mut overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); - overlay.select_current_option(true); + overlay.select_current_option(/*committed*/ true); overlay.submit_answers(); let event = rx.try_recv().expect("expected resolution"); @@ -2148,18 +2155,21 @@ mod tests { APPROVAL_PERSIST_SESSION_VALUE, APPROVAL_PERSIST_ALWAYS_VALUE, ], - None, - None, + /*tool_params*/ None, + /*tool_params_display*/ None, ), ), ) .expect("expected approval fallback"); - let mut overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let mut overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); if let Some(answer) = overlay.current_answer_mut() { answer.selection.selected_idx = Some(1); } - overlay.select_current_option(true); + overlay.select_current_option(/*committed*/ true); overlay.submit_answers(); let event = rx.try_recv().expect("expected resolution"); @@ -2199,18 +2209,21 @@ mod tests { APPROVAL_PERSIST_SESSION_VALUE, APPROVAL_PERSIST_ALWAYS_VALUE, ], - None, - None, + /*tool_params*/ None, + /*tool_params_display*/ None, ), ), ) .expect("expected approval fallback"); - let mut overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let mut overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); if let Some(answer) = overlay.current_answer_mut() { answer.selection.selected_idx = Some(2); } - overlay.select_current_option(true); + overlay.select_current_option(/*committed*/ true); overlay.submit_answers(); let event = rx.try_recv().expect("expected resolution"); @@ -2255,11 +2268,14 @@ mod tests { }, "required": ["confirmed"], }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); - let mut overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let mut overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); assert_eq!(overlay.on_ctrl_c(), CancellationEvent::Handled); @@ -2300,7 +2316,7 @@ mod tests { } }, }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); @@ -2317,7 +2333,7 @@ mod tests { } }, }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); @@ -2334,20 +2350,23 @@ mod tests { } }, }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); - let mut overlay = McpServerElicitationOverlay::new(first, tx, true, false, false); + let mut overlay = McpServerElicitationOverlay::new( + first, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); overlay.try_consume_mcp_server_elicitation_request(second); overlay.try_consume_mcp_server_elicitation_request(third); - overlay.select_current_option(true); + overlay.select_current_option(/*committed*/ true); overlay.submit_answers(); assert_eq!(overlay.request.message, "Second"); - overlay.select_current_option(true); + overlay.select_current_option(/*committed*/ true); overlay.submit_answers(); assert_eq!(overlay.request.message, "Third"); @@ -2371,11 +2390,14 @@ mod tests { }, "required": ["confirmed"], }), - None, + /*meta*/ None, ), ) .expect("expected supported form"); - let overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); insta::assert_snapshot!( "mcp_server_elicitation_boolean_form", @@ -2391,11 +2413,18 @@ mod tests { form_request( "Allow this request?", empty_object_schema(), - tool_approval_meta(&[], None, None), + tool_approval_meta( + &[], + /*tool_params*/ None, + /*tool_params_display*/ None, + ), ), ) .expect("expected approval fallback"); - let overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); insta::assert_snapshot!( "mcp_server_elicitation_approval_form_without_schema", @@ -2416,13 +2445,16 @@ mod tests { APPROVAL_PERSIST_SESSION_VALUE, APPROVAL_PERSIST_ALWAYS_VALUE, ], - None, - None, + /*tool_params*/ None, + /*tool_params_display*/ None, ), ), ) .expect("expected approval fallback"); - let overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); insta::assert_snapshot!( "mcp_server_elicitation_approval_form_with_session_persist", @@ -2472,7 +2504,10 @@ mod tests { ), ) .expect("expected approval fallback"); - let overlay = McpServerElicitationOverlay::new(request, tx, true, false, false); + let overlay = McpServerElicitationOverlay::new( + request, tx, /*has_input_focus*/ true, /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, + ); insta::assert_snapshot!( "mcp_server_elicitation_approval_form_with_param_summary", diff --git a/codex-rs/tui_app_server/src/bottom_pane/mod.rs b/codex-rs/tui_app_server/src/bottom_pane/mod.rs index d74f05b5d..f06853798 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/mod.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/mod.rs @@ -1369,7 +1369,7 @@ mod tests { }); // Start a running task so the status indicator is active above the composer. - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Push an approval modal (e.g., command approval) which should hide the status view. pane.push_approval_request(exec_request(), &features); @@ -1436,7 +1436,7 @@ mod tests { }); // Begin a task: show initial status. - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Use a height that allows the status line to be visible above the composer. let area = Rect::new(0, 0, 40, 6); @@ -1463,10 +1463,10 @@ mod tests { }); // Activate spinner (status view replaces composer) with no live ring. - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Use height == desired_height; expect spacer + status + composer rows without trailing padding. - let height = pane.desired_height(30); + let height = pane.desired_height(/*width*/ 30); assert!( height >= 3, "expected at least 3 rows to render spacer, status, and composer; got {height}" @@ -1493,7 +1493,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); let width = 48; let height = pane.desired_height(width); @@ -1516,7 +1516,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); let width = 120; let before = pane.desired_height(width); @@ -1545,7 +1545,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); pane.update_status( "Working".to_string(), Some("First detail line\nSecond detail line".to_string()), @@ -1582,7 +1582,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); pane.set_pending_input_preview( vec!["Queued follow-up question".to_string()], Vec::new(), @@ -1614,7 +1614,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); pane.set_pending_input_preview( vec!["Queued follow-up question".to_string()], Vec::new(), @@ -1706,7 +1706,7 @@ mod tests { }]), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Repro: a running task + skill popup + Esc should dismiss the popup, not interrupt. pane.insert_str("$"); @@ -1744,7 +1744,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Repro: a running task + slash-command popup + Esc should not interrupt the task. pane.insert_str("/"); @@ -1779,7 +1779,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); // Repro: `/agent ` hides the popup (cursor past command name). Esc should // keep editing command text instead of interrupting the running task. @@ -1815,7 +1815,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); pane.show_selection_view(SelectionViewParams { title: Some("Agents".to_string()), items: vec![SelectionItem { @@ -1863,7 +1863,7 @@ mod tests { skills: Some(Vec::new()), }); - pane.set_task_running(true); + pane.set_task_running(/*running*/ true); pane.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); diff --git a/codex-rs/tui_app_server/src/bottom_pane/paste_burst.rs b/codex-rs/tui_app_server/src/bottom_pane/paste_burst.rs index 92cdb5051..510294a5f 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/paste_burst.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/paste_burst.rs @@ -532,11 +532,15 @@ mod tests { let mut burst = PasteBurst::default(); let now = Instant::now(); - assert!(burst.decide_begin_buffer(now, "ab", 2).is_none()); + assert!( + burst + .decide_begin_buffer(now, "ab", /*retro_chars*/ 2) + .is_none() + ); assert!(!burst.is_active()); let grab = burst - .decide_begin_buffer(now, "a b", 2) + .decide_begin_buffer(now, "a b", /*retro_chars*/ 2) .expect("whitespace should be considered paste-like"); assert_eq!(grab.start_byte, 1); assert_eq!(grab.grabbed, " b"); diff --git a/codex-rs/tui_app_server/src/bottom_pane/pending_input_preview.rs b/codex-rs/tui_app_server/src/bottom_pane/pending_input_preview.rs index b9690c28e..090892f5f 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/pending_input_preview.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/pending_input_preview.rs @@ -183,14 +183,14 @@ mod tests { #[test] fn desired_height_empty() { let queue = PendingInputPreview::new(); - assert_eq!(queue.desired_height(40), 0); + assert_eq!(queue.desired_height(/*width*/ 40), 0); } #[test] fn desired_height_one_message() { let mut queue = PendingInputPreview::new(); queue.queued_messages.push("Hello, world!".to_string()); - assert_eq!(queue.desired_height(40), 3); + assert_eq!(queue.desired_height(/*width*/ 40), 3); } #[test] diff --git a/codex-rs/tui_app_server/src/bottom_pane/pending_thread_approvals.rs b/codex-rs/tui_app_server/src/bottom_pane/pending_thread_approvals.rs index 6a3a7c2f1..3c35b764d 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/pending_thread_approvals.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/pending_thread_approvals.rs @@ -108,7 +108,7 @@ mod tests { #[test] fn desired_height_empty() { let widget = PendingThreadApprovals::new(); - assert_eq!(widget.desired_height(40), 0); + assert_eq!(widget.desired_height(/*width*/ 40), 0); } #[test] @@ -117,7 +117,7 @@ mod tests { widget.set_threads(vec!["Robie [explorer]".to_string()]); assert_snapshot!( - snapshot_rows(&widget, 40).replace(' ', "."), + snapshot_rows(&widget, /*width*/ 40).replace(' ', "."), @r" ..!.Approval.needed.in.Robie.[explorer]. ..../agent.to.switch.threads............ @@ -136,7 +136,7 @@ mod tests { ]); assert_snapshot!( - snapshot_rows(&widget, 44).replace(' ', "."), + snapshot_rows(&widget, /*width*/ 44).replace(' ', "."), @r" ..!.Approval.needed.in.Main.[default]....... ..!.Approval.needed.in.Robie.[explorer]..... diff --git a/codex-rs/tui_app_server/src/bottom_pane/request_user_input/mod.rs b/codex-rs/tui_app_server/src/bottom_pane/request_user_input/mod.rs index 1511ff646..f7db7c65d 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/request_user_input/mod.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/request_user_input/mod.rs @@ -1485,9 +1485,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "First")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.try_consume_user_input_request(request_event( "turn-2", @@ -1511,9 +1511,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "First")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.try_consume_user_input_request(RequestUserInputEvent { call_id: "call-2".to_string(), @@ -1538,9 +1538,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.submit_answers(); @@ -1560,9 +1560,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -1587,9 +1587,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -1629,9 +1629,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Char('2'))); @@ -1650,9 +1650,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer().expect("answer missing"); assert_eq!(answer.options_state.selected_idx, Some(0)); @@ -1678,9 +1678,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); assert_eq!(overlay.current_index(), 0); @@ -1704,9 +1704,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); assert_eq!(overlay.current_index(), 0); @@ -1728,9 +1728,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); assert_eq!(overlay.current_index(), 0); @@ -1752,9 +1752,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let tips = overlay.footer_tips(); let tip_texts = tips.iter().map(|tip| tip.text.as_str()).collect::>(); @@ -1789,11 +1789,11 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); - overlay.move_question(true); + overlay.move_question(/*next*/ true); let tips = overlay.footer_tips(); let tip_texts = tips.iter().map(|tip| tip.text.as_str()).collect::>(); @@ -1813,9 +1813,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(1); @@ -1838,13 +1838,13 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); assert!(matches!(overlay.focus, Focus::Notes)); - overlay.move_question(true); + overlay.move_question(/*next*/ true); assert!(matches!(overlay.focus, Focus::Options)); assert_eq!(overlay.notes_ui_visible(), false); @@ -1862,9 +1862,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay @@ -1872,7 +1872,7 @@ mod tests { .set_text_content("freeform notes".to_string(), Vec::new(), Vec::new()); overlay.composer.move_cursor_to_end(); - overlay.move_question(true); + overlay.move_question(/*next*/ true); assert!(matches!(overlay.focus, Focus::Options)); assert_eq!(overlay.notes_ui_visible(), false); @@ -1902,9 +1902,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_without_options("q1", "Notes")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Esc)); @@ -1919,9 +1919,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Esc)); @@ -1936,9 +1936,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -1964,9 +1964,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -1999,9 +1999,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -2021,9 +2021,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(1); @@ -2042,9 +2042,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -2068,9 +2068,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -2097,9 +2097,9 @@ mod tests { let overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); assert_eq!(overlay.unanswered_count(), 1); @@ -2111,9 +2111,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -2133,9 +2133,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay @@ -2162,9 +2162,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -2179,9 +2179,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_without_options("q1", "Notes")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.submit_answers(); @@ -2200,9 +2200,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_without_options("q1", "Notes")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay .composer @@ -2231,9 +2231,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay @@ -2244,12 +2244,12 @@ mod tests { assert_eq!(overlay.answers[0].answer_committed, true); let _ = rx.try_recv(); - overlay.move_question(false); + overlay.move_question(/*next*/ false); overlay .composer .set_text_content("Edited".to_string(), Vec::new(), Vec::new()); overlay.composer.move_cursor_to_end(); - overlay.move_question(true); + overlay.move_question(/*next*/ true); assert_eq!(overlay.answers[0].answer_committed, false); overlay.submit_answers(); @@ -2268,16 +2268,16 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); { let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(1); } - overlay.select_current_option(false); + overlay.select_current_option(/*committed*/ false); overlay .composer .set_text_content("Notes for option 2".to_string(), Vec::new(), Vec::new()); @@ -2316,9 +2316,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.handle_key_event(KeyEvent::from(KeyCode::Down)); @@ -2345,9 +2345,9 @@ mod tests { vec![question_with_options_and_other("q1", "Pick one")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let rows = overlay.option_rows(); @@ -2401,14 +2401,14 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let large = "x".repeat(1_500); overlay.composer.handle_paste(large.clone()); - overlay.move_question(true); + overlay.move_question(/*next*/ true); let draft = &overlay.answers[0].draft; assert_eq!(draft.pending_pastes.len(), 1); @@ -2429,9 +2429,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let large = "x".repeat(1_200); @@ -2454,9 +2454,9 @@ mod tests { let overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Area")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 120, 16); insta::assert_snapshot!( @@ -2471,9 +2471,9 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Area")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); { let answer = overlay.current_answer_mut().expect("answer missing"); @@ -2494,9 +2494,9 @@ mod tests { let overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Area")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 120, 10); insta::assert_snapshot!( @@ -2514,9 +2514,9 @@ mod tests { vec![question_with_wrapped_options("q1", "Next Step")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let width = 48u16; @@ -2542,9 +2542,9 @@ mod tests { vec![question_with_wrapped_options("q1", "Next Step")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let width = 110u16; @@ -2574,9 +2574,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(0); @@ -2608,9 +2608,9 @@ mod tests { vec![question_with_wrapped_options("q1", "Next Step")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); { @@ -2641,9 +2641,9 @@ mod tests { vec![question_with_very_long_option_text("q1", "Status")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 120, 18); insta::assert_snapshot!( @@ -2661,9 +2661,9 @@ mod tests { vec![question_with_long_scroll_options("q1", "Scroll")], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(2); @@ -2687,9 +2687,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let answer = overlay.current_answer_mut().expect("answer missing"); answer.options_state.selected_idx = Some(1); @@ -2740,9 +2740,9 @@ mod tests { }], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); { let answer = overlay.current_answer_mut().expect("answer missing"); @@ -2792,9 +2792,9 @@ mod tests { }], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); { let answer = overlay.current_answer_mut().expect("answer missing"); @@ -2813,9 +2813,9 @@ mod tests { let overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_without_options("q1", "Goal")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 120, 10); insta::assert_snapshot!( @@ -2836,9 +2836,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); let area = Rect::new(0, 0, 120, 15); insta::assert_snapshot!( @@ -2859,11 +2859,11 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); - overlay.move_question(true); + overlay.move_question(/*next*/ true); let area = Rect::new(0, 0, 120, 12); insta::assert_snapshot!( "request_user_input_multi_question_last", @@ -2883,9 +2883,9 @@ mod tests { ], ), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); overlay.open_unanswered_confirmation(); @@ -2903,11 +2903,11 @@ mod tests { let mut overlay = RequestUserInputOverlay::new( request_event("turn-1", vec![question_with_options("q1", "Pick one")]), tx, - true, - false, - false, + /*has_input_focus*/ true, + /*enhanced_keys_supported*/ false, + /*disable_paste_burst*/ false, ); - overlay.select_current_option(false); + overlay.select_current_option(/*committed*/ false); overlay.focus = Focus::Notes; overlay .composer diff --git a/codex-rs/tui_app_server/src/bottom_pane/selection_popup_common.rs b/codex-rs/tui_app_server/src/bottom_pane/selection_popup_common.rs index 85f5a1c61..cff3a34f7 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/selection_popup_common.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/selection_popup_common.rs @@ -863,7 +863,7 @@ mod tests { ..Default::default() }; - let two_col = wrap_two_column_row(&row, 0, 1); + let two_col = wrap_two_column_row(&row, /*desc_col*/ 0, /*width*/ 1); assert_eq!(two_col.len(), 0); } } diff --git a/codex-rs/tui_app_server/src/bottom_pane/skills_toggle_view.rs b/codex-rs/tui_app_server/src/bottom_pane/skills_toggle_view.rs index 7a255d20c..1831223b7 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/skills_toggle_view.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/skills_toggle_view.rs @@ -429,6 +429,6 @@ mod tests { }, ]; let view = SkillsToggleView::new(items, tx); - assert_snapshot!("skills_toggle_basic", render_lines(&view, 72)); + assert_snapshot!("skills_toggle_basic", render_lines(&view, /*width*/ 72)); } } diff --git a/codex-rs/tui_app_server/src/bottom_pane/status_line_setup.rs b/codex-rs/tui_app_server/src/bottom_pane/status_line_setup.rs index 58c7ff7f1..cb0229e77 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/status_line_setup.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/status_line_setup.rs @@ -366,7 +366,7 @@ mod tests { AppEventSender::new(tx_raw), ); - assert_snapshot!(render_lines(&view, 72)); + assert_snapshot!(render_lines(&view, /*width*/ 72)); } fn render_lines(view: &StatusLineSetupView, width: u16) -> String { diff --git a/codex-rs/tui_app_server/src/bottom_pane/textarea.rs b/codex-rs/tui_app_server/src/bottom_pane/textarea.rs index 5677c9b11..f9e5f457b 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/textarea.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/textarea.rs @@ -1468,17 +1468,17 @@ mod tests { fn insert_and_replace_update_cursor_and_text() { // insert helpers let mut t = ta_with("hello"); - t.set_cursor(5); + t.set_cursor(/*pos*/ 5); t.insert_str("!"); assert_eq!(t.text(), "hello!"); assert_eq!(t.cursor(), 6); - t.insert_str_at(0, "X"); + t.insert_str_at(/*pos*/ 0, "X"); assert_eq!(t.text(), "Xhello!"); assert_eq!(t.cursor(), 7); // Insert after the cursor should not move it - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); let end = t.text().len(); t.insert_str_at(end, "Y"); assert_eq!(t.text(), "Xhello!Y"); @@ -1487,21 +1487,21 @@ mod tests { // replace_range cases // 1) cursor before range let mut t = ta_with("abcd"); - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); t.replace_range(2..3, "Z"); assert_eq!(t.text(), "abZd"); assert_eq!(t.cursor(), 1); // 2) cursor inside range let mut t = ta_with("abcd"); - t.set_cursor(2); + t.set_cursor(/*pos*/ 2); t.replace_range(1..3, "Q"); assert_eq!(t.text(), "aQd"); assert_eq!(t.cursor(), 2); // 3) cursor after range with shifted by diff let mut t = ta_with("abcd"); - t.set_cursor(4); + t.set_cursor(/*pos*/ 4); t.replace_range(0..1, "AA"); assert_eq!(t.text(), "AAbcd"); assert_eq!(t.cursor(), 5); @@ -1511,8 +1511,8 @@ mod tests { fn insert_str_at_clamps_to_char_boundary() { let mut t = TextArea::new(); t.insert_str("δ½ "); - t.set_cursor(0); - t.insert_str_at(1, "A"); + t.set_cursor(/*pos*/ 0); + t.insert_str_at(/*pos*/ 1, "A"); assert_eq!(t.text(), "Aδ½ "); assert_eq!(t.cursor(), 1); } @@ -1521,7 +1521,7 @@ mod tests { fn set_text_clamps_cursor_to_char_boundary() { let mut t = TextArea::new(); t.insert_str("abcd"); - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); t.set_text_clearing_elements("δ½ "); assert_eq!(t.cursor(), 0); t.insert_str("a"); @@ -1531,26 +1531,26 @@ mod tests { #[test] fn delete_backward_and_forward_edges() { let mut t = ta_with("abc"); - t.set_cursor(1); - t.delete_backward(1); + t.set_cursor(/*pos*/ 1); + t.delete_backward(/*n*/ 1); assert_eq!(t.text(), "bc"); assert_eq!(t.cursor(), 0); // deleting backward at start is a no-op - t.set_cursor(0); - t.delete_backward(1); + t.set_cursor(/*pos*/ 0); + t.delete_backward(/*n*/ 1); assert_eq!(t.text(), "bc"); assert_eq!(t.cursor(), 0); // forward delete removes next grapheme - t.set_cursor(1); - t.delete_forward(1); + t.set_cursor(/*pos*/ 1); + t.delete_forward(/*n*/ 1); assert_eq!(t.text(), "b"); assert_eq!(t.cursor(), 1); // forward delete at end is a no-op t.set_cursor(t.text().len()); - t.delete_forward(1); + t.delete_forward(/*n*/ 1); assert_eq!(t.text(), "b"); } @@ -1563,7 +1563,7 @@ mod tests { let elem_start = t.elements[0].range.start; t.set_cursor(elem_start); - t.delete_forward(1); + t.delete_forward(/*n*/ 1); assert_eq!(t.text(), "ab"); assert_eq!(t.cursor(), elem_start); @@ -1580,7 +1580,7 @@ mod tests { // From inside a word, delete from word start to cursor let mut t = ta_with("foo bar"); - t.set_cursor(6); // inside "bar" (after 'a') + t.set_cursor(/*pos*/ 6); // inside "bar" (after 'a') t.delete_backward_word(); assert_eq!(t.text(), "foo r"); assert_eq!(t.cursor(), 4); @@ -1594,27 +1594,27 @@ mod tests { // kill_to_end_of_line when not at EOL let mut t = ta_with("abc\ndef"); - t.set_cursor(1); // on first line, middle + t.set_cursor(/*pos*/ 1); // on first line, middle t.kill_to_end_of_line(); assert_eq!(t.text(), "a\ndef"); assert_eq!(t.cursor(), 1); // kill_to_end_of_line when at EOL deletes newline let mut t = ta_with("abc\ndef"); - t.set_cursor(3); // EOL of first line + t.set_cursor(/*pos*/ 3); // EOL of first line t.kill_to_end_of_line(); assert_eq!(t.text(), "abcdef"); assert_eq!(t.cursor(), 3); // kill_to_beginning_of_line from middle of line let mut t = ta_with("abc\ndef"); - t.set_cursor(5); // on second line, after 'e' + t.set_cursor(/*pos*/ 5); // on second line, after 'e' t.kill_to_beginning_of_line(); assert_eq!(t.text(), "abc\nef"); // kill_to_beginning_of_line at beginning of non-first line removes the previous newline let mut t = ta_with("abc\ndef"); - t.set_cursor(4); // beginning of second line + t.set_cursor(/*pos*/ 4); // beginning of second line t.kill_to_beginning_of_line(); assert_eq!(t.text(), "abcdef"); assert_eq!(t.cursor(), 3); @@ -1623,13 +1623,13 @@ mod tests { #[test] fn delete_forward_word_variants() { let mut t = ta_with("hello world "); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), " world "); assert_eq!(t.cursor(), 0); let mut t = ta_with("hello world "); - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); t.delete_forward_word(); assert_eq!(t.text(), "h world "); assert_eq!(t.cursor(), 1); @@ -1641,13 +1641,13 @@ mod tests { assert_eq!(t.cursor(), t.text().len()); let mut t = ta_with("foo \nbar"); - t.set_cursor(3); + t.set_cursor(/*pos*/ 3); t.delete_forward_word(); assert_eq!(t.text(), "foo"); assert_eq!(t.cursor(), 3); let mut t = ta_with("foo\nbar"); - t.set_cursor(3); + t.set_cursor(/*pos*/ 3); t.delete_forward_word(); assert_eq!(t.text(), "foo"); assert_eq!(t.cursor(), 3); @@ -1665,7 +1665,7 @@ mod tests { t.insert_element(""); t.insert_str(" tail"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), " tail"); assert_eq!(t.cursor(), 0); @@ -1675,7 +1675,7 @@ mod tests { t.insert_element(""); t.insert_str(" tail"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), " tail"); assert_eq!(t.cursor(), 0); @@ -1721,7 +1721,7 @@ mod tests { #[test] fn delete_forward_word_respects_word_separators() { let mut t = ta_with("path/to/file"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), "/to/file"); assert_eq!(t.cursor(), 0); @@ -1731,13 +1731,13 @@ mod tests { assert_eq!(t.cursor(), 0); let mut t = ta_with("/ foo"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), " foo"); assert_eq!(t.cursor(), 0); let mut t = ta_with(" /foo"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.delete_forward_word(); assert_eq!(t.text(), "foo"); assert_eq!(t.cursor(), 0); @@ -1746,7 +1746,7 @@ mod tests { #[test] fn yank_restores_last_kill() { let mut t = ta_with("hello"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.kill_to_end_of_line(); assert_eq!(t.text(), ""); assert_eq!(t.cursor(), 0); @@ -1766,7 +1766,7 @@ mod tests { assert_eq!(t.cursor(), 11); let mut t = ta_with("hello"); - t.set_cursor(5); + t.set_cursor(/*pos*/ 5); t.kill_to_beginning_of_line(); assert_eq!(t.text(), ""); assert_eq!(t.cursor(), 0); @@ -1779,7 +1779,7 @@ mod tests { #[test] fn kill_buffer_persists_across_set_text() { let mut t = ta_with("restore me"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.kill_to_end_of_line(); assert!(t.text().is_empty()); @@ -1817,7 +1817,7 @@ mod tests { #[test] fn control_b_and_f_move_cursor() { let mut t = ta_with("abcd"); - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); t.input(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::CONTROL)); assert_eq!(t.cursor(), 2); @@ -1829,7 +1829,7 @@ mod tests { #[test] fn control_b_f_fallback_control_chars_move_cursor() { let mut t = ta_with("abcd"); - t.set_cursor(2); + t.set_cursor(/*pos*/ 2); // Simulate terminals that send C0 control chars without CONTROL modifier. // ^B (U+0002) should move left @@ -1873,13 +1873,13 @@ mod tests { #[test] fn delete_forward_word_with_without_alt_modifier() { let mut t = ta_with("hello world"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.input(KeyEvent::new(KeyCode::Delete, KeyModifiers::ALT)); assert_eq!(t.text(), " world"); assert_eq!(t.cursor(), 0); let mut t = ta_with("hello"); - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.input(KeyEvent::new(KeyCode::Delete, KeyModifiers::NONE)); assert_eq!(t.text(), "ello"); assert_eq!(t.cursor(), 0); @@ -1888,7 +1888,7 @@ mod tests { #[test] fn delete_forward_word_alt_d() { let mut t = ta_with("hello world"); - t.set_cursor(6); + t.set_cursor(/*pos*/ 6); t.input(KeyEvent::new(KeyCode::Char('d'), KeyModifiers::ALT)); pretty_assertions::assert_eq!(t.text(), "hello "); pretty_assertions::assert_eq!(t.cursor(), 6); @@ -1898,13 +1898,13 @@ mod tests { fn control_h_backspace() { // Test Ctrl+H as backspace let mut t = ta_with("12345"); - t.set_cursor(3); // cursor after '3' + t.set_cursor(/*pos*/ 3); // cursor after '3' t.input(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::CONTROL)); assert_eq!(t.text(), "1245"); assert_eq!(t.cursor(), 2); // Test Ctrl+H at beginning (should be no-op) - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.input(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::CONTROL)); assert_eq!(t.text(), "1245"); assert_eq!(t.cursor(), 0); @@ -1967,19 +1967,19 @@ mod tests { let second_line_start = t.text().find("two").unwrap(); t.set_cursor(second_line_start + 1); - t.move_cursor_to_beginning_of_line(false); + t.move_cursor_to_beginning_of_line(/*move_up_at_bol*/ false); assert_eq!(t.cursor(), second_line_start); // Ctrl-A behavior: if at BOL, go to beginning of previous line - t.move_cursor_to_beginning_of_line(true); + t.move_cursor_to_beginning_of_line(/*move_up_at_bol*/ true); assert_eq!(t.cursor(), 0); // beginning of first line // Move to EOL of first line - t.move_cursor_to_end_of_line(false); + t.move_cursor_to_end_of_line(/*move_down_at_eol*/ false); assert_eq!(t.cursor(), 3); // Ctrl-E: if at EOL, go to end of next line - t.move_cursor_to_end_of_line(true); + t.move_cursor_to_end_of_line(/*move_down_at_eol*/ true); // end of second line ("two") is right before its '\n' let end_second_nl = t.text().find("\nthree").unwrap(); assert_eq!(t.cursor(), end_second_nl); @@ -1991,13 +1991,13 @@ mod tests { // Place cursor at absolute end of the text t.set_cursor(t.text().len()); // Should remain at end without panicking - t.move_cursor_to_end_of_line(true); + t.move_cursor_to_end_of_line(/*move_down_at_eol*/ true); assert_eq!(t.cursor(), t.text().len()); // Also verify behavior when at EOL of a non-final line: let eol_first_line = 3; // index of '\n' in "one\ntwo" t.set_cursor(eol_first_line); - t.move_cursor_to_end_of_line(true); + t.move_cursor_to_end_of_line(/*move_down_at_eol*/ true); assert_eq!(t.cursor(), t.text().len()); // moves to end of next (last) line } @@ -2052,7 +2052,7 @@ mod tests { fn cursor_pos_with_state_basic_and_scroll_behaviors() { // Case 1: No wrapping needed, height fits β€” scroll ignored, y maps directly. let mut t = ta_with("hello world"); - t.set_cursor(3); + t.set_cursor(/*pos*/ 3); let area = Rect::new(2, 5, 20, 3); // Even if an absurd scroll is provided, when content fits the area the // effective scroll is 0 and the cursor position matches cursor_pos. @@ -2080,7 +2080,7 @@ mod tests { let wrap_width = 5; let lines = t.desired_height(wrap_width); // Place cursor near start so an excessive scroll moves it to top row. - t.set_cursor(1); + t.set_cursor(/*pos*/ 1); let area = Rect::new(0, 0, wrap_width, 3); let state = TextAreaState { scroll: lines.saturating_mul(2), @@ -2093,15 +2093,15 @@ mod tests { fn wrapped_navigation_across_visual_lines() { let mut t = ta_with("abcdefghij"); // Force wrapping at width 4: lines -> ["abcd", "efgh", "ij"] - let _ = t.desired_height(4); + let _ = t.desired_height(/*width*/ 4); // From the very start, moving down should go to the start of the next wrapped line (index 4) - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); t.move_cursor_down(); assert_eq!(t.cursor(), 4); // Cursor at boundary index 4 should be displayed at start of second wrapped line - t.set_cursor(4); + t.set_cursor(/*pos*/ 4); let area = Rect::new(0, 0, 4, 10); let (x, y) = t.cursor_pos(area).unwrap(); assert_eq!((x, y), (0, 1)); @@ -2113,7 +2113,7 @@ mod tests { assert_eq!((x, y), (0, 0)); // Place cursor in the middle of the second wrapped line ("efgh"), at 'g' - t.set_cursor(6); + t.set_cursor(/*pos*/ 6); // Move up should go to same column on previous wrapped line -> index 2 ('c') t.move_cursor_up(); assert_eq!(t.cursor(), 2); @@ -2131,13 +2131,13 @@ mod tests { fn cursor_pos_with_state_after_movements() { let mut t = ta_with("abcdefghij"); // Wrap width 4 -> visual lines: abcd | efgh | ij - let _ = t.desired_height(4); + let _ = t.desired_height(/*width*/ 4); let area = Rect::new(0, 0, 4, 2); let mut state = TextAreaState::default(); let mut buf = Buffer::empty(area); // Start at beginning - t.set_cursor(0); + t.set_cursor(/*pos*/ 0); ratatui::widgets::StatefulWidgetRef::render_ref(&(&t), area, &mut buf, &mut state); let (x, y) = t.cursor_pos_with_state(area, state).unwrap(); assert_eq!((x, y), (0, 0)); @@ -2161,7 +2161,7 @@ mod tests { assert_eq!((x, y), (0, 0)); // Column preservation across moves: set to col 2 on first line, move down - t.set_cursor(2); + t.set_cursor(/*pos*/ 2); ratatui::widgets::StatefulWidgetRef::render_ref(&(&t), area, &mut buf, &mut state); let (x0, y0) = t.cursor_pos_with_state(area, state).unwrap(); assert_eq!((x0, y0), (2, 0)); @@ -2176,7 +2176,7 @@ mod tests { // Include spaces and an explicit newline to exercise boundaries let mut t = ta_with("word1 word2\nword3"); // Width 6 will wrap "word1 " and then "word2" before the newline - let _ = t.desired_height(6); + let _ = t.desired_height(/*width*/ 6); // Put cursor on the second wrapped line before the newline, at column 1 of "word2" let start_word2 = t.text().find("word2").unwrap(); @@ -2200,7 +2200,7 @@ mod tests { fn wrapped_navigation_with_wide_graphemes() { // Four thumbs up, each of display width 2, with width 3 to force wrapping inside grapheme boundaries let mut t = ta_with("πŸ‘πŸ‘πŸ‘πŸ‘"); - let _ = t.desired_height(3); + let _ = t.desired_height(/*width*/ 3); // Put cursor after the second emoji (which should be on first wrapped line) t.set_cursor("πŸ‘πŸ‘".len()); @@ -2320,8 +2320,8 @@ mod tests { 8 => ta.move_cursor_right(), 9 => ta.move_cursor_up(), 10 => ta.move_cursor_down(), - 11 => ta.move_cursor_to_beginning_of_line(true), - 12 => ta.move_cursor_to_end_of_line(true), + 11 => ta.move_cursor_to_beginning_of_line(/*move_up_at_bol*/ true), + 12 => ta.move_cursor_to_end_of_line(/*move_down_at_eol*/ true), 13 => { // Insert an element with a unique sentinel payload let payload = diff --git a/codex-rs/tui_app_server/src/bottom_pane/title_setup.rs b/codex-rs/tui_app_server/src/bottom_pane/title_setup.rs index 6714d8b3a..b9899e32d 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/title_setup.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/title_setup.rs @@ -281,7 +281,10 @@ mod tests { "thread".to_string(), ]; let view = TerminalTitleSetupView::new(Some(&selected), tx); - assert_snapshot!("terminal_title_setup_basic", render_lines(&view, 84)); + assert_snapshot!( + "terminal_title_setup_basic", + render_lines(&view, /*width*/ 84) + ); } #[test] diff --git a/codex-rs/tui_app_server/src/bottom_pane/unified_exec_footer.rs b/codex-rs/tui_app_server/src/bottom_pane/unified_exec_footer.rs index 3714aa495..9b69387c1 100644 --- a/codex-rs/tui_app_server/src/bottom_pane/unified_exec_footer.rs +++ b/codex-rs/tui_app_server/src/bottom_pane/unified_exec_footer.rs @@ -90,7 +90,7 @@ mod tests { #[test] fn desired_height_empty() { let footer = UnifiedExecFooter::new(); - assert_eq!(footer.desired_height(40), 0); + assert_eq!(footer.desired_height(/*width*/ 40), 0); } #[test] diff --git a/codex-rs/tui_app_server/src/chatwidget/tests.rs b/codex-rs/tui_app_server/src/chatwidget/tests.rs index 4ab4b26d2..e94a47f44 100644 --- a/codex-rs/tui_app_server/src/chatwidget/tests.rs +++ b/codex-rs/tui_app_server/src/chatwidget/tests.rs @@ -233,7 +233,7 @@ fn snapshot(percent: f64) -> RateLimitSnapshot { #[tokio::test] async fn resumed_initial_messages_render_history() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -297,7 +297,7 @@ async fn resumed_initial_messages_render_history() { #[tokio::test] async fn thread_snapshot_replay_does_not_duplicate_agent_message_history() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event_replay(Event { id: "turn-1".into(), @@ -338,7 +338,7 @@ async fn thread_snapshot_replay_does_not_duplicate_agent_message_history() { #[tokio::test] async fn replayed_user_message_preserves_text_elements_and_local_images() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let placeholder = "[Image #1]"; let message = format!("{placeholder} replayed"); @@ -404,7 +404,7 @@ async fn replayed_user_message_preserves_text_elements_and_local_images() { #[tokio::test] async fn replayed_user_message_preserves_remote_image_urls() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let message = "replayed with remote image".to_string(); let remote_image_urls = vec!["https://example.com/image.png".to_string()]; @@ -463,7 +463,7 @@ async fn replayed_user_message_preserves_remote_image_urls() { #[tokio::test] async fn session_configured_syncs_widget_config_permissions_and_cwd() { - let (mut chat, _rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.config .permissions @@ -516,7 +516,7 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() { #[tokio::test] async fn replayed_user_message_with_only_remote_images_renders_history_cell() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let remote_image_urls = vec!["https://example.com/remote-only.png".to_string()]; @@ -569,7 +569,7 @@ async fn replayed_user_message_with_only_remote_images_renders_history_cell() { #[tokio::test] async fn replayed_user_message_with_only_local_images_does_not_render_history_cell() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let local_images = vec![PathBuf::from("/tmp/replay-local-only.png")]; @@ -619,7 +619,7 @@ async fn replayed_user_message_with_only_local_images_does_not_render_history_ce #[tokio::test] async fn forked_thread_history_line_includes_name_and_id_snapshot() { - let (chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let mut chat = chat; let temp = tempdir().expect("tempdir"); chat.config.codex_home = temp.path().to_path_buf(); @@ -645,7 +645,7 @@ async fn forked_thread_history_line_includes_name_and_id_snapshot() { }) .await .expect("timed out waiting for forked thread history"); - let combined = lines_to_single_string(&history_cell.display_lines(80)); + let combined = lines_to_single_string(&history_cell.display_lines(/*width*/ 80)); assert!( combined.contains("Thread forked from"), @@ -656,7 +656,7 @@ async fn forked_thread_history_line_includes_name_and_id_snapshot() { #[tokio::test] async fn forked_thread_history_line_without_name_shows_id_once_snapshot() { - let (chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let mut chat = chat; let temp = tempdir().expect("tempdir"); chat.config.codex_home = temp.path().to_path_buf(); @@ -676,14 +676,14 @@ async fn forked_thread_history_line_without_name_shows_id_once_snapshot() { }) .await .expect("timed out waiting for forked thread history"); - let combined = lines_to_single_string(&history_cell.display_lines(80)); + let combined = lines_to_single_string(&history_cell.display_lines(/*width*/ 80)); assert_snapshot!("forked_thread_history_line_without_name", combined); } #[tokio::test] async fn submission_preserves_text_elements_and_local_images() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -767,7 +767,7 @@ async fn submission_preserves_text_elements_and_local_images() { #[tokio::test] async fn submission_with_remote_and_local_images_keeps_local_placeholder_numbering() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -862,7 +862,7 @@ async fn submission_with_remote_and_local_images_keeps_local_placeholder_numberi #[tokio::test] async fn enter_with_only_remote_images_submits_user_turn() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -927,7 +927,7 @@ async fn enter_with_only_remote_images_submits_user_turn() { #[tokio::test] async fn shift_enter_with_only_remote_images_does_not_submit_user_turn() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -967,7 +967,7 @@ async fn shift_enter_with_only_remote_images_does_not_submit_user_turn() { #[tokio::test] async fn enter_with_only_remote_images_does_not_submit_when_modal_is_active() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -1007,7 +1007,7 @@ async fn enter_with_only_remote_images_does_not_submit_when_modal_is_active() { #[tokio::test] async fn enter_with_only_remote_images_does_not_submit_when_input_disabled() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -1050,7 +1050,7 @@ async fn enter_with_only_remote_images_does_not_submit_when_input_disabled() { #[tokio::test] async fn submission_prefers_selected_duplicate_skill_path() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); @@ -1130,7 +1130,7 @@ async fn submission_prefers_selected_duplicate_skill_path() { #[tokio::test] async fn blocked_image_restore_preserves_mention_bindings() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let placeholder = "[Image #1]"; let text = format!("{placeholder} check $file"); @@ -1184,7 +1184,7 @@ async fn blocked_image_restore_preserves_mention_bindings() { #[tokio::test] async fn blocked_image_restore_with_remote_images_keeps_local_placeholder_mapping() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let first_placeholder = "[Image #2]"; let second_placeholder = "[Image #3]"; @@ -1228,7 +1228,7 @@ async fn blocked_image_restore_with_remote_images_keeps_local_placeholder_mappin #[tokio::test] async fn queued_restore_with_remote_images_keeps_local_placeholder_mapping() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let first_placeholder = "[Image #2]"; let second_placeholder = "[Image #3]"; @@ -1272,7 +1272,7 @@ async fn queued_restore_with_remote_images_keeps_local_placeholder_mapping() { #[tokio::test] async fn interrupted_turn_restores_queued_messages_with_images_and_elements() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let first_placeholder = "[Image #1]"; let first_text = format!("{first_placeholder} first"); @@ -1371,7 +1371,7 @@ async fn interrupted_turn_restores_queued_messages_with_images_and_elements() { async fn interrupted_turn_restore_keeps_active_mode_for_resubmission() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) .expect("expected plan collaboration mode"); @@ -1492,10 +1492,10 @@ async fn remap_placeholders_uses_byte_ranges_when_placeholder_missing() { let placeholder_two = "[Image #2]"; let text = format!("{placeholder_two} before {placeholder_one}"); let elements = vec![ - TextElement::new((0..placeholder_two.len()).into(), None), + TextElement::new((0..placeholder_two.len()).into(), /*placeholder*/ None), TextElement::new( ("[Image #2] before ".len().."[Image #2] before [Image #1]".len()).into(), - None, + /*placeholder*/ None, ), ]; @@ -1551,7 +1551,7 @@ async fn remap_placeholders_uses_byte_ranges_when_placeholder_missing() { /// Entering review mode uses the hint provided by the review request. #[tokio::test] async fn entered_review_mode_uses_request_hint() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "review-start".into(), @@ -1572,7 +1572,7 @@ async fn entered_review_mode_uses_request_hint() { /// Entering review mode renders the current changes banner when requested. #[tokio::test] async fn entered_review_mode_defaults_to_current_changes_banner() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "review-start".into(), @@ -1590,7 +1590,7 @@ async fn entered_review_mode_defaults_to_current_changes_banner() { #[tokio::test] async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.handle_codex_event(Event { id: "turn-start".into(), @@ -1715,7 +1715,7 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages #[tokio::test] async fn live_agent_message_renders_during_review_mode() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "review-start".into(), @@ -1742,7 +1742,7 @@ async fn live_agent_message_renders_during_review_mode() { #[tokio::test] async fn thread_snapshot_replay_preserves_agent_message_during_review_mode() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event_replay(Event { id: "review-start".into(), @@ -1770,7 +1770,7 @@ async fn thread_snapshot_replay_preserves_agent_message_during_review_mode() { /// Exiting review restores the pre-review context window indicator. #[tokio::test] async fn review_restores_context_window_indicator() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let context_window = 13_000; let pre_review_tokens = 12_700; // ~30% remaining after subtracting baseline. @@ -1819,7 +1819,7 @@ async fn review_restores_context_window_indicator() { /// Receiving a TokenCount event without usage clears the context indicator. #[tokio::test] async fn token_count_none_resets_context_indicator() { - let (mut chat, _rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let context_window = 13_000; let pre_compact_tokens = 12_700; @@ -1880,7 +1880,7 @@ async fn context_indicator_shows_used_tokens_when_window_unknown() { #[tokio::test] async fn turn_started_uses_runtime_context_window_before_first_token_count() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.model_context_window = Some(1_000_000); @@ -1966,11 +1966,11 @@ fn test_session_telemetry(config: &Config, model: &str) -> SessionTelemetry { ThreadId::new(), model, model_info.slug.as_str(), - None, - None, - None, + /*account_id*/ None, + /*account_email*/ None, + /*auth_mode*/ None, "test_originator".to_string(), - false, + /*log_user_prompts*/ false, "test".to_string(), SessionSource::Cli, ) @@ -2018,7 +2018,7 @@ async fn make_chatwidget_manual( animations_enabled: cfg.animations, skills: None, }); - bottom.set_collaboration_modes_enabled(true); + bottom.set_collaboration_modes_enabled(/*enabled*/ true); let model_catalog = test_model_catalog(&cfg); let reasoning_effort = None; let base_mode = CollaborationMode { @@ -2193,7 +2193,7 @@ pub(crate) fn set_chatgpt_auth(chat: &mut ChatWidget) { #[tokio::test] async fn prefetch_rate_limits_is_gated_on_chatgpt_auth_provider() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; assert!(!chat.should_prefetch_rate_limits()); @@ -2209,12 +2209,12 @@ async fn prefetch_rate_limits_is_gated_on_chatgpt_auth_provider() { #[tokio::test] async fn worked_elapsed_from_resets_when_timer_restarts() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - assert_eq!(chat.worked_elapsed_from(5), 5); - assert_eq!(chat.worked_elapsed_from(9), 4); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + assert_eq!(chat.worked_elapsed_from(/*current_elapsed*/ 5), 5); + assert_eq!(chat.worked_elapsed_from(/*current_elapsed*/ 9), 4); // Simulate status timer resetting (e.g., status indicator recreated for a new task). - assert_eq!(chat.worked_elapsed_from(3), 3); - assert_eq!(chat.worked_elapsed_from(7), 4); + assert_eq!(chat.worked_elapsed_from(/*current_elapsed*/ 3), 3); + assert_eq!(chat.worked_elapsed_from(/*current_elapsed*/ 7), 4); } pub(crate) async fn make_chatwidget_manual_with_sender() -> ( @@ -2223,7 +2223,7 @@ pub(crate) async fn make_chatwidget_manual_with_sender() -> ( tokio::sync::mpsc::UnboundedReceiver, tokio::sync::mpsc::UnboundedReceiver, ) { - let (widget, rx, op_rx) = make_chatwidget_manual(None).await; + let (widget, rx, op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let app_event_tx = widget.app_event_tx.clone(); (widget, app_event_tx, rx, op_rx) } @@ -2234,7 +2234,7 @@ fn drain_insert_history( let mut out = Vec::new(); while let Ok(ev) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = ev { - let mut lines = cell.display_lines(80); + let mut lines = cell.display_lines(/*width*/ 80); if !cell.is_stream_continuation() && !out.is_empty() && !lines.is_empty() { lines.insert(0, "".into()); } @@ -2257,7 +2257,7 @@ fn lines_to_single_string(lines: &[ratatui::text::Line<'static>]) -> String { #[tokio::test] async fn collab_spawn_end_shows_requested_model_and_effort() { - let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _ops) = make_chatwidget_manual(/*model_override*/ None).await; let sender_thread_id = ThreadId::new(); let spawned_thread_id = ThreadId::new(); @@ -2355,7 +2355,12 @@ async fn test_rate_limit_warnings_monthly() { let mut state = RateLimitWarningState::default(); let mut warnings: Vec = Vec::new(); - warnings.extend(state.take_warnings(Some(75.0), Some(43199), None, None)); + warnings.extend(state.take_warnings( + Some(75.0), + Some(43199), + /*primary_used_percent*/ None, + /*primary_window_minutes*/ None, + )); assert_eq!( warnings, vec![String::from( @@ -2367,7 +2372,7 @@ async fn test_rate_limit_warnings_monthly() { #[tokio::test] async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_rate_limit_snapshot(Some(RateLimitSnapshot { limit_id: None, @@ -2420,7 +2425,7 @@ async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() { #[tokio::test] async fn rate_limit_snapshot_updates_and_retains_plan_type() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_rate_limit_snapshot(Some(RateLimitSnapshot { limit_id: None, @@ -2479,7 +2484,7 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() { #[tokio::test] async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_rate_limit_snapshot(Some(RateLimitSnapshot { limit_id: Some("codex".to_string()), @@ -2537,7 +2542,7 @@ async fn rate_limit_switch_prompt_skips_when_on_lower_cost_model() { let (mut chat, _, _) = make_chatwidget_manual(Some(NUDGE_MODEL_SLUG)).await; chat.has_chatgpt_account = true; - chat.on_rate_limit_snapshot(Some(snapshot(95.0))); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 95.0))); assert!(matches!( chat.rate_limit_switch_prompt, @@ -2574,7 +2579,7 @@ async fn rate_limit_switch_prompt_shows_once_per_session() { let (mut chat, _, _) = make_chatwidget_manual(Some("gpt-5")).await; chat.has_chatgpt_account = true; - chat.on_rate_limit_snapshot(Some(snapshot(90.0))); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 90.0))); assert!( chat.rate_limit_warnings.primary_index >= 1, "warnings not emitted" @@ -2585,7 +2590,7 @@ async fn rate_limit_switch_prompt_shows_once_per_session() { RateLimitSwitchPromptState::Shown )); - chat.on_rate_limit_snapshot(Some(snapshot(95.0))); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 95.0))); assert!(matches!( chat.rate_limit_switch_prompt, RateLimitSwitchPromptState::Shown @@ -2598,7 +2603,7 @@ async fn rate_limit_switch_prompt_respects_hidden_notice() { chat.has_chatgpt_account = true; chat.config.notices.hide_rate_limit_model_nudge = Some(true); - chat.on_rate_limit_snapshot(Some(snapshot(95.0))); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 95.0))); assert!(matches!( chat.rate_limit_switch_prompt, @@ -2611,14 +2616,14 @@ async fn rate_limit_switch_prompt_defers_until_task_complete() { let (mut chat, _, _) = make_chatwidget_manual(Some("gpt-5")).await; chat.has_chatgpt_account = true; - chat.bottom_pane.set_task_running(true); - chat.on_rate_limit_snapshot(Some(snapshot(90.0))); + chat.bottom_pane.set_task_running(/*running*/ true); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 90.0))); assert!(matches!( chat.rate_limit_switch_prompt, RateLimitSwitchPromptState::Pending )); - chat.bottom_pane.set_task_running(false); + chat.bottom_pane.set_task_running(/*running*/ false); chat.maybe_show_pending_rate_limit_prompt(); assert!(matches!( chat.rate_limit_switch_prompt, @@ -2631,10 +2636,10 @@ async fn rate_limit_switch_prompt_popup_snapshot() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.has_chatgpt_account = true; - chat.on_rate_limit_snapshot(Some(snapshot(92.0))); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 92.0))); chat.maybe_show_pending_rate_limit_prompt(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("rate_limit_switch_prompt_popup", popup); } @@ -2643,7 +2648,7 @@ async fn plan_implementation_popup_snapshot() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.open_plan_implementation_prompt(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("plan_implementation_popup", popup); } @@ -2653,7 +2658,7 @@ async fn plan_implementation_popup_no_selected_snapshot() { chat.open_plan_implementation_prompt(); chat.handle_key_event(KeyEvent::from(KeyCode::Down)); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("plan_implementation_popup_no_selected", popup); } @@ -2680,7 +2685,7 @@ async fn plan_implementation_popup_yes_emits_submit_message_event() { async fn submit_user_message_with_mode_sets_coding_collaboration_mode() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let default_mode = collaboration_modes::default_mode_mask(chat.model_catalog.as_ref()) .expect("expected default collaboration mode"); @@ -2706,7 +2711,7 @@ async fn submit_user_message_with_mode_sets_coding_collaboration_mode() { async fn reasoning_selection_in_plan_mode_opens_scope_prompt_event() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1-codex-max")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) .expect("expected plan collaboration mode"); chat.set_collaboration_mask(plan_mask); @@ -2733,7 +2738,7 @@ async fn reasoning_selection_in_plan_mode_opens_scope_prompt_event() { async fn reasoning_selection_in_plan_mode_without_effort_change_does_not_open_scope_prompt_event() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1-codex-max")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) .expect("expected plan collaboration mode"); chat.set_collaboration_mask(plan_mask); @@ -2768,7 +2773,7 @@ async fn reasoning_selection_in_plan_mode_matching_plan_effort_but_different_glo { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1-codex-max")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) .expect("expected plan collaboration mode"); chat.set_collaboration_mask(plan_mask); @@ -2797,7 +2802,7 @@ async fn reasoning_selection_in_plan_mode_matching_plan_effort_but_different_glo #[tokio::test] async fn plan_mode_reasoning_override_is_marked_current_in_reasoning_popup() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1-codex-max")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); set_chatgpt_auth(&mut chat); chat.set_reasoning_effort(Some(ReasoningEffortConfig::High)); chat.set_plan_mode_reasoning_effort(Some(ReasoningEffortConfig::Low)); @@ -2809,7 +2814,7 @@ async fn plan_mode_reasoning_override_is_marked_current_in_reasoning_popup() { let preset = get_available_model(&chat, "gpt-5.1-codex-max"); chat.open_reasoning_popup(preset); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert!(popup.contains("Low (current)")); assert!( !popup.contains("High (current)"), @@ -2821,7 +2826,7 @@ async fn plan_mode_reasoning_override_is_marked_current_in_reasoning_popup() { async fn reasoning_selection_in_plan_mode_model_switch_does_not_open_scope_prompt_event() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1-codex-max")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) .expect("expected plan collaboration mode"); chat.set_collaboration_mask(plan_mask); @@ -3036,7 +3041,7 @@ async fn plan_reasoning_scope_popup_mentions_selected_reasoning() { Some(ReasoningEffortConfig::Medium), ); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert!(popup.contains("Choose where to apply medium reasoning.")); assert!(popup.contains("Always use medium reasoning in Plan mode.")); assert!(popup.contains("Apply to Plan mode override")); @@ -3052,7 +3057,7 @@ async fn plan_reasoning_scope_popup_mentions_built_in_plan_default_when_no_overr Some(ReasoningEffortConfig::Medium), ); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert!(popup.contains("built-in Plan default (medium)")); } @@ -3086,7 +3091,7 @@ async fn plan_reasoning_scope_popup_plan_only_does_not_update_all_modes_reasonin async fn submit_user_message_with_mode_errors_when_mode_changes_during_running_turn() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3112,7 +3117,7 @@ async fn submit_user_message_with_mode_errors_when_mode_changes_during_running_t #[tokio::test] async fn submit_user_message_blocks_when_thread_model_is_unavailable() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.set_model(""); chat.bottom_pane @@ -3136,7 +3141,7 @@ async fn submit_user_message_blocks_when_thread_model_is_unavailable() { async fn submit_user_message_with_mode_allows_same_mode_during_running_turn() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask.clone()); @@ -3166,7 +3171,7 @@ async fn submit_user_message_with_mode_allows_same_mode_during_running_turn() { async fn submit_user_message_with_mode_submits_when_plan_stream_is_not_active() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3195,7 +3200,7 @@ async fn submit_user_message_with_mode_submits_when_plan_stream_is_not_active() #[tokio::test] async fn plan_implementation_popup_skips_replayed_turn_complete() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3205,7 +3210,7 @@ async fn plan_implementation_popup_skips_replayed_turn_complete() { last_agent_message: Some("Plan details".to_string()), })]); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no plan popup for replayed turn, got {popup:?}" @@ -3215,7 +3220,7 @@ async fn plan_implementation_popup_skips_replayed_turn_complete() { #[tokio::test] async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_complete() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3228,7 +3233,7 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com turn_id: "turn-1".to_string(), last_agent_message: Some("Plan details".to_string()), })]); - let replay_popup = render_bottom_popup(&chat, 80); + let replay_popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !replay_popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no prompt for replayed turn completion, got {replay_popup:?}" @@ -3242,14 +3247,14 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com }), }); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected prompt for first live turn completion after replay, got {popup:?}" ); chat.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - let dismissed_popup = render_bottom_popup(&chat, 80); + let dismissed_popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !dismissed_popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected prompt to dismiss on Esc, got {dismissed_popup:?}" @@ -3262,7 +3267,7 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com last_agent_message: Some("Plan details".to_string()), }), }); - let duplicate_popup = render_bottom_popup(&chat, 80); + let duplicate_popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !duplicate_popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no prompt for duplicate live completion, got {duplicate_popup:?}" @@ -3292,16 +3297,16 @@ async fn replayed_thread_rollback_emits_ordered_app_event() { #[tokio::test] async fn plan_implementation_popup_skips_when_messages_queued() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); chat.queue_user_message("Queued message".into()); - chat.on_task_complete(Some("Plan details".to_string()), false); + chat.on_task_complete(Some("Plan details".to_string()), /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no plan popup with queued messages, got {popup:?}" @@ -3311,7 +3316,7 @@ async fn plan_implementation_popup_skips_when_messages_queued() { #[tokio::test] async fn plan_implementation_popup_skips_without_proposed_plan() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3324,9 +3329,9 @@ async fn plan_implementation_popup_skips_without_proposed_plan() { status: StepStatus::Pending, }], }); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no plan popup without proposed plan output, got {popup:?}" @@ -3336,7 +3341,7 @@ async fn plan_implementation_popup_skips_without_proposed_plan() { #[tokio::test] async fn plan_implementation_popup_shows_after_proposed_plan_output() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3344,9 +3349,9 @@ async fn plan_implementation_popup_shows_after_proposed_plan_output() { chat.on_task_started(); chat.on_plan_delta("- Step 1\n- Step 2\n".to_string()); chat.on_plan_item_completed("- Step 1\n- Step 2\n".to_string()); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected plan popup after proposed plan output, got {popup:?}" @@ -3356,7 +3361,7 @@ async fn plan_implementation_popup_shows_after_proposed_plan_output() { #[tokio::test] async fn plan_implementation_popup_skips_when_steer_follows_proposed_plan() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3385,9 +3390,9 @@ async fn plan_implementation_popup_skips_when_steer_follows_proposed_plan() { } complete_user_message(&mut chat, "user-1", "Please continue."); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected no plan popup after a steer follows the plan, got {popup:?}" @@ -3397,7 +3402,7 @@ async fn plan_implementation_popup_skips_when_steer_follows_proposed_plan() { #[tokio::test] async fn plan_implementation_popup_shows_after_new_plan_follows_steer() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3430,9 +3435,9 @@ async fn plan_implementation_popup_shows_after_new_plan_follows_steer() { " .to_string(), ); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains(PLAN_IMPLEMENTATION_TITLE), "expected plan popup after a newer plan follows the steer, got {popup:?}" @@ -3443,7 +3448,7 @@ async fn plan_implementation_popup_shows_after_new_plan_follows_steer() { async fn plan_implementation_popup_skips_when_rate_limit_prompt_pending() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; chat.has_chatgpt_account = true; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -3456,10 +3461,10 @@ async fn plan_implementation_popup_skips_when_rate_limit_prompt_pending() { status: StepStatus::Pending, }], }); - chat.on_rate_limit_snapshot(Some(snapshot(92.0))); - chat.on_task_complete(None, false); + chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 92.0))); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Approaching rate limits"), "expected rate limit popup, got {popup:?}" @@ -3474,7 +3479,7 @@ async fn plan_implementation_popup_skips_when_rate_limit_prompt_pending() { #[tokio::test] async fn exec_approval_emits_proposed_command_and_decision_history() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Trigger an exec approval request with a short, single-line command let ev = ExecApprovalRequestEvent { @@ -3505,7 +3510,7 @@ async fn exec_approval_emits_proposed_command_and_decision_history() { ); // The approval modal should display the command snippet for user confirmation. - let area = Rect::new(0, 0, 80, chat.desired_height(80)); + let area = Rect::new(0, 0, 80, chat.desired_height(/*width*/ 80)); let mut buf = ratatui::buffer::Buffer::empty(area); chat.render(area, &mut buf); assert_snapshot!("exec_approval_modal_exec", format!("{buf:?}")); @@ -3556,7 +3561,7 @@ fn app_server_exec_approval_request_splits_shell_wrapped_command() { #[tokio::test] async fn exec_approval_uses_approval_id_when_present() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "sub-short".into(), @@ -3598,7 +3603,7 @@ async fn exec_approval_uses_approval_id_when_present() { #[tokio::test] async fn exec_approval_decision_truncates_multiline_and_long_commands() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Multiline command: modal should show full command, history records decision only let ev_multi = ExecApprovalRequestEvent { @@ -3627,7 +3632,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() { "expected multiline approval request to render via modal without emitting history cells" ); - let area = Rect::new(0, 0, 80, chat.desired_height(80)); + let area = Rect::new(0, 0, 80, chat.desired_height(/*width*/ 80)); let mut buf = ratatui::buffer::Buffer::empty(area); chat.render(area, &mut buf); let mut saw_first_line = false; @@ -3873,7 +3878,7 @@ fn active_blob(chat: &ChatWidget) -> String { .active_cell .as_ref() .expect("active cell present") - .display_lines(80); + .display_lines(/*width*/ 80); lines_to_single_string(&lines) } @@ -3891,10 +3896,10 @@ fn get_available_model(chat: &ChatWidget, model: &str) -> ModelPreset { #[tokio::test] async fn empty_enter_during_task_does_not_queue() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Simulate running task so submissions would normally be queued. - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); // Press Enter with an empty composer. chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); @@ -3905,8 +3910,8 @@ async fn empty_enter_during_task_does_not_queue() { #[tokio::test] async fn restore_thread_input_state_syncs_sleep_inhibitor_state() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::PreventIdleSleep, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::PreventIdleSleep, /*enabled*/ true); chat.restore_thread_input_state(Some(ThreadInputState { composer: None, @@ -3923,7 +3928,7 @@ async fn restore_thread_input_state_syncs_sleep_inhibitor_state() { assert!(chat.turn_sleep_inhibitor.is_turn_running()); assert!(chat.bottom_pane.is_task_running()); - chat.restore_thread_input_state(None); + chat.restore_thread_input_state(/*input_state*/ None); assert!(!chat.agent_turn_running); assert!(!chat.turn_sleep_inhibitor.is_turn_running()); @@ -3932,7 +3937,7 @@ async fn restore_thread_input_state_syncs_sleep_inhibitor_state() { #[tokio::test] async fn restore_thread_input_state_restores_pending_steers_without_downgrading_them() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let mut pending_steers = VecDeque::new(); pending_steers.push_back(UserMessage::from("pending steer")); let mut rejected_steers_queue = VecDeque::new(); @@ -3964,13 +3969,13 @@ async fn restore_thread_input_state_restores_pending_steers_without_downgrading_ #[tokio::test] async fn alt_up_edits_most_recent_queued_message() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.queued_message_edit_binding = crate::key_hint::alt(KeyCode::Up); chat.bottom_pane .set_queued_message_edit_binding(crate::key_hint::alt(KeyCode::Up)); // Simulate a running task so messages would normally be queued. - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); // Seed two queued messages. chat.queued_user_messages @@ -3998,13 +4003,13 @@ async fn alt_up_edits_most_recent_queued_message() { async fn assert_shift_left_edits_most_recent_queued_message_for_terminal( terminal_info: TerminalInfo, ) { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.queued_message_edit_binding = queued_message_edit_binding_for_terminal(terminal_info); chat.bottom_pane .set_queued_message_edit_binding(chat.queued_message_edit_binding); // Simulate a running task so messages would normally be queued. - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); // Seed two queued messages. chat.queued_user_messages @@ -4136,7 +4141,7 @@ fn queued_message_edit_binding_mapping_covers_special_terminals_and_tmux() { /// is queued repeatedly. #[tokio::test] async fn enqueueing_history_prompt_multiple_times_is_stable() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); // Submit an initial prompt to seed history. @@ -4145,7 +4150,7 @@ async fn enqueueing_history_prompt_multiple_times_is_stable() { chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); // Simulate an active task so further submissions are queued. - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); for _ in 0..3 { // Recall the prompt from history and ensure it is what we expect. @@ -4164,7 +4169,7 @@ async fn enqueueing_history_prompt_multiple_times_is_stable() { #[tokio::test] async fn streaming_final_answer_keeps_task_running_state() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); @@ -4196,7 +4201,7 @@ async fn streaming_final_answer_keeps_task_running_state() { #[tokio::test] async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); assert_eq!(chat.bottom_pane.status_indicator_visible(), true); @@ -4215,7 +4220,7 @@ async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion() #[tokio::test] async fn commentary_completion_restores_status_indicator_before_exec_begin() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); assert_eq!(chat.bottom_pane.status_indicator_visible(), true); @@ -4242,8 +4247,8 @@ async fn commentary_completion_restores_status_indicator_before_exec_begin() { #[tokio::test] async fn plan_completion_restores_status_indicator_after_streaming_plan_output() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -4266,7 +4271,7 @@ async fn plan_completion_restores_status_indicator_after_streaming_plan_output() #[tokio::test] async fn preamble_keeps_working_status_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); // Regression sequence: a preamble line is committed to history before any exec/tool event. @@ -4282,7 +4287,7 @@ async fn preamble_keeps_working_status_snapshot() { Some(MessagePhase::Commentary), ); - let height = chat.desired_height(80); + let height = chat.desired_height(/*width*/ 80); let mut terminal = ratatui::Terminal::new(ratatui::backend::TestBackend::new(80, height)) .expect("create terminal"); terminal @@ -4293,7 +4298,7 @@ async fn preamble_keeps_working_status_snapshot() { #[tokio::test] async fn unified_exec_begin_restores_status_indicator_after_preamble() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); assert_eq!(chat.bottom_pane.status_indicator_visible(), true); @@ -4310,7 +4315,7 @@ async fn unified_exec_begin_restores_status_indicator_after_preamble() { #[tokio::test] async fn unified_exec_begin_restores_working_status_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); chat.on_agent_message_delta("Preamble line\n".to_string()); @@ -4335,9 +4340,9 @@ async fn unified_exec_begin_restores_working_status_snapshot() { #[tokio::test] async fn steer_enter_queues_while_plan_stream_is_active() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -4362,7 +4367,7 @@ async fn steer_enter_queues_while_plan_stream_is_active() { #[tokio::test] async fn submit_user_message_queues_while_compaction_turn_is_running() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let thread_id = ThreadId::new(); chat.thread_id = Some(thread_id); chat.handle_server_notification( @@ -4375,7 +4380,7 @@ async fn submit_user_message_queues_while_compaction_turn_is_running() { error: None, }, }), - None, + /*replay_kind*/ None, ); chat.submit_user_message(UserMessage::from("queued while compacting")); @@ -4418,7 +4423,7 @@ async fn submit_user_message_queues_while_compaction_turn_is_running() { error: None, }, }), - None, + /*replay_kind*/ None, ); match next_submit_op(&mut op_rx) { @@ -4435,7 +4440,7 @@ async fn submit_user_message_queues_while_compaction_turn_is_running() { #[tokio::test] async fn slash_compact_eagerly_queues_follow_up_before_turn_start() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Compact); @@ -4463,7 +4468,7 @@ async fn slash_compact_eagerly_queues_follow_up_before_turn_start() { #[tokio::test] async fn steer_enter_uses_pending_steers_while_turn_is_running_without_streaming() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); @@ -4493,7 +4498,7 @@ async fn steer_enter_uses_pending_steers_while_turn_is_running_without_streaming #[tokio::test] async fn steer_enter_uses_pending_steers_while_final_answer_stream_is_active() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); // Keep the assistant stream open (no commit tick/finalize) to model the repro window: @@ -4529,7 +4534,7 @@ async fn steer_enter_uses_pending_steers_while_final_answer_stream_is_active() { #[tokio::test] async fn failed_pending_steer_submit_does_not_add_pending_preview() { - let (mut chat, mut rx, op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); drop(op_rx); @@ -4548,7 +4553,7 @@ async fn failed_pending_steer_submit_does_not_add_pending_preview() { #[tokio::test] async fn live_legacy_agent_message_after_item_completed_does_not_duplicate_assistant_message() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; complete_assistant_message( &mut chat, @@ -4574,7 +4579,7 @@ async fn live_legacy_agent_message_after_item_completed_does_not_duplicate_assis #[tokio::test] async fn live_app_server_user_message_item_completed_does_not_duplicate_rendered_prompt() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.bottom_pane @@ -4602,7 +4607,7 @@ async fn live_app_server_user_message_item_completed_does_not_duplicate_rendered }], }, }), - None, + /*replay_kind*/ None, ); assert!(drain_insert_history(&mut rx).is_empty()); @@ -4610,7 +4615,7 @@ async fn live_app_server_user_message_item_completed_does_not_duplicate_rendered #[tokio::test] async fn live_app_server_turn_completed_clears_working_status_after_answer_item() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::TurnStarted(TurnStartedNotification { @@ -4622,7 +4627,7 @@ async fn live_app_server_turn_completed_clears_working_status_after_answer_item( error: None, }, }), - None, + /*replay_kind*/ None, ); assert!(chat.bottom_pane.is_task_running()); @@ -4643,7 +4648,7 @@ async fn live_app_server_turn_completed_clears_working_status_after_answer_item( memory_citation: None, }, }), - None, + /*replay_kind*/ None, ); let cells = drain_insert_history(&mut rx); @@ -4661,7 +4666,7 @@ async fn live_app_server_turn_completed_clears_working_status_after_answer_item( error: None, }, }), - None, + /*replay_kind*/ None, ); assert!(!chat.bottom_pane.is_task_running()); @@ -4670,7 +4675,7 @@ async fn live_app_server_turn_completed_clears_working_status_after_answer_item( #[tokio::test] async fn live_app_server_file_change_item_started_preserves_changes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::ItemStarted(ItemStartedNotification { @@ -4686,7 +4691,7 @@ async fn live_app_server_file_change_item_started_preserves_changes() { status: AppServerPatchApplyStatus::InProgress, }, }), - None, + /*replay_kind*/ None, ); let cells = drain_insert_history(&mut rx); @@ -4700,7 +4705,7 @@ async fn live_app_server_file_change_item_started_preserves_changes() { #[tokio::test] async fn live_app_server_command_execution_strips_shell_wrapper() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let script = r#"python3 -c 'print("Hello, world!")'"#; let command = shlex::try_join(["/bin/zsh", "-lc", script]).expect("round-trippable shell wrapper"); @@ -4724,7 +4729,7 @@ async fn live_app_server_command_execution_strips_shell_wrapper() { duration_ms: None, }, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( ServerNotification::ItemCompleted(ItemCompletedNotification { @@ -4745,7 +4750,7 @@ async fn live_app_server_command_execution_strips_shell_wrapper() { duration_ms: Some(5), }, }), - None, + /*replay_kind*/ None, ); let cells = drain_insert_history(&mut rx); @@ -4782,7 +4787,7 @@ fn app_server_patch_changes_to_core_preserves_diffs() { #[tokio::test] async fn live_app_server_collab_wait_items_render_history() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let sender_thread_id = ThreadId::from_string("019cff70-2599-75e2-af72-b90000000001").expect("valid thread id"); let receiver_thread_id = @@ -4819,7 +4824,7 @@ async fn live_app_server_collab_wait_items_render_history() { agents_states: HashMap::new(), }, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( @@ -4856,7 +4861,7 @@ async fn live_app_server_collab_wait_items_render_history() { ]), }, }), - None, + /*replay_kind*/ None, ); let combined = drain_insert_history(&mut rx) @@ -4869,7 +4874,7 @@ async fn live_app_server_collab_wait_items_render_history() { #[tokio::test] async fn live_app_server_collab_spawn_completed_renders_requested_model_and_effort() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let sender_thread_id = ThreadId::from_string("019cff70-2599-75e2-af72-b90000000002").expect("valid thread id"); let spawned_thread_id = @@ -4891,7 +4896,7 @@ async fn live_app_server_collab_spawn_completed_renders_requested_model_and_effo agents_states: HashMap::new(), }, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( @@ -4916,7 +4921,7 @@ async fn live_app_server_collab_spawn_completed_renders_requested_model_and_effo )]), }, }), - None, + /*replay_kind*/ None, ); let combined = drain_insert_history(&mut rx) @@ -4932,7 +4937,7 @@ async fn live_app_server_collab_spawn_completed_renders_requested_model_and_effo #[tokio::test] async fn live_app_server_failed_turn_does_not_duplicate_error_history() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::TurnStarted(TurnStartedNotification { @@ -4944,7 +4949,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() { error: None, }, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( @@ -4958,7 +4963,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), }), - None, + /*replay_kind*/ None, ); let first_cells = drain_insert_history(&mut rx); @@ -4979,7 +4984,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() { }), }, }), - None, + /*replay_kind*/ None, ); assert!(drain_insert_history(&mut rx).is_empty()); @@ -4988,7 +4993,7 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() { #[tokio::test] async fn replayed_retryable_app_server_error_keeps_turn_running() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::TurnStarted(TurnStartedNotification { @@ -5030,7 +5035,7 @@ async fn replayed_retryable_app_server_error_keeps_turn_running() { #[tokio::test] async fn live_app_server_stream_recovery_restores_previous_status_header() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::TurnStarted(TurnStartedNotification { @@ -5042,7 +5047,7 @@ async fn live_app_server_stream_recovery_restores_previous_status_header() { error: None, }, }), - None, + /*replay_kind*/ None, ); drain_insert_history(&mut rx); @@ -5057,7 +5062,7 @@ async fn live_app_server_stream_recovery_restores_previous_status_header() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), }), - None, + /*replay_kind*/ None, ); drain_insert_history(&mut rx); @@ -5070,7 +5075,7 @@ async fn live_app_server_stream_recovery_restores_previous_status_header() { delta: "hello".to_string(), }, ), - None, + /*replay_kind*/ None, ); let status = chat @@ -5084,7 +5089,7 @@ async fn live_app_server_stream_recovery_restores_previous_status_header() { #[tokio::test] async fn live_app_server_server_overloaded_error_renders_warning() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::TurnStarted(TurnStartedNotification { @@ -5096,7 +5101,7 @@ async fn live_app_server_server_overloaded_error_renders_warning() { error: None, }, }), - None, + /*replay_kind*/ None, ); drain_insert_history(&mut rx); @@ -5111,7 +5116,7 @@ async fn live_app_server_server_overloaded_error_renders_warning() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), }), - None, + /*replay_kind*/ None, ); let cells = drain_insert_history(&mut rx); @@ -5122,7 +5127,7 @@ async fn live_app_server_server_overloaded_error_renders_warning() { #[tokio::test] async fn live_app_server_invalid_thread_name_update_is_ignored() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let thread_id = ThreadId::new(); chat.thread_id = Some(thread_id); chat.thread_name = Some("original name".to_string()); @@ -5134,7 +5139,7 @@ async fn live_app_server_invalid_thread_name_update_is_ignored() { thread_name: Some("bad update".to_string()), }, ), - None, + /*replay_kind*/ None, ); assert_eq!(chat.thread_id, Some(thread_id)); @@ -5143,13 +5148,13 @@ async fn live_app_server_invalid_thread_name_update_is_ignored() { #[tokio::test] async fn live_app_server_thread_closed_requests_immediate_exit() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::ThreadClosed(ThreadClosedNotification { thread_id: "thread-1".to_string(), }), - None, + /*replay_kind*/ None, ); assert_matches!(rx.try_recv(), Ok(AppEvent::Exit(ExitMode::Immediate))); @@ -5157,7 +5162,7 @@ async fn live_app_server_thread_closed_requests_immediate_exit() { #[tokio::test] async fn replayed_thread_closed_notification_does_not_exit_tui() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::ThreadClosed(ThreadClosedNotification { @@ -5171,7 +5176,7 @@ async fn replayed_thread_closed_notification_does_not_exit_tui() { #[tokio::test] async fn replayed_reasoning_item_hides_raw_reasoning_when_disabled() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.show_raw_agent_reasoning = false; chat.handle_codex_event(Event { id: "configured".into(), @@ -5207,7 +5212,9 @@ async fn replayed_reasoning_item_hides_raw_reasoning_when_disabled() { ); let rendered = match rx.try_recv() { - Ok(AppEvent::InsertHistoryCell(cell)) => lines_to_single_string(&cell.transcript_lines(80)), + Ok(AppEvent::InsertHistoryCell(cell)) => { + lines_to_single_string(&cell.transcript_lines(/*width*/ 80)) + } other => panic!("expected InsertHistoryCell, got {other:?}"), }; assert!(!rendered.trim().is_empty()); @@ -5216,7 +5223,7 @@ async fn replayed_reasoning_item_hides_raw_reasoning_when_disabled() { #[tokio::test] async fn replayed_reasoning_item_shows_raw_reasoning_when_enabled() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.show_raw_agent_reasoning = true; chat.handle_codex_event(Event { id: "configured".into(), @@ -5252,7 +5259,9 @@ async fn replayed_reasoning_item_shows_raw_reasoning_when_enabled() { ); let rendered = match rx.try_recv() { - Ok(AppEvent::InsertHistoryCell(cell)) => lines_to_single_string(&cell.transcript_lines(80)), + Ok(AppEvent::InsertHistoryCell(cell)) => { + lines_to_single_string(&cell.transcript_lines(/*width*/ 80)) + } other => panic!("expected InsertHistoryCell, got {other:?}"), }; assert!(rendered.contains("Raw reasoning")); @@ -5260,7 +5269,7 @@ async fn replayed_reasoning_item_shows_raw_reasoning_when_enabled() { #[tokio::test] async fn live_reasoning_summary_is_not_rendered_twice_when_item_completes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; chat.handle_server_notification( @@ -5273,7 +5282,7 @@ async fn live_reasoning_summary_is_not_rendered_twice_when_item_completes() { error: None, }, }), - None, + /*replay_kind*/ None, ); let _ = drain_insert_history(&mut rx); @@ -5285,7 +5294,7 @@ async fn live_reasoning_summary_is_not_rendered_twice_when_item_completes() { delta: "Summary only".to_string(), summary_index: 0, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( @@ -5298,11 +5307,13 @@ async fn live_reasoning_summary_is_not_rendered_twice_when_item_completes() { content: Vec::new(), }, }), - None, + /*replay_kind*/ None, ); let rendered = match rx.try_recv() { - Ok(AppEvent::InsertHistoryCell(cell)) => lines_to_single_string(&cell.transcript_lines(80)), + Ok(AppEvent::InsertHistoryCell(cell)) => { + lines_to_single_string(&cell.transcript_lines(/*width*/ 80)) + } other => panic!("expected InsertHistoryCell, got {other:?}"), }; assert_eq!(rendered.matches("Summary only").count(), 1); @@ -5314,7 +5325,7 @@ fn rendered_user_message_event_from_inputs_matches_flattened_user_message_shape( let rendered = ChatWidget::rendered_user_message_event_from_inputs(&[ UserInput::Text { text: "hello ".to_string(), - text_elements: vec![TextElement::new((0..5).into(), None)], + text_elements: vec![TextElement::new((0..5).into(), /*placeholder*/ None)], }, UserInput::Image { image_url: "https://example.com/remote.png".to_string(), @@ -5352,7 +5363,7 @@ fn rendered_user_message_event_from_inputs_matches_flattened_user_message_shape( #[tokio::test] async fn item_completed_only_pops_front_pending_steer() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.pending_steers.push_back(pending_steer("first")); chat.pending_steers.push_back(pending_steer("second")); chat.refresh_pending_input_preview(); @@ -5382,7 +5393,7 @@ async fn item_completed_only_pops_front_pending_steer() { #[tokio::test(flavor = "multi_thread")] async fn item_completed_pops_pending_steer_with_local_image_and_text_elements() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); @@ -5465,7 +5476,7 @@ async fn item_completed_pops_pending_steer_with_local_image_and_text_elements() #[tokio::test(flavor = "multi_thread")] async fn submit_user_message_emits_structured_plugin_mentions_from_bindings() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); let configured = codex_protocol::protocol::SessionConfiguredEvent { @@ -5490,7 +5501,7 @@ async fn submit_user_message_emits_structured_plugin_mentions_from_bindings() { id: "initial".into(), msg: EventMsg::SessionConfigured(configured), }); - chat.set_feature_enabled(Feature::Plugins, true); + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); chat.bottom_pane.set_plugin_mentions(Some(vec![ codex_core::plugins::PluginCapabilitySummary { config_name: "sample@test".to_string(), @@ -5533,7 +5544,7 @@ async fn submit_user_message_emits_structured_plugin_mentions_from_bindings() { #[tokio::test] async fn steer_enter_during_final_stream_preserves_follow_up_prompts_in_order() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); // Simulate "dead mode" repro timing by keeping a final-answer stream active while the @@ -5603,7 +5614,7 @@ async fn steer_enter_during_final_stream_preserves_follow_up_prompts_in_order() #[tokio::test] async fn manual_interrupt_restores_pending_steers_to_composer() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); chat.on_agent_message_delta( @@ -5648,7 +5659,7 @@ async fn manual_interrupt_restores_pending_steers_to_composer() { #[tokio::test] async fn esc_interrupt_sends_all_pending_steers_immediately_and_keeps_existing_draft() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); chat.on_agent_message_delta("Final answer line\n".to_string()); @@ -5727,7 +5738,7 @@ async fn esc_interrupt_sends_all_pending_steers_immediately_and_keeps_existing_d #[tokio::test] async fn esc_with_pending_steers_overrides_agent_command_interrupt_behavior() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); @@ -5749,7 +5760,7 @@ async fn esc_with_pending_steers_overrides_agent_command_interrupt_behavior() { #[tokio::test] async fn manual_interrupt_restores_pending_steer_mention_bindings_to_composer() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); chat.on_agent_message_delta("Final answer line\n".to_string()); @@ -5792,7 +5803,7 @@ async fn manual_interrupt_restores_pending_steer_mention_bindings_to_composer() #[tokio::test] async fn manual_interrupt_restores_pending_steers_before_queued_messages() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); chat.on_agent_message_delta( @@ -5834,7 +5845,7 @@ queued draft" #[tokio::test] async fn replaced_turn_clears_pending_steers_but_keeps_queued_drafts() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); chat.on_agent_message_delta( @@ -5887,9 +5898,9 @@ async fn replaced_turn_clears_pending_steers_but_keeps_queued_drafts() { #[tokio::test] async fn enter_submits_when_plan_stream_is_not_active() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -5911,7 +5922,7 @@ async fn enter_submits_when_plan_stream_is_not_active() { #[tokio::test] async fn ctrl_c_shutdown_works_with_caps_lock() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_key_event(KeyEvent::new(KeyCode::Char('C'), KeyModifiers::CONTROL)); @@ -5939,7 +5950,7 @@ async fn ctrl_c_closes_realtime_conversation_before_interrupt_or_quit() { #[tokio::test] async fn ctrl_d_quits_without_prompt() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_key_event(KeyEvent::new(KeyCode::Char('d'), KeyModifiers::CONTROL)); assert_matches!(rx.try_recv(), Ok(AppEvent::Exit(ExitMode::ShutdownFirst))); @@ -5947,7 +5958,7 @@ async fn ctrl_d_quits_without_prompt() { #[tokio::test] async fn ctrl_d_with_modal_open_does_not_quit() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.open_approvals_popup(); chat.handle_key_event(KeyEvent::new(KeyCode::Char('d'), KeyModifiers::CONTROL)); @@ -5957,7 +5968,7 @@ async fn ctrl_d_with_modal_open_does_not_quit() { #[tokio::test] async fn ctrl_c_cleared_prompt_is_recoverable_via_history() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.bottom_pane.insert_str("draft message "); chat.bottom_pane @@ -6027,7 +6038,7 @@ async fn deleted_realtime_meter_uses_shared_stop_path() { #[tokio::test] async fn exec_history_cell_shows_working_then_completed() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Begin command let begin = begin_exec(&mut chat, "call-1", "echo done"); @@ -6036,7 +6047,7 @@ async fn exec_history_cell_shows_working_then_completed() { assert_eq!(cells.len(), 0, "no exec cell should have been flushed yet"); // End command successfully - end_exec(&mut chat, begin, "done", "", 0); + end_exec(&mut chat, begin, "done", "", /*exit_code*/ 0); let cells = drain_insert_history(&mut rx); // Exec end now finalizes and flushes the exec cell immediately. @@ -6057,7 +6068,7 @@ async fn exec_history_cell_shows_working_then_completed() { #[tokio::test] async fn exec_history_cell_shows_working_then_failed() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Begin command let begin = begin_exec(&mut chat, "call-2", "false"); @@ -6065,7 +6076,7 @@ async fn exec_history_cell_shows_working_then_failed() { assert_eq!(cells.len(), 0, "no exec cell should have been flushed yet"); // End command with failure - end_exec(&mut chat, begin, "", "Bloop", 2); + end_exec(&mut chat, begin, "", "Bloop", /*exit_code*/ 2); let cells = drain_insert_history(&mut rx); // Exec end with failure should also flush immediately. @@ -6081,7 +6092,7 @@ async fn exec_history_cell_shows_working_then_failed() { #[tokio::test] async fn exec_end_without_begin_uses_event_command() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let command = vec![ "bash".to_string(), "-lc".to_string(), @@ -6125,7 +6136,7 @@ async fn exec_end_without_begin_uses_event_command() { #[tokio::test] async fn exec_end_without_begin_does_not_flush_unrelated_running_exploring_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_exec(&mut chat, "call-exploring", "cat /dev/null"); @@ -6136,7 +6147,13 @@ async fn exec_end_without_begin_does_not_flush_unrelated_running_exploring_cell( begin_unified_exec_startup(&mut chat, "call-orphan", "proc-1", "echo repro-marker"); assert!(drain_insert_history(&mut rx).is_empty()); - end_exec(&mut chat, orphan, "repro-marker\n", "", 0); + end_exec( + &mut chat, + orphan, + "repro-marker\n", + "", + /*exit_code*/ 0, + ); let cells = drain_insert_history(&mut rx); assert_eq!(cells.len(), 1, "only the orphan end should be inserted"); @@ -6162,16 +6179,16 @@ async fn exec_end_without_begin_does_not_flush_unrelated_running_exploring_cell( #[tokio::test] async fn exec_end_without_begin_flushes_completed_unrelated_exploring_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); let begin_ls = begin_exec(&mut chat, "call-ls", "ls -la"); - end_exec(&mut chat, begin_ls, "", "", 0); + end_exec(&mut chat, begin_ls, "", "", /*exit_code*/ 0); assert!(drain_insert_history(&mut rx).is_empty()); assert!(active_blob(&chat).contains("ls -la")); let orphan = begin_unified_exec_startup(&mut chat, "call-after", "proc-1", "echo after"); - end_exec(&mut chat, orphan, "after\n", "", 0); + end_exec(&mut chat, orphan, "after\n", "", /*exit_code*/ 0); let cells = drain_insert_history(&mut rx); assert_eq!( @@ -6201,13 +6218,13 @@ async fn exec_end_without_begin_flushes_completed_unrelated_exploring_cell() { #[tokio::test] async fn overlapping_exploring_exec_end_is_not_misclassified_as_orphan() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let begin_ls = begin_exec(&mut chat, "call-ls", "ls -la"); let begin_cat = begin_exec(&mut chat, "call-cat", "cat foo.txt"); assert!(drain_insert_history(&mut rx).is_empty()); - end_exec(&mut chat, begin_ls, "foo.txt\n", "", 0); + end_exec(&mut chat, begin_ls, "foo.txt\n", "", /*exit_code*/ 0); let cells = drain_insert_history(&mut rx); assert!( @@ -6228,12 +6245,12 @@ async fn overlapping_exploring_exec_end_is_not_misclassified_as_orphan() { "expected grouped exploring header to remain active: {active:?}" ); - end_exec(&mut chat, begin_cat, "hello\n", "", 0); + end_exec(&mut chat, begin_cat, "hello\n", "", /*exit_code*/ 0); } #[tokio::test] async fn exec_history_shows_unified_exec_startup_commands() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); let begin = begin_exec_with_source( @@ -6247,7 +6264,13 @@ async fn exec_history_shows_unified_exec_startup_commands() { "exec begin should not flush until completion" ); - end_exec(&mut chat, begin, "echo unified exec startup\n", "", 0); + end_exec( + &mut chat, + begin, + "echo unified exec startup\n", + "", + /*exit_code*/ 0, + ); let cells = drain_insert_history(&mut rx); assert_eq!(cells.len(), 1, "expected finalized exec cell to flush"); @@ -6260,7 +6283,7 @@ async fn exec_history_shows_unified_exec_startup_commands() { #[tokio::test] async fn exec_history_shows_unified_exec_tool_calls() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); let begin = begin_exec_with_source( @@ -6269,7 +6292,7 @@ async fn exec_history_shows_unified_exec_tool_calls() { "ls", ExecCommandSource::UnifiedExecStartup, ); - end_exec(&mut chat, begin, "", "", 0); + end_exec(&mut chat, begin, "", "", /*exit_code*/ 0); let blob = active_blob(&chat); assert_eq!(blob, "β€’ Explored\n β”” List ls\n"); @@ -6277,13 +6300,19 @@ async fn exec_history_shows_unified_exec_tool_calls() { #[tokio::test] async fn unified_exec_unknown_end_with_active_exploring_cell_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_exec(&mut chat, "call-exploring", "cat /dev/null"); let orphan = begin_unified_exec_startup(&mut chat, "call-orphan", "proc-1", "echo repro-marker"); - end_exec(&mut chat, orphan, "repro-marker\n", "", 0); + end_exec( + &mut chat, + orphan, + "repro-marker\n", + "", + /*exit_code*/ 0, + ); let cells = drain_insert_history(&mut rx); let history = cells @@ -6300,7 +6329,7 @@ async fn unified_exec_unknown_end_with_active_exploring_cell_snapshot() { #[tokio::test] async fn unified_exec_end_after_task_complete_is_suppressed() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); let begin = begin_exec_with_source( @@ -6311,8 +6340,8 @@ async fn unified_exec_end_after_task_complete_is_suppressed() { ); drain_insert_history(&mut rx); - chat.on_task_complete(None, false); - end_exec(&mut chat, begin, "", "", 0); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); + end_exec(&mut chat, begin, "", "", /*exit_code*/ 0); let cells = drain_insert_history(&mut rx); assert!( @@ -6323,9 +6352,9 @@ async fn unified_exec_end_after_task_complete_is_suppressed() { #[tokio::test] async fn unified_exec_interaction_after_task_complete_is_suppressed() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); chat.handle_codex_event(Event { id: "call-1".to_string(), @@ -6345,7 +6374,7 @@ async fn unified_exec_interaction_after_task_complete_is_suppressed() { #[tokio::test] async fn unified_exec_wait_after_final_agent_message_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), msg: EventMsg::TurnStarted(TurnStartedEvent { @@ -6358,7 +6387,7 @@ async fn unified_exec_wait_after_final_agent_message_snapshot() { begin_unified_exec_startup(&mut chat, "call-wait", "proc-1", "cargo test -p codex-core"); terminal_interaction(&mut chat, "call-wait-stdin", "proc-1", ""); - complete_assistant_message(&mut chat, "msg-1", "Final response.", None); + complete_assistant_message(&mut chat, "msg-1", "Final response.", /*phase*/ None); chat.handle_codex_event(Event { id: "turn-1".into(), msg: EventMsg::TurnComplete(TurnCompleteEvent { @@ -6377,7 +6406,7 @@ async fn unified_exec_wait_after_final_agent_message_snapshot() { #[tokio::test] async fn unified_exec_wait_before_streamed_agent_message_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), msg: EventMsg::TurnStarted(TurnStartedEvent { @@ -6419,7 +6448,7 @@ async fn unified_exec_wait_before_streamed_agent_message_snapshot() { #[tokio::test] async fn unified_exec_wait_status_header_updates_on_late_command_display() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); chat.unified_exec_processes.push(UnifiedExecProcessSummary { key: "proc-1".to_string(), @@ -6449,7 +6478,7 @@ async fn unified_exec_wait_status_header_updates_on_late_command_display() { #[tokio::test] async fn unified_exec_waiting_multiple_empty_snapshots() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_unified_exec_startup(&mut chat, "call-wait-1", "proc-1", "just fix"); @@ -6484,7 +6513,7 @@ async fn unified_exec_waiting_multiple_empty_snapshots() { #[tokio::test] async fn unified_exec_wait_status_renders_command_in_single_details_row_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_unified_exec_startup( &mut chat, @@ -6495,7 +6524,7 @@ async fn unified_exec_wait_status_renders_command_in_single_details_row_snapshot terminal_interaction(&mut chat, "call-wait-ui-stdin", "proc-ui", ""); - let rendered = render_bottom_popup(&chat, 48); + let rendered = render_bottom_popup(&chat, /*width*/ 48); assert_snapshot!( "unified_exec_wait_status_renders_command_in_single_details_row", rendered @@ -6504,7 +6533,7 @@ async fn unified_exec_wait_status_renders_command_in_single_details_row_snapshot #[tokio::test] async fn unified_exec_empty_then_non_empty_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_unified_exec_startup(&mut chat, "call-wait-2", "proc-2", "just fix"); @@ -6521,7 +6550,7 @@ async fn unified_exec_empty_then_non_empty_snapshot() { #[tokio::test] async fn unified_exec_non_empty_then_empty_snapshots() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); begin_unified_exec_startup(&mut chat, "call-wait-3", "proc-3", "just fix"); @@ -6572,7 +6601,7 @@ async fn unified_exec_non_empty_then_empty_snapshots() { /// OpenReviewCustomPrompt to the app event channel. #[tokio::test] async fn review_popup_custom_prompt_action_sends_event() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Open the preset selection popup chat.open_review_popup(); @@ -6597,7 +6626,7 @@ async fn review_popup_custom_prompt_action_sends_event() { #[tokio::test] async fn slash_init_skips_when_project_doc_exists() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let tempdir = tempdir().unwrap(); let existing_path = tempdir.path().join(DEFAULT_PROJECT_DOC_FILENAME); std::fs::write(&existing_path, "existing instructions").unwrap(); @@ -6629,7 +6658,7 @@ async fn slash_init_skips_when_project_doc_exists() { #[tokio::test] async fn collab_mode_shift_tab_cycles_only_when_idle() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let initial = chat.current_collaboration_mode().clone(); chat.handle_key_event(KeyEvent::from(KeyCode::BackTab)); @@ -6649,7 +6678,7 @@ async fn collab_mode_shift_tab_cycles_only_when_idle() { #[tokio::test] async fn mode_switch_surfaces_model_change_notification_when_effective_model_changes() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let default_model = chat.current_model().to_string(); let mut plan_mask = @@ -6688,7 +6717,7 @@ async fn mode_switch_surfaces_model_change_notification_when_effective_model_cha #[tokio::test] async fn mode_switch_surfaces_reasoning_change_notification_when_model_stays_same() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); chat.set_reasoning_effort(Some(ReasoningEffortConfig::High)); let plan_mask = collaboration_modes::plan_mask(chat.model_catalog.as_ref()) @@ -6708,12 +6737,12 @@ async fn mode_switch_surfaces_reasoning_change_notification_when_model_stays_sam #[tokio::test] async fn collab_slash_command_opens_picker_and_updates_mode() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); chat.dispatch_command(SlashCommand::Collab); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Select Collaboration Mode"), "expected collaboration picker: {popup}" @@ -6765,8 +6794,8 @@ async fn collab_slash_command_opens_picker_and_updates_mode() { #[tokio::test] async fn plan_slash_command_switches_to_plan_mode() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let initial = chat.current_collaboration_mode().clone(); chat.dispatch_command(SlashCommand::Plan); @@ -6783,8 +6812,8 @@ async fn plan_slash_command_switches_to_plan_mode() { #[tokio::test] async fn plan_slash_command_with_args_submits_prompt_in_plan_mode() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let configured = codex_protocol::protocol::SessionConfiguredEvent { session_id: ThreadId::new(), @@ -6915,7 +6944,7 @@ async fn experimental_mode_plan_is_ignored_on_startup() { #[tokio::test] async fn set_model_updates_active_collaboration_mask() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); @@ -6929,12 +6958,12 @@ async fn set_model_updates_active_collaboration_mask() { #[tokio::test] async fn set_reasoning_effort_updates_active_collaboration_mask() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); chat.set_collaboration_mask(plan_mask); - chat.set_reasoning_effort(None); + chat.set_reasoning_effort(/*effort*/ None); assert_eq!( chat.current_reasoning_effort(), @@ -6946,7 +6975,7 @@ async fn set_reasoning_effort_updates_active_collaboration_mask() { #[tokio::test] async fn set_reasoning_effort_does_not_override_active_plan_override() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.1")).await; - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); chat.set_plan_mode_reasoning_effort(Some(ReasoningEffortConfig::High)); let plan_mask = collaboration_modes::mask_for_kind(chat.model_catalog.as_ref(), ModeKind::Plan) .expect("expected plan collaboration mask"); @@ -6963,9 +6992,9 @@ async fn set_reasoning_effort_does_not_override_active_plan_override() { #[tokio::test] async fn collab_mode_is_sent_after_enabling() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); - chat.set_feature_enabled(Feature::CollaborationModes, true); + chat.set_feature_enabled(Feature::CollaborationModes, /*enabled*/ true); chat.bottom_pane .set_composer_text("hello".to_string(), Vec::new(), Vec::new()); @@ -6988,7 +7017,7 @@ async fn collab_mode_is_sent_after_enabling() { #[tokio::test] async fn collab_mode_applies_default_preset() { - let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.bottom_pane @@ -7016,7 +7045,7 @@ async fn collab_mode_applies_default_preset() { #[tokio::test] async fn user_turn_includes_personality_from_config() { let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.2-codex")).await; - chat.set_feature_enabled(Feature::Personality, true); + chat.set_feature_enabled(Feature::Personality, /*enabled*/ true); chat.thread_id = Some(ThreadId::new()); chat.set_model("gpt-5.2-codex"); chat.set_personality(Personality::Friendly); @@ -7035,7 +7064,7 @@ async fn user_turn_includes_personality_from_config() { #[tokio::test] async fn slash_quit_requests_exit() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Quit); @@ -7044,7 +7073,7 @@ async fn slash_quit_requests_exit() { #[tokio::test] async fn slash_copy_state_tracks_turn_complete_final_reply() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7062,7 +7091,7 @@ async fn slash_copy_state_tracks_turn_complete_final_reply() { #[tokio::test] async fn slash_copy_state_tracks_plan_item_completion() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let plan_text = "## Plan\n\n1. Build it\n2. Test it".to_string(); chat.handle_codex_event(Event { @@ -7089,7 +7118,7 @@ async fn slash_copy_state_tracks_plan_item_completion() { #[tokio::test] async fn slash_copy_reports_when_no_copyable_output_exists() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Copy); @@ -7107,7 +7136,7 @@ async fn slash_copy_reports_when_no_copyable_output_exists() { #[tokio::test] async fn slash_copy_state_is_preserved_during_running_task() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7126,7 +7155,7 @@ async fn slash_copy_state_is_preserved_during_running_task() { #[tokio::test] async fn slash_copy_state_clears_on_thread_rollback() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7145,7 +7174,7 @@ async fn slash_copy_state_clears_on_thread_rollback() { #[tokio::test] async fn slash_copy_is_unavailable_when_legacy_agent_message_is_not_repeated_on_turn_complete() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event_replay(Event { id: "turn-1".into(), @@ -7180,7 +7209,7 @@ async fn slash_copy_is_unavailable_when_legacy_agent_message_is_not_repeated_on_ #[tokio::test] async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7190,7 +7219,12 @@ async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text( collaboration_mode_kind: ModeKind::Default, }), }); - complete_assistant_message(&mut chat, "msg-1", "Legacy item final message", None); + complete_assistant_message( + &mut chat, + "msg-1", + "Legacy item final message", + /*phase*/ None, + ); let _ = drain_insert_history(&mut rx); chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7220,7 +7254,7 @@ async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text( #[tokio::test] async fn slash_copy_does_not_return_stale_output_after_thread_rollback() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7230,7 +7264,12 @@ async fn slash_copy_does_not_return_stale_output_after_thread_rollback() { collaboration_mode_kind: ModeKind::Default, }), }); - complete_assistant_message(&mut chat, "msg-1", "Reply that will be rolled back", None); + complete_assistant_message( + &mut chat, + "msg-1", + "Reply that will be rolled back", + /*phase*/ None, + ); let _ = drain_insert_history(&mut rx); chat.handle_codex_event(Event { id: "turn-1".into(), @@ -7262,7 +7301,7 @@ async fn slash_copy_does_not_return_stale_output_after_thread_rollback() { #[tokio::test] async fn slash_exit_requests_exit() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Exit); @@ -7271,7 +7310,7 @@ async fn slash_exit_requests_exit() { #[tokio::test] async fn slash_stop_submits_background_terminal_cleanup() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Stop); @@ -7287,7 +7326,7 @@ async fn slash_stop_submits_background_terminal_cleanup() { #[tokio::test] async fn slash_clear_requests_ui_clear_when_idle() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Clear); @@ -7296,15 +7335,15 @@ async fn slash_clear_requests_ui_clear_when_idle() { #[tokio::test] async fn slash_clear_is_disabled_while_task_running() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.bottom_pane.set_task_running(true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.bottom_pane.set_task_running(/*running*/ true); chat.dispatch_command(SlashCommand::Clear); let event = rx.try_recv().expect("expected disabled command error"); match event { AppEvent::InsertHistoryCell(cell) => { - let rendered = lines_to_single_string(&cell.display_lines(80)); + let rendered = lines_to_single_string(&cell.display_lines(/*width*/ 80)); assert!( rendered.contains("'/clear' is disabled while a task is in progress."), "expected /clear task-running error, got {rendered:?}" @@ -7317,14 +7356,14 @@ async fn slash_clear_is_disabled_while_task_running() { #[tokio::test] async fn slash_memory_drop_reports_stubbed_feature() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::MemoryDrop); let event = rx.try_recv().expect("expected unsupported-feature error"); match event { AppEvent::InsertHistoryCell(cell) => { - let rendered = lines_to_single_string(&cell.display_lines(80)); + let rendered = lines_to_single_string(&cell.display_lines(/*width*/ 80)); assert!(rendered.contains("Memory maintenance: Not available in TUI yet.")); } other => panic!("expected InsertHistoryCell error, got {other:?}"), @@ -7337,7 +7376,7 @@ async fn slash_memory_drop_reports_stubbed_feature() { #[tokio::test] async fn slash_mcp_requests_inventory_via_app_server() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Mcp); @@ -7348,14 +7387,14 @@ async fn slash_mcp_requests_inventory_via_app_server() { #[tokio::test] async fn slash_memory_update_reports_stubbed_feature() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::MemoryUpdate); let event = rx.try_recv().expect("expected unsupported-feature error"); match event { AppEvent::InsertHistoryCell(cell) => { - let rendered = lines_to_single_string(&cell.display_lines(80)); + let rendered = lines_to_single_string(&cell.display_lines(/*width*/ 80)); assert!(rendered.contains("Memory maintenance: Not available in TUI yet.")); } other => panic!("expected InsertHistoryCell error, got {other:?}"), @@ -7368,7 +7407,7 @@ async fn slash_memory_update_reports_stubbed_feature() { #[tokio::test] async fn slash_resume_opens_picker() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Resume); @@ -7377,7 +7416,7 @@ async fn slash_resume_opens_picker() { #[tokio::test] async fn slash_fork_requests_current_fork() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Fork); @@ -7386,7 +7425,7 @@ async fn slash_fork_requests_current_fork() { #[tokio::test] async fn slash_rollout_displays_current_path() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let rollout_path = PathBuf::from("/tmp/codex-test-rollout.jsonl"); chat.current_rollout_path = Some(rollout_path.clone()); @@ -7403,7 +7442,7 @@ async fn slash_rollout_displays_current_path() { #[tokio::test] async fn slash_rollout_handles_missing_path() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.dispatch_command(SlashCommand::Rollout); @@ -7422,7 +7461,7 @@ async fn slash_rollout_handles_missing_path() { #[tokio::test] async fn undo_success_events_render_info_messages() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".to_string(), @@ -7459,7 +7498,7 @@ async fn undo_success_events_render_info_messages() { #[tokio::test] async fn undo_failure_events_render_error_message() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-2".to_string(), @@ -7494,7 +7533,7 @@ async fn undo_failure_events_render_error_message() { #[tokio::test] async fn undo_started_hides_interrupt_hint() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-hint".to_string(), @@ -7514,7 +7553,7 @@ async fn undo_started_hides_interrupt_hint() { /// The commit picker shows only commit subjects (no timestamps). #[tokio::test] async fn review_commit_picker_shows_subjects_without_timestamps() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Open the Review presets parent popup. chat.open_review_popup(); @@ -7576,7 +7615,7 @@ async fn review_commit_picker_shows_subjects_without_timestamps() { /// and uses the same text for the user-facing hint. #[tokio::test] async fn custom_prompt_submit_sends_review_op() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_review_custom_prompt(); // Paste prompt text via ChatWidget handler, then submit @@ -7604,7 +7643,7 @@ async fn custom_prompt_submit_sends_review_op() { /// Hitting Enter on an empty custom prompt view does not submit. #[tokio::test] async fn custom_prompt_enter_empty_does_not_send() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_review_custom_prompt(); // Enter without any text @@ -7616,7 +7655,7 @@ async fn custom_prompt_enter_empty_does_not_send() { #[tokio::test] async fn view_image_tool_call_adds_history_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let image_path = chat .config .cwd @@ -7639,7 +7678,7 @@ async fn view_image_tool_call_adds_history_cell() { #[tokio::test] async fn image_generation_call_adds_history_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "sub-image-generation".into(), @@ -7662,7 +7701,7 @@ async fn image_generation_call_adds_history_cell() { // marker (replacing the spinner) and flushes it into history. #[tokio::test] async fn interrupt_exec_marks_failed_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Begin a long-running command so we have an active exec cell with a spinner. begin_exec(&mut chat, "call-int", "sleep 1"); @@ -7692,7 +7731,7 @@ async fn interrupt_exec_marks_failed_snapshot() { // suggesting the user to tell the model what to do differently and to use /feedback. #[tokio::test] async fn interrupted_turn_error_message_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Simulate an in-progress task so the widget is in a running state. chat.handle_codex_event(Event { @@ -7727,7 +7766,7 @@ async fn interrupted_turn_error_message_snapshot() { // differently" error prompt. #[tokio::test] async fn interrupted_turn_pending_steers_message_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.pending_steers.push_back(pending_steer("steer 1")); chat.submit_pending_steers_after_interrupt = true; @@ -7762,7 +7801,7 @@ async fn interrupted_turn_pending_steers_message_snapshot() { /// parent popup, pressing Esc again dismisses all panels (back to normal mode). #[tokio::test] async fn review_custom_prompt_escape_navigates_back_then_dismisses() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Open the Review presets parent popup. chat.open_review_popup(); @@ -7771,7 +7810,7 @@ async fn review_custom_prompt_escape_navigates_back_then_dismisses() { chat.show_review_custom_prompt(); // Verify child view is on top. - let header = render_bottom_first_row(&chat, 60); + let header = render_bottom_first_row(&chat, /*width*/ 60); assert!( header.contains("Custom review instructions"), "expected custom prompt view header: {header:?}" @@ -7779,7 +7818,7 @@ async fn review_custom_prompt_escape_navigates_back_then_dismisses() { // Esc once: child view closes, parent (review presets) remains. chat.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - let header = render_bottom_first_row(&chat, 60); + let header = render_bottom_first_row(&chat, /*width*/ 60); assert!( header.contains("Select a review preset"), "expected to return to parent review popup: {header:?}" @@ -7797,7 +7836,7 @@ async fn review_custom_prompt_escape_navigates_back_then_dismisses() { /// parent popup, pressing Esc again dismisses all panels (back to normal mode). #[tokio::test] async fn review_branch_picker_escape_navigates_back_then_dismisses() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Open the Review presets parent popup. chat.open_review_popup(); @@ -7807,7 +7846,7 @@ async fn review_branch_picker_escape_navigates_back_then_dismisses() { chat.show_review_branch_picker(&cwd).await; // Verify child view header. - let header = render_bottom_first_row(&chat, 60); + let header = render_bottom_first_row(&chat, /*width*/ 60); assert!( header.contains("Select a base branch"), "expected branch picker header: {header:?}" @@ -7815,7 +7854,7 @@ async fn review_branch_picker_escape_navigates_back_then_dismisses() { // Esc once: child view closes, parent remains. chat.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - let header = render_bottom_first_row(&chat, 60); + let header = render_bottom_first_row(&chat, /*width*/ 60); assert!( header.contains("Select a review preset"), "expected to return to parent review popup: {header:?}" @@ -7965,7 +8004,11 @@ fn plugins_test_summary( enabled, install_policy, auth_policy: PluginAuthPolicy::OnInstall, - interface: Some(plugins_test_interface(display_name, description, None)), + interface: Some(plugins_test_interface( + display_name, + description, + /*long_description*/ None, + )), } } @@ -8004,7 +8047,7 @@ fn render_loaded_plugins_popup(chat: &mut ChatWidget, response: PluginListRespon let cwd = chat.config.cwd.clone(); chat.on_plugins_loaded(cwd.to_path_buf(), Ok(response)); chat.add_plugins_output(); - render_bottom_popup(chat, 100) + render_bottom_popup(chat, /*width*/ 100) } fn plugins_test_detail( @@ -8058,12 +8101,12 @@ fn type_plugins_search_query(chat: &mut ChatWidget, query: &str) { #[tokio::test] async fn plugins_popup_loading_state_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); chat.add_plugins_output(); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert!( popup.contains("Loading available plugins..."), "expected /plugins to open in a loading state before the marketplace arrives, got:\n{popup}" @@ -8073,8 +8116,8 @@ async fn plugins_popup_loading_state_snapshot() { #[tokio::test] async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_name() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); let mut response = plugins_test_response(vec![ plugins_test_curated_marketplace(vec![ @@ -8083,8 +8126,8 @@ async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_ "bravo", Some("Bravo Search"), Some("Search docs and tickets."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8092,8 +8135,8 @@ async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_ "alpha", Some("Alpha Sync"), Some("Already installed but disabled."), - true, - false, + /*installed*/ true, + /*enabled*/ false, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8101,8 +8144,8 @@ async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_ "starter", Some("Starter"), Some("Included by default."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::InstalledByDefault, ), ]), @@ -8111,8 +8154,8 @@ async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_ "hidden", Some("Hidden Repo Plugin"), Some("Should not be shown in /plugins."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, )]), ]); @@ -8137,16 +8180,16 @@ async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_ #[tokio::test] async fn plugin_detail_popup_snapshot_shows_install_actions_and_capability_summaries() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); let summary = plugins_test_summary( "plugin-figma", "figma", Some("Figma"), Some("Design handoff."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ); let response = plugins_test_response(vec![plugins_test_curated_marketplace(vec![ @@ -8168,7 +8211,7 @@ async fn plugin_detail_popup_snapshot_shows_install_actions_and_capability_summa }), ); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert_snapshot!( "plugin_detail_popup_installable", strip_osc8_for_snapshot(&popup) @@ -8177,16 +8220,16 @@ async fn plugin_detail_popup_snapshot_shows_install_actions_and_capability_summa #[tokio::test] async fn plugin_detail_popup_hides_disclosure_for_installed_plugins() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); let summary = plugins_test_summary( "plugin-figma", "figma", Some("Figma"), Some("Design handoff."), - true, - true, + /*installed*/ true, + /*enabled*/ true, PluginInstallPolicy::Available, ); let response = plugins_test_response(vec![plugins_test_curated_marketplace(vec![ @@ -8208,7 +8251,7 @@ async fn plugin_detail_popup_hides_disclosure_for_installed_plugins() { }), ); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert!( !popup.contains("Data shared with this app is subject to the app's"), "expected installed plugin details to hide the disclosure line, got:\n{popup}" @@ -8221,8 +8264,8 @@ async fn plugin_detail_popup_hides_disclosure_for_installed_plugins() { #[tokio::test] async fn plugins_popup_refresh_replaces_selection_with_first_row() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); let initial = plugins_test_response(vec![plugins_test_curated_marketplace(vec![ plugins_test_summary( @@ -8230,8 +8273,8 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "notion", Some("Notion"), Some("Workspace docs."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8239,15 +8282,15 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "slack", Some("Slack"), Some("Team chat."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]); render_loaded_plugins_popup(&mut chat, initial); chat.handle_key_event(KeyEvent::from(KeyCode::Down)); - let before = render_bottom_popup(&chat, 100); + let before = render_bottom_popup(&chat, /*width*/ 100); assert!( before.contains("β€Ί Slack"), "expected Slack to be selected before refresh, got:\n{before}" @@ -8259,8 +8302,8 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "airtable", Some("Airtable"), Some("Structured records."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8268,8 +8311,8 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "notion", Some("Notion"), Some("Workspace docs."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8277,15 +8320,15 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "slack", Some("Slack"), Some("Team chat."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]); let cwd = chat.config.cwd.clone(); chat.on_plugins_loaded(cwd.to_path_buf(), Ok(refreshed)); - let after = render_bottom_popup(&chat, 100); + let after = render_bottom_popup(&chat, /*width*/ 100); assert!( after.contains("β€Ί Airtable"), "expected refresh to rebuild the popup from the new first row, got:\n{after}" @@ -8298,8 +8341,8 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { #[tokio::test] async fn plugins_popup_refreshes_installed_counts_after_install() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); let initial = plugins_test_response(vec![plugins_test_curated_marketplace(vec![ plugins_test_summary( @@ -8307,8 +8350,8 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "calendar", Some("Calendar"), Some("Schedule management."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8316,8 +8359,8 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "drive", Some("Drive"), Some("Document access."), - true, - true, + /*installed*/ true, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]); @@ -8337,8 +8380,8 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "calendar", Some("Calendar"), Some("Schedule management."), - true, - true, + /*installed*/ true, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8346,15 +8389,15 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "drive", Some("Drive"), Some("Document access."), - true, - true, + /*installed*/ true, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]); let cwd = chat.config.cwd.clone(); chat.on_plugins_loaded(cwd.to_path_buf(), Ok(refreshed)); - let after = render_bottom_popup(&chat, 100); + let after = render_bottom_popup(&chat, /*width*/ 100); assert!( after.contains("Installed 2 of 2 available plugins."), "expected /plugins to refresh installed counts after install, got:\n{after}" @@ -8367,8 +8410,8 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { #[tokio::test] async fn plugins_popup_search_filters_visible_rows_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); render_loaded_plugins_popup( &mut chat, @@ -8378,8 +8421,8 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { "calendar", Some("Calendar"), Some("Schedule management."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8387,8 +8430,8 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { "slack", Some("Slack"), Some("Team chat."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8396,8 +8439,8 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { "drive", Some("Drive"), Some("Document access."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]), @@ -8405,7 +8448,7 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { type_plugins_search_query(&mut chat, "sla"); - let popup = render_bottom_popup(&chat, 100); + let popup = render_bottom_popup(&chat, /*width*/ 100); assert_snapshot!("plugins_popup_search_filtered", popup); assert!( !popup.contains("Calendar") && !popup.contains("Drive"), @@ -8415,8 +8458,8 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { #[tokio::test] async fn plugins_popup_search_no_matches_and_backspace_restores_results() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::Plugins, true); + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::Plugins, /*enabled*/ true); render_loaded_plugins_popup( &mut chat, @@ -8426,8 +8469,8 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { "calendar", Some("Calendar"), Some("Schedule management."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), plugins_test_summary( @@ -8435,8 +8478,8 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { "slack", Some("Slack"), Some("Team chat."), - false, - true, + /*installed*/ false, + /*enabled*/ true, PluginInstallPolicy::Available, ), ])]), @@ -8444,7 +8487,7 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { type_plugins_search_query(&mut chat, "zzz"); - let no_matches = render_bottom_popup(&chat, 100); + let no_matches = render_bottom_popup(&chat, /*width*/ 100); assert!( no_matches.contains("zzz"), "expected popup to show the typed search query, got:\n{no_matches}" @@ -8458,7 +8501,7 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { chat.handle_key_event(KeyEvent::from(KeyCode::Backspace)); } - let restored = render_bottom_popup(&chat, 100); + let restored = render_bottom_popup(&chat, /*width*/ 100); assert!( restored.contains("Calendar") && restored.contains("Slack"), "expected clearing the query to restore the plugin rows, got:\n{restored}" @@ -8471,13 +8514,13 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { #[tokio::test] async fn apps_popup_stays_loading_until_final_snapshot_updates() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let notion_id = "unit_test_apps_popup_refresh_connector_1"; let linear_id = "unit_test_apps_popup_refresh_connector_2"; @@ -8499,7 +8542,7 @@ async fn apps_popup_stays_loading_until_final_snapshot_updates() { plugin_display_names: Vec::new(), }], }), - false, + /*is_final*/ false, ); chat.add_connectors_output(); assert!( @@ -8507,7 +8550,7 @@ async fn apps_popup_stays_loading_until_final_snapshot_updates() { "expected /apps to trigger a forced connectors refresh" ); - let before = render_bottom_popup(&chat, 80); + let before = render_bottom_popup(&chat, /*width*/ 80); assert!( before.contains("Loading installed and available apps..."), "expected /apps to stay in the loading state until the full list arrives, got:\n{before}" @@ -8549,10 +8592,10 @@ async fn apps_popup_stays_loading_until_final_snapshot_updates() { }, ], }), - true, + /*is_final*/ true, ); - let after = render_bottom_popup(&chat, 80); + let after = render_bottom_popup(&chat, /*width*/ 80); assert!( after.contains("Installed 2 of 2 available apps."), "expected refreshed apps popup snapshot, got:\n{after}" @@ -8565,13 +8608,13 @@ async fn apps_popup_stays_loading_until_final_snapshot_updates() { #[tokio::test] async fn apps_refresh_failure_keeps_existing_full_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let notion_id = "unit_test_apps_refresh_failure_connector_1"; let linear_id = "unit_test_apps_refresh_failure_connector_2"; @@ -8611,7 +8654,7 @@ async fn apps_refresh_failure_keeps_existing_full_snapshot() { Ok(ConnectorsSnapshot { connectors: full_connectors.clone(), }), - true, + /*is_final*/ true, ); chat.on_connectors_loaded( @@ -8632,9 +8675,12 @@ async fn apps_refresh_failure_keeps_existing_full_snapshot() { plugin_display_names: Vec::new(), }], }), - false, + /*is_final*/ false, + ); + chat.on_connectors_loaded( + Err("failed to load apps".to_string()), + /*is_final*/ true, ); - chat.on_connectors_loaded(Err("failed to load apps".to_string()), true); assert_matches!( &chat.connectors_cache, @@ -8642,7 +8688,7 @@ async fn apps_refresh_failure_keeps_existing_full_snapshot() { ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed 1 of 2 available apps."), "expected previous full snapshot to be preserved, got:\n{popup}" @@ -8651,13 +8697,13 @@ async fn apps_refresh_failure_keeps_existing_full_snapshot() { #[tokio::test] async fn apps_popup_preserves_selected_app_across_refresh() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -8694,12 +8740,12 @@ async fn apps_popup_preserves_selected_app_across_refresh() { }, ], }), - true, + /*is_final*/ true, ); chat.add_connectors_output(); chat.handle_key_event(KeyEvent::from(KeyCode::Down)); - let before = render_bottom_popup(&chat, 80); + let before = render_bottom_popup(&chat, /*width*/ 80); assert!( before.contains("β€Ί Slack"), "expected Slack to be selected before refresh, got:\n{before}" @@ -8755,10 +8801,10 @@ async fn apps_popup_preserves_selected_app_across_refresh() { }, ], }), - true, + /*is_final*/ true, ); - let after = render_bottom_popup(&chat, 80); + let after = render_bottom_popup(&chat, /*width*/ 80); assert!( after.contains("β€Ί Slack"), "expected Slack to stay selected after refresh, got:\n{after}" @@ -8771,13 +8817,13 @@ async fn apps_popup_preserves_selected_app_across_refresh() { #[tokio::test] async fn apps_refresh_failure_with_cached_snapshot_triggers_pending_force_refetch() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.connectors_prefetch_in_flight = true; chat.connectors_force_refetch_pending = true; @@ -8800,7 +8846,10 @@ async fn apps_refresh_failure_with_cached_snapshot_triggers_pending_force_refetc connectors: full_connectors.clone(), }); - chat.on_connectors_loaded(Err("failed to load apps".to_string()), true); + chat.on_connectors_loaded( + Err("failed to load apps".to_string()), + /*is_final*/ true, + ); assert!(chat.connectors_prefetch_in_flight); assert!(!chat.connectors_force_refetch_pending); @@ -8812,13 +8861,13 @@ async fn apps_refresh_failure_with_cached_snapshot_triggers_pending_force_refetc #[tokio::test] async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let full_connectors = vec![ codex_chatgpt::connectors::AppInfo { @@ -8856,7 +8905,7 @@ async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads() { Ok(ConnectorsSnapshot { connectors: full_connectors.clone(), }), - true, + /*is_final*/ true, ); chat.add_connectors_output(); @@ -8895,7 +8944,7 @@ async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads() { }, ], }), - false, + /*is_final*/ false, ); assert_matches!( @@ -8903,7 +8952,7 @@ async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads() { ConnectorsCacheState::Ready(snapshot) if snapshot.connectors == full_connectors ); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed 1 of 2 available apps."), "expected popup to keep the last full snapshot while partial refresh loads, got:\n{popup}" @@ -8916,13 +8965,13 @@ async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads() { #[tokio::test] async fn apps_refresh_failure_without_full_snapshot_falls_back_to_installed_apps() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -8942,24 +8991,27 @@ async fn apps_refresh_failure_without_full_snapshot_falls_back_to_installed_apps plugin_display_names: Vec::new(), }], }), - false, + /*is_final*/ false, ); chat.add_connectors_output(); - let loading_popup = render_bottom_popup(&chat, 80); + let loading_popup = render_bottom_popup(&chat, /*width*/ 80); assert!( loading_popup.contains("Loading installed and available apps..."), "expected /apps to keep showing loading before the final result, got:\n{loading_popup}" ); - chat.on_connectors_loaded(Err("failed to load apps".to_string()), true); + chat.on_connectors_loaded( + Err("failed to load apps".to_string()), + /*is_final*/ true, + ); assert_matches!( &chat.connectors_cache, ConnectorsCacheState::Ready(snapshot) if snapshot.connectors.len() == 1 ); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed 1 of 1 available apps."), "expected /apps to fall back to the installed apps snapshot, got:\n{popup}" @@ -8972,13 +9024,13 @@ async fn apps_refresh_failure_without_full_snapshot_falls_back_to_installed_apps #[tokio::test] async fn apps_popup_shows_disabled_status_for_installed_but_disabled_apps() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -8998,11 +9050,11 @@ async fn apps_popup_shows_disabled_status_for_installed_but_disabled_apps() { plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed Β· Disabled. Press Enter to open the app page"), "expected selected app description to include disabled status, got:\n{popup}" @@ -9015,13 +9067,13 @@ async fn apps_popup_shows_disabled_status_for_installed_but_disabled_apps() { #[tokio::test] async fn apps_initial_load_applies_enabled_state_from_config() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let temp = tempdir().expect("tempdir"); let config_toml_path = temp.path().join("config.toml").abs(); @@ -9052,7 +9104,7 @@ async fn apps_initial_load_applies_enabled_state_from_config() { plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); assert_matches!( @@ -9068,13 +9120,13 @@ async fn apps_initial_load_applies_enabled_state_from_config() { #[tokio::test] async fn apps_initial_load_applies_enabled_state_from_requirements_with_user_override() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let requirements = ConfigRequirementsToml { apps: Some(AppsRequirementsToml { @@ -9118,7 +9170,7 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_with_user_ove plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); assert_matches!( @@ -9132,7 +9184,7 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_with_user_ove ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed Β· Disabled. Press Enter to open the app page"), "expected requirements-disabled connector to render as disabled, got:\n{popup}" @@ -9141,13 +9193,13 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_with_user_ove #[tokio::test] async fn apps_initial_load_applies_enabled_state_from_requirements_without_user_entry() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); let requirements = ConfigRequirementsToml { apps: Some(AppsRequirementsToml { @@ -9182,7 +9234,7 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_without_user_ plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); assert_matches!( @@ -9196,7 +9248,7 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_without_user_ ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed Β· Disabled. Press Enter to open the app page"), "expected requirements-disabled connector to render as disabled, got:\n{popup}" @@ -9205,13 +9257,13 @@ async fn apps_initial_load_applies_enabled_state_from_requirements_without_user_ #[tokio::test] async fn apps_refresh_preserves_toggled_enabled_state() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -9231,9 +9283,9 @@ async fn apps_refresh_preserves_toggled_enabled_state() { plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); - chat.update_connector_enabled("connector_1", false); + chat.update_connector_enabled("connector_1", /*enabled*/ false); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -9253,7 +9305,7 @@ async fn apps_refresh_preserves_toggled_enabled_state() { plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); assert_matches!( @@ -9267,7 +9319,7 @@ async fn apps_refresh_preserves_toggled_enabled_state() { ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Installed Β· Disabled. Press Enter to open the app page"), "expected disabled status to persist after reload, got:\n{popup}" @@ -9276,13 +9328,13 @@ async fn apps_refresh_preserves_toggled_enabled_state() { #[tokio::test] async fn apps_popup_for_not_installed_app_uses_install_only_selected_description() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); chat.config .features .enable(Feature::Apps) .expect("test config should allow feature update"); - chat.bottom_pane.set_connectors_enabled(true); + chat.bottom_pane.set_connectors_enabled(/*enabled*/ true); chat.on_connectors_loaded( Ok(ConnectorsSnapshot { @@ -9302,11 +9354,11 @@ async fn apps_popup_for_not_installed_app_uses_install_only_selected_description plugin_display_names: Vec::new(), }], }), - true, + /*is_final*/ true, ); chat.add_connectors_output(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Can be installed. Press Enter to open the app page to install"), "expected selected app description to be install-only for not-installed apps, got:\n{popup}" @@ -9319,7 +9371,7 @@ async fn apps_popup_for_not_installed_app_uses_install_only_selected_description #[tokio::test] async fn experimental_features_popup_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let features = vec![ ExperimentalFeatureItem { @@ -9338,13 +9390,13 @@ async fn experimental_features_popup_snapshot() { let view = ExperimentalFeaturesView::new(features, chat.app_event_tx.clone()); chat.bottom_pane.show_view(Box::new(view)); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("experimental_features_popup", popup); } #[tokio::test] async fn experimental_features_toggle_saves_on_exit() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let expected_feature = Feature::GhostCommit; let view = ExperimentalFeaturesView::new( @@ -9384,7 +9436,7 @@ async fn experimental_features_toggle_saves_on_exit() { #[tokio::test] async fn experimental_popup_shows_js_repl_node_requirement() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let js_repl_description = FEATURES .iter() @@ -9399,7 +9451,7 @@ async fn experimental_popup_shows_js_repl_node_requirement() { chat.open_experimental_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains(node_requirement), "expected js_repl feature description to mention the required Node version, got:\n{popup}" @@ -9408,7 +9460,7 @@ async fn experimental_popup_shows_js_repl_node_requirement() { #[tokio::test] async fn experimental_popup_includes_guardian_approval() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let guardian_stage = FEATURES .iter() .find(|spec| spec.id == Feature::GuardianApproval) @@ -9423,7 +9475,7 @@ async fn experimental_popup_includes_guardian_approval() { chat.open_experimental_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); let normalized_popup = popup.split_whitespace().collect::>().join(" "); assert!( popup.contains(guardian_name), @@ -9437,17 +9489,17 @@ async fn experimental_popup_includes_guardian_approval() { #[tokio::test] async fn multi_agent_enable_prompt_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.open_multi_agent_enable_prompt(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("multi_agent_enable_prompt", popup); } #[tokio::test] async fn multi_agent_enable_prompt_updates_feature_and_emits_notice() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.open_multi_agent_enable_prompt(); chat.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -9460,7 +9512,7 @@ async fn multi_agent_enable_prompt_updates_feature_and_emits_notice() { Ok(AppEvent::InsertHistoryCell(cell)) => cell, other => panic!("expected InsertHistoryCell event, got {other:?}"), }; - let rendered = lines_to_single_string(&cell.display_lines(120)); + let rendered = lines_to_single_string(&cell.display_lines(/*width*/ 120)); assert!(rendered.contains("Subagents will be enabled in the next session.")); } @@ -9470,7 +9522,7 @@ async fn model_selection_popup_snapshot() { chat.thread_id = Some(ThreadId::new()); chat.open_model_popup(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("model_selection_popup", popup); } @@ -9480,7 +9532,7 @@ async fn personality_selection_popup_snapshot() { chat.thread_id = Some(ThreadId::new()); chat.open_personality_popup(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("personality_selection_popup", popup); } @@ -9490,7 +9542,7 @@ async fn realtime_audio_selection_popup_snapshot() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.2-codex")).await; chat.open_realtime_audio_popup(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("realtime_audio_selection_popup", popup); } @@ -9500,7 +9552,7 @@ async fn realtime_audio_selection_popup_narrow_snapshot() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.2-codex")).await; chat.open_realtime_audio_popup(); - let popup = render_bottom_popup(&chat, 56); + let popup = render_bottom_popup(&chat, /*width*/ 56); assert_snapshot!("realtime_audio_selection_popup_narrow", popup); } @@ -9514,7 +9566,7 @@ async fn realtime_microphone_picker_popup_snapshot() { vec!["Built-in Mic".to_string(), "USB Mic".to_string()], ); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("realtime_microphone_picker_popup", popup); } @@ -9567,7 +9619,7 @@ async fn model_picker_hides_show_in_picker_false_models_from_cache() { preset("test-visible-model", true), preset("test-hidden-model", false), ]); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("model_picker_filters_hidden_models", popup); assert!( popup.contains("test-visible-model"), @@ -9615,12 +9667,12 @@ async fn server_overloaded_error_does_not_switch_models() { #[tokio::test] async fn approvals_selection_popup_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.notices.hide_full_access_warning = None; chat.open_approvals_popup(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); #[cfg(target_os = "windows")] insta::with_settings!({ snapshot_suffix => "windows" }, { assert_snapshot!("approvals_selection_popup", popup); @@ -9633,15 +9685,15 @@ async fn approvals_selection_popup_snapshot() { #[tokio::test] #[serial] async fn approvals_selection_popup_snapshot_windows_degraded_sandbox() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.notices.hide_full_access_warning = None; - chat.set_feature_enabled(Feature::WindowsSandbox, true); - chat.set_feature_enabled(Feature::WindowsSandboxElevated, false); + chat.set_feature_enabled(Feature::WindowsSandbox, /*enabled*/ true); + chat.set_feature_enabled(Feature::WindowsSandboxElevated, /*enabled*/ false); chat.open_approvals_popup(); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Default (non-admin sandbox)"), "expected degraded sandbox label in approvals popup: {popup}" @@ -9682,22 +9734,22 @@ async fn preset_matching_accepts_workspace_write_with_extra_roots() { #[tokio::test] async fn full_access_confirmation_popup_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let preset = builtin_approval_presets() .into_iter() .find(|preset| preset.id == "full-access") .expect("full access preset"); - chat.open_full_access_confirmation(preset, false); + chat.open_full_access_confirmation(preset, /*return_to_permissions*/ false); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("full_access_confirmation_popup", popup); } #[cfg(target_os = "windows")] #[tokio::test] async fn windows_auto_mode_prompt_requests_enabling_sandbox_feature() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let preset = builtin_approval_presets() .into_iter() @@ -9705,7 +9757,7 @@ async fn windows_auto_mode_prompt_requests_enabling_sandbox_feature() { .expect("auto preset"); chat.open_windows_sandbox_enable_prompt(preset); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains("requires Administrator permissions"), "expected auto mode prompt to mention Administrator permissions, popup: {popup}" @@ -9719,14 +9771,14 @@ async fn windows_auto_mode_prompt_requests_enabling_sandbox_feature() { #[cfg(target_os = "windows")] #[tokio::test] async fn startup_prompts_for_windows_sandbox_when_agent_requested() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - chat.set_feature_enabled(Feature::WindowsSandbox, false); - chat.set_feature_enabled(Feature::WindowsSandboxElevated, false); + chat.set_feature_enabled(Feature::WindowsSandbox, /*enabled*/ false); + chat.set_feature_enabled(Feature::WindowsSandboxElevated, /*enabled*/ false); - chat.maybe_prompt_windows_sandbox_enable(true); + chat.maybe_prompt_windows_sandbox_enable(/*show_now*/ true); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains("requires Administrator permissions"), "expected startup prompt to mention Administrator permissions: {popup}" @@ -9748,11 +9800,11 @@ async fn startup_prompts_for_windows_sandbox_when_agent_requested() { #[cfg(target_os = "windows")] #[tokio::test] async fn startup_does_not_prompt_for_windows_sandbox_when_not_requested() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - chat.set_feature_enabled(Feature::WindowsSandbox, false); - chat.set_feature_enabled(Feature::WindowsSandboxElevated, false); - chat.maybe_prompt_windows_sandbox_enable(false); + chat.set_feature_enabled(Feature::WindowsSandbox, /*enabled*/ false); + chat.set_feature_enabled(Feature::WindowsSandboxElevated, /*enabled*/ false); + chat.maybe_prompt_windows_sandbox_enable(/*show_now*/ false); assert!( chat.bottom_pane.no_modal_or_popup_active(), @@ -9770,7 +9822,7 @@ async fn model_reasoning_selection_popup_snapshot() { let preset = get_available_model(&chat, "gpt-5.1-codex-max"); chat.open_reasoning_popup(preset); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("model_reasoning_selection_popup", popup); } @@ -9784,7 +9836,7 @@ async fn model_reasoning_selection_popup_extra_high_warning_snapshot() { let preset = get_available_model(&chat, "gpt-5.1-codex-max"); chat.open_reasoning_popup(preset); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("model_reasoning_selection_popup_extra_high_warning", popup); } @@ -9797,7 +9849,7 @@ async fn reasoning_popup_shows_extra_high_with_space() { let preset = get_available_model(&chat, "gpt-5.1-codex-max"); chat.open_reasoning_popup(preset); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains("Extra high"), "expected popup to include 'Extra high'; popup: {popup}" @@ -9810,7 +9862,7 @@ async fn reasoning_popup_shows_extra_high_with_space() { #[tokio::test] async fn single_reasoning_option_skips_selection() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let single_effort = vec![ReasoningEffortPreset { effort: ReasoningEffortConfig::High, @@ -9833,7 +9885,7 @@ async fn single_reasoning_option_skips_selection() { }; chat.open_reasoning_popup(preset); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( !popup.contains("Select Reasoning Level"), "expected reasoning selection popup to be skipped" @@ -9854,18 +9906,18 @@ async fn single_reasoning_option_skips_selection() { #[tokio::test] async fn feedback_selection_popup_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Open the feedback category selection popup via slash command. chat.dispatch_command(SlashCommand::Feedback); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("feedback_selection_popup", popup); } #[tokio::test] async fn feedback_upload_consent_popup_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_selection_view(crate::bottom_pane::feedback_upload_consent_params( chat.app_event_tx.clone(), @@ -9879,13 +9931,13 @@ async fn feedback_upload_consent_popup_snapshot() { ]), )); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("feedback_upload_consent_popup", popup); } #[tokio::test] async fn feedback_good_result_consent_popup_includes_connectivity_diagnostics_filename() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_selection_view(crate::bottom_pane::feedback_upload_consent_params( chat.app_event_tx.clone(), @@ -9899,7 +9951,7 @@ async fn feedback_good_result_consent_popup_includes_connectivity_diagnostics_fi ]), )); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert_snapshot!("feedback_good_result_consent_popup", popup); } @@ -9912,26 +9964,26 @@ async fn reasoning_popup_escape_returns_to_model_popup() { let preset = get_available_model(&chat, "gpt-5.1-codex-max"); chat.open_reasoning_popup(preset); - let before_escape = render_bottom_popup(&chat, 80); + let before_escape = render_bottom_popup(&chat, /*width*/ 80); assert!(before_escape.contains("Select Reasoning Level")); chat.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); - let after_escape = render_bottom_popup(&chat, 80); + let after_escape = render_bottom_popup(&chat, /*width*/ 80); assert!(after_escape.contains("Select Model")); assert!(!after_escape.contains("Select Reasoning Level")); } #[tokio::test] async fn exec_history_extends_previous_when_consecutive() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // 1) Start "ls -la" (List) let begin_ls = begin_exec(&mut chat, "call-ls", "ls -la"); assert_snapshot!("exploring_step1_start_ls", active_blob(&chat)); // 2) Finish "ls -la" - end_exec(&mut chat, begin_ls, "", "", 0); + end_exec(&mut chat, begin_ls, "", "", /*exit_code*/ 0); assert_snapshot!("exploring_step2_finish_ls", active_blob(&chat)); // 3) Start "cat foo.txt" (Read) @@ -9939,23 +9991,41 @@ async fn exec_history_extends_previous_when_consecutive() { assert_snapshot!("exploring_step3_start_cat_foo", active_blob(&chat)); // 4) Complete "cat foo.txt" - end_exec(&mut chat, begin_cat_foo, "hello from foo", "", 0); + end_exec( + &mut chat, + begin_cat_foo, + "hello from foo", + "", + /*exit_code*/ 0, + ); assert_snapshot!("exploring_step4_finish_cat_foo", active_blob(&chat)); // 5) Start & complete "sed -n 100,200p foo.txt" (treated as Read of foo.txt) let begin_sed_range = begin_exec(&mut chat, "call-sed-range", "sed -n 100,200p foo.txt"); - end_exec(&mut chat, begin_sed_range, "chunk", "", 0); + end_exec( + &mut chat, + begin_sed_range, + "chunk", + "", + /*exit_code*/ 0, + ); assert_snapshot!("exploring_step5_finish_sed_range", active_blob(&chat)); // 6) Start & complete "cat bar.txt" let begin_cat_bar = begin_exec(&mut chat, "call-cat-bar", "cat bar.txt"); - end_exec(&mut chat, begin_cat_bar, "hello from bar", "", 0); + end_exec( + &mut chat, + begin_cat_bar, + "hello from bar", + "", + /*exit_code*/ 0, + ); assert_snapshot!("exploring_step6_finish_cat_bar", active_blob(&chat)); } #[tokio::test] async fn user_shell_command_renders_output_not_exploring() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let begin_ls = begin_exec_with_source( &mut chat, @@ -9963,7 +10033,13 @@ async fn user_shell_command_renders_output_not_exploring() { "ls", ExecCommandSource::UserShell, ); - end_exec(&mut chat, begin_ls, "file1\nfile2\n", "", 0); + end_exec( + &mut chat, + begin_ls, + "file1\nfile2\n", + "", + /*exit_code*/ 0, + ); let cells = drain_insert_history(&mut rx); assert_eq!( @@ -9977,7 +10053,7 @@ async fn user_shell_command_renders_output_not_exploring() { #[tokio::test] async fn bang_shell_command_submits_run_user_shell_command_in_app_server_tui() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let conversation_id = ThreadId::new(); let rollout_file = NamedTempFile::new().unwrap(); let configured = codex_protocol::protocol::SessionConfiguredEvent { @@ -10019,8 +10095,8 @@ async fn bang_shell_command_submits_run_user_shell_command_in_app_server_tui() { #[tokio::test] async fn disabled_slash_command_while_task_running_snapshot() { // Build a chat widget and simulate an active task - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.bottom_pane.set_task_running(true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.bottom_pane.set_task_running(/*running*/ true); // Dispatch a command that is unavailable while a task runs (e.g., /model) chat.dispatch_command(SlashCommand::Model); @@ -10038,7 +10114,7 @@ async fn disabled_slash_command_while_task_running_snapshot() { #[tokio::test] async fn fast_slash_command_updates_and_persists_local_service_tier() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await; - chat.set_feature_enabled(Feature::FastMode, true); + chat.set_feature_enabled(Feature::FastMode, /*enabled*/ true); chat.dispatch_command(SlashCommand::Fast); @@ -10071,7 +10147,7 @@ async fn user_turn_carries_service_tier_after_fast_toggle() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await; chat.thread_id = Some(ThreadId::new()); set_chatgpt_auth(&mut chat); - chat.set_feature_enabled(Feature::FastMode, true); + chat.set_feature_enabled(Feature::FastMode, /*enabled*/ true); chat.dispatch_command(SlashCommand::Fast); @@ -10121,7 +10197,7 @@ async fn fast_status_indicator_is_hidden_when_fast_mode_is_off() { #[tokio::test] async fn approvals_popup_shows_disabled_presets() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.permissions.approval_policy = Constrained::new(AskForApproval::OnRequest, |candidate| match candidate { @@ -10157,7 +10233,7 @@ async fn approvals_popup_shows_disabled_presets() { #[tokio::test] async fn approvals_popup_navigation_skips_disabled() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.permissions.approval_policy = Constrained::new(AskForApproval::OnRequest, |candidate| match candidate { @@ -10228,7 +10304,7 @@ async fn approvals_popup_navigation_skips_disabled() { #[tokio::test] async fn permissions_selection_emits_history_cell_when_selection_changes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10255,7 +10331,7 @@ async fn permissions_selection_emits_history_cell_when_selection_changes() { #[tokio::test] async fn permissions_selection_history_snapshot_after_mode_switch() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10279,7 +10355,7 @@ async fn permissions_selection_history_snapshot_after_mode_switch() { #[tokio::test] async fn permissions_selection_history_snapshot_full_access_to_default() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10295,7 +10371,7 @@ async fn permissions_selection_history_snapshot_full_access_to_default() { Constrained::allow_any(SandboxPolicy::DangerFullAccess); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); chat.handle_key_event(KeyEvent::from(KeyCode::Up)); if popup.contains("Guardian Approvals") { chat.handle_key_event(KeyEvent::from(KeyCode::Up)); @@ -10320,7 +10396,7 @@ async fn permissions_selection_history_snapshot_full_access_to_default() { #[tokio::test] async fn permissions_selection_emits_history_cell_when_current_is_selected() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10355,7 +10431,7 @@ async fn permissions_selection_emits_history_cell_when_current_is_selected() { #[tokio::test] async fn permissions_selection_hides_guardian_approvals_when_feature_disabled() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10364,7 +10440,7 @@ async fn permissions_selection_hides_guardian_approvals_when_feature_disabled() chat.config.notices.hide_full_access_warning = Some(true); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( !popup.contains("Guardian Approvals"), @@ -10375,7 +10451,7 @@ async fn permissions_selection_hides_guardian_approvals_when_feature_disabled() #[tokio::test] async fn permissions_selection_hides_guardian_approvals_when_feature_disabled_even_if_auto_review_is_active() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10395,7 +10471,7 @@ async fn permissions_selection_hides_guardian_approvals_when_feature_disabled_ev .expect("set sandbox policy"); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( !popup.contains("Guardian Approvals"), @@ -10405,7 +10481,7 @@ async fn permissions_selection_hides_guardian_approvals_when_feature_disabled_ev #[tokio::test] async fn permissions_selection_marks_guardian_approvals_current_after_session_configured() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10415,7 +10491,7 @@ async fn permissions_selection_marks_guardian_approvals_current_after_session_co let _ = chat .config .features - .set_enabled(Feature::GuardianApproval, true); + .set_enabled(Feature::GuardianApproval, /*enabled*/ true); chat.handle_codex_event(Event { id: "session-configured".to_string(), @@ -10440,7 +10516,7 @@ async fn permissions_selection_marks_guardian_approvals_current_after_session_co }); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains("Guardian Approvals (current)"), @@ -10451,7 +10527,7 @@ async fn permissions_selection_marks_guardian_approvals_current_after_session_co #[tokio::test] async fn permissions_selection_marks_guardian_approvals_current_with_custom_workspace_write_details() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10461,7 +10537,7 @@ async fn permissions_selection_marks_guardian_approvals_current_with_custom_work let _ = chat .config .features - .set_enabled(Feature::GuardianApproval, true); + .set_enabled(Feature::GuardianApproval, /*enabled*/ true); let extra_root = PathBuf::from("/tmp/guardian-approvals-extra").abs(); @@ -10494,7 +10570,7 @@ async fn permissions_selection_marks_guardian_approvals_current_with_custom_work }); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup.contains("Guardian Approvals (current)"), @@ -10504,14 +10580,14 @@ async fn permissions_selection_marks_guardian_approvals_current_with_custom_work #[tokio::test] async fn permissions_selection_can_disable_guardian_approvals() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); chat.set_windows_sandbox_mode(Some(WindowsSandboxModeToml::Unelevated)); } chat.config.notices.hide_full_access_warning = Some(true); - chat.set_feature_enabled(Feature::GuardianApproval, true); + chat.set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); chat.config .permissions .approval_policy @@ -10545,14 +10621,14 @@ async fn permissions_selection_can_disable_guardian_approvals() { #[tokio::test] async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); chat.set_windows_sandbox_mode(Some(WindowsSandboxModeToml::Unelevated)); } chat.config.notices.hide_full_access_warning = Some(true); - chat.set_feature_enabled(Feature::GuardianApproval, true); + chat.set_feature_enabled(Feature::GuardianApproval, /*enabled*/ true); chat.config .permissions .approval_policy @@ -10566,7 +10642,7 @@ async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context chat.set_approvals_reviewer(ApprovalsReviewer::User); chat.open_permissions_popup(); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup .lines() @@ -10575,7 +10651,7 @@ async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context ); chat.handle_key_event(KeyEvent::from(KeyCode::Down)); - let popup = render_bottom_popup(&chat, 120); + let popup = render_bottom_popup(&chat, /*width*/ 120); assert!( popup .lines() @@ -10611,7 +10687,7 @@ async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context #[tokio::test] async fn permissions_full_access_history_cell_emitted_only_after_confirmation() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; #[cfg(target_os = "windows")] { chat.config.notices.hide_world_writable_warning = Some(true); @@ -10630,7 +10706,7 @@ async fn permissions_full_access_history_cell_emitted_only_after_confirmation() while let Ok(event) = rx.try_recv() { match event { AppEvent::InsertHistoryCell(cell) => { - cells_before_confirmation.push(cell.display_lines(80)); + cells_before_confirmation.push(cell.display_lines(/*width*/ 80)); } AppEvent::OpenFullAccessConfirmation { preset, @@ -10651,7 +10727,7 @@ async fn permissions_full_access_history_cell_emitted_only_after_confirmation() open_confirmation_event.expect("expected full access confirmation event"); chat.open_full_access_confirmation(preset, return_to_permissions); - let popup = render_bottom_popup(&chat, 80); + let popup = render_bottom_popup(&chat, /*width*/ 80); assert!( popup.contains("Enable full access?"), "expected full access confirmation popup, got: {popup}" @@ -10683,7 +10759,7 @@ async fn permissions_full_access_history_cell_emitted_only_after_confirmation() #[tokio::test] async fn approval_modal_exec_snapshot() -> anyhow::Result<()> { // Build a chat widget with manual channels to avoid spawning the agent. - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Ensure policy allows surfacing approvals explicitly (not strictly required for direct event). chat.config .permissions @@ -10747,7 +10823,7 @@ async fn approval_modal_exec_snapshot() -> anyhow::Result<()> { // Ensures spacing looks correct when no reason text is provided. #[tokio::test] async fn approval_modal_exec_without_reason_snapshot() -> anyhow::Result<()> { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config .permissions .approval_policy @@ -10797,7 +10873,7 @@ async fn approval_modal_exec_without_reason_snapshot() -> anyhow::Result<()> { #[tokio::test] async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot() -> anyhow::Result<()> { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config .permissions .approval_policy @@ -10845,7 +10921,7 @@ async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot() // Snapshot test: patch approval modal #[tokio::test] async fn approval_modal_patch_snapshot() -> anyhow::Result<()> { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config .permissions .approval_policy @@ -10872,9 +10948,9 @@ async fn approval_modal_patch_snapshot() -> anyhow::Result<()> { }); // Render at the widget's desired height and snapshot. - let height = chat.desired_height(80); + let height = chat.desired_height(/*width*/ 80); let mut terminal = - ratatui::Terminal::new(VT100Backend::new(80, height)).expect("create terminal"); + ratatui::Terminal::new(VT100Backend::new(/*width*/ 80, height)).expect("create terminal"); terminal.set_viewport_area(Rect::new(0, 0, 80, height)); terminal .draw(|f| chat.render(f.area(), f.buffer_mut())) @@ -10889,10 +10965,10 @@ async fn approval_modal_patch_snapshot() -> anyhow::Result<()> { #[tokio::test] async fn interrupt_restores_queued_messages_into_composer() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Simulate a running task to enable queuing of user inputs. - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); // Queue two user messages while the task is running. chat.queued_user_messages @@ -10929,9 +11005,9 @@ async fn interrupt_restores_queued_messages_into_composer() { #[tokio::test] async fn interrupt_prepends_queued_messages_before_existing_composer_text() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - chat.bottom_pane.set_task_running(true); + chat.bottom_pane.set_task_running(/*running*/ true); chat.bottom_pane .set_composer_text("current draft".to_string(), Vec::new(), Vec::new()); @@ -10964,7 +11040,7 @@ async fn interrupt_prepends_queued_messages_before_existing_composer_text() { #[tokio::test] async fn interrupt_preserves_unified_exec_processes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; begin_unified_exec_startup(&mut chat, "call-1", "process-1", "sleep 5"); begin_unified_exec_startup(&mut chat, "call-2", "process-2", "sleep 6"); @@ -11001,7 +11077,7 @@ async fn interrupt_preserves_unified_exec_processes() { #[tokio::test] async fn review_ended_keeps_unified_exec_processes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; begin_unified_exec_startup(&mut chat, "call-1", "process-1", "sleep 5"); begin_unified_exec_startup(&mut chat, "call-2", "process-2", "sleep 6"); @@ -11038,7 +11114,7 @@ async fn review_ended_keeps_unified_exec_processes() { #[tokio::test] async fn interrupt_preserves_unified_exec_wait_streak_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "turn-1".into(), @@ -11060,7 +11136,7 @@ async fn interrupt_preserves_unified_exec_wait_streak_snapshot() { }), }); - end_exec(&mut chat, begin, "", "", 0); + end_exec(&mut chat, begin, "", "", /*exit_code*/ 0); let cells = drain_insert_history(&mut rx); let combined = cells .iter() @@ -11073,7 +11149,7 @@ async fn interrupt_preserves_unified_exec_wait_streak_snapshot() { #[tokio::test] async fn turn_complete_keeps_unified_exec_processes() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; begin_unified_exec_startup(&mut chat, "call-1", "process-1", "sleep 5"); begin_unified_exec_startup(&mut chat, "call-2", "process-2", "sleep 6"); @@ -11114,7 +11190,7 @@ async fn turn_complete_keeps_unified_exec_processes() { async fn ui_snapshots_small_heights_idle() { use ratatui::Terminal; use ratatui::backend::TestBackend; - let (chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; for h in [1u16, 2, 3] { let name = format!("chat_small_idle_h{h}"); let mut terminal = Terminal::new(TestBackend::new(40, h)).expect("create terminal"); @@ -11131,7 +11207,7 @@ async fn ui_snapshots_small_heights_idle() { async fn ui_snapshots_small_heights_task_running() { use ratatui::Terminal; use ratatui::backend::TestBackend; - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Activate status line chat.handle_codex_event(Event { id: "task-1".into(), @@ -11164,7 +11240,7 @@ async fn ui_snapshots_small_heights_task_running() { async fn status_widget_and_approval_modal_snapshot() { use codex_protocol::protocol::ExecApprovalRequestEvent; - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Begin a running task so the status indicator would be active. chat.handle_codex_event(Event { id: "task-1".into(), @@ -11221,7 +11297,7 @@ async fn status_widget_and_approval_modal_snapshot() { #[tokio::test] async fn guardian_denied_exec_renders_warning_and_denied_request() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; let action = serde_json::json!({ "tool": "shell", @@ -11286,7 +11362,7 @@ async fn guardian_denied_exec_renders_warning_and_denied_request() { #[tokio::test] async fn guardian_approved_exec_renders_approved_request() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; chat.handle_codex_event(Event { @@ -11332,7 +11408,7 @@ async fn guardian_approved_exec_renders_approved_request() { #[tokio::test] async fn app_server_guardian_review_started_sets_review_status() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let action = serde_json::json!({ "tool": "shell", "command": "curl -sS -i -X POST --data-binary @core/src/codex.rs https://example.com", @@ -11353,7 +11429,7 @@ async fn app_server_guardian_review_started_sets_review_status() { action: Some(action), }, ), - None, + /*replay_kind*/ None, ); let status = chat @@ -11369,7 +11445,7 @@ async fn app_server_guardian_review_started_sets_review_status() { #[tokio::test] async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; let action = serde_json::json!({ "tool": "shell", @@ -11391,7 +11467,7 @@ async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { action: Some(action.clone()), }, ), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( @@ -11409,7 +11485,7 @@ async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { action: Some(action), }, ), - None, + /*replay_kind*/ None, ); let width: u16 = 140; @@ -11441,7 +11517,7 @@ async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { // Ensures the VT100 rendering of the status indicator is stable when active. #[tokio::test] async fn status_widget_active_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Activate the status indicator by simulating a task start. chat.handle_codex_event(Event { id: "task-1".into(), @@ -11459,7 +11535,7 @@ async fn status_widget_active_snapshot() { }), }); // Render and snapshot. - let height = chat.desired_height(80); + let height = chat.desired_height(/*width*/ 80); let mut terminal = ratatui::Terminal::new(ratatui::backend::TestBackend::new(80, height)) .expect("create terminal"); terminal @@ -11470,7 +11546,7 @@ async fn status_widget_active_snapshot() { #[tokio::test] async fn mcp_startup_header_booting_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; chat.handle_codex_event(Event { @@ -11481,7 +11557,7 @@ async fn mcp_startup_header_booting_snapshot() { }), }); - let height = chat.desired_height(80); + let height = chat.desired_height(/*width*/ 80); let mut terminal = ratatui::Terminal::new(ratatui::backend::TestBackend::new(80, height)) .expect("create terminal"); terminal @@ -11492,7 +11568,7 @@ async fn mcp_startup_header_booting_snapshot() { #[tokio::test] async fn mcp_startup_complete_does_not_clear_running_task() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "task-1".into(), @@ -11520,7 +11596,7 @@ async fn mcp_startup_complete_does_not_clear_running_task() { #[tokio::test] async fn background_event_updates_status_header() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "bg-1".into(), @@ -11536,7 +11612,7 @@ async fn background_event_updates_status_header() { #[tokio::test] async fn guardian_parallel_reviews_render_aggregate_status_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); for (id, command) in [ @@ -11560,7 +11636,7 @@ async fn guardian_parallel_reviews_render_aggregate_status_snapshot() { }); } - let rendered = render_bottom_popup(&chat, 72); + let rendered = render_bottom_popup(&chat, /*width*/ 72); assert_snapshot!( "guardian_parallel_reviews_render_aggregate_status", rendered @@ -11569,7 +11645,7 @@ async fn guardian_parallel_reviews_render_aggregate_status_snapshot() { #[tokio::test] async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); chat.handle_codex_event(Event { @@ -11627,7 +11703,7 @@ async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial() #[tokio::test] async fn apply_patch_events_emit_history_cells() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // 1) Approval request -> proposed patch summary cell let mut changes = HashMap::new(); @@ -11654,7 +11730,7 @@ async fn apply_patch_events_emit_history_cells() { "expected approval request to surface via modal without emitting history cells" ); - let area = Rect::new(0, 0, 80, chat.desired_height(80)); + let area = Rect::new(0, 0, 80, chat.desired_height(/*width*/ 80)); let mut buf = ratatui::buffer::Buffer::empty(area); chat.render(area, &mut buf); let mut saw_summary = false; @@ -11726,7 +11802,7 @@ async fn apply_patch_events_emit_history_cells() { #[tokio::test] async fn apply_patch_manual_approval_adjusts_header() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let mut proposed_changes = HashMap::new(); proposed_changes.insert( @@ -11775,7 +11851,7 @@ async fn apply_patch_manual_approval_adjusts_header() { #[tokio::test] async fn apply_patch_manual_flow_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let mut proposed_changes = HashMap::new(); proposed_changes.insert( @@ -11828,7 +11904,7 @@ async fn apply_patch_manual_flow_snapshot() { #[tokio::test] async fn apply_patch_approval_sends_op_with_call_id() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Simulate receiving an approval request with a distinct event id and call id. let mut changes = HashMap::new(); changes.insert( @@ -11871,7 +11947,7 @@ async fn apply_patch_approval_sends_op_with_call_id() { #[tokio::test] async fn apply_patch_full_flow_integration_like() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // 1) Backend requests approval let mut changes = HashMap::new(); @@ -11950,7 +12026,7 @@ async fn apply_patch_full_flow_integration_like() { #[tokio::test] async fn apply_patch_untrusted_shows_approval_modal() -> anyhow::Result<()> { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Ensure approval policy is untrusted (OnRequest) chat.config .permissions @@ -12000,7 +12076,7 @@ async fn apply_patch_untrusted_shows_approval_modal() -> anyhow::Result<()> { #[tokio::test] async fn apply_patch_request_shows_diff_summary() -> anyhow::Result<()> { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Ensure we are in OnRequest so an approval is surfaced chat.config @@ -12035,7 +12111,7 @@ async fn apply_patch_request_shows_diff_summary() -> anyhow::Result<()> { "expected approval request to render via modal instead of history" ); - let area = Rect::new(0, 0, 80, chat.desired_height(80)); + let area = Rect::new(0, 0, 80, chat.desired_height(/*width*/ 80)); let mut buf = ratatui::buffer::Buffer::empty(area); chat.render(area, &mut buf); @@ -12071,7 +12147,7 @@ async fn apply_patch_request_shows_diff_summary() -> anyhow::Result<()> { #[tokio::test] async fn plan_update_renders_history_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let update = UpdatePlanArgs { explanation: Some("Adapting plan".to_string()), plan: vec![ @@ -12107,8 +12183,8 @@ async fn plan_update_renders_history_cell() { #[tokio::test] async fn stream_error_updates_status_indicator() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.bottom_pane.set_task_running(true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.bottom_pane.set_task_running(/*running*/ true); let msg = "Reconnecting... 2/5"; let details = "Idle timeout waiting for SSE"; chat.handle_codex_event(Event { @@ -12135,7 +12211,7 @@ async fn stream_error_updates_status_indicator() { #[tokio::test] async fn replayed_turn_started_does_not_mark_task_running() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.replay_initial_messages(vec![EventMsg::TurnStarted(TurnStartedEvent { turn_id: "turn-1".to_string(), @@ -12149,7 +12225,7 @@ async fn replayed_turn_started_does_not_mark_task_running() { #[tokio::test] async fn thread_snapshot_replayed_turn_started_marks_task_running() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event_replay(Event { id: "turn-1".into(), @@ -12171,7 +12247,7 @@ async fn thread_snapshot_replayed_turn_started_marks_task_running() { #[tokio::test] async fn replayed_in_progress_turn_marks_task_running() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.replay_thread_turns( vec![AppServerTurn { @@ -12194,7 +12270,7 @@ async fn replayed_in_progress_turn_marks_task_running() { #[tokio::test] async fn replayed_stream_error_does_not_set_retry_status_or_status_indicator() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.set_status_header("Idle".to_string()); chat.replay_initial_messages(vec![EventMsg::StreamError(StreamErrorEvent { @@ -12215,7 +12291,7 @@ async fn replayed_stream_error_does_not_set_retry_status_or_status_indicator() { #[tokio::test] async fn thread_snapshot_replayed_stream_recovery_restores_previous_status_header() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event_replay(Event { id: "task".into(), @@ -12255,7 +12331,7 @@ async fn thread_snapshot_replayed_stream_recovery_restores_previous_status_heade #[tokio::test] async fn resume_replay_interrupted_reconnect_does_not_leave_stale_working_state() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.set_status_header("Idle".to_string()); chat.replay_initial_messages(vec![ @@ -12287,7 +12363,7 @@ async fn resume_replay_interrupted_reconnect_does_not_leave_stale_working_state( #[tokio::test] async fn replayed_interrupted_reconnect_footer_row_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.replay_initial_messages(vec![ EventMsg::TurnStarted(TurnStartedEvent { @@ -12302,7 +12378,7 @@ async fn replayed_interrupted_reconnect_footer_row_snapshot() { }), ]); - let header = render_bottom_first_row(&chat, 80); + let header = render_bottom_first_row(&chat, /*width*/ 80); assert!( !header.contains("Reconnecting") && !header.contains("Working"), "expected replayed interrupted reconnect to avoid active status row, got {header:?}" @@ -12312,7 +12388,7 @@ async fn replayed_interrupted_reconnect_footer_row_snapshot() { #[tokio::test] async fn stream_error_restores_hidden_status_indicator() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.on_task_started(); chat.on_agent_message_delta("Preamble line\n".to_string()); chat.on_commit_tick(); @@ -12340,7 +12416,7 @@ async fn stream_error_restores_hidden_status_indicator() { #[tokio::test] async fn warning_event_adds_warning_history_cell() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "sub-1".into(), msg: EventMsg::Warning(WarningEvent { @@ -12359,7 +12435,7 @@ async fn warning_event_adds_warning_history_cell() { #[tokio::test] async fn status_line_invalid_items_warn_once() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.tui_status_line = Some(vec![ "model_name".to_string(), "bogus_item".to_string(), @@ -12387,7 +12463,7 @@ async fn status_line_invalid_items_warn_once() { #[tokio::test] async fn status_line_branch_state_resets_when_git_branch_disabled() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.status_line_branch = Some("main".to_string()); chat.status_line_branch_pending = true; chat.status_line_branch_lookup_complete = true; @@ -12402,7 +12478,7 @@ async fn status_line_branch_state_resets_when_git_branch_disabled() { #[tokio::test] async fn status_line_branch_refreshes_after_turn_complete() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.tui_status_line = Some(vec!["git-branch".to_string()]); chat.status_line_branch_lookup_complete = true; chat.status_line_branch_pending = false; @@ -12420,7 +12496,7 @@ async fn status_line_branch_refreshes_after_turn_complete() { #[tokio::test] async fn status_line_branch_refreshes_after_interrupt() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.tui_status_line = Some(vec!["git-branch".to_string()]); chat.status_line_branch_lookup_complete = true; chat.status_line_branch_pending = false; @@ -12438,7 +12514,7 @@ async fn status_line_branch_refreshes_after_interrupt() { #[tokio::test] async fn status_line_fast_mode_renders_on_and_off() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.config.tui_status_line = Some(vec!["fast-mode".to_string()]); chat.refresh_status_line(); @@ -12454,7 +12530,7 @@ async fn status_line_fast_mode_footer_snapshot() { use ratatui::Terminal; use ratatui::backend::TestBackend; - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.show_welcome_banner = false; chat.config.tui_status_line = Some(vec!["fast-mode".to_string()]); chat.set_service_tier(Some(ServiceTier::Fast)); @@ -12534,7 +12610,7 @@ async fn status_line_model_with_reasoning_fast_footer_snapshot() { #[tokio::test] async fn stream_recovery_restores_previous_status_header() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "task".into(), msg: EventMsg::TurnStarted(TurnStartedEvent { @@ -12571,8 +12647,8 @@ async fn stream_recovery_restores_previous_status_header() { #[tokio::test] async fn runtime_metrics_websocket_timing_logs_and_final_separator_sums_totals() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; - chat.set_feature_enabled(Feature::RuntimeMetrics, true); + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_feature_enabled(Feature::RuntimeMetrics, /*enabled*/ true); chat.on_task_started(); chat.apply_runtime_metrics_delta(RuntimeMetricsSummary { @@ -12601,11 +12677,11 @@ async fn runtime_metrics_websocket_timing_logs_and_final_separator_sums_totals() .expect("expected websocket timing log"); assert!(second_log.contains("TTFT: 80ms (iapi)")); - chat.on_task_complete(None, false); + chat.on_task_complete(/*last_agent_message*/ None, /*from_replay*/ false); let mut final_separator = None; while let Ok(event) = rx.try_recv() { if let AppEvent::InsertHistoryCell(cell) = event { - final_separator = Some(lines_to_single_string(&cell.display_lines(300))); + final_separator = Some(lines_to_single_string(&cell.display_lines(/*width*/ 300))); } } let final_separator = final_separator.expect("expected final separator with runtime metrics"); @@ -12615,7 +12691,7 @@ async fn runtime_metrics_websocket_timing_logs_and_final_separator_sums_totals() #[tokio::test] async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Begin turn chat.handle_codex_event(Event { @@ -12628,10 +12704,15 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { }); // First finalized assistant message - complete_assistant_message(&mut chat, "msg-first", "First message", None); + complete_assistant_message(&mut chat, "msg-first", "First message", /*phase*/ None); // Second finalized assistant message in the same turn - complete_assistant_message(&mut chat, "msg-second", "Second message", None); + complete_assistant_message( + &mut chat, + "msg-second", + "Second message", + /*phase*/ None, + ); // End turn chat.handle_codex_event(Event { @@ -12662,7 +12743,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { #[tokio::test] async fn final_reasoning_then_message_without_deltas_are_rendered() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // No deltas; only final reasoning followed by final message. chat.handle_codex_event(Event { @@ -12671,7 +12752,12 @@ async fn final_reasoning_then_message_without_deltas_are_rendered() { text: "I will first analyze the request.".into(), }), }); - complete_assistant_message(&mut chat, "msg-result", "Here is the result.", None); + complete_assistant_message( + &mut chat, + "msg-result", + "Here is the result.", + /*phase*/ None, + ); // Drain history and snapshot the combined visible content. let cells = drain_insert_history(&mut rx); @@ -12684,7 +12770,7 @@ async fn final_reasoning_then_message_without_deltas_are_rendered() { #[tokio::test] async fn deltas_then_same_final_message_are_rendered_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Stream some reasoning deltas first. chat.handle_codex_event(Event { @@ -12747,7 +12833,7 @@ async fn deltas_then_same_final_message_are_rendered_snapshot() { #[tokio::test] async fn user_prompt_submit_app_server_hook_notifications_render_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_server_notification( ServerNotification::HookStarted(AppServerHookStartedNotification { @@ -12769,7 +12855,7 @@ async fn user_prompt_submit_app_server_hook_notifications_render_snapshot() { entries: Vec::new(), }, }), - None, + /*replay_kind*/ None, ); chat.handle_server_notification( ServerNotification::HookCompleted(AppServerHookCompletedNotification { @@ -12800,7 +12886,7 @@ async fn user_prompt_submit_app_server_hook_notifications_render_snapshot() { ], }, }), - None, + /*replay_kind*/ None, ); let cells = drain_insert_history(&mut rx); @@ -12853,7 +12939,7 @@ async fn assert_hook_events_snapshot( status_message: &str, snapshot_name: &str, ) { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.handle_codex_event(Event { id: "hook-1".into(), @@ -12921,12 +13007,12 @@ async fn assert_hook_events_snapshot( // then the exec block, another blank line, the status line, a blank line, and the composer. #[tokio::test] async fn chatwidget_exec_and_status_layout_vt100_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; complete_assistant_message( &mut chat, "msg-search", "I’m going to search the repo for where β€œChange Approved” is rendered to update that view.", - None, + /*phase*/ None, ); let command = vec!["bash".into(), "-lc".into(), "rg \"Change Approved\"".into()]; @@ -13021,7 +13107,7 @@ async fn chatwidget_exec_and_status_layout_vt100_snapshot() { // E2E vt100 snapshot for complex markdown with indented and nested fenced code blocks #[tokio::test] async fn chatwidget_markdown_code_blocks_vt100_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; // Simulate a final agent message via streaming deltas instead of a single message @@ -13115,7 +13201,7 @@ printf 'fenced within fenced\n' #[tokio::test] async fn chatwidget_tall() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.handle_codex_event(Event { id: "t1".into(), @@ -13143,7 +13229,7 @@ async fn chatwidget_tall() { #[tokio::test] async fn enter_submits_steer_while_review_is_running() { - let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.handle_codex_event(Event { id: "turn-start".into(), @@ -13191,7 +13277,7 @@ async fn enter_submits_steer_while_review_is_running() { #[tokio::test] async fn review_queues_user_messages_snapshot() { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.handle_codex_event(Event { id: "turn-start".into(), @@ -13239,7 +13325,7 @@ async fn review_queues_user_messages_snapshot() { #[tokio::test] async fn compact_queues_user_messages_snapshot() { - let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; chat.thread_id = Some(ThreadId::new()); chat.handle_codex_event(Event { id: "turn-start".into(), diff --git a/codex-rs/tui_app_server/src/clipboard_text.rs b/codex-rs/tui_app_server/src/clipboard_text.rs index 019cbdba1..eee94b98f 100644 --- a/codex-rs/tui_app_server/src/clipboard_text.rs +++ b/codex-rs/tui_app_server/src/clipboard_text.rs @@ -202,13 +202,16 @@ mod tests { #[test] fn osc52_sequence_encodes_text_for_terminal_clipboard() { - assert_eq!(osc52_sequence("hello", false), "\u{1b}]52;c;aGVsbG8=\u{7}"); + assert_eq!( + osc52_sequence("hello", /*tmux*/ false), + "\u{1b}]52;c;aGVsbG8=\u{7}" + ); } #[test] fn osc52_sequence_wraps_tmux_passthrough() { assert_eq!( - osc52_sequence("hello", true), + osc52_sequence("hello", /*tmux*/ true), "\u{1b}Ptmux;\u{1b}\u{1b}]52;c;aGVsbG8=\u{7}\u{1b}\\" ); } diff --git a/codex-rs/tui_app_server/src/cwd_prompt.rs b/codex-rs/tui_app_server/src/cwd_prompt.rs index cf9e25615..0dace9c7b 100644 --- a/codex-rs/tui_app_server/src/cwd_prompt.rs +++ b/codex-rs/tui_app_server/src/cwd_prompt.rs @@ -268,7 +268,8 @@ mod tests { #[test] fn cwd_prompt_snapshot() { let screen = new_prompt(); - let mut terminal = Terminal::new(VT100Backend::new(80, 14)).expect("terminal"); + let mut terminal = + Terminal::new(VT100Backend::new(/*width*/ 80, /*height*/ 14)).expect("terminal"); terminal .draw(|frame| frame.render_widget_ref(&screen, frame.area())) .expect("render cwd prompt"); @@ -283,7 +284,8 @@ mod tests { "/Users/example/current".to_string(), "/Users/example/session".to_string(), ); - let mut terminal = Terminal::new(VT100Backend::new(80, 14)).expect("terminal"); + let mut terminal = + Terminal::new(VT100Backend::new(/*width*/ 80, /*height*/ 14)).expect("terminal"); terminal .draw(|frame| frame.render_widget_ref(&screen, frame.area())) .expect("render cwd prompt"); diff --git a/codex-rs/tui_app_server/src/debug_config.rs b/codex-rs/tui_app_server/src/debug_config.rs index 76f4a91a5..a6e652f79 100644 --- a/codex-rs/tui_app_server/src/debug_config.rs +++ b/codex-rs/tui_app_server/src/debug_config.rs @@ -752,7 +752,11 @@ approval_policy = "never" #[test] fn session_all_proxy_url_uses_socks_when_enabled() { assert_eq!( - session_all_proxy_url("127.0.0.1:3128", "127.0.0.1:8081", true), + session_all_proxy_url( + "127.0.0.1:3128", + "127.0.0.1:8081", + /*socks_enabled*/ true + ), "socks5h://127.0.0.1:8081".to_string() ); } @@ -760,7 +764,11 @@ approval_policy = "never" #[test] fn session_all_proxy_url_uses_http_when_socks_disabled() { assert_eq!( - session_all_proxy_url("127.0.0.1:3128", "127.0.0.1:8081", false), + session_all_proxy_url( + "127.0.0.1:3128", + "127.0.0.1:8081", + /*socks_enabled*/ false + ), "http://127.0.0.1:3128".to_string() ); } diff --git a/codex-rs/tui_app_server/src/diff_render.rs b/codex-rs/tui_app_server/src/diff_render.rs index ede36abf9..821146ec8 100644 --- a/codex-rs/tui_app_server/src/diff_render.rs +++ b/codex-rs/tui_app_server/src/diff_render.rs @@ -1356,7 +1356,7 @@ mod tests { assert_eq!(del_sign.bg, None); } fn diff_summary_for_tests(changes: &HashMap) -> Vec> { - create_diff_summary(changes, &PathBuf::from("/"), 80) + create_diff_summary(changes, &PathBuf::from("/"), /*wrap_cols*/ 80) } fn snapshot_lines(name: &str, lines: Vec>, width: u16, height: u16) { @@ -1493,16 +1493,21 @@ mod tests { // Call the wrapping function directly so we can precisely control the width let lines = push_wrapped_diff_line_with_style_context( - 1, + /*line_number*/ 1, DiffLineType::Insert, long_line, - 80, - line_number_width(1), + /*width*/ 80, + line_number_width(/*max_line_number*/ 1), current_diff_render_style_context(), ); // Render into a small terminal to capture the visual layout - snapshot_lines("wrap_behavior_insert", lines, 90, 8); + snapshot_lines( + "wrap_behavior_insert", + lines, + /*width*/ 90, + /*height*/ 8, + ); } #[test] @@ -1522,7 +1527,12 @@ mod tests { let lines = diff_summary_for_tests(&changes); - snapshot_lines("apply_update_block", lines, 80, 12); + snapshot_lines( + "apply_update_block", + lines, + /*width*/ 80, + /*height*/ 12, + ); } #[test] @@ -1542,7 +1552,12 @@ mod tests { let lines = diff_summary_for_tests(&changes); - snapshot_lines("apply_update_with_rename_block", lines, 80, 12); + snapshot_lines( + "apply_update_with_rename_block", + lines, + /*width*/ 80, + /*height*/ 12, + ); } #[test] @@ -1570,7 +1585,12 @@ mod tests { let lines = diff_summary_for_tests(&changes); - snapshot_lines("apply_multiple_files_block", lines, 80, 14); + snapshot_lines( + "apply_multiple_files_block", + lines, + /*width*/ 80, + /*height*/ 14, + ); } #[test] @@ -1585,7 +1605,12 @@ mod tests { let lines = diff_summary_for_tests(&changes); - snapshot_lines("apply_add_block", lines, 80, 10); + snapshot_lines( + "apply_add_block", + lines, + /*width*/ 80, + /*height*/ 10, + ); } #[test] @@ -1599,7 +1624,12 @@ mod tests { ); let lines = diff_summary_for_tests(&changes); - snapshot_lines("apply_delete_block", lines, 80, 12); + snapshot_lines( + "apply_delete_block", + lines, + /*width*/ 80, + /*height*/ 12, + ); } #[test] @@ -1618,10 +1648,15 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 72); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 72); // Render with backend width wider than wrap width to avoid Paragraph auto-wrap. - snapshot_lines("apply_update_block_wraps_long_lines", lines, 80, 12); + snapshot_lines( + "apply_update_block_wraps_long_lines", + lines, + /*width*/ 80, + /*height*/ 12, + ); } #[test] @@ -1641,7 +1676,7 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 28); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 28); snapshot_lines_text("apply_update_block_wraps_long_lines_text", &lines); } @@ -1668,7 +1703,7 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 80); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80); snapshot_lines_text("apply_update_block_line_numbers_three_digits_text", &lines); } @@ -1691,9 +1726,14 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &cwd, 80); + let lines = create_diff_summary(&changes, &cwd, /*wrap_cols*/ 80); - snapshot_lines("apply_update_block_relativizes_path", lines, 80, 10); + snapshot_lines( + "apply_update_block_relativizes_path", + lines, + /*width*/ 80, + /*height*/ 10, + ); } #[test] @@ -1707,11 +1747,11 @@ mod tests { let spans = &syntax_spans[0]; let lines = push_wrapped_diff_line_with_syntax_and_style_context( - 1, + /*line_number*/ 1, DiffLineType::Insert, long_rust, - 80, - line_number_width(1), + /*width*/ 80, + line_number_width(/*max_line_number*/ 1), spans, current_diff_render_style_context(), ); @@ -1722,7 +1762,12 @@ mod tests { lines.len() ); - snapshot_lines("syntax_highlighted_insert_wraps", lines, 90, 10); + snapshot_lines( + "syntax_highlighted_insert_wraps", + lines, + /*width*/ 90, + /*height*/ 10, + ); } #[test] @@ -1734,11 +1779,11 @@ mod tests { let spans = &syntax_spans[0]; let lines = push_wrapped_diff_line_with_syntax_and_style_context( - 1, + /*line_number*/ 1, DiffLineType::Insert, long_rust, - 80, - line_number_width(1), + /*width*/ 80, + line_number_width(/*max_line_number*/ 1), spans, current_diff_render_style_context(), ); @@ -1748,45 +1793,54 @@ mod tests { #[test] fn ui_snapshot_diff_gallery_80x24() { - snapshot_diff_gallery("diff_gallery_80x24", 80, 24); + snapshot_diff_gallery("diff_gallery_80x24", /*width*/ 80, /*height*/ 24); } #[test] fn ui_snapshot_diff_gallery_94x35() { - snapshot_diff_gallery("diff_gallery_94x35", 94, 35); + snapshot_diff_gallery("diff_gallery_94x35", /*width*/ 94, /*height*/ 35); } #[test] fn ui_snapshot_diff_gallery_120x40() { - snapshot_diff_gallery("diff_gallery_120x40", 120, 40); + snapshot_diff_gallery( + "diff_gallery_120x40", + /*width*/ 120, + /*height*/ 40, + ); } #[test] fn ui_snapshot_ansi16_insert_delete_no_background() { let mut lines = push_wrapped_diff_line_inner_with_theme_and_color_level( - 1, + /*line_number*/ 1, DiffLineType::Insert, "added in ansi16 mode", - 80, - line_number_width(2), - None, + /*width*/ 80, + line_number_width(/*max_line_number*/ 2), + /*syntax_spans*/ None, DiffTheme::Dark, DiffColorLevel::Ansi16, fallback_diff_backgrounds(DiffTheme::Dark, DiffColorLevel::Ansi16), ); lines.extend(push_wrapped_diff_line_inner_with_theme_and_color_level( - 2, + /*line_number*/ 2, DiffLineType::Delete, "deleted in ansi16 mode", - 80, - line_number_width(2), - None, + /*width*/ 80, + line_number_width(/*max_line_number*/ 2), + /*syntax_spans*/ None, DiffTheme::Dark, DiffColorLevel::Ansi16, fallback_diff_backgrounds(DiffTheme::Dark, DiffColorLevel::Ansi16), )); - snapshot_lines("ansi16_insert_delete_no_background", lines, 40, 4); + snapshot_lines( + "ansi16_insert_delete_no_background", + lines, + /*width*/ 40, + /*height*/ 4, + ); } #[test] @@ -1884,7 +1938,7 @@ mod tests { ); assert_eq!( style_line_bg_for(DiffLineType::Insert, backgrounds), - Style::default().bg(indexed_color(22)) + Style::default().bg(indexed_color(/*index*/ 22)) ); assert_eq!( style_line_bg_for(DiffLineType::Delete, backgrounds), @@ -2001,12 +2055,12 @@ mod tests { #[test] fn light_theme_wrapped_lines_keep_number_gutter_contrast() { let lines = push_wrapped_diff_line_inner_with_theme_and_color_level( - 12, + /*line_number*/ 12, DiffLineType::Insert, "abcdefghij", - 8, - line_number_width(12), - None, + /*width*/ 8, + line_number_width(/*max_line_number*/ 12), + /*syntax_spans*/ None, DiffTheme::Light, DiffColorLevel::TrueColor, fallback_diff_backgrounds(DiffTheme::Light, DiffColorLevel::TrueColor), @@ -2038,8 +2092,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Ansi16, TerminalName::WindowsTerminal, - false, - false, + /*has_wt_session*/ false, + /*has_force_color_override*/ false, ), DiffColorLevel::TrueColor ); @@ -2051,8 +2105,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Ansi16, TerminalName::Unknown, - true, - false, + /*has_wt_session*/ true, + /*has_force_color_override*/ false, ), DiffColorLevel::TrueColor ); @@ -2064,8 +2118,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Ansi16, TerminalName::WezTerm, - false, - false, + /*has_wt_session*/ false, + /*has_force_color_override*/ false, ), DiffColorLevel::Ansi16 ); @@ -2077,8 +2131,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Unknown, TerminalName::WindowsTerminal, - true, - false, + /*has_wt_session*/ true, + /*has_force_color_override*/ false, ), DiffColorLevel::TrueColor ); @@ -2090,8 +2144,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Unknown, TerminalName::WindowsTerminal, - false, - false, + /*has_wt_session*/ false, + /*has_force_color_override*/ false, ), DiffColorLevel::Ansi16 ); @@ -2103,8 +2157,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Ansi16, TerminalName::WindowsTerminal, - false, - true, + /*has_wt_session*/ false, + /*has_force_color_override*/ true, ), DiffColorLevel::Ansi16 ); @@ -2116,8 +2170,8 @@ mod tests { diff_color_level_for_terminal( StdoutColorLevel::Ansi256, TerminalName::WindowsTerminal, - true, - true, + /*has_wt_session*/ true, + /*has_force_color_override*/ true, ), DiffColorLevel::Ansi256 ); @@ -2133,7 +2187,7 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 80); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80); let has_rgb = lines.iter().any(|line| { line.spans .iter() @@ -2155,7 +2209,7 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 80); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80); let has_rgb = lines.iter().any(|line| { line.spans .iter() @@ -2183,7 +2237,7 @@ mod tests { fn wrap_styled_spans_single_line() { // Content that fits in one line should produce exactly one chunk. let spans = vec![RtSpan::raw("short")]; - let result = wrap_styled_spans(&spans, 80); + let result = wrap_styled_spans(&spans, /*max_cols*/ 80); assert_eq!(result.len(), 1); } @@ -2192,7 +2246,7 @@ mod tests { // Content wider than max_cols should produce multiple chunks. let long_text = "a".repeat(100); let spans = vec![RtSpan::raw(long_text)]; - let result = wrap_styled_spans(&spans, 40); + let result = wrap_styled_spans(&spans, /*max_cols*/ 40); assert!( result.len() >= 3, "100 chars at 40 cols should produce at least 3 lines, got {}", @@ -2211,7 +2265,7 @@ mod tests { RtSpan::styled("aaaa", style_a), // 4 cols, fills line exactly at max_cols=4 RtSpan::styled("bb", style_b), // should start on a new line ]; - let result = wrap_styled_spans(&spans, 4); + let result = wrap_styled_spans(&spans, /*max_cols*/ 4); assert_eq!( result.len(), 2, @@ -2231,7 +2285,7 @@ mod tests { let style = Style::default().fg(Color::Green); let text = "x".repeat(50); let spans = vec![RtSpan::styled(text, style)]; - let result = wrap_styled_spans(&spans, 20); + let result = wrap_styled_spans(&spans, /*max_cols*/ 20); for chunk in &result { for span in chunk { assert_eq!(span.style, style, "style should be preserved across wraps"); @@ -2244,7 +2298,7 @@ mod tests { // A tab should count as TAB_WIDTH columns, not zero. // With max_cols=8, a tab (4 cols) + "abcde" (5 cols) = 9 cols β†’ must wrap. let spans = vec![RtSpan::raw("\tabcde")]; - let result = wrap_styled_spans(&spans, 8); + let result = wrap_styled_spans(&spans, /*max_cols*/ 8); assert!( result.len() >= 2, "tab + 5 chars should exceed 8 cols and wrap, got {} line(s): {result:?}", @@ -2255,7 +2309,7 @@ mod tests { #[test] fn wrap_styled_spans_wraps_before_first_overflowing_char() { let spans = vec![RtSpan::raw("abcd\tη•Œ")]; - let result = wrap_styled_spans(&spans, 5); + let result = wrap_styled_spans(&spans, /*max_cols*/ 5); let line_text: Vec = result .iter() @@ -2285,11 +2339,11 @@ mod tests { fn fallback_wrapping_uses_display_width_for_tabs_and_wide_chars() { let width = 8; let lines = push_wrapped_diff_line_with_style_context( - 1, + /*line_number*/ 1, DiffLineType::Insert, "abcd\tη•ŒπŸ™‚", width, - line_number_width(1), + line_number_width(/*max_line_number*/ 1), current_diff_render_style_context(), ); @@ -2330,7 +2384,7 @@ mod tests { // Should complete quickly (no per-line parser init). If guardrails // are bypassed this would be extremely slow. - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 80); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80); // The diff rendered without timing out β€” the guardrails prevented // thousands of per-line parser initializations. Verify we actually @@ -2374,7 +2428,7 @@ mod tests { }, ); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 80); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80); let has_rgb = lines.iter().any(|line| { line.spans .iter() @@ -2413,7 +2467,7 @@ mod tests { .map(|span| span.style) .expect("expected highlighted span for second multiline string line"); - let lines = create_diff_summary(&changes, &PathBuf::from("/"), 120); + let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 120); let actual_style = lines .iter() .flat_map(|line| line.spans.iter()) diff --git a/codex-rs/tui_app_server/src/exec_cell/render.rs b/codex-rs/tui_app_server/src/exec_cell/render.rs index 1d5892aab..075b5a7ad 100644 --- a/codex-rs/tui_app_server/src/exec_cell/render.rs +++ b/codex-rs/tui_app_server/src/exec_cell/render.rs @@ -758,7 +758,7 @@ mod tests { interaction_input: None, }; - let cell = ExecCell::new(call, false); + let cell = ExecCell::new(call, /*animations_enabled*/ false); // Use a narrow width so each logical line wraps into many on-screen lines. let lines = cell.command_display_lines(width); @@ -796,8 +796,13 @@ mod tests { Line::from(" tail"), ]; - let truncated = - ExecCell::truncate_lines_middle(&lines, 2, 12, Some(4), Some(Line::from(" ".dim()))); + let truncated = ExecCell::truncate_lines_middle( + &lines, + /*max_rows*/ 2, + /*width*/ 12, + Some(4), + Some(Line::from(" ".dim())), + ); let rendered: Vec = truncated .iter() .map(|line| { @@ -820,7 +825,10 @@ mod tests { lines.extend(std::iter::repeat_n(Line::from(" "), 26)); lines.push(Line::from(" end")); - let truncated = ExecCell::truncate_lines_middle(&lines, 28, 80, None, None); + let truncated = ExecCell::truncate_lines_middle( + &lines, /*max_rows*/ 28, /*width*/ 80, /*omitted_hint*/ None, + /*ellipsis_prefix*/ None, + ); assert_eq!(truncated, lines); } @@ -840,9 +848,9 @@ mod tests { interaction_input: None, }; - let cell = ExecCell::new(call, false); + let cell = ExecCell::new(call, /*animations_enabled*/ false); let rendered: Vec = cell - .command_display_lines(36) + .command_display_lines(/*width*/ 36) .iter() .map(|line| { line.spans @@ -877,9 +885,9 @@ mod tests { interaction_input: None, }; - let cell = ExecCell::new(call, false); + let cell = ExecCell::new(call, /*animations_enabled*/ false); let rendered: Vec = cell - .display_lines(36) + .display_lines(/*width*/ 36) .iter() .map(|line| { line.spans @@ -918,9 +926,9 @@ mod tests { interaction_input: None, }; - let cell = ExecCell::new(call, false); + let cell = ExecCell::new(call, /*animations_enabled*/ false); let rendered: Vec = cell - .command_display_lines(36) + .command_display_lines(/*width*/ 36) .iter() .map(|line| { line.spans @@ -955,7 +963,7 @@ mod tests { interaction_input: None, }; - let cell = ExecCell::new(call, false); + let cell = ExecCell::new(call, /*animations_enabled*/ false); let width: u16 = 36; let logical_height = cell.transcript_lines(width).len() as u16; let wrapped_height = cell.desired_transcript_height(width); diff --git a/codex-rs/tui_app_server/src/history_cell.rs b/codex-rs/tui_app_server/src/history_cell.rs index 37d52b4f9..4aadbf06d 100644 --- a/codex-rs/tui_app_server/src/history_cell.rs +++ b/codex-rs/tui_app_server/src/history_cell.rs @@ -2948,7 +2948,7 @@ mod tests { ); assert_eq!( - render_lines(&cell.display_lines(80)), + render_lines(&cell.display_lines(/*width*/ 80)), vec![ "β€’ Generated Image:".to_string(), " β”” A tiny blue square".to_string(), @@ -2995,7 +2995,7 @@ mod tests { #[test] fn unified_exec_interaction_cell_renders_wait() { - let cell = new_unified_exec_interaction(None, String::new()); + let cell = new_unified_exec_interaction(/*command_display*/ None, String::new()); let lines = render_transcript(&cell); assert_eq!(lines, vec!["β€’ Waited for background terminal"]); } @@ -3033,7 +3033,7 @@ mod tests { turn_ttfm_ms: 0, }; let cell = FinalMessageSeparator::new(Some(12), Some(summary)); - let rendered = render_lines(&cell.display_lines(600)); + let rendered = render_lines(&cell.display_lines(/*width*/ 600)); assert_eq!(rendered.len(), 1); assert!(!rendered[0].contains("Worked for")); @@ -3050,8 +3050,8 @@ mod tests { #[test] fn final_message_separator_includes_worked_label_after_one_minute() { - let cell = FinalMessageSeparator::new(Some(61), None); - let rendered = render_lines(&cell.display_lines(200)); + let cell = FinalMessageSeparator::new(Some(61), /*runtime_metrics*/ None); + let rendered = render_lines(&cell.display_lines(/*width*/ 200)); assert_eq!(rendered.len(), 1); assert!(rendered[0].contains("Worked for")); @@ -3060,7 +3060,7 @@ mod tests { #[test] fn ps_output_empty_snapshot() { let cell = new_unified_exec_processes_output(Vec::new()); - let rendered = render_lines(&cell.display_lines(60)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 60)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3071,10 +3071,10 @@ mod tests { &config, "gpt-5", session_configured_event("gpt-5"), - false, + /*is_first_event*/ false, Some("Model just became available".to_string()), Some(PlanType::Free), - false, + /*show_fast_status*/ false, ); let rendered = render_transcript(&cell).join("\n"); @@ -3093,10 +3093,10 @@ mod tests { &config, "gpt-5", session_configured_event("gpt-5"), - false, + /*is_first_event*/ false, Some("Model just became available".to_string()), Some(PlanType::Free), - false, + /*show_fast_status*/ false, ); let rendered = render_transcript(&cell).join("\n"); @@ -3110,10 +3110,10 @@ mod tests { &config, "gpt-5", session_configured_event("gpt-5"), - true, + /*is_first_event*/ true, Some("Model just became available".to_string()), Some(PlanType::Free), - false, + /*show_fast_status*/ false, ); let rendered = render_transcript(&cell).join("\n"); @@ -3129,10 +3129,10 @@ mod tests { &config, "gpt-5", session_configured_event("gpt-5"), - false, + /*is_first_event*/ false, Some("Model just became available".to_string()), Some(PlanType::Free), - false, + /*show_fast_status*/ false, ); let rendered = render_transcript(&cell).join("\n"); @@ -3151,7 +3151,7 @@ mod tests { recent_chunks: vec!["src/main.rs:12:foo".to_string()], }, ]); - let rendered = render_lines(&cell.display_lines(40)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 40)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3163,7 +3163,7 @@ mod tests { ), recent_chunks: vec!["searching...".to_string()], }]); - let rendered = render_lines(&cell.display_lines(36)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 36)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3177,7 +3177,7 @@ mod tests { }) .collect(), ); - let rendered = render_lines(&cell.display_lines(32)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 32)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3190,7 +3190,7 @@ mod tests { " more indented".to_string(), ], }]); - let rendered = render_lines(&cell.display_lines(60)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 60)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3200,7 +3200,7 @@ mod tests { "Message exceeds the maximum length of 1048576 characters (1048577 provided)." .to_string(), ); - let rendered = render_lines(&cell.display_lines(120)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 120)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3265,7 +3265,7 @@ mod tests { HashMap::new(), &auth_statuses, ); - let rendered = render_lines(&cell.display_lines(120)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 120)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3276,7 +3276,7 @@ mod tests { let mut servers = config.mcp_servers.get().clone(); servers.insert( "some-server".to_string(), - stdio_server_config("docs-server", vec!["--stdio"], None, vec![]), + stdio_server_config("docs-server", vec!["--stdio"], /*env*/ None, vec![]), ); config .mcp_servers @@ -3305,7 +3305,7 @@ mod tests { HashMap::new(), &auth_statuses, ); - let rendered = render_lines(&cell.display_lines(120)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 120)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3313,7 +3313,8 @@ mod tests { #[tokio::test] async fn mcp_tools_output_from_statuses_renders_status_only_servers() { let mut config = test_config().await; - let mut plugin_docs = stdio_server_config("docs-server", vec!["--stdio"], None, vec![]); + let mut plugin_docs = + stdio_server_config("docs-server", vec!["--stdio"], /*env*/ None, vec![]); plugin_docs.enabled = false; plugin_docs.disabled_reason = Some(McpServerDisabledReason::Unknown); let servers = HashMap::from([("plugin_docs".to_string(), plugin_docs)]); @@ -3343,16 +3344,16 @@ mod tests { }]; let cell = new_mcp_tools_output_from_statuses(&config, &statuses); - let rendered = render_lines(&cell.display_lines(120)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 120)).join("\n"); insta::assert_snapshot!(rendered); } #[test] fn empty_agent_message_cell_transcript() { - let cell = AgentMessageCell::new(vec![Line::default()], false); - assert_eq!(cell.transcript_lines(80), vec![Line::from(" ")]); - assert_eq!(cell.desired_transcript_height(80), 1); + let cell = AgentMessageCell::new(vec![Line::default()], /*is_first_line*/ false); + assert_eq!(cell.transcript_lines(/*width*/ 80), vec![Line::from(" ")]); + assert_eq!(cell.desired_transcript_height(/*width*/ 80), 1); } #[test] @@ -3365,7 +3366,7 @@ mod tests { " this time".bold(), ]); let cell = PrefixedWrappedHistoryCell::new(summary, "βœ” ".green(), " "); - let rendered = render_lines(&cell.display_lines(24)); + let rendered = render_lines(&cell.display_lines(/*width*/ 24)); assert_eq!( rendered, vec![ @@ -3383,7 +3384,7 @@ mod tests { let url_like = "example.test/api/v1/projects/alpha-team/releases/2026-02-17/builds/1234567890"; let cell = PrefixedWrappedHistoryCell::new(Line::from(url_like), "βœ” ".green(), " "); - let rendered = render_lines(&cell.display_lines(24)); + let rendered = render_lines(&cell.display_lines(/*width*/ 24)); assert_eq!( rendered @@ -3400,7 +3401,7 @@ mod tests { let url_like = "example.test/api/v1/projects/alpha-team/releases/2026-02-17/builds/1234567890"; let cell = UnifiedExecInteractionCell::new(Some("true".to_string()), url_like.to_string()); - let rendered = render_lines(&cell.display_lines(24)); + let rendered = render_lines(&cell.display_lines(/*width*/ 24)); assert_eq!( rendered @@ -3497,7 +3498,7 @@ mod tests { queries: None, }, ); - let rendered = render_lines(&cell.display_lines(64)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 64)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3514,7 +3515,7 @@ mod tests { queries: None, }, ); - let rendered = render_lines(&cell.display_lines(64)); + let rendered = render_lines(&cell.display_lines(/*width*/ 64)); assert_eq!( rendered, @@ -3536,7 +3537,7 @@ mod tests { queries: None, }, ); - let rendered = render_lines(&cell.display_lines(64)); + let rendered = render_lines(&cell.display_lines(/*width*/ 64)); assert_eq!(rendered, vec!["β€’ Searched short query".to_string()]); } @@ -3553,7 +3554,7 @@ mod tests { queries: None, }, ); - let rendered = render_lines(&cell.transcript_lines(64)).join("\n"); + let rendered = render_lines(&cell.transcript_lines(/*width*/ 64)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3569,8 +3570,12 @@ mod tests { })), }; - let cell = new_active_mcp_tool_call("call-1".into(), invocation, true); - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let cell = new_active_mcp_tool_call( + "call-1".into(), + invocation, + /*animations_enabled*/ true, + ); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3578,7 +3583,7 @@ mod tests { #[test] fn mcp_inventory_loading_snapshot() { let cell = new_mcp_inventory_loading(/*animations_enabled*/ true); - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3601,13 +3606,17 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-2".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-2".into(), + invocation, + /*animations_enabled*/ true, + ); assert!( cell.complete(Duration::from_millis(1420), Ok(result)) .is_none() ); - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3632,12 +3641,16 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-image".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-image".into(), + invocation, + /*animations_enabled*/ true, + ); let extra_cell = cell .complete(Duration::from_millis(25), Ok(result)) .expect("expected image cell"); - let rendered = render_lines(&extra_cell.display_lines(80)); + let rendered = render_lines(&extra_cell.display_lines(/*width*/ 80)); assert_eq!(rendered, vec!["tool result (image output)"]); } @@ -3659,12 +3672,16 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-image-data-url".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-image-data-url".into(), + invocation, + /*animations_enabled*/ true, + ); let extra_cell = cell .complete(Duration::from_millis(25), Ok(result)) .expect("expected image cell"); - let rendered = render_lines(&extra_cell.display_lines(80)); + let rendered = render_lines(&extra_cell.display_lines(/*width*/ 80)); assert_eq!(rendered, vec!["tool result (image output)"]); } @@ -3685,12 +3702,16 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-image-2".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-image-2".into(), + invocation, + /*animations_enabled*/ true, + ); let extra_cell = cell .complete(Duration::from_millis(25), Ok(result)) .expect("expected image cell"); - let rendered = render_lines(&extra_cell.display_lines(80)); + let rendered = render_lines(&extra_cell.display_lines(/*width*/ 80)); assert_eq!(rendered, vec!["tool result (image output)"]); } @@ -3705,13 +3726,17 @@ mod tests { })), }; - let mut cell = new_active_mcp_tool_call("call-3".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-3".into(), + invocation, + /*animations_enabled*/ true, + ); assert!( cell.complete(Duration::from_secs(2), Err("network timeout".into())) .is_none() ); - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3744,13 +3769,17 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-4".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-4".into(), + invocation, + /*animations_enabled*/ true, + ); assert!( cell.complete(Duration::from_millis(640), Ok(result)) .is_none() ); - let rendered = render_lines(&cell.display_lines(48)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 48)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3775,13 +3804,17 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-5".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-5".into(), + invocation, + /*animations_enabled*/ true, + ); assert!( cell.complete(Duration::from_millis(1280), Ok(result)) .is_none() ); - let rendered = render_lines(&cell.display_lines(40)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 40)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3807,13 +3840,17 @@ mod tests { meta: None, }; - let mut cell = new_active_mcp_tool_call("call-6".into(), invocation, true); + let mut cell = new_active_mcp_tool_call( + "call-6".into(), + invocation, + /*animations_enabled*/ true, + ); assert!( cell.complete(Duration::from_millis(320), Ok(result)) .is_none() ); - let rendered = render_lines(&cell.display_lines(120)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 120)).join("\n"); insta::assert_snapshot!(rendered); } @@ -3823,12 +3860,12 @@ mod tests { let cell = SessionHeaderHistoryCell::new( "gpt-4o".to_string(), Some(ReasoningEffortConfig::High), - true, + /*show_fast_status*/ true, std::env::temp_dir(), "test", ); - let lines = render_lines(&cell.display_lines(80)); + let lines = render_lines(&cell.display_lines(/*width*/ 80)); let model_line = lines .iter() .find(|line| line.contains("model:")) @@ -3843,12 +3880,12 @@ mod tests { let cell = SessionHeaderHistoryCell::new( "gpt-4o".to_string(), Some(ReasoningEffortConfig::High), - false, + /*show_fast_status*/ false, std::env::temp_dir(), "test", ); - let lines = render_lines(&cell.display_lines(80)); + let lines = render_lines(&cell.display_lines(/*width*/ 80)); let model_line = lines .iter() .find(|line| line.contains("model:")) @@ -3913,12 +3950,12 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); // Mark call complete so markers are βœ“ cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -3940,7 +3977,7 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); // Call 1: Search only cell.complete_call("c1", CommandOutput::default(), Duration::from_millis(1)); @@ -3955,7 +3992,7 @@ mod tests { path: "shimmer.rs".into(), }], ExecCommandSource::Agent, - None, + /*interaction_input*/ None, ) .unwrap(); cell.complete_call("c2", CommandOutput::default(), Duration::from_millis(1)); @@ -3970,12 +4007,12 @@ mod tests { path: "status_indicator_widget.rs".into(), }], ExecCommandSource::Agent, - None, + /*interaction_input*/ None, ) .unwrap(); cell.complete_call("c3", CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4009,10 +4046,10 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); cell.complete_call("c1", CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4033,7 +4070,7 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); // Mark call complete so it renders as "Ran" cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); @@ -4059,11 +4096,11 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); // Wide enough that it fits inline - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4083,10 +4120,10 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(24); + let lines = cell.display_lines(/*width*/ 24); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4106,10 +4143,10 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4130,10 +4167,10 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); cell.complete_call(&call_id, CommandOutput::default(), Duration::from_millis(1)); - let lines = cell.display_lines(28); + let lines = cell.display_lines(/*width*/ 28); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4154,7 +4191,7 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); let stderr: String = (1..=10) .map(|n| n.to_string()) @@ -4171,7 +4208,7 @@ mod tests { ); let rendered = cell - .display_lines(80) + .display_lines(/*width*/ 80) .iter() .map(|l| { l.spans @@ -4204,7 +4241,7 @@ mod tests { duration: None, interaction_input: None, }, - true, + /*animations_enabled*/ true, ); let stderr = "error: first line on stderr\nerror: second line on stderr".to_string(); @@ -4260,7 +4297,7 @@ mod tests { remote_image_urls: vec!["https://example.com/example.png".to_string()], }; - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); assert!(rendered.contains("[Image #1]")); assert!(rendered.contains("describe these")); @@ -4276,7 +4313,7 @@ mod tests { remote_image_urls: vec!["data:image/png;base64,aGVsbG8=".to_string()], }; - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); assert!(rendered.contains("[Image #1]")); assert!(rendered.contains("describe inline image")); @@ -4294,7 +4331,7 @@ mod tests { ], }; - let rendered = render_lines(&cell.display_lines(80)).join("\n"); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)).join("\n"); assert!(rendered.contains("[Image #1]")); assert!(rendered.contains("[Image #2]")); @@ -4332,7 +4369,7 @@ mod tests { remote_image_urls: vec!["https://example.com/one.png".to_string()], }; - let rendered = render_lines(&cell.display_lines(80)); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)); let trailing_blank_count = rendered .iter() .rev() @@ -4355,7 +4392,7 @@ mod tests { remote_image_urls: vec!["https://example.com/one.png".to_string()], }; - let rendered = render_lines(&cell.display_lines(80)); + let rendered = render_lines(&cell.display_lines(/*width*/ 80)); let trailing_blank_count = rendered .iter() .rev() @@ -4440,7 +4477,7 @@ mod tests { let cell = new_plan_update(update); // Narrow width to force wrapping for both the note and steps - let lines = cell.display_lines(32); + let lines = cell.display_lines(/*width*/ 32); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4462,7 +4499,7 @@ mod tests { }; let cell = new_plan_update(update); - let lines = cell.display_lines(40); + let lines = cell.display_lines(/*width*/ 40); let rendered = render_lines(&lines).join("\n"); insta::assert_snapshot!(rendered); } @@ -4483,7 +4520,7 @@ mod tests { }; let cell = new_plan_update(update); - let rendered = render_lines(&cell.display_lines(30)); + let rendered = render_lines(&cell.display_lines(/*width*/ 30)); assert_eq!( rendered @@ -4510,7 +4547,7 @@ mod tests { &test_cwd(), ); - let rendered_display = render_lines(&cell.display_lines(80)); + let rendered_display = render_lines(&cell.display_lines(/*width*/ 80)); assert_eq!(rendered_display, vec!["β€’ Detailed reasoning goes here."]); let rendered_transcript = render_transcript(cell.as_ref()); @@ -4524,7 +4561,7 @@ mod tests { "High level reasoning".to_string(), summary.to_string(), &test_cwd(), - false, + /*transcript_only*/ false, )); let width: u16 = 24; @@ -4581,7 +4618,7 @@ mod tests { &test_cwd(), ); - let rendered_display = render_lines(&cell.display_lines(80)); + let rendered_display = render_lines(&cell.display_lines(/*width*/ 80)); assert_eq!(rendered_display, vec!["β€’ Detailed reasoning goes here."]); } @@ -4622,7 +4659,7 @@ mod tests { &test_cwd(), ); - let rendered_display = render_lines(&cell.display_lines(80)); + let rendered_display = render_lines(&cell.display_lines(/*width*/ 80)); assert_eq!(rendered_display, vec!["β€’ We should fix the bug next."]); let rendered_transcript = render_transcript(cell.as_ref()); @@ -4635,7 +4672,7 @@ mod tests { "Feature flag `foo`".to_string(), Some("Use flag `bar` instead.".to_string()), ); - let lines = cell.display_lines(80); + let lines = cell.display_lines(/*width*/ 80); let rendered = render_lines(&lines); assert_eq!( rendered, diff --git a/codex-rs/tui_app_server/src/lib.rs b/codex-rs/tui_app_server/src/lib.rs index a58dfc5fe..b84d39a03 100644 --- a/codex-rs/tui_app_server/src/lib.rs +++ b/codex-rs/tui_app_server/src/lib.rs @@ -1815,7 +1815,7 @@ mod tests { let cwd = temp_dir.path().join("project"); let params = latest_session_lookup_params( - false, + /*is_remote*/ false, &config, Some(cwd.as_path()), /*include_non_interactive*/ false, @@ -1834,7 +1834,7 @@ mod tests { let cwd = temp_dir.path().join("project"); let params = latest_session_lookup_params( - true, + /*is_remote*/ true, &config, Some(cwd.as_path()), /*include_non_interactive*/ false, @@ -1850,7 +1850,7 @@ mod tests { let temp_dir = TempDir::new()?; let config = build_config(&temp_dir).await?; - let cwd = read_session_cwd(&config, ThreadId::new(), None).await; + let cwd = read_session_cwd(&config, ThreadId::new(), /*path*/ None).await; assert_eq!(cwd, None); Ok(()) @@ -1862,7 +1862,7 @@ mod tests { let temp_dir = TempDir::new()?; let mut config = build_config(&temp_dir).await?; config.active_project = ProjectConfig { trust_level: None }; - config.set_windows_sandbox_enabled(false); + config.set_windows_sandbox_enabled(/*value*/ false); let should_show = should_show_trust_screen(&config); assert!( @@ -1914,7 +1914,7 @@ mod tests { .await .map_err(std::io::Error::other)?; state_runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .map_err(std::io::Error::other)?; @@ -1986,7 +1986,7 @@ mod tests { let temp_dir = TempDir::new()?; let mut config = build_config(&temp_dir).await?; config.active_project = ProjectConfig { trust_level: None }; - config.set_windows_sandbox_enabled(true); + config.set_windows_sandbox_enabled(/*value*/ true); let should_show = should_show_trust_screen(&config); if cfg!(target_os = "windows") { @@ -2288,7 +2288,7 @@ trust_level = "untrusted" .await .map_err(std::io::Error::other)?; runtime - .mark_backfill_complete(None) + .mark_backfill_complete(/*last_watermark*/ None) .await .map_err(std::io::Error::other)?; diff --git a/codex-rs/tui_app_server/src/live_wrap.rs b/codex-rs/tui_app_server/src/live_wrap.rs index e09a2c632..91d7e6f04 100644 --- a/codex-rs/tui_app_server/src/live_wrap.rs +++ b/codex-rs/tui_app_server/src/live_wrap.rs @@ -213,7 +213,7 @@ mod tests { #[test] fn rows_do_not_exceed_width_ascii() { - let mut rb = RowBuilder::new(10); + let mut rb = RowBuilder::new(/*target_width*/ 10); rb.push_fragment("hello whirl this is a test"); let rows = rb.rows().to_vec(); assert_eq!( @@ -234,7 +234,7 @@ mod tests { #[test] fn rows_do_not_exceed_width_emoji_cjk() { // πŸ˜€ is width 2; δ½ /ε₯½ are width 2. - let mut rb = RowBuilder::new(6); + let mut rb = RowBuilder::new(/*target_width*/ 6); rb.push_fragment("πŸ˜€πŸ˜€ δ½ ε₯½"); let rows = rb.rows().to_vec(); // At width 6, we expect the first row to fit exactly two emojis and a space @@ -252,11 +252,11 @@ mod tests { #[test] fn fragmentation_invariance_long_token() { let s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26 chars - let mut rb_all = RowBuilder::new(7); + let mut rb_all = RowBuilder::new(/*target_width*/ 7); rb_all.push_fragment(s); let all_rows = rb_all.rows().to_vec(); - let mut rb_chunks = RowBuilder::new(7); + let mut rb_chunks = RowBuilder::new(/*target_width*/ 7); for i in (0..s.len()).step_by(3) { let end = (i + 3).min(s.len()); rb_chunks.push_fragment(&s[i..end]); @@ -268,7 +268,7 @@ mod tests { #[test] fn newline_splits_rows() { - let mut rb = RowBuilder::new(10); + let mut rb = RowBuilder::new(/*target_width*/ 10); rb.push_fragment("hello\nworld"); let rows = rb.display_rows(); assert!(rows.iter().any(|r| r.explicit_break)); @@ -279,10 +279,10 @@ mod tests { #[test] fn rewrap_on_width_change() { - let mut rb = RowBuilder::new(10); + let mut rb = RowBuilder::new(/*target_width*/ 10); rb.push_fragment("abcdefghijK"); assert!(!rb.rows().is_empty()); - rb.set_width(5); + rb.set_width(/*width*/ 5); for r in rb.rows() { assert!(r.width() <= 5); } diff --git a/codex-rs/tui_app_server/src/local_chatgpt_auth.rs b/codex-rs/tui_app_server/src/local_chatgpt_auth.rs index 85e920f1d..b671d818e 100644 --- a/codex-rs/tui_app_server/src/local_chatgpt_auth.rs +++ b/codex-rs/tui_app_server/src/local_chatgpt_auth.rs @@ -132,8 +132,12 @@ mod tests { fn rejects_missing_local_auth() { let codex_home = TempDir::new().expect("tempdir"); - let err = load_local_chatgpt_auth(codex_home.path(), AuthCredentialsStoreMode::File, None) - .expect_err("missing auth should fail"); + let err = load_local_chatgpt_auth( + codex_home.path(), + AuthCredentialsStoreMode::File, + /*forced_chatgpt_workspace_id*/ None, + ) + .expect_err("missing auth should fail"); assert_eq!(err, "no local auth available"); } @@ -153,8 +157,12 @@ mod tests { ) .expect("api key auth should save"); - let err = load_local_chatgpt_auth(codex_home.path(), AuthCredentialsStoreMode::File, None) - .expect_err("api key auth should fail"); + let err = load_local_chatgpt_auth( + codex_home.path(), + AuthCredentialsStoreMode::File, + /*forced_chatgpt_workspace_id*/ None, + ) + .expect_err("api key auth should fail"); assert_eq!(err, "local auth is not a ChatGPT login"); } diff --git a/codex-rs/tui_app_server/src/markdown.rs b/codex-rs/tui_app_server/src/markdown.rs index 228febb85..e29246e76 100644 --- a/codex-rs/tui_app_server/src/markdown.rs +++ b/codex-rs/tui_app_server/src/markdown.rs @@ -41,7 +41,7 @@ mod tests { fn citations_render_as_plain_text() { let src = "Before 【F:/x.rs†L1】\nAfter 【F:/x.rs†L3】\n"; let mut out = Vec::new(); - append_markdown(src, None, None, &mut out); + append_markdown(src, /*width*/ None, /*cwd*/ None, &mut out); let rendered = lines_to_strings(&out); assert_eq!( rendered, @@ -57,7 +57,7 @@ mod tests { // Basic sanity: indented code with surrounding blank lines should produce the indented line. let src = "Before\n\n code 1\n\nAfter\n"; let mut out = Vec::new(); - append_markdown(src, None, None, &mut out); + append_markdown(src, /*width*/ None, /*cwd*/ None, &mut out); let lines = lines_to_strings(&out); assert_eq!(lines, vec!["Before", "", " code 1", "", "After"]); } @@ -66,7 +66,7 @@ mod tests { fn append_markdown_preserves_full_text_line() { let src = "Hi! How can I help with codex-rs today? Want me to explore the repo, run tests, or work on a specific change?\n"; let mut out = Vec::new(); - append_markdown(src, None, None, &mut out); + append_markdown(src, /*width*/ None, /*cwd*/ None, &mut out); assert_eq!( out.len(), 1, @@ -87,7 +87,12 @@ mod tests { #[test] fn append_markdown_matches_tui_markdown_for_ordered_item() { let mut out = Vec::new(); - append_markdown("1. Tight item\n", None, None, &mut out); + append_markdown( + "1. Tight item\n", + /*width*/ None, + /*cwd*/ None, + &mut out, + ); let lines = lines_to_strings(&out); assert_eq!(lines, vec!["1. Tight item".to_string()]); } @@ -96,7 +101,7 @@ mod tests { fn append_markdown_keeps_ordered_list_line_unsplit_in_context() { let src = "Loose vs. tight list items:\n1. Tight item\n"; let mut out = Vec::new(); - append_markdown(src, None, None, &mut out); + append_markdown(src, /*width*/ None, /*cwd*/ None, &mut out); let lines = lines_to_strings(&out); diff --git a/codex-rs/tui_app_server/src/markdown_render_tests.rs b/codex-rs/tui_app_server/src/markdown_render_tests.rs index fe7748226..4c6472a02 100644 --- a/codex-rs/tui_app_server/src/markdown_render_tests.rs +++ b/codex-rs/tui_app_server/src/markdown_render_tests.rs @@ -12,7 +12,7 @@ use crate::markdown_render::render_markdown_text_with_width_and_cwd; use insta::assert_snapshot; fn render_markdown_text_for_cwd(input: &str, cwd: &Path) -> Text<'static> { - render_markdown_text_with_width_and_cwd(input, None, Some(cwd)) + render_markdown_text_with_width_and_cwd(input, /*width*/ None, Some(cwd)) } #[test] diff --git a/codex-rs/tui_app_server/src/markdown_stream.rs b/codex-rs/tui_app_server/src/markdown_stream.rs index a18457d6b..3eb37e345 100644 --- a/codex-rs/tui_app_server/src/markdown_stream.rs +++ b/codex-rs/tui_app_server/src/markdown_stream.rs @@ -118,7 +118,7 @@ pub(crate) fn simulate_stream_markdown_for_tests( deltas: &[&str], finalize: bool, ) -> Vec> { - let mut collector = MarkdownStreamCollector::new(None, &test_cwd()); + let mut collector = MarkdownStreamCollector::new(/*width*/ None, &test_cwd()); let mut out = Vec::new(); for d in deltas { collector.push_delta(d); @@ -139,7 +139,7 @@ mod tests { #[tokio::test] async fn no_commit_until_newline() { - let mut c = super::MarkdownStreamCollector::new(None, &super::test_cwd()); + let mut c = super::MarkdownStreamCollector::new(/*width*/ None, &super::test_cwd()); c.push_delta("Hello, world"); let out = c.commit_complete_lines(); assert!(out.is_empty(), "should not commit without newline"); @@ -150,7 +150,7 @@ mod tests { #[tokio::test] async fn finalize_commits_partial_line() { - let mut c = super::MarkdownStreamCollector::new(None, &super::test_cwd()); + let mut c = super::MarkdownStreamCollector::new(/*width*/ None, &super::test_cwd()); c.push_delta("Line without newline"); let out = c.finalize_and_drain(); assert_eq!(out.len(), 1); @@ -158,7 +158,7 @@ mod tests { #[tokio::test] async fn e2e_stream_blockquote_simple_is_green() { - let out = super::simulate_stream_markdown_for_tests(&["> Hello\n"], true); + let out = super::simulate_stream_markdown_for_tests(&["> Hello\n"], /*finalize*/ true); assert_eq!(out.len(), 1); let l = &out[0]; assert_eq!( @@ -171,7 +171,10 @@ mod tests { #[tokio::test] async fn e2e_stream_blockquote_nested_is_green() { - let out = super::simulate_stream_markdown_for_tests(&["> Level 1\n>> Level 2\n"], true); + let out = super::simulate_stream_markdown_for_tests( + &["> Level 1\n>> Level 2\n"], + /*finalize*/ true, + ); // Filter out any blank lines that may be inserted at paragraph starts. let non_blank: Vec<_> = out .into_iter() @@ -194,7 +197,10 @@ mod tests { #[tokio::test] async fn e2e_stream_blockquote_with_list_items_is_green() { - let out = super::simulate_stream_markdown_for_tests(&["> - item 1\n> - item 2\n"], true); + let out = super::simulate_stream_markdown_for_tests( + &["> - item 1\n> - item 2\n"], + /*finalize*/ true, + ); assert_eq!(out.len(), 2); assert_eq!(out[0].style.fg, Some(Color::Green)); assert_eq!(out[1].style.fg, Some(Color::Green)); @@ -209,7 +215,7 @@ mod tests { " - Fourth level (bullet)\n", " - Fifth level to test indent consistency\n", ]; - let out = super::simulate_stream_markdown_for_tests(&md, true); + let out = super::simulate_stream_markdown_for_tests(&md, /*finalize*/ true); // Find the line that contains the third-level ordered text let find_idx = out.iter().position(|l| { l.spans @@ -234,10 +240,12 @@ mod tests { #[tokio::test] async fn e2e_stream_blockquote_wrap_preserves_green_style() { let long = "> This is a very long quoted line that should wrap across multiple columns to verify style preservation."; - let out = super::simulate_stream_markdown_for_tests(&[long, "\n"], true); + let out = super::simulate_stream_markdown_for_tests(&[long, "\n"], /*finalize*/ true); // Wrap to a narrow width to force multiple output lines. - let wrapped = - crate::wrapping::word_wrap_lines(out.iter(), crate::wrapping::RtOptions::new(24)); + let wrapped = crate::wrapping::word_wrap_lines( + out.iter(), + crate::wrapping::RtOptions::new(/*width*/ 24), + ); // Filter out purely blank lines let non_blank: Vec<_> = wrapped .into_iter() @@ -270,7 +278,7 @@ mod tests { async fn heading_starts_on_new_line_when_following_paragraph() { // Stream a paragraph line, then a heading on the next line. // Expect two distinct rendered lines: "Hello." and "Heading". - let mut c = super::MarkdownStreamCollector::new(None, &super::test_cwd()); + let mut c = super::MarkdownStreamCollector::new(/*width*/ None, &super::test_cwd()); c.push_delta("Hello.\n"); let out1 = c.commit_complete_lines(); let s1: Vec = out1 @@ -326,7 +334,7 @@ mod tests { // Paragraph without trailing newline, then a chunk that starts with the newline // and the heading text, then a final newline. The collector should first commit // only the paragraph line, and later commit the heading as its own line. - let mut c = super::MarkdownStreamCollector::new(None, &super::test_cwd()); + let mut c = super::MarkdownStreamCollector::new(/*width*/ None, &super::test_cwd()); c.push_delta("Sounds good!"); // No commit yet assert!(c.commit_complete_lines().is_empty()); @@ -372,7 +380,12 @@ mod tests { // Sanity check raw markdown rendering for a simple line does not produce spurious extras. let mut rendered: Vec> = Vec::new(); let test_cwd = super::test_cwd(); - crate::markdown::append_markdown("Hello.\n", None, Some(test_cwd.as_path()), &mut rendered); + crate::markdown::append_markdown( + "Hello.\n", + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered, + ); let rendered_strings: Vec = rendered .iter() .map(|l| { @@ -428,12 +441,17 @@ mod tests { "\n", ]; - let streamed = simulate_stream_markdown_for_tests(&deltas, true); + let streamed = simulate_stream_markdown_for_tests(&deltas, /*finalize*/ true); let streamed_str = lines_to_plain_strings(&streamed); let mut rendered_all: Vec> = Vec::new(); let test_cwd = super::test_cwd(); - crate::markdown::append_markdown(input, None, Some(test_cwd.as_path()), &mut rendered_all); + crate::markdown::append_markdown( + input, + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered_all, + ); let rendered_all_str = lines_to_plain_strings(&rendered_all); assert_eq!( @@ -445,7 +463,7 @@ mod tests { #[tokio::test] async fn e2e_stream_deep_nested_third_level_marker_is_light_blue() { let md = "1. First\n - Second level\n 1. Third level (ordered)\n - Fourth level (bullet)\n - Fifth level to test indent consistency\n"; - let streamed = super::simulate_stream_markdown_for_tests(&[md], true); + let streamed = super::simulate_stream_markdown_for_tests(&[md], /*finalize*/ true); let streamed_strs = lines_to_plain_strings(&streamed); // Locate the third-level line in the streamed output; avoid relying on exact indent. @@ -496,7 +514,7 @@ mod tests { // An empty fenced code block followed by a heading should not render the fence, // but should preserve a blank separator line so the heading starts on a new line. let deltas = vec!["```bash\n```\n", "## Heading\n"]; // empty block and close in same commit - let streamed = simulate_stream_markdown_for_tests(&deltas, true); + let streamed = simulate_stream_markdown_for_tests(&deltas, /*finalize*/ true); let texts = lines_to_plain_strings(&streamed); assert!( texts.iter().all(|s| !s.contains("```")), @@ -512,7 +530,7 @@ mod tests { #[tokio::test] async fn paragraph_then_empty_fence_then_heading_keeps_heading_on_new_line() { let deltas = vec!["Para.\n", "```\n```\n", "## Title\n"]; // empty fence block in one commit - let streamed = simulate_stream_markdown_for_tests(&deltas, true); + let streamed = simulate_stream_markdown_for_tests(&deltas, /*finalize*/ true); let texts = lines_to_plain_strings(&streamed); let para_idx = match texts.iter().position(|s| s == "Para.") { Some(i) => i, @@ -534,13 +552,18 @@ mod tests { // that still reproduce the mismatch. let deltas = vec!["- item.\n\n", "-"]; - let streamed = simulate_stream_markdown_for_tests(&deltas, true); + let streamed = simulate_stream_markdown_for_tests(&deltas, /*finalize*/ true); let streamed_strs = lines_to_plain_strings(&streamed); let full: String = deltas.iter().copied().collect(); let mut rendered_all: Vec> = Vec::new(); let test_cwd = super::test_cwd(); - crate::markdown::append_markdown(&full, None, Some(test_cwd.as_path()), &mut rendered_all); + crate::markdown::append_markdown( + &full, + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered_all, + ); let rendered_all_strs = lines_to_plain_strings(&rendered_all); assert_eq!( @@ -622,14 +645,19 @@ mod tests { "\n\n", ]; - let streamed = simulate_stream_markdown_for_tests(&deltas, true); + let streamed = simulate_stream_markdown_for_tests(&deltas, /*finalize*/ true); let streamed_strs = lines_to_plain_strings(&streamed); // Compute a full render for diagnostics only. let full: String = deltas.iter().copied().collect(); let mut rendered_all: Vec> = Vec::new(); let test_cwd = super::test_cwd(); - crate::markdown::append_markdown(&full, None, Some(test_cwd.as_path()), &mut rendered_all); + crate::markdown::append_markdown( + &full, + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered_all, + ); // Also assert exact expected plain strings for clarity. let expected = vec![ @@ -652,12 +680,17 @@ mod tests { // Targeted tests derived from fuzz findings. Each asserts streamed == full render. async fn assert_streamed_equals_full(deltas: &[&str]) { - let streamed = simulate_stream_markdown_for_tests(deltas, true); + let streamed = simulate_stream_markdown_for_tests(deltas, /*finalize*/ true); let streamed_strs = lines_to_plain_strings(&streamed); let full: String = deltas.iter().copied().collect(); let mut rendered: Vec> = Vec::new(); let test_cwd = super::test_cwd(); - crate::markdown::append_markdown(&full, None, Some(test_cwd.as_path()), &mut rendered); + crate::markdown::append_markdown( + &full, + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered, + ); let rendered_strs = lines_to_plain_strings(&rendered); assert_eq!(streamed_strs, rendered_strs, "full:\n---\n{full}\n---"); } diff --git a/codex-rs/tui_app_server/src/model_migration.rs b/codex-rs/tui_app_server/src/model_migration.rs index bd81ca90b..1b2de5ecf 100644 --- a/codex-rs/tui_app_server/src/model_migration.rs +++ b/codex-rs/tui_app_server/src/model_migration.rs @@ -432,15 +432,15 @@ mod tests { migration_copy_for_models( "gpt-5.1-codex-mini", "gpt-5.1-codex-max", - None, + /*model_link*/ None, Some( "Upgrade to gpt-5.2-codex for the latest and greatest agentic coding model." .to_string(), ), - None, + /*migration_markdown*/ None, "gpt-5.1-codex-max".to_string(), Some("Codex-optimized flagship for deep and fast reasoning.".to_string()), - true, + /*can_opt_out*/ true, ), ); @@ -455,7 +455,7 @@ mod tests { #[test] fn prompt_snapshot_gpt5_family() { - let backend = VT100Backend::new(65, 22); + let backend = VT100Backend::new(/*width*/ 65, /*height*/ 22); let mut terminal = Terminal::with_options(backend).expect("terminal"); terminal.set_viewport_area(Rect::new(0, 0, 65, 22)); @@ -465,11 +465,11 @@ mod tests { "gpt-5", "gpt-5.1", Some("https://www.codex.com/models/gpt-5.1".to_string()), - None, - None, + /*migration_copy*/ None, + /*migration_markdown*/ None, "gpt-5.1".to_string(), Some("Broad world knowledge with strong general reasoning.".to_string()), - false, + /*can_opt_out*/ false, ), ); { @@ -482,7 +482,7 @@ mod tests { #[test] fn prompt_snapshot_gpt5_codex() { - let backend = VT100Backend::new(60, 22); + let backend = VT100Backend::new(/*width*/ 60, /*height*/ 22); let mut terminal = Terminal::with_options(backend).expect("terminal"); terminal.set_viewport_area(Rect::new(0, 0, 60, 22)); @@ -492,11 +492,11 @@ mod tests { "gpt-5-codex", "gpt-5.1-codex-max", Some("https://www.codex.com/models/gpt-5.1-codex-max".to_string()), - None, - None, + /*migration_copy*/ None, + /*migration_markdown*/ None, "gpt-5.1-codex-max".to_string(), Some("Codex-optimized flagship for deep and fast reasoning.".to_string()), - false, + /*can_opt_out*/ false, ), ); { @@ -509,7 +509,7 @@ mod tests { #[test] fn prompt_snapshot_gpt5_codex_mini() { - let backend = VT100Backend::new(60, 22); + let backend = VT100Backend::new(/*width*/ 60, /*height*/ 22); let mut terminal = Terminal::with_options(backend).expect("terminal"); terminal.set_viewport_area(Rect::new(0, 0, 60, 22)); @@ -519,11 +519,11 @@ mod tests { "gpt-5-codex-mini", "gpt-5.1-codex-mini", Some("https://www.codex.com/models/gpt-5.1-codex-mini".to_string()), - None, - None, + /*migration_copy*/ None, + /*migration_markdown*/ None, "gpt-5.1-codex-mini".to_string(), Some("Optimized for codex. Cheaper, faster, but less capable.".to_string()), - false, + /*can_opt_out*/ false, ), ); { @@ -542,11 +542,11 @@ mod tests { "gpt-old", "gpt-new", Some("https://www.codex.com/models/gpt-new".to_string()), - None, - None, + /*migration_copy*/ None, + /*migration_markdown*/ None, "gpt-new".to_string(), Some("Latest recommended model for better performance.".to_string()), - true, + /*can_opt_out*/ true, ), ); @@ -571,11 +571,11 @@ mod tests { "gpt-old", "gpt-new", Some("https://www.codex.com/models/gpt-new".to_string()), - None, - None, + /*migration_copy*/ None, + /*migration_markdown*/ None, "gpt-new".to_string(), Some("Latest recommended model for better performance.".to_string()), - true, + /*can_opt_out*/ true, ), ); @@ -608,7 +608,7 @@ mod tests { }, ); - let backend = VT100Backend::new(40, 16); + let backend = VT100Backend::new(/*width*/ 40, /*height*/ 16); let mut terminal = Terminal::with_options(backend).expect("terminal"); terminal.set_viewport_area(Rect::new(0, 0, 40, 16)); diff --git a/codex-rs/tui_app_server/src/multi_agents.rs b/codex-rs/tui_app_server/src/multi_agents.rs index 4fff4ebfa..a1b0e57ff 100644 --- a/codex-rs/tui_app_server/src/multi_agents.rs +++ b/codex-rs/tui_app_server/src/multi_agents.rs @@ -688,27 +688,27 @@ mod tests { fn agent_shortcut_matches_option_arrow_word_motion_fallbacks_only_when_allowed() { assert!(previous_agent_shortcut_matches( KeyEvent::new(KeyCode::Left, KeyModifiers::ALT), - false, + /*allow_word_motion_fallback*/ false, )); assert!(next_agent_shortcut_matches( KeyEvent::new(KeyCode::Right, KeyModifiers::ALT), - false, + /*allow_word_motion_fallback*/ false, )); assert!(previous_agent_shortcut_matches( KeyEvent::new(KeyCode::Char('b'), KeyModifiers::ALT), - true, + /*allow_word_motion_fallback*/ true, )); assert!(next_agent_shortcut_matches( KeyEvent::new(KeyCode::Char('f'), KeyModifiers::ALT), - true, + /*allow_word_motion_fallback*/ true, )); assert!(!previous_agent_shortcut_matches( KeyEvent::new(KeyCode::Char('b'), KeyModifiers::ALT), - false, + /*allow_word_motion_fallback*/ false, )); assert!(!next_agent_shortcut_matches( KeyEvent::new(KeyCode::Char('f'), KeyModifiers::ALT), - false, + /*allow_word_motion_fallback*/ false, )); } @@ -757,7 +757,7 @@ mod tests { }), ); - let lines = cell.display_lines(200); + let lines = cell.display_lines(/*width*/ 200); let title = &lines[0]; assert_eq!(title.spans[2].content.as_ref(), "Robie"); assert_eq!(title.spans[2].style.fg, Some(Color::Cyan)); @@ -789,7 +789,7 @@ mod tests { } fn cell_to_text(cell: &PlainHistoryCell) -> String { - cell.display_lines(200) + cell.display_lines(/*width*/ 200) .iter() .map(line_to_text) .collect::>() diff --git a/codex-rs/tui_app_server/src/onboarding/auth.rs b/codex-rs/tui_app_server/src/onboarding/auth.rs index 37f8819b6..e442eebb1 100644 --- a/codex-rs/tui_app_server/src/onboarding/auth.rs +++ b/codex-rs/tui_app_server/src/onboarding/auth.rs @@ -922,7 +922,7 @@ mod tests { loader_overrides: Default::default(), cloud_requirements: cloud_requirements_loader_for_storage( codex_home_path.clone(), - false, + /*enable_codex_api_key_env*/ false, AuthCredentialsStoreMode::File, "https://chatgpt.com/backend-api/".to_string(), ), diff --git a/codex-rs/tui_app_server/src/onboarding/trust_directory.rs b/codex-rs/tui_app_server/src/onboarding/trust_directory.rs index 66add9315..f61e3b66b 100644 --- a/codex-rs/tui_app_server/src/onboarding/trust_directory.rs +++ b/codex-rs/tui_app_server/src/onboarding/trust_directory.rs @@ -214,7 +214,8 @@ mod tests { error: None, }; - let mut terminal = Terminal::new(VT100Backend::new(70, 14)).expect("terminal"); + let mut terminal = + Terminal::new(VT100Backend::new(/*width*/ 70, /*height*/ 14)).expect("terminal"); terminal .draw(|f| (&widget).render_ref(f.area(), f.buffer_mut())) .expect("draw"); diff --git a/codex-rs/tui_app_server/src/onboarding/welcome.rs b/codex-rs/tui_app_server/src/onboarding/welcome.rs index bdf4f9140..fa668caab 100644 --- a/codex-rs/tui_app_server/src/onboarding/welcome.rs +++ b/codex-rs/tui_app_server/src/onboarding/welcome.rs @@ -128,7 +128,11 @@ mod tests { #[test] fn welcome_renders_animation_on_first_draw() { - let widget = WelcomeWidget::new(false, FrameRequester::test_dummy(), true); + let widget = WelcomeWidget::new( + /*is_logged_in*/ false, + FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); let area = Rect::new(0, 0, MIN_ANIMATION_WIDTH, MIN_ANIMATION_HEIGHT); let mut buf = Buffer::empty(area); let frame_lines = widget.animation.current_frame().lines().count() as u16; @@ -140,7 +144,11 @@ mod tests { #[test] fn welcome_skips_animation_below_height_breakpoint() { - let widget = WelcomeWidget::new(false, FrameRequester::test_dummy(), true); + let widget = WelcomeWidget::new( + /*is_logged_in*/ false, + FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); let area = Rect::new(0, 0, MIN_ANIMATION_WIDTH, MIN_ANIMATION_HEIGHT - 1); let mut buf = Buffer::empty(area); (&widget).render(area, &mut buf); @@ -153,7 +161,11 @@ mod tests { fn ctrl_dot_changes_animation_variant() { let mut widget = WelcomeWidget { is_logged_in: false, - animation: AsciiAnimation::with_variants(FrameRequester::test_dummy(), &VARIANTS, 0), + animation: AsciiAnimation::with_variants( + FrameRequester::test_dummy(), + &VARIANTS, + /*variant_idx*/ 0, + ), animations_enabled: true, layout_area: Cell::new(None), }; diff --git a/codex-rs/tui_app_server/src/pager_overlay.rs b/codex-rs/tui_app_server/src/pager_overlay.rs index a9ab34a10..bca5f1f36 100644 --- a/codex-rs/tui_app_server/src/pager_overlay.rs +++ b/codex-rs/tui_app_server/src/pager_overlay.rs @@ -914,7 +914,7 @@ mod tests { lines: vec![Line::from("alpha")], })]); overlay.sync_live_tail( - 40, + /*width*/ 40, Some(ActiveCellTranscriptKey { revision: 1, is_stream_continuation: false, @@ -942,11 +942,11 @@ mod tests { animation_tick: None, }; - overlay.sync_live_tail(40, Some(key), |_| { + overlay.sync_live_tail(/*width*/ 40, Some(key), |_| { calls.set(calls.get() + 1); Some(vec![Line::from("tail")]) }); - overlay.sync_live_tail(40, Some(key), |_| { + overlay.sync_live_tail(/*width*/ 40, Some(key), |_| { calls.set(calls.get() + 1); Some(vec![Line::from("tail2")]) }); @@ -1012,8 +1012,8 @@ mod tests { vec!["bash".into(), "-lc".into(), "ls".into()], vec![ParsedCommand::Unknown { cmd: "ls".into() }], ExecCommandSource::Agent, - None, - true, + /*interaction_input*/ None, + /*animations_enabled*/ true, ); exec_cell.complete_call( "exec-1", @@ -1212,30 +1212,33 @@ mod tests { #[test] fn pager_view_content_height_counts_renderables() { let pv = PagerView::new( - vec![paragraph_block("a", 2), paragraph_block("b", 3)], + vec![ + paragraph_block("a", /*lines*/ 2), + paragraph_block("b", /*lines*/ 3), + ], "T".to_string(), - 0, + /*scroll_offset*/ 0, ); - assert_eq!(pv.content_height(80), 5); + assert_eq!(pv.content_height(/*width*/ 80), 5); } #[test] fn pager_view_ensure_chunk_visible_scrolls_down_when_needed() { let mut pv = PagerView::new( vec![ - paragraph_block("a", 1), - paragraph_block("b", 3), - paragraph_block("c", 3), + paragraph_block("a", /*lines*/ 1), + paragraph_block("b", /*lines*/ 3), + paragraph_block("c", /*lines*/ 3), ], "T".to_string(), - 0, + /*scroll_offset*/ 0, ); let area = Rect::new(0, 0, 20, 8); pv.scroll_offset = 0; let content_area = pv.content_area(area); - pv.ensure_chunk_visible(2, content_area); + pv.ensure_chunk_visible(/*idx*/ 2, content_area); let mut buf = Buffer::empty(area); pv.render(area, &mut buf); @@ -1259,24 +1262,28 @@ mod tests { fn pager_view_ensure_chunk_visible_scrolls_up_when_needed() { let mut pv = PagerView::new( vec![ - paragraph_block("a", 2), - paragraph_block("b", 3), - paragraph_block("c", 3), + paragraph_block("a", /*lines*/ 2), + paragraph_block("b", /*lines*/ 3), + paragraph_block("c", /*lines*/ 3), ], "T".to_string(), - 0, + /*scroll_offset*/ 0, ); let area = Rect::new(0, 0, 20, 3); pv.scroll_offset = 6; - pv.ensure_chunk_visible(0, area); + pv.ensure_chunk_visible(/*idx*/ 0, area); assert_eq!(pv.scroll_offset, 0); } #[test] fn pager_view_is_scrolled_to_bottom_accounts_for_wrapped_height() { - let mut pv = PagerView::new(vec![paragraph_block("a", 10)], "T".to_string(), 0); + let mut pv = PagerView::new( + vec![paragraph_block("a", /*lines*/ 10)], + "T".to_string(), + /*scroll_offset*/ 0, + ); let area = Rect::new(0, 0, 20, 8); let mut buf = Buffer::empty(area); diff --git a/codex-rs/tui_app_server/src/render/highlight.rs b/codex-rs/tui_app_server/src/render/highlight.rs index b44fc0a74..0c010d8fd 100644 --- a/codex-rs/tui_app_server/src/render/highlight.rs +++ b/codex-rs/tui_app_server/src/render/highlight.rs @@ -750,7 +750,7 @@ mod tests { } fn unique_foreground_colors_for_theme(theme_name: &str) -> Vec { - let theme = resolve_theme_by_name(theme_name, None) + let theme = resolve_theme_by_name(theme_name, /*codex_home*/ None) .unwrap_or_else(|| panic!("expected built-in theme {theme_name} to resolve")); let lines = highlight_to_line_spans_with_theme( "fn main() { let answer = 42; println!(\"hello\"); }\n", @@ -1000,13 +1000,13 @@ mod tests { #[test] fn ansi_palette_color_maps_ansi_white_to_gray() { - assert_eq!(ansi_palette_color(0x07), RtColor::Gray); + assert_eq!(ansi_palette_color(/*index*/ 0x07), RtColor::Gray); } #[test] fn ansi_family_themes_use_terminal_palette_colors_not_rgb() { for theme_name in ["ansi", "base16", "base16-256"] { - let theme = resolve_theme_by_name(theme_name, None) + let theme = resolve_theme_by_name(theme_name, /*codex_home*/ None) .unwrap_or_else(|| panic!("expected built-in theme {theme_name} to resolve")); let lines = highlight_to_line_spans_with_theme( "fn main() { let answer = 42; println!(\"hello\"); }\n", @@ -1212,8 +1212,8 @@ mod tests { #[test] fn bundled_theme_can_provide_diff_scope_backgrounds() { - let theme = - resolve_theme_by_name("github", None).expect("expected built-in GitHub theme to load"); + let theme = resolve_theme_by_name("github", /*codex_home*/ None) + .expect("expected built-in GitHub theme to load"); let rgbs = diff_scope_background_rgbs_for_theme(&theme); assert!( rgbs.inserted.is_some() && rgbs.deleted.is_some(), @@ -1331,13 +1331,13 @@ mod tests { #[test] fn validate_theme_name_none_for_bundled() { // Bundled themes should never produce a warning. - assert!(validate_theme_name(Some("dracula"), None).is_none()); + assert!(validate_theme_name(Some("dracula"), /*codex_home*/ None).is_none()); assert!(validate_theme_name(Some("nord"), Some(Path::new("/nonexistent"))).is_none()); } #[test] fn validate_theme_name_none_when_no_override() { - assert!(validate_theme_name(None, None).is_none()); + assert!(validate_theme_name(/*name*/ None, /*codex_home*/ None).is_none()); } #[test] diff --git a/codex-rs/tui_app_server/src/resume_picker.rs b/codex-rs/tui_app_server/src/resume_picker.rs index 84bf4b114..d5e7fbd1e 100644 --- a/codex-rs/tui_app_server/src/resume_picker.rs +++ b/codex-rs/tui_app_server/src/resume_picker.rs @@ -1872,8 +1872,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::Any, - false, - None, + /*show_all*/ false, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); let row = Row { @@ -1903,8 +1903,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -1946,7 +1946,7 @@ mod tests { state.view_rows = Some(3); state.selected = 1; state.scroll_top = 0; - state.update_view_rows(3); + state.update_view_rows(/*rows*/ 3); let metrics = calculate_column_metrics(&state.filtered_rows, state.show_all); @@ -1981,8 +1981,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); state.inline_error = Some(String::from( @@ -2217,8 +2217,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2250,7 +2250,7 @@ mod tests { state.view_rows = Some(2); state.selected = 0; state.scroll_top = 0; - state.update_view_rows(2); + state.update_view_rows(/*rows*/ 2); state.update_thread_names().await; @@ -2284,8 +2284,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2298,8 +2298,8 @@ mod tests { Some(cursor_from_str( "2025-01-02T00-00-00|00000000-0000-0000-0000-000000000000", )), - 2, - false, + /*num_scanned_files*/ 2, + /*reached_scan_cap*/ false, )); state.ingest_page(page( @@ -2310,8 +2310,8 @@ mod tests { Some(cursor_from_str( "2025-01-01T00-00-00|00000000-0000-0000-0000-000000000001", )), - 2, - false, + /*num_scanned_files*/ 2, + /*reached_scan_cap*/ false, )); state.ingest_page(page( @@ -2320,9 +2320,9 @@ mod tests { "2024-12-31T23:00:00Z", "very old", )], - None, - 1, - false, + /*next_cursor*/ None, + /*num_scanned_files*/ 1, + /*reached_scan_cap*/ false, )); let previews: Vec<_> = state @@ -2353,8 +2353,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); state.reset_pagination(); @@ -2366,12 +2366,12 @@ mod tests { Some(cursor_from_str( "2025-01-03T00-00-00|00000000-0000-0000-0000-000000000000", )), - 2, - false, + /*num_scanned_files*/ 2, + /*reached_scan_cap*/ false, )); assert!(recorded_requests.lock().unwrap().is_empty()); - state.ensure_minimum_rows_for_view(10); + state.ensure_minimum_rows_for_view(/*minimum_rows*/ 10); let guard = recorded_requests.lock().unwrap(); assert_eq!(guard.len(), 1); assert!(guard[0].search_token.is_none()); @@ -2387,7 +2387,7 @@ mod tests { labels: Vec::new(), }; - let created = column_visibility(30, &metrics, ThreadSortKey::CreatedAt); + let created = column_visibility(/*area_width*/ 30, &metrics, ThreadSortKey::CreatedAt); assert_eq!( created, ColumnVisibility { @@ -2398,7 +2398,7 @@ mod tests { } ); - let updated = column_visibility(30, &metrics, ThreadSortKey::UpdatedAt); + let updated = column_visibility(/*area_width*/ 30, &metrics, ThreadSortKey::UpdatedAt); assert_eq!( updated, ColumnVisibility { @@ -2409,7 +2409,7 @@ mod tests { } ); - let wide = column_visibility(40, &metrics, ThreadSortKey::CreatedAt); + let wide = column_visibility(/*area_width*/ 40, &metrics, ThreadSortKey::CreatedAt); assert_eq!( wide, ColumnVisibility { @@ -2434,8 +2434,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2464,8 +2464,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2478,8 +2478,11 @@ mod tests { } state.reset_pagination(); - state.ingest_page(page(items, None, 20, false)); - state.update_view_rows(5); + state.ingest_page(page( + items, /*next_cursor*/ None, /*num_scanned_files*/ 20, + /*reached_scan_cap*/ false, + )); + state.update_view_rows(/*rows*/ 5); assert_eq!(state.selected, 0); state @@ -2509,8 +2512,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2549,8 +2552,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); let thread_id = ThreadId::new(); @@ -2618,8 +2621,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); @@ -2632,8 +2635,11 @@ mod tests { } state.reset_pagination(); - state.ingest_page(page(items, None, 10, false)); - state.update_view_rows(5); + state.ingest_page(page( + items, /*next_cursor*/ None, /*num_scanned_files*/ 10, + /*reached_scan_cap*/ false, + )); + state.update_view_rows(/*rows*/ 5); state.selected = state.filtered_rows.len().saturating_sub(1); state.ensure_selected_visible(); @@ -2663,8 +2669,8 @@ mod tests { FrameRequester::test_dummy(), loader, ProviderFilter::MatchDefault(String::from("openai")), - true, - None, + /*show_all*/ true, + /*filter_cwd*/ None, SessionPickerAction::Resume, ); state.reset_pagination(); @@ -2677,8 +2683,8 @@ mod tests { Some(cursor_from_str( "2025-01-02T00-00-00|00000000-0000-0000-0000-000000000000", )), - 1, - false, + /*num_scanned_files*/ 1, + /*reached_scan_cap*/ false, )); recorded_requests.lock().unwrap().clear(); @@ -2698,8 +2704,8 @@ mod tests { Some(cursor_from_str( "2025-01-03T00-00-00|00000000-0000-0000-0000-000000000001", )), - 5, - false, + /*num_scanned_files*/ 5, + /*reached_scan_cap*/ false, )), }) .await @@ -2726,8 +2732,8 @@ mod tests { Some(cursor_from_str( "2025-01-04T00-00-00|00000000-0000-0000-0000-000000000002", )), - 7, - false, + /*num_scanned_files*/ 7, + /*reached_scan_cap*/ false, )), }) .await @@ -2748,7 +2754,12 @@ mod tests { .handle_background_event(BackgroundEvent::PageLoaded { request_token: second_request.request_token, search_token: second_request.search_token, - page: Ok(page(Vec::new(), None, 0, false)), + page: Ok(page( + Vec::new(), + /*next_cursor*/ None, + /*num_scanned_files*/ 0, + /*reached_scan_cap*/ false, + )), }) .await .unwrap(); @@ -2758,7 +2769,12 @@ mod tests { .handle_background_event(BackgroundEvent::PageLoaded { request_token: active_request.request_token, search_token: active_request.search_token, - page: Ok(page(Vec::new(), None, 3, true)), + page: Ok(page( + Vec::new(), + /*next_cursor*/ None, + /*num_scanned_files*/ 3, + /*reached_scan_cap*/ true, + )), }) .await .unwrap(); diff --git a/codex-rs/tui_app_server/src/status/rate_limits.rs b/codex-rs/tui_app_server/src/status/rate_limits.rs index 10dbaaaa2..81aa5f107 100644 --- a/codex-rs/tui_app_server/src/status/rate_limits.rs +++ b/codex-rs/tui_app_server/src/status/rate_limits.rs @@ -366,7 +366,7 @@ mod tests { let codex = RateLimitSnapshotDisplay { limit_name: "codex".to_string(), captured_at: now, - primary: Some(window(10.0)), + primary: Some(window(/*used_percent*/ 10.0)), secondary: None, credits: Some(CreditsSnapshotDisplay { has_credits: true, @@ -377,7 +377,7 @@ mod tests { let other = RateLimitSnapshotDisplay { limit_name: "codex-other".to_string(), captured_at: now, - primary: Some(window(20.0)), + primary: Some(window(/*used_percent*/ 20.0)), secondary: None, credits: Some(CreditsSnapshotDisplay { has_credits: true, diff --git a/codex-rs/tui_app_server/src/status/tests.rs b/codex-rs/tui_app_server/src/status/tests.rs index fbfbca912..69097c6ef 100644 --- a/codex-rs/tui_app_server/src/status/tests.rs +++ b/codex-rs/tui_app_server/src/status/tests.rs @@ -127,12 +127,12 @@ async fn status_snapshot_includes_reasoning_details() { primary: Some(RateLimitWindow { used_percent: 72.5, window_minutes: Some(300), - resets_at: Some(reset_at_from(&captured_at, 600)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 600)), }), secondary: Some(RateLimitWindow { used_percent: 45.0, window_minutes: Some(10080), - resets_at: Some(reset_at_from(&captured_at, 1_200)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 1_200)), }), credits: None, plan_type: None, @@ -149,16 +149,16 @@ async fn status_snapshot_includes_reasoning_details() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, + /*collaboration_mode*/ None, reasoning_effort_override, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -203,19 +203,19 @@ async fn status_permissions_non_default_workspace_write_is_custom() { let composite = new_status_output( &config, account_display.as_ref(), - None, + /*token_info*/ None, &usage, &None, - None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, + /*rate_limits*/ None, None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered_lines = render_lines(&composite.display_lines(80)); + let rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); let permissions_line = rendered_lines .iter() .find(|line| line.contains("Permissions:")) @@ -268,16 +268,16 @@ async fn status_snapshot_includes_forked_from() { Some(&token_info), &usage, &Some(session_id), - None, + /*thread_name*/ None, Some(forked_from), - None, + /*rate_limits*/ None, None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -314,7 +314,7 @@ async fn status_snapshot_includes_monthly_limit() { primary: Some(RateLimitWindow { used_percent: 12.0, window_minutes: Some(43_200), - resets_at: Some(reset_at_from(&captured_at, 86_400)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 86_400)), }), secondary: None, credits: None, @@ -330,16 +330,16 @@ async fn status_snapshot_includes_monthly_limit() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -380,16 +380,16 @@ async fn status_snapshot_shows_unlimited_credits() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered = render_lines(&composite.display_lines(120)); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)); assert!( rendered .iter() @@ -429,16 +429,16 @@ async fn status_snapshot_shows_positive_credits() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered = render_lines(&composite.display_lines(120)); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)); assert!( rendered .iter() @@ -478,16 +478,16 @@ async fn status_snapshot_hides_zero_credits() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered = render_lines(&composite.display_lines(120)); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)); assert!( rendered.iter().all(|line| !line.contains("Credits:")), "expected no Credits line, got {rendered:?}" @@ -525,16 +525,16 @@ async fn status_snapshot_hides_when_has_no_credits_flag() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered = render_lines(&composite.display_lines(120)); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)); assert!( rendered.iter().all(|line| !line.contains("Credits:")), "expected no Credits line when has_credits is false, got {rendered:?}" @@ -570,16 +570,16 @@ async fn status_card_token_usage_excludes_cached_tokens() { Some(&token_info), &usage, &None, - None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, + /*rate_limits*/ None, None, now, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered = render_lines(&composite.display_lines(120)); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)); assert!( rendered.iter().all(|line| !line.contains("cached")), @@ -615,7 +615,7 @@ async fn status_snapshot_truncates_in_narrow_terminal() { primary: Some(RateLimitWindow { used_percent: 72.5, window_minutes: Some(300), - resets_at: Some(reset_at_from(&captured_at, 600)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 600)), }), secondary: None, credits: None, @@ -632,16 +632,16 @@ async fn status_snapshot_truncates_in_narrow_terminal() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, + /*collaboration_mode*/ None, reasoning_effort_override, ); - let mut rendered_lines = render_lines(&composite.display_lines(70)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 70)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -681,16 +681,16 @@ async fn status_snapshot_shows_missing_limits_message() { Some(&token_info), &usage, &None, - None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, + /*rate_limits*/ None, None, now, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -726,12 +726,12 @@ async fn status_snapshot_includes_credits_and_limits() { primary: Some(RateLimitWindow { used_percent: 45.0, window_minutes: Some(300), - resets_at: Some(reset_at_from(&captured_at, 900)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 900)), }), secondary: Some(RateLimitWindow { used_percent: 30.0, window_minutes: Some(10_080), - resets_at: Some(reset_at_from(&captured_at, 2_700)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 2_700)), }), credits: Some(CreditsSnapshot { has_credits: true, @@ -750,16 +750,16 @@ async fn status_snapshot_includes_credits_and_limits() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -807,16 +807,16 @@ async fn status_snapshot_shows_empty_limits_message() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, captured_at, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -852,12 +852,12 @@ async fn status_snapshot_shows_stale_limits_message() { primary: Some(RateLimitWindow { used_percent: 72.5, window_minutes: Some(300), - resets_at: Some(reset_at_from(&captured_at, 600)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 600)), }), secondary: Some(RateLimitWindow { used_percent: 40.0, window_minutes: Some(10_080), - resets_at: Some(reset_at_from(&captured_at, 1_800)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 1_800)), }), credits: None, plan_type: None, @@ -873,16 +873,16 @@ async fn status_snapshot_shows_stale_limits_message() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, now, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -918,12 +918,12 @@ async fn status_snapshot_cached_limits_hide_credits_without_flag() { primary: Some(RateLimitWindow { used_percent: 60.0, window_minutes: Some(300), - resets_at: Some(reset_at_from(&captured_at, 1_200)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 1_200)), }), secondary: Some(RateLimitWindow { used_percent: 35.0, window_minutes: Some(10_080), - resets_at: Some(reset_at_from(&captured_at, 2_400)), + resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 2_400)), }), credits: Some(CreditsSnapshot { has_credits: false, @@ -943,16 +943,16 @@ async fn status_snapshot_cached_limits_hide_credits_without_flag() { Some(&token_info), &usage, &None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, Some(&rate_display), None, now, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let mut rendered_lines = render_lines(&composite.display_lines(80)); + let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); if cfg!(windows) { for line in &mut rendered_lines { *line = line.replace('\\', "/"); @@ -1001,16 +1001,16 @@ async fn status_context_window_uses_last_usage() { Some(&token_info), &total_usage, &None, - None, - None, - None, + /*thread_name*/ None, + /*forked_from*/ None, + /*rate_limits*/ None, None, now, &model_slug, - None, - None, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, ); - let rendered_lines = render_lines(&composite.display_lines(80)); + let rendered_lines = render_lines(&composite.display_lines(/*width*/ 80)); let context_line = rendered_lines .into_iter() .find(|line| line.contains("Context window")) diff --git a/codex-rs/tui_app_server/src/status_indicator_widget.rs b/codex-rs/tui_app_server/src/status_indicator_widget.rs index b68d6c4e3..471c0b4bd 100644 --- a/codex-rs/tui_app_server/src/status_indicator_widget.rs +++ b/codex-rs/tui_app_server/src/status_indicator_widget.rs @@ -302,14 +302,14 @@ mod tests { #[test] fn fmt_elapsed_compact_formats_seconds_minutes_hours() { - assert_eq!(fmt_elapsed_compact(0), "0s"); - assert_eq!(fmt_elapsed_compact(1), "1s"); - assert_eq!(fmt_elapsed_compact(59), "59s"); - assert_eq!(fmt_elapsed_compact(60), "1m 00s"); - assert_eq!(fmt_elapsed_compact(61), "1m 01s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 0), "0s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 1), "1s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 59), "59s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 60), "1m 00s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 61), "1m 01s"); assert_eq!(fmt_elapsed_compact(3 * 60 + 5), "3m 05s"); assert_eq!(fmt_elapsed_compact(59 * 60 + 59), "59m 59s"); - assert_eq!(fmt_elapsed_compact(3600), "1h 00m 00s"); + assert_eq!(fmt_elapsed_compact(/*elapsed_secs*/ 3600), "1h 00m 00s"); assert_eq!(fmt_elapsed_compact(3600 + 60 + 1), "1h 01m 01s"); assert_eq!(fmt_elapsed_compact(25 * 3600 + 2 * 60 + 3), "25h 02m 03s"); } @@ -318,7 +318,11 @@ mod tests { fn renders_with_working_header() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), true); + let w = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); // Render into a fixed-size test terminal and snapshot the backend. let mut terminal = Terminal::new(TestBackend::new(80, 2)).expect("terminal"); @@ -332,7 +336,11 @@ mod tests { fn renders_truncated() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), true); + let w = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); // Render into a fixed-size test terminal and snapshot the backend. let mut terminal = Terminal::new(TestBackend::new(20, 2)).expect("terminal"); @@ -346,7 +354,11 @@ mod tests { fn renders_wrapped_details_panama_two_lines() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let mut w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), false); + let mut w = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ false, + ); w.update_details( Some("A man a plan a canal panama".to_string()), StatusDetailsCapitalization::CapitalizeFirst, @@ -371,8 +383,11 @@ mod tests { fn timer_pauses_when_requested() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let mut widget = - StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), true); + let mut widget = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); let baseline = Instant::now(); widget.last_resume_at = baseline; @@ -393,14 +408,18 @@ mod tests { fn details_overflow_adds_ellipsis() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let mut w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), true); + let mut w = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); w.update_details( Some("abcd abcd abcd abcd".to_string()), StatusDetailsCapitalization::CapitalizeFirst, STATUS_DETAILS_DEFAULT_MAX_LINES, ); - let lines = w.wrapped_details_lines(6); + let lines = w.wrapped_details_lines(/*width*/ 6); assert_eq!(lines.len(), STATUS_DETAILS_DEFAULT_MAX_LINES); let last = lines.last().expect("expected last details line"); assert!( @@ -413,11 +432,15 @@ mod tests { fn details_args_can_disable_capitalization_and_limit_lines() { let (tx_raw, _rx) = unbounded_channel::(); let tx = AppEventSender::new(tx_raw); - let mut w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy(), true); + let mut w = StatusIndicatorWidget::new( + tx, + crate::tui::FrameRequester::test_dummy(), + /*animations_enabled*/ true, + ); w.update_details( Some("cargo test -p codex-core and then cargo test -p codex-tui".to_string()), StatusDetailsCapitalization::Preserve, - 1, + /*max_lines*/ 1, ); assert_eq!( @@ -425,7 +448,7 @@ mod tests { Some("cargo test -p codex-core and then cargo test -p codex-tui") ); - let lines = w.wrapped_details_lines(24); + let lines = w.wrapped_details_lines(/*width*/ 24); assert_eq!(lines.len(), 1); let last = lines.last().expect("expected one details line"); assert!( diff --git a/codex-rs/tui_app_server/src/streaming/chunking.rs b/codex-rs/tui_app_server/src/streaming/chunking.rs index b653f51ec..9bf43cba5 100644 --- a/codex-rs/tui_app_server/src/streaming/chunking.rs +++ b/codex-rs/tui_app_server/src/streaming/chunking.rs @@ -310,7 +310,7 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let decision = policy.decide(snapshot(1, 10), now); + let decision = policy.decide(snapshot(/*queued_lines*/ 1, /*oldest_age_ms*/ 10), now); assert_eq!(decision.mode, ChunkingMode::Smooth); assert_eq!(decision.entered_catch_up, false); assert_eq!(decision.drain_plan, DrainPlan::Single); @@ -321,7 +321,7 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let decision = policy.decide(snapshot(8, 10), now); + let decision = policy.decide(snapshot(/*queued_lines*/ 8, /*oldest_age_ms*/ 10), now); assert_eq!(decision.mode, ChunkingMode::CatchUp); assert_eq!(decision.entered_catch_up, true); assert_eq!(decision.drain_plan, DrainPlan::Batch(8)); @@ -332,7 +332,7 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let decision = policy.decide(snapshot(2, 120), now); + let decision = policy.decide(snapshot(/*queued_lines*/ 2, /*oldest_age_ms*/ 120), now); assert_eq!(decision.mode, ChunkingMode::CatchUp); assert_eq!(decision.entered_catch_up, true); assert_eq!(decision.drain_plan, DrainPlan::Batch(2)); @@ -342,9 +342,12 @@ mod tests { fn severe_backlog_uses_faster_paced_batches() { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let _ = policy.decide(snapshot(9, 10), now); + let _ = policy.decide(snapshot(/*queued_lines*/ 9, /*oldest_age_ms*/ 10), now); - let decision = policy.decide(snapshot(64, 10), now + Duration::from_millis(5)); + let decision = policy.decide( + snapshot(/*queued_lines*/ 64, /*oldest_age_ms*/ 10), + now + Duration::from_millis(5), + ); assert_eq!(decision.mode, ChunkingMode::CatchUp); assert_eq!(decision.drain_plan, DrainPlan::Batch(64)); } @@ -353,7 +356,7 @@ mod tests { fn catch_up_batch_drains_current_backlog() { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let decision = policy.decide(snapshot(512, 400), now); + let decision = policy.decide(snapshot(/*queued_lines*/ 512, /*oldest_age_ms*/ 400), now); assert_eq!(decision.mode, ChunkingMode::CatchUp); assert_eq!(decision.drain_plan, DrainPlan::Batch(512)); } @@ -363,13 +366,19 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let t0 = Instant::now(); - let _ = policy.decide(snapshot(9, 10), t0); + let _ = policy.decide(snapshot(/*queued_lines*/ 9, /*oldest_age_ms*/ 10), t0); assert_eq!(policy.mode(), ChunkingMode::CatchUp); - let pre_hold = policy.decide(snapshot(2, 40), t0 + Duration::from_millis(200)); + let pre_hold = policy.decide( + snapshot(/*queued_lines*/ 2, /*oldest_age_ms*/ 40), + t0 + Duration::from_millis(200), + ); assert_eq!(pre_hold.mode, ChunkingMode::CatchUp); - let post_hold = policy.decide(snapshot(2, 40), t0 + Duration::from_millis(460)); + let post_hold = policy.decide( + snapshot(/*queued_lines*/ 2, /*oldest_age_ms*/ 40), + t0 + Duration::from_millis(460), + ); assert_eq!(post_hold.mode, ChunkingMode::Smooth); assert_eq!(post_hold.drain_plan, DrainPlan::Single); } @@ -378,7 +387,7 @@ mod tests { fn drops_back_to_smooth_when_idle() { let mut policy = AdaptiveChunkingPolicy::default(); let now = Instant::now(); - let _ = policy.decide(snapshot(9, 10), now); + let _ = policy.decide(snapshot(/*queued_lines*/ 9, /*oldest_age_ms*/ 10), now); assert_eq!(policy.mode(), ChunkingMode::CatchUp); let decision = policy.decide( @@ -397,7 +406,7 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let t0 = Instant::now(); - let entered = policy.decide(snapshot(8, 20), t0); + let entered = policy.decide(snapshot(/*queued_lines*/ 8, /*oldest_age_ms*/ 20), t0); assert_eq!(entered.mode, ChunkingMode::CatchUp); let drained = policy.decide( @@ -409,11 +418,17 @@ mod tests { ); assert_eq!(drained.mode, ChunkingMode::Smooth); - let held = policy.decide(snapshot(8, 20), t0 + Duration::from_millis(120)); + let held = policy.decide( + snapshot(/*queued_lines*/ 8, /*oldest_age_ms*/ 20), + t0 + Duration::from_millis(120), + ); assert_eq!(held.mode, ChunkingMode::Smooth); assert_eq!(held.drain_plan, DrainPlan::Single); - let reentered = policy.decide(snapshot(8, 20), t0 + Duration::from_millis(320)); + let reentered = policy.decide( + snapshot(/*queued_lines*/ 8, /*oldest_age_ms*/ 20), + t0 + Duration::from_millis(320), + ); assert_eq!(reentered.mode, ChunkingMode::CatchUp); assert_eq!(reentered.drain_plan, DrainPlan::Batch(8)); } @@ -423,7 +438,7 @@ mod tests { let mut policy = AdaptiveChunkingPolicy::default(); let t0 = Instant::now(); - let _ = policy.decide(snapshot(8, 20), t0); + let _ = policy.decide(snapshot(/*queued_lines*/ 8, /*oldest_age_ms*/ 20), t0); let _ = policy.decide( QueueSnapshot { queued_lines: 0, @@ -432,7 +447,10 @@ mod tests { t0 + Duration::from_millis(20), ); - let severe = policy.decide(snapshot(64, 20), t0 + Duration::from_millis(120)); + let severe = policy.decide( + snapshot(/*queued_lines*/ 64, /*oldest_age_ms*/ 20), + t0 + Duration::from_millis(120), + ); assert_eq!(severe.mode, ChunkingMode::CatchUp); assert_eq!(severe.drain_plan, DrainPlan::Batch(64)); } diff --git a/codex-rs/tui_app_server/src/streaming/controller.rs b/codex-rs/tui_app_server/src/streaming/controller.rs index 8aaf4cb34..d524e707a 100644 --- a/codex-rs/tui_app_server/src/streaming/controller.rs +++ b/codex-rs/tui_app_server/src/streaming/controller.rs @@ -271,7 +271,7 @@ mod tests { #[tokio::test] async fn controller_loose_vs_tight_with_commit_ticks_matches_full() { - let mut ctrl = StreamController::new(None, &test_cwd()); + let mut ctrl = StreamController::new(/*width*/ None, &test_cwd()); let mut lines = Vec::new(); // Exact deltas from the session log (section: Loose vs. tight list items) @@ -370,7 +370,12 @@ mod tests { let source: String = deltas.iter().copied().collect(); let mut rendered: Vec> = Vec::new(); let test_cwd = test_cwd(); - crate::markdown::append_markdown(&source, None, Some(test_cwd.as_path()), &mut rendered); + crate::markdown::append_markdown( + &source, + /*width*/ None, + Some(test_cwd.as_path()), + &mut rendered, + ); let rendered_strs = lines_to_plain_strings(&rendered); assert_eq!(streamed, rendered_strs); diff --git a/codex-rs/tui_app_server/src/streaming/mod.rs b/codex-rs/tui_app_server/src/streaming/mod.rs index e39b00e09..ae3b68742 100644 --- a/codex-rs/tui_app_server/src/streaming/mod.rs +++ b/codex-rs/tui_app_server/src/streaming/mod.rs @@ -116,10 +116,10 @@ mod tests { #[test] fn drain_n_clamps_to_available_lines() { - let mut state = StreamState::new(None, &test_cwd()); + let mut state = StreamState::new(/*width*/ None, &test_cwd()); state.enqueue(vec![Line::from("one")]); - let drained = state.drain_n(8); + let drained = state.drain_n(/*max_lines*/ 8); assert_eq!(drained, vec![Line::from("one")]); assert!(state.is_idle()); } diff --git a/codex-rs/tui_app_server/src/text_formatting.rs b/codex-rs/tui_app_server/src/text_formatting.rs index 4869645dc..ae93890bb 100644 --- a/codex-rs/tui_app_server/src/text_formatting.rs +++ b/codex-rs/tui_app_server/src/text_formatting.rs @@ -362,80 +362,80 @@ mod tests { #[test] fn test_truncate_text() { let text = "Hello, world!"; - let truncated = truncate_text(text, 8); + let truncated = truncate_text(text, /*max_graphemes*/ 8); assert_eq!(truncated, "Hello..."); } #[test] fn test_truncate_empty_string() { let text = ""; - let truncated = truncate_text(text, 5); + let truncated = truncate_text(text, /*max_graphemes*/ 5); assert_eq!(truncated, ""); } #[test] fn test_truncate_max_graphemes_zero() { let text = "Hello"; - let truncated = truncate_text(text, 0); + let truncated = truncate_text(text, /*max_graphemes*/ 0); assert_eq!(truncated, ""); } #[test] fn test_truncate_max_graphemes_one() { let text = "Hello"; - let truncated = truncate_text(text, 1); + let truncated = truncate_text(text, /*max_graphemes*/ 1); assert_eq!(truncated, "H"); } #[test] fn test_truncate_max_graphemes_two() { let text = "Hello"; - let truncated = truncate_text(text, 2); + let truncated = truncate_text(text, /*max_graphemes*/ 2); assert_eq!(truncated, "He"); } #[test] fn test_truncate_max_graphemes_three_boundary() { let text = "Hello"; - let truncated = truncate_text(text, 3); + let truncated = truncate_text(text, /*max_graphemes*/ 3); assert_eq!(truncated, "..."); } #[test] fn test_truncate_text_shorter_than_limit() { let text = "Hi"; - let truncated = truncate_text(text, 10); + let truncated = truncate_text(text, /*max_graphemes*/ 10); assert_eq!(truncated, "Hi"); } #[test] fn test_truncate_text_exact_length() { let text = "Hello"; - let truncated = truncate_text(text, 5); + let truncated = truncate_text(text, /*max_graphemes*/ 5); assert_eq!(truncated, "Hello"); } #[test] fn test_truncate_emoji() { let text = "πŸ‘‹πŸŒπŸš€βœ¨πŸ’«"; - let truncated = truncate_text(text, 3); + let truncated = truncate_text(text, /*max_graphemes*/ 3); assert_eq!(truncated, "..."); - let truncated_longer = truncate_text(text, 4); + let truncated_longer = truncate_text(text, /*max_graphemes*/ 4); assert_eq!(truncated_longer, "πŸ‘‹..."); } #[test] fn test_truncate_unicode_combining_characters() { let text = "é́ñ̃"; // Characters with combining marks - let truncated = truncate_text(text, 2); + let truncated = truncate_text(text, /*max_graphemes*/ 2); assert_eq!(truncated, "é́ñ̃"); } #[test] fn test_truncate_very_long_text() { let text = "a".repeat(1000); - let truncated = truncate_text(&text, 10); + let truncated = truncate_text(&text, /*max_graphemes*/ 10); assert_eq!(truncated, "aaaaaaa..."); assert_eq!(truncated.len(), 10); // 7 'a's + 3 dots } @@ -461,7 +461,7 @@ mod tests { fn test_center_truncate_doesnt_truncate_short_path() { let sep = std::path::MAIN_SEPARATOR; let path = format!("{sep}Users{sep}codex{sep}Public"); - let truncated = center_truncate_path(&path, 40); + let truncated = center_truncate_path(&path, /*max_width*/ 40); assert_eq!(truncated, path); } @@ -470,7 +470,7 @@ mod tests { fn test_center_truncate_truncates_long_path() { let sep = std::path::MAIN_SEPARATOR; let path = format!("~{sep}hello{sep}the{sep}fox{sep}is{sep}very{sep}fast"); - let truncated = center_truncate_path(&path, 24); + let truncated = center_truncate_path(&path, /*max_width*/ 24); assert_eq!( truncated, @@ -484,7 +484,7 @@ mod tests { let path = format!( "C:{sep}Users{sep}codex{sep}Projects{sep}super{sep}long{sep}windows{sep}path{sep}file.txt" ); - let truncated = center_truncate_path(&path, 36); + let truncated = center_truncate_path(&path, /*max_width*/ 36); let expected = format!("C:{sep}Users{sep}codex{sep}…{sep}path{sep}file.txt"); @@ -495,7 +495,7 @@ mod tests { fn test_center_truncate_handles_long_segment() { let sep = std::path::MAIN_SEPARATOR; let path = format!("~{sep}supercalifragilisticexpialidocious"); - let truncated = center_truncate_path(&path, 18); + let truncated = center_truncate_path(&path, /*max_width*/ 18); assert_eq!(truncated, format!("~{sep}…cexpialidocious")); } diff --git a/codex-rs/tui_app_server/src/theme_picker.rs b/codex-rs/tui_app_server/src/theme_picker.rs index 54910ee10..563054a37 100644 --- a/codex-rs/tui_app_server/src/theme_picker.rs +++ b/codex-rs/tui_app_server/src/theme_picker.rs @@ -476,7 +476,9 @@ mod tests { #[test] fn theme_picker_uses_half_width_with_stacked_fallback_preview() { - let params = build_theme_picker_params(None, None, None); + let params = build_theme_picker_params( + /*current_name*/ None, /*codex_home*/ None, /*terminal_width*/ None, + ); assert_eq!(params.side_content_width, SideContentWidth::Half); assert_eq!(params.side_content_min_width, WIDE_PREVIEW_MIN_WIDTH); assert!(params.stacked_side_content.is_some()); @@ -484,7 +486,9 @@ mod tests { #[test] fn theme_picker_items_include_search_values_for_preview_mapping() { - let params = build_theme_picker_params(None, None, None); + let params = build_theme_picker_params( + /*current_name*/ None, /*codex_home*/ None, /*terminal_width*/ None, + ); assert!( params.items.iter().all(|item| item.search_value.is_some()), "theme picker preview mapping relies on item search_value to stay aligned with final item order" @@ -493,7 +497,11 @@ mod tests { #[test] fn wide_preview_renders_all_lines_with_vertical_center_and_left_inset() { - let lines = render_lines(&ThemePreviewWideRenderable, 80, 20); + let lines = render_lines( + &ThemePreviewWideRenderable, + /*width*/ 80, + /*height*/ 20, + ); let numbered_rows: Vec = lines .iter() .enumerate() @@ -539,7 +547,11 @@ mod tests { #[test] fn narrow_preview_renders_single_add_and_single_remove_in_four_lines() { - let lines = render_lines(&ThemePreviewNarrowRenderable, 80, 6); + let lines = render_lines( + &ThemePreviewNarrowRenderable, + /*width*/ 80, + /*height*/ 6, + ); let numbered_lines: Vec = lines .iter() .filter_map(|line| preview_line_number(line)) @@ -606,7 +618,8 @@ mod tests { #[test] fn subtitle_falls_back_to_preview_instructions_without_tilde_path() { - let subtitle = theme_picker_subtitle(None, None); + let subtitle = + theme_picker_subtitle(/*codex_home*/ None, /*terminal_width*/ None); assert_eq!(subtitle, PREVIEW_FALLBACK_SUBTITLE); } @@ -623,7 +636,11 @@ mod tests { #[test] fn unavailable_configured_theme_falls_back_to_configured_or_default_selection() { let configured_or_default_theme = highlight::configured_theme_name(); - let params = build_theme_picker_params(Some("not-a-real-theme"), None, Some(120)); + let params = build_theme_picker_params( + Some("not-a-real-theme"), + /*codex_home*/ None, + Some(120), + ); let selected_idx = params .initial_selected_idx .expect("expected selected index for active fallback theme"); diff --git a/codex-rs/tui_app_server/src/tooltips.rs b/codex-rs/tui_app_server/src/tooltips.rs index c91584a5b..cacb94b8e 100644 --- a/codex-rs/tui_app_server/src/tooltips.rs +++ b/codex-rs/tui_app_server/src/tooltips.rs @@ -291,7 +291,9 @@ mod tests { let mut seen = std::collections::BTreeSet::new(); for seed in 0..32 { let mut rng = StdRng::seed_from_u64(seed); - seen.insert(pick_paid_tooltip(&mut rng, false)); + seen.insert(pick_paid_tooltip( + &mut rng, /*fast_mode_enabled*/ false, + )); } let expected = std::collections::BTreeSet::from([paid_app_tooltip(), FAST_TOOLTIP]); @@ -303,7 +305,7 @@ mod tests { let mut seen = std::collections::BTreeSet::new(); for seed in 0..8 { let mut rng = StdRng::seed_from_u64(seed); - seen.insert(pick_paid_tooltip(&mut rng, true)); + seen.insert(pick_paid_tooltip(&mut rng, /*fast_mode_enabled*/ true)); } let expected = std::collections::BTreeSet::from([paid_app_tooltip()]); diff --git a/codex-rs/tui_app_server/src/update_action.rs b/codex-rs/tui_app_server/src/update_action.rs index 0bb6fa2ca..baee1662f 100644 --- a/codex-rs/tui_app_server/src/update_action.rs +++ b/codex-rs/tui_app_server/src/update_action.rs @@ -68,32 +68,47 @@ mod tests { #[test] fn detects_update_action_without_env_mutation() { assert_eq!( - detect_update_action(false, std::path::Path::new("/any/path"), false, false), + detect_update_action( + /*is_macos*/ false, + std::path::Path::new("/any/path"), + /*managed_by_npm*/ false, + /*managed_by_bun*/ false + ), None ); assert_eq!( - detect_update_action(false, std::path::Path::new("/any/path"), true, false), + detect_update_action( + /*is_macos*/ false, + std::path::Path::new("/any/path"), + /*managed_by_npm*/ true, + /*managed_by_bun*/ false + ), Some(UpdateAction::NpmGlobalLatest) ); assert_eq!( - detect_update_action(false, std::path::Path::new("/any/path"), false, true), + detect_update_action( + /*is_macos*/ false, + std::path::Path::new("/any/path"), + /*managed_by_npm*/ false, + /*managed_by_bun*/ true + ), Some(UpdateAction::BunGlobalLatest) ); assert_eq!( detect_update_action( - true, + /*is_macos*/ true, std::path::Path::new("/opt/homebrew/bin/codex"), - false, - false + /*managed_by_npm*/ false, + /*managed_by_bun*/ false ), Some(UpdateAction::BrewUpgrade) ); assert_eq!( detect_update_action( - true, + /*is_macos*/ true, std::path::Path::new("/usr/local/bin/codex"), - false, - false + /*managed_by_npm*/ false, + /*managed_by_bun*/ false ), Some(UpdateAction::BrewUpgrade) ); diff --git a/codex-rs/tui_app_server/src/voice.rs b/codex-rs/tui_app_server/src/voice.rs index 6758eff4d..df8c31953 100644 --- a/codex-rs/tui_app_server/src/voice.rs +++ b/codex-rs/tui_app_server/src/voice.rs @@ -881,7 +881,10 @@ mod tests { #[test] fn convert_pcm16_downmixes_and_resamples_for_model_input() { let input = vec![100, 300, 200, 400, 500, 700, 600, 800]; - let converted = convert_pcm16(&input, 48_000, 2, 24_000, 1); + let converted = convert_pcm16( + &input, /*input_sample_rate*/ 48_000, /*input_channels*/ 2, + /*output_sample_rate*/ 24_000, /*output_channels*/ 1, + ); assert_eq!(converted, vec![200, 700]); } diff --git a/codex-rs/tui_app_server/src/wrapping.rs b/codex-rs/tui_app_server/src/wrapping.rs index 9808a2431..09741c414 100644 --- a/codex-rs/tui_app_server/src/wrapping.rs +++ b/codex-rs/tui_app_server/src/wrapping.rs @@ -898,7 +898,7 @@ mod tests { #[test] fn trivial_unstyled_no_indents_wide_width() { let line = Line::from("hello"); - let out = word_wrap_line(&line, 10); + let out = word_wrap_line(&line, /*width_or_options*/ 10); assert_eq!(out.len(), 1); assert_eq!(concat_line(&out[0]), "hello"); } @@ -906,7 +906,7 @@ mod tests { #[test] fn simple_unstyled_wrap_narrow_width() { let line = Line::from("hello world"); - let out = word_wrap_line(&line, 5); + let out = word_wrap_line(&line, /*width_or_options*/ 5); assert_eq!(out.len(), 2); assert_eq!(concat_line(&out[0]), "hello"); assert_eq!(concat_line(&out[1]), "world"); @@ -915,7 +915,7 @@ mod tests { #[test] fn simple_styled_wrap_preserves_styles() { let line = Line::from(vec!["hello ".red(), "world".into()]); - let out = word_wrap_line(&line, 6); + let out = word_wrap_line(&line, /*width_or_options*/ 6); assert_eq!(out.len(), 2); // First line should carry the red style assert_eq!(concat_line(&out[0]), "hello"); @@ -929,7 +929,7 @@ mod tests { #[test] fn with_initial_and_subsequent_indents() { - let opts = RtOptions::new(8) + let opts = RtOptions::new(/*width*/ 8) .initial_indent(Line::from("- ")) .subsequent_indent(Line::from(" ")); let line = Line::from("hello world foo"); @@ -946,7 +946,7 @@ mod tests { #[test] fn empty_initial_indent_subsequent_spaces() { - let opts = RtOptions::new(8) + let opts = RtOptions::new(/*width*/ 8) .initial_indent(Line::from("")) .subsequent_indent(Line::from(" ")); let line = Line::from("hello world foobar"); @@ -960,7 +960,7 @@ mod tests { #[test] fn empty_input_yields_single_empty_line() { let line = Line::from(""); - let out = word_wrap_line(&line, 10); + let out = word_wrap_line(&line, /*width_or_options*/ 10); assert_eq!(out.len(), 1); assert_eq!(concat_line(&out[0]), ""); } @@ -968,7 +968,7 @@ mod tests { #[test] fn leading_spaces_preserved_on_first_line() { let line = Line::from(" hello"); - let out = word_wrap_line(&line, 8); + let out = word_wrap_line(&line, /*width_or_options*/ 8); assert_eq!(out.len(), 1); assert_eq!(concat_line(&out[0]), " hello"); } @@ -976,7 +976,7 @@ mod tests { #[test] fn multiple_spaces_between_words_dont_start_next_line_with_spaces() { let line = Line::from("hello world"); - let out = word_wrap_line(&line, 8); + let out = word_wrap_line(&line, /*width_or_options*/ 8); assert_eq!(out.len(), 2); assert_eq!(concat_line(&out[0]), "hello"); assert_eq!(concat_line(&out[1]), "world"); @@ -984,7 +984,7 @@ mod tests { #[test] fn break_words_false_allows_overflow_for_long_word() { - let opts = RtOptions::new(5).break_words(false); + let opts = RtOptions::new(/*width*/ 5).break_words(/*break_words*/ false); let line = Line::from("supercalifragilistic"); let out = word_wrap_line(&line, opts); assert_eq!(out.len(), 1); @@ -994,7 +994,7 @@ mod tests { #[test] fn hyphen_splitter_breaks_at_hyphen() { let line = Line::from("hello-world"); - let out = word_wrap_line(&line, 7); + let out = word_wrap_line(&line, /*width_or_options*/ 7); assert_eq!(out.len(), 2); assert_eq!(concat_line(&out[0]), "hello-"); assert_eq!(concat_line(&out[1]), "world"); @@ -1002,7 +1002,7 @@ mod tests { #[test] fn indent_consumes_width_leaving_one_char_space() { - let opts = RtOptions::new(4) + let opts = RtOptions::new(/*width*/ 4) .initial_indent(Line::from(">>>>")) .subsequent_indent(Line::from("--")); let line = Line::from("hello"); @@ -1016,7 +1016,7 @@ mod tests { #[test] fn wide_unicode_wraps_by_display_width() { let line = Line::from("πŸ˜€πŸ˜€πŸ˜€"); - let out = word_wrap_line(&line, 4); + let out = word_wrap_line(&line, /*width_or_options*/ 4); assert_eq!(out.len(), 2); assert_eq!(concat_line(&out[0]), "πŸ˜€πŸ˜€"); assert_eq!(concat_line(&out[1]), "πŸ˜€"); @@ -1026,7 +1026,7 @@ mod tests { fn styled_split_within_span_preserves_style() { use ratatui::style::Stylize; let line = Line::from(vec!["abcd".red()]); - let out = word_wrap_line(&line, 2); + let out = word_wrap_line(&line, /*width_or_options*/ 2); assert_eq!(out.len(), 2); assert_eq!(out[0].spans.len(), 1); assert_eq!(out[1].spans.len(), 1); @@ -1038,7 +1038,7 @@ mod tests { #[test] fn wrap_lines_applies_initial_indent_only_once() { - let opts = RtOptions::new(8) + let opts = RtOptions::new(/*width*/ 8) .initial_indent(Line::from("- ")) .subsequent_indent(Line::from(" ")); @@ -1057,14 +1057,14 @@ mod tests { #[test] fn wrap_lines_without_indents_is_concat_of_single_wraps() { let lines = vec![Line::from("hello"), Line::from("world!")]; - let out = word_wrap_lines(lines, 10); + let out = word_wrap_lines(lines, /*width_or_options*/ 10); let rendered: Vec = out.iter().map(concat_line).collect(); assert_eq!(rendered, vec!["hello", "world!"]); } #[test] fn wrap_lines_borrowed_applies_initial_indent_only_once() { - let opts = RtOptions::new(8) + let opts = RtOptions::new(/*width*/ 8) .initial_indent(Line::from("- ")) .subsequent_indent(Line::from(" ")); @@ -1081,7 +1081,7 @@ mod tests { #[test] fn wrap_lines_borrowed_without_indents_is_concat_of_single_wraps() { let lines = [Line::from("hello"), Line::from("world!")]; - let out = word_wrap_lines_borrowed(lines.iter(), 10); + let out = word_wrap_lines_borrowed(lines.iter(), /*width_or_options*/ 10); let rendered: Vec = out.iter().map(concat_line).collect(); assert_eq!(rendered, vec!["hello", "world!"]); } @@ -1089,7 +1089,7 @@ mod tests { #[test] fn wrap_lines_accepts_borrowed_iterators() { let lines = [Line::from("hello world"), Line::from("foo bar baz")]; - let out = word_wrap_lines(lines, 10); + let out = word_wrap_lines(lines, /*width_or_options*/ 10); let rendered: Vec = out.iter().map(concat_line).collect(); assert_eq!(rendered, vec!["hello", "world", "foo bar", "baz"]); } @@ -1097,7 +1097,7 @@ mod tests { #[test] fn wrap_lines_accepts_str_slices() { let lines = ["hello world", "goodnight moon"]; - let out = word_wrap_lines(lines, 12); + let out = word_wrap_lines(lines, /*width_or_options*/ 12); let rendered: Vec = out.iter().map(concat_line).collect(); assert_eq!(rendered, vec!["hello world", "goodnight", "moon"]); } @@ -1105,9 +1105,9 @@ mod tests { #[test] fn line_height_counts_double_width_emoji() { let line = "πŸ˜€πŸ˜€πŸ˜€".into(); // each emoji ~ width 2 - assert_eq!(word_wrap_line(&line, 4).len(), 2); - assert_eq!(word_wrap_line(&line, 2).len(), 3); - assert_eq!(word_wrap_line(&line, 6).len(), 1); + assert_eq!(word_wrap_line(&line, /*width_or_options*/ 4).len(), 2); + assert_eq!(word_wrap_line(&line, /*width_or_options*/ 2).len(), 3); + assert_eq!(word_wrap_line(&line, /*width_or_options*/ 6).len(), 1); } #[test] @@ -1116,7 +1116,7 @@ mod tests { let line = Line::from(sample); let lines = [line]; // Force small width to exercise wrapping at spaces. - let wrapped = word_wrap_lines_borrowed(&lines, 40); + let wrapped = word_wrap_lines_borrowed(&lines, /*width_or_options*/ 40); let joined: String = wrapped.iter().map(ToString::to_string).join("\n"); assert_eq!( joined, @@ -1134,10 +1134,10 @@ them."# let line = Line::from( "http://example.com/long-url-with-dashes-wider-than-terminal-window/blah-blah-blah-text/more-gibberish-text", ); - let opts = RtOptions::new(24) + let opts = RtOptions::new(/*width*/ 24) .word_separator(textwrap::WordSeparator::AsciiSpace) .word_splitter(textwrap::WordSplitter::NoHyphenation) - .break_words(false); + .break_words(/*break_words*/ false); let out = word_wrap_line(&line, opts); @@ -1229,7 +1229,7 @@ them."# #[test] fn adaptive_wrap_line_keeps_long_url_like_token_intact() { let line = Line::from("example.test/a-very-long-path-with-many-segments-and-query?x=1&y=2"); - let out = adaptive_wrap_line(&line, RtOptions::new(20)); + let out = adaptive_wrap_line(&line, RtOptions::new(/*width*/ 20)); assert_eq!(out.len(), 1); assert_eq!( concat_line(&out[0]), @@ -1240,7 +1240,7 @@ them."# #[test] fn adaptive_wrap_line_preserves_default_behavior_for_non_url_tokens() { let line = Line::from("a_very_long_token_without_spaces_to_force_wrapping"); - let out = adaptive_wrap_line(&line, RtOptions::new(20)); + let out = adaptive_wrap_line(&line, RtOptions::new(/*width*/ 20)); assert!( out.len() > 1, "expected non-url token to wrap with default options" @@ -1251,7 +1251,7 @@ them."# fn adaptive_wrap_line_mixed_line_wraps_long_non_url_token() { let long_non_url = "a_very_long_token_without_spaces_to_force_wrapping"; let line = Line::from(format!("see https://ex.com {long_non_url}")); - let out = adaptive_wrap_line(&line, RtOptions::new(24)); + let out = adaptive_wrap_line(&line, RtOptions::new(/*width*/ 24)); assert!( out.iter() @@ -1269,7 +1269,7 @@ them."# fn map_owned_wrapped_line_to_range_recovers_on_non_prefix_mismatch() { // Match source chars first, then introduce a non-penalty mismatch. // The function should recover and return the mapped prefix range. - let range = map_owned_wrapped_line_to_range("hello world", 0, "helloX", ""); + let range = map_owned_wrapped_line_to_range("hello world", /*cursor*/ 0, "helloX", ""); assert_eq!(range, 0..5); } @@ -1285,7 +1285,7 @@ them."# let text = "- item one and some more words"; // Simulate what textwrap would produce for the first continuation line // when subsequent_indent = "- ": it prepends "- " to the source slice. - let range = map_owned_wrapped_line_to_range(text, 0, "- - item one", "- "); + let range = map_owned_wrapped_line_to_range(text, /*cursor*/ 0, "- - item one", "- "); // The mapper should skip the synthetic "- " prefix and map "- item one" // back to source bytes 0..10. assert_eq!(range, 0..10); @@ -1330,7 +1330,7 @@ them."# panic!("expected at least one wrapped line"); }; - let mapped = map_owned_wrapped_line_to_range(text, 0, line.as_ref(), "- "); + let mapped = map_owned_wrapped_line_to_range(text, /*cursor*/ 0, line.as_ref(), "- "); let expected_len = line .as_ref() .strip_prefix("- ") diff --git a/codex-rs/utils/cache/src/lib.rs b/codex-rs/utils/cache/src/lib.rs index 743c289ff..ed4b92668 100644 --- a/codex-rs/utils/cache/src/lib.rs +++ b/codex-rs/utils/cache/src/lib.rs @@ -151,18 +151,18 @@ mod tests { let cache = BlockingLruCache::new(NonZeroUsize::new(2).expect("capacity")); assert!(cache.get(&"first").is_none()); - cache.insert("first", 1); + cache.insert("first", /*value*/ 1); assert_eq!(cache.get(&"first"), Some(1)); } #[tokio::test(flavor = "multi_thread")] async fn evicts_least_recently_used() { let cache = BlockingLruCache::new(NonZeroUsize::new(2).expect("capacity")); - cache.insert("a", 1); - cache.insert("b", 2); + cache.insert("a", /*value*/ 1); + cache.insert("b", /*value*/ 2); assert_eq!(cache.get(&"a"), Some(1)); - cache.insert("c", 3); + cache.insert("c", /*value*/ 3); assert!(cache.get(&"b").is_none()); assert_eq!(cache.get(&"a"), Some(1)); @@ -172,7 +172,7 @@ mod tests { #[test] fn disabled_without_runtime() { let cache = BlockingLruCache::new(NonZeroUsize::new(2).expect("capacity")); - cache.insert("first", 1); + cache.insert("first", /*value*/ 1); assert!(cache.get(&"first").is_none()); assert_eq!(cache.get_or_insert_with("first", || 2), 2); diff --git a/codex-rs/utils/cli/src/format_env_display.rs b/codex-rs/utils/cli/src/format_env_display.rs index fa35bdce2..dda0cad09 100644 --- a/codex-rs/utils/cli/src/format_env_display.rs +++ b/codex-rs/utils/cli/src/format_env_display.rs @@ -26,7 +26,7 @@ mod tests { #[test] fn returns_dash_when_empty() { - assert_eq!(format_env_display(None, &[]), "-"); + assert_eq!(format_env_display(/*env*/ None, &[]), "-"); let empty_map = HashMap::new(); assert_eq!(format_env_display(Some(&empty_map), &[]), "-"); @@ -45,7 +45,10 @@ mod tests { fn formats_env_vars_with_dollar_prefix() { let vars = vec!["TOKEN".to_string(), "PATH".to_string()]; - assert_eq!(format_env_display(None, &vars), "TOKEN=*****, PATH=*****"); + assert_eq!( + format_env_display(/*env*/ None, &vars), + "TOKEN=*****, PATH=*****" + ); } #[test] diff --git a/codex-rs/utils/home-dir/src/lib.rs b/codex-rs/utils/home-dir/src/lib.rs index 17be887a8..dd97b4558 100644 --- a/codex-rs/utils/home-dir/src/lib.rs +++ b/codex-rs/utils/home-dir/src/lib.rs @@ -120,7 +120,8 @@ mod tests { #[test] fn find_codex_home_without_env_uses_default_home_dir() { - let resolved = find_codex_home_from_env(None).expect("default CODEX_HOME"); + let resolved = + find_codex_home_from_env(/*codex_home_env*/ None).expect("default CODEX_HOME"); let mut expected = home_dir().expect("home dir"); expected.push(".codex"); assert_eq!(resolved, expected); diff --git a/codex-rs/utils/path-utils/src/path_utils_tests.rs b/codex-rs/utils/path-utils/src/path_utils_tests.rs index f028133f1..bda4b77ab 100644 --- a/codex-rs/utils/path-utils/src/path_utils_tests.rs +++ b/codex-rs/utils/path-utils/src/path_utils_tests.rs @@ -29,7 +29,8 @@ mod wsl { #[test] fn wsl_mnt_drive_paths_lowercase() { - let normalized = normalize_for_wsl_with_flag(PathBuf::from("/mnt/C/Users/Dev"), true); + let normalized = + normalize_for_wsl_with_flag(PathBuf::from("/mnt/C/Users/Dev"), /*is_wsl*/ true); assert_eq!(normalized, PathBuf::from("/mnt/c/users/dev")); } @@ -37,7 +38,7 @@ mod wsl { #[test] fn wsl_non_drive_paths_unchanged() { let path = PathBuf::from("/mnt/cc/Users/Dev"); - let normalized = normalize_for_wsl_with_flag(path.clone(), true); + let normalized = normalize_for_wsl_with_flag(path.clone(), /*is_wsl*/ true); assert_eq!(normalized, path); } @@ -45,7 +46,7 @@ mod wsl { #[test] fn wsl_non_mnt_paths_unchanged() { let path = PathBuf::from("/home/Dev"); - let normalized = normalize_for_wsl_with_flag(path.clone(), true); + let normalized = normalize_for_wsl_with_flag(path.clone(), /*is_wsl*/ true); assert_eq!(normalized, path); } @@ -60,7 +61,7 @@ mod native_workdir { #[test] fn windows_verbatim_paths_are_simplified() { let path = PathBuf::from(r"\\?\D:\c\x\worktrees\2508\swift-base"); - let normalized = normalize_for_native_workdir_with_flag(path, true); + let normalized = normalize_for_native_workdir_with_flag(path, /*is_windows*/ true); assert_eq!( normalized, @@ -71,7 +72,8 @@ mod native_workdir { #[test] fn non_windows_paths_are_unchanged() { let path = PathBuf::from(r"\\?\D:\c\x\worktrees\2508\swift-base"); - let normalized = normalize_for_native_workdir_with_flag(path.clone(), false); + let normalized = + normalize_for_native_workdir_with_flag(path.clone(), /*is_windows*/ false); assert_eq!(normalized, path); } diff --git a/codex-rs/utils/pty/src/tests.rs b/codex-rs/utils/pty/src/tests.rs index fa0e821a2..c614f357f 100644 --- a/codex-rs/utils/pty/src/tests.rs +++ b/codex-rs/utils/pty/src/tests.rs @@ -426,7 +426,7 @@ async fn pipe_process_round_trips_stdin() -> anyhow::Result<()> { drop(writer); session.close_stdin(); - let (output, code) = collect_output_until_exit(output_rx, exit_rx, 5_000).await; + let (output, code) = collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 5_000).await; let text = String::from_utf8_lossy(&output); assert!( @@ -535,7 +535,7 @@ async fn pipe_drains_stderr_without_stdout_activity() -> anyhow::Result<()> { let spawned = spawn_pipe_process(&python, &args, Path::new("."), &env_map, &None).await?; let (_session, output_rx, exit_rx) = combine_spawned_output(spawned); - let (output, code) = collect_output_until_exit(output_rx, exit_rx, 10_000).await; + let (output, code) = collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 10_000).await; assert_eq!(code, 0, "expected python to exit cleanly"); assert!(!output.is_empty(), "expected stderr output to be drained"); @@ -644,7 +644,7 @@ async fn pty_terminate_kills_background_children_in_same_process_group() -> anyh .await?; let (session, mut output_rx, _exit_rx) = combine_spawned_output(spawned); - let bg_pid = match wait_for_marker_pid(&mut output_rx, marker, 2_000).await { + let bg_pid = match wait_for_marker_pid(&mut output_rx, marker, /*timeout_ms*/ 2_000).await { Ok(pid) => pid, Err(err) => { session.terminate(); @@ -658,7 +658,7 @@ async fn pty_terminate_kills_background_children_in_same_process_group() -> anyh session.terminate(); - let exited = wait_for_process_exit(bg_pid, 3_000).await?; + let exited = wait_for_process_exit(bg_pid, /*timeout_ms*/ 3_000).await?; if !exited { let _ = unsafe { libc::kill(bg_pid, libc::SIGKILL) }; } @@ -708,7 +708,7 @@ async fn pty_spawn_can_preserve_inherited_fds() -> anyhow::Result<()> { drop(write_end); let (_session, output_rx, exit_rx) = combine_spawned_output(spawned); - let (_, code) = collect_output_until_exit(output_rx, exit_rx, 2_000).await; + let (_, code) = collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 2_000).await; assert_eq!(code, 0, "expected preserved-fd PTY child to exit cleanly"); let mut pipe_output = String::new(); @@ -762,14 +762,19 @@ async fn pty_preserving_inherited_fds_keeps_python_repl_running() -> anyhow::Res let (session, mut output_rx, exit_rx) = combine_spawned_output(spawned); let writer = session.writer_sender(); let newline = "\n"; - let mut output = - wait_for_python_repl_ready_via_probe(&writer, &mut output_rx, 5_000, newline).await?; + let mut output = wait_for_python_repl_ready_via_probe( + &writer, + &mut output_rx, + /*timeout_ms*/ 5_000, + newline, + ) + .await?; let marker = "__codex_preserved_py_pid:"; writer .send(format!("import os; print('{marker}' + str(os.getpid())){newline}").into_bytes()) .await?; - let python_pid = match wait_for_marker_pid(&mut output_rx, marker, 2_000).await { + let python_pid = match wait_for_marker_pid(&mut output_rx, marker, /*timeout_ms*/ 2_000).await { Ok(pid) => pid, Err(err) => { session.terminate(); @@ -782,7 +787,8 @@ async fn pty_preserving_inherited_fds_keeps_python_repl_running() -> anyhow::Res ); writer.send(format!("exit(){newline}").into_bytes()).await?; - let (remaining_output, code) = collect_output_until_exit(output_rx, exit_rx, 5_000).await; + let (remaining_output, code) = + collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 5_000).await; output.extend_from_slice(&remaining_output); assert_eq!(code, 0, "expected python to exit cleanly"); @@ -871,7 +877,12 @@ async fn pty_spawn_with_inherited_fds_supports_resize() -> anyhow::Result<()> { let (session, mut output_rx, exit_rx) = combine_spawned_output(spawned); let writer = session.writer_sender(); - let mut output = wait_for_output_contains(&mut output_rx, "start:31 101\r\n", 5_000).await?; + let mut output = wait_for_output_contains( + &mut output_rx, + "start:31 101\r\n", + /*timeout_ms*/ 5_000, + ) + .await?; session.resize(TerminalSize { rows: 45, @@ -880,7 +891,8 @@ async fn pty_spawn_with_inherited_fds_supports_resize() -> anyhow::Result<()> { writer.send(b"go\n".to_vec()).await?; session.close_stdin(); - let (remaining_output, code) = collect_output_until_exit(output_rx, exit_rx, 5_000).await; + let (remaining_output, code) = + collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 5_000).await; output.extend_from_slice(&remaining_output); let text = String::from_utf8_lossy(&output); let normalized = text.replace("\r\n", "\n"); @@ -933,7 +945,7 @@ async fn pipe_spawn_no_stdin_can_preserve_inherited_fds() -> anyhow::Result<()> drop(write_end); let (_session, output_rx, exit_rx) = combine_spawned_output(spawned); - let (_, code) = collect_output_until_exit(output_rx, exit_rx, 2_000).await; + let (_, code) = collect_output_until_exit(output_rx, exit_rx, /*timeout_ms*/ 2_000).await; assert_eq!(code, 0, "expected preserved-fd pipe child to exit cleanly"); let mut pipe_output = String::new(); diff --git a/codex-rs/utils/sleep-inhibitor/src/lib.rs b/codex-rs/utils/sleep-inhibitor/src/lib.rs index 0b3d2c9a3..9b7c0f885 100644 --- a/codex-rs/utils/sleep-inhibitor/src/lib.rs +++ b/codex-rs/utils/sleep-inhibitor/src/lib.rs @@ -77,37 +77,37 @@ mod tests { #[test] fn sleep_inhibitor_toggles_without_panicking() { - let mut inhibitor = SleepInhibitor::new(true); - inhibitor.set_turn_running(true); + let mut inhibitor = SleepInhibitor::new(/*enabled*/ true); + inhibitor.set_turn_running(/*turn_running*/ true); assert!(inhibitor.is_turn_running()); - inhibitor.set_turn_running(false); + inhibitor.set_turn_running(/*turn_running*/ false); assert!(!inhibitor.is_turn_running()); } #[test] fn sleep_inhibitor_disabled_does_not_panic() { - let mut inhibitor = SleepInhibitor::new(false); - inhibitor.set_turn_running(true); + let mut inhibitor = SleepInhibitor::new(/*enabled*/ false); + inhibitor.set_turn_running(/*turn_running*/ true); assert!(inhibitor.is_turn_running()); - inhibitor.set_turn_running(false); + inhibitor.set_turn_running(/*turn_running*/ false); assert!(!inhibitor.is_turn_running()); } #[test] fn sleep_inhibitor_multiple_true_calls_are_idempotent() { - let mut inhibitor = SleepInhibitor::new(true); - inhibitor.set_turn_running(true); - inhibitor.set_turn_running(true); - inhibitor.set_turn_running(true); - inhibitor.set_turn_running(false); + let mut inhibitor = SleepInhibitor::new(/*enabled*/ true); + inhibitor.set_turn_running(/*turn_running*/ true); + inhibitor.set_turn_running(/*turn_running*/ true); + inhibitor.set_turn_running(/*turn_running*/ true); + inhibitor.set_turn_running(/*turn_running*/ false); } #[test] fn sleep_inhibitor_can_toggle_multiple_times() { - let mut inhibitor = SleepInhibitor::new(true); - inhibitor.set_turn_running(true); - inhibitor.set_turn_running(false); - inhibitor.set_turn_running(true); - inhibitor.set_turn_running(false); + let mut inhibitor = SleepInhibitor::new(/*enabled*/ true); + inhibitor.set_turn_running(/*turn_running*/ true); + inhibitor.set_turn_running(/*turn_running*/ false); + inhibitor.set_turn_running(/*turn_running*/ true); + inhibitor.set_turn_running(/*turn_running*/ false); } } diff --git a/codex-rs/utils/stream-parser/src/assistant_text.rs b/codex-rs/utils/stream-parser/src/assistant_text.rs index 931c30bd5..019c5e0b4 100644 --- a/codex-rs/utils/stream-parser/src/assistant_text.rs +++ b/codex-rs/utils/stream-parser/src/assistant_text.rs @@ -80,7 +80,7 @@ mod tests { #[test] fn parses_citations_across_seed_and_delta_boundaries() { - let mut parser = AssistantTextStreamParser::new(false); + let mut parser = AssistantTextStreamParser::new(/*plan_mode*/ false); let seeded = parser.push_str("hello doc"); let parsed = parser.push_str("1 world"); @@ -96,7 +96,7 @@ mod tests { #[test] fn parses_plan_segments_after_citation_stripping() { - let mut parser = AssistantTextStreamParser::new(true); + let mut parser = AssistantTextStreamParser::new(/*plan_mode*/ true); let seeded = parser.push_str("Intro\n\n- step doc\n"); diff --git a/codex-rs/utils/string/src/truncate/tests.rs b/codex-rs/utils/string/src/truncate/tests.rs index 5d517e86d..3549cb228 100644 --- a/codex-rs/utils/string/src/truncate/tests.rs +++ b/codex-rs/utils/string/src/truncate/tests.rs @@ -5,37 +5,83 @@ use pretty_assertions::assert_eq; #[test] fn split_string_works() { - assert_eq!(split_string("hello world", 5, 5), (1, "hello", "world")); - assert_eq!(split_string("abc", 0, 0), (3, "", "")); + assert_eq!( + split_string( + "hello world", + /*beginning_bytes*/ 5, + /*end_bytes*/ 5 + ), + (1, "hello", "world") + ); + assert_eq!( + split_string("abc", /*beginning_bytes*/ 0, /*end_bytes*/ 0), + (3, "", "") + ); } #[test] fn split_string_handles_empty_string() { - assert_eq!(split_string("", 4, 4), (0, "", "")); + assert_eq!( + split_string("", /*beginning_bytes*/ 4, /*end_bytes*/ 4), + (0, "", "") + ); } #[test] fn split_string_only_keeps_prefix_when_tail_budget_is_zero() { - assert_eq!(split_string("abcdef", 3, 0), (3, "abc", "")); + assert_eq!( + split_string("abcdef", /*beginning_bytes*/ 3, /*end_bytes*/ 0), + (3, "abc", "") + ); } #[test] fn split_string_only_keeps_suffix_when_prefix_budget_is_zero() { - assert_eq!(split_string("abcdef", 0, 3), (3, "", "def")); + assert_eq!( + split_string("abcdef", /*beginning_bytes*/ 0, /*end_bytes*/ 3), + (3, "", "def") + ); } #[test] fn split_string_handles_overlapping_budgets_without_removal() { - assert_eq!(split_string("abcdef", 4, 4), (0, "abcd", "ef")); + assert_eq!( + split_string("abcdef", /*beginning_bytes*/ 4, /*end_bytes*/ 4), + (0, "abcd", "ef") + ); } #[test] fn split_string_respects_utf8_boundaries() { - assert_eq!(split_string("πŸ˜€abcπŸ˜€", 5, 5), (1, "πŸ˜€a", "cπŸ˜€")); + assert_eq!( + split_string("πŸ˜€abcπŸ˜€", /*beginning_bytes*/ 5, /*end_bytes*/ 5), + (1, "πŸ˜€a", "cπŸ˜€") + ); - assert_eq!(split_string("πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", 1, 1), (5, "", "")); - assert_eq!(split_string("πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", 7, 7), (3, "πŸ˜€", "πŸ˜€")); - assert_eq!(split_string("πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", 8, 8), (1, "πŸ˜€πŸ˜€", "πŸ˜€πŸ˜€")); + assert_eq!( + split_string( + "πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", + /*beginning_bytes*/ 1, + /*end_bytes*/ 1 + ), + (5, "", "") + ); + assert_eq!( + split_string( + "πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", + /*beginning_bytes*/ 7, + /*end_bytes*/ 7 + ), + (3, "πŸ˜€", "πŸ˜€") + ); + assert_eq!( + split_string( + "πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€", + /*beginning_bytes*/ 8, + /*end_bytes*/ 8 + ), + (1, "πŸ˜€πŸ˜€", "πŸ˜€πŸ˜€") + ); } #[test] @@ -50,7 +96,7 @@ fn truncate_with_token_budget_returns_original_when_under_limit() { #[test] fn truncate_with_token_budget_reports_truncation_at_zero_limit() { let s = "abcdef"; - let (out, original) = truncate_middle_with_token_budget(s, 0); + let (out, original) = truncate_middle_with_token_budget(s, /*max_tokens*/ 0); assert_eq!(out, "…2 tokens truncated…"); assert_eq!(original, Some(2)); } @@ -58,7 +104,7 @@ fn truncate_with_token_budget_reports_truncation_at_zero_limit() { #[test] fn truncate_middle_tokens_handles_utf8_content() { let s = "πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€\nsecond line with text\n"; - let (out, tokens) = truncate_middle_with_token_budget(s, 8); + let (out, tokens) = truncate_middle_with_token_budget(s, /*max_tokens*/ 8); assert_eq!(out, "πŸ˜€πŸ˜€πŸ˜€πŸ˜€β€¦8 tokens truncated… line with text\n"); assert_eq!(tokens, Some(16)); } @@ -66,6 +112,6 @@ fn truncate_middle_tokens_handles_utf8_content() { #[test] fn truncate_middle_bytes_handles_utf8_content() { let s = "πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€πŸ˜€\nsecond line with text\n"; - let out = truncate_middle_chars(s, 20); + let out = truncate_middle_chars(s, /*max_bytes*/ 20); assert_eq!(out, "πŸ˜€πŸ˜€β€¦21 chars truncated…with text\n"); } diff --git a/tools/argument-comment-lint/README.md b/tools/argument-comment-lint/README.md index 25ece8b6a..5e145aa39 100644 --- a/tools/argument-comment-lint/README.md +++ b/tools/argument-comment-lint/README.md @@ -132,6 +132,9 @@ just argument-comment-lint -p codex-core If no package selection is provided, `run-prebuilt-linter.sh` defaults to checking the `codex-rs` workspace with `--workspace --no-deps`. +For non-`--fix` runs, both wrappers also default the underlying Cargo +invocation to `--all-targets` unless you explicitly narrow the target set, so +workspace and package lint runs both cover test-only call sites by default. Repo runs also promote `uncommented_anonymous_literal_argument` to an error by default: @@ -152,7 +155,7 @@ CARGO_INCREMENTAL=1 \ ./tools/argument-comment-lint/run.sh -p codex-core ``` -To expand target coverage for an ad hoc run: +To override an explicitly narrow target selection, or to be explicit in scripts: ```bash ./tools/argument-comment-lint/run-prebuilt-linter.sh -p codex-core -- --all-targets diff --git a/tools/argument-comment-lint/run-prebuilt-linter.sh b/tools/argument-comment-lint/run-prebuilt-linter.sh index 3828e06d9..bc095ed55 100755 --- a/tools/argument-comment-lint/run-prebuilt-linter.sh +++ b/tools/argument-comment-lint/run-prebuilt-linter.sh @@ -10,9 +10,39 @@ has_manifest_path=false has_package_selection=false has_library_selection=false has_no_deps=false +has_cargo_target_selection=false +has_fix=false +after_separator=false expect_value="" +lint_args=() +cargo_args=() for arg in "$@"; do + if [[ "$after_separator" == true ]]; then + cargo_args+=("$arg") + case "$arg" in + --all-targets|--lib|--bins|--tests|--examples|--benches|--doc) + has_cargo_target_selection=true + ;; + --bin|--test|--example|--bench) + has_cargo_target_selection=true + ;; + --bin=*|--test=*|--example=*|--bench=*) + has_cargo_target_selection=true + ;; + esac + continue + fi + + case "$arg" in + --) + after_separator=true + continue + ;; + esac + + lint_args+=("$arg") + if [[ -n "$expect_value" ]]; then case "$expect_value" in manifest_path) @@ -30,9 +60,6 @@ for arg in "$@"; do fi case "$arg" in - --) - break - ;; --manifest-path) expect_value="manifest_path" ;; @@ -45,6 +72,9 @@ for arg in "$@"; do --package=*) has_package_selection=true ;; + --fix) + has_fix=true + ;; --lib|--lib-path) expect_value="library_selection" ;; @@ -60,17 +90,25 @@ for arg in "$@"; do esac done -lint_args=() +final_args=() if [[ "$has_manifest_path" == false ]]; then - lint_args+=(--manifest-path "$manifest_path") + final_args+=(--manifest-path "$manifest_path") fi if [[ "$has_package_selection" == false ]]; then - lint_args+=(--workspace) + final_args+=(--workspace) fi if [[ "$has_no_deps" == false ]]; then - lint_args+=(--no-deps) + final_args+=(--no-deps) +fi +if [[ "$has_fix" == false && "$has_cargo_target_selection" == false ]]; then + cargo_args+=(--all-targets) +fi +if [[ ${#lint_args[@]} -gt 0 ]]; then + final_args+=("${lint_args[@]}") +fi +if [[ ${#cargo_args[@]} -gt 0 ]]; then + final_args+=(-- "${cargo_args[@]}") fi -lint_args+=("$@") if ! command -v dotslash >/dev/null 2>&1; then cat >&2 </dev/null 2>&1 || ! command -v dylint-link >/dev/null 2>&1; then @@ -52,6 +57,31 @@ set_default_env() { } for arg in "$@"; do + if [[ "$after_separator" == true ]]; then + cargo_args+=("$arg") + case "$arg" in + --all-targets|--lib|--bins|--tests|--examples|--benches|--doc) + has_cargo_target_selection=true + ;; + --bin|--test|--example|--bench) + has_cargo_target_selection=true + ;; + --bin=*|--test=*|--example=*|--bench=*) + has_cargo_target_selection=true + ;; + esac + continue + fi + + case "$arg" in + --) + after_separator=true + continue + ;; + esac + + lint_args+=("$arg") + if [[ -n "$expect_value" ]]; then case "$expect_value" in manifest_path) @@ -69,9 +99,6 @@ for arg in "$@"; do fi case "$arg" in - --) - break - ;; --manifest-path) expect_value="manifest_path" ;; @@ -84,6 +111,9 @@ for arg in "$@"; do --package=*) has_package_selection=true ;; + --fix) + has_fix=true + ;; --workspace) has_package_selection=true ;; @@ -99,17 +129,25 @@ for arg in "$@"; do esac done -lint_args=() +final_args=() if [[ "$has_manifest_path" == false ]]; then - lint_args+=(--manifest-path "$manifest_path") + final_args+=(--manifest-path "$manifest_path") fi if [[ "$has_package_selection" == false ]]; then - lint_args+=(--workspace) + final_args+=(--workspace) fi if [[ "$has_no_deps" == false ]]; then - lint_args+=(--no-deps) + final_args+=(--no-deps) +fi +if [[ "$has_fix" == false && "$has_cargo_target_selection" == false ]]; then + cargo_args+=(--all-targets) +fi +if [[ ${#lint_args[@]} -gt 0 ]]; then + final_args+=("${lint_args[@]}") +fi +if [[ ${#cargo_args[@]} -gt 0 ]]; then + final_args+=(-- "${cargo_args[@]}") fi -lint_args+=("$@") ensure_local_prerequisites set_default_env @@ -118,6 +156,6 @@ cmd=(cargo dylint --path "$lint_path") if [[ "$has_library_selection" == false ]]; then cmd+=(--all) fi -cmd+=("${lint_args[@]}") +cmd+=("${final_args[@]}") exec "${cmd[@]}"