TUI Plugin Sharing 2 - add remote plugin section plumbing (#26702)

This adds the background plumbing for remote-backed plugin catalog
sections while leaving the fuller directory presentation to the next PR.
The TUI can fetch section-specific remote marketplace results, keep
local plugin data available, and carry section errors forward for later
rendering.

- Fetches explicit remote marketplace kinds for curated, workspace, and
shared-with-me sections.
- Gates shared-with-me loading on the plugin sharing feature flag.
- Adds section-level error state and user-actionable error copy.
- Merges remote marketplace results into the cached plugin list without
discarding local results.
This commit is contained in:
canvrno-oai
2026-06-15 10:25:37 -07:00
committed by GitHub
parent a18de1f3b6
commit 29224d945b
9 changed files with 364 additions and 16 deletions
@@ -644,6 +644,12 @@ impl PluginRequestProcessor {
data.push(remote_marketplace_to_info(remote_marketplace));
}
Ok(None) => {}
Err(err) if explicit_marketplace_kinds => {
return Err(remote_plugin_catalog_error_to_jsonrpc(
err,
"list OpenAI Curated remote plugin catalog",
));
}
Err(
RemotePluginCatalogError::AuthRequired
| RemotePluginCatalogError::UnsupportedAuthMode,
@@ -2064,7 +2064,7 @@ async fn plugin_list_includes_openai_curated_remote_collection_when_requested()
}
#[tokio::test]
async fn plugin_list_fail_opens_openai_curated_remote_collection_errors() -> Result<()> {
async fn plugin_list_propagates_explicit_openai_curated_remote_collection_errors() -> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
write_plugins_enabled_config_with_base_url(
@@ -2103,18 +2103,17 @@ async fn plugin_list_fail_opens_openai_curated_remote_collection_errors() -> Res
marketplace_kinds: Some(vec![PluginListMarketplaceKind::Vertical]),
})
.await?;
let response: JSONRPCResponse = timeout(
let err = timeout(
DEFAULT_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
mcp.read_stream_until_error_message(RequestId::Integer(request_id)),
)
.await??;
let response: PluginListResponse = to_response(response)?;
assert_eq!(err.error.code, -32603);
assert!(
response
.marketplaces
.iter()
.all(|marketplace| marketplace.name != "openai-curated-remote")
err.error
.message
.contains("list OpenAI Curated remote plugin catalog")
);
Ok(())
}