From 61dfe0b86c75bb4e6c173a70ca9fb2f2daac2f67 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Fri, 27 Mar 2026 19:00:44 -0700 Subject: [PATCH] chore: clean up argument-comment lint and roll out all-target CI on macOS (#16054) ## Why `argument-comment-lint` was green in CI even though the repo still had many uncommented literal arguments. The main gap was target coverage: the repo wrapper did not force Cargo to inspect test-only call sites, so examples like the `latest_session_lookup_params(true, ...)` tests in `codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path. This change cleans up the existing backlog, makes the default repo lint path cover all Cargo targets, and starts rolling that stricter CI enforcement out on the platform where it is currently validated. ## What changed - mechanically fixed existing `argument-comment-lint` violations across the `codex-rs` workspace, including tests, examples, and benches - updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and `tools/argument-comment-lint/run.sh` so non-`--fix` runs default to `--all-targets` unless the caller explicitly narrows the target set - fixed both wrappers so forwarded cargo arguments after `--` are preserved with a single separator - documented the new default behavior in `tools/argument-comment-lint/README.md` - updated `rust-ci` so the macOS lint lane keeps the plain wrapper invocation and therefore enforces `--all-targets`, while Linux and Windows temporarily pass `-- --lib --bins` That temporary CI split keeps the stricter all-targets check where it is already cleaned up, while leaving room to finish the remaining Linux- and Windows-specific target-gated cleanup before enabling `--all-targets` on those runners. The Linux and Windows failures on the intermediate revision were caused by the wrapper forwarding bug, not by additional lint findings in those lanes. ## Validation - `bash -n tools/argument-comment-lint/run.sh` - `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh` - shell-level wrapper forwarding check for `-- --lib --bins` - shell-level wrapper forwarding check for `-- --tests` - `just argument-comment-lint` - `cargo test` in `tools/argument-comment-lint` - `cargo test -p codex-terminal-detection` ## Follow-up - Clean up remaining Linux-only target-gated callsites, then switch the Linux lint lane back to the plain wrapper invocation. - Clean up remaining Windows-only target-gated callsites, then switch the Windows lint lane back to the plain wrapper invocation. --- .github/workflows/rust-ci.yml | 5 + .../analytics/src/analytics_client_tests.rs | 12 +- codex-rs/app-server-client/src/lib.rs | 5 +- codex-rs/app-server-protocol/src/export.rs | 2 +- .../tests/schema_fixtures.rs | 2 +- .../app-server/src/codex_message_processor.rs | 33 +- .../plugin_app_helpers.rs | 2 +- codex-rs/app-server/src/filters.rs | 2 +- codex-rs/app-server/src/in_process.rs | 3 +- codex-rs/app-server/src/lib.rs | 5 +- .../src/message_processor/tracing_tests.rs | 24 +- codex-rs/app-server/src/outgoing_message.rs | 6 +- codex-rs/app-server/src/thread_status.rs | 12 +- codex-rs/app-server/src/transport/auth.rs | 51 +- codex-rs/app-server/src/transport/mod.rs | 12 +- codex-rs/app-server/tests/suite/auth.rs | 2 +- .../tests/suite/conversation_summary.rs | 4 +- .../tests/suite/fuzzy_file_search.rs | 12 +- codex-rs/app-server/tests/suite/v2/account.rs | 12 +- .../app-server/tests/suite/v2/analytics.rs | 4 +- .../app-server/tests/suite/v2/command_exec.rs | 18 +- .../app-server/tests/suite/v2/compaction.rs | 24 +- .../suite/v2/connection_handling_websocket.rs | 50 +- .../v2/connection_handling_websocket_unix.rs | 12 +- .../app-server/tests/suite/v2/model_list.rs | 6 +- .../app-server/tests/suite/v2/plan_item.rs | 4 +- .../tests/suite/v2/plugin_install.rs | 20 +- .../app-server/tests/suite/v2/plugin_list.rs | 10 +- .../tests/suite/v2/realtime_conversation.rs | 10 +- codex-rs/app-server/tests/suite/v2/review.rs | 2 +- .../app-server/tests/suite/v2/thread_fork.rs | 6 +- .../app-server/tests/suite/v2/thread_list.rs | 248 +-- .../tests/suite/v2/thread_metadata_update.rs | 16 +- .../tests/suite/v2/thread_name_websocket.rs | 34 +- .../app-server/tests/suite/v2/thread_read.rs | 6 +- .../tests/suite/v2/thread_resume.rs | 18 +- .../tests/suite/v2/thread_shell_command.rs | 6 +- .../tests/suite/v2/thread_unsubscribe.rs | 2 +- .../app-server/tests/suite/v2/turn_start.rs | 12 +- .../tests/suite/v2/turn_start_zsh_fork.rs | 8 +- .../tests/suite/v2/windows_sandbox_setup.rs | 2 +- codex-rs/apply-patch/src/invocation.rs | 13 +- codex-rs/apply-patch/src/parser.rs | 32 +- codex-rs/apply-patch/src/seek_sequence.rs | 20 +- codex-rs/chatgpt/src/connectors.rs | 16 +- codex-rs/cli/src/debug_sandbox.rs | 10 +- codex-rs/cli/src/main.rs | 36 +- codex-rs/cloud-requirements/src/lib.rs | 28 +- codex-rs/cloud-tasks/src/app.rs | 4 +- codex-rs/cloud-tasks/src/lib.rs | 27 +- codex-rs/cloud-tasks/tests/env_filter.rs | 36 +- codex-rs/code-mode/src/description.rs | 6 +- codex-rs/code-mode/src/service.rs | 2 +- .../endpoint/realtime_websocket/methods.rs | 18 +- codex-rs/codex-api/src/rate_limits.rs | 2 +- codex-rs/codex-api/src/sse/responses.rs | 28 +- codex-rs/codex-api/tests/clients.rs | 14 +- .../codex-api/tests/models_integration.rs | 2 +- codex-rs/codex-api/tests/sse_end_to_end.rs | 2 +- codex-rs/config/src/constraint.rs | 27 +- codex-rs/connectors/src/lib.rs | 109 +- codex-rs/core-skills/src/loader_tests.rs | 2 +- codex-rs/core-skills/src/manager_tests.rs | 78 +- codex-rs/core/src/agent/control_tests.rs | 74 +- codex-rs/core/src/agent/registry_tests.rs | 66 +- codex-rs/core/src/agent/role_tests.rs | 17 +- codex-rs/core/src/auth_env_telemetry.rs | 3 +- codex-rs/core/src/client_common_tests.rs | 3 +- codex-rs/core/src/client_tests.rs | 25 +- .../src/codex/rollout_reconstruction_tests.rs | 2 +- codex-rs/core/src/codex_tests.rs | 153 +- codex-rs/core/src/codex_tests_guardian.rs | 7 +- codex-rs/core/src/commit_attribution_tests.rs | 4 +- codex-rs/core/src/compact_tests.rs | 28 +- codex-rs/core/src/config/config_tests.rs | 118 +- codex-rs/core/src/config/edit_tests.rs | 71 +- codex-rs/core/src/config/managed_features.rs | 5 +- codex-rs/core/src/config/permissions_tests.rs | 6 +- codex-rs/core/src/config_loader/tests.rs | 70 +- codex-rs/core/src/connectors_tests.rs | 74 +- .../core/src/context_manager/history_tests.rs | 46 +- .../core/src/contextual_user_message_tests.rs | 4 +- .../core/src/environment_context_tests.rs | 96 +- codex-rs/core/src/event_mapping_tests.rs | 2 +- codex-rs/core/src/exec_env_tests.rs | 2 +- codex-rs/core/src/exec_policy_tests.rs | 20 +- codex-rs/core/src/exec_tests.rs | 50 +- .../core/src/external_agent_config_tests.rs | 2 +- codex-rs/core/src/file_watcher_tests.rs | 32 +- codex-rs/core/src/git_info_tests.rs | 4 +- codex-rs/core/src/guardian/review_session.rs | 20 +- codex-rs/core/src/guardian/tests.rs | 72 +- codex-rs/core/src/mcp/auth.rs | 19 +- codex-rs/core/src/mcp/mod_tests.rs | 13 +- .../core/src/mcp_connection_manager_tests.rs | 4 +- .../core/src/mcp_tool_approval_templates.rs | 4 +- codex-rs/core/src/mcp_tool_call_tests.rs | 142 +- codex-rs/core/src/memories/storage_tests.rs | 2 +- codex-rs/core/src/memories/tests.rs | 58 +- codex-rs/core/src/message_history_tests.rs | 8 +- .../collaboration_mode_presets_tests.rs | 6 +- .../core/src/models_manager/manager_tests.rs | 46 +- .../core/src/network_proxy_loader_tests.rs | 4 +- .../core/src/original_image_detail_tests.rs | 2 +- codex-rs/core/src/plugins/manager_tests.rs | 52 +- .../core/src/plugins/marketplace_tests.rs | 46 +- codex-rs/core/src/project_doc_tests.rs | 63 +- codex-rs/core/src/realtime_context_tests.rs | 6 +- codex-rs/core/src/sandbox_tags_tests.rs | 2 +- codex-rs/core/src/shell_snapshot_tests.rs | 12 +- codex-rs/core/src/shell_tests.rs | 62 +- codex-rs/core/src/skills_watcher.rs | 2 +- .../core/src/stream_events_utils_tests.rs | 19 +- .../core/src/tasks/ghost_snapshot_tests.rs | 5 +- codex-rs/core/src/tasks/mod_tests.rs | 20 +- codex-rs/core/src/thread_manager_tests.rs | 6 +- .../src/thread_rollout_truncation_tests.rs | 16 +- .../core/src/tools/handlers/js_repl_tests.rs | 2 +- .../core/src/tools/handlers/list_dir_tests.rs | 71 +- codex-rs/core/src/tools/handlers/mod.rs | 10 +- .../src/tools/handlers/multi_agents_tests.rs | 15 +- .../handlers/request_user_input_tests.rs | 29 +- .../core/src/tools/handlers/shell_tests.rs | 46 +- .../src/tools/handlers/unified_exec_tests.rs | 19 +- codex-rs/core/src/tools/js_repl/mod_tests.rs | 45 +- codex-rs/core/src/tools/registry_tests.rs | 2 +- .../src/tools/runtimes/apply_patch_tests.rs | 4 +- .../runtimes/shell/unix_escalation_tests.rs | 21 +- codex-rs/core/src/tools/spec.rs | 8 +- codex-rs/core/src/tools/spec_tests.rs | 330 +++- .../src/unified_exec/async_watcher_tests.rs | 12 +- .../unified_exec/head_tail_buffer_tests.rs | 12 +- codex-rs/core/src/unified_exec/mod_tests.rs | 92 +- .../src/unified_exec/process_manager_tests.rs | 2 +- codex-rs/core/src/util_tests.rs | 16 +- codex-rs/core/src/windows_sandbox_tests.rs | 27 +- codex-rs/core/tests/responses_headers.rs | 48 +- codex-rs/core/tests/suite/agent_jobs.rs | 2 +- codex-rs/core/tests/suite/agent_websocket.rs | 21 +- codex-rs/core/tests/suite/approvals.rs | 65 +- codex-rs/core/tests/suite/auth_refresh.rs | 2 +- codex-rs/core/tests/suite/client.rs | 29 +- .../core/tests/suite/client_websockets.rs | 104 +- codex-rs/core/tests/suite/code_mode.rs | 160 +- codex-rs/core/tests/suite/compact.rs | 115 +- codex-rs/core/tests/suite/compact_remote.rs | 66 +- .../core/tests/suite/compact_resume_fork.rs | 35 +- codex-rs/core/tests/suite/exec.rs | 7 +- codex-rs/core/tests/suite/hooks.rs | 12 +- codex-rs/core/tests/suite/image_rollout.rs | 2 +- codex-rs/core/tests/suite/memories.rs | 21 +- .../core/tests/suite/model_info_overrides.rs | 8 +- codex-rs/core/tests/suite/model_switching.rs | 16 +- codex-rs/core/tests/suite/models_cache_ttl.rs | 16 +- .../core/tests/suite/permissions_messages.rs | 4 +- codex-rs/core/tests/suite/personality.rs | 4 +- .../core/tests/suite/realtime_conversation.rs | 48 +- codex-rs/core/tests/suite/remote_models.rs | 64 +- codex-rs/core/tests/suite/resume_warning.rs | 8 +- codex-rs/core/tests/suite/review.rs | 27 +- codex-rs/core/tests/suite/rmcp_client.rs | 2 +- .../core/tests/suite/rollout_list_find.rs | 11 +- codex-rs/core/tests/suite/seatbelt.rs | 6 +- codex-rs/core/tests/suite/shell_command.rs | 18 +- .../core/tests/suite/shell_serialization.rs | 42 +- .../tests/suite/spawn_agent_description.rs | 2 +- .../tests/suite/subagent_notifications.rs | 16 +- codex-rs/core/tests/suite/tools.rs | 4 +- .../tests/suite/unstable_features_warning.rs | 16 +- codex-rs/core/tests/suite/view_image.rs | 20 +- codex-rs/exec-server/tests/exec_process.rs | 3 +- .../src/event_processor_with_human_output.rs | 29 +- codex-rs/exec/src/lib.rs | 2 +- .../tests/event_processor_with_json_output.rs | 56 +- codex-rs/exec/tests/suite/sandbox.rs | 2 +- .../execpolicy-legacy/src/execv_checker.rs | 5 +- codex-rs/execpolicy-legacy/tests/suite/cp.rs | 10 +- .../execpolicy-legacy/tests/suite/head.rs | 4 +- .../execpolicy-legacy/tests/suite/literal.rs | 8 +- codex-rs/execpolicy-legacy/tests/suite/ls.rs | 24 +- codex-rs/execpolicy-legacy/tests/suite/sed.rs | 10 +- codex-rs/execpolicy/src/amend.rs | 2 +- codex-rs/features/src/tests.rs | 6 +- codex-rs/feedback/src/lib.rs | 14 +- codex-rs/file-search/src/lib.rs | 45 +- codex-rs/git-utils/src/ghost_commits.rs | 7 +- codex-rs/hooks/src/engine/dispatcher.rs | 107 +- codex-rs/hooks/src/events/common.rs | 4 +- codex-rs/hooks/src/events/session_start.rs | 6 +- codex-rs/hooks/src/events/stop.rs | 6 +- .../linux-sandbox/src/linux_run_main_tests.rs | 50 +- codex-rs/login/src/auth/auth_tests.rs | 119 +- .../login/src/auth/default_client_tests.rs | 2 +- .../login/tests/suite/device_code_login.rs | 29 +- codex-rs/mcp-server/src/codex_tool_runner.rs | 6 +- codex-rs/mcp-server/src/outgoing_message.rs | 2 +- codex-rs/mcp-server/tests/suite/codex_tool.rs | 4 +- codex-rs/network-proxy/src/config.rs | 39 +- codex-rs/network-proxy/src/http_proxy.rs | 30 +- codex-rs/network-proxy/src/mitm_tests.rs | 21 +- codex-rs/network-proxy/src/network_policy.rs | 12 +- codex-rs/network-proxy/src/proxy.rs | 18 +- codex-rs/network-proxy/src/runtime.rs | 72 +- codex-rs/network-proxy/src/socks5.rs | 13 +- codex-rs/otel/src/provider.rs | 6 +- codex-rs/otel/src/trace_context.rs | 4 +- codex-rs/otel/tests/suite/manager_metrics.rs | 30 +- .../tests/suite/otel_export_routing_policy.rs | 38 +- .../otel/tests/suite/otlp_http_loopback.rs | 2 +- codex-rs/otel/tests/suite/runtime_summary.rs | 38 +- codex-rs/otel/tests/suite/send.rs | 24 +- codex-rs/otel/tests/suite/snapshot.rs | 8 +- codex-rs/otel/tests/suite/validation.rs | 12 +- codex-rs/protocol/src/items.rs | 2 +- codex-rs/protocol/src/models.rs | 60 +- codex-rs/protocol/src/openai_models.rs | 25 +- codex-rs/protocol/src/permissions.rs | 5 +- codex-rs/protocol/src/protocol.rs | 17 +- codex-rs/rmcp-client/src/auth_status.rs | 32 +- codex-rs/rmcp-client/src/utils.rs | 4 +- .../tests/process_group_cleanup.rs | 2 +- codex-rs/rmcp-client/tests/resources.rs | 8 +- .../tests/streamable_http_recovery.rs | 14 +- codex-rs/rollout/src/metadata_tests.rs | 6 +- codex-rs/rollout/src/recorder_tests.rs | 48 +- codex-rs/rollout/src/tests.rs | 176 ++- codex-rs/sandboxing/src/bwrap_tests.rs | 4 +- codex-rs/sandboxing/src/landlock_tests.rs | 39 +- codex-rs/sandboxing/src/manager_tests.rs | 12 +- .../sandboxing/src/policy_transforms_tests.rs | 21 +- codex-rs/sandboxing/src/seatbelt_tests.rs | 38 +- codex-rs/secrets/src/lib.rs | 2 +- codex-rs/shell-escalation/src/unix/socket.rs | 6 +- codex-rs/state/src/model/thread_metadata.rs | 5 +- codex-rs/state/src/runtime/backfill.rs | 10 +- codex-rs/state/src/runtime/logs.rs | 80 +- codex-rs/state/src/runtime/memories.rs | 459 ++++-- codex-rs/state/src/runtime/threads.rs | 17 +- .../terminal-detection/src/terminal_tests.rs | 222 ++- codex-rs/tui_app_server/src/app.rs | 319 ++-- .../src/app/agent_navigation.rs | 13 +- .../src/app/pending_interactive_replay.rs | 34 +- codex-rs/tui_app_server/src/app_backtrack.rs | 61 +- .../tui_app_server/src/app_server_session.rs | 6 +- .../src/bottom_pane/app_link_view.rs | 12 +- .../src/bottom_pane/approval_overlay.rs | 37 +- .../src/bottom_pane/chat_composer.rs | 1373 +++++++++-------- .../src/bottom_pane/chat_composer_history.rs | 16 +- .../src/bottom_pane/feedback_view.rs | 24 +- .../tui_app_server/src/bottom_pane/footer.rs | 32 +- .../src/bottom_pane/list_selection_view.rs | 43 +- .../src/bottom_pane/mcp_server_elicitation.rs | 99 +- .../tui_app_server/src/bottom_pane/mod.rs | 28 +- .../src/bottom_pane/paste_burst.rs | 8 +- .../src/bottom_pane/pending_input_preview.rs | 4 +- .../bottom_pane/pending_thread_approvals.rs | 6 +- .../src/bottom_pane/request_user_input/mod.rs | 330 ++-- .../src/bottom_pane/selection_popup_common.rs | 2 +- .../src/bottom_pane/skills_toggle_view.rs | 2 +- .../src/bottom_pane/status_line_setup.rs | 2 +- .../src/bottom_pane/textarea.rs | 120 +- .../src/bottom_pane/title_setup.rs | 5 +- .../src/bottom_pane/unified_exec_footer.rs | 2 +- .../tui_app_server/src/chatwidget/tests.rs | 1270 ++++++++------- codex-rs/tui_app_server/src/clipboard_text.rs | 7 +- codex-rs/tui_app_server/src/cwd_prompt.rs | 6 +- codex-rs/tui_app_server/src/debug_config.rs | 12 +- codex-rs/tui_app_server/src/diff_render.rs | 188 ++- .../tui_app_server/src/exec_cell/render.rs | 30 +- codex-rs/tui_app_server/src/history_cell.rs | 217 +-- codex-rs/tui_app_server/src/lib.rs | 14 +- codex-rs/tui_app_server/src/live_wrap.rs | 14 +- .../tui_app_server/src/local_chatgpt_auth.rs | 16 +- codex-rs/tui_app_server/src/markdown.rs | 15 +- .../src/markdown_render_tests.rs | 2 +- .../tui_app_server/src/markdown_stream.rs | 81 +- .../tui_app_server/src/model_migration.rs | 44 +- codex-rs/tui_app_server/src/multi_agents.rs | 16 +- .../tui_app_server/src/onboarding/auth.rs | 2 +- .../src/onboarding/trust_directory.rs | 3 +- .../tui_app_server/src/onboarding/welcome.rs | 18 +- codex-rs/tui_app_server/src/pager_overlay.rs | 45 +- .../tui_app_server/src/render/highlight.rs | 14 +- codex-rs/tui_app_server/src/resume_picker.rs | 118 +- .../tui_app_server/src/status/rate_limits.rs | 4 +- codex-rs/tui_app_server/src/status/tests.rs | 186 +-- .../src/status_indicator_widget.rs | 55 +- .../tui_app_server/src/streaming/chunking.rs | 48 +- .../src/streaming/controller.rs | 9 +- codex-rs/tui_app_server/src/streaming/mod.rs | 4 +- .../tui_app_server/src/text_formatting.rs | 32 +- codex-rs/tui_app_server/src/theme_picker.rs | 29 +- codex-rs/tui_app_server/src/tooltips.rs | 6 +- codex-rs/tui_app_server/src/update_action.rs | 33 +- codex-rs/tui_app_server/src/voice.rs | 5 +- codex-rs/tui_app_server/src/wrapping.rs | 62 +- codex-rs/utils/cache/src/lib.rs | 10 +- codex-rs/utils/cli/src/format_env_display.rs | 7 +- codex-rs/utils/home-dir/src/lib.rs | 3 +- .../utils/path-utils/src/path_utils_tests.rs | 12 +- codex-rs/utils/pty/src/tests.rs | 36 +- codex-rs/utils/sleep-inhibitor/src/lib.rs | 32 +- .../utils/stream-parser/src/assistant_text.rs | 4 +- codex-rs/utils/string/src/truncate/tests.rs | 72 +- tools/argument-comment-lint/README.md | 5 +- .../run-prebuilt-linter.sh | 56 +- tools/argument-comment-lint/run.sh | 56 +- 307 files changed, 7724 insertions(+), 4710 deletions(-) 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[@]}"