mirror of
https://github.com/openai/codex.git
synced 2026-04-24 22:54:54 +00:00
updating app server types to support execpoilcy amendment (#7747)
also includes minor refactor merging `ApprovalDecision` with `CommandExecutionRequestAcceptSettings`
This commit is contained in:
@@ -3,6 +3,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::protocol::common::AuthMode;
|
use crate::protocol::common::AuthMode;
|
||||||
use codex_protocol::account::PlanType;
|
use codex_protocol::account::PlanType;
|
||||||
|
use codex_protocol::approvals::ExecPolicyAmendment as CoreExecPolicyAmendment;
|
||||||
use codex_protocol::approvals::SandboxCommandAssessment as CoreSandboxCommandAssessment;
|
use codex_protocol::approvals::SandboxCommandAssessment as CoreSandboxCommandAssessment;
|
||||||
use codex_protocol::config_types::ReasoningSummary;
|
use codex_protocol::config_types::ReasoningSummary;
|
||||||
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
|
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
|
||||||
@@ -287,6 +288,11 @@ v2_enum_from_core!(
|
|||||||
#[ts(export_to = "v2/")]
|
#[ts(export_to = "v2/")]
|
||||||
pub enum ApprovalDecision {
|
pub enum ApprovalDecision {
|
||||||
Accept,
|
Accept,
|
||||||
|
/// Approve and remember the approval for the session.
|
||||||
|
AcceptForSession,
|
||||||
|
AcceptWithExecpolicyAmendment {
|
||||||
|
execpolicy_amendment: ExecPolicyAmendment,
|
||||||
|
},
|
||||||
Decline,
|
Decline,
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
@@ -382,6 +388,27 @@ impl From<CoreSandboxCommandAssessment> for SandboxCommandAssessment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
#[ts(type = "Array<string>", export_to = "v2/")]
|
||||||
|
pub struct ExecPolicyAmendment {
|
||||||
|
pub command: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecPolicyAmendment {
|
||||||
|
pub fn into_core(self) -> CoreExecPolicyAmendment {
|
||||||
|
CoreExecPolicyAmendment::new(self.command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreExecPolicyAmendment> for ExecPolicyAmendment {
|
||||||
|
fn from(value: CoreExecPolicyAmendment) -> Self {
|
||||||
|
Self {
|
||||||
|
command: value.command().to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
#[ts(tag = "type")]
|
#[ts(tag = "type")]
|
||||||
@@ -1468,15 +1495,8 @@ pub struct CommandExecutionRequestApprovalParams {
|
|||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
/// Optional model-provided risk assessment describing the blocked command.
|
/// Optional model-provided risk assessment describing the blocked command.
|
||||||
pub risk: Option<SandboxCommandAssessment>,
|
pub risk: Option<SandboxCommandAssessment>,
|
||||||
}
|
/// Optional proposed execpolicy amendment to allow similar commands without prompting.
|
||||||
|
pub proposed_execpolicy_amendment: Option<ExecPolicyAmendment>,
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
#[ts(export_to = "v2/")]
|
|
||||||
pub struct CommandExecutionRequestAcceptSettings {
|
|
||||||
/// If true, automatically approve this command for the duration of the session.
|
|
||||||
#[serde(default)]
|
|
||||||
pub for_session: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
@@ -1484,10 +1504,6 @@ pub struct CommandExecutionRequestAcceptSettings {
|
|||||||
#[ts(export_to = "v2/")]
|
#[ts(export_to = "v2/")]
|
||||||
pub struct CommandExecutionRequestApprovalResponse {
|
pub struct CommandExecutionRequestApprovalResponse {
|
||||||
pub decision: ApprovalDecision,
|
pub decision: ApprovalDecision,
|
||||||
/// Optional approval settings for when the decision is `accept`.
|
|
||||||
/// Ignored if the decision is `decline` or `cancel`.
|
|
||||||
#[serde(default)]
|
|
||||||
pub accept_settings: Option<CommandExecutionRequestAcceptSettings>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use codex_app_server_protocol::ApprovalDecision;
|
|||||||
use codex_app_server_protocol::AskForApproval;
|
use codex_app_server_protocol::AskForApproval;
|
||||||
use codex_app_server_protocol::ClientInfo;
|
use codex_app_server_protocol::ClientInfo;
|
||||||
use codex_app_server_protocol::ClientRequest;
|
use codex_app_server_protocol::ClientRequest;
|
||||||
use codex_app_server_protocol::CommandExecutionRequestAcceptSettings;
|
|
||||||
use codex_app_server_protocol::CommandExecutionRequestApprovalParams;
|
use codex_app_server_protocol::CommandExecutionRequestApprovalParams;
|
||||||
use codex_app_server_protocol::CommandExecutionRequestApprovalResponse;
|
use codex_app_server_protocol::CommandExecutionRequestApprovalResponse;
|
||||||
use codex_app_server_protocol::FileChangeRequestApprovalParams;
|
use codex_app_server_protocol::FileChangeRequestApprovalParams;
|
||||||
@@ -754,6 +753,7 @@ impl CodexClient {
|
|||||||
item_id,
|
item_id,
|
||||||
reason,
|
reason,
|
||||||
risk,
|
risk,
|
||||||
|
proposed_execpolicy_amendment,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
@@ -765,10 +765,12 @@ impl CodexClient {
|
|||||||
if let Some(risk) = risk.as_ref() {
|
if let Some(risk) = risk.as_ref() {
|
||||||
println!("< risk assessment: {risk:?}");
|
println!("< risk assessment: {risk:?}");
|
||||||
}
|
}
|
||||||
|
if let Some(execpolicy_amendment) = proposed_execpolicy_amendment.as_ref() {
|
||||||
|
println!("< proposed execpolicy amendment: {execpolicy_amendment:?}");
|
||||||
|
}
|
||||||
|
|
||||||
let response = CommandExecutionRequestApprovalResponse {
|
let response = CommandExecutionRequestApprovalResponse {
|
||||||
decision: ApprovalDecision::Accept,
|
decision: ApprovalDecision::Accept,
|
||||||
accept_settings: Some(CommandExecutionRequestAcceptSettings { for_session: false }),
|
|
||||||
};
|
};
|
||||||
self.send_server_request_response(request_id, &response)?;
|
self.send_server_request_response(request_id, &response)?;
|
||||||
println!("< approved commandExecution request for item {item_id}");
|
println!("< approved commandExecution request for item {item_id}");
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use codex_app_server_protocol::ContextCompactedNotification;
|
|||||||
use codex_app_server_protocol::ErrorNotification;
|
use codex_app_server_protocol::ErrorNotification;
|
||||||
use codex_app_server_protocol::ExecCommandApprovalParams;
|
use codex_app_server_protocol::ExecCommandApprovalParams;
|
||||||
use codex_app_server_protocol::ExecCommandApprovalResponse;
|
use codex_app_server_protocol::ExecCommandApprovalResponse;
|
||||||
|
use codex_app_server_protocol::ExecPolicyAmendment as V2ExecPolicyAmendment;
|
||||||
use codex_app_server_protocol::FileChangeOutputDeltaNotification;
|
use codex_app_server_protocol::FileChangeOutputDeltaNotification;
|
||||||
use codex_app_server_protocol::FileChangeRequestApprovalParams;
|
use codex_app_server_protocol::FileChangeRequestApprovalParams;
|
||||||
use codex_app_server_protocol::FileChangeRequestApprovalResponse;
|
use codex_app_server_protocol::FileChangeRequestApprovalResponse;
|
||||||
@@ -179,7 +180,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
|||||||
cwd,
|
cwd,
|
||||||
reason,
|
reason,
|
||||||
risk,
|
risk,
|
||||||
proposed_execpolicy_amendment: _,
|
proposed_execpolicy_amendment,
|
||||||
parsed_cmd,
|
parsed_cmd,
|
||||||
}) => match api_version {
|
}) => match api_version {
|
||||||
ApiVersion::V1 => {
|
ApiVersion::V1 => {
|
||||||
@@ -207,6 +208,8 @@ pub(crate) async fn apply_bespoke_event_handling(
|
|||||||
.map(V2ParsedCommand::from)
|
.map(V2ParsedCommand::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let command_string = shlex_join(&command);
|
let command_string = shlex_join(&command);
|
||||||
|
let proposed_execpolicy_amendment_v2 =
|
||||||
|
proposed_execpolicy_amendment.map(V2ExecPolicyAmendment::from);
|
||||||
|
|
||||||
let params = CommandExecutionRequestApprovalParams {
|
let params = CommandExecutionRequestApprovalParams {
|
||||||
thread_id: conversation_id.to_string(),
|
thread_id: conversation_id.to_string(),
|
||||||
@@ -216,6 +219,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
|||||||
item_id: item_id.clone(),
|
item_id: item_id.clone(),
|
||||||
reason,
|
reason,
|
||||||
risk: risk.map(V2SandboxCommandAssessment::from),
|
risk: risk.map(V2SandboxCommandAssessment::from),
|
||||||
|
proposed_execpolicy_amendment: proposed_execpolicy_amendment_v2,
|
||||||
};
|
};
|
||||||
let rx = outgoing
|
let rx = outgoing
|
||||||
.send_request(ServerRequestPayload::CommandExecutionRequestApproval(
|
.send_request(ServerRequestPayload::CommandExecutionRequestApproval(
|
||||||
@@ -1047,7 +1051,11 @@ async fn on_file_change_request_approval_response(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let (decision, completion_status) = match response.decision {
|
let (decision, completion_status) = match response.decision {
|
||||||
ApprovalDecision::Accept => (ReviewDecision::Approved, None),
|
ApprovalDecision::Accept
|
||||||
|
| ApprovalDecision::AcceptForSession
|
||||||
|
| ApprovalDecision::AcceptWithExecpolicyAmendment { .. } => {
|
||||||
|
(ReviewDecision::Approved, None)
|
||||||
|
}
|
||||||
ApprovalDecision::Decline => {
|
ApprovalDecision::Decline => {
|
||||||
(ReviewDecision::Denied, Some(PatchApplyStatus::Declined))
|
(ReviewDecision::Denied, Some(PatchApplyStatus::Declined))
|
||||||
}
|
}
|
||||||
@@ -1109,25 +1117,27 @@ async fn on_command_execution_request_approval_response(
|
|||||||
error!("failed to deserialize CommandExecutionRequestApprovalResponse: {err}");
|
error!("failed to deserialize CommandExecutionRequestApprovalResponse: {err}");
|
||||||
CommandExecutionRequestApprovalResponse {
|
CommandExecutionRequestApprovalResponse {
|
||||||
decision: ApprovalDecision::Decline,
|
decision: ApprovalDecision::Decline,
|
||||||
accept_settings: None,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let CommandExecutionRequestApprovalResponse {
|
let decision = response.decision;
|
||||||
decision,
|
|
||||||
accept_settings,
|
|
||||||
} = response;
|
|
||||||
|
|
||||||
let (decision, completion_status) = match (decision, accept_settings) {
|
let (decision, completion_status) = match decision {
|
||||||
(ApprovalDecision::Accept, Some(settings)) if settings.for_session => {
|
ApprovalDecision::Accept => (ReviewDecision::Approved, None),
|
||||||
(ReviewDecision::ApprovedForSession, None)
|
ApprovalDecision::AcceptForSession => (ReviewDecision::ApprovedForSession, None),
|
||||||
}
|
ApprovalDecision::AcceptWithExecpolicyAmendment {
|
||||||
(ApprovalDecision::Accept, _) => (ReviewDecision::Approved, None),
|
execpolicy_amendment,
|
||||||
(ApprovalDecision::Decline, _) => (
|
} => (
|
||||||
|
ReviewDecision::ApprovedExecpolicyAmendment {
|
||||||
|
proposed_execpolicy_amendment: execpolicy_amendment.into_core(),
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
ApprovalDecision::Decline => (
|
||||||
ReviewDecision::Denied,
|
ReviewDecision::Denied,
|
||||||
Some(CommandExecutionStatus::Declined),
|
Some(CommandExecutionStatus::Declined),
|
||||||
),
|
),
|
||||||
(ApprovalDecision::Cancel, _) => (
|
ApprovalDecision::Cancel => (
|
||||||
ReviewDecision::Abort,
|
ReviewDecision::Abort,
|
||||||
Some(CommandExecutionStatus::Declined),
|
Some(CommandExecutionStatus::Declined),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -427,7 +427,6 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
|||||||
request_id,
|
request_id,
|
||||||
serde_json::to_value(CommandExecutionRequestApprovalResponse {
|
serde_json::to_value(CommandExecutionRequestApprovalResponse {
|
||||||
decision: ApprovalDecision::Decline,
|
decision: ApprovalDecision::Decline,
|
||||||
accept_settings: None,
|
|
||||||
})?,
|
})?,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user