Skip to content

Commit 5b1a4c2

Browse files
authored
feat: Normalize remote plugin summary identities. (openai#22265)
Makes plugin summaries use config-style plugin@marketplace IDs while exposing backend remote IDs separately as remotePluginId. Also fix the consistency issue of REMOTE_SHARED_WITH_ME_MARKETPLACE_NAME
1 parent 46f30d0 commit 5b1a4c2

17 files changed

Lines changed: 209 additions & 44 deletions

File tree

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/v2/PluginListResponse.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/json/v2/PluginShareListResponse.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/schema/typescript/v2/PluginSummary.ts

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/app-server-protocol/src/protocol/v2/plugin.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,8 @@ pub enum PluginAvailability {
538538
#[ts(export_to = "v2/")]
539539
pub struct PluginSummary {
540540
pub id: String,
541+
/// Backend remote plugin identifier when available.
542+
pub remote_plugin_id: Option<String>,
541543
pub name: String,
542544
/// Remote sharing context associated with this plugin when available.
543545
pub share_context: Option<PluginShareContext>,

codex-rs/app-server-protocol/src/protocol/v2/tests.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,7 +3003,10 @@ fn plugin_share_list_response_serializes_share_items() {
30033003
serde_json::to_value(PluginShareListResponse {
30043004
data: vec![PluginShareListItem {
30053005
plugin: PluginSummary {
3006-
id: "plugins~Plugin_00000000000000000000000000000000".to_string(),
3006+
id: "gmail@chatgpt-global".to_string(),
3007+
remote_plugin_id: Some(
3008+
"plugins~Plugin_00000000000000000000000000000000".to_string(),
3009+
),
30073010
name: "gmail".to_string(),
30083011
share_context: None,
30093012
source: PluginSource::Remote,
@@ -3022,7 +3025,8 @@ fn plugin_share_list_response_serializes_share_items() {
30223025
json!({
30233026
"data": [{
30243027
"plugin": {
3025-
"id": "plugins~Plugin_00000000000000000000000000000000",
3028+
"id": "gmail@chatgpt-global",
3029+
"remotePluginId": "plugins~Plugin_00000000000000000000000000000000",
30263030
"name": "gmail",
30273031
"shareContext": null,
30283032
"source": { "type": "remote" },

codex-rs/app-server/src/request_processors/plugins.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ impl PluginRequestProcessor {
482482
);
483483
PluginSummary {
484484
id: plugin.id,
485+
remote_plugin_id: None,
485486
installed: plugin.installed,
486487
enabled: plugin.enabled,
487488
name: plugin.name,
@@ -723,6 +724,7 @@ impl PluginRequestProcessor {
723724
marketplace_path: outcome.marketplace_path,
724725
summary: PluginSummary {
725726
id: outcome.plugin.id,
727+
remote_plugin_id: None,
726728
name: outcome.plugin.name,
727729
share_context,
728730
source: marketplace_plugin_source_to_info(outcome.plugin.source),
@@ -1107,7 +1109,6 @@ impl PluginRequestProcessor {
11071109
)
11081110
})?;
11091111
if remote_detail.summary.availability == PluginAvailability::DisabledByAdmin {
1110-
let remote_plugin_id = &remote_detail.summary.id;
11111112
return Err(invalid_request(format!(
11121113
"remote plugin {remote_plugin_id} is disabled by admin"
11131114
)));
@@ -1587,6 +1588,7 @@ fn remote_marketplace_to_info(marketplace: RemoteMarketplace) -> PluginMarketpla
15871588
fn remote_plugin_summary_to_info(summary: RemoteCatalogPluginSummary) -> PluginSummary {
15881589
PluginSummary {
15891590
id: summary.id,
1591+
remote_plugin_id: Some(summary.remote_plugin_id),
15901592
name: summary.name,
15911593
share_context: summary
15921594
.share_context

codex-rs/app-server/tests/suite/v2/plugin_list.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ async fn plugin_list_keeps_valid_marketplaces_when_another_marketplace_fails_to_
240240
interface: None,
241241
plugins: vec![PluginSummary {
242242
id: "valid-plugin@valid-marketplace".to_string(),
243+
remote_plugin_id: None,
243244
name: "valid-plugin".to_string(),
244245
share_context: None,
245246
source: PluginSource::Local {
@@ -529,6 +530,7 @@ async fn plugin_list_uses_alternate_discoverable_manifest_and_keeps_undiscoverab
529530
plugins: vec![
530531
PluginSummary {
531532
id: "valid-plugin@alternate-marketplace".to_string(),
533+
remote_plugin_id: None,
532534
name: "valid-plugin".to_string(),
533535
share_context: None,
534536
source: PluginSource::Local {
@@ -562,6 +564,7 @@ async fn plugin_list_uses_alternate_discoverable_manifest_and_keeps_undiscoverab
562564
},
563565
PluginSummary {
564566
id: "missing-plugin@alternate-marketplace".to_string(),
567+
remote_plugin_id: None,
565568
name: "missing-plugin".to_string(),
566569
share_context: None,
567570
source: PluginSource::Local {
@@ -688,6 +691,7 @@ async fn plugin_list_returns_share_context_for_shared_local_plugin() -> Result<(
688691
.flat_map(|marketplace| marketplace.plugins.iter())
689692
.find(|plugin| plugin.name == "demo-plugin")
690693
.expect("expected demo-plugin entry");
694+
assert_eq!(plugin.remote_plugin_id, None);
691695
let share_context = plugin
692696
.share_context
693697
.as_ref()
@@ -1464,11 +1468,7 @@ async fn plugin_list_sync_upgrades_and_removes_remote_installed_plugin_bundles()
14641468
.into_iter()
14651469
.map(|plugin| (plugin.id, plugin.installed, plugin.enabled))
14661470
.collect::<Vec<_>>(),
1467-
vec![(
1468-
"plugins~Plugin_00000000000000000000000000000000".to_string(),
1469-
true,
1470-
true
1471-
)]
1471+
vec![("linear@chatgpt-global".to_string(), true, true)]
14721472
);
14731473

14741474
wait_for_path_exists(&new_path.join(".codex-plugin/plugin.json")).await?;
@@ -1629,9 +1629,10 @@ async fn plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled() -
16291629
Some("ChatGPT Plugins")
16301630
);
16311631
assert_eq!(remote_marketplace.plugins.len(), 1);
1632+
assert_eq!(remote_marketplace.plugins[0].id, "linear@chatgpt-global");
16321633
assert_eq!(
1633-
remote_marketplace.plugins[0].id,
1634-
"plugins~Plugin_00000000000000000000000000000000"
1634+
remote_marketplace.plugins[0].remote_plugin_id.as_deref(),
1635+
Some("plugins~Plugin_00000000000000000000000000000000")
16351636
);
16361637
assert_eq!(remote_marketplace.plugins[0].name, "linear");
16371638
assert_eq!(remote_marketplace.plugins[0].source, PluginSource::Remote);
@@ -1725,12 +1726,14 @@ async fn plugin_list_fetches_workspace_directory_kind_without_remote_plugin_flag
17251726
"plugins~Plugin_11111111111111111111111111111111",
17261727
"workspace-linear",
17271728
"Workspace Linear",
1729+
"LISTED",
17281730
/*enabled*/ None,
17291731
);
17301732
let workspace_installed_body = workspace_remote_plugin_page_body(
17311733
"plugins~Plugin_11111111111111111111111111111111",
17321734
"workspace-linear",
17331735
"Workspace Linear",
1736+
"LISTED",
17341737
/*enabled*/ Some(false),
17351738
);
17361739
mount_remote_plugin_list(&server, "WORKSPACE", &workspace_plugin_body).await;
@@ -1764,6 +1767,14 @@ async fn plugin_list_fetches_workspace_directory_kind_without_remote_plugin_flag
17641767
Some("Workspace Directory")
17651768
);
17661769
assert_eq!(marketplace.plugins.len(), 1);
1770+
assert_eq!(
1771+
marketplace.plugins[0].id,
1772+
"workspace-linear@workspace-directory"
1773+
);
1774+
assert_eq!(
1775+
marketplace.plugins[0].remote_plugin_id.as_deref(),
1776+
Some("plugins~Plugin_11111111111111111111111111111111")
1777+
);
17671778
assert_eq!(marketplace.plugins[0].name, "workspace-linear");
17681779
assert_eq!(marketplace.plugins[0].installed, true);
17691780
assert_eq!(marketplace.plugins[0].enabled, false);
@@ -1803,6 +1814,7 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
18031814
"plugins~Plugin_22222222222222222222222222222222",
18041815
"shared-linear",
18051816
"Shared Linear",
1817+
"PRIVATE",
18061818
/*enabled*/ None,
18071819
))?;
18081820
shared_plugin_body["plugins"][0]["share_principals"] = serde_json::Value::Null;
@@ -1811,6 +1823,7 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
18111823
"plugins~Plugin_22222222222222222222222222222222",
18121824
"shared-linear",
18131825
"Shared Linear",
1826+
"PRIVATE",
18141827
/*enabled*/ Some(true),
18151828
);
18161829
mount_shared_workspace_plugins(&server, &shared_plugin_body).await;
@@ -1844,6 +1857,11 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
18441857
Some("Shared with me")
18451858
);
18461859
assert_eq!(marketplace.plugins.len(), 1);
1860+
assert_eq!(marketplace.plugins[0].id, "shared-linear@shared-with-me");
1861+
assert_eq!(
1862+
marketplace.plugins[0].remote_plugin_id.as_deref(),
1863+
Some("plugins~Plugin_22222222222222222222222222222222")
1864+
);
18471865
assert_eq!(marketplace.plugins[0].name, "shared-linear");
18481866
assert_eq!(marketplace.plugins[0].installed, true);
18491867
assert_eq!(marketplace.plugins[0].enabled, true);
@@ -2381,6 +2399,7 @@ fn workspace_remote_plugin_page_body(
23812399
remote_plugin_id: &str,
23822400
plugin_name: &str,
23832401
display_name: &str,
2402+
discoverability: &str,
23842403
enabled: Option<bool>,
23852404
) -> String {
23862405
let enabled_field = enabled
@@ -2393,7 +2412,7 @@ fn workspace_remote_plugin_page_body(
23932412
"id": "{remote_plugin_id}",
23942413
"name": "{plugin_name}",
23952414
"scope": "WORKSPACE",
2396-
"discoverability": "PRIVATE",
2415+
"discoverability": "{discoverability}",
23972416
"creator_account_user_id": "user-gavin__account-123",
23982417
"share_url": "https://chatgpt.example/plugins/share/share-key-1",
23992418
"installation_policy": "AVAILABLE",

0 commit comments

Comments
 (0)