diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 80e889a031..c1ab56b653 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -686,11 +686,11 @@ "chrono_0.4.43": "{\"dependencies\":[{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1.3.0\"},{\"name\":\"defmt\",\"optional\":true,\"req\":\"^1.0.1\"},{\"features\":[\"fallback\"],\"name\":\"iana-time-zone\",\"optional\":true,\"req\":\"^0.1.45\",\"target\":\"cfg(unix)\"},{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"default_features\":false,\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"name\":\"pure-rust-locales\",\"optional\":true,\"req\":\"^0.8.2\"},{\"default_features\":false,\"name\":\"rkyv\",\"optional\":true,\"req\":\"^0.7.43\"},{\"default_features\":false,\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.99\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"similar-asserts\",\"req\":\"^1.6.1\"},{\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"kind\":\"dev\",\"name\":\"windows-bindgen\",\"req\":\"^0.66\"},{\"name\":\"windows-link\",\"optional\":true,\"req\":\"^0.2\",\"target\":\"cfg(windows)\"}],\"features\":{\"__internal_bench\":[],\"alloc\":[],\"clock\":[\"winapi\",\"iana-time-zone\",\"now\"],\"core-error\":[],\"default\":[\"clock\",\"std\",\"oldtime\",\"wasmbind\"],\"defmt\":[\"dep:defmt\",\"pure-rust-locales?/defmt\"],\"libc\":[],\"now\":[\"std\"],\"oldtime\":[],\"rkyv\":[\"dep:rkyv\",\"rkyv/size_32\"],\"rkyv-16\":[\"dep:rkyv\",\"rkyv?/size_16\"],\"rkyv-32\":[\"dep:rkyv\",\"rkyv?/size_32\"],\"rkyv-64\":[\"dep:rkyv\",\"rkyv?/size_64\"],\"rkyv-validation\":[\"rkyv?/validation\"],\"std\":[\"alloc\"],\"unstable-locales\":[\"pure-rust-locales\"],\"wasmbind\":[\"wasm-bindgen\",\"js-sys\"],\"winapi\":[\"windows-link\"]}}", "chunked_transfer_1.5.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"}],\"features\":{}}", "cipher_0.4.4": "{\"dependencies\":[{\"name\":\"blobby\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"crypto-common\",\"req\":\"^0.1.6\"},{\"name\":\"inout\",\"req\":\"^0.1\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.5\"}],\"features\":{\"alloc\":[],\"block-padding\":[\"inout/block-padding\"],\"dev\":[\"blobby\"],\"rand_core\":[\"crypto-common/rand_core\"],\"std\":[\"alloc\",\"crypto-common/std\",\"inout/std\"]}}", - "clap_4.5.56": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.14\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"clap-cargo\",\"req\":\"^0.15.0\"},{\"default_features\":false,\"name\":\"clap_builder\",\"req\":\"=4.5.56\"},{\"name\":\"clap_derive\",\"optional\":true,\"req\":\"=4.5.55\"},{\"kind\":\"dev\",\"name\":\"jiff\",\"req\":\"^0.2.3\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.15\"},{\"kind\":\"dev\",\"name\":\"semver\",\"req\":\"^1.0.26\"},{\"kind\":\"dev\",\"name\":\"shlex\",\"req\":\"^1.3.0\"},{\"features\":[\"term-svg\"],\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.16\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.91\"},{\"default_features\":false,\"features\":[\"color-auto\",\"diff\",\"examples\"],\"kind\":\"dev\",\"name\":\"trycmd\",\"req\":\"^0.15.3\"}],\"features\":{\"cargo\":[\"clap_builder/cargo\"],\"color\":[\"clap_builder/color\"],\"debug\":[\"clap_builder/debug\",\"clap_derive?/debug\"],\"default\":[\"std\",\"color\",\"help\",\"usage\",\"error-context\",\"suggestions\"],\"deprecated\":[\"clap_builder/deprecated\",\"clap_derive?/deprecated\"],\"derive\":[\"dep:clap_derive\"],\"env\":[\"clap_builder/env\"],\"error-context\":[\"clap_builder/error-context\"],\"help\":[\"clap_builder/help\"],\"std\":[\"clap_builder/std\"],\"string\":[\"clap_builder/string\"],\"suggestions\":[\"clap_builder/suggestions\"],\"unicode\":[\"clap_builder/unicode\"],\"unstable-derive-ui-tests\":[],\"unstable-doc\":[\"clap_builder/unstable-doc\",\"derive\"],\"unstable-ext\":[\"clap_builder/unstable-ext\"],\"unstable-markdown\":[\"clap_derive/unstable-markdown\"],\"unstable-styles\":[\"clap_builder/unstable-styles\"],\"unstable-v5\":[\"clap_builder/unstable-v5\",\"clap_derive?/unstable-v5\",\"deprecated\"],\"usage\":[\"clap_builder/usage\"],\"wrap_help\":[\"clap_builder/wrap_help\"]}}", - "clap_builder_4.5.56": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.7\"},{\"name\":\"anstyle\",\"req\":\"^1.0.8\"},{\"name\":\"backtrace\",\"optional\":true,\"req\":\"^0.3.73\"},{\"name\":\"clap_lex\",\"req\":\"^0.7.4\"},{\"kind\":\"dev\",\"name\":\"color-print\",\"req\":\"^0.3.6\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.16\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"},{\"name\":\"strsim\",\"optional\":true,\"req\":\"^0.11.0\"},{\"name\":\"terminal_size\",\"optional\":true,\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"unic-emoji-char\",\"req\":\"^0.9.0\"},{\"name\":\"unicase\",\"optional\":true,\"req\":\"^2.6.0\"},{\"name\":\"unicode-width\",\"optional\":true,\"req\":\"^0.2.0\"}],\"features\":{\"cargo\":[],\"color\":[\"dep:anstream\"],\"debug\":[\"dep:backtrace\"],\"default\":[\"std\",\"color\",\"help\",\"usage\",\"error-context\",\"suggestions\"],\"deprecated\":[],\"env\":[],\"error-context\":[],\"help\":[],\"std\":[\"anstyle/std\"],\"string\":[],\"suggestions\":[\"dep:strsim\",\"error-context\"],\"unicode\":[\"dep:unicode-width\",\"dep:unicase\"],\"unstable-doc\":[\"cargo\",\"wrap_help\",\"env\",\"unicode\",\"string\",\"unstable-ext\"],\"unstable-ext\":[],\"unstable-styles\":[\"color\"],\"unstable-v5\":[\"deprecated\"],\"usage\":[],\"wrap_help\":[\"help\",\"dep:terminal_size\"]}}", + "clap_4.5.58": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.14\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"clap-cargo\",\"req\":\"^0.15.0\"},{\"default_features\":false,\"name\":\"clap_builder\",\"req\":\"=4.5.58\"},{\"name\":\"clap_derive\",\"optional\":true,\"req\":\"=4.5.55\"},{\"kind\":\"dev\",\"name\":\"jiff\",\"req\":\"^0.2.3\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.15\"},{\"kind\":\"dev\",\"name\":\"semver\",\"req\":\"^1.0.26\"},{\"kind\":\"dev\",\"name\":\"shlex\",\"req\":\"^1.3.0\"},{\"features\":[\"term-svg\"],\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.16\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.91\"},{\"default_features\":false,\"features\":[\"color-auto\",\"diff\",\"examples\"],\"kind\":\"dev\",\"name\":\"trycmd\",\"req\":\"^0.15.3\"}],\"features\":{\"cargo\":[\"clap_builder/cargo\"],\"color\":[\"clap_builder/color\"],\"debug\":[\"clap_builder/debug\",\"clap_derive?/debug\"],\"default\":[\"std\",\"color\",\"help\",\"usage\",\"error-context\",\"suggestions\"],\"deprecated\":[\"clap_builder/deprecated\",\"clap_derive?/deprecated\"],\"derive\":[\"dep:clap_derive\"],\"env\":[\"clap_builder/env\"],\"error-context\":[\"clap_builder/error-context\"],\"help\":[\"clap_builder/help\"],\"std\":[\"clap_builder/std\"],\"string\":[\"clap_builder/string\"],\"suggestions\":[\"clap_builder/suggestions\"],\"unicode\":[\"clap_builder/unicode\"],\"unstable-derive-ui-tests\":[],\"unstable-doc\":[\"clap_builder/unstable-doc\",\"derive\"],\"unstable-ext\":[\"clap_builder/unstable-ext\"],\"unstable-markdown\":[\"clap_derive/unstable-markdown\"],\"unstable-styles\":[\"clap_builder/unstable-styles\"],\"unstable-v5\":[\"clap_builder/unstable-v5\",\"clap_derive?/unstable-v5\",\"deprecated\"],\"usage\":[\"clap_builder/usage\"],\"wrap_help\":[\"clap_builder/wrap_help\"]}}", + "clap_builder_4.5.58": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.7\"},{\"name\":\"anstyle\",\"req\":\"^1.0.8\"},{\"name\":\"backtrace\",\"optional\":true,\"req\":\"^0.3.73\"},{\"name\":\"clap_lex\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"color-print\",\"req\":\"^0.3.6\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.16\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"},{\"name\":\"strsim\",\"optional\":true,\"req\":\"^0.11.0\"},{\"name\":\"terminal_size\",\"optional\":true,\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"unic-emoji-char\",\"req\":\"^0.9.0\"},{\"name\":\"unicase\",\"optional\":true,\"req\":\"^2.6.0\"},{\"name\":\"unicode-width\",\"optional\":true,\"req\":\"^0.2.0\"}],\"features\":{\"cargo\":[],\"color\":[\"dep:anstream\"],\"debug\":[\"dep:backtrace\"],\"default\":[\"std\",\"color\",\"help\",\"usage\",\"error-context\",\"suggestions\"],\"deprecated\":[],\"env\":[],\"error-context\":[],\"help\":[],\"std\":[\"anstyle/std\"],\"string\":[],\"suggestions\":[\"dep:strsim\",\"error-context\"],\"unicode\":[\"dep:unicode-width\",\"dep:unicase\"],\"unstable-doc\":[\"cargo\",\"wrap_help\",\"env\",\"unicode\",\"string\",\"unstable-ext\"],\"unstable-ext\":[],\"unstable-styles\":[\"color\"],\"unstable-v5\":[\"deprecated\"],\"usage\":[],\"wrap_help\":[\"help\",\"dep:terminal_size\"]}}", "clap_complete_4.5.65": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.14\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"clap\",\"req\":\"^4.5.20\"},{\"default_features\":false,\"features\":[\"std\",\"derive\",\"help\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.5.20\"},{\"name\":\"clap_lex\",\"optional\":true,\"req\":\"^0.7.0\"},{\"name\":\"completest\",\"optional\":true,\"req\":\"^0.4.2\"},{\"name\":\"completest-pty\",\"optional\":true,\"req\":\"^0.5.5\"},{\"name\":\"is_executable\",\"optional\":true,\"req\":\"^1.0.1\"},{\"name\":\"shlex\",\"optional\":true,\"req\":\"^1.3.0\"},{\"features\":[\"diff\",\"dir\",\"examples\"],\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.0\"},{\"default_features\":false,\"features\":[\"color-auto\",\"diff\",\"examples\"],\"kind\":\"dev\",\"name\":\"trycmd\",\"req\":\"^0.15.1\"}],\"features\":{\"debug\":[\"clap/debug\"],\"default\":[],\"unstable-doc\":[\"unstable-dynamic\"],\"unstable-dynamic\":[\"dep:clap_lex\",\"dep:shlex\",\"dep:is_executable\",\"clap/unstable-ext\"],\"unstable-shell-tests\":[\"dep:completest\",\"dep:completest-pty\"]}}", "clap_derive_4.5.55": "{\"dependencies\":[{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.10\"},{\"name\":\"heck\",\"req\":\"^0.5.0\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0.69\"},{\"default_features\":false,\"name\":\"pulldown-cmark\",\"optional\":true,\"req\":\"^0.13.0\"},{\"name\":\"quote\",\"req\":\"^1.0.9\"},{\"features\":[\"full\"],\"name\":\"syn\",\"req\":\"^2.0.8\"}],\"features\":{\"debug\":[],\"default\":[],\"deprecated\":[],\"raw-deprecated\":[\"deprecated\"],\"unstable-markdown\":[\"dep:pulldown-cmark\",\"dep:anstyle\"],\"unstable-v5\":[\"deprecated\"]}}", - "clap_lex_0.7.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.14\"}],\"features\":{}}", + "clap_lex_1.0.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.14\"}],\"features\":{}}", "clipboard-win_5.4.1": "{\"dependencies\":[{\"name\":\"error-code\",\"req\":\"^3\",\"target\":\"cfg(windows)\"},{\"name\":\"windows-win\",\"optional\":true,\"req\":\"^3\",\"target\":\"cfg(windows)\"}],\"features\":{\"monitor\":[\"windows-win\"],\"std\":[\"error-code/std\"]}}", "cmake_0.1.57": "{\"dependencies\":[{\"name\":\"cc\",\"req\":\"^1.2.46\"}],\"features\":{}}", "cmp_any_0.8.1": "{\"dependencies\":[],\"features\":{}}", @@ -790,9 +790,9 @@ "enumflags2_0.7.12": "{\"dependencies\":[{\"name\":\"enumflags2_derive\",\"req\":\"=0.7.12\"},{\"default_features\":false,\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.0\"}],\"features\":{\"std\":[]}}", "enumflags2_derive_0.7.12": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"parsing\",\"printing\",\"derive\",\"proc-macro\"],\"name\":\"syn\",\"req\":\"^2.0\"}],\"features\":{}}", "env-flags_0.1.1": "{\"dependencies\":[],\"features\":{}}", - "env_filter_0.1.4": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"log\",\"req\":\"^0.4.8\"},{\"default_features\":false,\"features\":[\"std\",\"perf\"],\"name\":\"regex\",\"optional\":true,\"req\":\"^1.0.3\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6\"}],\"features\":{\"default\":[\"regex\"],\"regex\":[\"dep:regex\"]}}", + "env_filter_1.0.0": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"log\",\"req\":\"^0.4.8\"},{\"default_features\":false,\"features\":[\"std\",\"perf\"],\"name\":\"regex\",\"optional\":true,\"req\":\"^1.0.3\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6\"}],\"features\":{\"default\":[\"regex\"],\"regex\":[\"dep:regex\"]}}", "env_home_0.1.0": "{\"dependencies\":[],\"features\":{}}", - "env_logger_0.11.8": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"wincon\"],\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.11\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.6\"},{\"default_features\":false,\"name\":\"env_filter\",\"req\":\"^0.1.0\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"jiff\",\"optional\":true,\"req\":\"^0.2.3\"},{\"features\":[\"std\"],\"name\":\"log\",\"req\":\"^0.4.21\"}],\"features\":{\"auto-color\":[\"color\",\"anstream/auto\"],\"color\":[\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"auto-color\",\"humantime\",\"regex\"],\"humantime\":[\"dep:jiff\"],\"kv\":[\"log/kv\"],\"regex\":[\"env_filter/regex\"],\"unstable-kv\":[\"kv\"]}}", + "env_logger_0.11.9": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"wincon\"],\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.11\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.6\"},{\"default_features\":false,\"name\":\"env_filter\",\"req\":\"^1.0.0\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"jiff\",\"optional\":true,\"req\":\"^0.2.3\"},{\"features\":[\"std\"],\"name\":\"log\",\"req\":\"^0.4.21\"}],\"features\":{\"auto-color\":[\"color\",\"anstream/auto\"],\"color\":[\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"auto-color\",\"humantime\",\"regex\"],\"humantime\":[\"dep:jiff\"],\"kv\":[\"log/kv\"],\"regex\":[\"env_filter/regex\"],\"unstable-kv\":[\"kv\"]}}", "equivalent_1.0.2": "{\"dependencies\":[],\"features\":{}}", "erased-serde_0.3.31": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.13\"},{\"default_features\":false,\"name\":\"serde\",\"req\":\"^1.0.166\"},{\"kind\":\"dev\",\"name\":\"serde_cbor\",\"req\":\"^0.11.2\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.166\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.99\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.83\"}],\"features\":{\"alloc\":[\"serde/alloc\"],\"default\":[\"std\"],\"std\":[\"serde/std\"],\"unstable-debug\":[]}}", "errno_0.3.14": "{\"dependencies\":[{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(target_os=\\\"hermit\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(target_os=\\\"wasi\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_Diagnostics_Debug\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"std\"],\"std\":[\"libc/std\"]}}", diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index 64e5d2c682..96b5e34e07 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -830,7 +830,6 @@ mod tests { use codex_protocol::ThreadId; use codex_protocol::account::PlanType; use codex_protocol::parse_command::ParsedCommand; - use codex_protocol::protocol::AskForApproval; use pretty_assertions::assert_eq; use serde_json::json; use std::path::PathBuf; @@ -844,7 +843,7 @@ mod tests { model_provider: None, profile: None, cwd: None, - approval_policy: Some(AskForApproval::OnRequest), + approval_policy: Some(v1::AskForApprovalProtocolV1::OnRequest), sandbox: None, config: None, base_instructions: None, diff --git a/codex-rs/app-server-protocol/src/protocol/v1.rs b/codex-rs/app-server-protocol/src/protocol/v1.rs index 25e60ca751..86a885cb1c 100644 --- a/codex-rs/app-server-protocol/src/protocol/v1.rs +++ b/codex-rs/app-server-protocol/src/protocol/v1.rs @@ -9,7 +9,7 @@ use codex_protocol::config_types::Verbosity; use codex_protocol::models::ResponseItem; use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::parse_command::ParsedCommand; -use codex_protocol::protocol::AskForApproval; +use codex_protocol::protocol::AskForApproval as CoreAskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::FileChange; use codex_protocol::protocol::ReviewDecision; @@ -71,7 +71,7 @@ pub struct NewConversationParams { pub model_provider: Option, pub profile: Option, pub cwd: Option, - pub approval_policy: Option, + pub approval_policy: Option, pub sandbox: Option, pub config: Option>, pub base_instructions: Option, @@ -358,7 +358,7 @@ pub struct SetDefaultModelResponse {} #[derive(Deserialize, Debug, Clone, PartialEq, Serialize, JsonSchema, TS)] #[serde(rename_all = "camelCase")] pub struct UserSavedConfig { - pub approval_policy: Option, + pub approval_policy: Option, pub sandbox_mode: Option, pub sandbox_settings: Option, pub forced_chatgpt_workspace_id: Option, @@ -377,7 +377,7 @@ pub struct UserSavedConfig { pub struct Profile { pub model: Option, pub model_provider: Option, - pub approval_policy: Option, + pub approval_policy: Option, pub model_reasoning_effort: Option, pub model_reasoning_summary: Option, pub model_verbosity: Option, @@ -414,7 +414,7 @@ pub struct SendUserTurnParams { pub conversation_id: ThreadId, pub items: Vec, pub cwd: PathBuf, - pub approval_policy: AskForApproval, + pub approval_policy: AskForApprovalProtocolV1, pub sandbox_policy: SandboxPolicy, pub model: String, pub effort: Option, @@ -529,6 +529,53 @@ impl From for CoreTextElement { } } +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "kebab-case")] +pub enum AskForApprovalProtocolV1 { + /// Under this policy, only "known safe" commands—those matching + /// `is_safe_command()` and performing read-only file operations—are + /// auto-approved. Everything else will ask the user to approve. + #[serde(rename = "untrusted")] + UnlessTrusted, + + /// DEPRECATED: *All* commands are auto-approved, but they are expected to + /// run inside a sandbox where network access is disabled and writes are + /// confined to a specific set of paths. If the command fails, it will be + /// escalated to the user to approve execution without a sandbox. + /// Prefer `on-request` for interactive runs or `never` for non-interactive + /// runs. + OnFailure, + + /// The model decides when to ask the user for approval. + OnRequest, + + /// Never ask the user to approve commands. Failures are immediately returned + /// to the model, and never escalated to the user for approval. + Never, +} + +impl AskForApprovalProtocolV1 { + pub fn to_core(self) -> CoreAskForApproval { + match self { + AskForApprovalProtocolV1::UnlessTrusted => CoreAskForApproval::UnlessTrusted, + AskForApprovalProtocolV1::OnFailure => CoreAskForApproval::OnFailure, + AskForApprovalProtocolV1::OnRequest => CoreAskForApproval::OnRequest, + AskForApprovalProtocolV1::Never => CoreAskForApproval::Never, + } + } +} + +impl From for AskForApprovalProtocolV1 { + fn from(value: CoreAskForApproval) -> Self { + match value { + CoreAskForApproval::UnlessTrusted => AskForApprovalProtocolV1::UnlessTrusted, + CoreAskForApproval::OnFailure => AskForApprovalProtocolV1::OnFailure, + CoreAskForApproval::OnRequest => AskForApprovalProtocolV1::OnRequest, + CoreAskForApproval::Never => AskForApprovalProtocolV1::Never, + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] /// Deprecated in favor of AccountLoginCompletedNotification. diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 5a6a246a3d..960bc8bf74 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -24,7 +24,7 @@ use codex_app_server_protocol::AppsListParams; use codex_app_server_protocol::AppsListResponse; use codex_app_server_protocol::ArchiveConversationParams; use codex_app_server_protocol::ArchiveConversationResponse; -use codex_app_server_protocol::AskForApproval; +use codex_app_server_protocol::AskForApprovalProtocolV1 as V1AskForApproval; use codex_app_server_protocol::AuthMode; use codex_app_server_protocol::AuthStatusChangeNotification; use codex_app_server_protocol::CancelLoginAccountParams; @@ -225,6 +225,7 @@ use codex_protocol::config_types::CollaborationMode; use codex_protocol::config_types::ForcedLoginMethod; use codex_protocol::config_types::Personality; use codex_protocol::config_types::WindowsSandboxLevel; +use codex_protocol::protocol::AskForApproval; use codex_protocol::dynamic_tools::DynamicToolSpec as CoreDynamicToolSpec; use codex_protocol::items::TurnItem; use codex_protocol::models::ResponseItem; @@ -1831,7 +1832,7 @@ impl CodexMessageProcessor { model, config_profile: profile, cwd: cwd.clone().map(PathBuf::from), - approval_policy, + approval_policy: approval_policy.map(V1AskForApproval::to_core), sandbox_mode, model_provider, codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), @@ -1941,7 +1942,7 @@ impl CodexMessageProcessor { model, model_provider, cwd, - approval_policy, + approval_policy.map(|policy| policy.to_core()), sandbox, base_instructions, developer_instructions, @@ -2064,7 +2065,7 @@ impl CodexMessageProcessor { model: Option, model_provider: Option, cwd: Option, - approval_policy: Option, + approval_policy: Option, sandbox: Option, base_instructions: Option, developer_instructions: Option, @@ -2074,8 +2075,7 @@ impl CodexMessageProcessor { model, model_provider, cwd: cwd.map(PathBuf::from), - approval_policy: approval_policy - .map(codex_app_server_protocol::AskForApproval::to_core), + approval_policy, sandbox_mode: sandbox.map(SandboxMode::to_core), codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), base_instructions, @@ -2781,7 +2781,7 @@ impl CodexMessageProcessor { model, model_provider, cwd, - approval_policy, + approval_policy.map(|policy| policy.to_core()), sandbox, base_instructions, developer_instructions, @@ -3248,7 +3248,7 @@ impl CodexMessageProcessor { model, model_provider, cwd, - approval_policy, + approval_policy.map(|policy| policy.to_core()), sandbox, base_instructions, developer_instructions, @@ -4198,7 +4198,7 @@ impl CodexMessageProcessor { model, config_profile: profile, cwd: cwd.map(PathBuf::from), - approval_policy, + approval_policy: approval_policy.map(V1AskForApproval::to_core), sandbox_mode, model_provider, codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), @@ -4393,7 +4393,7 @@ impl CodexMessageProcessor { model, config_profile: profile, cwd: cwd.map(PathBuf::from), - approval_policy, + approval_policy: approval_policy.map(V1AskForApproval::to_core), sandbox_mode, model_provider, codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), @@ -4767,7 +4767,7 @@ impl CodexMessageProcessor { .submit(Op::UserTurn { items: mapped_items, cwd, - approval_policy, + approval_policy: approval_policy.to_core(), sandbox_policy, model, effort, @@ -5252,7 +5252,7 @@ impl CodexMessageProcessor { let _ = thread .submit(Op::OverrideTurnContext { cwd: params.cwd, - approval_policy: params.approval_policy.map(AskForApproval::to_core), + approval_policy: params.approval_policy.map(|policy| policy.to_core()), sandbox_policy: params.sandbox_policy.map(|p| p.to_core()), windows_sandbox_level: None, model: params.model, @@ -6098,7 +6098,7 @@ fn collect_resume_override_mismatches( } if let Some(requested_approval) = request.approval_policy.as_ref() { let active_approval: AskForApproval = config_snapshot.approval_policy.into(); - if requested_approval != &active_approval { + if *requested_approval != active_approval.into() { mismatch_details.push(format!( "approval_policy requested={requested_approval:?} active={active_approval:?}" )); diff --git a/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs b/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs index 863a7bfc4f..305d27aec0 100644 --- a/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs +++ b/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs @@ -7,6 +7,7 @@ use app_test_support::format_with_current_shell; use app_test_support::to_response; use codex_app_server_protocol::AddConversationListenerParams; use codex_app_server_protocol::AddConversationSubscriptionResponse; +use codex_app_server_protocol::AskForApprovalProtocolV1; use codex_app_server_protocol::ExecCommandApprovalParams; use codex_app_server_protocol::InputItem; use codex_app_server_protocol::JSONRPCNotification; @@ -21,7 +22,6 @@ use codex_app_server_protocol::SendUserMessageResponse; use codex_app_server_protocol::SendUserTurnParams; use codex_app_server_protocol::SendUserTurnResponse; use codex_app_server_protocol::ServerRequest; -use codex_core::protocol::AskForApproval; use codex_core::protocol::SandboxPolicy; use codex_core::protocol_config_types::ReasoningSummary; use codex_core::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR; @@ -331,7 +331,7 @@ async fn test_send_user_turn_changes_approval_policy_behavior() -> Result<()> { text_elements: Vec::new(), }], cwd: working_directory.clone(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::new_read_only_policy(), model: "mock-model".to_string(), effort: Some(ReasoningEffort::Medium), @@ -405,7 +405,7 @@ async fn test_send_user_turn_updates_sandbox_and_cwd_between_turns() -> Result<( let new_conv_id = mcp .send_new_conversation_request(NewConversationParams { cwd: Some(first_cwd.to_string_lossy().into_owned()), - approval_policy: Some(AskForApproval::Never), + approval_policy: Some(AskForApprovalProtocolV1::Never), sandbox: Some(SandboxMode::WorkspaceWrite), ..Default::default() }) @@ -441,7 +441,7 @@ async fn test_send_user_turn_updates_sandbox_and_cwd_between_turns() -> Result<( text_elements: Vec::new(), }], cwd: first_cwd.clone(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::WorkspaceWrite { writable_roots: vec![first_cwd.try_into()?], read_only_access: Default::default(), @@ -475,7 +475,7 @@ async fn test_send_user_turn_updates_sandbox_and_cwd_between_turns() -> Result<( text_elements: Vec::new(), }], cwd: second_cwd.clone(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::DangerFullAccess, model: model.clone(), effort: Some(ReasoningEffort::Medium), diff --git a/codex-rs/app-server/tests/suite/config.rs b/codex-rs/app-server/tests/suite/config.rs index 84b268a3c2..fa4702368e 100644 --- a/codex-rs/app-server/tests/suite/config.rs +++ b/codex-rs/app-server/tests/suite/config.rs @@ -9,7 +9,7 @@ use codex_app_server_protocol::RequestId; use codex_app_server_protocol::SandboxSettings; use codex_app_server_protocol::Tools; use codex_app_server_protocol::UserSavedConfig; -use codex_core::protocol::AskForApproval; +use codex_app_server_protocol::AskForApprovalProtocolV1; use codex_protocol::config_types::ForcedLoginMethod; use codex_protocol::config_types::ReasoningSummary; use codex_protocol::config_types::SandboxMode; @@ -83,7 +83,7 @@ async fn get_config_toml_parses_all_fields() -> Result<()> { let writable_root = test_tmp_path(); let expected = GetUserSavedConfigResponse { config: UserSavedConfig { - approval_policy: Some(AskForApproval::OnRequest), + approval_policy: Some(AskForApprovalProtocolV1::OnRequest), sandbox_mode: Some(SandboxMode::WorkspaceWrite), sandbox_settings: Some(SandboxSettings { writable_roots: vec![writable_root], @@ -106,7 +106,7 @@ async fn get_config_toml_parses_all_fields() -> Result<()> { "test".into(), Profile { model: Some("gpt-4o".into()), - approval_policy: Some(AskForApproval::OnRequest), + approval_policy: Some(AskForApprovalProtocolV1::OnRequest), model_reasoning_effort: Some(ReasoningEffort::High), model_reasoning_summary: Some(ReasoningSummary::Detailed), model_verbosity: Some(Verbosity::Medium), diff --git a/codex-rs/app-server/tests/suite/output_schema.rs b/codex-rs/app-server/tests/suite/output_schema.rs index c120a7fe2d..0ccb528a46 100644 --- a/codex-rs/app-server/tests/suite/output_schema.rs +++ b/codex-rs/app-server/tests/suite/output_schema.rs @@ -9,7 +9,7 @@ use codex_app_server_protocol::NewConversationResponse; use codex_app_server_protocol::RequestId; use codex_app_server_protocol::SendUserTurnParams; use codex_app_server_protocol::SendUserTurnResponse; -use codex_core::protocol::AskForApproval; +use codex_app_server_protocol::AskForApprovalProtocolV1; use codex_core::protocol::SandboxPolicy; use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::ReasoningEffort; @@ -83,7 +83,7 @@ async fn send_user_turn_accepts_output_schema_v1() -> Result<()> { text_elements: Vec::new(), }], cwd: codex_home.path().to_path_buf(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::new_read_only_policy(), model: "mock-model".to_string(), effort: Some(ReasoningEffort::Medium), @@ -185,7 +185,7 @@ async fn send_user_turn_output_schema_is_per_turn_v1() -> Result<()> { text_elements: Vec::new(), }], cwd: codex_home.path().to_path_buf(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::new_read_only_policy(), model: "mock-model".to_string(), effort: Some(ReasoningEffort::Medium), @@ -233,7 +233,7 @@ async fn send_user_turn_output_schema_is_per_turn_v1() -> Result<()> { text_elements: Vec::new(), }], cwd: codex_home.path().to_path_buf(), - approval_policy: AskForApproval::Never, + approval_policy: AskForApprovalProtocolV1::Never, sandbox_policy: SandboxPolicy::new_read_only_policy(), model: "mock-model".to_string(), effort: Some(ReasoningEffort::Medium), diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 9874cc2774..04553e612b 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -893,7 +893,7 @@ pub struct ConfigToml { pub model_auto_compact_token_limit: Option, /// Default approval policy for executing commands. - pub approval_policy: Option, + pub approval_policy: Option, #[serde(default)] pub shell_environment_policy: ShellEnvironmentPolicyToml, @@ -1113,7 +1113,9 @@ impl From for UserSavedConfig { .collect(); Self { - approval_policy: config_toml.approval_policy, + approval_policy: config_toml + .approval_policy + .and_then(|approval_policy| Some(approval_policy.to_core()).map(Into::into)), sandbox_mode: config_toml.sandbox_mode, sandbox_settings: config_toml.sandbox_workspace_write.map(From::from), forced_chatgpt_workspace_id: config_toml.forced_chatgpt_workspace_id, @@ -1129,6 +1131,71 @@ impl From for UserSavedConfig { } } +#[derive( + Debug, + Clone, + Copy, + Default, + PartialEq, + Eq, + Hash, + Serialize, + Deserialize, + JsonSchema, +)] +#[serde(rename_all = "kebab-case")] +pub enum AskForApprovalToml { + /// Under this policy, only "known safe" commands—those matching + /// `is_safe_command()` and performing read-only file operations—are + /// auto-approved. Everything else will ask the user to approve. + #[serde(rename = "untrusted")] + UnlessTrusted, + + /// DEPRECATED: *All* commands are auto-approved, but they are expected to + /// run inside a sandbox where network access is disabled and writes are + /// confined to a specific set of paths. If the command fails, it will be + /// escalated to the user to approve execution without a sandbox. + /// Prefer `OnRequest` for interactive runs or `Never` for non-interactive + /// runs. + OnFailure, + + /// The model decides when to ask the user for approval. + #[default] + OnRequest, + + /// Never ask the user to approve commands. Failures are immediately returned + /// to the model, and never escalated to the user for approval. + Never, +} + +impl AskForApprovalToml { + pub fn to_core(self) -> AskForApproval { + match self { + AskForApprovalToml::UnlessTrusted => AskForApproval::UnlessTrusted, + AskForApprovalToml::OnFailure => AskForApproval::OnFailure, + AskForApprovalToml::OnRequest => AskForApproval::OnRequest, + AskForApprovalToml::Never => AskForApproval::Never, + } + } +} + +impl From for AskForApprovalToml { + fn from(value: AskForApproval) -> Self { + match value { + AskForApproval::UnlessTrusted => AskForApprovalToml::UnlessTrusted, + AskForApproval::OnFailure => AskForApprovalToml::OnFailure, + AskForApproval::OnRequest => AskForApprovalToml::OnRequest, + AskForApproval::Never => AskForApprovalToml::Never, + } + } +} + +impl From for AskForApproval { + fn from(value: AskForApprovalToml) -> Self { + value.to_core() + } +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)] #[schemars(deny_unknown_fields)] pub struct ProjectConfig { @@ -1570,8 +1637,8 @@ impl Config { || config_profile.approval_policy.is_some() || cfg.approval_policy.is_some(); let mut approval_policy = approval_policy_override - .or(config_profile.approval_policy) - .or(cfg.approval_policy) + .or_else(|| config_profile.approval_policy.map(AskForApprovalToml::to_core)) + .or_else(|| cfg.approval_policy.map(AskForApprovalToml::to_core)) .unwrap_or_else(|| { if active_project.is_trusted() { AskForApproval::OnRequest diff --git a/codex-rs/core/src/config/profile.rs b/codex-rs/core/src/config/profile.rs index ff343cbf53..0d433f67e3 100644 --- a/codex-rs/core/src/config/profile.rs +++ b/codex-rs/core/src/config/profile.rs @@ -5,7 +5,7 @@ use serde::Serialize; use crate::config::types::Personality; use crate::config::types::WindowsToml; -use crate::protocol::AskForApproval; +use crate::config::AskForApprovalToml; use codex_protocol::config_types::ReasoningSummary; use codex_protocol::config_types::SandboxMode; use codex_protocol::config_types::Verbosity; @@ -21,7 +21,7 @@ pub struct ConfigProfile { /// The key in the `model_providers` map identifying the /// [`ModelProviderInfo`] to use. pub model_provider: Option, - pub approval_policy: Option, + pub approval_policy: Option, pub sandbox_mode: Option, pub model_reasoning_effort: Option, pub model_reasoning_summary: Option, @@ -57,7 +57,9 @@ impl From for codex_app_server_protocol::Profile { Self { model: config_profile.model, model_provider: config_profile.model_provider, - approval_policy: config_profile.approval_policy, + approval_policy: config_profile + .approval_policy + .map(|approval_policy| approval_policy.to_core().into()), model_reasoning_effort: config_profile.model_reasoning_effort, model_reasoning_summary: config_profile.model_reasoning_summary, model_verbosity: config_profile.model_verbosity,