mirror of
https://github.com/openai/codex.git
synced 2026-05-16 17:23:57 +00:00
Compare commits
5 Commits
split-mcp-
...
rreichel3/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d54804a8d | ||
|
|
3c4e07849d | ||
|
|
87c4b64da9 | ||
|
|
e808f90724 | ||
|
|
bb728b0693 |
@@ -380,6 +380,9 @@
|
||||
"enable_request_compression": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enhanced_exec_policy_suggestions": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"exec_permission_approvals": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -1986,6 +1989,9 @@
|
||||
"enable_request_compression": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enhanced_exec_policy_suggestions": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"exec_permission_approvals": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
@@ -223,9 +223,33 @@ impl ExecPolicyManager {
|
||||
self.policy.load_full()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn create_exec_approval_requirement_for_command(
|
||||
&self,
|
||||
req: ExecApprovalRequest<'_>,
|
||||
) -> ExecApprovalRequirement {
|
||||
self.create_exec_approval_requirement_for_command_impl(
|
||||
req, /*enhanced_exec_policy_suggestions*/ false,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn create_exec_approval_requirement_for_command_with_enhanced_suggestions(
|
||||
&self,
|
||||
req: ExecApprovalRequest<'_>,
|
||||
enhanced_exec_policy_suggestions: bool,
|
||||
) -> ExecApprovalRequirement {
|
||||
self.create_exec_approval_requirement_for_command_impl(
|
||||
req,
|
||||
enhanced_exec_policy_suggestions,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn create_exec_approval_requirement_for_command_impl(
|
||||
&self,
|
||||
req: ExecApprovalRequest<'_>,
|
||||
enhanced_exec_policy_suggestions: bool,
|
||||
) -> ExecApprovalRequirement {
|
||||
let ExecApprovalRequest {
|
||||
command,
|
||||
@@ -287,6 +311,8 @@ impl ExecPolicyManager {
|
||||
if auto_amendment_allowed {
|
||||
try_derive_execpolicy_amendment_for_prompt_rules(
|
||||
&evaluation.matched_rules,
|
||||
&commands,
|
||||
enhanced_exec_policy_suggestions,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@@ -301,7 +327,11 @@ impl ExecPolicyManager {
|
||||
is_policy_match(rule_match) && rule_match.decision() == Decision::Allow
|
||||
}),
|
||||
proposed_execpolicy_amendment: if auto_amendment_allowed {
|
||||
try_derive_execpolicy_amendment_for_allow_rules(&evaluation.matched_rules)
|
||||
try_derive_execpolicy_amendment_for_allow_rules(
|
||||
&evaluation.matched_rules,
|
||||
&commands,
|
||||
enhanced_exec_policy_suggestions,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
@@ -640,12 +670,15 @@ fn commands_for_exec_policy(command: &[String]) -> (Vec<Vec<String>>, bool) {
|
||||
/// - Examples:
|
||||
/// - execpolicy: empty. Command: `["python"]`. Heuristics prompt -> `Some(vec!["python"])`.
|
||||
/// - execpolicy: empty. Command: `["bash", "-c", "cd /some/folder && prog1 --option1 arg1 && prog2 --option2 arg2"]`.
|
||||
/// Parsed commands include `cd /some/folder`, `prog1 --option1 arg1`, and `prog2 --option2 arg2`. If heuristics allow `cd` but prompt
|
||||
/// on `prog1`, we return `Some(vec!["prog1", "--option1", "arg1"])`.
|
||||
/// Parsed commands include `cd /some/folder`, `prog1 --option1 arg1`, and `prog2 --option2 arg2`. In enhanced mode for
|
||||
/// multi-command scripts, we derive the suggestion from the first parsed segment, so this returns
|
||||
/// `Some(vec!["cd", "/some/folder"])`.
|
||||
/// - execpolicy: contains a `prompt for prefix ["prog2"]` rule. For the same command as above,
|
||||
/// we return `None` because an execpolicy prompt still applies even if we amend execpolicy to allow ["prog1", "--option1", "arg1"].
|
||||
/// we return `None` because an execpolicy prompt still applies even if we amend execpolicy to allow ["cd", "/some/folder"].
|
||||
fn try_derive_execpolicy_amendment_for_prompt_rules(
|
||||
matched_rules: &[RuleMatch],
|
||||
commands: &[Vec<String>],
|
||||
enhanced_exec_policy_suggestions: bool,
|
||||
) -> Option<ExecPolicyAmendment> {
|
||||
if matched_rules
|
||||
.iter()
|
||||
@@ -654,13 +687,23 @@ fn try_derive_execpolicy_amendment_for_prompt_rules(
|
||||
return None;
|
||||
}
|
||||
|
||||
if enhanced_exec_policy_suggestions && commands.len() > 1 {
|
||||
return auto_derived_execpolicy_amendment_for_mode(
|
||||
&commands[0],
|
||||
/*enhanced_exec_policy_suggestions*/ true,
|
||||
);
|
||||
}
|
||||
|
||||
matched_rules
|
||||
.iter()
|
||||
.find_map(|rule_match| match rule_match {
|
||||
RuleMatch::HeuristicsRuleMatch {
|
||||
command,
|
||||
decision: Decision::Prompt,
|
||||
} => Some(ExecPolicyAmendment::from(command.clone())),
|
||||
} => auto_derived_execpolicy_amendment_for_mode(
|
||||
command,
|
||||
enhanced_exec_policy_suggestions,
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
@@ -670,22 +713,65 @@ fn try_derive_execpolicy_amendment_for_prompt_rules(
|
||||
/// - If any execpolicy rule matches, return None, because we would already be running command outside the sandbox
|
||||
fn try_derive_execpolicy_amendment_for_allow_rules(
|
||||
matched_rules: &[RuleMatch],
|
||||
commands: &[Vec<String>],
|
||||
enhanced_exec_policy_suggestions: bool,
|
||||
) -> Option<ExecPolicyAmendment> {
|
||||
if matched_rules.iter().any(is_policy_match) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if enhanced_exec_policy_suggestions && commands.len() > 1 {
|
||||
return auto_derived_execpolicy_amendment_for_mode(
|
||||
&commands[0],
|
||||
/*enhanced_exec_policy_suggestions*/ true,
|
||||
);
|
||||
}
|
||||
|
||||
matched_rules
|
||||
.iter()
|
||||
.find_map(|rule_match| match rule_match {
|
||||
RuleMatch::HeuristicsRuleMatch {
|
||||
command,
|
||||
decision: Decision::Allow,
|
||||
} => Some(ExecPolicyAmendment::from(command.clone())),
|
||||
} => auto_derived_execpolicy_amendment_for_mode(
|
||||
command,
|
||||
enhanced_exec_policy_suggestions,
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// In enhanced mode, keep generated execpolicy suggestions broad enough to
|
||||
/// cover similar invocations, but stop before the first flag so we do not bake
|
||||
/// incidental option values into a persisted allow rule.
|
||||
///
|
||||
/// If truncating before the first flag would leave fewer than two tokens, fall
|
||||
/// back to the whole command segment.
|
||||
fn auto_derived_execpolicy_amendment_for_mode(
|
||||
command: &[String],
|
||||
enhanced_exec_policy_suggestions: bool,
|
||||
) -> Option<ExecPolicyAmendment> {
|
||||
if command.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !enhanced_exec_policy_suggestions {
|
||||
return Some(ExecPolicyAmendment::from(command.to_vec()));
|
||||
}
|
||||
|
||||
let prefix: Vec<String> = command
|
||||
.iter()
|
||||
.take_while(|token| !token.starts_with('-'))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
if prefix.len() >= 2 {
|
||||
return Some(ExecPolicyAmendment::from(prefix));
|
||||
}
|
||||
|
||||
Some(ExecPolicyAmendment::from(command.to_vec()))
|
||||
}
|
||||
|
||||
fn derive_requested_execpolicy_amendment_from_prefix_rule(
|
||||
prefix_rule: Option<&Vec<String>>,
|
||||
matched_rules: &[RuleMatch],
|
||||
|
||||
@@ -81,6 +81,17 @@ fn unrestricted_file_system_sandbox_policy() -> FileSystemSandboxPolicy {
|
||||
FileSystemSandboxPolicy::unrestricted()
|
||||
}
|
||||
|
||||
async fn create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
manager: &ExecPolicyManager,
|
||||
req: ExecApprovalRequest<'_>,
|
||||
) -> ExecApprovalRequirement {
|
||||
manager
|
||||
.create_exec_approval_requirement_for_command_with_enhanced_suggestions(
|
||||
req, /*enhanced_exec_policy_suggestions*/ true,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn test_config() -> (TempDir, Config) {
|
||||
let home = TempDir::new().expect("create temp dir");
|
||||
let config = ConfigBuilder::default()
|
||||
@@ -1032,7 +1043,7 @@ async fn exec_approval_requirement_falls_back_to_heuristics() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn empty_bash_lc_script_falls_back_to_original_command() {
|
||||
async fn empty_bash_lc_script_falls_back_to_whole_command_when_truncated_prefix_is_too_short() {
|
||||
let command = vec!["bash".to_string(), "-lc".to_string(), "".to_string()];
|
||||
|
||||
let manager = ExecPolicyManager::default();
|
||||
@@ -1057,7 +1068,8 @@ async fn empty_bash_lc_script_falls_back_to_original_command() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn whitespace_bash_lc_script_falls_back_to_original_command() {
|
||||
async fn whitespace_bash_lc_script_falls_back_to_whole_command_when_truncated_prefix_is_too_short()
|
||||
{
|
||||
let command = vec![
|
||||
"bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
@@ -1118,7 +1130,7 @@ async fn request_rule_uses_prefix_rule() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn request_rule_falls_back_when_prefix_rule_does_not_approve_all_commands() {
|
||||
async fn request_rule_falls_back_to_first_segment_for_multi_command_scripts() {
|
||||
let command = vec![
|
||||
"bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
@@ -1126,25 +1138,27 @@ async fn request_rule_falls_back_when_prefix_rule_does_not_approve_all_commands(
|
||||
];
|
||||
let manager = ExecPolicyManager::default();
|
||||
|
||||
let requirement = manager
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
let requirement = create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&manager,
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::OnRequest,
|
||||
sandbox_policy: &SandboxPolicy::DangerFullAccess,
|
||||
file_system_sandbox_policy: &unrestricted_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::RequireEscalated,
|
||||
prefix_rule: Some(vec!["cargo".to_string(), "install".to_string()]),
|
||||
})
|
||||
.await;
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
requirement,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(vec![
|
||||
"rm".to_string(),
|
||||
"-rf".to_string(),
|
||||
"/tmp/codex".to_string(),
|
||||
"cargo".to_string(),
|
||||
"install".to_string(),
|
||||
"cargo-insta".to_string(),
|
||||
])),
|
||||
}
|
||||
);
|
||||
@@ -1165,21 +1179,23 @@ async fn heuristics_apply_when_other_commands_match_policy() {
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
ExecPolicyManager::new(policy)
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&ExecPolicyManager::new(policy),
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::DangerFullAccess,
|
||||
file_system_sandbox_policy: &unrestricted_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
})
|
||||
.await,
|
||||
},
|
||||
)
|
||||
.await,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(vec![
|
||||
"orange".to_string()
|
||||
]))
|
||||
"apple".to_string()
|
||||
])),
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1260,6 +1276,98 @@ async fn proposed_execpolicy_amendment_is_present_for_single_command_without_pol
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_stops_before_first_flag_for_generated_suggestions() {
|
||||
let command = vec![
|
||||
"cargo".to_string(),
|
||||
"test".to_string(),
|
||||
"--package".to_string(),
|
||||
"codex-core".to_string(),
|
||||
];
|
||||
|
||||
let manager = ExecPolicyManager::default();
|
||||
let requirement = create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&manager,
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::new_read_only_policy(),
|
||||
file_system_sandbox_policy: &read_only_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
requirement,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(vec![
|
||||
"cargo".to_string(),
|
||||
"test".to_string(),
|
||||
]))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_preserves_full_command_when_enhanced_suggestions_disabled() {
|
||||
let command = vec![
|
||||
"cargo".to_string(),
|
||||
"test".to_string(),
|
||||
"--package".to_string(),
|
||||
"codex-core".to_string(),
|
||||
];
|
||||
|
||||
let manager = ExecPolicyManager::default();
|
||||
let requirement = manager
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::new_read_only_policy(),
|
||||
file_system_sandbox_policy: &read_only_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
})
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
requirement,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(command))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_falls_back_to_whole_command_if_flag_starts_too_early() {
|
||||
let command = vec!["curl".to_string(), "-k".to_string(), "xyz.com".to_string()];
|
||||
|
||||
let manager = ExecPolicyManager::default();
|
||||
let requirement = create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&manager,
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::new_read_only_policy(),
|
||||
file_system_sandbox_policy: &read_only_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
requirement,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(command))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_is_omitted_when_policy_prompts() {
|
||||
let policy_src = r#"prefix_rule(pattern=["rm"], decision="prompt")"#;
|
||||
@@ -1292,23 +1400,25 @@ async fn proposed_execpolicy_amendment_is_omitted_when_policy_prompts() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_is_present_for_multi_command_scripts() {
|
||||
async fn proposed_execpolicy_amendment_is_based_on_first_segment_for_multi_command_scripts() {
|
||||
let command = vec![
|
||||
"bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
"cargo build && echo ok".to_string(),
|
||||
];
|
||||
let manager = ExecPolicyManager::default();
|
||||
let requirement = manager
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
let requirement = create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&manager,
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::new_read_only_policy(),
|
||||
file_system_sandbox_policy: &read_only_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
})
|
||||
.await;
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
requirement,
|
||||
@@ -1323,7 +1433,8 @@ async fn proposed_execpolicy_amendment_is_present_for_multi_command_scripts() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn proposed_execpolicy_amendment_uses_first_no_match_in_multi_command_scripts() {
|
||||
async fn proposed_execpolicy_amendment_uses_whole_one_token_first_segment_for_multi_command_scripts()
|
||||
{
|
||||
let policy_src = r#"prefix_rule(pattern=["cat"], decision="allow")"#;
|
||||
let mut parser = PolicyParser::new();
|
||||
parser
|
||||
@@ -1338,21 +1449,21 @@ async fn proposed_execpolicy_amendment_uses_first_no_match_in_multi_command_scri
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
ExecPolicyManager::new(policy)
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
create_exec_approval_requirement_with_enhanced_suggestions(
|
||||
&ExecPolicyManager::new(policy),
|
||||
ExecApprovalRequest {
|
||||
command: &command,
|
||||
approval_policy: AskForApproval::UnlessTrusted,
|
||||
sandbox_policy: &SandboxPolicy::new_read_only_policy(),
|
||||
file_system_sandbox_policy: &read_only_file_system_sandbox_policy(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
prefix_rule: None,
|
||||
})
|
||||
.await,
|
||||
},
|
||||
)
|
||||
.await,
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(vec![
|
||||
"apple".to_string()
|
||||
])),
|
||||
proposed_execpolicy_amendment: Some(ExecPolicyAmendment::new(vec!["cat".to_string()])),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,8 @@ pub enum Feature {
|
||||
UseLegacyLandlock,
|
||||
/// Allow the model to request approval and propose exec rules.
|
||||
RequestRule,
|
||||
/// Use tighter generated execpolicy prefix suggestions for approval prompts.
|
||||
EnhancedExecPolicySuggestions,
|
||||
/// Enable Windows sandbox (restricted token) on Windows.
|
||||
WindowsSandbox,
|
||||
/// Use the elevated Windows sandbox pipeline (setup + runner).
|
||||
@@ -677,6 +679,16 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
stage: Stage::Removed,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::EnhancedExecPolicySuggestions,
|
||||
key: "enhanced_exec_policy_suggestions",
|
||||
stage: Stage::Experimental {
|
||||
name: "Enhanced exec policy suggestions",
|
||||
menu_description: "When Codex proposes a reusable exec policy prefix, stop before the first flag-like argument and use the first segment of a compound shell command.",
|
||||
announcement: "",
|
||||
},
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::WindowsSandbox,
|
||||
key: "experimental_windows_sandbox",
|
||||
|
||||
@@ -85,6 +85,29 @@ fn guardian_approval_is_experimental_and_user_toggleable() {
|
||||
assert_eq!(Feature::GuardianApproval.default_enabled(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enhanced_exec_policy_suggestions_is_experimental_and_user_toggleable() {
|
||||
let spec = Feature::EnhancedExecPolicySuggestions.info();
|
||||
let stage = spec.stage;
|
||||
|
||||
assert!(matches!(stage, Stage::Experimental { .. }));
|
||||
assert_eq!(
|
||||
stage.experimental_menu_name(),
|
||||
Some("Enhanced exec policy suggestions")
|
||||
);
|
||||
assert_eq!(
|
||||
stage.experimental_menu_description(),
|
||||
Some(
|
||||
"When Codex proposes a reusable exec policy prefix, stop before the first flag-like argument and use the first segment of a compound shell command."
|
||||
)
|
||||
);
|
||||
assert_eq!(stage.experimental_announcement(), None);
|
||||
assert_eq!(
|
||||
Feature::EnhancedExecPolicySuggestions.default_enabled(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_permissions_is_under_development() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -428,18 +428,24 @@ impl ShellHandler {
|
||||
let exec_approval_requirement = session
|
||||
.services
|
||||
.exec_policy
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
command: &exec_params.command,
|
||||
approval_policy: turn.approval_policy.value(),
|
||||
sandbox_policy: turn.sandbox_policy.get(),
|
||||
file_system_sandbox_policy: &turn.file_system_sandbox_policy,
|
||||
sandbox_permissions: if effective_additional_permissions.permissions_preapproved {
|
||||
codex_protocol::models::SandboxPermissions::UseDefault
|
||||
} else {
|
||||
effective_additional_permissions.sandbox_permissions
|
||||
.create_exec_approval_requirement_for_command_with_enhanced_suggestions(
|
||||
ExecApprovalRequest {
|
||||
command: &exec_params.command,
|
||||
approval_policy: turn.approval_policy.value(),
|
||||
sandbox_policy: turn.sandbox_policy.get(),
|
||||
file_system_sandbox_policy: &turn.file_system_sandbox_policy,
|
||||
sandbox_permissions: if effective_additional_permissions.permissions_preapproved
|
||||
{
|
||||
codex_protocol::models::SandboxPermissions::UseDefault
|
||||
} else {
|
||||
effective_additional_permissions.sandbox_permissions
|
||||
},
|
||||
prefix_rule,
|
||||
},
|
||||
prefix_rule,
|
||||
})
|
||||
session
|
||||
.features()
|
||||
.enabled(Feature::EnhancedExecPolicySuggestions),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = ShellRequest {
|
||||
|
||||
@@ -15,6 +15,7 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::exec_env::create_env;
|
||||
use crate::exec_policy::ExecApprovalRequest;
|
||||
use crate::features::Feature;
|
||||
use crate::protocol::ExecCommandSource;
|
||||
use crate::sandboxing::ExecRequest;
|
||||
use crate::tools::context::ExecCommandToolOutput;
|
||||
@@ -596,18 +597,24 @@ impl UnifiedExecProcessManager {
|
||||
.session
|
||||
.services
|
||||
.exec_policy
|
||||
.create_exec_approval_requirement_for_command(ExecApprovalRequest {
|
||||
command: &request.command,
|
||||
approval_policy: context.turn.approval_policy.value(),
|
||||
sandbox_policy: context.turn.sandbox_policy.get(),
|
||||
file_system_sandbox_policy: &context.turn.file_system_sandbox_policy,
|
||||
sandbox_permissions: if request.additional_permissions_preapproved {
|
||||
crate::sandboxing::SandboxPermissions::UseDefault
|
||||
} else {
|
||||
request.sandbox_permissions
|
||||
.create_exec_approval_requirement_for_command_with_enhanced_suggestions(
|
||||
ExecApprovalRequest {
|
||||
command: &request.command,
|
||||
approval_policy: context.turn.approval_policy.value(),
|
||||
sandbox_policy: context.turn.sandbox_policy.get(),
|
||||
file_system_sandbox_policy: &context.turn.file_system_sandbox_policy,
|
||||
sandbox_permissions: if request.additional_permissions_preapproved {
|
||||
crate::sandboxing::SandboxPermissions::UseDefault
|
||||
} else {
|
||||
request.sandbox_permissions
|
||||
},
|
||||
prefix_rule: request.prefix_rule.clone(),
|
||||
},
|
||||
prefix_rule: request.prefix_rule.clone(),
|
||||
})
|
||||
context
|
||||
.session
|
||||
.features()
|
||||
.enabled(Feature::EnhancedExecPolicySuggestions),
|
||||
)
|
||||
.await;
|
||||
let req = UnifiedExecToolRequest {
|
||||
command: request.command.clone(),
|
||||
|
||||
@@ -36,7 +36,7 @@ pub(crate) struct ExecServerFileSystem {
|
||||
impl Default for ExecServerFileSystem {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
file_system: Arc::new(Environment.get_filesystem()),
|
||||
file_system: Arc::new(Environment::default().get_filesystem()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7720,8 +7720,13 @@ async fn experimental_popup_shows_js_repl_node_requirement() {
|
||||
chat.open_experimental_popup();
|
||||
|
||||
let popup = render_bottom_popup(&chat, 120);
|
||||
let normalized_popup = popup
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
.replace("- ", "-");
|
||||
assert!(
|
||||
popup.contains(node_requirement),
|
||||
normalized_popup.contains(node_requirement),
|
||||
"expected js_repl feature description to mention the required Node version, got:\n{popup}"
|
||||
);
|
||||
}
|
||||
@@ -7744,7 +7749,11 @@ async fn experimental_popup_includes_guardian_approval() {
|
||||
chat.open_experimental_popup();
|
||||
|
||||
let popup = render_bottom_popup(&chat, 120);
|
||||
let normalized_popup = popup.split_whitespace().collect::<Vec<_>>().join(" ");
|
||||
let normalized_popup = popup
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
.replace("- ", "-");
|
||||
assert!(
|
||||
popup.contains(guardian_name),
|
||||
"expected guardian approvals entry in experimental popup, got:\n{popup}"
|
||||
|
||||
@@ -8264,8 +8264,13 @@ async fn experimental_popup_shows_js_repl_node_requirement() {
|
||||
chat.open_experimental_popup();
|
||||
|
||||
let popup = render_bottom_popup(&chat, 120);
|
||||
let normalized_popup = popup
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
.replace("- ", "-");
|
||||
assert!(
|
||||
popup.contains(node_requirement),
|
||||
normalized_popup.contains(node_requirement),
|
||||
"expected js_repl feature description to mention the required Node version, got:\n{popup}"
|
||||
);
|
||||
}
|
||||
@@ -8288,7 +8293,11 @@ async fn experimental_popup_includes_guardian_approval() {
|
||||
chat.open_experimental_popup();
|
||||
|
||||
let popup = render_bottom_popup(&chat, 120);
|
||||
let normalized_popup = popup.split_whitespace().collect::<Vec<_>>().join(" ");
|
||||
let normalized_popup = popup
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
.replace("- ", "-");
|
||||
assert!(
|
||||
popup.contains(guardian_name),
|
||||
"expected guardian approvals entry in experimental popup, got:\n{popup}"
|
||||
|
||||
Reference in New Issue
Block a user