fix: align marketplace display name with existing interface conventions (#14886)

1. camelCase for displayName;
2. move displayName under interface.
This commit is contained in:
xl-openai 2026-03-16 21:52:19 -07:00 committed by GitHub
parent fbd7f9b986
commit e5a28ba0c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 136 additions and 35 deletions

View file

@ -8491,6 +8491,17 @@
"title": "LogoutAccountResponse",
"type": "object"
},
"MarketplaceInterface": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"McpAuthStatus": {
"enum": [
"unsupported",
@ -9376,10 +9387,14 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
"interface": {
"anyOf": [
{
"$ref": "#/definitions/v2/MarketplaceInterface"
},
{
"type": "null"
}
]
},
"name": {

View file

@ -5279,6 +5279,17 @@
"title": "LogoutAccountResponse",
"type": "object"
},
"MarketplaceInterface": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"McpAuthStatus": {
"enum": [
"unsupported",
@ -6164,10 +6175,14 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
"interface": {
"anyOf": [
{
"$ref": "#/definitions/MarketplaceInterface"
},
{
"type": "null"
}
]
},
"name": {

View file

@ -5,6 +5,17 @@
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"MarketplaceInterface": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"PluginAuthPolicy": {
"enum": [
"ON_INSTALL",
@ -127,10 +138,14 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
"interface": {
"anyOf": [
{
"$ref": "#/definitions/MarketplaceInterface"
},
{
"type": "null"
}
]
},
"name": {

View file

@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type MarketplaceInterface = { displayName: string | null, };

View file

@ -2,6 +2,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
import type { MarketplaceInterface } from "./MarketplaceInterface";
import type { PluginSummary } from "./PluginSummary";
export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, displayName: string | null, plugins: Array<PluginSummary>, };
export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, interface: MarketplaceInterface | null, plugins: Array<PluginSummary>, };

View file

@ -139,6 +139,7 @@ export type { ListMcpServerStatusResponse } from "./ListMcpServerStatusResponse"
export type { LoginAccountParams } from "./LoginAccountParams";
export type { LoginAccountResponse } from "./LoginAccountResponse";
export type { LogoutAccountResponse } from "./LogoutAccountResponse";
export type { MarketplaceInterface } from "./MarketplaceInterface";
export type { McpAuthStatus } from "./McpAuthStatus";
export type { McpElicitationArrayType } from "./McpElicitationArrayType";
export type { McpElicitationBooleanSchema } from "./McpElicitationBooleanSchema";

View file

@ -3276,10 +3276,17 @@ pub struct SkillsListEntry {
pub struct PluginMarketplaceEntry {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub interface: Option<MarketplaceInterface>,
pub plugins: Vec<PluginSummary>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct MarketplaceInterface {
pub display_name: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[ts(export_to = "v2/")]
pub enum PluginInstallPolicy {

View file

@ -72,6 +72,7 @@ use codex_app_server_protocol::LoginAccountParams;
use codex_app_server_protocol::LoginAccountResponse;
use codex_app_server_protocol::LoginApiKeyParams;
use codex_app_server_protocol::LogoutAccountResponse;
use codex_app_server_protocol::MarketplaceInterface;
use codex_app_server_protocol::McpServerOauthLoginCompletedNotification;
use codex_app_server_protocol::McpServerOauthLoginParams;
use codex_app_server_protocol::McpServerOauthLoginResponse;
@ -5452,7 +5453,9 @@ impl CodexMessageProcessor {
.map(|marketplace| PluginMarketplaceEntry {
name: marketplace.name,
path: marketplace.path,
display_name: marketplace.display_name,
interface: marketplace.interface.map(|interface| MarketplaceInterface {
display_name: interface.display_name,
}),
plugins: marketplace
.plugins
.into_iter()

View file

@ -152,7 +152,9 @@ async fn plugin_list_includes_install_and_enabled_state_from_config() -> Result<
repo_root.path().join(".agents/plugins/marketplace.json"),
r#"{
"name": "codex-curated",
"display_name": "ChatGPT Official",
"interface": {
"displayName": "ChatGPT Official"
},
"plugins": [
{
"name": "enabled-plugin",
@ -222,7 +224,10 @@ enabled = false
assert_eq!(marketplace.name, "codex-curated");
assert_eq!(
marketplace.display_name.as_deref(),
marketplace
.interface
.as_ref()
.and_then(|interface| interface.display_name.as_deref()),
Some("ChatGPT Official")
);
assert_eq!(marketplace.plugins.len(), 3);

View file

@ -3,6 +3,7 @@ use super::curated_plugins_repo_path;
use super::load_plugin_manifest;
use super::manifest::PluginManifestInterfaceSummary;
use super::marketplace::MarketplaceError;
use super::marketplace::MarketplaceInterfaceSummary;
use super::marketplace::MarketplacePluginAuthPolicy;
use super::marketplace::MarketplacePluginInstallPolicy;
use super::marketplace::MarketplacePluginSourceSummary;
@ -121,7 +122,7 @@ pub struct PluginDetailSummary {
pub struct ConfiguredMarketplaceSummary {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub interface: Option<MarketplaceInterfaceSummary>,
pub plugins: Vec<ConfiguredMarketplacePluginSummary>,
}
@ -846,7 +847,7 @@ impl PluginsManager {
(!plugins.is_empty()).then_some(ConfiguredMarketplaceSummary {
name: marketplace.name,
path: marketplace.path,
display_name: marketplace.display_name,
interface: marketplace.interface,
plugins,
})
})

View file

@ -999,7 +999,7 @@ enabled = false
tmp.path().join("repo/.agents/plugins/marketplace.json"),
)
.unwrap(),
display_name: None,
interface: None,
plugins: vec![
ConfiguredMarketplacePluginSummary {
id: "enabled-plugin@debug".to_string(),
@ -1044,7 +1044,9 @@ async fn list_marketplaces_includes_curated_repo_marketplace() {
curated_root.join(".agents/plugins/marketplace.json"),
r#"{
"name": "openai-curated",
"display_name": "ChatGPT Official",
"interface": {
"displayName": "ChatGPT Official"
},
"plugins": [
{
"name": "linear",
@ -1079,7 +1081,9 @@ async fn list_marketplaces_includes_curated_repo_marketplace() {
name: "openai-curated".to_string(),
path: AbsolutePathBuf::try_from(curated_root.join(".agents/plugins/marketplace.json"))
.unwrap(),
display_name: Some("ChatGPT Official".to_string()),
interface: Some(MarketplaceInterfaceSummary {
display_name: Some("ChatGPT Official".to_string()),
}),
plugins: vec![ConfiguredMarketplacePluginSummary {
id: "linear@openai-curated".to_string(),
name: "linear".to_string(),
@ -1284,7 +1288,7 @@ enabled = true
tmp.path().join("repo/.agents/plugins/marketplace.json"),
)
.unwrap(),
display_name: None,
interface: None,
plugins: vec![ConfiguredMarketplacePluginSummary {
id: "sample-plugin@debug".to_string(),
name: "sample-plugin".to_string(),

View file

@ -28,10 +28,15 @@ pub struct ResolvedMarketplacePlugin {
pub struct MarketplaceSummary {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub interface: Option<MarketplaceInterfaceSummary>,
pub plugins: Vec<MarketplacePluginSummary>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MarketplaceInterfaceSummary {
pub display_name: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MarketplacePluginSummary {
pub name: String,
@ -213,7 +218,7 @@ pub(crate) fn load_marketplace_summary(
Ok(MarketplaceSummary {
name: marketplace.name,
path: path.clone(),
display_name: marketplace.display_name,
interface: marketplace_interface_summary(marketplace.interface),
plugins,
})
}
@ -367,14 +372,21 @@ fn marketplace_root_dir(
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct MarketplaceFile {
name: String,
#[serde(default)]
#[serde(alias = "displayName")]
display_name: Option<String>,
interface: Option<MarketplaceInterface>,
plugins: Vec<MarketplacePlugin>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
struct MarketplaceInterface {
#[serde(default)]
display_name: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct MarketplacePlugin {
@ -394,6 +406,19 @@ enum MarketplacePluginSource {
Local { path: String },
}
fn marketplace_interface_summary(
interface: Option<MarketplaceInterface>,
) -> Option<MarketplaceInterfaceSummary> {
let interface = interface?;
if interface.display_name.is_some() {
Some(MarketplaceInterfaceSummary {
display_name: interface.display_name,
})
} else {
None
}
}
#[cfg(test)]
#[path = "marketplace_tests.rs"]
mod tests;

View file

@ -137,7 +137,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
path:
AbsolutePathBuf::try_from(home_root.join(".agents/plugins/marketplace.json"),)
.unwrap(),
display_name: None,
interface: None,
plugins: vec![
MarketplacePluginSummary {
name: "shared-plugin".to_string(),
@ -164,7 +164,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
path:
AbsolutePathBuf::try_from(repo_root.join(".agents/plugins/marketplace.json"),)
.unwrap(),
display_name: None,
interface: None,
plugins: vec![
MarketplacePluginSummary {
name: "shared-plugin".to_string(),
@ -247,7 +247,7 @@ fn list_marketplaces_keeps_distinct_entries_for_same_name() {
MarketplaceSummary {
name: "codex-curated".to_string(),
path: AbsolutePathBuf::try_from(home_marketplace).unwrap(),
display_name: None,
interface: None,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -261,7 +261,7 @@ fn list_marketplaces_keeps_distinct_entries_for_same_name() {
MarketplaceSummary {
name: "codex-curated".to_string(),
path: AbsolutePathBuf::try_from(repo_marketplace.clone()).unwrap(),
display_name: None,
interface: None,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -328,7 +328,7 @@ fn list_marketplaces_dedupes_multiple_roots_in_same_repo() {
name: "codex-curated".to_string(),
path: AbsolutePathBuf::try_from(repo_root.join(".agents/plugins/marketplace.json"))
.unwrap(),
display_name: None,
interface: None,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -353,7 +353,9 @@ fn list_marketplaces_reads_marketplace_display_name() {
repo_root.join(".agents/plugins/marketplace.json"),
r#"{
"name": "openai-curated",
"display_name": "ChatGPT Official",
"interface": {
"displayName": "ChatGPT Official"
},
"plugins": [
{
"name": "local-plugin",
@ -372,8 +374,10 @@ fn list_marketplaces_reads_marketplace_display_name() {
.unwrap();
assert_eq!(
marketplaces[0].display_name,
Some("ChatGPT Official".to_string())
marketplaces[0].interface,
Some(MarketplaceInterfaceSummary {
display_name: Some("ChatGPT Official".to_string()),
})
);
}