Add marketplace display names to plugin/list (#14861)

Add display_name support to marketplace.json.
This commit is contained in:
xl-openai 2026-03-16 19:04:40 -07:00 committed by GitHub
parent 59533a2c26
commit 49c2b66ece
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 77 additions and 1 deletions

View file

@ -9372,6 +9372,12 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
},

View file

@ -6160,6 +6160,12 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
},

View file

@ -127,6 +127,12 @@
},
"PluginMarketplaceEntry": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
},

View file

@ -4,4 +4,4 @@
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
import type { PluginSummary } from "./PluginSummary";
export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, plugins: Array<PluginSummary>, };
export type PluginMarketplaceEntry = { name: string, path: AbsolutePathBuf, displayName: string | null, plugins: Array<PluginSummary>, };

View file

@ -3276,6 +3276,7 @@ pub struct SkillsListEntry {
pub struct PluginMarketplaceEntry {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub plugins: Vec<PluginSummary>,
}

View file

@ -5452,6 +5452,7 @@ impl CodexMessageProcessor {
.map(|marketplace| PluginMarketplaceEntry {
name: marketplace.name,
path: marketplace.path,
display_name: marketplace.display_name,
plugins: marketplace
.plugins
.into_iter()

View file

@ -152,6 +152,7 @@ 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",
"plugins": [
{
"name": "enabled-plugin",
@ -220,6 +221,10 @@ enabled = false
.expect("expected repo marketplace entry");
assert_eq!(marketplace.name, "codex-curated");
assert_eq!(
marketplace.display_name.as_deref(),
Some("ChatGPT Official")
);
assert_eq!(marketplace.plugins.len(), 3);
assert_eq!(marketplace.plugins[0].id, "enabled-plugin@codex-curated");
assert_eq!(marketplace.plugins[0].name, "enabled-plugin");

View file

@ -118,6 +118,7 @@ pub struct PluginDetailSummary {
pub struct ConfiguredMarketplaceSummary {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub plugins: Vec<ConfiguredMarketplacePluginSummary>,
}
@ -801,6 +802,7 @@ impl PluginsManager {
(!plugins.is_empty()).then_some(ConfiguredMarketplaceSummary {
name: marketplace.name,
path: marketplace.path,
display_name: marketplace.display_name,
plugins,
})
})

View file

@ -999,6 +999,7 @@ enabled = false
tmp.path().join("repo/.agents/plugins/marketplace.json"),
)
.unwrap(),
display_name: None,
plugins: vec![
ConfiguredMarketplacePluginSummary {
id: "enabled-plugin@debug".to_string(),
@ -1043,6 +1044,7 @@ async fn list_marketplaces_includes_curated_repo_marketplace() {
curated_root.join(".agents/plugins/marketplace.json"),
r#"{
"name": "openai-curated",
"display_name": "ChatGPT Official",
"plugins": [
{
"name": "linear",
@ -1077,6 +1079,7 @@ 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()),
plugins: vec![ConfiguredMarketplacePluginSummary {
id: "linear@openai-curated".to_string(),
name: "linear".to_string(),
@ -1281,6 +1284,7 @@ enabled = true
tmp.path().join("repo/.agents/plugins/marketplace.json"),
)
.unwrap(),
display_name: None,
plugins: vec![ConfiguredMarketplacePluginSummary {
id: "sample-plugin@debug".to_string(),
name: "sample-plugin".to_string(),

View file

@ -28,6 +28,7 @@ pub struct ResolvedMarketplacePlugin {
pub struct MarketplaceSummary {
pub name: String,
pub path: AbsolutePathBuf,
pub display_name: Option<String>,
pub plugins: Vec<MarketplacePluginSummary>,
}
@ -212,6 +213,7 @@ pub(crate) fn load_marketplace_summary(
Ok(MarketplaceSummary {
name: marketplace.name,
path: path.clone(),
display_name: marketplace.display_name,
plugins,
})
}
@ -367,6 +369,9 @@ fn marketplace_root_dir(
#[derive(Debug, Deserialize)]
struct MarketplaceFile {
name: String,
#[serde(default)]
#[serde(alias = "displayName")]
display_name: Option<String>,
plugins: Vec<MarketplacePlugin>,
}

View file

@ -137,6 +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,
plugins: vec![
MarketplacePluginSummary {
name: "shared-plugin".to_string(),
@ -163,6 +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,
plugins: vec![
MarketplacePluginSummary {
name: "shared-plugin".to_string(),
@ -245,6 +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,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -258,6 +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,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -324,6 +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,
plugins: vec![MarketplacePluginSummary {
name: "local-plugin".to_string(),
source: MarketplacePluginSourceSummary::Local {
@ -337,6 +342,41 @@ fn list_marketplaces_dedupes_multiple_roots_in_same_repo() {
);
}
#[test]
fn list_marketplaces_reads_marketplace_display_name() {
let tmp = tempdir().unwrap();
let repo_root = tmp.path().join("repo");
fs::create_dir_all(repo_root.join(".git")).unwrap();
fs::create_dir_all(repo_root.join(".agents/plugins")).unwrap();
fs::write(
repo_root.join(".agents/plugins/marketplace.json"),
r#"{
"name": "openai-curated",
"display_name": "ChatGPT Official",
"plugins": [
{
"name": "local-plugin",
"source": {
"source": "local",
"path": "./plugin"
}
}
]
}"#,
)
.unwrap();
let marketplaces =
list_marketplaces_with_home(&[AbsolutePathBuf::try_from(repo_root).unwrap()], None)
.unwrap();
assert_eq!(
marketplaces[0].display_name,
Some("ChatGPT Official".to_string())
);
}
#[test]
fn list_marketplaces_resolves_plugin_interface_paths_to_absolute() {
let tmp = tempdir().unwrap();