mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Expose configured marketplace source in plugin list JSON (#26417)
## Summary - Follow-up to #25330 - Add `marketplaceSource` to `codex plugin list --json` entries for configured marketplaces - Keep the existing per-plugin `source` field unchanged; this still reports the local plugin source path - Include only the configured marketplace `sourceType` and `source` from `config.toml` - Keep human-readable output unchanged - Add CLI coverage for configured local and git marketplace sources Example: ```json { "source": { "source": "local", "path": "/path/to/.codex/.tmp/marketplaces/debug/plugins/sample" }, "marketplaceSource": { "sourceType": "git", "source": "https://example.com/acme/agent-skills.git" } } ``` ## Validation - `just fmt` - `just fix -p codex-cli` - `just test -p codex-cli plugin_list`
This commit is contained in:
committed by
GitHub
Unverified
parent
cbf62f64cb
commit
cdc1d592df
@@ -20,6 +20,7 @@ use codex_plugin::PluginId;
|
||||
use codex_plugin::validate_plugin_segment;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -177,9 +178,14 @@ pub async fn run_plugin_list(
|
||||
.is_none_or(|name| marketplace.name == *name)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let marketplace_sources = configured_marketplace_sources(&plugins_input);
|
||||
|
||||
if args.json {
|
||||
let output = JsonPluginListOutput::from_marketplaces(marketplaces, args.available);
|
||||
let output = JsonPluginListOutput::from_marketplaces(
|
||||
marketplaces,
|
||||
args.available,
|
||||
&marketplace_sources,
|
||||
);
|
||||
println!("{}", serde_json::to_string_pretty(&output)?);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -269,13 +275,19 @@ impl JsonPluginListOutput {
|
||||
fn from_marketplaces(
|
||||
marketplaces: Vec<codex_core_plugins::ConfiguredMarketplace>,
|
||||
include_available: bool,
|
||||
marketplace_sources: &HashMap<String, JsonMarketplaceSource>,
|
||||
) -> Self {
|
||||
let mut installed = Vec::new();
|
||||
let mut available = Vec::new();
|
||||
|
||||
for marketplace in marketplaces {
|
||||
let marketplace_source = marketplace_sources.get(&marketplace.name).cloned();
|
||||
for plugin in marketplace.plugins {
|
||||
let entry = JsonPluginListEntry::from_configured_plugin(&marketplace.name, plugin);
|
||||
let entry = JsonPluginListEntry::from_configured_plugin(
|
||||
&marketplace.name,
|
||||
marketplace_source.clone(),
|
||||
plugin,
|
||||
);
|
||||
if entry.installed {
|
||||
installed.push(entry);
|
||||
} else if include_available {
|
||||
@@ -301,6 +313,8 @@ struct JsonPluginListEntry {
|
||||
installed: bool,
|
||||
enabled: bool,
|
||||
source: JsonPluginSource,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
marketplace_source: Option<JsonMarketplaceSource>,
|
||||
install_policy: &'static str,
|
||||
auth_policy: &'static str,
|
||||
}
|
||||
@@ -308,6 +322,7 @@ struct JsonPluginListEntry {
|
||||
impl JsonPluginListEntry {
|
||||
fn from_configured_plugin(
|
||||
marketplace_name: &str,
|
||||
marketplace_source: Option<JsonMarketplaceSource>,
|
||||
plugin: codex_core_plugins::ConfiguredMarketplacePlugin,
|
||||
) -> Self {
|
||||
let version = plugin.installed_version.or(plugin.local_version);
|
||||
@@ -319,6 +334,7 @@ impl JsonPluginListEntry {
|
||||
installed: plugin.installed,
|
||||
enabled: plugin.enabled,
|
||||
source: JsonPluginSource::from_marketplace_source(plugin.source),
|
||||
marketplace_source,
|
||||
install_policy: install_policy_label(plugin.policy.installation),
|
||||
auth_policy: auth_policy_label(plugin.policy.authentication),
|
||||
}
|
||||
@@ -375,6 +391,44 @@ impl JsonPluginSource {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct JsonMarketplaceSource {
|
||||
source_type: String,
|
||||
source: String,
|
||||
}
|
||||
|
||||
fn configured_marketplace_sources(
|
||||
plugins_input: &PluginsConfigInput,
|
||||
) -> HashMap<String, JsonMarketplaceSource> {
|
||||
let Some(user_config) = plugins_input.config_layer_stack.effective_user_config() else {
|
||||
return HashMap::new();
|
||||
};
|
||||
let Some(marketplaces) = user_config
|
||||
.get("marketplaces")
|
||||
.and_then(toml::Value::as_table)
|
||||
else {
|
||||
return HashMap::new();
|
||||
};
|
||||
|
||||
marketplaces
|
||||
.iter()
|
||||
.filter_map(|(marketplace_name, marketplace)| {
|
||||
let source_type = marketplace
|
||||
.get("source_type")
|
||||
.and_then(toml::Value::as_str)?;
|
||||
let source = marketplace.get("source").and_then(toml::Value::as_str)?;
|
||||
Some((
|
||||
marketplace_name.clone(),
|
||||
JsonMarketplaceSource {
|
||||
source_type: source_type.to_string(),
|
||||
source: source.to_string(),
|
||||
},
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn install_policy_label(policy: MarketplacePluginInstallPolicy) -> &'static str {
|
||||
match policy {
|
||||
MarketplacePluginInstallPolicy::NotAvailable => "NOT_AVAILABLE",
|
||||
|
||||
Reference in New Issue
Block a user