mirror of
https://github.com/openai/codex.git
synced 2026-04-29 00:55:38 +00:00
feat: support remote_sync for plugin install/uninstall. (#14878)
- Added forceRemoteSync to plugin/install and plugin/uninstall. - With forceRemoteSync=true, we update the remote plugin status first, then apply the local change only if the backend call succeeds. - Kept plugin/list(forceRemoteSync=true) as the main recon path, and for now it treats remote enabled=false as uninstall. We will eventually migrate to plugin/installed for more precise state handling.
This commit is contained in:
@@ -3396,6 +3396,9 @@ pub struct SkillsConfigWriteResponse {
|
||||
pub struct PluginInstallParams {
|
||||
pub marketplace_path: AbsolutePathBuf,
|
||||
pub plugin_name: String,
|
||||
/// When true, apply the remote plugin change before the local install flow.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub force_remote_sync: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
@@ -3411,6 +3414,9 @@ pub struct PluginInstallResponse {
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct PluginUninstallParams {
|
||||
pub plugin_id: String,
|
||||
/// When true, apply the remote plugin change before the local uninstall flow.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub force_remote_sync: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
@@ -7571,6 +7577,69 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_install_params_serialization_uses_force_remote_sync() {
|
||||
let marketplace_path = if cfg!(windows) {
|
||||
r"C:\plugins\marketplace.json"
|
||||
} else {
|
||||
"/plugins/marketplace.json"
|
||||
};
|
||||
let marketplace_path = AbsolutePathBuf::try_from(PathBuf::from(marketplace_path)).unwrap();
|
||||
let marketplace_path_json = marketplace_path.as_path().display().to_string();
|
||||
assert_eq!(
|
||||
serde_json::to_value(PluginInstallParams {
|
||||
marketplace_path: marketplace_path.clone(),
|
||||
plugin_name: "gmail".to_string(),
|
||||
force_remote_sync: false,
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"marketplacePath": marketplace_path_json,
|
||||
"pluginName": "gmail",
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(PluginInstallParams {
|
||||
marketplace_path,
|
||||
plugin_name: "gmail".to_string(),
|
||||
force_remote_sync: true,
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"marketplacePath": marketplace_path_json,
|
||||
"pluginName": "gmail",
|
||||
"forceRemoteSync": true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_uninstall_params_serialization_uses_force_remote_sync() {
|
||||
assert_eq!(
|
||||
serde_json::to_value(PluginUninstallParams {
|
||||
plugin_id: "gmail@openai-curated".to_string(),
|
||||
force_remote_sync: false,
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"pluginId": "gmail@openai-curated",
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(PluginUninstallParams {
|
||||
plugin_id: "gmail@openai-curated".to_string(),
|
||||
force_remote_sync: true,
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"pluginId": "gmail@openai-curated",
|
||||
"forceRemoteSync": true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codex_error_info_serializes_http_status_code_in_camel_case() {
|
||||
let value = CodexErrorInfo::ResponseTooManyFailedAttempts {
|
||||
|
||||
Reference in New Issue
Block a user