[codex] Populate remote plugin local versions (#29956)

# What

- Carry installed remote release versions through remote plugin
summaries as `localVersion`.
- Keep the app-server mapping a pure adapter by populating that value in
the remote catalog layer.

# Why

Remote plugin summaries always returned `localVersion: null` even after
their versioned bundles had been installed locally. Consumers such as
scheduled-task template discovery use `localVersion` to resolve a
plugin's materialized root, so templates from remote curated plugins
were silently skipped.
This commit is contained in:
Abhinav
2026-06-24 20:13:03 -07:00
committed by GitHub
Unverified
parent b3e1c33776
commit 6db937275f
5 changed files with 16 additions and 4 deletions
@@ -2158,7 +2158,7 @@ fn remote_plugin_summary_to_info(summary: RemoteCatalogPluginSummary) -> PluginS
PluginSummary {
id: summary.id,
remote_plugin_id: Some(summary.remote_plugin_id),
local_version: None,
local_version: summary.local_version,
name: summary.name,
share_context: summary
.share_context
@@ -1655,6 +1655,7 @@ async fn plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled() -
.chatgpt_account_id("account-123"),
AuthCredentialsStoreMode::File,
)?;
write_installed_plugin_with_version(&codex_home, "openai-curated-remote", "linear", "1.2.3")?;
let global_directory_body = r#"{
"plugins": [
@@ -1704,6 +1705,7 @@ async fn plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled() -
"authentication_policy": "ON_USE",
"status": "ENABLED",
"release": {
"version": "1.2.3",
"display_name": "Linear",
"description": "Track work in Linear",
"app_ids": [],
@@ -1813,6 +1815,10 @@ async fn plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled() -
);
assert_eq!(remote_marketplace.plugins[0].name, "linear");
assert_eq!(remote_marketplace.plugins[0].source, PluginSource::Remote);
assert_eq!(
remote_marketplace.plugins[0].local_version.as_deref(),
Some("1.2.3")
);
assert_eq!(remote_marketplace.plugins[0].installed, true);
assert_eq!(remote_marketplace.plugins[0].enabled, true);
assert_eq!(
@@ -171,7 +171,7 @@ async fn plugin_share_save_uploads_local_plugin() -> Result<()> {
plugin: PluginSummary {
id: "demo-plugin@workspace-shared-with-me".to_string(),
remote_plugin_id: Some("plugins_123".to_string()),
local_version: None,
local_version: Some("0.1.0".to_string()),
name: "demo-plugin".to_string(),
share_context: Some(expected_share_context("plugins_123")),
source: PluginSource::Remote,
@@ -575,7 +575,7 @@ async fn plugin_share_list_returns_created_workspace_plugins() -> Result<()> {
plugin: PluginSummary {
id: "demo-plugin@workspace-shared-with-me".to_string(),
remote_plugin_id: Some("plugins_123".to_string()),
local_version: None,
local_version: Some("0.1.0".to_string()),
name: "demo-plugin".to_string(),
share_context: Some(expected_share_context("plugins_123")),
source: PluginSource::Remote,
@@ -1176,7 +1176,7 @@ async fn plugin_share_delete_removes_created_workspace_plugin() -> Result<()> {
plugin: PluginSummary {
id: "demo-plugin@workspace-shared-with-me".to_string(),
remote_plugin_id: Some("plugins_123".to_string()),
local_version: None,
local_version: Some("0.1.0".to_string()),
name: "demo-plugin".to_string(),
share_context: Some(expected_share_context("plugins_123")),
source: PluginSource::Remote,
+4
View File
@@ -161,6 +161,7 @@ pub struct RemoteInstalledPlugin {
pub struct RemotePluginSummary {
pub id: String,
pub remote_plugin_id: String,
pub local_version: Option<String>,
pub name: String,
pub share_context: Option<RemotePluginShareContext>,
pub installed: bool,
@@ -1040,6 +1041,7 @@ pub fn group_remote_installed_plugins_by_marketplaces(
let plugin_summary = RemotePluginSummary {
id: plugin_id.as_key(),
remote_plugin_id: plugin.id.clone(),
local_version: None,
name: plugin.name.clone(),
share_context: None,
installed: true,
@@ -1470,6 +1472,8 @@ fn build_remote_plugin_summary(
Ok(RemotePluginSummary {
id: plugin_id.as_key(),
remote_plugin_id: plugin.id.clone(),
local_version: installed_plugin
.and_then(|installed| installed.plugin.release.version.clone()),
name: plugin.name.clone(),
share_context: remote_plugin_share_context(plugin)?,
installed: installed_plugin.is_some(),
@@ -618,6 +618,7 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
summary: RemotePluginSummary {
id: "demo-plugin@workspace-shared-with-me".to_string(),
remote_plugin_id: "plugins_123".to_string(),
local_version: None,
name: "demo-plugin".to_string(),
share_context: Some(RemotePluginShareContext {
remote_plugin_id: "plugins_123".to_string(),
@@ -657,6 +658,7 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
summary: RemotePluginSummary {
id: "demo-plugin@workspace-shared-with-me".to_string(),
remote_plugin_id: "plugins_456".to_string(),
local_version: Some("0.1.0".to_string()),
name: "demo-plugin".to_string(),
share_context: Some(RemotePluginShareContext {
remote_plugin_id: "plugins_456".to_string(),