Allow disabling plugin discovery prefetch at app-server startup (#57249)

## Why

Hosts that only need installed plugin inventory should be able to skip startup requests for plugin discovery.

## What changed

Add the stable, default-enabled `features.plugin_discovery_prefetch` flag. Setting it to `false` skips startup prefetching of the plugin directory, featured plugins, and recommendations while preserving installed plugin cache refreshes and bundle downloads.

## Testing

Update app-server integration coverage to verify that installed plugin bundles download with discovery prefetch disabled and that no directory, featured, or suggested plugin requests are made during startup. Also cover listing remote marketplaces with the flag disabled.

GitOrigin-RevId: 7cc3072f6045131b9f1acb851f6240db75ac173e
This commit is contained in:
Alex Zamoshchin
2026-10-26 20:54:08 +00:00
committed by copyberry
parent 8f71a8657e
commit 3ad642e520
7 changed files with 47 additions and 10 deletions
@@ -83,6 +83,7 @@ use codex_core::config::Config;
use codex_core::config::ThreadStoreConfig;
use codex_exec_server::EnvironmentManager;
use codex_extension_api::TurnStartAdmission;
use codex_features::Feature;
use codex_feedback::CodexFeedback;
use codex_goal_extension::GoalService;
use codex_home::CodexHomeUserInstructionsProvider;
@@ -568,6 +569,7 @@ impl MessageProcessor {
.plugins_manager()
.maybe_start_plugin_startup_tasks_for_config(
&config.plugins_config_input(),
config.features.enabled(Feature::PluginDiscoveryPrefetch),
reload_config,
Some(on_effective_plugins_changed),
startup_warnings_tx,
@@ -308,6 +308,7 @@ impl AccountRequestProcessor {
.maybe_start_remote_plugin_caches_refresh(
&plugins_config,
auth,
/*prefetch_recommendations*/ true,
Some(on_effective_plugins_changed),
);
}
@@ -1961,7 +1961,8 @@ enabled = true
}
#[tokio::test]
async fn app_server_startup_sync_downloads_remote_installed_plugin_bundles() -> Result<()> {
async fn app_server_startup_downloads_installed_plugin_bundles_without_discovery_prefetch()
-> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
write_remote_plugin_catalog_config(
@@ -2001,11 +2002,24 @@ async fn app_server_startup_sync_downloads_remote_installed_plugin_bundles() ->
.await;
mount_empty_user_installed_plugins(&server).await;
for endpoint in [
"/backend-api/ps/plugins/list",
"/backend-api/plugins/featured",
"/backend-api/ps/plugins/suggested/codex",
] {
Mock::given(path(endpoint))
.respond_with(ResponseTemplate::new(404))
.expect(0)
.mount(&server)
.await;
}
let installed_path = codex_home
.path()
.join("plugins/cache/openai-curated-remote/linear/1.2.3");
let _mcp = TestAppServer::builder()
.with_codex_home(codex_home.path())
.with_args(&["-c", "features.plugin_discovery_prefetch=false"])
.with_plugin_startup_tasks()
.with_env_overrides(&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))])
.build_initialized_with_timeout(DEFAULT_TIMEOUT)
@@ -2137,7 +2151,7 @@ enum ProjectPluginConfiguration {
Invalid,
}
#[test_case(ProjectPluginConfiguration::None, None, "", true, true; "without project override")]
#[test_case(ProjectPluginConfiguration::None, None, "plugin_discovery_prefetch = false", true, true; "without discovery prefetch")]
#[test_case(ProjectPluginConfiguration::Disabled, None, "", true, true; "project disables local plugins")]
#[test_case(ProjectPluginConfiguration::Invalid, None, "", true, true; "invalid project preserves remote plugins")]
#[test_case(ProjectPluginConfiguration::None, Some("tpp"), "", true, true; "configured product sku")]