mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
Merge d01ecbfa32 into sapling-pr-archive-bolinfest
This commit is contained in:
@@ -42,6 +42,7 @@ use codex_protocol::approvals::ElicitationRequest;
|
||||
use codex_protocol::approvals::ElicitationRequestEvent;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::mcp::RequestId as ProtocolRequestId;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
@@ -646,6 +647,8 @@ pub const MCP_SANDBOX_STATE_META_CAPABILITY: &str = "codex/sandbox-state-meta";
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SandboxState {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub permission_profile: Option<PermissionProfile>,
|
||||
pub sandbox_policy: SandboxPolicy,
|
||||
pub codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
pub sandbox_cwd: PathBuf,
|
||||
|
||||
@@ -691,6 +691,7 @@ async fn run_review_on_session(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: params.model.clone(),
|
||||
effort: params.reasoning_effort,
|
||||
summary: Some(params.reasoning_summary),
|
||||
|
||||
@@ -519,6 +519,7 @@ async fn augment_mcp_tool_request_meta_with_sandbox_state(
|
||||
}
|
||||
|
||||
let sandbox_state = serde_json::to_value(SandboxState {
|
||||
permission_profile: Some(turn_context.permission_profile()),
|
||||
sandbox_policy: turn_context.sandbox_policy.get().clone(),
|
||||
codex_linux_sandbox_exe: turn_context.codex_linux_sandbox_exe.clone(),
|
||||
sandbox_cwd: turn_context.cwd.to_path_buf(),
|
||||
|
||||
@@ -135,6 +135,7 @@ pub(super) async fn user_input_or_turn_inner(
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
@@ -162,7 +163,7 @@ pub(super) async fn user_input_or_turn_inner(
|
||||
approval_policy: Some(approval_policy),
|
||||
approvals_reviewer,
|
||||
sandbox_policy: Some(sandbox_policy),
|
||||
permission_profile: None,
|
||||
permission_profile,
|
||||
windows_sandbox_level: None,
|
||||
collaboration_mode,
|
||||
reasoning_summary: summary,
|
||||
|
||||
@@ -4023,6 +4023,7 @@ async fn user_turn_updates_approvals_reviewer() {
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview),
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
effort: config.model_reasoning_effort,
|
||||
summary: config.model_reasoning_summary,
|
||||
|
||||
@@ -54,8 +54,8 @@ use codex_shell_escalation::EscalationPolicy;
|
||||
use codex_shell_escalation::EscalationSession;
|
||||
use codex_shell_escalation::ExecParams;
|
||||
use codex_shell_escalation::ExecResult;
|
||||
use codex_shell_escalation::Permissions as EscalatedPermissions;
|
||||
use codex_shell_escalation::PreparedExec;
|
||||
use codex_shell_escalation::ResolvedPermissionProfile;
|
||||
use codex_shell_escalation::ShellCommandExecutor;
|
||||
use codex_shell_escalation::Stopwatch;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
@@ -371,13 +371,17 @@ impl CoreShellActionProvider {
|
||||
.map(|_| {
|
||||
// Shell request additional permissions were already normalized and
|
||||
// merged into the first-attempt sandbox policy.
|
||||
EscalationExecution::Permissions(EscalationPermissions::Permissions(
|
||||
EscalatedPermissions {
|
||||
sandbox_policy: sandbox_policy.clone(),
|
||||
file_system_sandbox_policy: file_system_sandbox_policy.clone(),
|
||||
network_sandbox_policy,
|
||||
},
|
||||
))
|
||||
EscalationExecution::Permissions(
|
||||
EscalationPermissions::ResolvedPermissionProfile(
|
||||
ResolvedPermissionProfile {
|
||||
permission_profile: PermissionProfile::from_runtime_permissions(
|
||||
file_system_sandbox_policy,
|
||||
network_sandbox_policy,
|
||||
),
|
||||
sandbox_policy: sandbox_policy.clone(),
|
||||
},
|
||||
),
|
||||
)
|
||||
})
|
||||
.unwrap_or(EscalationExecution::TurnDefault),
|
||||
}
|
||||
@@ -844,9 +848,9 @@ impl ShellCommandExecutor for CoreShellCommandExecutor {
|
||||
additional_permissions: None,
|
||||
})?
|
||||
}
|
||||
EscalationExecution::Permissions(EscalationPermissions::PermissionProfile(
|
||||
permission_profile,
|
||||
)) => {
|
||||
EscalationExecution::Permissions(
|
||||
EscalationPermissions::AdditionalPermissionProfile(permission_profile),
|
||||
) => {
|
||||
// Merge additive permissions into the existing turn/request sandbox policy.
|
||||
self.prepare_sandboxed_exec(PrepareSandboxedExecParams {
|
||||
command,
|
||||
@@ -858,15 +862,19 @@ impl ShellCommandExecutor for CoreShellCommandExecutor {
|
||||
additional_permissions: Some(permission_profile),
|
||||
})?
|
||||
}
|
||||
EscalationExecution::Permissions(EscalationPermissions::Permissions(permissions)) => {
|
||||
// Use a fully specified sandbox policy instead of merging into the turn policy.
|
||||
EscalationExecution::Permissions(EscalationPermissions::ResolvedPermissionProfile(
|
||||
permissions,
|
||||
)) => {
|
||||
// Use a fully specified permission profile instead of merging into the turn policy.
|
||||
let (file_system_sandbox_policy, network_sandbox_policy) =
|
||||
permissions.permission_profile.to_runtime_permissions();
|
||||
self.prepare_sandboxed_exec(PrepareSandboxedExecParams {
|
||||
command,
|
||||
workdir,
|
||||
env,
|
||||
sandbox_policy: &permissions.sandbox_policy,
|
||||
file_system_sandbox_policy: &permissions.file_system_sandbox_policy,
|
||||
network_sandbox_policy: permissions.network_sandbox_policy,
|
||||
file_system_sandbox_policy: &file_system_sandbox_policy,
|
||||
network_sandbox_policy,
|
||||
additional_permissions: None,
|
||||
})?
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ use codex_sandboxing::SandboxType;
|
||||
use codex_shell_escalation::EscalationExecution;
|
||||
use codex_shell_escalation::EscalationPermissions;
|
||||
use codex_shell_escalation::ExecResult;
|
||||
use codex_shell_escalation::Permissions as EscalatedPermissions;
|
||||
use codex_shell_escalation::ResolvedPermissionProfile;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value;
|
||||
@@ -317,11 +317,13 @@ fn shell_request_escalation_execution_is_explicit() {
|
||||
network_sandbox_policy,
|
||||
Some(&requested_permissions),
|
||||
),
|
||||
EscalationExecution::Permissions(EscalationPermissions::Permissions(
|
||||
EscalatedPermissions {
|
||||
EscalationExecution::Permissions(EscalationPermissions::ResolvedPermissionProfile(
|
||||
ResolvedPermissionProfile {
|
||||
permission_profile: PermissionProfile::from_runtime_permissions(
|
||||
&file_system_sandbox_policy,
|
||||
network_sandbox_policy,
|
||||
),
|
||||
sandbox_policy,
|
||||
file_system_sandbox_policy,
|
||||
network_sandbox_policy,
|
||||
},
|
||||
)),
|
||||
);
|
||||
|
||||
@@ -663,6 +663,7 @@ impl TestCodex {
|
||||
approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -367,6 +367,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1005,6 +1006,7 @@ async fn apply_patch_custom_tool_streaming_emits_updated_changes() -> Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1103,6 +1105,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1188,6 +1191,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() ->
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1344,6 +1348,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1412,6 +1417,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1489,6 +1495,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1566,6 +1573,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -593,8 +593,9 @@ async fn submit_turn(
|
||||
final_output_json_schema: None,
|
||||
cwd: test.cwd.path().to_path_buf(),
|
||||
approval_policy,
|
||||
approvals_reviewer: None,
|
||||
approvals_reviewer: Some(ApprovalsReviewer::User),
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -1660,6 +1660,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: Some(ReasoningEffort::Low),
|
||||
summary: Some(
|
||||
@@ -1781,6 +1782,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: session_configured.model,
|
||||
effort: None,
|
||||
summary: Some(ReasoningSummary::Concise),
|
||||
|
||||
@@ -2619,6 +2619,7 @@ text(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -186,6 +186,7 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: test.config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: Some(
|
||||
@@ -307,6 +308,7 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: test.config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: Some(
|
||||
|
||||
@@ -1687,6 +1687,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: resumed.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1779,6 +1780,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: previous_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1805,6 +1807,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: next_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1917,6 +1920,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: previous_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1967,6 +1971,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: next_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -3204,6 +3209,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: previous_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -3230,6 +3236,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: next_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -54,6 +54,7 @@ async fn submit_user_turn(
|
||||
approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -136,6 +137,7 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -126,6 +126,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -214,6 +215,7 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -540,6 +540,7 @@ async fn plan_mode_emits_plan_item_from_proposed_plan_block() -> anyhow::Result<
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -618,6 +619,7 @@ async fn plan_mode_strips_plan_from_agent_messages() -> anyhow::Result<()> {
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -728,6 +730,7 @@ async fn plan_mode_streaming_citations_are_stripped_across_added_deltas_and_done
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -916,6 +919,7 @@ async fn plan_mode_streaming_proposed_plan_tag_split_across_added_and_delta_is_p
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1031,6 +1035,7 @@ async fn plan_mode_handles_missing_plan_close_tag() -> anyhow::Result<()> {
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -83,6 +83,7 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -64,6 +64,7 @@ async fn submit_skill_turn(test: &TestCodex, skill_path: PathBuf, prompt: &str)
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -131,6 +131,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -170,6 +171,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: next_model.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -231,6 +233,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -270,6 +273,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: next_model.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -413,6 +417,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result<
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -435,6 +440,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result<
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: text_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -544,6 +550,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -566,6 +573,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -678,6 +686,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -700,6 +709,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: text_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -814,6 +824,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history()
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -844,6 +855,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history()
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: image_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
service_tier: None,
|
||||
@@ -1002,6 +1014,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: large_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -1063,6 +1076,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: smaller_model_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
|
||||
@@ -124,6 +124,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -149,6 +150,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
|
||||
approval_policy: AskForApproval::OnRequest,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -229,6 +231,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -254,6 +257,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -367,6 +371,7 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: resumed.session_configured.model.clone(),
|
||||
effort: resumed.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
|
||||
@@ -100,6 +100,7 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> {
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -111,6 +111,7 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -1146,7 +1146,11 @@ async fn handle_container_exec_user_approved_records_tool_decision() {
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("user_approved_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"user_approved_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
@@ -1215,7 +1219,11 @@ async fn handle_container_exec_user_approved_for_session_records_tool_decision()
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("user_approved_session_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"user_approved_session_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
@@ -1283,7 +1291,11 @@ async fn handle_sandbox_error_user_approves_retry_records_tool_decision() {
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("sandbox_retry_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"sandbox_retry_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
@@ -1351,7 +1363,11 @@ async fn handle_container_exec_user_denies_records_tool_decision() {
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("user_denied_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"user_denied_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
@@ -1419,7 +1435,11 @@ async fn handle_sandbox_error_user_approves_for_session_records_tool_decision()
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("sandbox_session_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"sandbox_session_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
@@ -1487,7 +1507,11 @@ async fn handle_sandbox_error_user_denies_records_tool_decision() {
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_local_shell_call("sandbox_deny_call", "completed", vec!["/bin/date"]),
|
||||
ev_local_shell_call(
|
||||
"sandbox_deny_call",
|
||||
"completed",
|
||||
vec!["/usr/bin/touch", "codex-otel-approval-test"],
|
||||
),
|
||||
ev_completed("done"),
|
||||
]),
|
||||
)
|
||||
|
||||
@@ -120,6 +120,7 @@ async fn submit_danger_full_access_user_turn(test: &TestCodex, text: &str) {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use codex_core::ForkSnapshot;
|
||||
use codex_core::config::Constrained;
|
||||
use codex_core::config_loader::ConfigLayerStack;
|
||||
use codex_core::context::ContextualUserFragment;
|
||||
use codex_core::context::PermissionsInstructions;
|
||||
use codex_core::load_exec_policy;
|
||||
@@ -551,6 +552,7 @@ async fn permissions_message_includes_writable_roots() -> Result<()> {
|
||||
let mut builder = test_codex().with_config(move |config| {
|
||||
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest);
|
||||
config.permissions.sandbox_policy = Constrained::allow_any(sandbox_policy_for_config);
|
||||
config.config_layer_stack = ConfigLayerStack::default();
|
||||
});
|
||||
let test = builder.build(&server).await?;
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ async fn user_turn_personality_none_does_not_add_update_message() -> anyhow::Res
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -158,6 +159,7 @@ async fn config_personality_some_sets_instructions_template() -> anyhow::Result<
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -217,6 +219,7 @@ async fn config_personality_none_sends_no_personality() -> anyhow::Result<()> {
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -282,6 +285,7 @@ async fn default_personality_is_pragmatic_without_config_toml() -> anyhow::Resul
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -335,6 +339,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()>
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -375,6 +380,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()>
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -443,6 +449,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -483,6 +490,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -564,6 +572,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()>
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -604,6 +613,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()>
|
||||
approval_policy: test.config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -724,6 +734,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: remote_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -846,6 +857,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: remote_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -886,6 +898,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: remote_slug.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
|
||||
@@ -728,6 +728,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: new_policy.clone(),
|
||||
permission_profile: None,
|
||||
model: "o3".to_string(),
|
||||
effort: Some(ReasoningEffort::High),
|
||||
summary: Some(ReasoningSummary::Detailed),
|
||||
@@ -842,6 +843,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
|
||||
approval_policy: default_approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: default_sandbox_policy.clone(),
|
||||
permission_profile: None,
|
||||
model: default_model.clone(),
|
||||
effort: default_effort,
|
||||
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||
@@ -864,6 +866,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
|
||||
approval_policy: default_approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: default_sandbox_policy.clone(),
|
||||
permission_profile: None,
|
||||
model: default_model.clone(),
|
||||
effort: default_effort,
|
||||
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||
@@ -970,6 +973,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
approval_policy: default_approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: default_sandbox_policy.clone(),
|
||||
permission_profile: None,
|
||||
model: default_model,
|
||||
effort: default_effort,
|
||||
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||
@@ -992,6 +996,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: "o3".to_string(),
|
||||
effort: Some(ReasoningEffort::High),
|
||||
summary: Some(ReasoningSummary::Detailed),
|
||||
|
||||
@@ -171,6 +171,7 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
permission_profile: None,
|
||||
personality: None,
|
||||
environments: None,
|
||||
})
|
||||
@@ -248,6 +249,7 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
permission_profile: None,
|
||||
personality: None,
|
||||
environments: None,
|
||||
})
|
||||
@@ -324,6 +326,7 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
permission_profile: None,
|
||||
personality: None,
|
||||
environments: None,
|
||||
})
|
||||
@@ -408,6 +411,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<(
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: requested_model.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -468,6 +472,7 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning()
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile: None,
|
||||
model: requested_model.to_string(),
|
||||
effort: None,
|
||||
summary: Some(
|
||||
@@ -636,6 +641,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: REMOTE_MODEL_SLUG.to_string(),
|
||||
effort: None,
|
||||
summary: Some(ReasoningSummary::Auto),
|
||||
@@ -863,6 +869,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: model.to_string(),
|
||||
effort: None,
|
||||
summary: Some(ReasoningSummary::Auto),
|
||||
|
||||
@@ -197,6 +197,7 @@ async fn submit_turn(
|
||||
approval_policy,
|
||||
approvals_reviewer: Some(ApprovalsReviewer::User),
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -150,6 +150,7 @@ async fn submit_turn(
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -141,6 +141,7 @@ async fn request_user_input_round_trip_for_mode(mode: ModeKind) -> anyhow::Resul
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -260,6 +261,7 @@ where
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -143,6 +143,7 @@ async fn submit_turn_with_timeout(test: &TestCodex, prompt: &str) -> Result<()>
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
},
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -290,6 +290,7 @@ async fn call_cwd_tool(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -424,6 +425,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -856,6 +858,7 @@ async fn stdio_mcp_parallel_tool_calls_default_false_runs_serially() -> anyhow::
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -989,6 +992,7 @@ async fn stdio_mcp_parallel_tool_calls_opt_in_runs_concurrently() -> anyhow::Res
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1089,6 +1093,7 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1241,6 +1246,7 @@ async fn stdio_image_responses_preserve_original_detail_metadata() -> anyhow::Re
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1479,6 +1485,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: text_only_model_slug.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1588,6 +1595,7 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1725,6 +1733,7 @@ async fn stdio_server_propagates_explicit_local_env_var_source() -> anyhow::Resu
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1835,6 +1844,7 @@ async fn remote_stdio_env_var_source_does_not_copy_local_env() -> anyhow::Result
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1960,6 +1970,7 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -2177,6 +2188,7 @@ async fn streamable_http_with_oauth_round_trip_impl() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -56,6 +56,7 @@ async fn openai_model_header_mismatch_emits_warning_event_and_warning_item() ->
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: REQUESTED_MODEL.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -207,6 +208,7 @@ async fn response_model_field_mismatch_emits_warning_when_header_matches_request
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: REQUESTED_MODEL.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -294,6 +296,7 @@ async fn openai_model_header_mismatch_only_emits_one_warning_per_turn() -> Resul
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: REQUESTED_MODEL.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
@@ -345,6 +348,7 @@ async fn openai_model_header_casing_only_mismatch_does_not_warn() -> Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: REQUESTED_MODEL.to_string(),
|
||||
effort: test.config.model_reasoning_effort,
|
||||
summary: None,
|
||||
|
||||
@@ -167,6 +167,7 @@ async fn run_snapshot_command_with_options(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -259,6 +260,7 @@ async fn run_shell_command_snapshot_with_options(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -331,6 +333,7 @@ async fn run_tool_turn_on_harness(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -567,6 +570,7 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -54,6 +54,7 @@ async fn submit_turn_with_policies(
|
||||
approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -115,6 +115,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -409,6 +409,7 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result<
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -88,6 +88,7 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -160,6 +161,7 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -242,6 +244,7 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -339,6 +342,7 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<()
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -444,6 +448,7 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -45,6 +45,7 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -363,6 +364,7 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -510,6 +510,7 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -176,6 +176,7 @@ async fn submit_unified_exec_turn(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -261,6 +262,7 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1752,6 +1754,7 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1846,6 +1849,7 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -2320,6 +2324,7 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> {
|
||||
approvals_reviewer: None,
|
||||
// Important!
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -2429,6 +2434,7 @@ async fn unified_exec_enforces_glob_deny_read_policy() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: read_only_policy,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -2558,6 +2564,7 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -180,6 +180,7 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: fixture.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -169,6 +169,7 @@ async fn assert_user_turn_local_image_resizes_to(
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -290,6 +291,7 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -422,6 +424,7 @@ async fn view_image_tool_can_preserve_original_resolution_when_requested_on_gpt5
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -522,6 +525,7 @@ async fn view_image_tool_errors_clearly_for_unsupported_detail_values() -> anyho
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -613,6 +617,7 @@ async fn view_image_tool_treats_null_detail_as_omitted() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -714,6 +719,7 @@ async fn view_image_tool_resizes_when_model_lacks_original_detail_support() -> a
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -819,6 +825,7 @@ async fn view_image_tool_does_not_force_original_resolution_with_capability_only
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -922,6 +929,7 @@ await codex.emitImage(out);
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1043,6 +1051,7 @@ console.log(out.type);
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
service_tier: None,
|
||||
@@ -1137,6 +1146,7 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1219,6 +1229,7 @@ async fn view_image_tool_errors_for_non_image_files() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1306,6 +1317,7 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1444,6 +1456,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: model_slug.to_string(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
@@ -1525,6 +1538,7 @@ async fn replaces_invalid_local_image_after_bad_request() -> anyhow::Result<()>
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -160,6 +160,7 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::mcp::RequestId;
|
||||
use crate::models::PermissionProfile;
|
||||
use crate::parse_command::ParsedCommand;
|
||||
use crate::permissions::FileSystemSandboxPolicy;
|
||||
use crate::permissions::NetworkSandboxPolicy;
|
||||
use crate::protocol::FileChange;
|
||||
use crate::protocol::ReviewDecision;
|
||||
use crate::protocol::SandboxPolicy;
|
||||
@@ -16,18 +14,23 @@ use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use ts_rs::TS;
|
||||
|
||||
/// Fully resolved permissions for rerunning an intercepted child process.
|
||||
///
|
||||
/// `permission_profile` is the canonical permission model. `sandbox_policy`
|
||||
/// remains as the legacy adapter for sandbox backends that still require it.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Permissions {
|
||||
pub struct ResolvedPermissionProfile {
|
||||
pub permission_profile: PermissionProfile,
|
||||
pub sandbox_policy: SandboxPolicy,
|
||||
pub file_system_sandbox_policy: FileSystemSandboxPolicy,
|
||||
pub network_sandbox_policy: NetworkSandboxPolicy,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EscalationPermissions {
|
||||
PermissionProfile(PermissionProfile),
|
||||
Permissions(Permissions),
|
||||
/// Permissions to merge with the active turn permissions.
|
||||
AdditionalPermissionProfile(PermissionProfile),
|
||||
/// Fully resolved permissions that should replace the active turn permissions.
|
||||
ResolvedPermissionProfile(ResolvedPermissionProfile),
|
||||
}
|
||||
|
||||
/// Proposed execpolicy change to allow commands starting with this prefix.
|
||||
|
||||
@@ -537,6 +537,13 @@ pub enum Op {
|
||||
/// Policy to use for tool calls such as `local_shell`.
|
||||
sandbox_policy: SandboxPolicy,
|
||||
|
||||
/// Full permissions profile to use for tool calls such as `local_shell`.
|
||||
///
|
||||
/// When omitted, `sandbox_policy` is used as a legacy compatibility
|
||||
/// projection.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
|
||||
/// Must be a valid model slug for the configured client session
|
||||
/// associated with this conversation.
|
||||
model: String,
|
||||
|
||||
@@ -22,10 +22,10 @@ pub use unix::ExecParams;
|
||||
#[cfg(unix)]
|
||||
pub use unix::ExecResult;
|
||||
#[cfg(unix)]
|
||||
pub use unix::Permissions;
|
||||
#[cfg(unix)]
|
||||
pub use unix::PreparedExec;
|
||||
#[cfg(unix)]
|
||||
pub use unix::ResolvedPermissionProfile;
|
||||
#[cfg(unix)]
|
||||
pub use unix::ShellCommandExecutor;
|
||||
#[cfg(unix)]
|
||||
pub use unix::Stopwatch;
|
||||
|
||||
@@ -922,7 +922,7 @@ mod tests {
|
||||
server,
|
||||
Arc::new(DeterministicEscalationPolicy {
|
||||
decision: EscalationDecision::escalate(EscalationExecution::Permissions(
|
||||
EscalationPermissions::PermissionProfile(PermissionProfile {
|
||||
EscalationPermissions::AdditionalPermissionProfile(PermissionProfile {
|
||||
network: Some(NetworkPermissions {
|
||||
enabled: Some(true),
|
||||
}),
|
||||
@@ -931,12 +931,14 @@ mod tests {
|
||||
)),
|
||||
}),
|
||||
Arc::new(PermissionAssertingShellCommandExecutor {
|
||||
expected_permissions: EscalationPermissions::PermissionProfile(PermissionProfile {
|
||||
network: Some(NetworkPermissions {
|
||||
enabled: Some(true),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
expected_permissions: EscalationPermissions::AdditionalPermissionProfile(
|
||||
PermissionProfile {
|
||||
network: Some(NetworkPermissions {
|
||||
enabled: Some(true),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
}),
|
||||
CancellationToken::new(),
|
||||
CancellationToken::new(),
|
||||
|
||||
@@ -76,4 +76,4 @@ pub use self::escalation_policy::EscalationPolicy;
|
||||
pub use self::execve_wrapper::main_execve_wrapper;
|
||||
pub use self::stopwatch::Stopwatch;
|
||||
pub use codex_protocol::approvals::EscalationPermissions;
|
||||
pub use codex_protocol::approvals::Permissions;
|
||||
pub use codex_protocol::approvals::ResolvedPermissionProfile;
|
||||
|
||||
@@ -139,6 +139,28 @@ pub(super) fn target_preset_for_upgrade<'a>(
|
||||
.find(|preset| preset.model == target_model && preset.show_in_picker)
|
||||
}
|
||||
|
||||
pub(super) fn apply_accepted_model_migration(
|
||||
config: &mut Config,
|
||||
app_event_tx: &AppEventSender,
|
||||
from_model: String,
|
||||
target_model: String,
|
||||
target_default_effort: ReasoningEffortConfig,
|
||||
) {
|
||||
app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged {
|
||||
from_model,
|
||||
to_model: target_model.clone(),
|
||||
});
|
||||
|
||||
config.model = Some(target_model.clone());
|
||||
config.model_reasoning_effort = Some(target_default_effort);
|
||||
app_event_tx.send(AppEvent::UpdateModel(target_model.clone()));
|
||||
app_event_tx.send(AppEvent::UpdateReasoningEffort(Some(target_default_effort)));
|
||||
app_event_tx.send(AppEvent::PersistModelSelection {
|
||||
model: target_model,
|
||||
effort: Some(target_default_effort),
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) const MODEL_AVAILABILITY_NUX_MAX_SHOW_COUNT: u32 = 4;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -218,7 +240,7 @@ pub(super) async fn handle_model_migration_prompt_if_needed(
|
||||
|
||||
if let Some(ModelUpgrade {
|
||||
id: target_model,
|
||||
reasoning_effort_mapping,
|
||||
reasoning_effort_mapping: _,
|
||||
migration_config_key,
|
||||
model_link,
|
||||
upgrade_copy,
|
||||
@@ -263,30 +285,13 @@ pub(super) async fn handle_model_migration_prompt_if_needed(
|
||||
);
|
||||
match run_model_migration_prompt(tui, prompt_copy).await {
|
||||
ModelMigrationOutcome::Accepted => {
|
||||
app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged {
|
||||
from_model: model.to_string(),
|
||||
to_model: target_model.clone(),
|
||||
});
|
||||
|
||||
let mapped_effort = if let Some(reasoning_effort_mapping) = reasoning_effort_mapping
|
||||
&& let Some(reasoning_effort) = config.model_reasoning_effort
|
||||
{
|
||||
reasoning_effort_mapping
|
||||
.get(&reasoning_effort)
|
||||
.cloned()
|
||||
.or(config.model_reasoning_effort)
|
||||
} else {
|
||||
config.model_reasoning_effort
|
||||
};
|
||||
|
||||
config.model = Some(target_model.clone());
|
||||
config.model_reasoning_effort = mapped_effort;
|
||||
app_event_tx.send(AppEvent::UpdateModel(target_model.clone()));
|
||||
app_event_tx.send(AppEvent::UpdateReasoningEffort(mapped_effort));
|
||||
app_event_tx.send(AppEvent::PersistModelSelection {
|
||||
model: target_model.clone(),
|
||||
effort: mapped_effort,
|
||||
});
|
||||
apply_accepted_model_migration(
|
||||
config,
|
||||
app_event_tx,
|
||||
model.to_string(),
|
||||
target_model.clone(),
|
||||
target_preset.default_reasoning_effort,
|
||||
);
|
||||
}
|
||||
ModelMigrationOutcome::Rejected => {
|
||||
app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use super::*;
|
||||
use assert_matches::assert_matches;
|
||||
use codex_config::types::ModelAvailabilityNuxConfig;
|
||||
use codex_protocol::openai_models::ModelAvailabilityNux;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::sync::mpsc::unbounded_channel;
|
||||
|
||||
fn all_model_presets() -> Vec<ModelPreset> {
|
||||
crate::legacy_core::test_support::all_model_presets().clone()
|
||||
@@ -172,6 +174,61 @@ fn select_model_availability_nux_returns_none_when_all_models_are_exhausted() {
|
||||
assert_eq!(selected, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn accepted_model_migration_persists_target_default_reasoning_effort() {
|
||||
let codex_home = tempdir().expect("temp codex home");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("config");
|
||||
config.model = Some("gpt-5.2".to_string());
|
||||
config.model_reasoning_effort = Some(ReasoningEffortConfig::XHigh);
|
||||
|
||||
let (tx_raw, mut rx) = unbounded_channel();
|
||||
let app_event_tx = AppEventSender::new(tx_raw);
|
||||
|
||||
apply_accepted_model_migration(
|
||||
&mut config,
|
||||
&app_event_tx,
|
||||
"gpt-5.2".to_string(),
|
||||
"gpt-5.4".to_string(),
|
||||
ReasoningEffortConfig::Medium,
|
||||
);
|
||||
|
||||
assert_eq!(config.model.as_deref(), Some("gpt-5.4"));
|
||||
assert_eq!(
|
||||
config.model_reasoning_effort,
|
||||
Some(ReasoningEffortConfig::Medium)
|
||||
);
|
||||
|
||||
let acknowledged = rx.try_recv().expect("acknowledged event");
|
||||
assert_matches!(
|
||||
acknowledged,
|
||||
AppEvent::PersistModelMigrationPromptAcknowledged { from_model, to_model }
|
||||
if from_model == "gpt-5.2" && to_model == "gpt-5.4"
|
||||
);
|
||||
|
||||
let update_model = rx.try_recv().expect("update model event");
|
||||
assert_matches!(
|
||||
update_model,
|
||||
AppEvent::UpdateModel(model) if model == "gpt-5.4"
|
||||
);
|
||||
|
||||
let update_effort = rx.try_recv().expect("update effort event");
|
||||
assert_matches!(
|
||||
update_effort,
|
||||
AppEvent::UpdateReasoningEffort(Some(ReasoningEffortConfig::Medium))
|
||||
);
|
||||
|
||||
let persist_selection = rx.try_recv().expect("persist model selection event");
|
||||
assert_matches!(
|
||||
persist_selection,
|
||||
AppEvent::PersistModelSelection { model, effort }
|
||||
if model == "gpt-5.4" && effort == Some(ReasoningEffortConfig::Medium)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn model_migration_prompt_respects_hide_flag_and_self_target() {
|
||||
let mut seen = BTreeMap::new();
|
||||
|
||||
@@ -497,6 +497,7 @@ impl App {
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
@@ -580,6 +581,7 @@ impl App {
|
||||
approvals_reviewer
|
||||
.unwrap_or(self.chat_widget.config_ref().approvals_reviewer),
|
||||
sandbox_policy.clone(),
|
||||
permission_profile.clone(),
|
||||
model.to_string(),
|
||||
effort,
|
||||
*summary,
|
||||
|
||||
@@ -8,6 +8,7 @@ use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::mcp::RequestId as McpRequestId;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::ConversationAudioParams;
|
||||
@@ -44,6 +45,7 @@ pub(crate) enum AppCommandView<'a> {
|
||||
approval_policy: AskForApproval,
|
||||
approvals_reviewer: &'a Option<ApprovalsReviewer>,
|
||||
sandbox_policy: &'a SandboxPolicy,
|
||||
permission_profile: &'a Option<PermissionProfile>,
|
||||
model: &'a str,
|
||||
effort: Option<ReasoningEffortConfig>,
|
||||
summary: &'a Option<ReasoningSummaryConfig>,
|
||||
@@ -140,6 +142,7 @@ impl AppCommand {
|
||||
cwd: PathBuf,
|
||||
approval_policy: AskForApproval,
|
||||
sandbox_policy: SandboxPolicy,
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
model: String,
|
||||
effort: Option<ReasoningEffortConfig>,
|
||||
summary: Option<ReasoningSummaryConfig>,
|
||||
@@ -155,6 +158,7 @@ impl AppCommand {
|
||||
approval_policy,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
@@ -291,6 +295,7 @@ impl AppCommand {
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
@@ -305,6 +310,7 @@ impl AppCommand {
|
||||
approval_policy: *approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
model,
|
||||
effort: *effort,
|
||||
summary,
|
||||
|
||||
@@ -526,6 +526,7 @@ impl AppServerSession {
|
||||
approval_policy: AskForApproval,
|
||||
approvals_reviewer: codex_protocol::config_types::ApprovalsReviewer,
|
||||
sandbox_policy: SandboxPolicy,
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
model: String,
|
||||
effort: Option<codex_protocol::openai_models::ReasoningEffort>,
|
||||
summary: Option<codex_protocol::config_types::ReasoningSummary>,
|
||||
@@ -535,12 +536,15 @@ impl AppServerSession {
|
||||
output_schema: Option<serde_json::Value>,
|
||||
) -> Result<TurnStartResponse> {
|
||||
let request_id = self.next_request_id();
|
||||
let sandbox_policy = if self.is_remote()
|
||||
|| matches!(sandbox_policy, SandboxPolicy::ExternalSandbox { .. })
|
||||
{
|
||||
Some(sandbox_policy.into())
|
||||
let is_external_sandbox = matches!(&sandbox_policy, SandboxPolicy::ExternalSandbox { .. });
|
||||
let should_send_permission_profile =
|
||||
!self.is_remote() && !is_external_sandbox && permission_profile.is_some();
|
||||
let (sandbox_policy, permission_profile) = if should_send_permission_profile {
|
||||
(None, permission_profile.map(Into::into))
|
||||
} else if self.is_remote() || is_external_sandbox {
|
||||
(Some(sandbox_policy.into()), None)
|
||||
} else {
|
||||
None
|
||||
(None, None)
|
||||
};
|
||||
self.client
|
||||
.request_typed(ClientRequest::TurnStart {
|
||||
@@ -553,11 +557,8 @@ impl AppServerSession {
|
||||
cwd: Some(cwd),
|
||||
approval_policy: Some(approval_policy.into()),
|
||||
approvals_reviewer: Some(approvals_reviewer.into()),
|
||||
// Embedded sessions already installed their full profile
|
||||
// at thread start/resume/fork. Avoid sending a lossy
|
||||
// legacy projection until user turns carry profiles.
|
||||
sandbox_policy,
|
||||
permission_profile: None,
|
||||
permission_profile,
|
||||
model: Some(model),
|
||||
service_tier,
|
||||
effort,
|
||||
|
||||
@@ -6008,11 +6008,20 @@ impl ChatWidget {
|
||||
None if self.config.notices.fast_default_opt_out == Some(true) => Some(None),
|
||||
None => None,
|
||||
};
|
||||
let permission_profile = if matches!(
|
||||
self.config.permissions.sandbox_policy.get(),
|
||||
SandboxPolicy::ExternalSandbox { .. }
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(self.config.permissions.permission_profile())
|
||||
};
|
||||
let op = AppCommand::user_turn(
|
||||
items,
|
||||
self.config.cwd.to_path_buf(),
|
||||
self.config.permissions.approval_policy.value(),
|
||||
self.config.permissions.sandbox_policy.get().clone(),
|
||||
permission_profile,
|
||||
effective_mode.model().to_string(),
|
||||
effective_mode.reasoning_effort(),
|
||||
/*summary*/ None,
|
||||
|
||||
@@ -86,6 +86,75 @@ async fn submission_preserves_text_elements_and_local_images() {
|
||||
assert!(stored_remote_image_urls.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn submission_includes_configured_permission_profile() {
|
||||
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 expected_permission_profile = PermissionProfile {
|
||||
network: Some(NetworkPermissions {
|
||||
enabled: Some(false),
|
||||
}),
|
||||
file_system: Some(FileSystemPermissions {
|
||||
entries: vec![
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::GlobPattern {
|
||||
pattern: "/home/user/project/secrets/**".to_string(),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::None,
|
||||
},
|
||||
],
|
||||
glob_scan_max_depth: None,
|
||||
}),
|
||||
};
|
||||
let configured = codex_protocol::protocol::SessionConfiguredEvent {
|
||||
session_id: conversation_id,
|
||||
forked_from_id: None,
|
||||
thread_name: None,
|
||||
model: "test-model".to_string(),
|
||||
model_provider_id: "test-provider".to_string(),
|
||||
service_tier: None,
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: Some(expected_permission_profile.clone()),
|
||||
cwd: test_path_buf("/home/user/project").abs(),
|
||||
reasoning_effort: Some(ReasoningEffortConfig::default()),
|
||||
history_log_id: 0,
|
||||
history_entry_count: 0,
|
||||
initial_messages: None,
|
||||
network_proxy: None,
|
||||
rollout_path: Some(rollout_file.path().to_path_buf()),
|
||||
};
|
||||
chat.handle_codex_event(Event {
|
||||
id: "initial".into(),
|
||||
msg: EventMsg::SessionConfigured(configured),
|
||||
});
|
||||
drain_insert_history(&mut rx);
|
||||
|
||||
chat.bottom_pane.set_composer_text(
|
||||
"submit with configured permissions".to_string(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
);
|
||||
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
|
||||
|
||||
let permission_profile = match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
permission_profile, ..
|
||||
} => permission_profile,
|
||||
other => panic!("expected Op::UserTurn, got {other:?}"),
|
||||
};
|
||||
assert_eq!(permission_profile, Some(expected_permission_profile));
|
||||
}
|
||||
|
||||
#[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(/*model_override*/ None).await;
|
||||
|
||||
Reference in New Issue
Block a user