mirror of
https://github.com/openai/codex.git
synced 2026-11-03 19:53:25 +00:00
Preserve curated plugin root selection
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use crate::app_mcp_routing::apply_app_mcp_routing_policy;
|
||||
use crate::app_mcp_routing::apps_route_available;
|
||||
use crate::is_openai_curated_marketplace_name;
|
||||
use crate::manifest::PluginManifest;
|
||||
use crate::manifest::PluginManifestHooks;
|
||||
use crate::manifest::PluginManifestMcpServers;
|
||||
use crate::manifest::PluginManifestPaths;
|
||||
@@ -657,7 +656,7 @@ async fn load_plugin(
|
||||
let active_plugin_root = plugin_id
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|plugin_id| active_plugin_root(plugin_id, store));
|
||||
.and_then(|plugin_id| store.active_plugin_root(plugin_id));
|
||||
let root = active_plugin_root
|
||||
.clone()
|
||||
.unwrap_or_else(|| match &plugin_id {
|
||||
@@ -709,7 +708,7 @@ async fn load_plugin(
|
||||
return loaded_plugin;
|
||||
};
|
||||
|
||||
loaded_plugin.is_first_party = is_openai_curated_plugin(&loaded_plugin_id, &manifest, store);
|
||||
loaded_plugin.is_first_party = is_openai_curated_plugin(&loaded_plugin_id, &plugin_root, store);
|
||||
let manifest_paths = &manifest.paths;
|
||||
match scope {
|
||||
PluginLoadScope::AllCapabilities {
|
||||
@@ -751,31 +750,12 @@ async fn load_plugin(
|
||||
loaded_plugin
|
||||
}
|
||||
|
||||
fn active_plugin_root(plugin_id: &PluginId, store: &PluginStore) -> Option<AbsolutePathBuf> {
|
||||
if is_openai_curated_marketplace_name(&plugin_id.marketplace_name)
|
||||
&& let Some(curated_sha) = read_curated_plugins_sha(store.codex_home())
|
||||
{
|
||||
let expected_version = curated_plugin_cache_version(&curated_sha);
|
||||
let expected_root = store.plugin_root(plugin_id, &expected_version);
|
||||
if expected_root.as_path().is_dir() {
|
||||
return Some(expected_root);
|
||||
}
|
||||
}
|
||||
store.active_plugin_root(plugin_id)
|
||||
}
|
||||
|
||||
fn is_openai_curated_plugin(
|
||||
plugin_id: &PluginId,
|
||||
manifest: &PluginManifest,
|
||||
loaded_root: &AbsolutePathBuf,
|
||||
store: &PluginStore,
|
||||
) -> bool {
|
||||
if !is_openai_curated_marketplace_name(&plugin_id.marketplace_name)
|
||||
|| manifest
|
||||
.interface
|
||||
.as_ref()
|
||||
.and_then(|interface| interface.developer_name.as_deref())
|
||||
!= Some("OpenAI")
|
||||
{
|
||||
if !is_openai_curated_marketplace_name(&plugin_id.marketplace_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -783,11 +763,8 @@ fn is_openai_curated_plugin(
|
||||
return false;
|
||||
};
|
||||
let expected_version = curated_plugin_cache_version(&curated_sha);
|
||||
if !store
|
||||
.plugin_root(plugin_id, &expected_version)
|
||||
.as_path()
|
||||
.is_dir()
|
||||
{
|
||||
let expected_root = store.plugin_root(plugin_id, &expected_version);
|
||||
if loaded_root != &expected_root || !expected_root.as_path().is_dir() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,21 +248,14 @@ enabled = true
|
||||
.expect("valid curated plugin config")
|
||||
}
|
||||
|
||||
fn write_curated_cached_plugin_with_developer(
|
||||
codex_home: &Path,
|
||||
plugin_name: &str,
|
||||
version: &str,
|
||||
developer_name: &str,
|
||||
) {
|
||||
fn write_curated_cached_plugin(codex_home: &Path, plugin_name: &str, version: &str) {
|
||||
let plugin_root = codex_home
|
||||
.join("plugins/cache/openai-curated")
|
||||
.join(plugin_name)
|
||||
.join(version);
|
||||
write_file(
|
||||
&plugin_root.join(".codex-plugin/plugin.json"),
|
||||
&format!(
|
||||
r#"{{"name":"{plugin_name}","interface":{{"developerName":"{developer_name}"}}}}"#,
|
||||
),
|
||||
&format!(r#"{{"name":"{plugin_name}"}}"#),
|
||||
);
|
||||
write_file(&plugin_root.join("skills/SKILL.md"), "skill");
|
||||
}
|
||||
@@ -281,18 +274,12 @@ async fn load_curated_plugin(temp_dir: &TempDir, plugin_name: &str) -> PluginLoa
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_curated_plugin_prefers_synced_sha_root_over_stale_local_cache() {
|
||||
async fn load_curated_plugin_uses_synced_sha_root_when_it_is_only_installed_root() {
|
||||
let temp_dir = TempDir::new().expect("tempdir");
|
||||
let curated_root = curated_plugins_repo_path(temp_dir.path());
|
||||
write_openai_curated_marketplace(&curated_root, &["slack"]);
|
||||
write_curated_plugin_sha_with(temp_dir.path(), TEST_CURATED_PLUGIN_SHA);
|
||||
write_curated_cached_plugin_with_developer(temp_dir.path(), "slack", "local", "Third Party");
|
||||
write_curated_cached_plugin_with_developer(
|
||||
temp_dir.path(),
|
||||
"slack",
|
||||
TEST_CURATED_PLUGIN_CACHE_VERSION,
|
||||
"OpenAI",
|
||||
);
|
||||
write_curated_cached_plugin(temp_dir.path(), "slack", TEST_CURATED_PLUGIN_CACHE_VERSION);
|
||||
|
||||
let outcome = load_curated_plugin(&temp_dir, "slack").await;
|
||||
let plugin = outcome.plugins().first().expect("configured plugin");
|
||||
@@ -313,12 +300,12 @@ async fn load_curated_plugin_prefers_synced_sha_root_over_stale_local_cache() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_curated_plugin_with_openai_metadata_without_synced_cache_is_not_first_party() {
|
||||
async fn load_curated_plugin_without_synced_cache_root_is_not_first_party() {
|
||||
let temp_dir = TempDir::new().expect("tempdir");
|
||||
let curated_root = curated_plugins_repo_path(temp_dir.path());
|
||||
write_openai_curated_marketplace(&curated_root, &["slack"]);
|
||||
write_curated_plugin_sha_with(temp_dir.path(), TEST_CURATED_PLUGIN_SHA);
|
||||
write_curated_cached_plugin_with_developer(temp_dir.path(), "slack", "local", "OpenAI");
|
||||
write_curated_cached_plugin(temp_dir.path(), "slack", "local");
|
||||
|
||||
let outcome = load_curated_plugin(&temp_dir, "slack").await;
|
||||
|
||||
@@ -332,18 +319,36 @@ async fn load_curated_plugin_with_openai_metadata_without_synced_cache_is_not_fi
|
||||
assert_eq!(outcome.effective_first_party_plugin_roots(), Vec::new());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_curated_plugin_keeps_local_root_priority_over_synced_sha_root() {
|
||||
let temp_dir = TempDir::new().expect("tempdir");
|
||||
let curated_root = curated_plugins_repo_path(temp_dir.path());
|
||||
write_openai_curated_marketplace(&curated_root, &["slack"]);
|
||||
write_curated_plugin_sha_with(temp_dir.path(), TEST_CURATED_PLUGIN_SHA);
|
||||
write_curated_cached_plugin(temp_dir.path(), "slack", "local");
|
||||
write_curated_cached_plugin(temp_dir.path(), "slack", TEST_CURATED_PLUGIN_CACHE_VERSION);
|
||||
|
||||
let outcome = load_curated_plugin(&temp_dir, "slack").await;
|
||||
let plugin = outcome.plugins().first().expect("configured plugin");
|
||||
let local_root = AbsolutePathBuf::try_from(
|
||||
temp_dir
|
||||
.path()
|
||||
.join("plugins/cache/openai-curated/slack/local"),
|
||||
)
|
||||
.expect("local plugin root");
|
||||
|
||||
assert_eq!(plugin.root, local_root);
|
||||
assert!(!plugin.is_first_party);
|
||||
assert_eq!(outcome.effective_first_party_plugin_roots(), Vec::new());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_curated_plugin_missing_from_synced_marketplace_is_not_first_party() {
|
||||
let temp_dir = TempDir::new().expect("tempdir");
|
||||
let curated_root = curated_plugins_repo_path(temp_dir.path());
|
||||
write_openai_curated_marketplace(&curated_root, &["github"]);
|
||||
write_curated_plugin_sha_with(temp_dir.path(), TEST_CURATED_PLUGIN_SHA);
|
||||
write_curated_cached_plugin_with_developer(
|
||||
temp_dir.path(),
|
||||
"slack",
|
||||
TEST_CURATED_PLUGIN_CACHE_VERSION,
|
||||
"OpenAI",
|
||||
);
|
||||
write_curated_cached_plugin(temp_dir.path(), "slack", TEST_CURATED_PLUGIN_CACHE_VERSION);
|
||||
|
||||
let outcome = load_curated_plugin(&temp_dir, "slack").await;
|
||||
|
||||
|
||||
@@ -574,10 +574,7 @@ async fn load_plugins_loads_default_skills_and_mcp_servers() {
|
||||
&plugin_root.join(".codex-plugin/plugin.json"),
|
||||
r#"{
|
||||
"name": "sample",
|
||||
"description": "Plugin that includes the sample MCP server and Skills",
|
||||
"interface": {
|
||||
"developerName": "OpenAI"
|
||||
}
|
||||
"description": "Plugin that includes the sample MCP server and Skills"
|
||||
}"#,
|
||||
);
|
||||
write_file(
|
||||
|
||||
Reference in New Issue
Block a user