Compare commits

...

1 Commits

Author SHA1 Message Date
won
5f56cf7c37 Support auto_review compatibility 2026-04-22 23:31:59 -07:00
8 changed files with 55 additions and 3 deletions

View File

@@ -351,6 +351,9 @@
"apps": {
"type": "boolean"
},
"auto_review": {
"type": "boolean"
},
"browser_use": {
"type": "boolean"
},
@@ -2508,6 +2511,9 @@
"apps": {
"type": "boolean"
},
"auto_review": {
"type": "boolean"
},
"browser_use": {
"type": "boolean"
},

View File

@@ -6610,6 +6610,27 @@ async fn feature_requirements_normalize_effective_feature_values() -> std::io::R
Ok(())
}
#[tokio::test]
async fn feature_requirements_accept_auto_review_alias() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let config = ConfigBuilder::without_managed_config_for_tests()
.codex_home(codex_home.path().to_path_buf())
.cloud_requirements(CloudRequirementsLoader::new(async {
Ok(Some(crate::config_loader::ConfigRequirementsToml {
feature_requirements: Some(crate::config_loader::FeatureRequirementsToml {
entries: BTreeMap::from([("auto_review".to_string(), false)]),
}),
..Default::default()
}))
}))
.build()
.await?;
assert!(!config.features.enabled(Feature::GuardianApproval));
Ok(())
}
#[tokio::test]
async fn browser_feature_requirements_are_valid() -> std::io::Result<()> {
let codex_home = TempDir::new()?;

View File

@@ -204,6 +204,11 @@ fn parse_feature_requirements(
continue;
}
if key == "auto_review" {
pinned_features.insert(Feature::GuardianApproval, enabled);
continue;
}
if let Some(feature) = feature_for_key(&key) {
push_feature_requirement_warning(
&mut startup_warnings,

View File

@@ -49,6 +49,10 @@ const ALIASES: &[Alias] = &[
legacy_key: "telepathy",
feature: Feature::Chronicle,
},
Alias {
legacy_key: "auto_review",
feature: Feature::GuardianApproval,
},
];
pub fn legacy_feature_keys() -> impl Iterator<Item = &'static str> {

View File

@@ -90,8 +90,13 @@ fn code_mode_only_requires_code_mode() {
fn guardian_approval_is_stable_and_enabled_by_default() {
let spec = Feature::GuardianApproval.info();
assert_eq!(spec.key, "guardian_approval");
assert_eq!(spec.stage, Stage::Stable);
assert_eq!(Feature::GuardianApproval.default_enabled(), true);
assert_eq!(
feature_for_key("auto_review"),
Some(Feature::GuardianApproval)
);
}
#[test]

View File

@@ -108,6 +108,7 @@ mod tests {
approval_policy: AskForApproval::Never,
approvals_reviewer: ApprovalsReviewer::User,
sandbox_policy: SandboxPolicy::new_read_only_policy(),
permission_profile: None,
cwd: cwd.abs(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
@@ -155,7 +156,7 @@ mod tests {
.insert(side_thread_id, SideThreadState::new(main_thread_id));
app.config.permissions.approval_policy =
codex_config::Constrained::allow_any(AskForApproval::OnRequest);
app.config.approvals_reviewer = ApprovalsReviewer::GuardianSubagent;
app.config.approvals_reviewer = ApprovalsReviewer::AutoReview;
app.config.permissions.sandbox_policy =
codex_config::Constrained::allow_any(SandboxPolicy::new_workspace_write_policy());
@@ -164,7 +165,7 @@ mod tests {
let expected_main_session = ThreadSessionState {
approval_policy: AskForApproval::OnRequest,
approvals_reviewer: ApprovalsReviewer::GuardianSubagent,
approvals_reviewer: ApprovalsReviewer::AutoReview,
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
..main_session
};

View File

@@ -146,6 +146,7 @@ class AppToolsConfig(BaseModel):
class ApprovalsReviewer(Enum):
user = "user"
auto_review = "auto_review"
guardian_subagent = "guardian_subagent"

View File

@@ -4,7 +4,11 @@ from pathlib import Path
from typing import Any
from codex_app_server.client import AppServerClient, _params_dict
from codex_app_server.generated.v2_all import ThreadListParams, ThreadTokenUsageUpdatedNotification
from codex_app_server.generated.v2_all import (
ApprovalsReviewer,
ThreadListParams,
ThreadTokenUsageUpdatedNotification,
)
from codex_app_server.models import UnknownNotification
ROOT = Path(__file__).resolve().parents[1]
@@ -40,6 +44,11 @@ def test_generated_v2_bundle_has_single_shared_plan_type_definition() -> None:
assert source.count("class PlanType(") == 1
def test_approvals_reviewer_exposes_auto_review_and_legacy_guardian_value() -> None:
assert ApprovalsReviewer.auto_review.value == "auto_review"
assert ApprovalsReviewer.guardian_subagent.value == "guardian_subagent"
def test_notifications_are_typed_with_canonical_v2_methods() -> None:
client = AppServerClient()
event = client._coerce_notification(