Skip to main content

ai_agent/utils/plugins/
plugin_blocklist.rs

1// Source: ~/claudecode/openclaudecode/src/utils/plugins/pluginBlocklist.ts
2#![allow(dead_code)]
3
4use super::installed_plugins_manager::load_installed_plugins_v2;
5use super::marketplace_manager::{get_marketplace, load_known_marketplaces_config_safe};
6use super::plugin_flagging::{add_flagged_plugin, get_flagged_plugins, load_flagged_plugins};
7
8/// Detect plugins installed from a marketplace that are no longer listed there.
9pub fn detect_delisted_plugins(
10    installed_plugins: &super::installed_plugins_manager::InstalledPluginsFileV2,
11    marketplace: &super::types::PluginMarketplace,
12    marketplace_name: &str,
13) -> Vec<String> {
14    let marketplace_plugin_names: std::collections::HashSet<_> = marketplace
15        .plugins
16        .iter()
17        .map(|p| p.name.as_str())
18        .collect();
19
20    let suffix = format!("@{}", marketplace_name);
21    let mut delisted = Vec::new();
22
23    for plugin_id in installed_plugins.plugins.keys() {
24        if !plugin_id.ends_with(&suffix) {
25            continue;
26        }
27
28        let plugin_name = &plugin_id[..plugin_id.len() - suffix.len()];
29        if !marketplace_plugin_names.contains(plugin_name) {
30            delisted.push(plugin_id.clone());
31        }
32    }
33
34    delisted
35}
36
37/// Detect delisted plugins across all marketplaces, auto-uninstall them,
38/// and record them as flagged.
39pub async fn detect_and_uninstall_delisted_plugins()
40-> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
41    load_flagged_plugins().await?;
42
43    let installed_plugins = load_installed_plugins_v2()?;
44    let already_flagged = get_flagged_plugins();
45    let known_marketplaces = load_known_marketplaces_config_safe().await?;
46    let mut newly_flagged = Vec::new();
47
48    for marketplace_name in known_marketplaces.keys() {
49        let marketplace = match get_marketplace(marketplace_name).await {
50            Ok(m) => m,
51            Err(e) => {
52                log::debug!(
53                    "Failed to check for delisted plugins in \"{}\": {}",
54                    marketplace_name,
55                    e
56                );
57                continue;
58            }
59        };
60
61        if !marketplace.force_remove_deleted_plugins.unwrap_or(false) {
62            continue;
63        }
64
65        let delisted = detect_delisted_plugins(&installed_plugins, &marketplace, marketplace_name);
66
67        for plugin_id in delisted {
68            if already_flagged.contains_key(&plugin_id) {
69                continue;
70            }
71
72            let installations = installed_plugins
73                .plugins
74                .get(&plugin_id)
75                .cloned()
76                .unwrap_or_default();
77
78            let has_user_install = installations.iter().any(|i| {
79                matches!(
80                    i.scope,
81                    super::schemas::PluginScope::User
82                        | super::schemas::PluginScope::Project
83                        | super::schemas::PluginScope::Local
84                )
85            });
86
87            if !has_user_install {
88                continue;
89            }
90
91            add_flagged_plugin(&plugin_id).await?;
92            newly_flagged.push(plugin_id);
93        }
94    }
95
96    Ok(newly_flagged)
97}