mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[ez][codex-rs] Support approvals reviewer in app defaults (#27075)
[from codex] ## Summary - add `approvals_reviewer` support to `[apps._default]` - resolve connected-app reviewers in per-app, app-default, then global order - expose the setting through the v2 config API and regenerate schema fixtures ## Context PR #25167 added `apps.<connector_id>.approvals_reviewer`, but the shared app defaults table could not specify the reviewer. This extends the same behavior to `[apps._default]` while preserving per-app overrides. Managed `allowed_approvals_reviewers` requirements still constrain both default and per-app values. A disallowed app value falls back to the global reviewer, and non-app MCP servers continue using the global reviewer. ## Testing - `just write-config-schema` - `just write-app-server-schema` - `just fmt` - `just test -p codex-config` - `just test -p codex-core app_approvals_reviewer` - `just test -p codex-app-server-protocol` - `just test -p codex-app-server config_read_includes_apps`
This commit is contained in:
@@ -1775,13 +1775,18 @@ The server also emits `app/list/updated` notifications whenever either source (a
|
||||
```
|
||||
|
||||
Connected apps may override the thread's approval reviewer in `config.toml`.
|
||||
When omitted, the app inherits the top-level `approvals_reviewer` value:
|
||||
Use `apps._default.approvals_reviewer` to set the reviewer for all apps, and a
|
||||
per-app value to override that default. When both are omitted, the app inherits
|
||||
the top-level `approvals_reviewer` value:
|
||||
|
||||
```toml
|
||||
approvals_reviewer = "auto_review"
|
||||
|
||||
[apps.demo-app]
|
||||
[apps._default]
|
||||
approvals_reviewer = "user"
|
||||
|
||||
[apps.demo-app]
|
||||
approvals_reviewer = "auto_review"
|
||||
```
|
||||
|
||||
Setting the app value to `"user"` routes its approval prompts to the user
|
||||
|
||||
@@ -7,6 +7,7 @@ use codex_app_server_protocol::AppConfig;
|
||||
use codex_app_server_protocol::AppToolApproval;
|
||||
use codex_app_server_protocol::ApprovalsReviewer;
|
||||
use codex_app_server_protocol::AppsConfig;
|
||||
use codex_app_server_protocol::AppsDefaultConfig;
|
||||
use codex_app_server_protocol::AskForApproval;
|
||||
use codex_app_server_protocol::ConfigBatchWriteParams;
|
||||
use codex_app_server_protocol::ConfigEdit;
|
||||
@@ -332,6 +333,9 @@ async fn config_read_includes_apps() -> Result<()> {
|
||||
write_config(
|
||||
&codex_home,
|
||||
r#"
|
||||
[apps._default]
|
||||
approvals_reviewer = "auto_review"
|
||||
|
||||
[apps.app1]
|
||||
enabled = false
|
||||
approvals_reviewer = "user"
|
||||
@@ -365,7 +369,12 @@ default_tools_approval_mode = "prompt"
|
||||
assert_eq!(
|
||||
config.apps,
|
||||
Some(AppsConfig {
|
||||
default: None,
|
||||
default: Some(AppsDefaultConfig {
|
||||
enabled: true,
|
||||
approvals_reviewer: Some(ApprovalsReviewer::AutoReview),
|
||||
destructive_enabled: true,
|
||||
open_world_enabled: true,
|
||||
}),
|
||||
apps: std::collections::HashMap::from([(
|
||||
"app1".to_string(),
|
||||
AppConfig {
|
||||
@@ -380,6 +389,16 @@ default_tools_approval_mode = "prompt"
|
||||
)]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
origins
|
||||
.get("apps._default.approvals_reviewer")
|
||||
.expect("origin")
|
||||
.name,
|
||||
ConfigLayerSource::User {
|
||||
file: user_file.clone(),
|
||||
profile: None,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
origins.get("apps.app1.enabled").expect("origin").name,
|
||||
ConfigLayerSource::User {
|
||||
|
||||
Reference in New Issue
Block a user