Restore remote installed plugin fallback

This commit is contained in:
xli-oai
2026-05-14 23:25:22 -07:00
parent 9bc1f2d9bf
commit 1ff7845d67
3 changed files with 77 additions and 9 deletions

View File

@@ -864,14 +864,40 @@ impl PluginRequestProcessor {
}
if config.features.enabled(Feature::RemotePlugin) {
if let Some(remote_marketplaces) =
let remote_marketplaces = if let Some(remote_marketplaces) =
plugins_manager.remote_installed_marketplaces_from_cache()
{
for remote_marketplace in remote_marketplaces
.into_iter()
.map(remote_marketplace_to_info)
{
merge_plugin_marketplace_entry(&mut data, remote_marketplace);
Ok(remote_marketplaces)
} else {
let remote_plugin_service_config = RemotePluginServiceConfig {
chatgpt_base_url: config.chatgpt_base_url.clone(),
};
plugins_manager
.fetch_and_cache_remote_installed_marketplaces(
&remote_plugin_service_config,
auth.as_ref(),
)
.await
};
match remote_marketplaces {
Ok(remote_marketplaces) => {
for remote_marketplace in remote_marketplaces
.into_iter()
.map(remote_marketplace_to_info)
{
merge_plugin_marketplace_entry(&mut data, remote_marketplace);
}
}
Err(
RemotePluginCatalogError::AuthRequired
| RemotePluginCatalogError::UnsupportedAuthMode,
) => {}
Err(err) => {
warn!(
error = %err,
"plugin/installed remote installed plugin fetch failed; returning local marketplaces only"
);
}
}
}

View File

@@ -1802,7 +1802,7 @@ async fn plugin_list_does_not_append_global_remote_when_marketplace_kinds_are_ex
}
#[tokio::test]
async fn plugin_installed_does_not_fetch_remote_installed_when_cache_is_empty() -> Result<()> {
async fn plugin_installed_falls_back_to_remote_installed_and_caches_response() -> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
write_remote_plugin_catalog_config(
@@ -1827,6 +1827,7 @@ async fn plugin_installed_does_not_fetch_remote_installed_when_cache_is_empty()
mount_remote_installed_plugins(&server, "GLOBAL", &global_installed_body).await;
mount_remote_installed_plugins(&server, "WORKSPACE", empty_remote_installed_plugins_body())
.await;
write_installed_plugin_with_version(&codex_home, "chatgpt-global", "linear", "1.2.3")?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
@@ -1845,14 +1846,43 @@ async fn plugin_installed_does_not_fetch_remote_installed_when_cache_is_empty()
.await??;
let response: PluginInstalledResponse = to_response(response)?;
assert_eq!(response.marketplaces, Vec::new());
assert_eq!(response.marketplaces.len(), 1);
assert_eq!(response.marketplaces[0].name, "chatgpt-global");
assert_eq!(
response.marketplaces[0]
.plugins
.iter()
.map(|plugin| (plugin.id.clone(), plugin.installed, plugin.enabled))
.collect::<Vec<_>>(),
vec![("linear@chatgpt-global".to_string(), true, true)]
);
wait_for_remote_plugin_request_count(
&server,
"/ps/plugins/installed",
/*expected_count*/ 0,
/*expected_count*/ 2,
)
.await?;
wait_for_remote_plugin_request_count(&server, "/ps/plugins/list", /*expected_count*/ 0).await?;
let second_request_id = mcp
.send_plugin_installed_request(PluginInstalledParams {
cwds: None,
install_suggestion_plugin_names: None,
})
.await?;
let _: PluginInstalledResponse = to_response(
timeout(
DEFAULT_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(second_request_id)),
)
.await??,
)?;
wait_for_remote_plugin_request_count(
&server,
"/ps/plugins/installed",
/*expected_count*/ 2,
)
.await?;
Ok(())
}

View File

@@ -618,6 +618,18 @@ impl PluginsManager {
))
}
pub async fn fetch_and_cache_remote_installed_marketplaces(
&self,
config: &RemotePluginServiceConfig,
auth: Option<&CodexAuth>,
) -> Result<Vec<crate::remote::RemoteMarketplace>, RemotePluginCatalogError> {
let plugins = crate::remote::fetch_remote_installed_plugins(config, auth).await?;
let marketplaces =
crate::remote::remote_installed_marketplaces_from_cache(&plugins, &self.store);
self.write_remote_installed_plugins_cache(plugins);
Ok(marketplaces)
}
fn write_remote_installed_plugins_cache(&self, plugins: Vec<RemoteInstalledPlugin>) -> bool {
let mut cache = match self.remote_installed_plugins_cache.write() {
Ok(cache) => cache,