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;use schemars::JsonSchema;use schemars::r#gen::SchemaGenerator;use schemars::schema::InstanceType;use schemars::schema::Metadata;use schemars::schema::Schema;use schemars::schema::SchemaObject;use serde::Deserialize;use serde::Serialize;use serde_json::Value as JsonValue;use ts_rs::TS;// Macro to declare a camelCased API v2 enum mirroring a core enum which// tends to use either snake_case or kebab-case.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,}/// This translation layer make sure that we expose codex error code in camel case.////// When an upstream HTTP status is available (for example, from the Responses API or a provider),/// it is forwarded in `httpStatusCode` on the relevant `codexErrorInfo` variant.#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum CodexErrorInfo { ContextWindowExceeded, UsageLimitExceeded, ServerOverloaded, CyberPolicy, HttpConnectionFailed { #[serde(rename = "httpStatusCode")] #[ts(rename = "httpStatusCode")] http_status_code: Option<u16>, }, /// Failed to connect to the response SSE stream. ResponseStreamConnectionFailed { #[serde(rename = "httpStatusCode")] #[ts(rename = "httpStatusCode")] http_status_code: Option<u16>, }, InternalServerError, Unauthorized, BadRequest, ThreadRollbackFailed, SandboxError, /// The response SSE stream disconnected in the middle of a turn before completion. ResponseStreamDisconnected { #[serde(rename = "httpStatusCode")] #[ts(rename = "httpStatusCode")] http_status_code: Option<u16>, }, /// Reached the retry limit for responses. ResponseTooManyFailedAttempts { #[serde(rename = "httpStatusCode")] #[ts(rename = "httpStatusCode")] http_status_code: Option<u16>, }, /// Returned when `turn/start` or `turn/steer` is submitted while the current active turn /// cannot accept same-turn steering, for example `/review` or manual `/compact`. 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::UsageLimitExceeded => CodexErrorInfo::UsageLimitExceeded, CoreCodexErrorInfo::ServerOverloaded => CodexErrorInfo::ServerOverloaded, CoreCodexErrorInfo::CyberPolicy => CodexErrorInfo::CyberPolicy, 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, OnFailure, 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::OnFailure => CoreAskForApproval::OnFailure, 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::OnFailure => AskForApproval::OnFailure, 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/")]/// 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.pub enum ApprovalsReviewer { #[serde(rename = "user")] User, #[serde(rename = "auto_review", alias = "guardian_subagent")] AutoReview,}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.", ) }}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, } }}