Centralize app enabled-state evaluation (#36916)

## What changed

- Add `AppToolPolicyEvaluator::apply_app_enabled_state` and use it when
  presenting app lists, building plugin context, and deciding whether app
  instructions are available.
- Preserve each app's source state unless local or managed configuration
  explicitly overrides it.
- Keep connector discovery and post-install refresh checks based on raw
  accessibility rather than configured enablement.

## Testing

- Cover default enablement, per-app overrides, managed disablement, and
  preservation of unconfigured source state.

GitOrigin-RevId: f1a62d55e7cc48b37113848e3baa0d69d8d9c8a8
This commit is contained in:
jif
2026-08-04 15:49:49 +00:00
committed by copyberry
parent 2999b8e831
commit c8e255e7f8
9 changed files with 123 additions and 136 deletions
@@ -1,5 +1,6 @@
use super::*;
use crate::app_info::app_info_to_api;
use codex_connectors::AppToolPolicyEvaluator;
mod installed;
mod read;
@@ -250,12 +251,13 @@ impl AppsRequestProcessor {
let mut codex_apps_ready = true;
let mut last_notified_apps = None;
let mut sent_app_list_update = false;
let app_policy = AppToolPolicyEvaluator::new(&config.config_layer_stack);
if accessible_connectors.is_some() || all_connectors.is_some() {
let merged = connectors::with_app_enabled_state(
merge_loaded_apps(all_connectors.as_deref(), accessible_connectors.as_deref()),
&config,
);
let merged = app_policy.apply_app_enabled_state(merge_loaded_apps(
all_connectors.as_deref(),
accessible_connectors.as_deref(),
));
if !force_refetch {
last_notified_apps = Some(merged);
} else if should_send_app_list_updated_notification(
@@ -314,10 +316,10 @@ impl AppsRequestProcessor {
} else {
accessible_connectors.as_deref()
};
let merged = connectors::with_app_enabled_state(
merge_loaded_apps(all_connectors_for_update, accessible_connectors_for_update),
&config,
);
let merged = app_policy.apply_app_enabled_state(merge_loaded_apps(
all_connectors_for_update,
accessible_connectors_for_update,
));
if should_send_app_list_updated_notification(
merged.as_slice(),
accessible_loaded,