mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Revert "fix: harden plugin feature gating" (#15102)
Reverts openai/codex#15020 I messed up the commit in my PR and accidentally merged changes that were still under review.
This commit is contained in:
@@ -44,7 +44,6 @@ use crate::skills::loader::SkillRoot;
|
||||
use crate::skills::loader::load_skills_from_roots;
|
||||
use codex_app_server_protocol::ConfigValueWriteParams;
|
||||
use codex_app_server_protocol::MergeStrategy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use serde::Deserialize;
|
||||
@@ -939,11 +938,7 @@ impl PluginsManager {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn maybe_start_curated_repo_sync_for_config(
|
||||
self: &Arc<Self>,
|
||||
config: &Config,
|
||||
session_source: &SessionSource,
|
||||
) {
|
||||
pub fn maybe_start_curated_repo_sync_for_config(self: &Arc<Self>, config: &Config) {
|
||||
if plugins_feature_enabled_from_stack(&config.config_layer_stack) {
|
||||
let mut configured_curated_plugin_ids =
|
||||
configured_plugins_from_stack(&config.config_layer_stack)
|
||||
@@ -966,15 +961,11 @@ impl PluginsManager {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
configured_curated_plugin_ids.sort_unstable_by_key(super::store::PluginId::as_key);
|
||||
self.start_curated_repo_sync(configured_curated_plugin_ids, session_source.clone());
|
||||
self.start_curated_repo_sync(configured_curated_plugin_ids);
|
||||
}
|
||||
}
|
||||
|
||||
fn start_curated_repo_sync(
|
||||
self: &Arc<Self>,
|
||||
configured_curated_plugin_ids: Vec<PluginId>,
|
||||
session_source: SessionSource,
|
||||
) {
|
||||
fn start_curated_repo_sync(self: &Arc<Self>, configured_curated_plugin_ids: Vec<PluginId>) {
|
||||
if CURATED_REPO_SYNC_STARTED.swap(true, Ordering::SeqCst) {
|
||||
return;
|
||||
}
|
||||
@@ -989,7 +980,6 @@ impl PluginsManager {
|
||||
codex_home.as_path(),
|
||||
&curated_plugin_version,
|
||||
&configured_curated_plugin_ids,
|
||||
&session_source,
|
||||
) {
|
||||
Ok(cache_refreshed) => {
|
||||
if cache_refreshed {
|
||||
@@ -1215,7 +1205,6 @@ fn refresh_curated_plugin_cache(
|
||||
codex_home: &Path,
|
||||
plugin_version: &str,
|
||||
configured_curated_plugin_ids: &[PluginId],
|
||||
session_source: &SessionSource,
|
||||
) -> Result<bool, String> {
|
||||
let store = PluginStore::new(codex_home.to_path_buf());
|
||||
let curated_marketplace_path = AbsolutePathBuf::try_from(
|
||||
@@ -1226,12 +1215,9 @@ fn refresh_curated_plugin_cache(
|
||||
.map_err(|err| format!("failed to load curated marketplace for cache refresh: {err}"))?;
|
||||
|
||||
let mut plugin_sources = HashMap::<String, AbsolutePathBuf>::new();
|
||||
let mut product_restricted_plugin_names = HashSet::<String>::new();
|
||||
for plugin in curated_marketplace.plugins {
|
||||
let plugin_name = plugin.name;
|
||||
if plugin_sources.contains_key(&plugin_name)
|
||||
|| product_restricted_plugin_names.contains(&plugin_name)
|
||||
{
|
||||
if plugin_sources.contains_key(&plugin_name) {
|
||||
warn!(
|
||||
plugin = plugin_name,
|
||||
marketplace = OPENAI_CURATED_MARKETPLACE_NAME,
|
||||
@@ -1242,32 +1228,16 @@ fn refresh_curated_plugin_cache(
|
||||
let source_path = match plugin.source {
|
||||
MarketplacePluginSource::Local { path } => path,
|
||||
};
|
||||
if session_source.matches_product_restriction(&plugin.policy.products) {
|
||||
plugin_sources.insert(plugin_name, source_path);
|
||||
} else {
|
||||
product_restricted_plugin_names.insert(plugin_name);
|
||||
}
|
||||
plugin_sources.insert(plugin_name, source_path);
|
||||
}
|
||||
|
||||
let mut cache_refreshed = false;
|
||||
for plugin_id in configured_curated_plugin_ids {
|
||||
// Curated plugin cache entries are intentionally sticky across session source changes.
|
||||
// Product restrictions gate refresh for this source, but do not retroactively evict an
|
||||
// already-active cache entry from a shared CODEX_HOME.
|
||||
if store.active_plugin_version(plugin_id).as_deref() == Some(plugin_version) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(source_path) = plugin_sources.get(&plugin_id.plugin_name).cloned() else {
|
||||
if product_restricted_plugin_names.contains(&plugin_id.plugin_name) {
|
||||
info!(
|
||||
plugin = plugin_id.plugin_name,
|
||||
marketplace = OPENAI_CURATED_MARKETPLACE_NAME,
|
||||
session_source = %session_source,
|
||||
"skipping curated plugin cache refresh for product-restricted plugin"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
warn!(
|
||||
plugin = plugin_id.plugin_name,
|
||||
marketplace = OPENAI_CURATED_MARKETPLACE_NAME,
|
||||
|
||||
@@ -9,12 +9,10 @@ use crate::config_loader::ConfigRequirements;
|
||||
use crate::config_loader::ConfigRequirementsToml;
|
||||
use crate::plugins::MarketplacePluginInstallPolicy;
|
||||
use crate::plugins::test_support::TEST_CURATED_PLUGIN_SHA;
|
||||
use crate::plugins::test_support::write_curated_plugin;
|
||||
use crate::plugins::test_support::write_curated_plugin_sha_with as write_curated_plugin_sha;
|
||||
use crate::plugins::test_support::write_file;
|
||||
use crate::plugins::test_support::write_openai_curated_marketplace;
|
||||
use codex_app_server_protocol::ConfigLayerSource;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
@@ -1034,12 +1032,6 @@ async fn list_marketplaces_includes_curated_repo_marketplace() {
|
||||
r#"{"name":"linear"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
write_file(
|
||||
&tmp.path().join(CONFIG_TOML_FILE),
|
||||
r#"[features]
|
||||
plugins = true
|
||||
"#,
|
||||
);
|
||||
|
||||
let config = load_config(tmp.path(), tmp.path()).await;
|
||||
let marketplaces = PluginsManager::new(tmp.path().to_path_buf())
|
||||
@@ -1635,13 +1627,8 @@ fn refresh_curated_plugin_cache_replaces_existing_local_version_with_sha() {
|
||||
);
|
||||
|
||||
assert!(
|
||||
refresh_curated_plugin_cache(
|
||||
tmp.path(),
|
||||
TEST_CURATED_PLUGIN_SHA,
|
||||
&[plugin_id],
|
||||
&SessionSource::Cli,
|
||||
)
|
||||
.expect("cache refresh should succeed")
|
||||
refresh_curated_plugin_cache(tmp.path(), TEST_CURATED_PLUGIN_SHA, &[plugin_id])
|
||||
.expect("cache refresh should succeed")
|
||||
);
|
||||
|
||||
assert!(
|
||||
@@ -1671,13 +1658,8 @@ fn refresh_curated_plugin_cache_reinstalls_missing_configured_plugin_with_curren
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
refresh_curated_plugin_cache(
|
||||
tmp.path(),
|
||||
TEST_CURATED_PLUGIN_SHA,
|
||||
&[plugin_id],
|
||||
&SessionSource::Cli,
|
||||
)
|
||||
.expect("cache refresh should recreate missing configured plugin")
|
||||
refresh_curated_plugin_cache(tmp.path(), TEST_CURATED_PLUGIN_SHA, &[plugin_id])
|
||||
.expect("cache refresh should recreate missing configured plugin")
|
||||
);
|
||||
|
||||
assert!(
|
||||
@@ -1706,64 +1688,8 @@ fn refresh_curated_plugin_cache_returns_false_when_configured_plugins_are_curren
|
||||
);
|
||||
|
||||
assert!(
|
||||
!refresh_curated_plugin_cache(
|
||||
tmp.path(),
|
||||
TEST_CURATED_PLUGIN_SHA,
|
||||
&[plugin_id],
|
||||
&SessionSource::Cli,
|
||||
)
|
||||
.expect("cache refresh should be a no-op when configured plugins are current")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refresh_curated_plugin_cache_skips_product_restricted_plugins_for_session_source() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let curated_root = curated_plugins_repo_path(tmp.path());
|
||||
write_file(
|
||||
&curated_root.join(".agents/plugins/marketplace.json"),
|
||||
&format!(
|
||||
r#"{{
|
||||
"name": "{OPENAI_CURATED_MARKETPLACE_NAME}",
|
||||
"plugins": [
|
||||
{{
|
||||
"name": "chatgpt-plugin",
|
||||
"source": {{
|
||||
"source": "local",
|
||||
"path": "./plugins/chatgpt-plugin"
|
||||
}},
|
||||
"policy": {{
|
||||
"products": ["CHATGPT"]
|
||||
}}
|
||||
}}
|
||||
]
|
||||
}}"#
|
||||
),
|
||||
);
|
||||
write_curated_plugin(&curated_root, "chatgpt-plugin");
|
||||
write_curated_plugin_sha(tmp.path(), TEST_CURATED_PLUGIN_SHA);
|
||||
let plugin_id = PluginId::new(
|
||||
"chatgpt-plugin".to_string(),
|
||||
OPENAI_CURATED_MARKETPLACE_NAME.to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
!refresh_curated_plugin_cache(
|
||||
tmp.path(),
|
||||
TEST_CURATED_PLUGIN_SHA,
|
||||
&[plugin_id],
|
||||
&SessionSource::Cli,
|
||||
)
|
||||
.expect("cache refresh should skip disallowed product plugin")
|
||||
);
|
||||
|
||||
assert!(
|
||||
!tmp.path()
|
||||
.join(format!(
|
||||
"plugins/cache/openai-curated/chatgpt-plugin/{TEST_CURATED_PLUGIN_SHA}"
|
||||
))
|
||||
.exists()
|
||||
!refresh_curated_plugin_cache(tmp.path(), TEST_CURATED_PLUGIN_SHA, &[plugin_id])
|
||||
.expect("cache refresh should be a no-op when configured plugins are current")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ pub enum MarketplacePluginSource {
|
||||
pub struct MarketplacePluginPolicy {
|
||||
pub installation: MarketplacePluginInstallPolicy,
|
||||
pub authentication: MarketplacePluginAuthPolicy,
|
||||
// TODO: Surface or enforce product gating at the Codex/plugin consumer boundary instead of
|
||||
// only carrying it through core marketplace metadata.
|
||||
pub products: Vec<Product>,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user