Allow installed plugin metadata to skip display enrichment (#56483)

## Why

Runtime metadata and tool suggestions do not require resolved image URLs or creator names. Callers that need display enrichment must still be able to distinguish a complete display snapshot from one fetched without it.

## What changed

- Add `InstalledPluginDisplayAssets` to select whether installed plugin requests include display enrichment, preserving `Include` as the default.
- Send `includeDisplayAssets=false` on every request page when `Skip` is selected.
- Track display enrichment in the installed plugin cache. Allow tool suggestions to use snapshots without enrichment, while treating those snapshots as cache misses for display callers.
- Avoid invalidating effective runtime metadata when only the cache's display enrichment state changes.

## Testing

Add coverage for paginated requests without display enrichment, cache eligibility and enrichment state transitions, and discovery using snapshots fetched with or without display assets.

GitOrigin-RevId: 1fdfd6443a300a03753416f2f6c633b52a97d0fb
This commit is contained in:
bkotsopoulos
2026-10-23 14:15:03 +00:00
committed by copyberry
parent 7d592f6dd9
commit de06fd0be4
8 changed files with 238 additions and 13 deletions
+56 -5
View File
@@ -61,6 +61,7 @@ use crate::marketplace_upgrade::ConfiguredMarketplaceUpgradeError;
use crate::marketplace_upgrade::ConfiguredMarketplaceUpgradeOutcome;
use crate::marketplace_upgrade::upgrade_configured_git_marketplaces_with_mode;
use crate::remote::CODEX_PRODUCT_SKU;
use crate::remote::InstalledPluginDisplayAssets;
use crate::remote::REMOTE_GLOBAL_MARKETPLACE_NAME;
use crate::remote::RecommendedPluginsMode;
use crate::remote::RemoteInstalledPlugin;
@@ -280,10 +281,11 @@ struct RemoteInstalledPluginsCache {
// A cancelled pass may mutate bundles before publication; retry must notify consumers.
needs_effective_plugins_refresh: bool,
plugins: Option<Vec<RemoteInstalledPlugin>>,
display_assets: InstalledPluginDisplayAssets,
}
enum RemoteInstalledPluginsCachePublication {
Refresh,
Refresh(InstalledPluginDisplayAssets),
Reconcile,
}
@@ -1247,11 +1249,24 @@ impl PluginsManager {
pub fn build_remote_installed_plugin_marketplaces_from_cache(
&self,
visible_marketplaces: &[&str],
) -> Option<Vec<crate::remote::RemoteMarketplace>> {
self.build_remote_installed_plugin_marketplaces_from_cache_with_display_assets(
visible_marketplaces,
InstalledPluginDisplayAssets::Include,
)
}
/// A runtime snapshot cannot satisfy a caller that requires display enrichment.
pub fn build_remote_installed_plugin_marketplaces_from_cache_with_display_assets(
&self,
visible_marketplaces: &[&str],
display_assets: InstalledPluginDisplayAssets,
) -> Option<Vec<crate::remote::RemoteMarketplace>> {
let auth = self.auth_manager.auth_cached();
self.build_remote_installed_plugin_marketplaces_from_cache_for_auth(
auth.as_ref(),
visible_marketplaces,
display_assets,
)
}
@@ -1259,6 +1274,7 @@ impl PluginsManager {
&self,
auth: Option<&CodexAuth>,
visible_marketplaces: &[&str],
display_assets: InstalledPluginDisplayAssets,
) -> Option<Vec<crate::remote::RemoteMarketplace>> {
let cache = match self.remote_installed_plugins_cache.read() {
Ok(cache) => cache,
@@ -1269,6 +1285,11 @@ impl PluginsManager {
{
return None;
}
if display_assets == InstalledPluginDisplayAssets::Include
&& cache.display_assets == InstalledPluginDisplayAssets::Skip
{
return None;
}
let plugins = cache.plugins.as_ref()?;
Some(
crate::remote::group_remote_installed_plugins_by_marketplaces(
@@ -1309,13 +1330,33 @@ impl PluginsManager {
auth: Option<&CodexAuth>,
visible_marketplaces: &[&str],
on_effective_plugins_changed: Option<EffectivePluginsChangedCallback>,
) -> Result<Vec<crate::remote::RemoteMarketplace>, RemotePluginCatalogError> {
self.build_and_cache_remote_installed_plugin_marketplaces_with_display_assets(
config,
auth,
visible_marketplaces,
on_effective_plugins_changed,
InstalledPluginDisplayAssets::Include,
)
.await
}
/// Fetch installed runtime metadata without optional display enrichment.
pub async fn build_and_cache_remote_installed_plugin_marketplaces_with_display_assets(
&self,
config: &PluginsConfigInput,
auth: Option<&CodexAuth>,
visible_marketplaces: &[&str],
on_effective_plugins_changed: Option<EffectivePluginsChangedCallback>,
display_assets: InstalledPluginDisplayAssets,
) -> Result<Vec<crate::remote::RemoteMarketplace>, RemotePluginCatalogError> {
let generation = self
.prepare_remote_installed_plugins_cache_generation(auth)
.ok_or(RemotePluginCatalogError::AuthRequired)?;
let plugins = crate::remote::fetch_remote_installed_plugins(
let plugins = crate::remote::fetch_remote_installed_plugins_with_display_assets(
&remote_plugin_service_config(config),
auth,
display_assets,
)
.await?;
let marketplaces = crate::remote::group_remote_installed_plugins_by_marketplaces(
@@ -1326,7 +1367,7 @@ impl PluginsManager {
generation,
plugins,
auth,
RemoteInstalledPluginsCachePublication::Refresh,
RemoteInstalledPluginsCachePublication::Refresh(display_assets),
) else {
let auth_identity = RemoteInstalledPluginsAuthIdentity::from_auth(auth);
if !self.remote_installed_plugins_auth_is_current(&auth_identity) {
@@ -1336,6 +1377,7 @@ impl PluginsManager {
.build_remote_installed_plugin_marketplaces_from_cache_for_auth(
auth,
visible_marketplaces,
display_assets,
)
.unwrap_or(marketplaces));
};
@@ -1346,6 +1388,7 @@ impl PluginsManager {
.build_remote_installed_plugin_marketplaces_from_cache_for_auth(
auth,
visible_marketplaces,
display_assets,
)
.unwrap_or(marketplaces))
}
@@ -1463,6 +1506,12 @@ impl PluginsManager {
}
let needs_effective_plugins_refresh =
is_reconcile && std::mem::take(&mut cache.needs_effective_plugins_refresh);
cache.display_assets = match publication {
RemoteInstalledPluginsCachePublication::Refresh(display_assets) => display_assets,
RemoteInstalledPluginsCachePublication::Reconcile => {
InstalledPluginDisplayAssets::Include
}
};
if cache.plugins.as_ref() == Some(&plugins) {
drop(cache);
if needs_effective_plugins_refresh {
@@ -1492,7 +1541,7 @@ impl PluginsManager {
generation,
plugins,
auth.as_ref(),
RemoteInstalledPluginsCachePublication::Refresh,
RemoteInstalledPluginsCachePublication::Refresh(InstalledPluginDisplayAssets::Include),
)
.expect("test cache generation should remain current")
}
@@ -3382,7 +3431,9 @@ impl PluginsManager {
request.generation,
plugins,
request.auth.as_ref(),
RemoteInstalledPluginsCachePublication::Refresh,
RemoteInstalledPluginsCachePublication::Refresh(
InstalledPluginDisplayAssets::Include,
),
) else {
continue;
};