Remove remote plugin uninstall prefix gate

This commit is contained in:
xli-oai
2026-05-01 19:31:36 -07:00
parent 127434cd8b
commit 5d9d97c3dd
2 changed files with 79 additions and 21 deletions

View File

@@ -27,6 +27,7 @@ use wiremock::matchers::path;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
const REMOTE_PLUGIN_ID: &str = "plugins~Plugin_linear";
const WORKSPACE_REMOTE_PLUGIN_ID: &str = "plugins_69f27c3e67848191a45cbaa5f2adb39d";
const UNKNOWN_PREFIX_REMOTE_PLUGIN_ID: &str = "newremote_69f27c3e67848191a45cbaa5f2adb39d";
#[tokio::test]
async fn plugin_uninstall_removes_plugin_cache_and_config_entry() -> Result<()> {
@@ -397,6 +398,79 @@ async fn plugin_uninstall_accepts_workspace_remote_plugin_id_shape() -> Result<(
Ok(())
}
#[tokio::test]
async fn plugin_uninstall_accepts_remote_plugin_id_without_known_prefix() -> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
write_remote_plugin_catalog_config(
codex_home.path(),
&format!("{}/backend-api/", server.uri()),
)?;
write_chatgpt_auth(
codex_home.path(),
ChatGptAuthFixture::new("chatgpt-token")
.account_id("account-123")
.chatgpt_user_id("user-123")
.chatgpt_account_id("account-123"),
AuthCredentialsStoreMode::File,
)?;
mount_remote_plugin_detail_with_name(
&server,
UNKNOWN_PREFIX_REMOTE_PLUGIN_ID,
"new-tool",
"1.0.0",
"GLOBAL",
)
.await;
Mock::given(method("POST"))
.and(path(format!(
"/backend-api/plugins/{UNKNOWN_PREFIX_REMOTE_PLUGIN_ID}/uninstall"
)))
.and(header("authorization", "Bearer chatgpt-token"))
.and(header("chatgpt-account-id", "account-123"))
.respond_with(ResponseTemplate::new(200).set_body_string(format!(
r#"{{"id":"{UNKNOWN_PREFIX_REMOTE_PLUGIN_ID}","enabled":false}}"#
)))
.mount(&server)
.await;
let remote_plugin_cache_root = codex_home
.path()
.join("plugins/cache/chatgpt-global/new-tool");
std::fs::create_dir_all(remote_plugin_cache_root.join("1.0.0/.codex-plugin"))?;
std::fs::write(
remote_plugin_cache_root.join("1.0.0/.codex-plugin/plugin.json"),
r#"{"name":"new-tool","version":"1.0.0"}"#,
)?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
let request_id = mcp
.send_plugin_uninstall_request(PluginUninstallParams {
plugin_id: UNKNOWN_PREFIX_REMOTE_PLUGIN_ID.to_string(),
})
.await?;
let response: JSONRPCResponse = timeout(
DEFAULT_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
)
.await??;
let response: PluginUninstallResponse = to_response(response)?;
assert_eq!(response, PluginUninstallResponse {});
wait_for_remote_plugin_request_count(
&server,
"POST",
&format!("/plugins/{UNKNOWN_PREFIX_REMOTE_PLUGIN_ID}/uninstall"),
/*expected_count*/ 1,
)
.await?;
assert!(!remote_plugin_cache_root.exists());
Ok(())
}
#[tokio::test]
async fn plugin_uninstall_rejects_before_post_when_remote_detail_fetch_fails() -> Result<()> {
let codex_home = TempDir::new()?;
@@ -454,7 +528,7 @@ async fn plugin_uninstall_rejects_before_post_when_remote_detail_fetch_fails() -
}
#[tokio::test]
async fn plugin_uninstall_rejects_invalid_plugin_id_before_remote_path() -> Result<()> {
async fn plugin_uninstall_rejects_remote_plugin_id_with_spaces_before_network_call() -> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
write_remote_plugin_catalog_config(
@@ -477,7 +551,7 @@ async fn plugin_uninstall_rejects_invalid_plugin_id_before_remote_path() -> Resu
.await??;
assert_eq!(err.error.code, -32600);
assert!(err.error.message.contains("invalid plugin id"));
assert!(err.error.message.contains("invalid remote plugin id"));
wait_for_remote_plugin_request_count(
&server,
"POST",
@@ -512,7 +586,7 @@ async fn plugin_uninstall_rejects_invalid_remote_plugin_id_before_network_call()
.await??;
assert_eq!(err.error.code, -32600);
assert!(err.error.message.contains("invalid plugin id"));
assert!(err.error.message.contains("invalid remote plugin id"));
wait_for_remote_plugin_request_count(
&server,
"POST",
@@ -546,7 +620,7 @@ async fn plugin_uninstall_rejects_empty_remote_plugin_id() -> Result<()> {
.await??;
assert_eq!(err.error.code, -32600);
assert!(err.error.message.contains("invalid plugin id"));
assert!(err.error.message.contains("invalid remote plugin id"));
Ok(())
}