[plugins] Refresh plugin and tool caches after remote install (#28951)

Summary
- Refresh the installed remote-plugin snapshot and Codex Apps tools
after completing a remote JIT install.
- Gate `completed: true` on every expected `app_connector_id` appearing
after the uncached `tools/list` refresh, while continuing to skip local
bundle verification for server-side installs.
- Keep the cached recommendations response and filter refreshed
installed remote IDs locally, so this does not add another
recommendations fetch.
- Add regression coverage for tools appearing after the hard refresh and
remaining absent after the refresh. The resumed model request sees the
refreshed tool router when installation completes.

Root Cause
- Remote suggestions from `openai-curated-remote` returned `true` before
taking the existing connector refresh path, leaving the resumed turn
with the pre-install Apps tool catalog.

Validation
- `just test -p codex-core request_plugin_install`
- `just test -p codex-core-plugins
recommended_plugin_candidates_filter_installed_and_disabled_plugins`
- `just test -p codex-core-plugins`
- `just fix -p codex-core-plugins`
- `just fix -p codex-core`
- `just fmt`
- `just test -p codex-core` was not fully clean locally: 2,729 passed,
26 failed, and 16 skipped. The failures were dominated by local
Seatbelt/network/timing issues, including plugin-install timeouts under
full-suite contention; the focused plugin-install runs pass.
This commit is contained in:
Alex Daley authored and GitHub committed 2026-06-18 20:08:04 -04:00
1 parent 5c12034e42
commit 7e37354a58
5 files changed
+370 -53

No files matched your search

+15
View File
@@ -39,6 +39,7 @@ use crate::marketplace_upgrade::ConfiguredMarketplaceUpgradeError;
use crate::marketplace_upgrade::ConfiguredMarketplaceUpgradeOutcome;
use crate::marketplace_upgrade::configured_git_marketplace_names;
use crate::marketplace_upgrade::upgrade_configured_git_marketplaces;
use crate::remote::REMOTE_GLOBAL_MARKETPLACE_NAME;
use crate::remote::RecommendedPluginsMode;
use crate::remote::RemoteInstalledPlugin;
use crate::remote::RemotePluginCatalogError;
@@ -1098,6 +1099,19 @@ impl PluginsManager {
.iter()
.map(|plugin| plugin.config_name.as_str())
.collect::<HashSet<_>>();
let installed_remote_plugin_ids = {
let cache = match self.remote_installed_plugins_cache.read() {
Ok(cache) => cache,
Err(err) => err.into_inner(),
};
cache
.as_deref()
.unwrap_or_default()
.iter()
.filter(|plugin| plugin.marketplace_name == REMOTE_GLOBAL_MARKETPLACE_NAME)
.map(|plugin| plugin.id.clone())
.collect::<HashSet<_>>()
};
let disabled_plugin_ids = input
.disabled_tools
.iter()
@@ -1109,6 +1123,7 @@ impl PluginsManager {
.into_iter()
.filter(|plugin| {
!installed_plugin_ids.contains(plugin.config_id.as_str())
&& !installed_remote_plugin_ids.contains(plugin.remote_plugin_id.as_str())
&& !disabled_plugin_ids.contains(plugin.config_id.as_str())
})
.map(|plugin| {