| use crate::JsonSchema; |
| use crate::TS; |
| use codex_experimental_api_macros::ExperimentalApi; |
| use codex_protocol::config_types::ApprovalsReviewer as CoreApprovalsReviewer; |
| use codex_protocol::config_types::SandboxMode as CoreSandboxMode; |
| use codex_protocol::protocol::AskForApproval as CoreAskForApproval; |
| use codex_protocol::protocol::CodexErrorInfo as CoreCodexErrorInfo; |
| use codex_protocol::protocol::GranularApprovalConfig as CoreGranularApprovalConfig; |
| use codex_protocol::protocol::NonSteerableTurnKind as CoreNonSteerableTurnKind; |
| #[cfg(test)] |
| use schemars::r#gen::SchemaGenerator; |
| #[cfg(test)] |
| use schemars::schema::InstanceType; |
| #[cfg(test)] |
| use schemars::schema::Metadata; |
| #[cfg(test)] |
| use schemars::schema::Schema; |
| #[cfg(test)] |
| use schemars::schema::SchemaObject; |
| use serde::Deserialize; |
| use serde::Serialize; |
| #[cfg(test)] |
| use serde_json::Value as JsonValue; |
|
|
| |
| |
| macro_rules! v2_enum_from_core { |
| ( |
| $(#[$enum_meta:meta])* |
| pub enum $Name:ident from $Src:path { |
| $( $(#[$variant_meta:meta])* $Variant:ident ),+ $(,)? |
| } |
| ) => { |
| #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] |
| $(#[$enum_meta])* |
| #[serde(rename_all = "camelCase")] |
| #[ts(export_to = "v2/")] |
| pub enum $Name { |
| $( $(#[$variant_meta])* $Variant ),+ |
| } |
|
|
| impl $Name { |
| pub fn to_core(self) -> $Src { |
| match self { $( $Name::$Variant => <$Src>::$Variant ),+ } |
| } |
| } |
|
|
| impl From<$Src> for $Name { |
| fn from(value: $Src) -> Self { |
| match value { $( <$Src>::$Variant => $Name::$Variant ),+ } |
| } |
| } |
| }; |
| } |
|
|
| pub(super) use v2_enum_from_core; |
|
|
| pub(super) const fn default_enabled() -> bool { |
| true |
| } |
|
|
| #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] |
| #[serde(rename_all = "camelCase")] |
| #[ts(export_to = "v2/")] |
| pub enum NonSteerableTurnKind { |
| Review, |
| Compact, |
| } |
|
|
| |
| |
| |
| |
| #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] |
| #[serde(rename_all = "camelCase")] |
| #[ts(export_to = "v2/")] |
| pub enum CodexErrorInfo { |
| ContextWindowExceeded, |
| SessionBudgetExceeded, |
| UsageLimitExceeded, |
| RateLimitExceeded, |
| ServerOverloaded, |
| CyberPolicy, |
| MisalignmentPolicyViolation, |
| HttpConnectionFailed { |
| #[serde(rename = "httpStatusCode")] |
| #[ts(rename = "httpStatusCode")] |
| http_status_code: Option<u16>, |
| }, |
| |
| ResponseStreamConnectionFailed { |
| #[serde(rename = "httpStatusCode")] |
| #[ts(rename = "httpStatusCode")] |
| http_status_code: Option<u16>, |
| }, |
| InternalServerError, |
| Unauthorized, |
| BadRequest, |
| ThreadRollbackFailed, |
| SandboxError, |
| |
| ResponseStreamDisconnected { |
| #[serde(rename = "httpStatusCode")] |
| #[ts(rename = "httpStatusCode")] |
| http_status_code: Option<u16>, |
| }, |
| |
| ResponseTooManyFailedAttempts { |
| #[serde(rename = "httpStatusCode")] |
| #[ts(rename = "httpStatusCode")] |
| http_status_code: Option<u16>, |
| }, |
| |
| |
| ActiveTurnNotSteerable { |
| #[serde(rename = "turnKind")] |
| #[ts(rename = "turnKind")] |
| turn_kind: NonSteerableTurnKind, |
| }, |
| Other, |
| } |
|
|
| impl From<CoreCodexErrorInfo> for CodexErrorInfo { |
| fn from(value: CoreCodexErrorInfo) -> Self { |
| match value { |
| CoreCodexErrorInfo::ContextWindowExceeded => CodexErrorInfo::ContextWindowExceeded, |
| CoreCodexErrorInfo::SessionBudgetExceeded => CodexErrorInfo::SessionBudgetExceeded, |
| CoreCodexErrorInfo::UsageLimitExceeded => CodexErrorInfo::UsageLimitExceeded, |
| CoreCodexErrorInfo::RateLimitExceeded => CodexErrorInfo::RateLimitExceeded, |
| CoreCodexErrorInfo::ServerOverloaded => CodexErrorInfo::ServerOverloaded, |
| CoreCodexErrorInfo::CyberPolicy => CodexErrorInfo::CyberPolicy, |
| CoreCodexErrorInfo::MisalignmentPolicyViolation => { |
| CodexErrorInfo::MisalignmentPolicyViolation |
| } |
| CoreCodexErrorInfo::HttpConnectionFailed { http_status_code } => { |
| CodexErrorInfo::HttpConnectionFailed { http_status_code } |
| } |
| CoreCodexErrorInfo::ResponseStreamConnectionFailed { http_status_code } => { |
| CodexErrorInfo::ResponseStreamConnectionFailed { http_status_code } |
| } |
| CoreCodexErrorInfo::InternalServerError => CodexErrorInfo::InternalServerError, |
| CoreCodexErrorInfo::Unauthorized => CodexErrorInfo::Unauthorized, |
| CoreCodexErrorInfo::BadRequest => CodexErrorInfo::BadRequest, |
| CoreCodexErrorInfo::ThreadRollbackFailed => CodexErrorInfo::ThreadRollbackFailed, |
| CoreCodexErrorInfo::SandboxError => CodexErrorInfo::SandboxError, |
| CoreCodexErrorInfo::ResponseStreamDisconnected { http_status_code } => { |
| CodexErrorInfo::ResponseStreamDisconnected { http_status_code } |
| } |
| CoreCodexErrorInfo::ResponseTooManyFailedAttempts { http_status_code } => { |
| CodexErrorInfo::ResponseTooManyFailedAttempts { http_status_code } |
| } |
| CoreCodexErrorInfo::ActiveTurnNotSteerable { turn_kind } => { |
| CodexErrorInfo::ActiveTurnNotSteerable { |
| turn_kind: turn_kind.into(), |
| } |
| } |
| CoreCodexErrorInfo::Other => CodexErrorInfo::Other, |
| } |
| } |
| } |
|
|
| impl From<CoreNonSteerableTurnKind> for NonSteerableTurnKind { |
| fn from(value: CoreNonSteerableTurnKind) -> Self { |
| match value { |
| CoreNonSteerableTurnKind::Review => Self::Review, |
| CoreNonSteerableTurnKind::Compact => Self::Compact, |
| } |
| } |
| } |
|
|
| #[derive( |
| Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS, ExperimentalApi, |
| )] |
| #[serde(rename_all = "kebab-case")] |
| #[ts(rename_all = "kebab-case", export_to = "v2/")] |
| pub enum AskForApproval { |
| #[serde(rename = "untrusted")] |
| #[ts(rename = "untrusted")] |
| UnlessTrusted, |
| OnRequest, |
| #[experimental("askForApproval.granular")] |
| Granular { |
| sandbox_approval: bool, |
| rules: bool, |
| #[serde(default)] |
| skill_approval: bool, |
| #[serde(default)] |
| request_permissions: bool, |
| mcp_elicitations: bool, |
| }, |
| Never, |
| } |
|
|
| impl AskForApproval { |
| pub fn to_core(self) -> CoreAskForApproval { |
| match self { |
| AskForApproval::UnlessTrusted => CoreAskForApproval::UnlessTrusted, |
| AskForApproval::OnRequest => CoreAskForApproval::OnRequest, |
| AskForApproval::Granular { |
| sandbox_approval, |
| rules, |
| skill_approval, |
| request_permissions, |
| mcp_elicitations, |
| } => CoreAskForApproval::Granular(CoreGranularApprovalConfig { |
| sandbox_approval, |
| rules, |
| skill_approval, |
| request_permissions, |
| mcp_elicitations, |
| }), |
| AskForApproval::Never => CoreAskForApproval::Never, |
| } |
| } |
| } |
|
|
| impl From<CoreAskForApproval> for AskForApproval { |
| fn from(value: CoreAskForApproval) -> Self { |
| match value { |
| CoreAskForApproval::UnlessTrusted => AskForApproval::UnlessTrusted, |
| CoreAskForApproval::OnRequest => AskForApproval::OnRequest, |
| CoreAskForApproval::Granular(granular_config) => AskForApproval::Granular { |
| sandbox_approval: granular_config.sandbox_approval, |
| rules: granular_config.rules, |
| skill_approval: granular_config.skill_approval, |
| request_permissions: granular_config.request_permissions, |
| mcp_elicitations: granular_config.mcp_elicitations, |
| }, |
| CoreAskForApproval::Never => AskForApproval::Never, |
| } |
| } |
| } |
|
|
| #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, TS)] |
| #[ts( |
| type = r#""user" | "auto_review" | "guardian_subagent""#, |
| export_to = "v2/" |
| )] |
| |
| |
| |
| |
| |
| pub enum ApprovalsReviewer { |
| #[serde(rename = "user")] |
| User, |
| #[serde(rename = "auto_review", alias = "guardian_subagent")] |
| AutoReview, |
| } |
|
|
| #[cfg(test)] |
| impl JsonSchema for ApprovalsReviewer { |
| fn schema_name() -> String { |
| "ApprovalsReviewer".to_string() |
| } |
|
|
| fn json_schema(_generator: &mut SchemaGenerator) -> Schema { |
| string_enum_schema_with_description( |
| &["user", "auto_review", "guardian_subagent"], |
| "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", |
| ) |
| } |
| } |
|
|
| #[cfg(test)] |
| fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema { |
| let mut schema = SchemaObject { |
| instance_type: Some(InstanceType::String.into()), |
| metadata: Some(Box::new(Metadata { |
| description: Some(description.to_string()), |
| ..Default::default() |
| })), |
| ..Default::default() |
| }; |
| schema.enum_values = Some( |
| values |
| .iter() |
| .map(|value| JsonValue::String((*value).to_string())) |
| .collect(), |
| ); |
| Schema::Object(schema) |
| } |
|
|
| impl ApprovalsReviewer { |
| pub fn to_core(self) -> CoreApprovalsReviewer { |
| match self { |
| ApprovalsReviewer::User => CoreApprovalsReviewer::User, |
| ApprovalsReviewer::AutoReview => CoreApprovalsReviewer::AutoReview, |
| } |
| } |
| } |
|
|
| impl From<CoreApprovalsReviewer> for ApprovalsReviewer { |
| fn from(value: CoreApprovalsReviewer) -> Self { |
| match value { |
| CoreApprovalsReviewer::User => ApprovalsReviewer::User, |
| CoreApprovalsReviewer::AutoReview => ApprovalsReviewer::AutoReview, |
| } |
| } |
| } |
|
|
| #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] |
| #[serde(rename_all = "kebab-case")] |
| #[ts(rename_all = "kebab-case", export_to = "v2/")] |
| pub enum SandboxMode { |
| ReadOnly, |
| WorkspaceWrite, |
| DangerFullAccess, |
| } |
|
|
| impl SandboxMode { |
| pub fn to_core(self) -> CoreSandboxMode { |
| match self { |
| SandboxMode::ReadOnly => CoreSandboxMode::ReadOnly, |
| SandboxMode::WorkspaceWrite => CoreSandboxMode::WorkspaceWrite, |
| SandboxMode::DangerFullAccess => CoreSandboxMode::DangerFullAccess, |
| } |
| } |
| } |
|
|
| impl From<CoreSandboxMode> for SandboxMode { |
| fn from(value: CoreSandboxMode) -> Self { |
| match value { |
| CoreSandboxMode::ReadOnly => SandboxMode::ReadOnly, |
| CoreSandboxMode::WorkspaceWrite => SandboxMode::WorkspaceWrite, |
| CoreSandboxMode::DangerFullAccess => SandboxMode::DangerFullAccess, |
| } |
| } |
| } |
|
|