mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Support remote plugin install writes (#18917)
## Summary - Add a remote plugin install write call that POSTs the selected remote plugin to the ChatGPT cloud plugin API. - Align remote install with the latest remote read contract: `pluginName` carries the backend remote plugin id directly, for example `plugins~Plugin_linear`, and install no longer synthesizes `<name>@<marketplace>` ids. - Validate remote install ids with the same character rules as remote read, return the same install response shape as local installs, and include mocked app-server coverage for the write path. ## Validation - `just fmt` - `cargo test -p codex-app-server --test all plugin_install` - `cargo test -p codex-core-plugins` - `just fix -p codex-app-server` - `just fix -p codex-core-plugins`
This commit is contained in:
committed by
GitHub
Unverified
parent
19badb0be2
commit
33cc135cc3
@@ -107,6 +107,20 @@ pub enum RemotePluginCatalogError {
|
||||
expected_marketplace_name: String,
|
||||
actual_marketplace_name: String,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"remote plugin install returned unexpected plugin id: expected `{expected}`, got `{actual}`"
|
||||
)]
|
||||
UnexpectedPluginId { expected: String, actual: String },
|
||||
|
||||
#[error(
|
||||
"remote plugin install returned unexpected enabled state for `{plugin_id}`: expected {expected_enabled}, got {actual_enabled}"
|
||||
)]
|
||||
UnexpectedEnabledState {
|
||||
plugin_id: String,
|
||||
expected_enabled: bool,
|
||||
actual_enabled: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize)]
|
||||
@@ -258,6 +272,12 @@ struct RemotePluginInstalledResponse {
|
||||
pagination: RemotePluginPagination,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
struct RemotePluginInstallResponse {
|
||||
id: String,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
pub async fn fetch_remote_marketplaces(
|
||||
config: &RemotePluginServiceConfig,
|
||||
auth: Option<&CodexAuth>,
|
||||
@@ -418,6 +438,41 @@ pub async fn fetch_remote_plugin_detail(
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn install_remote_plugin(
|
||||
config: &RemotePluginServiceConfig,
|
||||
auth: Option<&CodexAuth>,
|
||||
marketplace_name: &str,
|
||||
plugin_id: &str,
|
||||
) -> Result<(), RemotePluginCatalogError> {
|
||||
let auth = ensure_chatgpt_auth(auth)?;
|
||||
if RemotePluginScope::from_marketplace_name(marketplace_name).is_none() {
|
||||
return Err(RemotePluginCatalogError::UnknownMarketplace {
|
||||
marketplace_name: marketplace_name.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let base_url = config.chatgpt_base_url.trim_end_matches('/');
|
||||
let url = format!("{base_url}/ps/plugins/{plugin_id}/install");
|
||||
let client = build_reqwest_client();
|
||||
let request = authenticated_request(client.post(&url), auth)?;
|
||||
let response: RemotePluginInstallResponse = send_and_decode(request, &url).await?;
|
||||
if response.id != plugin_id {
|
||||
return Err(RemotePluginCatalogError::UnexpectedPluginId {
|
||||
expected: plugin_id.to_string(),
|
||||
actual: response.id,
|
||||
});
|
||||
}
|
||||
if !response.enabled {
|
||||
return Err(RemotePluginCatalogError::UnexpectedEnabledState {
|
||||
plugin_id: plugin_id.to_string(),
|
||||
expected_enabled: true,
|
||||
actual_enabled: response.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_remote_plugin_summary(
|
||||
plugin: &RemotePluginDirectoryItem,
|
||||
installed_plugin: Option<&RemotePluginInstalledItem>,
|
||||
|
||||
Reference in New Issue
Block a user