[codex] Refactor marketplace add into shared core flow (#17717)

## Summary

Move `codex marketplace add` onto a shared core implementation so the
CLI and app-server path can use one source of truth.

This change:
- adds shared marketplace-add orchestration in `codex-core`
- switches the CLI command to call that shared implementation
- removes duplicated CLI-only marketplace add helpers
- preserves focused parser and add-path coverage while moving the shared
behavior into core tests

## Why

The new `marketplace/add` RPC should reuse the same underlying
marketplace-add flow as the CLI. This refactor lands that consolidation
first so the follow-up app-server PR can be mostly protocol and handler
wiring.

## Validation

- `cargo test -p codex-core marketplace_add`
- `cargo test -p codex-cli marketplace_cmd`
- `just fix -p codex-core`
- `just fix -p codex-cli`
- `just fmt`
This commit is contained in:
xli-oai
2026-04-13 20:37:11 -07:00
committed by GitHub
parent d9a385ac8c
commit ff584c5a4b
24 changed files with 1321 additions and 720 deletions

View File

@@ -3326,6 +3326,26 @@ pub struct SkillsListResponse {
pub data: Vec<SkillsListEntry>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct MarketplaceAddParams {
pub source: String,
#[ts(optional = nullable)]
pub ref_name: Option<String>,
#[ts(optional = nullable)]
pub sparse_paths: Option<Vec<String>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct MarketplaceAddResponse {
pub marketplace_name: String,
pub installed_root: AbsolutePathBuf,
pub already_added: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -8352,6 +8372,37 @@ mod tests {
);
}
#[test]
fn marketplace_add_params_serialization_uses_optional_ref_name_and_sparse_paths() {
assert_eq!(
serde_json::to_value(MarketplaceAddParams {
source: "owner/repo".to_string(),
ref_name: None,
sparse_paths: None,
})
.unwrap(),
json!({
"source": "owner/repo",
"refName": null,
"sparsePaths": null,
}),
);
assert_eq!(
serde_json::to_value(MarketplaceAddParams {
source: "owner/repo".to_string(),
ref_name: Some("main".to_string()),
sparse_paths: Some(vec!["plugins/foo".to_string()]),
})
.unwrap(),
json!({
"source": "owner/repo",
"refName": "main",
"sparsePaths": ["plugins/foo"],
}),
);
}
#[test]
fn plugin_install_params_serialization_uses_force_remote_sync() {
let marketplace_path = if cfg!(windows) {